From 806720507e7e86ef1227a37146b3718ba027f036 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 23 Dec 2012 01:18:35 +0000 Subject: style cleanup: wrap long lines (>200) --- source/blender/avi/intern/avi_mjpeg.c | 21 +++++++++-- source/blender/blenkernel/BKE_shrinkwrap.h | 14 ++++--- source/blender/blenkernel/intern/dynamicpaint.c | 4 +- .../compositor/intern/COM_ExecutionSystem.h | 28 +++++++++----- .../blender/compositor/intern/COM_OpenCLDevice.cpp | 8 +++- .../editors/armature/editarmature_retarget.c | 8 +++- source/blender/editors/armature/meshlaplacian.c | 4 +- .../blender/editors/interface/interface_layout.c | 4 +- .../blender/editors/space_outliner/outliner_draw.c | 44 +++++++++++++++------- .../blender/editors/space_outliner/outliner_tree.c | 12 ++++-- .../blender/editors/space_view3d/view3d_header.c | 15 ++++++-- 11 files changed, 115 insertions(+), 47 deletions(-) (limited to 'source') diff --git a/source/blender/avi/intern/avi_mjpeg.c b/source/blender/avi/intern/avi_mjpeg.c index 396f1199cd9..5ecb3edf92f 100644 --- a/source/blender/avi/intern/avi_mjpeg.c +++ b/source/blender/avi/intern/avi_mjpeg.c @@ -316,7 +316,8 @@ static int check_and_decode_jpeg(unsigned char *inbuf, unsigned char *outbuf, in } } -static void check_and_compress_jpeg(int quality, unsigned char *outbuf, unsigned char *inbuf, int width, int height, int bufsize) +static void check_and_compress_jpeg(int quality, unsigned char *outbuf, const unsigned char *inbuf, + int width, int height, int bufsize) { /* JPEG's are always multiples of 16, extra is ignored in AVI's */ if ((width & 0xF) || (height & 0xF)) { @@ -379,7 +380,11 @@ void *avi_converter_to_mjpeg(AviMovie *movie, int stream, unsigned char *buffer, buf = MEM_mallocN(movie->header->Height * movie->header->Width * 3, "avi.avi_converter_to_mjpeg 1"); if (!movie->interlace) { - check_and_compress_jpeg(movie->streams[stream].sh.Quality / 100, buf, buffer, movie->header->Width, movie->header->Height, bufsize); + check_and_compress_jpeg(movie->streams[stream].sh.Quality / 100, + buf, buffer, + movie->header->Width, + movie->header->Height, + bufsize); } else { deinterlace(movie->odd_fields, buf, buffer, movie->header->Width, movie->header->Height); @@ -388,10 +393,18 @@ void *avi_converter_to_mjpeg(AviMovie *movie, int stream, unsigned char *buffer, buffer = buf; buf = MEM_mallocN(movie->header->Height * movie->header->Width * 3, "avi.avi_converter_to_mjpeg 2"); - check_and_compress_jpeg(movie->streams[stream].sh.Quality / 100, buf, buffer, movie->header->Width, movie->header->Height / 2, bufsize / 2); + check_and_compress_jpeg(movie->streams[stream].sh.Quality / 100, + buf, buffer, + movie->header->Width, + movie->header->Height / 2, + bufsize / 2); *size += numbytes; numbytes = 0; - check_and_compress_jpeg(movie->streams[stream].sh.Quality / 100, buf + *size, buffer + (movie->header->Height / 2) * movie->header->Width * 3, movie->header->Width, movie->header->Height / 2, bufsize / 2); + check_and_compress_jpeg(movie->streams[stream].sh.Quality / 100, + buf + *size, buffer + (movie->header->Height / 2) * movie->header->Width * 3, + movie->header->Width, + movie->header->Height / 2, + bufsize / 2); } *size += numbytes; diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h index d1332ba937e..61d82e6c604 100644 --- a/source/blender/blenkernel/BKE_shrinkwrap.h +++ b/source/blender/blenkernel/BKE_shrinkwrap.h @@ -121,7 +121,8 @@ typedef struct ShrinkwrapCalcData { } ShrinkwrapCalcData; -void shrinkwrapModifier_deform(struct ShrinkwrapModifierData *smd, struct Object *ob, struct DerivedMesh *dm, float (*vertexCos)[3], int numVerts); +void shrinkwrapModifier_deform(struct ShrinkwrapModifierData *smd, struct Object *ob, struct DerivedMesh *dm, + float (*vertexCos)[3], int numVerts); /* * This function casts a ray in the given BVHTree.. but it takes into consideration the space_transform, that is: @@ -130,9 +131,12 @@ void shrinkwrapModifier_deform(struct ShrinkwrapModifierData *smd, struct Object * then the input (vert, dir, BVHTreeRayHit) must be defined in ob1 coordinates space * and the BVHTree must be built in ob2 coordinate space. * - * Thus it provides an easy way to cast the same ray across several trees (where each tree was built on its own coords space) + * Thus it provides an easy way to cast the same ray across several trees + * (where each tree was built on its own coords space) */ -int normal_projection_project_vertex(char options, const float *vert, const float *dir, const SpaceTransform *transf, BVHTree *tree, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata); +int normal_projection_project_vertex(char options, const float vert[3], const float dir[3], + const SpaceTransform *transf, BVHTree *tree, BVHTreeRayHit *hit, + BVHTree_RayCastCallback callback, void *userdata); /* * NULL initializers to local data @@ -142,6 +146,4 @@ int normal_projection_project_vertex(char options, const float *vert, const floa #define NULL_BVHTreeRayHit {NULL, } #define NULL_BVHTreeNearest {0, } - -#endif - +#endif /* __BKE_SHRINKWRAP_H__ */ diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index e32f8d53b7d..23fae2e9de0 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -2839,7 +2839,9 @@ static void dynamicPaint_freeBrushMaterials(BrushMaterials *bMats) /* * Get material diffuse color and alpha (including linked textures) in given coordinates */ -static void dynamicPaint_doMaterialTex(BrushMaterials *bMats, float color[3], float *alpha, Object *brushOb, const float volume_co[3], const float surface_co[3], int faceIndex, short isQuad, DerivedMesh *orcoDm) +static void dynamicPaint_doMaterialTex(BrushMaterials *bMats, float color[3], float *alpha, Object *brushOb, + const float volume_co[3], const float surface_co[3], + int faceIndex, short isQuad, DerivedMesh *orcoDm) { Material *mat = bMats->mat; MFace *mface = orcoDm->getTessFaceArray(orcoDm); diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.h b/source/blender/compositor/intern/COM_ExecutionSystem.h index 25f06108d96..9beccba0c73 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystem.h +++ b/source/blender/compositor/intern/COM_ExecutionSystem.h @@ -41,7 +41,8 @@ using namespace std; * In order to get to an efficient model for execution, several steps are being done. these steps are explained below. * * @section EM_Step1 Step 1: translating blender node system to the new compsitor system - * Blenders node structure is based on C structs (DNA). These structs are not efficient in the new architecture. We want to use classes in order to simplify the system. + * Blenders node structure is based on C structs (DNA). These structs are not efficient in the new architecture. + * We want to use classes in order to simplify the system. * during this step the blender node_tree is evaluated and converted to a CPP node system. * * @see ExecutionSystem @@ -49,13 +50,17 @@ using namespace std; * @see Node * * @section EM_Step2 Step2: translating nodes to operations - * Ungrouping the GroupNodes. Group nodes are node_tree's in node_tree's. The new system only supports a single level of node_tree. We will 'flatten' the system in a single level. + * Ungrouping the GroupNodes. Group nodes are node_tree's in node_tree's. + * The new system only supports a single level of node_tree. We will 'flatten' the system in a single level. * @see GroupNode * @see ExecutionSystemHelper.ungroup * - * Every node has the ability to convert itself to operations. The node itself is responsible to create a correct NodeOperation setup based on its internal settings. - * Most Node only need to convert it to its NodeOperation. Like a ColorToBWNode doesn't check anything, but replaces itself with a ConvertColorToBWOperation. - * More complex nodes can use different NodeOperation based on settings; like MixNode. based on the selected Mixtype a different operation will be used. + * Every node has the ability to convert itself to operations. The node itself is responsible to create a correct + * NodeOperation setup based on its internal settings. + * Most Node only need to convert it to its NodeOperation. Like a ColorToBWNode doesn't check anything, + * but replaces itself with a ConvertColorToBWOperation. + * More complex nodes can use different NodeOperation based on settings; like MixNode. + * based on the selected Mixtype a different operation will be used. * for more information see the page about creating new Nodes. [@subpage newnode] * * @see ExecutionSystem.convertToOperations @@ -63,9 +68,12 @@ using namespace std; * @see NodeOperation base class for all operations in the system * * @section EM_Step3 Step3: add additional conversions to the operation system - * - Data type conversions: the system has 3 data types COM_DT_VALUE, COM_DT_VECTOR, COM_DT_COLOR. The user can connect a Value socket to a color socket. As values are ordered differently than colors a conversion happens. + * - Data type conversions: the system has 3 data types COM_DT_VALUE, COM_DT_VECTOR, COM_DT_COLOR. + * The user can connect a Value socket to a color socket. + * As values are ordered differently than colors a conversion happens. * - * - Image size conversions: the system can automatically convert when resolutions do not match. An InputSocket has a resize mode. This can be any of the following settings. + * - Image size conversions: the system can automatically convert when resolutions do not match. + * An InputSocket has a resize mode. This can be any of the following settings. * - [@ref InputSocketResizeMode.COM_SC_CENTER]: The center of both images are aligned * - [@ref InputSocketResizeMode.COM_SC_FIT_WIDTH]: The width of both images are aligned * - [@ref InputSocketResizeMode.COM_SC_FIT_HEIGHT]: the height of both images are aligned @@ -77,8 +85,10 @@ using namespace std; * @see Converter.convertResolution Image size conversions * * @section EM_Step4 Step4: group operations in executions groups - * ExecutionGroup are groups of operations that are calculated as being one bigger operation. All operations will be part of an ExecutionGroup. - * Complex nodes will be added to separate groups. Between ExecutionGroup's the data will be stored in MemoryBuffers. ReadBufferOperations and WriteBufferOperations are added where needed. + * ExecutionGroup are groups of operations that are calculated as being one bigger operation. + * All operations will be part of an ExecutionGroup. + * Complex nodes will be added to separate groups. Between ExecutionGroup's the data will be stored in MemoryBuffers. + * ReadBufferOperations and WriteBufferOperations are added where needed. * *
  *
diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.cpp b/source/blender/compositor/intern/COM_OpenCLDevice.cpp
index d5da079c9fd..bb60a629812 100644
--- a/source/blender/compositor/intern/COM_OpenCLDevice.cpp
+++ b/source/blender/compositor/intern/COM_OpenCLDevice.cpp
@@ -65,12 +65,16 @@ void OpenCLDevice::execute(WorkPackage *work)
 	
 	executionGroup->finalizeChunkExecution(chunkNumber, inputBuffers);
 }
-cl_mem OpenCLDevice::COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel, int parameterIndex, int offsetIndex, list *cleanup, MemoryBuffer **inputMemoryBuffers, SocketReader *reader)
+cl_mem OpenCLDevice::COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel, int parameterIndex, int offsetIndex,
+                                                               list *cleanup, MemoryBuffer **inputMemoryBuffers,
+                                                               SocketReader *reader)
 {
 	return COM_clAttachMemoryBufferToKernelParameter(kernel, parameterIndex, offsetIndex, cleanup, inputMemoryBuffers, (ReadBufferOperation *)reader);
 }
 
-cl_mem OpenCLDevice::COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel, int parameterIndex, int offsetIndex, list *cleanup, MemoryBuffer **inputMemoryBuffers, ReadBufferOperation *reader)
+cl_mem OpenCLDevice::COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel, int parameterIndex, int offsetIndex,
+                                                               list *cleanup, MemoryBuffer **inputMemoryBuffers,
+                                                               ReadBufferOperation *reader)
 {
 	cl_int error;
 	
diff --git a/source/blender/editors/armature/editarmature_retarget.c b/source/blender/editors/armature/editarmature_retarget.c
index 68cfc7fb8c0..be3e037e330 100644
--- a/source/blender/editors/armature/editarmature_retarget.c
+++ b/source/blender/editors/armature/editarmature_retarget.c
@@ -1830,7 +1830,9 @@ static float calcCostLengthDistance(BArcIterator *iter, float **vec_cache, RigEd
 }
 #endif
 
-static float calcCostAngleLengthDistance(BArcIterator *iter, float **UNUSED(vec_cache), RigEdge *edge, float *vec0, float *vec1, float *vec2, int i1, int i2, float angle_weight, float length_weight, float distance_weight)
+static float calcCostAngleLengthDistance(BArcIterator *iter, float **UNUSED(vec_cache), RigEdge *edge,
+                                         float *vec0, float *vec1, float *vec2, int i1, int i2,
+                                         float angle_weight, float length_weight, float distance_weight)
 {
 	float vec_second[3], vec_first[3];
 	float length2;
@@ -1878,7 +1880,9 @@ static void copyMemoPositions(int *positions, MemoNode *table, int nb_positions,
 	}
 }
 
-static MemoNode *solveJoints(MemoNode *table, BArcIterator *iter, float **vec_cache, int nb_joints, int nb_positions, int previous, int current, RigEdge *edge, int joints_left, float angle_weight, float length_weight, float distance_weight)
+static MemoNode *solveJoints(MemoNode *table, BArcIterator *iter, float **vec_cache,
+                             int nb_joints, int nb_positions, int previous, int current, RigEdge *edge,
+                             int joints_left, float angle_weight, float length_weight, float distance_weight)
 {
 	MemoNode *node;
 	int index = indexMemoNode(nb_positions, previous, current, joints_left);
diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c
index 2848db18d59..19a97fa0810 100644
--- a/source/blender/editors/armature/meshlaplacian.c
+++ b/source/blender/editors/armature/meshlaplacian.c
@@ -649,7 +649,9 @@ static float heat_limit_weight(float weight)
 		return weight;
 }
 
-void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numsource, bDeformGroup **dgrouplist, bDeformGroup **dgroupflip, float (*root)[3], float (*tip)[3], int *selected, const char **err_str)
+void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numsource,
+                         bDeformGroup **dgrouplist, bDeformGroup **dgroupflip,
+                         float (*root)[3], float (*tip)[3], int *selected, const char **err_str)
 {
 	LaplacianSystem *sys;
 	MPoly *mp;
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index a15256bc86f..20f2c52485e 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -346,7 +346,9 @@ 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), int expand, int slider, int toggle, int 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),
+                          int expand, int slider, int toggle, int icon_only)
 {
 	uiStyle *style = layout->root->style;
 	uiBut *but;
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 6913ebc8a11..222dcac454f 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -445,15 +445,21 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
 				uiBlockSetEmboss(block, UI_EMBOSSN);
 
 				restrict_bool = group_restrict_flag(gr, OB_RESTRICT_VIEW);
-				bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF, (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
+				bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF,
+				                  (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+				                  NULL, 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
 				uiButSetFunc(bt, restrictbutton_gr_restrict_view, scene, gr);
 
 				restrict_bool = group_restrict_flag(gr, OB_RESTRICT_SELECT);
-				bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_SELECT_ON : ICON_RESTRICT_SELECT_OFF, (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Restrict/Allow selection in the 3D View");
+				bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_SELECT_ON : ICON_RESTRICT_SELECT_OFF,
+				                  (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+				                  NULL, 0, 0, 0, 0, "Restrict/Allow selection in the 3D View");
 				uiButSetFunc(bt, restrictbutton_gr_restrict_select, scene, gr);
 
 				restrict_bool = group_restrict_flag(gr, OB_RESTRICT_RENDER);
-				bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_RENDER_ON : ICON_RESTRICT_RENDER_OFF, (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Restrict/Allow renderability");
+				bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_RENDER_ON : ICON_RESTRICT_RENDER_OFF,
+				                  (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+				                  NULL, 0, 0, 0, 0, "Restrict/Allow renderability");
 				uiButSetFunc(bt, restrictbutton_gr_restrict_render, scene, gr);
 
 				uiBlockSetEmboss(block, UI_EMBOSS);
@@ -463,7 +469,8 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
 				uiBlockSetEmboss(block, UI_EMBOSSN);
 				
 				bt = uiDefIconButBitI(block, ICONTOGN, SCE_LAY_DISABLE, 0, ICON_CHECKBOX_HLT - 1,
-				                      (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y, te->directdata, 0, 0, 0, 0, "Render this RenderLayer");
+				                      (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+				                      te->directdata, 0, 0, 0, 0, "Render this RenderLayer");
 				uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
 				
 				uiBlockSetEmboss(block, UI_EMBOSS);
@@ -476,13 +483,18 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
 				
 				
 				bt = uiDefIconButBitI(block, ICONTOG, passflag, 0, ICON_CHECKBOX_HLT - 1,
-				                      (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y, layflag, 0, 0, 0, 0, "Render this Pass");
+				                      (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+				                      layflag, 0, 0, 0, 0, "Render this Pass");
 				uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
 				
 				layflag++;  /* is lay_xor */
-				if (ELEM8(passflag, SCE_PASS_SPEC, SCE_PASS_SHADOW, SCE_PASS_AO, SCE_PASS_REFLECT, SCE_PASS_REFRACT, SCE_PASS_INDIRECT, SCE_PASS_EMIT, SCE_PASS_ENVIRONMENT))
+				if (ELEM8(passflag, SCE_PASS_SPEC, SCE_PASS_SHADOW, SCE_PASS_AO, SCE_PASS_REFLECT, SCE_PASS_REFRACT,
+				          SCE_PASS_INDIRECT, SCE_PASS_EMIT, SCE_PASS_ENVIRONMENT))
+				{
 					bt = uiDefIconButBitI(block, TOG, passflag, 0, (*layflag & passflag) ? ICON_DOT : ICON_BLANK1,
-					                      (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y, layflag, 0, 0, 0, 0, "Exclude this Pass from Combined");
+					                      (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+					                      layflag, 0, 0, 0, 0, "Exclude this Pass from Combined");
+				}
 				uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
 				
 				uiBlockSetEmboss(block, UI_EMBOSS);
@@ -493,11 +505,13 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
 				
 				uiBlockSetEmboss(block, UI_EMBOSSN);
 				bt = uiDefIconButBitI(block, ICONTOGN, eModifierMode_Realtime, 0, ICON_RESTRICT_VIEW_OFF,
-				                      (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y, &(md->mode), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
+				                      (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+				                      &(md->mode), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
 				uiButSetFunc(bt, restrictbutton_modifier_cb, scene, ob);
 				
 				bt = uiDefIconButBitI(block, ICONTOGN, eModifierMode_Render, 0, ICON_RESTRICT_RENDER_OFF,
-				                      (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y, &(md->mode), 0, 0, 0, 0, "Restrict/Allow renderability");
+				                      (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+				                      &(md->mode), 0, 0, 0, 0, "Restrict/Allow renderability");
 				uiButSetFunc(bt, restrictbutton_modifier_cb, scene, ob);
 			}
 			else if (tselem->type == TSE_POSE_CHANNEL) {
@@ -506,11 +520,13 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
 				
 				uiBlockSetEmboss(block, UI_EMBOSSN);
 				bt = uiDefIconButBitI(block, ICONTOG, BONE_HIDDEN_P, 0, ICON_RESTRICT_VIEW_OFF,
-				                      (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y, &(bone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
+				                      (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+				                      &(bone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
 				uiButSetFunc(bt, restrictbutton_bone_cb, NULL, bone);
 				
 				bt = uiDefIconButBitI(block, ICONTOG, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF,
-				                      (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y, &(bone->flag), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View");
+				                      (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+				                      &(bone->flag), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View");
 				uiButSetFunc(bt, restrictbutton_bone_cb, NULL, NULL);
 			}
 			else if (tselem->type == TSE_EBONE) {
@@ -518,11 +534,13 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
 				
 				uiBlockSetEmboss(block, UI_EMBOSSN);
 				bt = uiDefIconButBitI(block, ICONTOG, BONE_HIDDEN_A, 0, ICON_RESTRICT_VIEW_OFF,
-				                      (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y, &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
+				                      (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+				                      &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
 				uiButSetFunc(bt, restrictbutton_ebone_cb, NULL, ebone);
 				
 				bt = uiDefIconButBitI(block, ICONTOG, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF,
-				                      (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y, &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View");
+				                      (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+				                      &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View");
 				uiButSetFunc(bt, restrictbutton_ebone_cb, NULL, NULL);
 			}
 		}
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index ddbc49bf995..d911818d0cb 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -803,8 +803,12 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
 	}
 
 	/* One exception */
-	if (type == TSE_ID_BASE);
-	else if (id == NULL) return NULL;
+	if (type == TSE_ID_BASE) {
+		/* pass */
+	}
+	else if (id == NULL) {
+		return NULL;
+	}
 
 	te = MEM_callocN(sizeof(TreeElement), "tree elem");
 	/* add to the visual tree */
@@ -840,7 +844,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
 		TreeStoreElem *tsepar = parent ? TREESTORE(parent) : NULL;
 		
 		/* ID datablock */
-		if (tsepar==NULL || tsepar->type != TSE_ID_BASE)
+		if (tsepar == NULL || tsepar->type != TSE_ID_BASE)
 			outliner_add_id_contents(soops, te, tselem, id);
 	}
 	else if (type == TSE_ANIM_DATA) {
@@ -1511,7 +1515,7 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
 		}
 		/* make hierarchy */
 		ten = soops->tree.first;
-		ten= ten->next; /* first one is main */
+		ten = ten->next;  /* first one is main */
 		while (ten) {
 			TreeElement *nten = ten->next, *par;
 			tselem = TREESTORE(ten);
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index 79bf003a563..2b30e4e6b81 100644
--- a/source/blender/editors/space_view3d/view3d_header.c
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -487,11 +487,17 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
 		block = uiLayoutGetBlock(row);
 		
 		if (v3d->twflag & V3D_USE_MANIPULATOR) {
-			but = uiDefIconButBitC(block, TOG, V3D_MANIP_TRANSLATE, B_MAN_TRANS, ICON_MAN_TRANS, 0, 0, UI_UNIT_X, UI_UNIT_Y, &v3d->twtype, 1.0, 0.0, 0, 0, TIP_("Translate manipulator - Shift-Click for multiple modes"));
+			but = uiDefIconButBitC(block, TOG, V3D_MANIP_TRANSLATE, B_MAN_TRANS, ICON_MAN_TRANS,
+			                       0, 0, UI_UNIT_X, UI_UNIT_Y, &v3d->twtype, 1.0, 0.0, 0, 0,
+			                       TIP_("Translate manipulator - Shift-Click for multiple modes"));
 			uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
-			but = uiDefIconButBitC(block, TOG, V3D_MANIP_ROTATE, B_MAN_ROT, ICON_MAN_ROT, 0, 0, UI_UNIT_X, UI_UNIT_Y, &v3d->twtype, 1.0, 0.0, 0, 0, TIP_("Rotate manipulator - Shift-Click for multiple modes"));
+			but = uiDefIconButBitC(block, TOG, V3D_MANIP_ROTATE, B_MAN_ROT, ICON_MAN_ROT,
+			                       0, 0, UI_UNIT_X, UI_UNIT_Y, &v3d->twtype, 1.0, 0.0, 0, 0,
+			                       TIP_("Rotate manipulator - Shift-Click for multiple modes"));
 			uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
-			but = uiDefIconButBitC(block, TOG, V3D_MANIP_SCALE, B_MAN_SCALE, ICON_MAN_SCALE, 0, 0, UI_UNIT_X, UI_UNIT_Y, &v3d->twtype, 1.0, 0.0, 0, 0, TIP_("Scale manipulator - Shift-Click for multiple modes"));
+			but = uiDefIconButBitC(block, TOG, V3D_MANIP_SCALE, B_MAN_SCALE, ICON_MAN_SCALE,
+			                       0, 0, UI_UNIT_X, UI_UNIT_Y, &v3d->twtype, 1.0, 0.0, 0, 0,
+			                       TIP_("Scale manipulator - Shift-Click for multiple modes"));
 			uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
 		}
 			
@@ -500,7 +506,8 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
 		}
 			
 		str_menu = BIF_menustringTransformOrientation(C, "Orientation");
-		but = uiDefButC(block, MENU, B_MAN_MODE, str_menu, 0, 0, 70 * dpi_fac, UI_UNIT_Y, &v3d->twmode, 0, 0, 0, 0, TIP_("Transform Orientation"));
+		but = uiDefButC(block, MENU, B_MAN_MODE, str_menu, 0, 0, 70 * dpi_fac, UI_UNIT_Y, &v3d->twmode, 0, 0, 0, 0,
+		                TIP_("Transform Orientation"));
 		uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
 		MEM_freeN((void *)str_menu);
 	}
-- 
cgit v1.2.3


From 0ac66ada2d307ca8e7c82ea5b47ff73611cff55f Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Sun, 23 Dec 2012 01:54:11 +0000
Subject: initial support for 'occlude background geometry' in weight paint
 mode.

Only support mouse vertex select at the moment.
---
 source/blender/editors/include/ED_mesh.h           |  6 +-
 source/blender/editors/mesh/editface.c             |  2 +-
 source/blender/editors/mesh/meshtools.c            | 82 ++++++++++++++++++----
 source/blender/editors/sculpt_paint/paint_vertex.c | 10 +--
 source/blender/editors/space_view3d/drawobject.c   |  8 ++-
 .../blender/editors/space_view3d/view3d_select.c   |  5 +-
 6 files changed, 86 insertions(+), 27 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 1b4a67d38c0..f5ab002e0ef 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -291,9 +291,9 @@ int            mesh_get_x_mirror_vert(struct Object *ob, int index);
 struct BMVert *editbmesh_get_x_mirror_vert(struct Object *ob, struct BMEditMesh *em, struct BMVert *eve, const float co[3], int index);
 int           *mesh_get_x_mirror_faces(struct Object *ob, struct BMEditMesh *em);
 
-int ED_mesh_pick_vert(struct bContext *C, struct Mesh *me, const int mval[2], unsigned int *index, int size);
-int ED_mesh_pick_face(struct bContext *C, struct Mesh *me, const int mval[2], unsigned int *index, int size);
-int ED_mesh_pick_face_vert(struct bContext *C, struct Mesh *me, struct Object *ob, const int mval[2], unsigned int *index, int size);
+int ED_mesh_pick_vert(struct bContext *C,      struct Object *ob, const int mval[2], unsigned int *index, int size, int use_zbuf);
+int ED_mesh_pick_face(struct bContext *C,      struct Object *ob, const int mval[2], unsigned int *index, int size);
+int ED_mesh_pick_face_vert(struct bContext *C, struct Object *ob, const int mval[2], unsigned int *index, int size);
 
 #define ED_MESH_PICK_DEFAULT_VERT_SIZE 50
 #define ED_MESH_PICK_DEFAULT_FACE_SIZE 3
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
index 29139c5154f..11226b38cbb 100644
--- a/source/blender/editors/mesh/editface.c
+++ b/source/blender/editors/mesh/editface.c
@@ -477,7 +477,7 @@ int paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], in
 	/* Get the face under the cursor */
 	me = BKE_mesh_from_object(ob);
 
-	if (!ED_mesh_pick_face(C, me, mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE))
+	if (!ED_mesh_pick_face(C, ob, mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE))
 		return 0;
 	
 	if (index >= me->totpoly)
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index 773331d20f8..d798dfb6ccb 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -1165,9 +1165,12 @@ int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em)
  *
  * \return boolean TRUE == Found
  */
-int ED_mesh_pick_face(bContext *C, Mesh *me, const int mval[2], unsigned int *index, int size)
+int ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], unsigned int *index, int size)
 {
 	ViewContext vc;
+	Mesh *me = ob->data;
+
+	BLI_assert(me && GS(me->id.name) == ID_ME);
 
 	if (!me || me->totpoly == 0)
 		return 0;
@@ -1197,11 +1200,14 @@ int ED_mesh_pick_face(bContext *C, Mesh *me, const int mval[2], unsigned int *in
  * Use when the back buffer stores face index values. but we want a vert.
  * This gets the face then finds the closest vertex to mval.
  */
-int ED_mesh_pick_face_vert(bContext *C, Mesh *me, Object *ob, const int mval[2], unsigned int *index, int size)
+int ED_mesh_pick_face_vert(bContext *C, Object *ob, const int mval[2], unsigned int *index, int size)
 {
 	unsigned int poly_index;
+	Mesh *me = ob->data;
+
+	BLI_assert(me && GS(me->id.name) == ID_ME);
 
-	if (ED_mesh_pick_face(C, me, mval, &poly_index, size)) {
+	if (ED_mesh_pick_face(C, ob, mval, &poly_index, size)) {
 		Scene *scene = CTX_data_scene(C);
 		struct ARegion *ar = CTX_wm_region(C);
 
@@ -1250,31 +1256,77 @@ int ED_mesh_pick_face_vert(bContext *C, Mesh *me, Object *ob, const int mval[2],
  *
  * \return boolean TRUE == Found
  */
-int ED_mesh_pick_vert(bContext *C, Mesh *me, const int mval[2], unsigned int *index, int size)
+int ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int *index, int size, int use_zbuf)
 {
 	ViewContext vc;
+	Mesh *me = ob->data;
+
+	BLI_assert(me && GS(me->id.name) == ID_ME);
 
 	if (!me || me->totvert == 0)
 		return 0;
 
 	view3d_set_viewcontext(C, &vc);
 
-	if (size > 0) {
-		/* sample rect to increase chances of selecting, so that when clicking
-		 * on an face in the backbuf, we can still select a vert */
+	if (use_zbuf) {
+		if (size > 0) {
+			/* sample rect to increase chances of selecting, so that when clicking
+			 * 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);
+			float dummy_dist;
+			*index = view3d_sample_backbuf_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]);
+		}
+
+		if ((*index) <= 0 || (*index) > (unsigned int)me->totvert)
+			return 0;
+
+		(*index)--;
 	}
 	else {
-		/* sample only on the exact position */
-		*index = view3d_sample_backbuf(&vc, mval[0], mval[1]);
-	}
+		/* derived mesh to find deformed locations */
+		DerivedMesh *dm = mesh_get_derived_final(vc.scene, ob, CD_MASK_BAREMESH);
+		struct ARegion *ar = vc.ar;
 
-	if ((*index) <= 0 || (*index) > (unsigned int)me->totvert)
-		return 0;
+		int v_idx_best = -1;
+		int v_idx;
 
-	(*index)--;
+
+		if (dm == NULL) {
+			return 0;
+		}
+
+		if (dm->getVertCo) {
+			/* find the vert closest to 'mval' */
+			const float mval_f[2] = {(float)mval[0],
+			                         (float)mval[1]};
+			float len_best = FLT_MAX;
+
+			v_idx = me->totvert - 1;
+			do {
+				float co[3], sco[2], len;
+				dm->getVertCo(dm, v_idx, co);
+				mul_m4_v3(ob->obmat, co);
+				if (ED_view3d_project_float_global(ar, co, sco, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+					len = len_squared_v2v2(mval_f, sco);
+					if (len < len_best) {
+						len_best = len;
+						v_idx_best = v_idx;
+					}
+				}
+			} while (v_idx--);
+		}
+
+		dm->release(dm);
+
+		if (v_idx_best != -1) {
+			*index = v_idx_best;
+			return 1;
+		}
+	}
 
 	return 1;
 }
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 359486a4a8d..63f5b7e6904 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -1037,15 +1037,15 @@ static int weight_sample_invoke(bContext *C, wmOperator *op, wmEvent *event)
 		view3d_operator_needs_opengl(C);
 
 		if (use_vert_sel) {
-			if (ED_mesh_pick_vert(C, me, event->mval, &index, ED_MESH_PICK_DEFAULT_VERT_SIZE)) {
+			if (ED_mesh_pick_vert(C, vc.obact, event->mval, &index, ED_MESH_PICK_DEFAULT_VERT_SIZE, TRUE)) {
 				v_idx_best = index;
 			}
 		}
 		else {
-			if (ED_mesh_pick_face_vert(C, me, vc.obact, event->mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) {
+			if (ED_mesh_pick_face_vert(C, vc.obact, event->mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) {
 				v_idx_best = index;
 			}
-			else if (ED_mesh_pick_face(C, me, event->mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) {
+			else if (ED_mesh_pick_face(C, vc.obact, event->mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) {
 				/* this relies on knowning the internal worksings of ED_mesh_pick_face_vert() */
 				BKE_report(op->reports, RPT_WARNING, "The modifier used does not support deformed locations");
 			}
@@ -1126,13 +1126,13 @@ static EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C, PointerRNA
 				view3d_operator_needs_opengl(C);
 
 				if (use_vert_sel) {
-					if (ED_mesh_pick_vert(C, me, mval, &index, ED_MESH_PICK_DEFAULT_VERT_SIZE)) {
+					if (ED_mesh_pick_vert(C, vc.obact, mval, &index, ED_MESH_PICK_DEFAULT_VERT_SIZE, TRUE)) {
 						MDeformVert *dvert = &me->dvert[index];
 						found |= weight_paint_sample_enum_itemf__helper(dvert, defbase_tot, groups);
 					}
 				}
 				else {
-					if (ED_mesh_pick_face(C, me, mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) {
+					if (ED_mesh_pick_face(C, vc.obact, mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) {
 						MPoly *mp = &me->mpoly[index];
 						unsigned int fidx = mp->totloop - 1;
 
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 01759fff74f..91f25c960e9 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -3244,11 +3244,15 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
 	}
 	
 	if (is_obact && paint_vertsel_test(ob)) {
-		
+		const int use_depth = (v3d->flag & V3D_ZBUF_SELECT);
 		glColor3f(0.0f, 0.0f, 0.0f);
 		glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
-		
+
+		if (!use_depth) glDisable(GL_DEPTH_TEST);
+		else            bglPolygonOffset(rv3d->dist, 1.0);
 		drawSelectedVertices(dm, ob->data);
+		if (!use_depth) glEnable(GL_DEPTH_TEST);
+		else            bglPolygonOffset(rv3d->dist, 0.0);
 		
 		glPointSize(1.0f);
 	}
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index d37042fa2ec..c08df884d4f 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -2142,11 +2142,14 @@ void VIEW3D_OT_select_border(wmOperatorType *ot)
 /* gets called via generic mouse select operator */
 static int mouse_weight_paint_vertex_select(bContext *C, const int mval[2], short extend, short deselect, short toggle, Object *obact)
 {
+	View3D *v3d = CTX_wm_view3d(C);
+	const int use_zbuf = (v3d->flag & V3D_ZBUF_SELECT);
+
 	Mesh *me = obact->data; /* already checked for NULL */
 	unsigned int index = 0;
 	MVert *mv;
 
-	if (ED_mesh_pick_vert(C, me, mval, &index, ED_MESH_PICK_DEFAULT_VERT_SIZE)) {
+	if (ED_mesh_pick_vert(C, obact, mval, &index, ED_MESH_PICK_DEFAULT_VERT_SIZE, use_zbuf)) {
 		mv = &me->mvert[index];
 		if (extend) {
 			mv->flag |= SELECT;
-- 
cgit v1.2.3


From b3128cf4068490848834b286df4cc5ca338529c0 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Sun, 23 Dec 2012 02:04:38 +0000
Subject: minor speedup ED_mesh_pick_vert, ED_mesh_pick_face_vert avoid matrix
 multiply, use len_manhattan_v2v2

---
 source/blender/editors/mesh/meshtools.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index d798dfb6ccb..22f7eb707ab 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -40,6 +40,8 @@
 #include "DNA_modifier_types.h"
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
 
 #include "BLI_math.h"
 #include "BLI_blenlib.h"
@@ -1216,6 +1218,8 @@ int ED_mesh_pick_face_vert(bContext *C, Object *ob, const int mval[2], unsigned
 		int v_idx_best = -1;
 
 		if (dm->getVertCo) {
+			RegionView3D *rv3d = ar->regiondata;
+
 			/* find the vert closest to 'mval' */
 			const float mval_f[2] = {(float)mval[0],
 			                         (float)mval[1]};
@@ -1223,14 +1227,15 @@ int ED_mesh_pick_face_vert(bContext *C, Object *ob, const int mval[2], unsigned
 			int fidx;
 			float len_best = FLT_MAX;
 
+			ED_view3d_init_mats_rv3d(ob, rv3d);
+
 			fidx = mp->totloop - 1;
 			do {
 				float co[3], sco[2], len;
 				const int v_idx = me->mloop[mp->loopstart + fidx].v;
 				dm->getVertCo(dm, v_idx, co);
-				mul_m4_v3(ob->obmat, co);
-				if (ED_view3d_project_float_global(ar, co, sco, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
-					len = len_squared_v2v2(mval_f, sco);
+				if (ED_view3d_project_float_object(ar, co, sco, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+					len = len_manhattan_v2v2(mval_f, sco);
 					if (len < len_best) {
 						len_best = len;
 						v_idx_best = v_idx;
@@ -1300,18 +1305,21 @@ int ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int *
 		}
 
 		if (dm->getVertCo) {
+			RegionView3D *rv3d = ar->regiondata;
+
 			/* find the vert closest to 'mval' */
 			const float mval_f[2] = {(float)mval[0],
 			                         (float)mval[1]};
 			float len_best = FLT_MAX;
 
+			ED_view3d_init_mats_rv3d(ob, rv3d);
+
 			v_idx = me->totvert - 1;
 			do {
 				float co[3], sco[2], len;
 				dm->getVertCo(dm, v_idx, co);
-				mul_m4_v3(ob->obmat, co);
-				if (ED_view3d_project_float_global(ar, co, sco, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
-					len = len_squared_v2v2(mval_f, sco);
+				if (ED_view3d_project_float_object(ar, co, sco, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+					len = len_manhattan_v2v2(mval_f, sco);
 					if (len < len_best) {
 						len_best = len;
 						v_idx_best = v_idx;
-- 
cgit v1.2.3


From 45681464e7d0ce2b040b4f835a3a40c78d55b7ae Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Sun, 23 Dec 2012 02:32:03 +0000
Subject: use foreachMappedVert for ED_mesh_pick_vert()

---
 source/blender/blenkernel/intern/DerivedMesh.c | 15 +++---
 source/blender/editors/mesh/meshtools.c        | 73 ++++++++++++++++----------
 2 files changed, 52 insertions(+), 36 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 2dc01513149..4ccec3893e8 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -2310,20 +2310,19 @@ DerivedMesh *editbmesh_get_derived_base(Object *obedit, BMEditMesh *em)
 static void make_vertexcosnos__mapFunc(void *userData, int index, const float co[3],
                                        const float no_f[3], const short no_s[3])
 {
-	float *vec = userData;
-	
-	vec += 6 * index;
+	DMCoNo *co_no = &((DMCoNo *)userData)[index];
 
 	/* check if we've been here before (normal should not be 0) */
-	if (vec[3] || vec[4] || vec[5]) return;
+	if (!is_zero_v3(co_no->no)) {
+		return;
+	}
 
-	copy_v3_v3(vec, co);
-	vec += 3;
+	copy_v3_v3(co_no->co, co);
 	if (no_f) {
-		copy_v3_v3(vec, no_f);
+		copy_v3_v3(co_no->no, no_f);
 	}
 	else {
-		normal_short_to_float_v3(vec, no_s);
+		normal_short_to_float_v3(co_no->no, no_s);
 	}
 }
 
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index 22f7eb707ab..96b8f1080b9 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -1261,6 +1261,32 @@ int ED_mesh_pick_face_vert(bContext *C, Object *ob, const int mval[2], unsigned
  *
  * \return boolean TRUE == Found
  */
+typedef struct VertPickData {
+	const MVert *mvert;
+	const float *mval_f;  /* [2] */
+	ARegion *ar;
+
+	/* runtime */
+	float len_best;
+	int v_idx_best;
+} VertPickData;
+
+static void ed_mesh_pick_vert__mapFunc(void *userData, int index, const float co[3],
+                                       const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
+{
+	VertPickData *data = userData;
+	if ((data->mvert[index].flag & ME_HIDE) == 0) {
+		float sco[2];
+
+		if (ED_view3d_project_float_object(data->ar, co, sco, V3D_PROJ_TEST_CLIP_DEFAULT) == V3D_PROJ_RET_OK) {
+			const float len = len_manhattan_v2v2(data->mval_f, sco);
+			if (len < data->len_best) {
+				data->len_best = len;
+				data->v_idx_best = index;
+			}
+		}
+	}
+}
 int ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int *index, int size, int use_zbuf)
 {
 	ViewContext vc;
@@ -1294,46 +1320,37 @@ int ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int *
 	else {
 		/* derived mesh to find deformed locations */
 		DerivedMesh *dm = mesh_get_derived_final(vc.scene, ob, CD_MASK_BAREMESH);
-		struct ARegion *ar = vc.ar;
+		ARegion *ar = vc.ar;
+		RegionView3D *rv3d = ar->regiondata;
 
-		int v_idx_best = -1;
-		int v_idx;
+		/* find the vert closest to 'mval' */
+		const float mval_f[2] = {(float)mval[0],
+		                         (float)mval[1]};
 
+		VertPickData data = {0};
+
+		ED_view3d_init_mats_rv3d(ob, rv3d);
 
 		if (dm == NULL) {
 			return 0;
 		}
 
-		if (dm->getVertCo) {
-			RegionView3D *rv3d = ar->regiondata;
-
-			/* find the vert closest to 'mval' */
-			const float mval_f[2] = {(float)mval[0],
-			                         (float)mval[1]};
-			float len_best = FLT_MAX;
-
-			ED_view3d_init_mats_rv3d(ob, rv3d);
+		/* setup data */
+		data.mvert = me->mvert;
+		data.ar = ar;
+		data.mval_f = mval_f;
+		data.len_best = FLT_MAX;
+		data.v_idx_best = -1;
 
-			v_idx = me->totvert - 1;
-			do {
-				float co[3], sco[2], len;
-				dm->getVertCo(dm, v_idx, co);
-				if (ED_view3d_project_float_object(ar, co, sco, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
-					len = len_manhattan_v2v2(mval_f, sco);
-					if (len < len_best) {
-						len_best = len;
-						v_idx_best = v_idx;
-					}
-				}
-			} while (v_idx--);
-		}
+		dm->foreachMappedVert(dm, ed_mesh_pick_vert__mapFunc, &data);
 
 		dm->release(dm);
 
-		if (v_idx_best != -1) {
-			*index = v_idx_best;
-			return 1;
+		if (data.v_idx_best == -1) {
+			return 0;
 		}
+
+		*index = data.v_idx_best;
 	}
 
 	return 1;
-- 
cgit v1.2.3


From 4612bbf7dbe739795678688cb3814c1f5bbc38b1 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Sun, 23 Dec 2012 03:04:19 +0000
Subject: add zbuf/depth option to weight paint lasso select.

---
 source/blender/editors/include/ED_view3d.h         |  4 ++
 source/blender/editors/space_view3d/drawobject.c   |  8 ++--
 .../editors/space_view3d/view3d_iterators.c        | 47 ++++++++++++++++++++++
 .../blender/editors/space_view3d/view3d_select.c   | 37 +++++++++++++++--
 4 files changed, 88 insertions(+), 8 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index f7f58a4ee7a..4df49920bf7 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -124,6 +124,10 @@ typedef enum {
 /* view3d_iterators.c */
 
 /* foreach iterators */
+void meshobject_foreachScreenVert(
+        struct ViewContext *vc,
+        void (*func)(void *userData, struct MVert *eve, const float screen_co[2], int index),
+        void *userData, const eV3DProjTest clip_flag);
 void mesh_foreachScreenVert(
         struct ViewContext *vc,
         void (*func)(void *userData, struct BMVert *eve, const float screen_co[2], int index),
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 91f25c960e9..12dca8685c8 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -101,7 +101,7 @@ typedef enum eWireDrawMode {
 } eWireDrawMode;
 
 typedef struct drawDMVerts_userData {
-	BMEditMesh *em; /* BMESH BRANCH ONLY */
+	BMEditMesh *em;
 
 	int sel;
 	BMVert *eve_act;
@@ -119,7 +119,7 @@ typedef struct drawDMVerts_userData {
 } drawDMVerts_userData;
 
 typedef struct drawDMEdgesSel_userData {
-	BMEditMesh *em; /* BMESH BRANCH ONLY */
+	BMEditMesh *em;
 
 	unsigned char *baseCol, *selCol, *actCol;
 	BMEdge *eed_act;
@@ -128,8 +128,8 @@ typedef struct drawDMEdgesSel_userData {
 typedef struct drawDMFacesSel_userData {
 	unsigned char *cols[3];
 
-	DerivedMesh *dm; /* BMESH BRANCH ONLY */
-	BMEditMesh *em;  /* BMESH BRANCH ONLY */
+	DerivedMesh *dm;
+	BMEditMesh *em;
 
 	BMFace *efa_act;
 	int *orig_index_mf_to_mpoly;
diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c
index a0b36e57d69..81e890c37ee 100644
--- a/source/blender/editors/space_view3d/view3d_iterators.c
+++ b/source/blender/editors/space_view3d/view3d_iterators.c
@@ -27,6 +27,7 @@
 #include "DNA_curve_types.h"
 #include "DNA_lattice_types.h"
 #include "DNA_meta_types.h"
+#include "DNA_mesh_types.h"
 #include "DNA_armature_types.h"
 #include "DNA_object_types.h"
 
@@ -47,6 +48,12 @@
 #include "ED_object.h"
 #include "ED_view3d.h"
 
+typedef struct foreachScreenObjectVert_userData {
+	void (*func)(void *userData, MVert *mv, const float screen_co_b[2], int index);
+	void *userData;
+	ViewContext vc;
+	eV3DProjTest clip_flag;
+} foreachScreenObjectVert_userData;
 
 typedef struct foreachScreenVert_userData {
 	void (*func)(void *userData, BMVert *eve, const float screen_co_b[2], int index);
@@ -79,6 +86,46 @@ typedef struct foreachScreenFace_userData {
 
 /* ------------------------------------------------------------------------ */
 
+
+static void meshobject_foreachScreenVert__mapFunc(void *userData, int index, const float co[3],
+                                            const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
+{
+	foreachScreenObjectVert_userData *data = userData;
+	struct MVert *mv = &((Mesh *)(data->vc.obact->data))->mvert[index];
+
+	if (!(mv->flag & ME_HIDE)) {
+		float screen_co[2];
+
+		if (ED_view3d_project_float_object(data->vc.ar, co, screen_co, data->clip_flag) != V3D_PROJ_RET_OK) {
+			return;
+		}
+
+		data->func(data->userData, mv, screen_co, index);
+	}
+}
+
+void meshobject_foreachScreenVert(
+        ViewContext *vc,
+        void (*func)(void *userData, MVert *eve, const float screen_co[2], int index),
+        void *userData, eV3DProjTest clip_flag)
+{
+	foreachScreenObjectVert_userData data;
+	DerivedMesh *dm = mesh_get_derived_deform(vc->scene, vc->obact, CD_MASK_BAREMESH);
+
+	data.vc = *vc;
+	data.func = func;
+	data.userData = userData;
+	data.clip_flag = clip_flag;
+
+	if (clip_flag & V3D_PROJ_TEST_CLIP_BB) {
+		ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat);  /* for local clipping lookups */
+	}
+
+	dm->foreachMappedVert(dm, meshobject_foreachScreenVert__mapFunc, &data);
+
+	dm->release(dm);
+}
+
 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, const float co[3],
                                             const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
 {
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index c08df884d4f..f09518d956d 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -70,6 +70,7 @@
 #include "BKE_paint.h"
 #include "BKE_tessmesh.h"
 #include "BKE_tracking.h"
+#include "BKE_utildefines.h"
 
 
 #include "BIF_gl.h"
@@ -800,8 +801,19 @@ static int do_paintvert_box_select(ViewContext *vc, rcti *rect, int select, int
 	return OPERATOR_FINISHED;
 }
 
+static void do_lasso_select_meshobject__doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index))
+{
+	LassoSelectUserData *data = userData;
+
+	if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
+	    BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED))
+	{
+		BKE_BIT_TEST_SET(mv->flag, data->select, SELECT);
+	}
+}
 static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], short moves, short extend, short select)
 {
+	const int use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT);
 	Object *ob = vc->obact;
 	Mesh *me = ob ? ob->data : NULL;
 	rcti rect;
@@ -811,14 +823,31 @@ static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], sh
 
 	if (extend == 0 && select)
 		paintvert_deselect_all_visible(ob, SEL_DESELECT, FALSE);  /* flush selection at the end */
-	bm_vertoffs = me->totvert + 1; /* max index array */
 
 	BLI_lasso_boundbox(&rect, mcords, moves);
-	EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
 
-	edbm_backbuf_check_and_select_verts_obmode(me, select);
+	if (use_zbuf) {
+		bm_vertoffs = me->totvert + 1; /* max index array */
 
-	EDBM_backbuf_free();
+		EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+
+		edbm_backbuf_check_and_select_verts_obmode(me, select);
+
+		EDBM_backbuf_free();
+	}
+	else {
+		LassoSelectUserData data;
+		rcti rect;
+
+		BLI_lasso_boundbox(&rect, mcords, moves);
+
+		view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select);
+
+		ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d);
+
+		meshobject_foreachScreenVert(vc, do_lasso_select_meshobject__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+
+	}
 
 	paintvert_flush_flags(ob);
 }
-- 
cgit v1.2.3


From bdda669096069558db8829fa5676b1e165ec3203 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Sun, 23 Dec 2012 07:30:48 +0000
Subject: add zbuf/depth option to weight paint border & circle select

---
 .../blender/editors/space_view3d/view3d_select.c   | 161 +++++++++++++--------
 1 file changed, 99 insertions(+), 62 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index f09518d956d..b337d703192 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -742,65 +742,6 @@ static void do_lasso_select_meta(ViewContext *vc, const int mcords[][2], short m
 	mball_foreachScreenElem(vc, do_lasso_select_mball__doSelectElem, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
 }
 
-static int do_paintvert_box_select(ViewContext *vc, rcti *rect, int select, int extend)
-{
-	Mesh *me;
-	MVert *mvert;
-	struct ImBuf *ibuf;
-	unsigned int *rt;
-	int a, index;
-	char *selar;
-	int sx = BLI_rcti_size_x(rect) + 1;
-	int sy = BLI_rcti_size_y(rect) + 1;
-
-	me = vc->obact->data;
-
-	if (me == NULL || me->totvert == 0 || sx * sy <= 0)
-		return OPERATOR_CANCELLED;
-
-	selar = MEM_callocN(me->totvert + 1, "selar");
-
-	if (extend == 0 && select)
-		paintvert_deselect_all_visible(vc->obact, SEL_DESELECT, FALSE);
-
-	view3d_validate_backbuf(vc);
-
-	ibuf = IMB_allocImBuf(sx, sy, 32, IB_rect);
-	rt = ibuf->rect;
-	glReadPixels(rect->xmin + vc->ar->winrct.xmin,  rect->ymin + vc->ar->winrct.ymin, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE,  ibuf->rect);
-	if (ENDIAN_ORDER == B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf);
-
-	a = sx * sy;
-	while (a--) {
-		if (*rt) {
-			index = WM_framebuffer_to_index(*rt);
-			if (index <= me->totvert) selar[index] = 1;
-		}
-		rt++;
-	}
-
-	mvert = me->mvert;
-	for (a = 1; a <= me->totvert; a++, mvert++) {
-		if (selar[a]) {
-			if ((mvert->flag & ME_HIDE) == 0) {
-				if (select) mvert->flag |=  SELECT;
-				else        mvert->flag &= ~SELECT;
-			}
-		}
-	}
-
-	IMB_freeImBuf(ibuf);
-	MEM_freeN(selar);
-
-#ifdef __APPLE__	
-	glReadBuffer(GL_BACK);
-#endif
-
-	paintvert_flush_flags(vc->obact);
-
-	return OPERATOR_FINISHED;
-}
-
 static void do_lasso_select_meshobject__doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index))
 {
 	LassoSelectUserData *data = userData;
@@ -1699,6 +1640,85 @@ int edge_inside_circle(const float cent[2], float radius, const float screen_co_
 	return FALSE;
 }
 
+static void do_paintvert_box_select__doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index))
+{
+	BoxSelectUserData *data = userData;
+
+	if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co)) {
+		BKE_BIT_TEST_SET(mv->flag, data->select, SELECT);
+	}
+}
+static int do_paintvert_box_select(ViewContext *vc, rcti *rect, int select, int extend)
+{
+	const int use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT);
+	Mesh *me;
+	MVert *mvert;
+	struct ImBuf *ibuf;
+	unsigned int *rt;
+	int a, index;
+	char *selar;
+	int sx = BLI_rcti_size_x(rect) + 1;
+	int sy = BLI_rcti_size_y(rect) + 1;
+
+	me = vc->obact->data;
+
+	if (me == NULL || me->totvert == 0 || sx * sy <= 0)
+		return OPERATOR_CANCELLED;
+
+
+	if (extend == 0 && select)
+		paintvert_deselect_all_visible(vc->obact, SEL_DESELECT, FALSE);
+
+	if (use_zbuf) {
+		selar = MEM_callocN(me->totvert + 1, "selar");
+		view3d_validate_backbuf(vc);
+
+		ibuf = IMB_allocImBuf(sx, sy, 32, IB_rect);
+		rt = ibuf->rect;
+		glReadPixels(rect->xmin + vc->ar->winrct.xmin,  rect->ymin + vc->ar->winrct.ymin, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE,  ibuf->rect);
+		if (ENDIAN_ORDER == B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf);
+
+		a = sx * sy;
+		while (a--) {
+			if (*rt) {
+				index = WM_framebuffer_to_index(*rt);
+				if (index <= me->totvert) selar[index] = 1;
+			}
+			rt++;
+		}
+
+		mvert = me->mvert;
+		for (a = 1; a <= me->totvert; a++, mvert++) {
+			if (selar[a]) {
+				if ((mvert->flag & ME_HIDE) == 0) {
+					if (select) mvert->flag |=  SELECT;
+					else        mvert->flag &= ~SELECT;
+				}
+			}
+		}
+
+		IMB_freeImBuf(ibuf);
+		MEM_freeN(selar);
+
+#ifdef __APPLE__
+		glReadBuffer(GL_BACK);
+#endif
+	}
+	else {
+		BoxSelectUserData data;
+
+		view3d_userdata_boxselect_init(&data, vc, rect, select);
+
+		ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d);
+
+		meshobject_foreachScreenVert(vc, do_paintvert_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+	}
+
+	paintvert_flush_flags(vc->obact);
+
+	return OPERATOR_FINISHED;
+}
+
 static void do_nurbs_box_select__doSelect(void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2])
 {
 	BoxSelectUserData *data = userData;
@@ -2398,22 +2418,39 @@ static void paint_facesel_circle_select(ViewContext *vc, int select, const int m
 	}
 }
 
+static void paint_vertsel_circle_select_doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index))
+{
+	CircleSelectUserData *data = userData;
 
+	if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
+		BKE_BIT_TEST_SET(mv->flag, data->select, SELECT);
+	}
+}
 static void paint_vertsel_circle_select(ViewContext *vc, int select, const int mval[2], float rad)
 {
+	const int use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT);
 	Object *ob = vc->obact;
-	Mesh *me = ob ? ob->data : NULL;
+	Mesh *me = ob->data;
 	/* int bbsel; */ /* UNUSED */
 	/* CircleSelectUserData data = {NULL}; */ /* UNUSED */
-	if (me) {
+
+	if (use_zbuf) {
 		bm_vertoffs = me->totvert + 1; /* max index array */
 
 		/* bbsel = */ /* UNUSED */ EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
 		edbm_backbuf_check_and_select_verts_obmode(me, select == LEFTMOUSE);
 		EDBM_backbuf_free();
+	}
+	else {
+		CircleSelectUserData data;
 
-		paintvert_flush_flags(ob);
+		ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); /* for foreach's screen/vert projection */
+
+		view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
+		meshobject_foreachScreenVert(vc, paint_vertsel_circle_select_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
 	}
+
+	paintvert_flush_flags(ob);
 }
 
 
-- 
cgit v1.2.3


From cb70c5ba0fee7f1313a037eda7fae82356132c10 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Sun, 23 Dec 2012 08:20:44 +0000
Subject: fix for bug where weight paint would draw hidden faces but not draw
 then with the backbuffer (depth selection).

---
 source/blender/blenlib/intern/math_matrix.c      |  2 +-
 source/blender/editors/space_view3d/drawmesh.c   |  2 +-
 source/blender/editors/space_view3d/drawobject.c | 28 ++++++++++++++----------
 3 files changed, 19 insertions(+), 13 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index 3a294769eb3..02fc5b07d6d 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -990,7 +990,7 @@ void normalize_m4_m4(float rmat[4][4], float mat[4][4])
 	if (len != 0.0f) rmat[2][3] = mat[2][3] / len;
 }
 
-void adjoint_m2_m2(float m1[][2], float m[][2])
+void adjoint_m2_m2(float m1[2][2], float m[2][2])
 {
 	BLI_assert(m1 != m);
 	m1[0][0] =  m[1][1];
diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c
index e36654323fd..ad7d3b1bddd 100644
--- a/source/blender/editors/space_view3d/drawmesh.c
+++ b/source/blender/editors/space_view3d/drawmesh.c
@@ -1018,7 +1018,7 @@ void draw_mesh_paint(View3D *v3d, RegionView3D *rv3d,
 	const short do_light = (v3d->drawtype >= OB_SOLID);
 
 	/* hide faces in face select mode */
-	if (draw_flags & DRAW_FACE_SELECT)
+	if (me->editflag & (ME_EDIT_PAINT_VERT_SEL | ME_EDIT_PAINT_FACE_SEL))
 		facemask = wpaint__setSolidDrawOptions_facemask;
 
 	if (ob->mode & OB_MODE_WEIGHT_PAINT) {
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 12dca8685c8..01849429119 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -7103,7 +7103,21 @@ static DMDrawOption bbs_mesh_solid_hide2__setDrawOpts(void *userData, int index)
 		return DM_DRAW_OPTION_SKIP;
 	}
 }
-static void bbs_mesh_solid(Scene *scene, Object *ob)
+
+static void bbs_mesh_solid_verts(Scene *scene, Object *ob)
+{
+	Mesh *me = ob->data;
+	DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
+	glColor3ub(0, 0, 0);
+
+	dm->drawMappedFaces(dm, bbs_mesh_solid_hide2__setDrawOpts, GPU_enable_material, NULL, me, 0);
+
+	bbs_obmode_mesh_verts(ob, dm, 1);
+	bm_vertoffs = me->totvert + 1;
+	dm->release(dm);
+}
+
+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;
@@ -7168,18 +7182,10 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
 				    /* currently vertex select only supports weight paint */
 				    (ob->mode & OB_MODE_WEIGHT_PAINT))
 				{
-					DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
-					glColor3ub(0, 0, 0);
-
-					dm->drawMappedFaces(dm, bbs_mesh_solid_hide2__setDrawOpts, GPU_enable_material, NULL, me, 0);
-
-
-					bbs_obmode_mesh_verts(ob, dm, 1);
-					bm_vertoffs = me->totvert + 1;
-					dm->release(dm);
+					bbs_mesh_solid_verts(scene, ob);
 				}
 				else {
-					bbs_mesh_solid(scene, ob);
+					bbs_mesh_solid_faces(scene, ob);
 				}
 			}
 			break;
-- 
cgit v1.2.3


From c4a165f168196b52ed66105bbe99fe51da8b5317 Mon Sep 17 00:00:00 2001
From: Bastien Montagne 
Date: Sun, 23 Dec 2012 10:51:48 +0000
Subject: Adding Scale Visual keying (and de-duplicated part of the code
 returning visual values to key).

---
 source/blender/editors/animation/keyframing.c | 131 +++++++++++++-------------
 1 file changed, 66 insertions(+), 65 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 8ba330e7c3c..aee53fed3c8 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -540,8 +540,8 @@ static float setting_get_rna_value(PointerRNA *ptr, PropertyRNA *prop, int index
 enum {
 	VISUALKEY_NONE = 0,
 	VISUALKEY_LOC,
-	VISUALKEY_ROT
-	/* VISUALKEY_SCA */ /* TODO - looks like support can be added now */
+	VISUALKEY_ROT,
+	VISUALKEY_SCA,
 };
 
 /* This helper function determines if visual-keyframing should be used when  
@@ -560,7 +560,7 @@ static short visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
 	/* validate data */
 	if (ELEM3(NULL, ptr, ptr->data, prop))
 		return 0;
-		
+	
 	/* get first constraint and determine type of keyframe constraints to check for 
 	 *  - constraints can be on either Objects or PoseChannels, so we only check if the
 	 *    ptr->type is RNA_Object or RNA_PoseBone, which are the RNA wrapping-info for
@@ -586,7 +586,7 @@ static short visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
 	/* check if any data to search using */
 	if (ELEM(NULL, con, identifier) && (has_parent == FALSE))
 		return 0;
-		
+	
 	/* location or rotation identifiers only... */
 	if (identifier == NULL) {
 		printf("%s failed: NULL identifier\n", __func__);
@@ -598,6 +598,9 @@ static short visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
 	else if (strstr(identifier, "rotation")) {
 		searchtype = VISUALKEY_ROT;
 	}
+	else if (strstr(identifier, "scale")) {
+		searchtype = VISUALKEY_SCA;
+	}
 	else {
 		printf("%s failed: identifier - '%s'\n", __func__, identifier);
 		return 0;
@@ -628,7 +631,7 @@ static short visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
 					return 1;
 				case CONSTRAINT_TYPE_KINEMATIC:
 					return 1;
-					
+				
 				/* single-transform constraits  */
 				case CONSTRAINT_TYPE_TRACKTO:
 					if (searchtype == VISUALKEY_ROT) return 1;
@@ -642,15 +645,21 @@ static short visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
 				case CONSTRAINT_TYPE_LOCLIMIT:
 					if (searchtype == VISUALKEY_LOC) return 1;
 					break;
-				case CONSTRAINT_TYPE_ROTLIKE:
-					if (searchtype == VISUALKEY_ROT) return 1;
+				case CONSTRAINT_TYPE_SIZELIMIT:
+					if (searchtype == VISUALKEY_SCA) return 1;
 					break;
 				case CONSTRAINT_TYPE_DISTLIMIT:
 					if (searchtype == VISUALKEY_LOC) return 1;
 					break;
+				case CONSTRAINT_TYPE_ROTLIKE:
+					if (searchtype == VISUALKEY_ROT) return 1;
+					break;
 				case CONSTRAINT_TYPE_LOCLIKE:
 					if (searchtype == VISUALKEY_LOC) return 1;
 					break;
+				case CONSTRAINT_TYPE_SIZELIKE:
+					if (searchtype == VISUALKEY_SCA) return 1;
+					break;
 				case CONSTRAINT_TYPE_LOCKTRACK:
 					if (searchtype == VISUALKEY_ROT) return 1;
 					break;
@@ -675,45 +684,26 @@ static short visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
 static float visualkey_get_value(PointerRNA *ptr, PropertyRNA *prop, int array_index)
 {
 	const char *identifier = RNA_property_identifier(prop);
+	float tmat[4][4];
+	int rotmode;
 	
 	/* handle for Objects or PoseChannels only 
+	 *  - only Location, Rotation or Scale keyframes are supported curently
 	 *  - constraints can be on either Objects or PoseChannels, so we only check if the
-	 *	  ptr->type is RNA_Object or RNA_PoseBone, which are the RNA wrapping-info for
+	 *    ptr->type is RNA_Object or RNA_PoseBone, which are the RNA wrapping-info for
 	 *        those structs, allowing us to identify the owner of the data
-	 *	- assume that array_index will be sane
+	 *  - assume that array_index will be sane
 	 */
 	if (ptr->type == &RNA_Object) {
 		Object *ob = (Object *)ptr->data;
-		
-		/* only Location or Rotation keyframes are supported now */
+
+		/* Loc code is specific... */
 		if (strstr(identifier, "location")) {
 			return ob->obmat[3][array_index];
 		}
-		else if (strstr(identifier, "rotation_euler")) {
-			float eul[3];
-			
-			mat4_to_eulO(eul, ob->rotmode, ob->obmat);
-			return eul[array_index];
-		}
-		else if (strstr(identifier, "rotation_quaternion")) {
-			float trimat[3][3], quat[4];
-			
-			copy_m3_m4(trimat, ob->obmat);
-			mat3_to_quat_is_ok(quat, trimat);
-			
-			return quat[array_index];
-		}
-		else if (strstr(identifier, "rotation_axis_angle")) {
-			float axis[3], angle;
-			
-			mat4_to_axis_angle(axis, &angle, ob->obmat);
-			
-			/* w = 0, x,y,z = 1,2,3 */
-			if (array_index == 0)
-				return angle;
-			else
-				return axis[array_index - 1];
-		}
+
+		copy_m4_m4(tmat, ob->obmat);
+		rotmode = ob->rotmode;
 	}
 	else if (ptr->type == &RNA_PoseBone) {
 		Object *ob = (Object *)ptr->id.data; /* we assume that this is always set, and is an object */
@@ -727,41 +717,52 @@ static float visualkey_get_value(PointerRNA *ptr, PropertyRNA *prop, int array_i
 		 */
 		copy_m4_m4(tmat, pchan->pose_mat);
 		constraint_mat_convertspace(ob, pchan, tmat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
+		rotmode = pchan->rotmode;
 		
-		/* Loc, Rot/Quat keyframes are supported... */
+		/* Loc code is specific... */
 		if (strstr(identifier, "location")) {
 			/* only use for non-connected bones */
-			if ((pchan->bone->parent) && !(pchan->bone->flag & BONE_CONNECTED))
+			if ((pchan->bone->parent == NULL) || !(pchan->bone->flag & BONE_CONNECTED))
 				return tmat[3][array_index];
-			else if (pchan->bone->parent == NULL)
-				return tmat[3][array_index];
-		}
-		else if (strstr(identifier, "rotation_euler")) {
-			float eul[3];
-			
-			mat4_to_eulO(eul, pchan->rotmode, tmat);
-			return eul[array_index];
-		}
-		else if (strstr(identifier, "rotation_quaternion")) {
-			float trimat[3][3], quat[4];
-			
-			copy_m3_m4(trimat, tmat);
-			mat3_to_quat_is_ok(quat, trimat);
-			
-			return quat[array_index];
-		}
-		else if (strstr(identifier, "rotation_axis_angle")) {
-			float axis[3], angle;
-			
-			mat4_to_axis_angle(axis, &angle, tmat);
-			
-			/* w = 0, x,y,z = 1,2,3 */
-			if (array_index == 0)
-				return angle;
-			else
-				return axis[array_index - 1];
 		}
 	}
+	else {
+		return setting_get_rna_value(ptr, prop, array_index);
+	}
+	
+	/* Rot/Scale code are common! */
+	if (strstr(identifier, "rotation_euler")) {
+		float eul[3];
+		
+		mat4_to_eulO(eul, rotmode, tmat);
+		return eul[array_index];
+	}
+	else if (strstr(identifier, "rotation_quaternion")) {
+		float mat3[3][3], quat[4];
+		
+		copy_m3_m4(mat3, tmat);
+		mat3_to_quat_is_ok(quat, mat3);
+		
+		return quat[array_index];
+	}
+	else if (strstr(identifier, "rotation_axis_angle")) {
+		float axis[3], angle;
+		
+		mat4_to_axis_angle(axis, &angle, tmat);
+		
+		/* w = 0, x,y,z = 1,2,3 */
+		if (array_index == 0)
+			return angle;
+		else
+			return axis[array_index - 1];
+	}
+	else if (strstr(identifier, "scale")) {
+		float scale[3];
+		
+		mat4_to_size(scale, tmat);
+		
+		return scale[array_index];
+	}
 	
 	/* as the function hasn't returned yet, read value from system in the default way */
 	return setting_get_rna_value(ptr, prop, array_index);
-- 
cgit v1.2.3


From ba14beb000fef2c5911b4e17c0bf260de1cf251d Mon Sep 17 00:00:00 2001
From: Bastien Montagne 
Date: Sun, 23 Dec 2012 11:31:15 +0000
Subject: Code cleanup: add usual 'BKE_' prefix to 'public' constraint
 functions from blenkernel...

---
 source/blender/blenkernel/BKE_constraint.h         |  48 +++++-----
 source/blender/blenkernel/intern/action.c          |   6 +-
 source/blender/blenkernel/intern/armature.c        |  17 ++--
 source/blender/blenkernel/intern/constraint.c      | 106 ++++++++++-----------
 source/blender/blenkernel/intern/depsgraph.c       |  10 +-
 source/blender/blenkernel/intern/dynamicpaint.c    |   2 +-
 source/blender/blenkernel/intern/fcurve.c          |   8 +-
 source/blender/blenkernel/intern/movieclip.c       |   2 +-
 source/blender/blenkernel/intern/object.c          |  26 ++---
 source/blender/blenloader/intern/readfile.c        |   6 +-
 .../blender/blenloader/intern/versioning_legacy.c  |   2 +-
 source/blender/blenloader/intern/writefile.c       |   2 +-
 source/blender/editors/animation/keyframing.c      |   2 +-
 source/blender/editors/armature/editarmature.c     |  14 +--
 .../editors/armature/editarmature_retarget.c       |   4 +-
 source/blender/editors/armature/poseobject.c       |   6 +-
 .../editors/interface/interface_templates.c        |   6 +-
 source/blender/editors/object/object_constraint.c  |  28 +++---
 source/blender/editors/object/object_edit.c        |   2 +-
 source/blender/editors/object/object_relations.c   |  12 +--
 source/blender/editors/space_clip/tracking_ops.c   |   4 +-
 source/blender/editors/space_view3d/drawobject.c   |   6 +-
 source/blender/editors/transform/transform.c       |  10 +-
 .../editors/transform/transform_conversions.c      |   2 +-
 source/blender/ikplugin/intern/iksolver_plugin.c   |   4 +-
 source/blender/ikplugin/intern/itasc_plugin.cpp    |   4 +-
 source/blender/makesrna/intern/rna_constraint.c    |   4 +-
 source/blender/makesrna/intern/rna_object.c        |  10 +-
 source/blender/makesrna/intern/rna_pose.c          |  10 +-
 source/gameengine/Converter/BL_ArmatureObject.cpp  |   5 +-
 30 files changed, 185 insertions(+), 183 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h
index 79e75127763..c79dc62bb61 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 *constraint_get_typeinfo(struct bConstraint *con);
-bConstraintTypeInfo *get_constraint_typeinfo(int type);
+bConstraintTypeInfo *BKE_constraint_get_typeinfo(struct bConstraint *con);
+bConstraintTypeInfo *BKE_get_constraint_typeinfo(int type);
 
 /* ---------------------------------------------------------------------------- */
 /* Useful macros for testing various common flag combinations */
@@ -120,38 +120,38 @@ bConstraintTypeInfo *get_constraint_typeinfo(int type);
 /* ---------------------------------------------------------------------------- */
 
 /* Constraint function prototypes */
-void unique_constraint_name(struct bConstraint *con, struct ListBase *list);
+void BKE_unique_constraint_name(struct bConstraint *con, struct ListBase *list);
 
-void free_constraints(struct ListBase *list);
-void copy_constraints(struct ListBase *dst, const struct ListBase *src, int do_extern);
-void relink_constraints(struct ListBase *list);
-void id_loop_constraints(struct ListBase *list, ConstraintIDFunc func, void *userdata);
-void free_constraint_data(struct bConstraint *con);
+void BKE_free_constraints(struct ListBase *list);
+void BKE_copy_constraints(struct ListBase *dst, const struct ListBase *src, int do_extern);
+void BKE_relink_constraints(struct ListBase *list);
+void BKE_id_loop_constraints(struct ListBase *list, ConstraintIDFunc func, void *userdata);
+void BKE_free_constraint_data(struct bConstraint *con);
 
 /* Constraint API function prototypes */
-struct bConstraint *constraints_get_active(struct ListBase *list);
-void constraints_set_active(ListBase *list, struct bConstraint *con);
-struct bConstraint *constraints_findByName(struct ListBase *list, const char *name);
-	
-struct bConstraint *add_ob_constraint(struct Object *ob, const char *name, short type);
-struct bConstraint *add_pose_constraint(struct Object *ob, struct bPoseChannel *pchan, const char *name, short type);
+struct bConstraint *BKE_constraints_get_active(struct ListBase *list);
+void BKE_constraints_set_active(ListBase *list, struct bConstraint *con);
+struct bConstraint *BKE_constraints_findByName(struct ListBase *list, const char *name);
+
+struct bConstraint *BKE_add_ob_constraint(struct Object *ob, const char *name, short type);
+struct bConstraint *BKE_add_pose_constraint(struct Object *ob, struct bPoseChannel *pchan, const char *name, short type);
 
-int remove_constraint(ListBase *list, struct bConstraint *con);
-void remove_constraints_type(ListBase *list, short type, short last_only);
+int BKE_remove_constraint(ListBase *list, struct bConstraint *con);
+void BKE_remove_constraints_type(ListBase *list, short type, short last_only);
 
 /* Constraints + Proxies function prototypes */
-void extract_proxylocal_constraints(struct ListBase *dst, struct ListBase *src);
-short proxylocked_constraints_owner(struct Object *ob, struct bPoseChannel *pchan);
+void BKE_extract_proxylocal_constraints(struct ListBase *dst, struct ListBase *src);
+short BKE_proxylocked_constraints_owner(struct Object *ob, struct bPoseChannel *pchan);
 
 /* Constraint Evaluation function prototypes */
-struct bConstraintOb *constraints_make_evalob(struct Scene *scene, struct Object *ob, void *subdata, short datatype);
-void constraints_clear_evalob(struct bConstraintOb *cob);
+struct bConstraintOb *BKE_constraints_make_evalob(struct Scene *scene, struct Object *ob, void *subdata, short datatype);
+void BKE_constraints_clear_evalob(struct bConstraintOb *cob);
 
-void constraint_mat_convertspace(struct Object *ob, struct bPoseChannel *pchan, float mat[4][4], short from, short to);
+void BKE_constraint_mat_convertspace(struct Object *ob, struct bPoseChannel *pchan, float mat[4][4], short from, short to);
 
-void get_constraint_target_matrix(struct Scene *scene, struct bConstraint *con, int n, short ownertype, void *ownerdata, float mat[4][4], float ctime);
-void get_constraint_targets_for_solving(struct bConstraint *con, struct bConstraintOb *ob, struct ListBase *targets, float ctime);
-void solve_constraints(struct ListBase *conlist, struct bConstraintOb *cob, float ctime);
+void BKE_get_constraint_target_matrix(struct Scene *scene, struct bConstraint *con, int n, short ownertype, void *ownerdata, float mat[4][4], float ctime);
+void BKE_get_constraint_targets_for_solving(struct bConstraint *con, struct bConstraintOb *ob, struct ListBase *targets, float ctime);
+void BKE_solve_constraints(struct ListBase *conlist, struct bConstraintOb *cob, float ctime);
 
 #ifdef __cplusplus
 }
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 83d1538ecbe..63e12dfb99d 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -543,7 +543,7 @@ void BKE_pose_copy_data(bPose **dst, bPose *src, int copycon)
 	for (pchan = outPose->chanbase.first; pchan; pchan = pchan->next) {
 		/* TODO: rename this argument... */
 		if (copycon) {
-			copy_constraints(&listb, &pchan->constraints, TRUE);  // copy_constraints NULLs listb
+			BKE_copy_constraints(&listb, &pchan->constraints, TRUE);  // BKE_copy_constraints NULLs listb
 			pchan->constraints = listb;
 			pchan->mpath = NULL; /* motion paths should not get copied yet... */
 		}
@@ -621,7 +621,7 @@ void BKE_pose_channel_free(bPoseChannel *pchan)
 		pchan->mpath = NULL;
 	}
 
-	free_constraints(&pchan->constraints);
+	BKE_free_constraints(&pchan->constraints);
 	
 	if (pchan->prop) {
 		IDP_FreeProperty(pchan->prop);
@@ -711,7 +711,7 @@ void BKE_pose_channel_copy_data(bPoseChannel *pchan, const bPoseChannel *pchan_f
 	pchan->iklinweight = pchan_from->iklinweight;
 
 	/* constraints */
-	copy_constraints(&pchan->constraints, &pchan_from->constraints, TRUE);
+	BKE_copy_constraints(&pchan->constraints, &pchan_from->constraints, TRUE);
 
 	/* id-properties */
 	if (pchan->prop) {
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 9155d67dc36..ad14dee168a 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -1620,15 +1620,16 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected
 			 *     2. copy proxy-pchan's constraints on-to new
 			 *     3. add extracted local constraints back on top
 			 *
-			 * Note for copy_constraints: when copying constraints, disable 'do_extern' otherwise
-			 *                            we get the libs direct linked in this blend. */
-			extract_proxylocal_constraints(&proxylocal_constraints, &pchan->constraints);
-			copy_constraints(&pchanw.constraints, &pchanp->constraints, FALSE);
+			 * Note for BKE_copy_constraints: when copying constraints, disable 'do_extern' otherwise
+			 *                                we get the libs direct linked in this blend.
+			 */
+			BKE_extract_proxylocal_constraints(&proxylocal_constraints, &pchan->constraints);
+			BKE_copy_constraints(&pchanw.constraints, &pchanp->constraints, FALSE);
 			BLI_movelisttolist(&pchanw.constraints, &proxylocal_constraints);
 			
 			/* constraints - set target ob pointer to own object */
 			for (con = pchanw.constraints.first; con; con = con->next) {
-				bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+				bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 				ListBase targets = {NULL, NULL};
 				bConstraintTarget *ct;
 				
@@ -2426,15 +2427,15 @@ void BKE_pose_where_is_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float
 			/* prepare PoseChannel for Constraint solving
 			 * - makes a copy of matrix, and creates temporary struct to use
 			 */
-			cob = constraints_make_evalob(scene, ob, pchan, CONSTRAINT_OBTYPE_BONE);
+			cob = BKE_constraints_make_evalob(scene, ob, pchan, CONSTRAINT_OBTYPE_BONE);
 
 			/* Solve PoseChannel's Constraints */
-			solve_constraints(&pchan->constraints, cob, ctime); /* ctime doesnt alter objects */
+			BKE_solve_constraints(&pchan->constraints, cob, ctime); /* ctime doesnt alter objects */
 
 			/* cleanup after Constraint Solving
 			 * - applies matrix back to pchan, and frees temporary struct used
 			 */
-			constraints_clear_evalob(cob);
+			BKE_constraints_clear_evalob(cob);
 
 			/* prevent constraints breaking a chain */
 			if (pchan->bone->flag & BONE_CONNECTED) {
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index c3aab22fe5a..4874a3a019d 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -96,7 +96,7 @@
 /* -------------- Naming -------------- */
 
 /* Find the first available, non-duplicate name for a given constraint */
-void unique_constraint_name(bConstraint *con, ListBase *list)
+void BKE_unique_constraint_name(bConstraint *con, ListBase *list)
 {
 	BLI_uniquename(list, con, "Const", '.', offsetof(bConstraint, name), sizeof(con->name));
 }
@@ -105,7 +105,7 @@ void unique_constraint_name(bConstraint *con, ListBase *list)
 
 /* package an object/bone for use in constraint evaluation */
 /* This function MEM_calloc's a bConstraintOb struct, that will need to be freed after evaluation */
-bConstraintOb *constraints_make_evalob(Scene *scene, Object *ob, void *subdata, short datatype)
+bConstraintOb *BKE_constraints_make_evalob(Scene *scene, Object *ob, void *subdata, short datatype)
 {
 	bConstraintOb *cob;
 	
@@ -169,7 +169,7 @@ bConstraintOb *constraints_make_evalob(Scene *scene, Object *ob, void *subdata,
 }
 
 /* cleanup after constraint evaluation */
-void constraints_clear_evalob(bConstraintOb *cob)
+void BKE_constraints_clear_evalob(bConstraintOb *cob)
 {
 	float delta[4][4], imat[4][4];
 	
@@ -219,7 +219,7 @@ void constraints_clear_evalob(bConstraintOb *cob)
  * of a matrix from one space to another for constraint evaluation.
  * For now, this is only implemented for Objects and PoseChannels.
  */
-void constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[4][4], short from, short to)
+void BKE_constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[4][4], short from, short to)
 {
 	float diff_mat[4][4];
 	float imat[4][4];
@@ -242,7 +242,7 @@ void constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[4][4
 				/* use pose-space as stepping stone for other spaces... */
 				if (ELEM(to, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_PARLOCAL)) {
 					/* call self with slightly different values */
-					constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
+					BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
 				}
 			}
 			break;
@@ -278,7 +278,7 @@ void constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[4][4
 				/* use pose-space as stepping stone for other spaces */
 				if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_PARLOCAL)) {
 					/* call self with slightly different values */
-					constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
+					BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
 				}
 			}
 			break;
@@ -293,7 +293,7 @@ void constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[4][4
 				/* use pose-space as stepping stone for other spaces */
 				if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL)) {
 					/* call self with slightly different values */
-					constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
+					BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
 				}
 			}
 			break;
@@ -499,7 +499,7 @@ static void constraint_target_to_mat4(Object *ob, const char *substring, float m
 	/*	Case OBJECT */
 	if (!strlen(substring)) {
 		copy_m4_m4(mat, ob->obmat);
-		constraint_mat_convertspace(ob, NULL, mat, from, to);
+		BKE_constraint_mat_convertspace(ob, NULL, mat, from, to);
 	}
 	/*  Case VERTEXGROUP */
 	/* Current method just takes the average location of all the points in the
@@ -512,11 +512,11 @@ static void constraint_target_to_mat4(Object *ob, const char *substring, float m
 	 */
 	else if (ob->type == OB_MESH) {
 		contarget_get_mesh_mat(ob, substring, mat);
-		constraint_mat_convertspace(ob, NULL, mat, from, to);
+		BKE_constraint_mat_convertspace(ob, NULL, mat, from, to);
 	}
 	else if (ob->type == OB_LATTICE) {
 		contarget_get_lattice_mat(ob, substring, mat);
-		constraint_mat_convertspace(ob, NULL, mat, from, to);
+		BKE_constraint_mat_convertspace(ob, NULL, mat, from, to);
 	}
 	/*	Case BONE */
 	else {
@@ -549,7 +549,7 @@ static void constraint_target_to_mat4(Object *ob, const char *substring, float m
 			copy_m4_m4(mat, ob->obmat);
 			
 		/* convert matrix space as required */
-		constraint_mat_convertspace(ob, pchan, mat, from, to);
+		BKE_constraint_mat_convertspace(ob, pchan, mat, from, to);
 	}
 }
 
@@ -4211,7 +4211,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 *get_constraint_typeinfo(int type)
+bConstraintTypeInfo *BKE_get_constraint_typeinfo(int type)
 {
 	/* initialize the type-info list? */
 	if (CTI_INIT) {
@@ -4236,11 +4236,11 @@ bConstraintTypeInfo *get_constraint_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.
  */
-bConstraintTypeInfo *constraint_get_typeinfo(bConstraint *con)
+bConstraintTypeInfo *BKE_constraint_get_typeinfo(bConstraint *con)
 {
 	/* only return typeinfo for valid constraints */
 	if (con)
-		return get_constraint_typeinfo(con->type);
+		return BKE_get_constraint_typeinfo(con->type);
 	else
 		return NULL;
 }
@@ -4252,7 +4252,7 @@ bConstraintTypeInfo *constraint_get_typeinfo(bConstraint *con)
  
 /* ---------- Data Management ------- */
 
-/* helper function for free_constraint_data() - unlinks references */
+/* helper function for BKE_free_constraint_data() - unlinks references */
 static void con_unlink_refs_cb(bConstraint *UNUSED(con), ID **idpoin, short isReference, void *UNUSED(userData))
 {
 	if (*idpoin && isReference)
@@ -4263,10 +4263,10 @@ static void con_unlink_refs_cb(bConstraint *UNUSED(con), ID **idpoin, short isRe
  * be sure to run BIK_clear_data() when freeing an IK constraint,
  * unless DAG_scene_sort is called. 
  */
-void free_constraint_data(bConstraint *con)
+void BKE_free_constraint_data(bConstraint *con)
 {
 	if (con->data) {
-		bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+		bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 		
 		if (cti) {
 			/* perform any special freeing constraint may have */
@@ -4284,13 +4284,13 @@ void free_constraint_data(bConstraint *con)
 }
 
 /* Free all constraints from a constraint-stack */
-void free_constraints(ListBase *list)
+void BKE_free_constraints(ListBase *list)
 {
 	bConstraint *con;
 	
 	/* Free constraint data and also any extra data */
 	for (con = list->first; con; con = con->next)
-		free_constraint_data(con);
+		BKE_free_constraint_data(con);
 	
 	/* Free the whole list */
 	BLI_freelistN(list);
@@ -4298,10 +4298,10 @@ void free_constraints(ListBase *list)
 
 
 /* Remove the specified constraint from the given constraint stack */
-int remove_constraint(ListBase *list, bConstraint *con)
+int BKE_remove_constraint(ListBase *list, bConstraint *con)
 {
 	if (con) {
-		free_constraint_data(con);
+		BKE_free_constraint_data(con);
 		BLI_freelinkN(list, con);
 		return 1;
 	}
@@ -4310,7 +4310,7 @@ int remove_constraint(ListBase *list, bConstraint *con)
 }
 
 /* Remove all the constraints of the specified type from the given constraint stack */
-void remove_constraints_type(ListBase *list, short type, short last_only)
+void BKE_remove_constraints_type(ListBase *list, short type, short last_only)
 {
 	bConstraint *con, *conp;
 	
@@ -4322,7 +4322,7 @@ void remove_constraints_type(ListBase *list, short type, short last_only)
 		conp = con->prev;
 		
 		if (con->type == type) {
-			remove_constraint(list, con);
+			BKE_remove_constraint(list, con);
 			if (last_only) 
 				return;
 		}
@@ -4335,7 +4335,7 @@ void remove_constraints_type(ListBase *list, short type, short last_only)
 static bConstraint *add_new_constraint_internal(const char *name, short type)
 {
 	bConstraint *con = MEM_callocN(sizeof(bConstraint), "Constraint");
-	bConstraintTypeInfo *cti = get_constraint_typeinfo(type);
+	bConstraintTypeInfo *cti = BKE_get_constraint_typeinfo(type);
 	const char *newName;
 
 	/* Set up a generic constraint datablock */
@@ -4385,17 +4385,17 @@ static bConstraint *add_new_constraint(Object *ob, bPoseChannel *pchan, const ch
 		 * (otherwise unique-naming code will fail, since it assumes element exists in list)
 		 */
 		BLI_addtail(list, con);
-		unique_constraint_name(con, list);
+		BKE_unique_constraint_name(con, list);
 		
 		/* if the target list is a list on some PoseChannel belonging to a proxy-protected
 		 * Armature layer, we must tag newly added constraints with a flag which allows them
 		 * to persist after proxy syncing has been done
 		 */
-		if (proxylocked_constraints_owner(ob, pchan))
+		if (BKE_proxylocked_constraints_owner(ob, pchan))
 			con->flag |= CONSTRAINT_PROXY_LOCAL;
 		
 		/* make this constraint the active one */
-		constraints_set_active(list, con);
+		BKE_constraints_set_active(list, con);
 	}
 
 	/* set type+owner specific immutable settings */
@@ -4419,7 +4419,7 @@ static bConstraint *add_new_constraint(Object *ob, bPoseChannel *pchan, const ch
 /* ......... */
 
 /* Add new constraint for the given bone */
-bConstraint *add_pose_constraint(Object *ob, bPoseChannel *pchan, const char *name, short type)
+bConstraint *BKE_add_pose_constraint(Object *ob, bPoseChannel *pchan, const char *name, short type)
 {
 	if (pchan == NULL)
 		return NULL;
@@ -4428,14 +4428,14 @@ bConstraint *add_pose_constraint(Object *ob, bPoseChannel *pchan, const char *na
 }
 
 /* Add new constraint for the given object */
-bConstraint *add_ob_constraint(Object *ob, const char *name, short type)
+bConstraint *BKE_add_ob_constraint(Object *ob, const char *name, short type)
 {
 	return add_new_constraint(ob, NULL, name, type);
 }
 
 /* ......... */
 
-/* helper for relink_constraints() - call ID_NEW() on every ID reference the constraint has */
+/* helper for BKE_relink_constraints() - call ID_NEW() on every ID reference the constraint has */
 static void con_relink_id_cb(bConstraint *UNUSED(con), ID **idpoin, short UNUSED(isReference), void *UNUSED(userdata))
 {
 	/* ID_NEW() expects a struct with inline "id" member as first
@@ -4449,20 +4449,20 @@ static void con_relink_id_cb(bConstraint *UNUSED(con), ID **idpoin, short UNUSED
 }
 
 /* Reassign links that constraints have to other data (called during file loading?) */
-void relink_constraints(ListBase *conlist)
+void BKE_relink_constraints(ListBase *conlist)
 {
 	/* just a wrapper around ID-loop for just calling ID_NEW() on all ID refs */
-	id_loop_constraints(conlist, con_relink_id_cb, NULL);
+	BKE_id_loop_constraints(conlist, con_relink_id_cb, NULL);
 }
 
 
 /* Run the given callback on all ID-blocks in list of constraints */
-void id_loop_constraints(ListBase *conlist, ConstraintIDFunc func, void *userdata)
+void BKE_id_loop_constraints(ListBase *conlist, ConstraintIDFunc func, void *userdata)
 {
 	bConstraint *con;
 	
 	for (con = conlist->first; con; con = con->next) {
-		bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+		bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 		
 		if (cti) {
 			if (cti->id_looper)
@@ -4473,14 +4473,14 @@ void id_loop_constraints(ListBase *conlist, ConstraintIDFunc func, void *userdat
 
 /* ......... */
 
-/* helper for copy_constraints(), to be used for making sure that ID's are valid */
+/* helper for BKE_copy_constraints(), to be used for making sure that ID's are valid */
 static void con_extern_cb(bConstraint *UNUSED(con), ID **idpoin, short UNUSED(isReference), void *UNUSED(userData))
 {
 	if (*idpoin && (*idpoin)->lib)
 		id_lib_extern(*idpoin);
 }
 
-/* helper for copy_constraints(), to be used for making sure that usercounts of copied ID's are fixed up */
+/* helper for BKE_copy_constraints(), to be used for making sure that usercounts of copied ID's are fixed up */
 static void con_fix_copied_refs_cb(bConstraint *UNUSED(con), ID **idpoin, short isReference, void *UNUSED(userData))
 {
 	/* increment usercount if this is a reference type */
@@ -4489,7 +4489,7 @@ static void con_fix_copied_refs_cb(bConstraint *UNUSED(con), ID **idpoin, short
 }
 
 /* duplicate all of the constraints in a constraint stack */
-void copy_constraints(ListBase *dst, const ListBase *src, int do_extern)
+void BKE_copy_constraints(ListBase *dst, const ListBase *src, int do_extern)
 {
 	bConstraint *con, *srccon;
 	
@@ -4497,7 +4497,7 @@ void copy_constraints(ListBase *dst, const ListBase *src, int do_extern)
 	BLI_duplicatelist(dst, src);
 	
 	for (con = dst->first, srccon = src->first; con && srccon; srccon = srccon->next, con = con->next) {
-		bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+		bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 		
 		/* make a new copy of the constraint's data */
 		con->data = MEM_dupallocN(con->data);
@@ -4524,13 +4524,13 @@ void copy_constraints(ListBase *dst, const ListBase *src, int do_extern)
 
 /* ......... */
 
-bConstraint *constraints_findByName(ListBase *list, const char *name)
+bConstraint *BKE_constraints_findByName(ListBase *list, const char *name)
 {
 	return BLI_findstring(list, name, offsetof(bConstraint, name));
 }
 
 /* finds the 'active' constraint in a constraint stack */
-bConstraint *constraints_get_active(ListBase *list)
+bConstraint *BKE_constraints_get_active(ListBase *list)
 {
 	bConstraint *con;
 	
@@ -4547,7 +4547,7 @@ bConstraint *constraints_get_active(ListBase *list)
 }
 
 /* Set the given constraint as the active one (clearing all the others) */
-void constraints_set_active(ListBase *list, bConstraint *con)
+void BKE_constraints_set_active(ListBase *list, bConstraint *con)
 {
 	bConstraint *c;
 	
@@ -4564,7 +4564,7 @@ void constraints_set_active(ListBase *list, bConstraint *con)
 /* -------- Constraints and Proxies ------- */
 
 /* Rescue all constraints tagged as being CONSTRAINT_PROXY_LOCAL (i.e. added to bone that's proxy-synced in this file) */
-void extract_proxylocal_constraints(ListBase *dst, ListBase *src)
+void BKE_extract_proxylocal_constraints(ListBase *dst, ListBase *src)
 {
 	bConstraint *con, *next;
 	
@@ -4581,7 +4581,7 @@ void extract_proxylocal_constraints(ListBase *dst, ListBase *src)
 }
 
 /* Returns if the owner of the constraint is proxy-protected */
-short proxylocked_constraints_owner(Object *ob, bPoseChannel *pchan)
+short BKE_proxylocked_constraints_owner(Object *ob, bPoseChannel *pchan)
 {
 	/* Currently, constraints can only be on object or bone level */
 	if (ob && ob->proxy) {
@@ -4610,9 +4610,9 @@ short proxylocked_constraints_owner(Object *ob, bPoseChannel *pchan)
  * None of the actual calculations of the matrices should be done here! Also, this function is
  * not to be used by any new constraints, particularly any that have multiple targets.
  */
-void get_constraint_target_matrix(struct Scene *scene, bConstraint *con, int n, short ownertype, void *ownerdata, float mat[4][4], float ctime)
+void BKE_get_constraint_target_matrix(struct Scene *scene, bConstraint *con, int n, short ownertype, void *ownerdata, float mat[4][4], float ctime)
 {
-	bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+	bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 	ListBase targets = {NULL, NULL};
 	bConstraintOb *cob;
 	bConstraintTarget *ct;
@@ -4679,9 +4679,9 @@ void get_constraint_target_matrix(struct Scene *scene, bConstraint *con, int n,
 }
 
 /* Get the list of targets required for solving a constraint */
-void get_constraint_targets_for_solving(bConstraint *con, bConstraintOb *cob, ListBase *targets, float ctime)
+void BKE_get_constraint_targets_for_solving(bConstraint *con, bConstraintOb *cob, ListBase *targets, float ctime)
 {
-	bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+	bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 	
 	if (cti && cti->get_constraint_targets) {
 		bConstraintTarget *ct;
@@ -4711,10 +4711,10 @@ void get_constraint_targets_for_solving(bConstraint *con, bConstraintOb *cob, Li
 /* This function is called whenever constraints need to be evaluated. Currently, all
  * constraints that can be evaluated are everytime this gets run.
  *
- * constraints_make_evalob and constraints_clear_evalob should be called before and 
+ * BKE_constraints_make_evalob and BKE_constraints_clear_evalob should be called before and 
  * after running this function, to sort out cob
  */
-void solve_constraints(ListBase *conlist, bConstraintOb *cob, float ctime)
+void BKE_solve_constraints(ListBase *conlist, bConstraintOb *cob, float ctime)
 {
 	bConstraint *con;
 	float oldmat[4][4];
@@ -4726,7 +4726,7 @@ void solve_constraints(ListBase *conlist, bConstraintOb *cob, float ctime)
 	
 	/* loop over available constraints, solving and blending them */
 	for (con = conlist->first; con; con = con->next) {
-		bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+		bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 		ListBase targets = {NULL, NULL};
 		
 		/* these we can skip completely (invalid constraints...) */
@@ -4746,10 +4746,10 @@ void solve_constraints(ListBase *conlist, bConstraintOb *cob, float ctime)
 		copy_m4_m4(oldmat, cob->matrix);
 		
 		/* move owner matrix into right space */
-		constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, CONSTRAINT_SPACE_WORLD, con->ownspace);
+		BKE_constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, CONSTRAINT_SPACE_WORLD, con->ownspace);
 		
 		/* prepare targets for constraint solving */
-		get_constraint_targets_for_solving(con, cob, &targets, ctime);
+		BKE_get_constraint_targets_for_solving(con, cob, &targets, ctime);
 		
 		/* Solve the constraint and put result in cob->matrix */
 		cti->evaluate_constraint(con, cob, &targets);
@@ -4764,7 +4764,7 @@ void solve_constraints(ListBase *conlist, bConstraintOb *cob, float ctime)
 		
 		/* move owner back into worldspace for next constraint/other business */
 		if ((con->flag & CONSTRAINT_SPACEONCE) == 0) 
-			constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, con->ownspace, CONSTRAINT_SPACE_WORLD);
+			BKE_constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, con->ownspace, CONSTRAINT_SPACE_WORLD);
 			
 		/* Interpolate the enforcement, to blend result of constraint into final owner transform 
 		 *  - all this happens in worldspace to prevent any weirdness creeping in ([#26014] and [#25725]),
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index 6ba140fcec1..42389564ec0 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -472,7 +472,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
 			
 			for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
 				for (con = pchan->constraints.first; con; con = con->next) {
-					bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+					bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 					ListBase targets = {NULL, NULL};
 					bConstraintTarget *ct;
 					
@@ -754,7 +754,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
 	
 	/* object constraints */
 	for (con = ob->constraints.first; con; con = con->next) {
-		bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+		bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 		ListBase targets = {NULL, NULL};
 		bConstraintTarget *ct;
 		
@@ -2295,7 +2295,7 @@ static void dag_object_time_update_flags(Object *ob)
 	if (ob->constraints.first) {
 		bConstraint *con;
 		for (con = ob->constraints.first; con; con = con->next) {
-			bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+			bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 			ListBase targets = {NULL, NULL};
 			bConstraintTarget *ct;
 			
@@ -2738,7 +2738,7 @@ static void dag_id_flush_update(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 = constraint_get_typeinfo(con);
+					bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 					if (ELEM3(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER,
 					          CONSTRAINT_TYPE_OBJECTSOLVER))
 					{
@@ -3030,7 +3030,7 @@ void DAG_pose_sort(Object *ob)
 			addtoroot = 0;
 		}
 		for (con = pchan->constraints.first; con; con = con->next) {
-			bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+			bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 			ListBase targets = {NULL, NULL};
 			bConstraintTarget *ct;
 			
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 23fae2e9de0..0efbd92641b 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -529,7 +529,7 @@ static int subframe_updateObject(Scene *scene, Object *ob, int flags, float fram
 
 		/* also update constraint targets */
 		for (con = ob->constraints.first; con; con = con->next) {
-			bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+			bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(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 5e01773cab9..1511ac5bb3f 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -1192,7 +1192,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar)
 					
 					/* extract transform just like how the constraints do it! */
 					copy_m4_m4(mat, pchan->pose_mat);
-					constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
+					BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
 					
 					/* ... and from that, we get our transform */
 					copy_v3_v3(tmp_loc, mat[3]);
@@ -1217,7 +1217,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar)
 					
 					/* extract transform just like how the constraints do it! */
 					copy_m4_m4(mat, ob->obmat);
-					constraint_mat_convertspace(ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL);
+					BKE_constraint_mat_convertspace(ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL);
 					
 					/* ... and from that, we get our transform */
 					copy_v3_v3(tmp_loc, mat[3]);
@@ -1288,7 +1288,7 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
 			if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) {
 				/* just like how the constraints do it! */
 				copy_m4_m4(mat, pchan->pose_mat);
-				constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
+				BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
 			}
 			else {
 				/* specially calculate local matrix, since chan_mat is not valid 
@@ -1315,7 +1315,7 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
 			if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) {
 				/* just like how the constraints do it! */
 				copy_m4_m4(mat, ob->obmat);
-				constraint_mat_convertspace(ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL);
+				BKE_constraint_mat_convertspace(ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL);
 			}
 			else {
 				/* transforms to matrix */
diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c
index 4156b5b4367..69e368f0d08 100644
--- a/source/blender/blenkernel/intern/movieclip.c
+++ b/source/blender/blenkernel/intern/movieclip.c
@@ -1325,7 +1325,7 @@ void BKE_movieclip_unlink(Main *bmain, MovieClip *clip)
 		bConstraint *con;
 
 		for (con = ob->constraints.first; con; con = con->next) {
-			bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+			bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 
 			if (cti->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
 				bFollowTrackConstraint *data = (bFollowTrackConstraint *) con->data;
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 9a54e091524..99b163ce45b 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -349,7 +349,7 @@ void BKE_object_free(Object *ob)
 	free_controllers(&ob->controllers);
 	free_actuators(&ob->actuators);
 	
-	free_constraints(&ob->constraints);
+	BKE_free_constraints(&ob->constraints);
 	
 	free_partdeflect(ob->pd);
 
@@ -434,7 +434,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 = constraint_get_typeinfo(con);
+					bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 					ListBase targets = {NULL, NULL};
 					bConstraintTarget *ct;
 					
@@ -465,7 +465,7 @@ void BKE_object_unlink(Object *ob)
 		sca_remove_ob_poin(obt, ob);
 		
 		for (con = obt->constraints.first; con; con = con->next) {
-			bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+			bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 			ListBase targets = {NULL, NULL};
 			bConstraintTarget *ct;
 			
@@ -1129,7 +1129,7 @@ static void copy_object_pose(Object *obn, Object *ob)
 		}
 		
 		for (con = chan->constraints.first; con; con = con->next) {
-			bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+			bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 			ListBase targets = {NULL, NULL};
 			bConstraintTarget *ct;
 			
@@ -1229,7 +1229,7 @@ static Object *object_copy_do(Object *ob, int copy_caches)
 			BKE_pose_rebuild(obn, obn->data);
 	}
 	defgroup_copy_list(&obn->defbase, &ob->defbase);
-	copy_constraints(&obn->constraints, &ob->constraints, TRUE);
+	BKE_copy_constraints(&obn->constraints, &ob->constraints, TRUE);
 
 	obn->mode = 0;
 	obn->sculpt = NULL;
@@ -2113,9 +2113,9 @@ void BKE_object_where_is_calc_time(Scene *scene, Object *ob, float ctime)
 	if (ob->constraints.first && !(ob->transflag & OB_NO_CONSTRAINTS)) {
 		bConstraintOb *cob;
 		
-		cob = constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
-		solve_constraints(&ob->constraints, cob, ctime);
-		constraints_clear_evalob(cob);
+		cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
+		BKE_solve_constraints(&ob->constraints, cob, ctime);
+		BKE_constraints_clear_evalob(cob);
 	}
 	
 	/* set negative scale flag in object */
@@ -2184,9 +2184,9 @@ void BKE_object_where_is_calc_simul(Scene *scene, Object *ob)
 	if (ob->constraints.first) {
 		bConstraintOb *cob;
 		
-		cob = constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
-		solve_constraints(&ob->constraints, cob, (float)scene->r.cfra);
-		constraints_clear_evalob(cob);
+		cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
+		BKE_solve_constraints(&ob->constraints, cob, (float)scene->r.cfra);
+		BKE_constraints_clear_evalob(cob);
 	}
 }
 
@@ -3134,11 +3134,11 @@ void BKE_object_relink(Object *ob)
 	if (ob->id.lib)
 		return;
 
-	relink_constraints(&ob->constraints);
+	BKE_relink_constraints(&ob->constraints);
 	if (ob->pose) {
 		bPoseChannel *chan;
 		for (chan = ob->pose->chanbase.first; chan; chan = chan->next) {
-			relink_constraints(&chan->constraints);
+			BKE_relink_constraints(&chan->constraints);
 		}
 	}
 	modifiers_foreachIDLink(ob, copy_object__forwardModifierLinks, NULL);
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 38d41dbc96a..81101e01516 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -2535,7 +2535,7 @@ static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist)
 	cld.fd = fd;
 	cld.id = id;
 	
-	id_loop_constraints(conlist, lib_link_constraint_cb, &cld);
+	BKE_id_loop_constraints(conlist, lib_link_constraint_cb, &cld);
 }
 
 static void direct_link_constraints(FileData *fd, ListBase *lb)
@@ -7504,7 +7504,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
 			for (ob = main->object.first; ob; ob = ob->id.next) {
 				bConstraint *con;
 				for (con = ob->constraints.first; con; con = con->next) {
-					bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+					bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 					
 					if (!cti)
 						continue;
@@ -9186,7 +9186,7 @@ static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb)
 	ced.fd = fd;
 	ced.mainvar = mainvar;
 	
-	id_loop_constraints(lb, expand_constraint_cb, &ced);
+	BKE_id_loop_constraints(lb, expand_constraint_cb, &ced);
 	
 	/* deprecated manual expansion stuff */
 	for (curcon = lb->first; curcon; curcon = curcon->next) {
diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c
index 8a56e3c2ab8..2e783ac956e 100644
--- a/source/blender/blenloader/intern/versioning_legacy.c
+++ b/source/blender/blenloader/intern/versioning_legacy.c
@@ -545,7 +545,7 @@ void blo_do_version_old_trackto_to_constraints(Object *ob)
 {
 	/* create new trackto constraint from the relationship */
 	if (ob->track) {
-		bConstraint *con = add_ob_constraint(ob, "AutoTrack", CONSTRAINT_TYPE_TRACKTO);
+		bConstraint *con = BKE_add_ob_constraint(ob, "AutoTrack", CONSTRAINT_TYPE_TRACKTO);
 		bTrackToConstraint *data = con->data;
 
 		/* copy tracking settings from the object */
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index f82883addb1..7ce10d1815f 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -1228,7 +1228,7 @@ static void write_constraints(WriteData *wd, ListBase *conlist)
 	bConstraint *con;
 
 	for (con=conlist->first; con; con=con->next) {
-		bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+		bConstraintTypeInfo *cti= BKE_constraint_get_typeinfo(con);
 		
 		/* Write the specific data */
 		if (cti && con->data) {
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index aee53fed3c8..9add193a514 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -716,7 +716,7 @@ static float visualkey_get_value(PointerRNA *ptr, PropertyRNA *prop, int array_i
 		 * will be what owns the pose-channel that is getting this anyway.
 		 */
 		copy_m4_m4(tmat, pchan->pose_mat);
-		constraint_mat_convertspace(ob, pchan, tmat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
+		BKE_constraint_mat_convertspace(ob, pchan, tmat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
 		rotmode = pchan->rotmode;
 		
 		/* Loc code is specific... */
diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c
index ae405c0e113..37314373e98 100644
--- a/source/blender/editors/armature/editarmature.c
+++ b/source/blender/editors/armature/editarmature.c
@@ -812,7 +812,7 @@ static void joined_armature_fix_links(Object *tarArm, Object *srcArm, bPoseChann
 			pose = ob->pose;
 			for (pchant = pose->chanbase.first; pchant; pchant = pchant->next) {
 				for (con = pchant->constraints.first; con; con = con->next) {
-					bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+					bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 					ListBase targets = {NULL, NULL};
 					bConstraintTarget *ct;
 					
@@ -859,7 +859,7 @@ static void joined_armature_fix_links(Object *tarArm, Object *srcArm, bPoseChann
 		/* fix object-level constraints */
 		if (ob != srcArm) {
 			for (con = ob->constraints.first; con; con = con->next) {
-				bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+				bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 				ListBase targets = {NULL, NULL};
 				bConstraintTarget *ct;
 				
@@ -1032,7 +1032,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 = constraint_get_typeinfo(con);
+					bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 					ListBase targets = {NULL, NULL};
 					bConstraintTarget *ct;
 					
@@ -1070,7 +1070,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 = constraint_get_typeinfo(con);
+				bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 				ListBase targets = {NULL, NULL};
 				bConstraintTarget *ct;
 				
@@ -1712,7 +1712,7 @@ static int armature_delete_selected_exec(bContext *C, wmOperator *UNUSED(op))
 			}
 			else {
 				for (con = pchan->constraints.first; con; con = con->next) {
-					bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+					bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 					ListBase targets = {NULL, NULL};
 					bConstraintTarget *ct;
 					
@@ -2523,7 +2523,7 @@ void updateDuplicateSubtargetObjects(EditBone *dupBone, ListBase *editbones, Obj
 				/* does this constraint have a subtarget in
 				 * this armature?
 				 */
-				bConstraintTypeInfo *cti = constraint_get_typeinfo(curcon);
+				bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(curcon);
 				ListBase targets = {NULL, NULL};
 				bConstraintTarget *ct;
 				
@@ -5533,7 +5533,7 @@ static void constraint_bone_name_fix(Object *ob, ListBase *conlist, char *oldnam
 	bConstraintTarget *ct;
 	
 	for (curcon = conlist->first; curcon; curcon = curcon->next) {
-		bConstraintTypeInfo *cti = constraint_get_typeinfo(curcon);
+		bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(curcon);
 		ListBase targets = {NULL, NULL};
 		
 		if (cti && cti->get_constraint_targets) {
diff --git a/source/blender/editors/armature/editarmature_retarget.c b/source/blender/editors/armature/editarmature_retarget.c
index be3e037e330..3e34a4c6808 100644
--- a/source/blender/editors/armature/editarmature_retarget.c
+++ b/source/blender/editors/armature/editarmature_retarget.c
@@ -725,7 +725,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 = constraint_get_typeinfo(con);
+				bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 				ListBase targets = {NULL, NULL};
 				bConstraintTarget *ct;
 				
@@ -850,7 +850,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 = constraint_get_typeinfo(con);
+						bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 						ListBase targets = {NULL, NULL};
 						bConstraintTarget *ct;
 						
diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c
index 576e5983d16..49d4b670cde 100644
--- a/source/blender/editors/armature/poseobject.c
+++ b/source/blender/editors/armature/poseobject.c
@@ -417,7 +417,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 = constraint_get_typeinfo(con);
+				bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 				ListBase targets = {NULL, NULL};
 				bConstraintTarget *ct;
 				
@@ -925,7 +925,7 @@ static void pose_copy_menu(Scene *scene)
 						/* copy constraints to tmpbase and apply 'local' tags before 
 						 * appending to list of constraints for this channel
 						 */
-						copy_constraints(&tmp_constraints, &pchanact->constraints, TRUE);
+						BKE_copy_constraints(&tmp_constraints, &pchanact->constraints, TRUE);
 						if ((ob->proxy) && (pchan->bone->layer & arm->layer_protected)) {
 							bConstraint *con;
 							
@@ -1034,7 +1034,7 @@ static void pose_copy_menu(Scene *scene)
 				/* copy constraints to tmpbase and apply 'local' tags before 
 				 * appending to list of constraints for this channel
 				 */
-				copy_constraints(&tmp_constraints, &const_copy, TRUE);
+				BKE_copy_constraints(&tmp_constraints, &const_copy, TRUE);
 				if ((ob->proxy) && (pchan->bone->layer & arm->layer_protected)) {
 					/* add proxy-local tags */
 					for (con = tmp_constraints.first; con; con = con->next)
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 6983723e9b5..4e0776ee539 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -1080,7 +1080,7 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
 	// int rb_col; // UNUSED
 
 	/* get constraint typeinfo */
-	cti = constraint_get_typeinfo(con);
+	cti = BKE_constraint_get_typeinfo(con);
 	if (cti == NULL) {
 		/* exception for 'Null' constraint - it doesn't have constraint typeinfo! */
 		BLI_strncpy(typestr, (con->type == CONSTRAINT_TYPE_NULL) ? "Null" : "Unknown", sizeof(typestr));
@@ -1089,7 +1089,7 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
 		BLI_strncpy(typestr, cti->name, sizeof(typestr));
 		
 	/* determine whether constraint is proxy protected or not */
-	if (proxylocked_constraints_owner(ob, pchan))
+	if (BKE_proxylocked_constraints_owner(ob, pchan))
 		proxy_protected = (con->flag & CONSTRAINT_PROXY_LOCAL) == 0;
 	else
 		proxy_protected = 0;
@@ -1151,7 +1151,7 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
 		 *
 		 *  Up/Down buttons should only be shown (or not grayed - todo) if they serve some purpose.
 		 */
-		if (proxylocked_constraints_owner(ob, pchan)) {
+		if (BKE_proxylocked_constraints_owner(ob, pchan)) {
 			if (con->prev) {
 				prev_proxylock = (con->prev->flag & CONSTRAINT_PROXY_LOCAL) ? 0 : 1;
 			}
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index f78e1203bc4..6cb7cd5e326 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -141,7 +141,7 @@ ListBase *get_constraint_lb(Object *ob, bConstraint *con, bPoseChannel **pchan_r
 /* single constraint */
 bConstraint *get_active_constraint(Object *ob)
 {
-	return constraints_get_active(get_active_constraints(ob));
+	return BKE_constraints_get_active(get_active_constraints(ob));
 }
 
 /* -------------- Constraint Management (Add New, Remove, Rename) -------------------- */
@@ -225,7 +225,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 = constraint_get_typeinfo(con);
+	bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 	ListBase targets = {NULL, NULL};
 	bConstraintTarget *ct;
 	int num_targets, i;
@@ -297,7 +297,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 = constraint_get_typeinfo(curcon);
+			bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(curcon);
 			ListBase targets = {NULL, NULL};
 			bConstraintTarget *ct;
 			
@@ -610,7 +610,7 @@ static bConstraint *edit_constraint_property_get(wmOperator *op, Object *ob, int
 		list = get_active_constraints(ob);
 	}
 	
-	con = constraints_findByName(list, constraint_name);
+	con = BKE_constraints_findByName(list, constraint_name);
 	//if (G.debug & G_DEBUG)
 	//printf("constraint found = %p, %s\n", (void *)con, (con)?con->name:"");
 
@@ -1123,7 +1123,7 @@ void ED_object_constraint_set_active(Object *ob, bConstraint *con)
 	if ((lb && con) && (con->flag & CONSTRAINT_ACTIVE))
 		return;
 	
-	constraints_set_active(lb, con);
+	BKE_constraints_set_active(lb, con);
 }
 
 void ED_object_constraint_update(Object *ob)
@@ -1162,9 +1162,9 @@ static int constraint_delete_exec(bContext *C, wmOperator *UNUSED(op))
 	const short is_ik = ELEM(con->type, CONSTRAINT_TYPE_KINEMATIC, CONSTRAINT_TYPE_SPLINEIK);
 
 	/* free the constraint */
-	if (remove_constraint(lb, con)) {
+	if (BKE_remove_constraint(lb, con)) {
 		/* there's no active constraint now, so make sure this is the case */
-		constraints_set_active(lb, NULL);
+		BKE_constraints_set_active(lb, NULL);
 		
 		ED_object_constraint_update(ob); /* needed to set the flags on posebones correctly */
 		
@@ -1308,7 +1308,7 @@ static int pose_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op))
 	/* free constraints for all selected bones */
 	CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
 	{
-		free_constraints(&pchan->constraints);
+		BKE_free_constraints(&pchan->constraints);
 		pchan->constflag &= ~(PCHAN_HAS_IK | PCHAN_HAS_SPLINEIK | PCHAN_HAS_CONST);
 	}
 	CTX_DATA_END;
@@ -1346,7 +1346,7 @@ static int object_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op))
 	/* do freeing */
 	CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
 	{
-		free_constraints(&ob->constraints);
+		BKE_free_constraints(&ob->constraints);
 		DAG_id_tag_update(&ob->id, OB_RECALC_OB);
 	}
 	CTX_DATA_END;
@@ -1391,7 +1391,7 @@ static int pose_constraint_copy_exec(bContext *C, wmOperator *op)
 	{
 		/* if we're not handling the object we're copying from, copy all constraints over */
 		if (pchan != chan) {
-			copy_constraints(&chan->constraints, &pchan->constraints, TRUE);
+			BKE_copy_constraints(&chan->constraints, &pchan->constraints, TRUE);
 			/* update flags (need to add here, not just copy) */
 			chan->constflag |= pchan->constflag;
 		}
@@ -1432,7 +1432,7 @@ static int object_constraint_copy_exec(bContext *C, wmOperator *UNUSED(op))
 	{
 		/* if we're not handling the object we're copying from, copy all constraints over */
 		if (obact != ob) {
-			copy_constraints(&ob->constraints, &obact->constraints, TRUE);
+			BKE_copy_constraints(&ob->constraints, &obact->constraints, TRUE);
 			DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 		}
 	}
@@ -1642,9 +1642,9 @@ static int constraint_add_exec(bContext *C, wmOperator *op, Object *ob, ListBase
 	
 	/* create a new constraint of the type requried, and add it to the active/given constraints list */
 	if (pchan)
-		con = add_pose_constraint(ob, pchan, NULL, type);
+		con = BKE_add_pose_constraint(ob, pchan, NULL, type);
 	else
-		con = add_ob_constraint(ob, NULL, type);
+		con = BKE_add_ob_constraint(ob, NULL, type);
 	
 	/* get the first selected object/bone, and make that the target
 	 *	- apart from the buttons-window add buttons, we shouldn't add in this way
@@ -1940,7 +1940,7 @@ static int pose_ik_clear_exec(bContext *C, wmOperator *UNUSED(op))
 		for (con = pchan->constraints.first; con; con = next) {
 			next = con->next;
 			if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
-				remove_constraint(&pchan->constraints, con);
+				BKE_remove_constraint(&pchan->constraints, con);
 			}
 		}
 		pchan->constflag &= ~(PCHAN_HAS_IK | PCHAN_HAS_TARGET);
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index c9492d8f683..fcc3b5d012e 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -954,7 +954,7 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
 				}
 				else if (event == 22) {
 					/* Copy the constraint channels over */
-					copy_constraints(&base->object->constraints, &ob->constraints, TRUE);
+					BKE_copy_constraints(&base->object->constraints, &ob->constraints, TRUE);
 					
 					do_scene_sort = TRUE;
 				}
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 0988a196fb1..fa44d3d7fb4 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -716,12 +716,12 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
 				bFollowPathConstraint *data;
 				float cmat[4][4], vec[3];
 				
-				con = add_ob_constraint(ob, "AutoPath", CONSTRAINT_TYPE_FOLLOWPATH);
+				con = BKE_add_ob_constraint(ob, "AutoPath", CONSTRAINT_TYPE_FOLLOWPATH);
 				
 				data = con->data;
 				data->tar = par;
 				
-				get_constraint_target_matrix(scene, con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, scene->r.cfra);
+				BKE_get_constraint_target_matrix(scene, con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, scene->r.cfra);
 				sub_v3_v3v3(vec, ob->obmat[3], cmat[3]);
 				
 				ob->loc[0] = vec[0];
@@ -1051,7 +1051,7 @@ static int object_track_clear_exec(bContext *C, wmOperator *op)
 		for (con = ob->constraints.last; con; con = pcon) {
 			pcon = con->prev;
 			if (ELEM3(con->type, CONSTRAINT_TYPE_TRACKTO, CONSTRAINT_TYPE_LOCKTRACK, CONSTRAINT_TYPE_DAMPTRACK))
-				remove_constraint(&ob->constraints, con);
+				BKE_remove_constraint(&ob->constraints, con);
 		}
 		
 		if (type == 1)
@@ -1109,7 +1109,7 @@ static int track_set_exec(bContext *C, wmOperator *op)
 		CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
 		{
 			if (ob != obact) {
-				con = add_ob_constraint(ob, "AutoTrack", CONSTRAINT_TYPE_DAMPTRACK);
+				con = BKE_add_ob_constraint(ob, "AutoTrack", CONSTRAINT_TYPE_DAMPTRACK);
 
 				data = con->data;
 				data->tar = obact;
@@ -1129,7 +1129,7 @@ static int track_set_exec(bContext *C, wmOperator *op)
 		CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
 		{
 			if (ob != obact) {
-				con = add_ob_constraint(ob, "AutoTrack", CONSTRAINT_TYPE_TRACKTO);
+				con = BKE_add_ob_constraint(ob, "AutoTrack", CONSTRAINT_TYPE_TRACKTO);
 
 				data = con->data;
 				data->tar = obact;
@@ -1151,7 +1151,7 @@ static int track_set_exec(bContext *C, wmOperator *op)
 		CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
 		{
 			if (ob != obact) {
-				con = add_ob_constraint(ob, "AutoTrack", CONSTRAINT_TYPE_LOCKTRACK);
+				con = BKE_add_ob_constraint(ob, "AutoTrack", CONSTRAINT_TYPE_LOCKTRACK);
 
 				data = con->data;
 				data->tar = obact;
diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c
index 77662d8ac13..56a890c714a 100644
--- a/source/blender/editors/space_clip/tracking_ops.c
+++ b/source/blender/editors/space_clip/tracking_ops.c
@@ -1801,7 +1801,7 @@ static void object_solver_inverted_matrix(Scene *scene, Object *ob, float invmat
 	int found = FALSE;
 
 	for (con = ob->constraints.first; con; con = con->next) {
-		bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+		bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 
 		if (!cti)
 			continue;
@@ -1832,7 +1832,7 @@ static Object *object_solver_camera(Scene *scene, Object *ob)
 	bConstraint *con;
 
 	for (con = ob->constraints.first; con; con = con->next) {
-		bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+		bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 
 		if (!cti)
 			continue;
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 01849429119..6edbd3fb0b3 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -6885,10 +6885,10 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
 			UI_make_axis_color(col1, col2, 'Z');
 			glColor3ubv(col2);
 			
-			cob = constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
+			cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
 			
 			for (curcon = list->first; curcon; curcon = curcon->next) {
-				bConstraintTypeInfo *cti = constraint_get_typeinfo(curcon);
+				bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(curcon);
 				ListBase targets = {NULL, NULL};
 				bConstraintTarget *ct;
 				
@@ -6942,7 +6942,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
 				}
 			}
 			
-			constraints_clear_evalob(cob);
+			BKE_constraints_clear_evalob(cob);
 		}
 	}
 
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index b2ee17b8a8b..f861d41c260 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -2258,8 +2258,8 @@ static void protectedQuaternionBits(short protectflag, float *quat, float *oldqu
 static void constraintTransLim(TransInfo *t, TransData *td)
 {
 	if (td->con) {
-		bConstraintTypeInfo *ctiLoc = get_constraint_typeinfo(CONSTRAINT_TYPE_LOCLIMIT);
-		bConstraintTypeInfo *ctiDist = get_constraint_typeinfo(CONSTRAINT_TYPE_DISTLIMIT);
+		bConstraintTypeInfo *ctiLoc = BKE_get_constraint_typeinfo(CONSTRAINT_TYPE_LOCLIMIT);
+		bConstraintTypeInfo *ctiDist = BKE_get_constraint_typeinfo(CONSTRAINT_TYPE_DISTLIMIT);
 		
 		bConstraintOb cob = {NULL};
 		bConstraint *con;
@@ -2309,7 +2309,7 @@ static void constraintTransLim(TransInfo *t, TransData *td)
 				}
 				
 				/* get constraint targets if needed */
-				get_constraint_targets_for_solving(con, &cob, &targets, ctime);
+				BKE_get_constraint_targets_for_solving(con, &cob, &targets, ctime);
 				
 				/* do constraint */
 				cti->evaluate_constraint(con, &cob, &targets);
@@ -2361,7 +2361,7 @@ static void constraintob_from_transdata(bConstraintOb *cob, TransData *td)
 static void constraintRotLim(TransInfo *UNUSED(t), TransData *td)
 {
 	if (td->con) {
-		bConstraintTypeInfo *cti = get_constraint_typeinfo(CONSTRAINT_TYPE_ROTLIMIT);
+		bConstraintTypeInfo *cti = BKE_get_constraint_typeinfo(CONSTRAINT_TYPE_ROTLIMIT);
 		bConstraintOb cob;
 		bConstraint *con;
 		int do_limit = FALSE;
@@ -2428,7 +2428,7 @@ static void constraintRotLim(TransInfo *UNUSED(t), TransData *td)
 static void constraintSizeLim(TransInfo *t, TransData *td)
 {
 	if (td->con && td->ext) {
-		bConstraintTypeInfo *cti = get_constraint_typeinfo(CONSTRAINT_TYPE_SIZELIMIT);
+		bConstraintTypeInfo *cti = BKE_get_constraint_typeinfo(CONSTRAINT_TYPE_SIZELIMIT);
 		bConstraintOb cob = {NULL};
 		bConstraint *con;
 		float size_sign[3], size_abs[3];
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 7da47425370..8e27530f730 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -835,7 +835,7 @@ static short pose_grab_with_ik_add(bPoseChannel *pchan)
 		}
 	}
 
-	con = add_pose_constraint(NULL, pchan, "TempConstraint", CONSTRAINT_TYPE_KINEMATIC);
+	con = BKE_add_pose_constraint(NULL, pchan, "TempConstraint", CONSTRAINT_TYPE_KINEMATIC);
 	pchan->constflag |= (PCHAN_HAS_IK | PCHAN_HAS_TARGET);    /* for draw, but also for detecting while pose solving */
 	data = con->data;
 	if (targetless) {
diff --git a/source/blender/ikplugin/intern/iksolver_plugin.c b/source/blender/ikplugin/intern/iksolver_plugin.c
index 75aaa23369b..67f0694797b 100644
--- a/source/blender/ikplugin/intern/iksolver_plugin.c
+++ b/source/blender/ikplugin/intern/iksolver_plugin.c
@@ -372,7 +372,7 @@ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree)
 		/* 1.0=ctime, we pass on object for auto-ik (owner-type here is object, even though
 		 * strictly speaking, it is a posechannel)
 		 */
-		get_constraint_target_matrix(scene, target->con, 0, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0);
+		BKE_get_constraint_target_matrix(scene, target->con, 0, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0);
 
 		/* and set and transform goal */
 		mult_m4_m4m4(goal, goalinv, rootmat);
@@ -383,7 +383,7 @@ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree)
 
 		/* same for pole vector target */
 		if (data->poletar) {
-			get_constraint_target_matrix(scene, target->con, 1, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0);
+			BKE_get_constraint_target_matrix(scene, target->con, 1, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0);
 
 			if (data->flag & CONSTRAINT_IK_SETANGLE) {
 				/* don't solve IK when we are setting the pole angle */
diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp
index 903080d5b79..ef992e1d010 100644
--- a/source/blender/ikplugin/intern/itasc_plugin.cpp
+++ b/source/blender/ikplugin/intern/itasc_plugin.cpp
@@ -551,7 +551,7 @@ static bool target_callback(const iTaSC::Timestamp& timestamp, const iTaSC::Fram
 	bConstraint *constraint = (bConstraint *)target->blenderConstraint;
 	float tarmat[4][4];
 
-	get_constraint_target_matrix(target->blscene, constraint, 0, CONSTRAINT_OBTYPE_OBJECT, target->owner, tarmat, 1.0);
+	BKE_get_constraint_target_matrix(target->blscene, constraint, 0, CONSTRAINT_OBTYPE_OBJECT, target->owner, tarmat, 1.0);
 
 	// rootmat contains the target pose in world coordinate
 	// if enforce is != 1.0, blend the target position with the end effector position
@@ -620,7 +620,7 @@ static bool base_callback(const iTaSC::Timestamp& timestamp, const iTaSC::Frame&
 		IK_Channel &rootchan = ikscene->channels[0];
 
 		// get polar target matrix in world space
-		get_constraint_target_matrix(ikscene->blscene, ikscene->polarConstraint, 1, CONSTRAINT_OBTYPE_OBJECT, ikscene->blArmature, mat, 1.0);
+		BKE_get_constraint_target_matrix(ikscene->blscene, ikscene->polarConstraint, 1, CONSTRAINT_OBTYPE_OBJECT, ikscene->blArmature, mat, 1.0);
 		// convert to armature space
 		mult_m4_m4m4(polemat, imat, mat);
 		// get the target in world space (was computed before as target object are defined before base object)
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index 30a9bfd81f6..84b7080ba9b 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -214,7 +214,7 @@ static void rna_Constraint_name_set(PointerRNA *ptr, const char *value)
 		
 		/* if we have the list, check for unique name, otherwise give up */
 		if (list)
-			unique_constraint_name(con, list);
+			BKE_unique_constraint_name(con, list);
 	}
 	
 	/* fix all the animation data which may link to this */
@@ -293,7 +293,7 @@ static EnumPropertyItem *rna_Constraint_target_space_itemf(bContext *UNUSED(C),
                                                            PropertyRNA *UNUSED(prop), int *UNUSED(free))
 {
 	bConstraint *con = (bConstraint *)ptr->data;
-	bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+	bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 	ListBase targets = {NULL, NULL};
 	bConstraintTarget *ct;
 	
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index b218cc6a944..8a67d9270e8 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -1252,20 +1252,20 @@ static PointerRNA rna_Object_collision_get(PointerRNA *ptr)
 static PointerRNA rna_Object_active_constraint_get(PointerRNA *ptr)
 {
 	Object *ob = (Object *)ptr->id.data;
-	bConstraint *con = constraints_get_active(&ob->constraints);
+	bConstraint *con = BKE_constraints_get_active(&ob->constraints);
 	return rna_pointer_inherit_refine(ptr, &RNA_Constraint, con);
 }
 
 static void rna_Object_active_constraint_set(PointerRNA *ptr, PointerRNA value)
 {
 	Object *ob = (Object *)ptr->id.data;
-	constraints_set_active(&ob->constraints, (bConstraint *)value.data);
+	BKE_constraints_set_active(&ob->constraints, (bConstraint *)value.data);
 }
 
 static bConstraint *rna_Object_constraints_new(Object *object, int type)
 {
 	WM_main_add_notifier(NC_OBJECT | ND_CONSTRAINT | NA_ADDED, object);
-	return add_ob_constraint(object, NULL, type);
+	return BKE_add_ob_constraint(object, NULL, type);
 }
 
 static void rna_Object_constraints_remove(Object *object, ReportList *reports, PointerRNA *con_ptr)
@@ -1276,7 +1276,7 @@ static void rna_Object_constraints_remove(Object *object, ReportList *reports, P
 		return;
 	}
 
-	remove_constraint(&object->constraints, con);
+	BKE_remove_constraint(&object->constraints, con);
 	RNA_POINTER_INVALIDATE(con_ptr);
 
 	ED_object_constraint_update(object);
@@ -1286,7 +1286,7 @@ static void rna_Object_constraints_remove(Object *object, ReportList *reports, P
 
 static void rna_Object_constraints_clear(Object *object)
 {
-	free_constraints(&object->constraints);
+	BKE_free_constraints(&object->constraints);
 
 	ED_object_constraint_update(object);
 	ED_object_constraint_set_active(object, NULL);
diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c
index 28d1de2c601..87ef3c983aa 100644
--- a/source/blender/makesrna/intern/rna_pose.c
+++ b/source/blender/makesrna/intern/rna_pose.c
@@ -472,14 +472,14 @@ static void rna_pose_pgroup_name_set(PointerRNA *ptr, const char *value, char *r
 static PointerRNA rna_PoseChannel_active_constraint_get(PointerRNA *ptr)
 {
 	bPoseChannel *pchan = (bPoseChannel *)ptr->data;
-	bConstraint *con = constraints_get_active(&pchan->constraints);
+	bConstraint *con = BKE_constraints_get_active(&pchan->constraints);
 	return rna_pointer_inherit_refine(ptr, &RNA_Constraint, con);
 }
 
 static void rna_PoseChannel_active_constraint_set(PointerRNA *ptr, PointerRNA value)
 {
 	bPoseChannel *pchan = (bPoseChannel *)ptr->data;
-	constraints_set_active(&pchan->constraints, (bConstraint *)value.data);
+	BKE_constraints_set_active(&pchan->constraints, (bConstraint *)value.data);
 }
 
 static bConstraint *rna_PoseChannel_constraints_new(bPoseChannel *pchan, int type)
@@ -487,7 +487,7 @@ static bConstraint *rna_PoseChannel_constraints_new(bPoseChannel *pchan, int typ
 	/*WM_main_add_notifier(NC_OBJECT|ND_CONSTRAINT|NA_ADDED, object); */
 	/* TODO, pass object also */
 	/* TODO, new pose bones don't have updated draw flags */
-	return add_pose_constraint(NULL, pchan, NULL, type);
+	return BKE_add_pose_constraint(NULL, pchan, NULL, type);
 }
 
 static void rna_PoseChannel_constraints_remove(ID *id, bPoseChannel *pchan, ReportList *reports, PointerRNA *con_ptr)
@@ -501,12 +501,12 @@ static void rna_PoseChannel_constraints_remove(ID *id, bPoseChannel *pchan, Repo
 		return;
 	}
 
-	remove_constraint(&pchan->constraints, con);
+	BKE_remove_constraint(&pchan->constraints, con);
 	RNA_POINTER_INVALIDATE(con_ptr);
 
 	ED_object_constraint_update(ob);
 
-	constraints_set_active(&pchan->constraints, NULL);  /* XXX, is this really needed? - Campbell */
+	BKE_constraints_set_active(&pchan->constraints, NULL);  /* XXX, is this really needed? - Campbell */
 
 	WM_main_add_notifier(NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, id);
 
diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp
index 1f1c404efcb..395a57d753c 100644
--- a/source/gameengine/Converter/BL_ArmatureObject.cpp
+++ b/source/gameengine/Converter/BL_ArmatureObject.cpp
@@ -112,7 +112,8 @@ void game_copy_pose(bPose **dst, bPose *src, int copy_constraint)
 		if (copy_constraint) {
 			ListBase listb;
 			// copy all constraint for backward compatibility
-			copy_constraints(&listb, &pchan->constraints, FALSE);  // copy_constraints NULLs listb, no need to make extern for this operation.
+			// BKE_copy_constraints NULLs listb, no need to make extern for this operation.
+			BKE_copy_constraints(&listb, &pchan->constraints, FALSE);
 			pchan->constraints= listb;
 		} else {
 			pchan->constraints.first = NULL;
@@ -304,7 +305,7 @@ void BL_ArmatureObject::LoadConstraints(KX_BlenderSceneConverter* converter)
 			case CONSTRAINT_TYPE_TRANSFORM:
 			case CONSTRAINT_TYPE_DISTLIMIT:
 			case CONSTRAINT_TYPE_TRANSLIKE:
-				cti = constraint_get_typeinfo(pcon);
+				cti = BKE_constraint_get_typeinfo(pcon);
 				gametarget = gamesubtarget = NULL;
 				if (cti && cti->get_constraint_targets) {
 					ListBase listb = { NULL, NULL };
-- 
cgit v1.2.3


From 60ffe9f8ec9cc30e59e2a4e65fbb6b0f5f2e3297 Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Sun, 23 Dec 2012 13:02:38 +0000
Subject: Bug fix (own collection)

Icons in search menus were not drawing on the right location when UI panels were zoomed in large.
Not very common, but annoying. (DPI setting worked fine)
---
 source/blender/editors/interface/interface_widgets.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 4687647223a..7fa5ceb5fe3 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -3467,14 +3467,14 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic
 	if (iconid) {
 		float height, aspect;
 		int xs = rect->xmin + 0.2f * UI_UNIT_X;
-		int ys = 1 + (rect->ymin + rect->ymax - UI_DPI_ICON_SIZE) / 2;
+		int ys = rect->ymin + 0.1f * BLI_rcti_size_y(rect);
 		
 		/* icons are 80% of height of button (16 pixels inside 20 height) */
 		height = 0.8f * BLI_rcti_size_y(rect);
 		aspect = ICON_DEFAULT_HEIGHT / height;
-
+		
 		glEnable(GL_BLEND);
-		UI_icon_draw_aspect(xs, ys, iconid, aspect, 0.5f); /* XXX scale weak get from fstyle? */
+		UI_icon_draw_aspect(xs, ys, iconid, aspect, 1.0f); /* XXX scale weak get from fstyle? */
 		glDisable(GL_BLEND);
 	}
 }
-- 
cgit v1.2.3


From 851cb9b3455369fb9796e3c27e05e5e88f4f36b0 Mon Sep 17 00:00:00 2001
From: Sergey Sharybin 
Date: Sun, 23 Dec 2012 13:57:09 +0000
Subject: Added support of J2K codec for Jpeg2000 writing

This codec is absolutely needed to generate DCP using OpenDCP,
before that external application to convert JP2 to J2K was used
which slowed down export a lot.

New codec is exposed to image format settings panel and called
Codec. Default one is JP2 which creates files with .jp2 extension,
new one is called J2K which creates with .j2c extension.

Other changes:
- Fixed avi jpeg warning which was treating as error here.
- Made it so extension is detecting from ImageFormatData instead
  of image file type, which makes it possible to have different
  extension for the same file type depending on it's settings.

  IRIS format should still be changed (depending on number of
  channels it'll be .bw, .rgb or .rgba extension)

- Default image format settings would be set from image buffer
  when re-saving it. Makes it possible to easily open .j2c file
  and save it using J2K codec (without this change it'll save as
  .jp2 using JP2 codec)
---
 source/blender/avi/intern/avi_mjpeg.c              |  2 +-
 source/blender/blenkernel/BKE_image.h              |  6 ++-
 source/blender/blenkernel/intern/dynamicpaint.c    |  2 +-
 source/blender/blenkernel/intern/image.c           | 58 ++++++++++++++++++++--
 source/blender/blenkernel/intern/ocean.c           |  2 +-
 .../operations/COM_OutputFileOperation.cpp         |  4 +-
 source/blender/editors/render/render_opengl.c      |  4 +-
 source/blender/editors/render/render_shading.c     |  2 +-
 source/blender/editors/screen/screendump.c         |  4 +-
 source/blender/editors/space_image/image_buttons.c |  2 +
 source/blender/editors/space_image/image_ops.c     |  5 +-
 source/blender/imbuf/IMB_imbuf_types.h             |  2 +
 source/blender/imbuf/intern/jp2.c                  | 12 ++++-
 source/blender/makesdna/DNA_scene_types.h          |  7 ++-
 source/blender/makesrna/intern/rna_scene.c         | 18 ++++++-
 source/blender/makesrna/intern/rna_scene_api.c     |  2 +-
 .../composite/nodes/node_composite_outputFile.c    |  4 +-
 source/blender/render/intern/source/pipeline.c     |  8 +--
 source/blender/windowmanager/WM_api.h              |  3 +-
 source/blender/windowmanager/intern/wm_operators.c |  4 +-
 source/gameengine/BlenderRoutines/KX_BlenderGL.cpp |  2 +-
 21 files changed, 119 insertions(+), 34 deletions(-)

(limited to 'source')

diff --git a/source/blender/avi/intern/avi_mjpeg.c b/source/blender/avi/intern/avi_mjpeg.c
index 5ecb3edf92f..91b8fa5a060 100644
--- a/source/blender/avi/intern/avi_mjpeg.c
+++ b/source/blender/avi/intern/avi_mjpeg.c
@@ -206,7 +206,7 @@ static int Decode_JPEG(unsigned char *inBuffer, unsigned char *outBuffer, unsign
 	return 1;
 }
 
-static void Compress_JPEG(int quality, unsigned char *outbuffer, unsigned char *inBuffer, int width, int height, int bufsize)
+static void Compress_JPEG(int quality, unsigned char *outbuffer, const unsigned char *inBuffer, int width, int height, int bufsize)
 {
 	int i, rowstride;
 	unsigned int y;
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index 1f9630d9fce..499609932d1 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -60,8 +60,10 @@ int     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(struct ImBuf *ibuf, const char *name, struct ImageFormatData *imf);
 int     BKE_imbuf_write_as(struct ImBuf *ibuf, const char *name, struct ImageFormatData *imf, const short is_copy);
-void    BKE_makepicstring(char *string, const char *base, const char *relbase, int frame, const char imtype, const short use_ext, const short use_frames);
-int     BKE_add_image_extension(char *string, const char imtype);
+void    BKE_makepicstring(char *string, const char *base, const char *relbase, int frame, const struct ImageFormatData *im_format, const short use_ext, const short use_frames);
+void    BKE_makepicstring_from_type(char *string, const char *base, const char *relbase, int frame, const char imtype, const short use_ext, const short use_frames);
+int     BKE_add_image_extension(char *string, const struct ImageFormatData *im_format);
+int     BKE_add_image_extension_from_type(char *string, const char imtype);
 char    BKE_ftype_to_imtype(const int ftype);
 int     BKE_imtype_to_ftype(const char imtype);
 
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 0efbd92641b..fff51ab2a59 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -2689,7 +2689,7 @@ void dynamicPaint_outputSurfaceImage(DynamicPaintSurface *surface, char *filenam
 	if (format == R_IMF_IMTYPE_OPENEXR) format = R_IMF_IMTYPE_PNG;
 	#endif
 	BLI_strncpy(output_file, filename, sizeof(output_file));
-	BKE_add_image_extension(output_file, format);
+	BKE_add_image_extension_from_type(output_file, format);
 
 	/* Validate output file path	*/
 	BLI_path_abs(output_file, G.main->name);
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index f3cdf11d664..0e83f0f1988 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -1165,7 +1165,7 @@ char BKE_imtype_from_arg(const char *imtype_arg)
 	else return R_IMF_IMTYPE_INVALID;
 }
 
-int BKE_add_image_extension(char *string, const char imtype)
+static int do_add_image_extension(char *string, const char imtype, const ImageFormatData *im_format)
 {
 	const char *extension = NULL;
 
@@ -1232,8 +1232,22 @@ int BKE_add_image_extension(char *string, const char imtype)
 	}
 #ifdef WITH_OPENJPEG
 	else if (imtype == R_IMF_IMTYPE_JP2) {
-		if (!BLI_testextensie(string, ".jp2"))
-			extension = ".jp2";
+		if (im_format) {
+			if (im_format->jp2_codec == R_IMF_JP2_CODEC_JP2) {
+				if (!BLI_testextensie(string, ".jp2"))
+					extension = ".jp2";
+			}
+			else if (im_format->jp2_codec == R_IMF_JP2_CODEC_J2K) {
+				if (!BLI_testextensie(string, ".j2c"))
+					extension = ".j2c";
+			}
+			else
+				BLI_assert(!"Unsupported jp2 codec was specified in im_format->jp2_codec");
+		}
+		else {
+			if (!BLI_testextensie(string, ".jp2"))
+				extension = ".jp2";
+		}
 	}
 #endif
 	else { //   R_IMF_IMTYPE_AVIRAW, R_IMF_IMTYPE_AVIJPEG, R_IMF_IMTYPE_JPEG90, R_IMF_IMTYPE_QUICKTIME etc
@@ -1259,6 +1273,16 @@ int BKE_add_image_extension(char *string, const char imtype)
 	}
 }
 
+int BKE_add_image_extension(char *string, const ImageFormatData *im_format)
+{
+	return do_add_image_extension(string, im_format->imtype, im_format);
+}
+
+int BKE_add_image_extension_from_type(char *string, const char imtype)
+{
+	return do_add_image_extension(string, imtype, NULL);
+}
+
 void BKE_imformat_defaults(ImageFormatData *im_format)
 {
 	memset(im_format, 0, sizeof(*im_format));
@@ -1351,6 +1375,13 @@ void BKE_imbuf_to_image_format(struct ImageFormatData *im_format, const ImBuf *i
 			if (ftype & JP2_CINE_48FPS)
 				im_format->jp2_flag |= R_IMF_JP2_FLAG_CINE_48;
 		}
+
+		if (ftype & JP2_JP2)
+			im_format->jp2_codec = R_IMF_JP2_CODEC_JP2;
+		else if (ftype & JP2_J2K)
+			im_format->jp2_codec = R_IMF_JP2_CODEC_J2K;
+		else
+			BLI_assert(!"Unsupported jp2 codec was specified in file type");
 	}
 #endif
 
@@ -1906,6 +1937,13 @@ int BKE_imbuf_write(ImBuf *ibuf, const char *name, ImageFormatData *imf)
 			if (imf->jp2_flag & R_IMF_JP2_FLAG_CINE_48)
 				ibuf->ftype |= JP2_CINE_48FPS;
 		}
+
+		if (imf->jp2_codec == R_IMF_JP2_CODEC_JP2)
+			ibuf->ftype |= JP2_JP2;
+		else if (imf->jp2_codec == R_IMF_JP2_CODEC_J2K)
+			ibuf->ftype |= JP2_J2K;
+		else
+			BLI_assert(!"Unsupported jp2 codec was specified in im_format->jp2_codec");
 	}
 #endif
 	else {
@@ -1956,7 +1994,8 @@ int BKE_imbuf_write_stamp(Scene *scene, struct Object *camera, ImBuf *ibuf, cons
 }
 
 
-void BKE_makepicstring(char *string, const char *base, const char *relbase, int frame, const char imtype, const short use_ext, const short use_frames)
+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)
 {
 	if (string == NULL) return;
 	BLI_strncpy(string, base, FILE_MAX - 10);   /* weak assumption */
@@ -1966,8 +2005,17 @@ void BKE_makepicstring(char *string, const char *base, const char *relbase, int
 		BLI_path_frame(string, frame, 4);
 
 	if (use_ext)
-		BKE_add_image_extension(string, imtype);
+		do_add_image_extension(string, imtype, im_format);
+}
 
+void BKE_makepicstring(char *string, const char *base, const char *relbase, int frame, const ImageFormatData *im_format, const short use_ext, const short use_frames)
+{
+	do_makepicstring(string, base, relbase, frame, im_format->imtype, im_format, use_ext, use_frames);
+}
+
+void BKE_makepicstring_from_type(char *string, const char *base, const char *relbase, int frame, const char imtype, const short use_ext, const short use_frames)
+{
+	do_makepicstring(string, base, relbase, frame, imtype, NULL, use_ext, use_frames);
 }
 
 /* used by sequencer too */
diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c
index e694a7e7eb3..57234a5feae 100644
--- a/source/blender/blenkernel/intern/ocean.c
+++ b/source/blender/blenkernel/intern/ocean.c
@@ -967,7 +967,7 @@ static void cache_filename(char *string, const char *path, const char *relbase,
 
 	BLI_join_dirfile(cachepath, sizeof(cachepath), path, fname);
 
-	BKE_makepicstring(string, cachepath, relbase, frame, R_IMF_IMTYPE_OPENEXR, 1, TRUE);
+	BKE_makepicstring_from_type(string, cachepath, relbase, frame, R_IMF_IMTYPE_OPENEXR, 1, TRUE);
 }
 
 /* silly functions but useful to inline when the args do a lot of indirections */
diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.cpp b/source/blender/compositor/operations/COM_OutputFileOperation.cpp
index 7d05202df96..47b69ec87f9 100644
--- a/source/blender/compositor/operations/COM_OutputFileOperation.cpp
+++ b/source/blender/compositor/operations/COM_OutputFileOperation.cpp
@@ -141,7 +141,7 @@ void OutputSingleLayerOperation::deinitExecution()
 		IMB_colormanagement_imbuf_for_write(ibuf, TRUE, FALSE, m_viewSettings, m_displaySettings,
 		                                    this->m_format);
 
-		BKE_makepicstring(filename, this->m_path, bmain->name, this->m_rd->cfra, this->m_format->imtype,
+		BKE_makepicstring(filename, this->m_path, bmain->name, this->m_rd->cfra, this->m_format,
 		                  (this->m_rd->scemode & R_EXTENSION), true);
 		
 		if (0 == BKE_imbuf_write(ibuf, filename, this->m_format))
@@ -205,7 +205,7 @@ void OutputOpenExrMultiLayerOperation::deinitExecution()
 		char filename[FILE_MAX];
 		void *exrhandle = IMB_exr_get_handle();
 		
-		BKE_makepicstring(filename, this->m_path, bmain->name, this->m_rd->cfra, R_IMF_IMTYPE_MULTILAYER,
+		BKE_makepicstring_from_type(filename, this->m_path, bmain->name, this->m_rd->cfra, R_IMF_IMTYPE_MULTILAYER,
 		                  (this->m_rd->scemode & R_EXTENSION), true);
 		BLI_make_existing_file(filename);
 		
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index 16fe94ff2e5..cbc076b3342 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -281,7 +281,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
 				IMB_color_to_bw(ibuf);
 			}
 
-			BKE_makepicstring(name, scene->r.pic, oglrender->bmain->name, scene->r.cfra, scene->r.im_format.imtype, scene->r.scemode & R_EXTENSION, FALSE);
+			BKE_makepicstring(name, scene->r.pic, oglrender->bmain->name, scene->r.cfra, &scene->r.im_format, scene->r.scemode & R_EXTENSION, 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);
@@ -505,7 +505,7 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op)
 	is_movie = BKE_imtype_is_movie(scene->r.im_format.imtype);
 
 	if (!is_movie) {
-		BKE_makepicstring(name, scene->r.pic, oglrender->bmain->name, scene->r.cfra, scene->r.im_format.imtype, scene->r.scemode & R_EXTENSION, TRUE);
+		BKE_makepicstring(name, scene->r.pic, oglrender->bmain->name, scene->r.cfra, &scene->r.im_format, scene->r.scemode & R_EXTENSION, TRUE);
 
 		if ((scene->r.mode & R_NO_OVERWRITE) && BLI_exists(name)) {
 			printf("skipping existing frame \"%s\"\n", name);
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index eef5e705ce7..53e1f49d544 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -688,7 +688,7 @@ static int envmap_save_exec(bContext *C, wmOperator *op)
 	RNA_string_get(op->ptr, "filepath", path);
 	
 	if (scene->r.scemode & R_EXTENSION) {
-		BKE_add_image_extension(path, imtype);
+		BKE_add_image_extension(path, &scene->r.im_format);
 	}
 	
 	WM_cursor_wait(1);
diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c
index ca85daadf3b..2982e1f21af 100644
--- a/source/blender/editors/screen/screendump.c
+++ b/source/blender/editors/screen/screendump.c
@@ -223,7 +223,7 @@ static int screenshot_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)
 static int screenshot_check(bContext *UNUSED(C), wmOperator *op)
 {
 	ScreenshotData *scd = op->customdata;
-	return WM_operator_filesel_ensure_ext_imtype(op, scd->im_format.imtype);
+	return WM_operator_filesel_ensure_ext_imtype(op, &scd->im_format);
 }
 
 static int screenshot_cancel(bContext *UNUSED(C), wmOperator *op)
@@ -361,7 +361,7 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update, float
 				char name[FILE_MAX];
 				int ok;
 				
-				BKE_makepicstring(name, rd.pic, sj->bmain->name, rd.cfra, rd.im_format.imtype, rd.scemode & R_EXTENSION, TRUE);
+				BKE_makepicstring(name, rd.pic, sj->bmain->name, rd.cfra, &rd.im_format, rd.scemode & R_EXTENSION, TRUE);
 				
 				ibuf->rect = sj->dumprect;
 				ok = BKE_imbuf_write(ibuf, name, &rd.im_format);
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index d02186e59dd..51fbbacc07c 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -796,6 +796,8 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, int color_man
 	}
 
 	if (imf->imtype == R_IMF_IMTYPE_JP2) {
+		uiItemR(col, imfptr, "jpeg2k_codec", 0, NULL, ICON_NONE);
+
 		row = uiLayoutRow(col, FALSE);
 		uiItemR(row, imfptr, "use_jpeg2k_cinema_preset", 0, NULL, ICON_NONE);
 		uiItemR(row, imfptr, "use_jpeg2k_cinema_48", 0, NULL, ICON_NONE);
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 0d0fdc6be1c..070330c2d47 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -1217,7 +1217,7 @@ static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima,
 			simopts->im_format.imtype = R_IMF_IMTYPE_PNG;
 		}
 		else {
-			simopts->im_format.imtype = BKE_ftype_to_imtype(ibuf->ftype);
+			BKE_imbuf_to_image_format(&simopts->im_format, ibuf);
 		}
 		//simopts->subimtype = scene->r.subimtype; /* XXX - this is lame, we need to make these available too! */
 		simopts->im_format.quality = ibuf->ftype & 0xff;
@@ -1434,7 +1434,7 @@ static int image_save_as_exec(bContext *C, wmOperator *op)
 static int image_save_as_check(bContext *UNUSED(C), wmOperator *op)
 {
 	ImageFormatData *imf = op->customdata;
-	return WM_operator_filesel_ensure_ext_imtype(op, imf->imtype);
+	return WM_operator_filesel_ensure_ext_imtype(op, imf);
 }
 
 static int image_save_as_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
@@ -1559,6 +1559,7 @@ static int image_save_exec(bContext *C, wmOperator *op)
 	Scene *scene = CTX_data_scene(C);
 	SaveImageOptions simopts;
 
+	save_image_options_defaults(&simopts);
 	if (save_image_options_init(&simopts, sima, scene, FALSE) == 0)
 		return OPERATOR_CANCELLED;
 	save_image_options_from_op(&simopts, op);
diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h
index 28e62d496b2..433123914ce 100644
--- a/source/blender/imbuf/IMB_imbuf_types.h
+++ b/source/blender/imbuf/IMB_imbuf_types.h
@@ -217,6 +217,8 @@ typedef struct ImBuf {
 #define JP2_YCC			(1 << 15)
 #define JP2_CINE		(1 << 14)
 #define JP2_CINE_48FPS	(1 << 13) 
+#define JP2_JP2	(1 << 12)
+#define JP2_J2K	(1 << 11)
 #endif
 
 #define RAWTGA	        (TGA | 1)
diff --git a/source/blender/imbuf/intern/jp2.c b/source/blender/imbuf/intern/jp2.c
index 3a2bf99c75c..8d6218a389e 100644
--- a/source/blender/imbuf/intern/jp2.c
+++ b/source/blender/imbuf/intern/jp2.c
@@ -228,6 +228,10 @@ struct ImBuf *imb_jp2_decode(unsigned char *mem, size_t size, int flags, char co
 	}
 	
 	ibuf->ftype = JP2;
+	if (is_jp2)
+		ibuf->ftype |= JP2_JP2;
+	else
+		ibuf->ftype |= JP2_J2K;
 	
 	if (use_float) {
 		float *rect_float = ibuf->rect_float;
@@ -852,9 +856,15 @@ int imb_savejp2(struct ImBuf *ibuf, const char *name, int flags)
 		int codestream_length;
 		opj_cio_t *cio = NULL;
 		FILE *f = NULL;
+		opj_cinfo_t *cinfo = NULL;
 
 		/* get a JP2 compressor handle */
-		opj_cinfo_t *cinfo = opj_create_compress(CODEC_JP2);
+		if (ibuf->ftype & JP2_JP2)
+			cinfo = opj_create_compress(CODEC_JP2);
+		else if (ibuf->ftype & JP2_J2K)
+			cinfo = opj_create_compress(CODEC_J2K);
+		else
+			BLI_assert(!"Unsupported codec was specified in save settings");
 
 		/* catch events using our callbacks and give a local context */
 		opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr);
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index a01785a29ca..5e06a3084ac 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -271,8 +271,9 @@ typedef struct ImageFormatData {
 
 	/* Jpeg2000 */
 	char  jp2_flag;
+	char jp2_codec;
 
-	char pad[7];
+	char pad[6];
 
 	/* color management */
 	ColorManagedViewSettings view_settings;
@@ -341,6 +342,10 @@ typedef struct ImageFormatData {
 #define R_IMF_JP2_FLAG_CINE_PRESET  (1<<1)  /* was R_JPEG2K_CINE_PRESET */
 #define R_IMF_JP2_FLAG_CINE_48      (1<<2)  /* was R_JPEG2K_CINE_48FPS */
 
+/* ImageFormatData.jp2_codec */
+#define R_IMF_JP2_CODEC_JP2  0
+#define R_IMF_JP2_CODEC_J2K  1
+
 /* ImageFormatData.cineon_flag */
 #define R_IMF_CINEON_FLAG_LOG (1<<0)  /* was R_CINEON_LOG */
 
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index c4b5d8d5109..1ead8e6e975 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -873,7 +873,7 @@ static int rna_SceneRender_file_ext_length(PointerRNA *ptr)
 	RenderData *rd = (RenderData *)ptr->data;
 	char ext[8];
 	ext[0] = '\0';
-	BKE_add_image_extension(ext, rd->im_format.imtype);
+	BKE_add_image_extension(ext, &rd->im_format);
 	return strlen(ext);
 }
 
@@ -881,7 +881,7 @@ static void rna_SceneRender_file_ext_get(PointerRNA *ptr, char *str)
 {
 	RenderData *rd = (RenderData *)ptr->data;
 	str[0] = '\0';
-	BKE_add_image_extension(str, rd->im_format.imtype);
+	BKE_add_image_extension(str, &rd->im_format);
 }
 
 #ifdef WITH_QUICKTIME
@@ -2881,6 +2881,14 @@ static void rna_def_scene_image_format_data(BlenderRNA *brna)
 	};
 #endif
 
+#ifdef WITH_OPENJPEG
+	static EnumPropertyItem jp2_codec_items[] = {
+		{R_IMF_JP2_CODEC_JP2, "JP2", 0, "JP2", ""},
+		{R_IMF_JP2_CODEC_J2K, "J2K", 0, "J2K", ""},
+		{0, NULL, 0, NULL, NULL}
+	};
+#endif
+
 	StructRNA *srna;
 	PropertyRNA *prop;
 
@@ -2968,6 +2976,12 @@ static void rna_def_scene_image_format_data(BlenderRNA *brna)
 	RNA_def_property_boolean_sdna(prop, NULL, "jp2_flag", R_IMF_JP2_FLAG_CINE_48);
 	RNA_def_property_ui_text(prop, "Cinema (48)", "Use Openjpeg Cinema Preset (48fps)");
 	RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+
+	prop = RNA_def_property(srna, "jpeg2k_codec", PROP_ENUM, PROP_NONE);
+	RNA_def_property_enum_sdna(prop, NULL, "jp2_codec");
+	RNA_def_property_enum_items(prop, jp2_codec_items);
+	RNA_def_property_ui_text(prop, "Codec", "Codec settings for Jpek2000");
+	RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
 #endif
 
 	/* Cineon and DPX */
diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c
index 012767b5845..9b5a858a581 100644
--- a/source/blender/makesrna/intern/rna_scene_api.c
+++ b/source/blender/makesrna/intern/rna_scene_api.c
@@ -84,7 +84,7 @@ static void rna_SceneRender_get_frame_path(RenderData *rd, int frame, char *name
 	if (BKE_imtype_is_movie(rd->im_format.imtype))
 		BKE_movie_filepath_get(name, rd);
 	else
-		BKE_makepicstring(name, rd->pic, G.main->name, (frame == INT_MIN) ? rd->cfra : frame, rd->im_format.imtype,
+		BKE_makepicstring(name, rd->pic, G.main->name, (frame == INT_MIN) ? rd->cfra : frame, &rd->im_format,
 		                  rd->scemode & R_EXTENSION, TRUE);
 }
 
diff --git a/source/blender/nodes/composite/nodes/node_composite_outputFile.c b/source/blender/nodes/composite/nodes/node_composite_outputFile.c
index 214617c91e5..fe23f7373fb 100644
--- a/source/blender/nodes/composite/nodes/node_composite_outputFile.c
+++ b/source/blender/nodes/composite/nodes/node_composite_outputFile.c
@@ -269,7 +269,7 @@ static void exec_output_file_singlelayer(RenderData *rd, bNode *node, bNodeStack
 			
 			/* get full path */
 			BLI_join_dirfile(path, FILE_MAX, nimf->base_path, sockdata->path);
-			BKE_makepicstring(filename, path, bmain->name, rd->cfra, format->imtype, (rd->scemode & R_EXTENSION), TRUE);
+			BKE_makepicstring(filename, path, bmain->name, rd->cfra, format, (rd->scemode & R_EXTENSION), TRUE);
 			
 			if (0 == BKE_imbuf_write(ibuf, filename, format))
 				printf("Cannot save Node File Output to %s\n", filename);
@@ -304,7 +304,7 @@ static void exec_output_file_multilayer(RenderData *rd, bNode *node, bNodeStack
 	int recty = -1;
 	int has_preview = 0;
 	
-	BKE_makepicstring(filename, nimf->base_path, bmain->name, rd->cfra, R_IMF_IMTYPE_MULTILAYER, (rd->scemode & R_EXTENSION), TRUE);
+	BKE_makepicstring_from_type(filename, nimf->base_path, bmain->name, rd->cfra, R_IMF_IMTYPE_MULTILAYER, (rd->scemode & R_EXTENSION), TRUE);
 	BLI_make_existing_file(filename);
 	
 	for (sock=node->inputs.first, i=0; sock; sock=sock->next, ++i) {
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 413d7cb959e..35ac038f2f2 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -2117,7 +2117,7 @@ void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *sr
 			}
 			else {
 				char name[FILE_MAX];
-				BKE_makepicstring(name, scene->r.pic, bmain->name, scene->r.cfra, scene->r.im_format.imtype, scene->r.scemode & R_EXTENSION, FALSE);
+				BKE_makepicstring(name, scene->r.pic, bmain->name, scene->r.cfra, &scene->r.im_format, scene->r.scemode & R_EXTENSION, FALSE);
 
 				/* reports only used for Movie */
 				do_write_image_or_movie(re, bmain, scene, NULL, name);
@@ -2176,7 +2176,7 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie
 		if (name_override)
 			BLI_strncpy(name, name_override, sizeof(name));
 		else
-			BKE_makepicstring(name, scene->r.pic, bmain->name, scene->r.cfra, scene->r.im_format.imtype, scene->r.scemode & R_EXTENSION, TRUE);
+			BKE_makepicstring(name, scene->r.pic, bmain->name, scene->r.cfra, &scene->r.im_format, scene->r.scemode & R_EXTENSION, TRUE);
 		
 		if (re->r.im_format.imtype == R_IMF_IMTYPE_MULTILAYER) {
 			if (re->result) {
@@ -2204,7 +2204,7 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie
 
 				if (BLI_testextensie(name, ".exr"))
 					name[strlen(name) - 4] = 0;
-				BKE_add_image_extension(name, R_IMF_IMTYPE_JPEG90);
+				BKE_add_image_extension(name, &imf);
 				ibuf->planes = 24;
 
 				IMB_colormanagement_imbuf_for_write(ibuf, TRUE, FALSE, &scene->view_settings,
@@ -2309,7 +2309,7 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
 			/* Touch/NoOverwrite options are only valid for image's */
 			if (BKE_imtype_is_movie(scene->r.im_format.imtype) == 0) {
 				if (scene->r.mode & (R_NO_OVERWRITE | R_TOUCH))
-					BKE_makepicstring(name, scene->r.pic, bmain->name, scene->r.cfra, scene->r.im_format.imtype, scene->r.scemode & R_EXTENSION, TRUE);
+					BKE_makepicstring(name, scene->r.pic, bmain->name, scene->r.cfra, &scene->r.im_format, scene->r.scemode & R_EXTENSION, TRUE);
 
 				if (scene->r.mode & R_NO_OVERWRITE && BLI_exists(name)) {
 					printf("skipping existing frame \"%s\"\n", name);
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 75ab0f5bcd7..c418b07401d 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -62,6 +62,7 @@ struct MenuType;
 struct wmDropBox;
 struct wmDrag;
 struct ImBuf;
+struct ImageFormatData;
 
 typedef struct wmJob wmJob;
 
@@ -185,7 +186,7 @@ int			WM_enum_search_invoke(struct bContext *C, struct wmOperator *op, struct wm
 int			WM_operator_confirm		(struct bContext *C, struct wmOperator *op, struct wmEvent *event);
 		/* invoke callback, file selector "filepath" unset + exec */
 int			WM_operator_filesel		(struct bContext *C, struct wmOperator *op, struct wmEvent *event);
-int         WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const char imtype);
+int         WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const struct ImageFormatData *im_format);
 			/* poll callback, context checks */
 int			WM_operator_winactive	(struct bContext *C);
 			/* invoke callback, exec + redo popup */
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index b5f1d590f37..8867101779a 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -976,14 +976,14 @@ int WM_operator_filesel(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
 	}
 }
 
-int WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const char imtype)
+int WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const struct ImageFormatData *im_format)
 {
 	PropertyRNA *prop;
 	char filepath[FILE_MAX];
 	/* dont NULL check prop, this can only run on ops with a 'filepath' */
 	prop = RNA_struct_find_property(op->ptr, "filepath");
 	RNA_property_string_get(op->ptr, prop, filepath);
-	if (BKE_add_image_extension(filepath, imtype)) {
+	if (BKE_add_image_extension(filepath, im_format)) {
 		RNA_property_string_set(op->ptr, prop, filepath);
 		/* note, we could check for and update 'filename' here,
 		 * but so far nothing needs this. */
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp
index 00836fa8ecb..f8ad8870e83 100644
--- a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp
+++ b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp
@@ -259,7 +259,7 @@ void BL_MakeScreenShot(ScrArea *curarea, const char* filename)
 		ImBuf *ibuf;
 		BLI_path_abs(path, G.main->name);
 		/* BKE_add_image_extension() checks for if extension was already set */
-		BKE_add_image_extension(path, R_IMF_IMTYPE_PNG); /* scene->r.im_format.imtype */
+		BKE_add_image_extension_from_type(path, R_IMF_IMTYPE_PNG); /* scene->r.im_format.imtype */
 		ibuf= IMB_allocImBuf(dumpsx, dumpsy, 24, 0);
 		ibuf->rect= dumprect;
 		ibuf->ftype= PNG;
-- 
cgit v1.2.3


From 789b2acd772c2856a09017972e9cc7278f60c4ab Mon Sep 17 00:00:00 2001
From: Bastien Montagne 
Date: Sun, 23 Dec 2012 13:58:42 +0000
Subject: Add keying "options" parameter to keyframe_insert() bpy_rna function,
 so now you can enable 'INSERTKEY_NEEDED', 'INSERTKEY_VISUAL' and/or
 'INSERTKEY_XYZ_TO_RGB' when you directly key some property from python script
 (previously those options were only available through keyingsets).

Thanks to Campbell for review!
---
 source/blender/makesrna/RNA_enum_types.h       |  1 +
 source/blender/makesrna/intern/rna_animation.c | 25 +++++++++--------
 source/blender/python/intern/bpy_rna_anim.c    | 39 +++++++++++++++++++-------
 3 files changed, 44 insertions(+), 21 deletions(-)

(limited to 'source')

diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index 0f9a00de7b6..9d08cf2d364 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -70,6 +70,7 @@ extern EnumPropertyItem keyframe_handle_type_items[];
 extern EnumPropertyItem keyblock_type_items[];
 
 extern EnumPropertyItem keyingset_path_grouping_items[];
+extern EnumPropertyItem keying_flag_items[];
 
 extern EnumPropertyItem keyframe_paste_offset_items[];
 extern EnumPropertyItem keyframe_paste_merge_items[];
diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c
index 7229dddf6d6..402d05a20b6 100644
--- a/source/blender/makesrna/intern/rna_animation.c
+++ b/source/blender/makesrna/intern/rna_animation.c
@@ -52,6 +52,20 @@ EnumPropertyItem keyingset_path_grouping_items[] = {
 	{0, NULL, 0, NULL, NULL}
 };
 
+/* It would be cool to get rid of this 'INSERTKEY_' prefix in 'py strings' values, but it would break existing
+ * exported keyingset... :/
+ */
+EnumPropertyItem keying_flag_items[] = {
+	{INSERTKEY_NEEDED, "INSERTKEY_NEEDED", 0, "Only Needed",
+	                   "Only insert keyframes where they're needed in the relevant F-Curves"},
+	{INSERTKEY_MATRIX, "INSERTKEY_VISUAL", 0, "Visual Keying",
+	                   "Insert keyframes based on 'visual transforms'"},
+	{INSERTKEY_XYZ2RGB, "INSERTKEY_XYZ_TO_RGB", 0, "XYZ=RGB Colors",
+	                    "Color for newly added transformation F-Curves (Location, Rotation, Scale) "
+	                    "and also Color is based on the transform axis"},
+	{0, NULL, 0, NULL, NULL}
+};
+
 #ifdef RNA_RUNTIME
 
 #include "BLI_math_base.h"
@@ -518,17 +532,6 @@ static void rna_def_common_keying_flags(StructRNA *srna, short UNUSED(reg))
 {
 	PropertyRNA *prop;
 
-	static EnumPropertyItem keying_flag_items[] = {
-		{INSERTKEY_NEEDED, "INSERTKEY_NEEDED", 0, "Only Needed",
-		                   "Only insert keyframes where they're needed in the relevant F-Curves"},
-		{INSERTKEY_MATRIX, "INSERTKEY_VISUAL", 0, "Visual Keying",
-		                   "Insert keyframes based on 'visual transforms'"},
-		{INSERTKEY_XYZ2RGB, "INSERTKEY_XYZ_TO_RGB", 0, "XYZ=RGB Colors",
-		                    "Color for newly added transformation F-Curves (Location, Rotation, Scale) "
-		                    "and also Color is based on the transform axis"},
-		{0, NULL, 0, NULL, NULL}
-	};
-
 	prop = RNA_def_property(srna, "bl_options", PROP_ENUM, PROP_NONE);
 	RNA_def_property_enum_sdna(prop, NULL, "keyingflag");
 	RNA_def_property_enum_items(prop, keying_flag_items);
diff --git a/source/blender/python/intern/bpy_rna_anim.c b/source/blender/python/intern/bpy_rna_anim.c
index 69839514a12..cacae8fd184 100644
--- a/source/blender/python/intern/bpy_rna_anim.c
+++ b/source/blender/python/intern/bpy_rna_anim.c
@@ -44,6 +44,7 @@
 #include "BKE_fcurve.h"
 
 #include "RNA_access.h"
+#include "RNA_enum_types.h"
 
 #include "WM_api.h"
 #include "WM_types.h"
@@ -147,14 +148,17 @@ static int pyrna_struct_anim_args_parse(
 /* internal use for insert and delete */
 static int pyrna_struct_keyframe_parse(
         PointerRNA *ptr, PyObject *args, PyObject *kw, const char *parse_str, const char *error_prefix,
-        const char **path_full, int *index, float *cfra, const char **group_name)     /* return values */
+        const char **path_full, int *index, float *cfra, const char **group_name, int *options)     /* return values */
 {
-	static const char *kwlist[] = {"data_path", "index", "frame", "group", NULL};
+	static const char *kwlist[] = {"data_path", "index", "frame", "group", "options", NULL};
+	PyObject *pyoptions = NULL;
 	const char *path;
 
-	/* note, parse_str MUST start with 's|ifs' */
-	if (!PyArg_ParseTupleAndKeywords(args, kw, parse_str, (char **)kwlist, &path, index, cfra, group_name))
+	/* note, parse_str MUST start with 's|ifsO!' */
+	if (!PyArg_ParseTupleAndKeywords(args, kw, parse_str, (char **)kwlist, &path, index, cfra, group_name,
+	                                 &PySet_Type, &pyoptions)) {
 		return -1;
+	}
 
 	if (pyrna_struct_anim_args_parse(ptr, error_prefix, path, path_full, index) < 0)
 		return -1;
@@ -162,6 +166,13 @@ static int pyrna_struct_keyframe_parse(
 	if (*cfra == FLT_MAX)
 		*cfra = CTX_data_scene(BPy_GetContext())->r.cfra;
 
+	/* flag may be null (no option currently for remove keyframes e.g.). */
+	if (pyrna_struct_anim_args_parse(ptr, error_prefix, path, path_full, index) < 0)
+		return -1;
+
+	if (pyoptions && options && (pyrna_set_to_enum_bitfield(keying_flag_items, pyoptions, options, error_prefix) < 0))
+		return -1;
+
 	return 0; /* success */
 }
 
@@ -172,12 +183,19 @@ char pyrna_struct_keyframe_insert_doc[] =
 "\n"
 "   :arg data_path: path to the property to key, analogous to the fcurve's data path.\n"
 "   :type data_path: string\n"
-"   :arg index: array index of the property to key. Defaults to -1 which will key all indices or a single channel if the property is not an array.\n"
+"   :arg index: array index of the property to key. Defaults to -1 which will key all indices or a single channel "
+               "if the property is not an array.\n"
 "   :type index: int\n"
 "   :arg frame: The frame on which the keyframe is inserted, defaulting to the current frame.\n"
 "   :type frame: float\n"
 "   :arg group: The name of the group the F-Curve should be added to if it doesn't exist yet.\n"
 "   :type group: str\n"
+"   :arg options: Some optional flags:\n"
+"                     'NEEDED': Only insert keyframes where they're needed in the relevant F-Curves.\n"
+"                     'VISUAL': Insert keyframes based on 'visual transforms'.\n"
+"                     'XYZ_TO_RGB': Color for newly added transformation F-Curves (Location, Rotation, Scale) "
+                                   "and also Color is based on the transform axis.\n"
+"   :type flag: set\n"
 "   :return: Success of keyframe insertion.\n"
 "   :rtype: boolean\n"
 ;
@@ -188,12 +206,13 @@ PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyOb
 	int index = -1;
 	float cfra = FLT_MAX;
 	const char *group_name = NULL;
+	int options = 0;
 
 	PYRNA_STRUCT_CHECK_OBJ(self);
 
 	if (pyrna_struct_keyframe_parse(&self->ptr, args, kw,
-	                                "s|ifs:bpy_struct.keyframe_insert()", "bpy_struct.keyframe_insert()",
-	                                &path_full, &index, &cfra, &group_name) == -1)
+	                                "s|ifsO!:bpy_struct.keyframe_insert()", "bpy_struct.keyframe_insert()",
+	                                &path_full, &index, &cfra, &group_name, &options) == -1)
 	{
 		return NULL;
 	}
@@ -203,7 +222,7 @@ PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyOb
 
 		BKE_reports_init(&reports, RPT_STORE);
 
-		result = insert_keyframe(&reports, (ID *)self->ptr.id.data, NULL, group_name, path_full, index, cfra, 0);
+		result = insert_keyframe(&reports, (ID *)self->ptr.id.data, NULL, group_name, path_full, index, cfra, options);
 		MEM_freeN((void *)path_full);
 
 		if (BPy_reports_to_error(&reports, PyExc_RuntimeError, TRUE) == -1)
@@ -240,9 +259,9 @@ PyObject *pyrna_struct_keyframe_delete(BPy_StructRNA *self, PyObject *args, PyOb
 	PYRNA_STRUCT_CHECK_OBJ(self);
 
 	if (pyrna_struct_keyframe_parse(&self->ptr, args, kw,
-	                                "s|ifs:bpy_struct.keyframe_delete()",
+	                                "s|ifsO!:bpy_struct.keyframe_delete()",
 	                                "bpy_struct.keyframe_insert()",
-	                                &path_full, &index, &cfra, &group_name) == -1)
+	                                &path_full, &index, &cfra, &group_name, NULL) == -1)
 	{
 		return NULL;
 	}
-- 
cgit v1.2.3


From 3217ecbc8e561e9f84aa732256323a5e9489f7cc Mon Sep 17 00:00:00 2001
From: Sergey Sharybin 
Date: Sun, 23 Dec 2012 14:34:10 +0000
Subject: Compilation fix for collada

---
 source/blender/collada/ImageExporter.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp
index aba290f5ce4..55fe2034869 100644
--- a/source/blender/collada/ImageExporter.cpp
+++ b/source/blender/collada/ImageExporter.cpp
@@ -89,7 +89,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
 			// make absolute destination path
 
 			BLI_strncpy(export_file, name.c_str(), sizeof(export_file));
-			BKE_add_image_extension(export_file, imageFormat.imtype);
+			BKE_add_image_extension(export_file, &imageFormat);
 
 			BLI_join_dirfile(export_path, sizeof(export_path), export_dir, export_file);
 
-- 
cgit v1.2.3


From 97bdec181145902292c41d6f559154c4ec5d06ee Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Sun, 23 Dec 2012 16:08:02 +0000
Subject: fix for use of uninitialized variable with ui_handler_region_menu.

---
 source/blender/editors/interface/interface_handlers.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index fed84092133..958334fb476 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -6928,8 +6928,6 @@ static int ui_handler_region_menu(bContext *C, wmEvent *event, void *UNUSED(user
 {
 	ARegion *ar;
 	uiBut *but;
-	uiHandleButtonData *data;
-	int retval;
 
 	/* here we handle buttons at the window level, modal, for example
 	 * while number sliding, text editing, or when a menu block is open */
@@ -6940,17 +6938,23 @@ static int ui_handler_region_menu(bContext *C, wmEvent *event, void *UNUSED(user
 	but = ui_but_find_activated(ar);
 
 	if (but) {
+		uiHandleButtonData *data;
+
 		/* handle activated button events */
 		data = but->active;
 
 		if (data->state == BUTTON_STATE_MENU_OPEN) {
+			int retval;
+
 			/* handle events for menus and their buttons recursively,
 			 * this will handle events from the top to the bottom menu */
 			if (data->menu)
 				retval = ui_handle_menus_recursive(C, event, data->menu, 0);
 
 			/* handle events for the activated button */
-			if (retval == WM_UI_HANDLER_CONTINUE || event->type == TIMER) {
+			if ((data->menu && (retval == WM_UI_HANDLER_CONTINUE)) ||
+			    (event->type == TIMER))
+			{
 				if (data->menu && data->menu->menuretval)
 					ui_handle_button_return_submenu(C, event, but);
 				else
-- 
cgit v1.2.3


From 90900495050a8a1060de94eaa533899c361ea80f Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Sun, 23 Dec 2012 16:09:26 +0000
Subject: code cleanup

---
 source/blender/blenkernel/intern/image.c                | 1 +
 source/blender/blenlib/intern/BLI_kdopbvh.c             | 2 +-
 source/blender/blenlib/intern/math_vector_inline.c      | 2 +-
 source/blender/bmesh/tools/bmesh_bevel.c                | 2 +-
 source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c | 2 +-
 source/blender/editors/space_view3d/view3d_edit.c       | 5 +++--
 source/blender/modifiers/intern/MOD_weightvgmix.c       | 2 +-
 7 files changed, 9 insertions(+), 7 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 0e83f0f1988..7782afaca25 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -1168,6 +1168,7 @@ char BKE_imtype_from_arg(const char *imtype_arg)
 static int do_add_image_extension(char *string, const char imtype, const ImageFormatData *im_format)
 {
 	const char *extension = NULL;
+	(void)im_format;  /* may be unused, depends on build options */
 
 	if (imtype == R_IMF_IMTYPE_IRIS) {
 		if (!BLI_testextensie(string, ".rgb"))
diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c
index 55f67cedfc6..b2d07b9ee4d 100644
--- a/source/blender/blenlib/intern/BLI_kdopbvh.c
+++ b/source/blender/blenlib/intern/BLI_kdopbvh.c
@@ -1554,7 +1554,7 @@ int BLI_bvhtree_ray_cast(BVHTree *tree, const float co[3], const float dir[3], f
 float BLI_bvhtree_bb_raycast(const float bv[6], const float light_start[3], const float light_end[3], float pos[3])
 {
 	BVHRayCastData data;
-	float dist = 0.0;
+	float dist;
 
 	data.hit.dist = FLT_MAX;
 	
diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c
index 04b9d574347..8c62fdf81a7 100644
--- a/source/blender/blenlib/intern/math_vector_inline.c
+++ b/source/blender/blenlib/intern/math_vector_inline.c
@@ -461,7 +461,7 @@ MINLINE void mul_v3_v3v3(float r[3], const float v1[3], const float v2[3])
 	r[2] = v1[2] * v2[2];
 }
 
-MINLINE void negate_v2(float r[3])
+MINLINE void negate_v2(float r[2])
 {
 	r[0] = -r[0];
 	r[1] = -r[1];
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index fbac538eb7f..50e59ab3e64 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -1276,7 +1276,7 @@ static void bevel_build_trifan(BMesh *bm, BevVert *bv)
 				else { BLI_assert(0); }
 			}
 			else {
-				if      (l_fan->v       == v_fan) { l_fan = l_fan; }
+				if      (l_fan->v       == v_fan) { /* l_fan = l_fan; */ }
 				else if (l_fan->next->v == v_fan) { l_fan = l_fan->next; }
 				else if (l_fan->prev->v == v_fan) { l_fan = l_fan->prev; }
 				else { BLI_assert(0); }
diff --git a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c
index acdab2510a4..71c1cedbd5e 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c
@@ -268,7 +268,7 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int
 			BMW_end(&walker);
 #else
 
-			BM_elem_index_set(v_first, (offset + depth) % nth ? VERT_INDEX_IGNORE : VERT_INDEX_DO_COLLAPSE);  /* set_dirty! */
+			BM_elem_index_set(v_first, ((offset + depth) % nth) ? VERT_INDEX_IGNORE : VERT_INDEX_DO_COLLAPSE);  /* set_dirty! */
 
 			vert_seek_b_tot = 0;
 			vert_seek_b[vert_seek_b_tot++] = v_first;
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 78c3f4e4f4a..adaad2557d4 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -1261,8 +1261,9 @@ void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot)
  */
 static int ndof_all_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
-	if (event->type != NDOF_MOTION)
+	if (event->type != NDOF_MOTION) {
 		return OPERATOR_CANCELLED;
+	}
 	else {
 	
 		ViewOpsData *vod;
@@ -1389,7 +1390,7 @@ static int ndof_all_invoke(bContext *C, wmOperator *op, wmEvent *event)
 			}
 			
 			/* rotate around custom center */
-			if (vod && vod->use_dyn_ofs) {
+			if (vod->use_dyn_ofs) {
 				float q1[4];
 				
 				/* compute the post multiplication quat, to rotate the offset correctly */
diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c
index 5883b176317..f025352795b 100644
--- a/source/blender/modifiers/intern/MOD_weightvgmix.c
+++ b/source/blender/modifiers/intern/MOD_weightvgmix.c
@@ -361,7 +361,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
 
 	/* Mix weights. */
 	for (i = 0; i < numIdx; i++) {
-		float weight2 = 0.0;
+		float weight2;
 		org_w[i] = dw1[i] ? dw1[i]->weight : wmd->default_weight_a;
 		weight2  = dw2[i] ? dw2[i]->weight : wmd->default_weight_b;
 
-- 
cgit v1.2.3


From 84eaa875def980c31a339f0ca7f62b6086b88ef4 Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Sun, 23 Dec 2012 18:41:00 +0000
Subject: Patch for weirdo library recursive linking errors:

In case you accidentally link data in a library file from the main file, Blender would crash.
Now it survives, giving error messages to tell what to fix.
---
 source/blender/blenloader/intern/readfile.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 81101e01516..87eaab387a2 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -8747,7 +8747,15 @@ static void expand_doit_library(void *fdhandle, Main *mainvar, void *old)
 				Library *lib = read_struct(fd, bheadlib, "Library");
 				Main *ptr = blo_find_main(fd, lib->name, fd->relabase);
 				
-				id = is_yet_read(fd, ptr, bhead);
+				if (ptr->curlib == NULL) {
+					const char *idname= bhead_id_name(fd, bhead);
+					
+					BKE_reportf_wrap(fd->reports, RPT_WARNING, TIP_("LIB ERROR: Data refers to main .blend file: '%s' from %s"),
+					                 idname, mainvar->curlib->filepath);
+					return;
+				}
+				else
+					id = is_yet_read(fd, ptr, bhead);
 				
 				if (id == NULL) {
 					read_libblock(fd, ptr, bhead, LIB_READ+LIB_INDIRECT, NULL);
-- 
cgit v1.2.3


From c52468d31df98d4b975e4f00abdfa3e8ca442f6e Mon Sep 17 00:00:00 2001
From: Morten Mikkelsen 
Date: Sun, 23 Dec 2012 18:58:10 +0000
Subject: flip lines to reduce odds of re-execution (non critical race
 condition when triangles overlap

---
 source/blender/render/intern/source/multires_bake.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/render/intern/source/multires_bake.c b/source/blender/render/intern/source/multires_bake.c
index 9785edd3288..b8784685836 100644
--- a/source/blender/render/intern/source/multires_bake.c
+++ b/source/blender/render/intern/source/multires_bake.c
@@ -233,8 +233,8 @@ static void set_rast_triangle(const MBakeRast *bake_rast, const int x, const int
 
 	if (x >= 0 && x < w && y >= 0 && y < h) {
 		if ((bake_rast->texels[y * w + x]) == 0) {
-			flush_pixel(bake_rast->data, x, y);
 			bake_rast->texels[y * w + x] = FILTER_MASK_USED;
+			flush_pixel(bake_rast->data, x, y);
 		}
 	}
 }
-- 
cgit v1.2.3


From 388c08c88b7f7ec27dcde3f44761adba8926bde8 Mon Sep 17 00:00:00 2001
From: Thomas Dinges 
Date: Mon, 24 Dec 2012 00:29:24 +0000
Subject: User Interface / Preferences: * Added a new "Text Style" area into
 the theme section, with settings to control font kerning, shadow size, color
 and offset.

---
 source/blender/makesrna/intern/rna_userdef.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 2b17249e4fe..397453d8408 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -437,7 +437,7 @@ static void rna_def_userdef_theme_ui_font_style(BlenderRNA *brna)
 	
 	static EnumPropertyItem font_kerning_style[] = {
 		{0, "UNFITTED", 0, "Unfitted", "Use scaled but un-grid-fitted kerning distances"},
-		{1, "DEFAULT", 0, "Default", "Use scaled and grid-fitted kerning distances"},
+		{1, "FITTED", 0, "Fitted", "Use scaled and grid-fitted kerning distances"},
 		{0, NULL, 0, NULL, NULL}
 	};
 
@@ -2214,6 +2214,7 @@ static void rna_def_userdef_themes(BlenderRNA *brna)
 	
 	static EnumPropertyItem active_theme_area[] = {
 		{0, "USER_INTERFACE", ICON_UI, "User Interface", ""},
+		{19, "STYLE", ICON_FONTPREVIEW, "Text Style", ""},
 		{18, "BONE_COLOR_SETS", ICON_COLOR, "Bone Color Sets", ""},
 		{1, "VIEW_3D", ICON_VIEW3D, "3D View", ""},
 		{2, "TIMELINE", ICON_TIME, "Timeline", ""},
-- 
cgit v1.2.3


From 119665d5b7b61f1924b4f0bf89fe1cff00017eed Mon Sep 17 00:00:00 2001
From: Mitchell Stokes 
Date: Mon, 24 Dec 2012 02:59:16 +0000
Subject: BGE: Use canvas->SetViewPort() instead of glViewport() in the 2D
 filter.

---
 source/gameengine/Rasterizer/RAS_2DFilterManager.cpp | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

(limited to 'source')

diff --git a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp
index cf869e71945..152c6bcce4e 100644
--- a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp
+++ b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp
@@ -428,8 +428,7 @@ void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas)
 
 	// reverting to texunit 0, without this we get bug [#28462]
 	glActiveTextureARB(GL_TEXTURE0);
-
-	glViewport(rect.GetLeft(), rect.GetBottom(), rect_width, rect_height);
+	canvas->SetViewPort(rect.GetLeft(), rect.GetBottom(), rect_width, rect_height);
 
 	glDisable(GL_DEPTH_TEST);
 	// in case the previous material was wire
@@ -466,7 +465,7 @@ void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas)
 	}
 
 	glEnable(GL_DEPTH_TEST);
-	glViewport(viewport[0],viewport[1],viewport[2],viewport[3]);
+	canvas->SetViewPort(viewport[0],viewport[1],viewport[2],viewport[3]);
 	EndShaderProgram();
 	glPopMatrix();
 	glMatrixMode(GL_MODELVIEW);
-- 
cgit v1.2.3


From a1c9241797b003979c1da747e217e875c497c775 Mon Sep 17 00:00:00 2001
From: Mitchell Stokes 
Date: Mon, 24 Dec 2012 03:13:53 +0000
Subject: BGE: "Fix" for issue [#33663] "Objects Share Materials / Textures
 When Grouped In SingleTexture / MultiTexture Mode" reported by Josiah Lane
 (solarlune).

This commit adds a UI option in the Render properties to enable the new material caching in the converter. This caching can cause problems with Singletexture and Multitexture materials when texface is being used to handle materials. By default this option is enabled and users with broken games have two options:

  1) Fix up their materials so they are properly using textures
  2) Disable the material caching and take a speed hit during conversion time

Regardless of the setting, caching is always enabled for GLSL materials.
---
 source/blender/makesdna/DNA_scene_types.h                 |  1 +
 source/blender/makesrna/intern/rna_scene.c                |  5 +++++
 source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp |  2 ++
 source/gameengine/Converter/BL_BlenderDataConversion.cpp  |  6 +++++-
 source/gameengine/Converter/KX_BlenderSceneConverter.cpp  | 13 ++++++++++++-
 source/gameengine/Converter/KX_BlenderSceneConverter.h    |  5 +++++
 source/gameengine/GamePlayer/ghost/GPG_Application.cpp    |  2 ++
 source/gameengine/Ketsji/KX_ISceneConverter.h             |  4 ++++
 8 files changed, 36 insertions(+), 2 deletions(-)

(limited to 'source')

diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 5e06a3084ac..5af116df772 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -693,6 +693,7 @@ typedef struct GameData {
 #define GAME_SHOW_MOUSE						(1 << 14)
 #define GAME_GLSL_NO_COLOR_MANAGEMENT		(1 << 15)
 #define GAME_SHOW_OBSTACLE_SIMULATION		(1 << 16)
+#define GAME_NO_MATERIAL_CACHING			(1 << 17)
 /* Note: GameData.flag is now an int (max 32 flags). A short could only take 16 flags */
 
 /* GameData.playerflag */
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 1ead8e6e975..8a295e883e1 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -2776,6 +2776,11 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
 	                         "Use extra textures like normal or specular maps for GLSL rendering");
 	RNA_def_property_update(prop, NC_SCENE | NA_EDITED, "rna_Scene_glsl_update");
 
+	prop = RNA_def_property(srna, "use_material_caching", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", GAME_NO_MATERIAL_CACHING);
+	RNA_def_property_ui_text(prop, "Use Material Caching",
+							 "Cache materials in the converter. This is faster, but can cause propblems with older Singletexture and Multitexture games");
+
 	/* obstacle simulation */
 	prop = RNA_def_property(srna, "obstacle_simulation", PROP_ENUM, PROP_NONE);
 	RNA_def_property_enum_sdna(prop, NULL, "obstacleSimulation");
diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
index 482700d5958..176dc33d057 100644
--- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
+++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
@@ -468,6 +468,8 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c
 				sceneconverter->SetMaterials(true);
 			if (useglslmat && (gs.matmode == GAME_MAT_GLSL))
 				sceneconverter->SetGLSLMaterials(true);
+			if (scene->gm.flag & GAME_NO_MATERIAL_CACHING)
+				sceneconverter->SetCacheMaterials(false);
 					
 			KX_Scene* startscene = new KX_Scene(keyboarddevice,
 				mousedevice,
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index 874bf614413..d0d6f9cb81c 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -922,6 +922,9 @@ static RAS_MaterialBucket *material_from_mesh(Material *ma, MFace *mface, MTFace
 		/* do Texture Face materials */
 		Image* bima = (tface)? (Image*)tface->tpage: NULL;
 		STR_String imastr =  (tface)? (bima? (bima)->id.name : "" ) : "";
+
+		if (!converter->GetCacheMaterials())
+			polymat = NULL;
 		
 		char alpha_blend=0;
 		short tile=0;
@@ -1044,7 +1047,8 @@ static RAS_MaterialBucket *material_from_mesh(Material *ma, MFace *mface, MTFace
 				polymat->m_shininess = 35.0;
 			}
 			
-			converter->CachePolyMaterial(ma, polymat);
+			if (converter->GetCacheMaterials())
+				converter->CachePolyMaterial(ma, polymat);
 		}
 	}
 	
diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
index ceaa0a5f5a8..5524612f707 100644
--- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
+++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
@@ -131,7 +131,8 @@ KX_BlenderSceneConverter::KX_BlenderSceneConverter(
 							m_ketsjiEngine(engine),
 							m_alwaysUseExpandFraming(false),
 							m_usemat(false),
-							m_useglslmat(false)
+							m_useglslmat(false),
+							m_use_mat_cache(true)
 {
 	tag_main(maggie, 0); /* avoid re-tagging later on */
 	m_newfilename = "";
@@ -488,6 +489,11 @@ void KX_BlenderSceneConverter::SetGLSLMaterials(bool val)
 	m_useglslmat = val;
 }
 
+void KX_BlenderSceneConverter::SetCacheMaterials(bool val)
+{
+	m_use_mat_cache = val;
+}
+
 bool KX_BlenderSceneConverter::GetMaterials()
 {
 	return m_usemat;
@@ -498,6 +504,11 @@ bool KX_BlenderSceneConverter::GetGLSLMaterials()
 	return m_useglslmat;
 }
 
+bool KX_BlenderSceneConverter::GetCacheMaterials()
+{
+	return m_use_mat_cache;
+}
+
 void KX_BlenderSceneConverter::RegisterBlenderMaterial(BL_Material *mat)
 {
 	// First make sure we don't register the material twice
diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.h b/source/gameengine/Converter/KX_BlenderSceneConverter.h
index f7723350eee..06dac1707c5 100644
--- a/source/gameengine/Converter/KX_BlenderSceneConverter.h
+++ b/source/gameengine/Converter/KX_BlenderSceneConverter.h
@@ -91,6 +91,7 @@ class KX_BlenderSceneConverter : public KX_ISceneConverter
 	bool					m_alwaysUseExpandFraming;
 	bool					m_usemat;
 	bool					m_useglslmat;
+	bool					m_use_mat_cache;
 
 public:
 	KX_BlenderSceneConverter(
@@ -160,6 +161,10 @@ public:
 	virtual void SetGLSLMaterials(bool val);
 	virtual bool GetGLSLMaterials();
 
+	// cache materials during conversion
+	virtual void SetCacheMaterials(bool val);
+	virtual bool GetCacheMaterials();
+
 	struct Scene* GetBlenderSceneForName(const STR_String& name);
 
 //	struct Main* GetMain() { return m_maggie; }
diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
index 1dcc68c8e75..89d11515bb3 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
@@ -703,6 +703,8 @@ bool GPG_Application::startEngine(void)
 			m_sceneconverter->SetMaterials(true);
 		if (m_blenderglslmat && (m_globalSettings->matmode == GAME_MAT_GLSL))
 			m_sceneconverter->SetGLSLMaterials(true);
+		if (m_startScene->gm.flag & GAME_NO_MATERIAL_CACHING)
+			m_sceneconverter->SetCacheMaterials(false);
 
 		KX_Scene* startscene = new KX_Scene(m_keyboard,
 			m_mouse,
diff --git a/source/gameengine/Ketsji/KX_ISceneConverter.h b/source/gameengine/Ketsji/KX_ISceneConverter.h
index 7c1d593a81e..616895a8269 100644
--- a/source/gameengine/Ketsji/KX_ISceneConverter.h
+++ b/source/gameengine/Ketsji/KX_ISceneConverter.h
@@ -89,6 +89,10 @@ public:
 	virtual void SetGLSLMaterials(bool val) =0;
 	virtual bool GetGLSLMaterials()=0;
 
+	// cache materials during conversion
+	virtual void SetCacheMaterials(bool val) =0;
+	virtual bool GetCacheMaterials()=0;
+
 	virtual struct Scene* GetBlenderSceneForName(const STR_String& name)=0;
 	
 	
-- 
cgit v1.2.3


From 8ac1d8a4eafe4988ae6c6049bb0ebd40381e46ae Mon Sep 17 00:00:00 2001
From: Sergey Sharybin 
Date: Mon, 24 Dec 2012 13:33:47 +0000
Subject: Fix #33650: Compositor locks up when input is an unrendered render
 layer.

Issue was caused by resolution detecting which assumed zero resolution is
undefined one and should be re-evaluated. It doesn't work in cases when
there's a missing input, causing lots of unneeded resolution re-calculation.

It wasn't so much issue in average sized node trees, but it was a real
problem in generated tree from the report.

Currently used pretty simple solution which added a boolean flag to the
node operation which signal whether resolution was ever set or not.

There're probably smarter solutions here but can not think about them.
---
 source/blender/compositor/intern/COM_NodeOperation.cpp | 1 +
 source/blender/compositor/intern/COM_NodeOperation.h   | 8 +++++---
 2 files changed, 6 insertions(+), 3 deletions(-)

(limited to 'source')

diff --git a/source/blender/compositor/intern/COM_NodeOperation.cpp b/source/blender/compositor/intern/COM_NodeOperation.cpp
index a05c37e1b09..d33b8085022 100644
--- a/source/blender/compositor/intern/COM_NodeOperation.cpp
+++ b/source/blender/compositor/intern/COM_NodeOperation.cpp
@@ -34,6 +34,7 @@ NodeOperation::NodeOperation() : NodeBase()
 	this->m_complex = false;
 	this->m_width = 0;
 	this->m_height = 0;
+	this->m_isResolutionSet = false;
 	this->m_openCL = false;
 	this->m_btree = NULL;
 }
diff --git a/source/blender/compositor/intern/COM_NodeOperation.h b/source/blender/compositor/intern/COM_NodeOperation.h
index f856d8e6a11..60ffadf60f7 100644
--- a/source/blender/compositor/intern/COM_NodeOperation.h
+++ b/source/blender/compositor/intern/COM_NodeOperation.h
@@ -81,6 +81,7 @@ private:
 	 */
 	const bNodeTree *m_btree;
 
+	bool m_isResolutionSet;
 public:
 	/**
 	 * @brief is this node an operation?
@@ -170,7 +171,7 @@ public:
 	virtual void deinitExecution();
 
 	bool isResolutionSet() {
-		return this->m_width != 0 && this->m_height != 0;
+		return this->m_isResolutionSet;
 	}
 
 	/**
@@ -181,6 +182,7 @@ public:
 		if (!isResolutionSet()) {
 			this->m_width = resolution[0];
 			this->m_height = resolution[1];
+			this->m_isResolutionSet = true;
 		}
 	}
 	
@@ -254,8 +256,8 @@ public:
 protected:
 	NodeOperation();
 
-	void setWidth(unsigned int width) { this->m_width = width; }
-	void setHeight(unsigned int height) { this->m_height = height; }
+	void setWidth(unsigned int width) { this->m_width = width; this->m_isResolutionSet = true; }
+	void setHeight(unsigned int height) { this->m_height = height; this->m_isResolutionSet = true; }
 	SocketReader *getInputSocketReader(unsigned int inputSocketindex);
 	NodeOperation *getInputOperation(unsigned int inputSocketindex);
 
-- 
cgit v1.2.3


From 128e6d51baebb9e3724cf84538ec074ca3f230b3 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Mon, 24 Dec 2012 14:21:14 +0000
Subject: fix possible bug with ui_item_fit() causing uninitialized variable
 use.

---
 source/blender/editors/interface/interface_layout.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 20f2c52485e..2ba4c1355c0 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -186,13 +186,13 @@ static const char *ui_item_name_add_colon(const char *name, char namestr[UI_MAX_
 
 static int ui_item_fit(int item, int pos, int all, int available, int last, int alignment, int *offset)
 {
+	if (offset)
+		*offset = 0;
+
 	/* available == 0 is unlimited */
 	if (available == 0)
 		return item;
-	
-	if (offset)
-		*offset = 0;
-	
+
 	if (all > available) {
 		/* contents is bigger than available space */
 		if (last)
-- 
cgit v1.2.3


From fb989c2a6531ffb53aad2cb8aba85f974d8e9fcf Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Mon, 24 Dec 2012 14:59:15 +0000
Subject: code cleanup: don't alloca zero size and remove paranoid NULL checks
 (checked all uses and there not needed).

---
 source/blender/blenlib/BLI_path_util.h     | 12 ++++++++++--
 source/blender/blenlib/intern/path_util.c  |  3 ---
 source/blender/bmesh/intern/bmesh_interp.c |  2 +-
 3 files changed, 11 insertions(+), 6 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h
index 557ecb3dd0c..8c51c925d97 100644
--- a/source/blender/blenlib/BLI_path_util.h
+++ b/source/blender/blenlib/BLI_path_util.h
@@ -120,7 +120,11 @@ int BLI_split_name_num(char *left, int *nr, const char *name, const char delim);
 void BLI_splitdirstring(char *di, char *fi);
 
 /* make sure path separators conform to system one */
-void BLI_clean(char *path);
+void BLI_clean(char *path)
+#ifdef __GNUC__
+__attribute__((nonnull(1)))
+#endif
+;
 
 /**
  * dir can be any input, like from buttons, and this function
@@ -173,7 +177,11 @@ int BLI_path_is_rel(const char *path);
  * \a from The character to replace
  * \a to The character to replace with
  */
-void BLI_char_switch(char *string, char from, char to);
+void BLI_char_switch(char *string, char from, char to)
+#ifdef __GNUC__
+__attribute__((nonnull(1)))
+#endif
+;
 
 /* Initialize path to program executable */
 void BLI_init_program_path(const char *argv0);
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index 7c1842b10f2..3c43fe2fb72 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -1212,8 +1212,6 @@ void BLI_setenv_if_new(const char *env, const char *val)
 
 void BLI_clean(char *path)
 {
-	if (path == NULL) return;
-
 #ifdef WIN32
 	if (path && BLI_strnlen(path, 3) > 2) {
 		BLI_char_switch(path + 2, '/', '\\');
@@ -1225,7 +1223,6 @@ void BLI_clean(char *path)
 
 void BLI_char_switch(char *string, char from, char to) 
 {
-	if (string == NULL) return;
 	while (*string != 0) {
 		if (*string == from) *string = to;
 		string++;
diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c
index df58b90bc03..4ec91b8d8d7 100644
--- a/source/blender/bmesh/intern/bmesh_interp.c
+++ b/source/blender/bmesh/intern/bmesh_interp.c
@@ -603,7 +603,7 @@ void BM_loop_interp_from_face(BMesh *bm, BMLoop *target, BMFace *source,
 {
 	BMLoop *l_iter;
 	BMLoop *l_first;
-	void **vblocks  = BLI_array_alloca(vblocks, do_vertex ? source->len : 0);
+	void **vblocks  = do_vertex ? BLI_array_alloca(vblocks, source->len) : NULL;
 	void **blocks   = BLI_array_alloca(blocks,  source->len);
 	float (*cos)[3] = BLI_array_alloca(cos,     source->len);
 	float *w        = BLI_array_alloca(w,       source->len);
-- 
cgit v1.2.3


From 2fe36c0139827aaba2f8aad0caa89cab8796357a Mon Sep 17 00:00:00 2001
From: Sergey Sharybin 
Date: Mon, 24 Dec 2012 15:51:27 +0000
Subject: Separate image input and sequencer's color spaces in the UI

This two things were using the same DNA and RNA structures because
internally they're completely the same. However, that was confusing
from the interface point of view.

Now it should be much more clear what's going on there.
---
 source/blender/editors/interface/interface_templates.c |  2 +-
 source/blender/makesrna/RNA_access.h                   |  3 ++-
 source/blender/makesrna/intern/rna_color.c             | 17 ++++++++++++++---
 source/blender/makesrna/intern/rna_image.c             |  2 +-
 source/blender/makesrna/intern/rna_movieclip.c         |  2 +-
 source/blender/makesrna/intern/rna_scene.c             |  2 +-
 source/blender/makesrna/intern/rna_sequencer.c         |  2 +-
 7 files changed, 21 insertions(+), 9 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 4e0776ee539..5145c28a2cd 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -3080,7 +3080,7 @@ void uiTemplateColorspaceSettings(uiLayout *layout, PointerRNA *ptr, const char
 
 	colorspace_settings_ptr = RNA_property_pointer_get(ptr, prop);
 
-	uiItemL(layout, "Color Space:", ICON_NONE);
+	uiItemL(layout, "Input Color Space:", ICON_NONE);
 	uiItemR(layout, &colorspace_settings_ptr, "name", 0, "", ICON_NONE);
 }
 
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 5f4e4ce4259..7625605c5fb 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -104,7 +104,8 @@ extern StructRNA RNA_CollectionProperty;
 extern StructRNA RNA_CollisionModifier;
 extern StructRNA RNA_CollisionSensor;
 extern StructRNA RNA_CollisionSettings;
-extern StructRNA RNA_ColorManagedColorspaceSettings;
+extern StructRNA RNA_ColorManagedInputColorspaceSettings;
+extern StructRNA RNA_ColorManagedSequencerColorspaceSettings;
 extern StructRNA RNA_ColorManagedDisplaySettings;
 extern StructRNA RNA_ColorManagedViewSettings;
 extern StructRNA RNA_ColorRamp;
diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c
index 5752fd318c7..21bd55e0137 100644
--- a/source/blender/makesrna/intern/rna_color.c
+++ b/source/blender/makesrna/intern/rna_color.c
@@ -973,15 +973,26 @@ static void rna_def_colormanage(BlenderRNA *brna)
 	RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagement_update");
 
 	/* ** Colorspace **  */
-	srna = RNA_def_struct(brna, "ColorManagedColorspaceSettings", NULL);
-	RNA_def_struct_ui_text(srna, "ColorManagedColorspaceSettings", "Input color space settings");
+	srna = RNA_def_struct(brna, "ColorManagedInputColorspaceSettings", NULL);
+	RNA_def_struct_ui_text(srna, "ColorManagedInputColorspaceSettings", "Input color space settings");
 
 	prop = RNA_def_property(srna, "name", PROP_ENUM, PROP_NONE);
 	RNA_def_property_enum_items(prop, color_space_items);
 	RNA_def_property_enum_funcs(prop, "rna_ColorManagedColorspaceSettings_colorspace_get",
 	                                  "rna_ColorManagedColorspaceSettings_colorspace_set",
 	                                  "rna_ColorManagedColorspaceSettings_colorspace_itemf");
-	RNA_def_property_ui_text(prop, "Color Space", "Input color space name");
+	RNA_def_property_ui_text(prop, "Input Color Space", "Color space of the image or movie on disk");
+	RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagedColorspaceSettings_reload_update");
+
+	srna = RNA_def_struct(brna, "ColorManagedSequencerColorspaceSettings", NULL);
+	RNA_def_struct_ui_text(srna, "ColorManagedSequencerColorspaceSettings", "Input color space settings");
+
+	prop = RNA_def_property(srna, "name", PROP_ENUM, PROP_NONE);
+	RNA_def_property_enum_items(prop, color_space_items);
+	RNA_def_property_enum_funcs(prop, "rna_ColorManagedColorspaceSettings_colorspace_get",
+	                                  "rna_ColorManagedColorspaceSettings_colorspace_set",
+	                                  "rna_ColorManagedColorspaceSettings_colorspace_itemf");
+	RNA_def_property_ui_text(prop, "Color Space", "Color space that the sequencer operates in");
 	RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagedColorspaceSettings_reload_update");
 }
 
diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c
index 9fedbee41ff..ad7682b3af5 100644
--- a/source/blender/makesrna/intern/rna_image.c
+++ b/source/blender/makesrna/intern/rna_image.c
@@ -674,7 +674,7 @@ static void rna_def_image(BlenderRNA *brna)
 
 	prop = RNA_def_property(srna, "colorspace_settings", PROP_POINTER, PROP_NONE);
 	RNA_def_property_pointer_sdna(prop, NULL, "colorspace_settings");
-	RNA_def_property_struct_type(prop, "ColorManagedColorspaceSettings");
+	RNA_def_property_struct_type(prop, "ColorManagedInputColorspaceSettings");
 	RNA_def_property_ui_text(prop, "Color Space Settings", "Input color space settings");
 
 	RNA_api_image(srna);
diff --git a/source/blender/makesrna/intern/rna_movieclip.c b/source/blender/makesrna/intern/rna_movieclip.c
index 99effc990a8..3b018591455 100644
--- a/source/blender/makesrna/intern/rna_movieclip.c
+++ b/source/blender/makesrna/intern/rna_movieclip.c
@@ -308,7 +308,7 @@ static void rna_def_movieclip(BlenderRNA *brna)
 	/* color management */
 	prop = RNA_def_property(srna, "colorspace_settings", PROP_POINTER, PROP_NONE);
 	RNA_def_property_pointer_sdna(prop, NULL, "colorspace_settings");
-	RNA_def_property_struct_type(prop, "ColorManagedColorspaceSettings");
+	RNA_def_property_struct_type(prop, "ColorManagedInputColorspaceSettings");
 	RNA_def_property_ui_text(prop, "Color Space Settings", "Input color space settings");
 }
 
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 8a295e883e1..cdf123bf621 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -4670,7 +4670,7 @@ void RNA_def_scene(BlenderRNA *brna)
 
 	prop = RNA_def_property(srna, "sequencer_colorspace_settings", PROP_POINTER, PROP_NONE);
 	RNA_def_property_pointer_sdna(prop, NULL, "sequencer_colorspace_settings");
-	RNA_def_property_struct_type(prop, "ColorManagedColorspaceSettings");
+	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");
 
 	/* Nestled Data  */
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index 18a9b9683f8..5c51f871ac8 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -1694,7 +1694,7 @@ static void rna_def_color_management(StructRNA *srna)
 
 	prop = RNA_def_property(srna, "colorspace_settings", PROP_POINTER, PROP_NONE);
 	RNA_def_property_pointer_sdna(prop, NULL, "strip->colorspace_settings");
-	RNA_def_property_struct_type(prop, "ColorManagedColorspaceSettings");
+	RNA_def_property_struct_type(prop, "ColorManagedInputColorspaceSettings");
 	RNA_def_property_ui_text(prop, "Color Space Settings", "Input color space settings");
 }
 
-- 
cgit v1.2.3


From 58088eca185ed7d5f83a3793043f3c0a59c73f82 Mon Sep 17 00:00:00 2001
From: Bastien Montagne 
Date: Mon, 24 Dec 2012 17:32:38 +0000
Subject: Looks like I forgot to cleanup that file when we switched to dynamic
 i18n languages.

---
 source/blender/makesrna/intern/rna_userdef.c | 56 +---------------------------
 1 file changed, 2 insertions(+), 54 deletions(-)

(limited to 'source')

diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 397453d8408..bb7f7cb8820 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -3018,62 +3018,10 @@ static void rna_def_userdef_system(BlenderRNA *brna)
 		{0, NULL, 0, NULL, NULL}
 	};
 	
-#if 0
-	/* hardcoded here, could become dynamic somehow */
-	/* locale according to http://www.roseindia.net/tutorials/I18N/locales-list.shtml */
-	/* if you edit here, please also edit the source/blender/blenfont/intern/blf_lang.c 's locales */
-	/* Note: As this list is in alphabetical order, and not defined order,
-	 *       here is the highest define currently in use: 35 (Esperanto). */
-	static EnumPropertyItem language_items[] = {
-		{ 0, "", 0, N_("Nearly Done"), ""},
-		{ 0, "DEFAULT", 0, "Default (Default)", ""},
-		/* using the utf8 flipped form of Arabic (العربية) */
-		{21, "ARABIC", 0, "Arabic (ﺔﻴﺑﺮﻌﻟﺍ)", "ar_EG"},
-		{32, "BRAZILIANPORTUGUESE", 0, "Brazilian Portuguese (Português do Brasil)", "pt_BR"},
-		{ 1, "ENGLISH", 0, "English (English)", "en_US"},
-		{ 8, "FRENCH", 0, "French (Français)", "fr_FR"},
-		{ 4, "ITALIAN", 0, "Italian (Italiano)", "it_IT"},
-		{ 2, "JAPANESE", 0, "Japanese (日本語)", "ja_JP"},
-		{12, "PORTUGUESE", 0, "Portuguese (Português)", "pt"},
-		{15, "RUSSIAN", 0, "Russian (Русский)", "ru_RU"},
-		{13, "SIMPLIFIED_CHINESE", 0, "Simplified Chinese (简体中文)", "zh_CN"},
-		{ 9, "SPANISH", 0, "Spanish (Español)", "es"},
-		{14, "TRADITIONAL_CHINESE", 0, "Traditional Chinese (繁體中文)", "zh_TW"},
-		{18, "UKRAINIAN", 0, "Ukrainian (Український)", "uk_UA"},
-		{ 0, "", 0, N_("In Progress"), ""},
-/*		{22, "BULGARIAN", 0, "Bulgarian (Български)", "bg_BG"},*/ /* XXX Not active nor enough translated. */
-/*		{10, "CATALAN", 0, "Catalan (Català)", "ca_AD"},*/ /* XXX Not active nor enough translated. */
-		{16, "CROATIAN", 0, "Croatian (Hrvatski)", "hr_HR"},
-		{11, "CZECH", 0, "Czech (Český)", "cs_CZ"},
-		{ 3, "DUTCH", 0, "Dutch (Nederlandse taal)", "nl_NL"},
-		{35, "ESPERANTO", 0, "Esperanto (Esperanto)", "eo"},
-		{34, "ESTONIAN", 0, "Estonian (Eestlane)", "et_EE"},
-/*		{ 6, "FINNISH", 0, "Finnish (Suomi)", "fi_FI"},*/ /* XXX Not active nor enough translated. */
-		{ 5, "GERMAN", 0, "German (Deutsch)", "de_DE"},
-/*		{23, "GREEK", 0, "Greek (Ελληνικά)", "el_GR"},*/ /* XXX Not active nor enough translated. */
-		/* using the utf8 flipped form of Hebrew (עִבְרִית)) */
-		{33, "HEBREW", 0, "Hebrew (תירִבְעִ)", "he_IL"},
-		{31, "HUNGARIAN", 0, "Hungarian (Magyar)", "hu_HU"},
-		{27, "INDONESIAN", 0, "Indonesian (Bahasa indonesia)", "id_ID"},
-		{29, "KYRGYZ", 0, "Kyrgyz (Кыргыз тили)", "ky_KG"},
-/*		{24, "KOREAN", 0, "Korean (한국 언어)", "ko_KR"}, */ /* XXX Not active nor enough translated. */
-/*		{25, "NEPALI", 0, "Nepali (नेपाली)", "ne_NP"},*/ /* XXX Not active nor enough translated. */
-		/* using the utf8 flipped form of Persian (فارسی) */
-		{26, "PERSIAN", 0, "Persian (ﯽﺳﺭﺎﻓ)", "fa_IR"},
-/*		{19, "POLISH", 0, "Polish (Polski)", "pl_PL"},*/ /* XXX Not active nor enough translated. */
-/*		{20, "ROMANIAN", 0, "Romanian (Român)", "ro_RO"}, */ /* XXX Not active nor enough translated. */
-		{17, "SERBIAN", 0, "Serbian (Српски)", "sr_RS"},
-		{28, "SERBIAN_LATIN", 0, "Serbian Latin (Srpski latinica)", "sr_RS@latin"},
-		{ 7, "SWEDISH", 0, "Swedish (Svenska)", "sv_SE"},
-		{30, "TURKISH", 0, "Turkish (Türkçe)", "tr_TR"},
-		{ 0, NULL, 0, NULL, NULL}
-	};
-#else
 	static EnumPropertyItem language_items[] = {
-		{ 0, "DEFAULT", 0, "Default (Default)", ""},
-		{ 0, NULL, 0, NULL, NULL}
+		{0, "DEFAULT", 0, "Default (Default)", ""},
+		{0, NULL, 0, NULL, NULL}
 	};
-#endif
 
 #ifdef WITH_CYCLES
 	static EnumPropertyItem compute_device_items[] = {
-- 
cgit v1.2.3


From ec4fc2e13244b70f84c6082d109a723e603e7d4a Mon Sep 17 00:00:00 2001
From: Bastien Montagne 
Date: Mon, 24 Dec 2012 17:40:47 +0000
Subject: Usual minor UI messages tweaks...

---
 source/blender/makesrna/intern/rna_scene.c | 22 ++++++++++++++--------
 1 file changed, 14 insertions(+), 8 deletions(-)

(limited to 'source')

diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index cdf123bf621..a15bbb7e988 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -116,7 +116,8 @@ EnumPropertyItem proportional_falloff_curve_only_items[] = {
 EnumPropertyItem proportional_editing_items[] = {
 	{PROP_EDIT_OFF, "DISABLED", ICON_PROP_OFF, "Disable", "Proportional Editing disabled"},
 	{PROP_EDIT_ON, "ENABLED", ICON_PROP_ON, "Enable", "Proportional Editing enabled"},
-	{PROP_EDIT_CONNECTED, "CONNECTED", ICON_PROP_CON, "Connected", "Proportional Editing using connected geometry only"},
+	{PROP_EDIT_CONNECTED, "CONNECTED", ICON_PROP_CON, "Connected",
+	                      "Proportional Editing using connected geometry only"},
 	{0, NULL, 0, NULL, NULL}
 };
 
@@ -1361,7 +1362,8 @@ static void rna_TimeLine_remove(Scene *scene, ReportList *reports, PointerRNA *m
 {
 	TimeMarker *marker = marker_ptr->data;
 	if (BLI_remlink_safe(&scene->markers, marker) == FALSE) {
-		BKE_reportf(reports, RPT_ERROR, "Timeline marker '%s' not found in scene '%s'", marker->name, scene->id.name + 2);
+		BKE_reportf(reports, RPT_ERROR, "Timeline marker '%s' not found in scene '%s'",
+		            marker->name, scene->id.name + 2);
 		return;
 	}
 
@@ -1994,7 +1996,8 @@ void rna_def_render_layer_common(StructRNA *srna, int scene)
 
 	if (scene) {
 		prop = RNA_def_property(srna, "samples", PROP_INT, PROP_UNSIGNED);
-		RNA_def_property_ui_text(prop, "Samples", "Override number of render samples for this render layer, 0 will use the scene setting");
+		RNA_def_property_ui_text(prop, "Samples", "Override number of render samples for this render layer, "
+		                                          "0 will use the scene setting");
 		RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
 	}
 
@@ -2448,8 +2451,10 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
 		{RAS_STORE_AUTO, "AUTO", 0, "Auto Select", "Chooses the best supported mode"},
 		{RAS_STORE_IMMEDIATE, "IMMEDIATE", 0, "Immediate Mode", "Slowest performance, requires OpenGL (any version)"},
 		{RAS_STORE_VA, "VERTEX_ARRAY", 0, "Vertex Arrays", "Better performance, requires at least OpenGL 1.1"},
-		/* VBOS are currently disabled since they cannot beat vertex array with display lists in performance. */
-		/* {RAS_STORE_VBO, "VERTEX_BUFFER_OBJECT", 0, "Vertex Buffer Objects", "Best performance, requires at least OpenGL 1.4"}, */
+#if 0  /* XXX VBOS are currently disabled since they cannot beat vertex array with display lists in performance. */
+		{RAS_STORE_VBO, "VERTEX_BUFFER_OBJECT", 0, "Vertex Buffer Objects",
+		                "Best performance, requires at least OpenGL 1.4"}, 
+#endif
 		{0, NULL, 0, NULL, NULL}};
 
 	srna = RNA_def_struct(brna, "SceneGameData", NULL);
@@ -2484,13 +2489,13 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
 	RNA_def_property_enum_sdna(prop, NULL, "exitkey");
 	RNA_def_property_enum_items(prop, event_type_items);
 	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_ui_text(prop, "Exit Key", "The key that exits the Game Engine");
 	RNA_def_property_update(prop, NC_SCENE, NULL);
 	
 	prop = RNA_def_property(srna, "raster_storage", PROP_ENUM, PROP_NONE);
 	RNA_def_property_enum_sdna(prop, NULL, "raster_storage");
 	RNA_def_property_enum_items(prop, storage_items);
-	RNA_def_property_ui_text(prop, "Storage",  "Sets the storage mode used by the rasterizer");
+	RNA_def_property_ui_text(prop, "Storage", "Set the storage mode used by the rasterizer");
 	RNA_def_property_update(prop, NC_SCENE, NULL);
 	
 	/* Do we need it here ? (since we already have it in World */
@@ -2779,7 +2784,8 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
 	prop = RNA_def_property(srna, "use_material_caching", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", GAME_NO_MATERIAL_CACHING);
 	RNA_def_property_ui_text(prop, "Use Material Caching",
-							 "Cache materials in the converter. This is faster, but can cause propblems with older Singletexture and Multitexture games");
+	                         "Cache materials in the converter (this is faster, but can cause problems with older "
+	                         "Singletexture and Multitexture games");
 
 	/* obstacle simulation */
 	prop = RNA_def_property(srna, "obstacle_simulation", PROP_ENUM, PROP_NONE);
-- 
cgit v1.2.3


From 62b6303735a1bbdb0f978ecf6afc1829d13ebe7b Mon Sep 17 00:00:00 2001
From: Mitchell Stokes 
Date: Tue, 25 Dec 2012 06:20:50 +0000
Subject: BGE: Fixing an assert with the canvas' GetViewPort(). bf_gpu was
 changing the viewport when handling shadow buffers.
 KX_LightObject::BindShadowBuffer() now updates the canvas with the new
 viewport information from bf_gpu.

---
 source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp | 12 ++++++++++++
 source/gameengine/BlenderRoutines/KX_BlenderCanvas.h   |  7 +++++++
 source/gameengine/GamePlayer/common/GPC_Canvas.cpp     | 10 +++++++++-
 source/gameengine/GamePlayer/common/GPC_Canvas.h       |  1 +
 source/gameengine/Ketsji/KX_KetsjiEngine.cpp           |  2 +-
 source/gameengine/Ketsji/KX_Light.cpp                  |  5 ++++-
 source/gameengine/Ketsji/KX_Light.h                    |  2 +-
 source/gameengine/Rasterizer/RAS_ICanvas.h             | 14 +++++++++++++-
 8 files changed, 48 insertions(+), 5 deletions(-)

(limited to 'source')

diff --git a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp
index 346d2017ef0..719041e8d41 100644
--- a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp
+++ b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp
@@ -178,6 +178,18 @@ SetViewPort(
 	glScissor(minx + x1, miny + y1, vp_width, vp_height);
 }
 
+	void
+KX_BlenderCanvas::
+UpdateViewPort(
+	int x1, int y1,
+	int x2, int y2
+) {
+	m_viewport[0] = x1;
+	m_viewport[1] = y1;
+	m_viewport[2] = x2;
+	m_viewport[3] = y2;
+}
+
 	const int*
 KX_BlenderCanvas::
 GetViewPort() {
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h
index 244394a115d..4117c13aede 100644
--- a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h
+++ b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h
@@ -151,6 +151,13 @@ public:
 		int x1, int y1,
 		int x2, int y2
 	);
+
+		void
+	UpdateViewPort(
+		int x1, int y1,
+		int x2, int y2
+	);
+
 		const int*
 	GetViewPort();
 
diff --git a/source/gameengine/GamePlayer/common/GPC_Canvas.cpp b/source/gameengine/GamePlayer/common/GPC_Canvas.cpp
index b5c1c29238a..058454ca352 100644
--- a/source/gameengine/GamePlayer/common/GPC_Canvas.cpp
+++ b/source/gameengine/GamePlayer/common/GPC_Canvas.cpp
@@ -131,7 +131,15 @@ void GPC_Canvas::SetViewPort(int x1, int y1, int x2, int y2)
 
 	glViewport(x1,y1,x2-x1 + 1,y2-y1 + 1);
 	glScissor(x1,y1,x2-x1 + 1,y2-y1 + 1);
-};
+}
+
+void GPC_Canvas::UpdateViewPort(int x1, int y1, int x2, int y2)
+{
+	m_viewport[0] = x1;
+	m_viewport[1] = y1;
+	m_viewport[2] = x2;
+	m_viewport[3] = y2;
+}
 
 const int *GPC_Canvas::GetViewPort()
 {
diff --git a/source/gameengine/GamePlayer/common/GPC_Canvas.h b/source/gameengine/GamePlayer/common/GPC_Canvas.h
index ec5375c0e13..00c5911a8b4 100644
--- a/source/gameengine/GamePlayer/common/GPC_Canvas.h
+++ b/source/gameengine/GamePlayer/common/GPC_Canvas.h
@@ -155,6 +155,7 @@ public:
 	);
 	
 	void SetViewPort(int x1, int y1, int x2, int y2);
+	void UpdateViewPort(int x1, int y1, int x2, int y2);
 	const int *GetViewPort();
 
 	void ClearColor(float r, float g, float b, float a);
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
index 6638b711a1b..f0d5d5c6685 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
@@ -1167,7 +1167,7 @@ void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene)
 			m_rasterizer->SetDrawingMode(RAS_IRasterizer::KX_SHADOW);
 
 			/* binds framebuffer object, sets up camera .. */
-			light->BindShadowBuffer(m_rasterizer, cam, camtrans);
+			light->BindShadowBuffer(m_rasterizer, m_canvas, cam, camtrans);
 
 			/* update scene */
 			scene->CalculateVisibleMeshes(m_rasterizer, cam, light->GetShadowLayer());
diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp
index cf58d18838a..5414a4df0f8 100644
--- a/source/gameengine/Ketsji/KX_Light.cpp
+++ b/source/gameengine/Ketsji/KX_Light.cpp
@@ -236,7 +236,7 @@ int KX_LightObject::GetShadowLayer()
 		return 0;
 }
 
-void KX_LightObject::BindShadowBuffer(RAS_IRasterizer *ras, KX_Camera *cam, MT_Transform& camtrans)
+void KX_LightObject::BindShadowBuffer(RAS_IRasterizer *ras, RAS_ICanvas *canvas, KX_Camera *cam, MT_Transform& camtrans)
 {
 	GPULamp *lamp;
 	float viewmat[4][4], winmat[4][4];
@@ -246,6 +246,9 @@ void KX_LightObject::BindShadowBuffer(RAS_IRasterizer *ras, KX_Camera *cam, MT_T
 	lamp = GetGPULamp();
 	GPU_lamp_shadow_buffer_bind(lamp, viewmat, &winsize, winmat);
 
+	/* GPU_lamp_shadow_buffer_bind() changes the viewport, so update the canvas */
+	canvas->UpdateViewPort(0, 0, winsize, winsize);
+
 	/* setup camera transformation */
 	MT_Matrix4x4 modelviewmat((float*)viewmat);
 	MT_Matrix4x4 projectionmat((float*)winmat);
diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h
index 52f076c772a..f88fc7f6a1b 100644
--- a/source/gameengine/Ketsji/KX_Light.h
+++ b/source/gameengine/Ketsji/KX_Light.h
@@ -64,7 +64,7 @@ public:
 	struct GPULamp *GetGPULamp();
 	bool HasShadowBuffer();
 	int GetShadowLayer();
-	void BindShadowBuffer(class RAS_IRasterizer *ras, class KX_Camera *cam, class MT_Transform& camtrans);
+	void BindShadowBuffer(class RAS_IRasterizer *ras, class RAS_ICanvas *canvas, class KX_Camera *cam, class MT_Transform& camtrans);
 	void UnbindShadowBuffer(class RAS_IRasterizer *ras);
 	struct Image *GetTextureImage(short texslot);
 	void Update();
diff --git a/source/gameengine/Rasterizer/RAS_ICanvas.h b/source/gameengine/Rasterizer/RAS_ICanvas.h
index 60b9f052075..63ad7892aa5 100644
--- a/source/gameengine/Rasterizer/RAS_ICanvas.h
+++ b/source/gameengine/Rasterizer/RAS_ICanvas.h
@@ -178,7 +178,19 @@ public:
 	SetViewPort(
 		int x1, int y1,
 		int x2, int y2
-	) = 0; 
+	) = 0;
+
+	/**
+	 * Update the Canvas' viewport (used when the viewport changes without using SetViewPort()
+	 * eg: Shadow buffers and FBOs
+	 */
+
+	virtual
+		void
+	UpdateViewPort(
+		int x1, int y1,
+		int x2, int y2
+	) = 0;
 
 	/**
 	 * Get the visible viewport
-- 
cgit v1.2.3


From a418dfb98c34914fde81bdde9b10967fd05ae648 Mon Sep 17 00:00:00 2001
From: Mitchell Stokes 
Date: Tue, 25 Dec 2012 06:31:42 +0000
Subject: BGE: Committing SolarLune's patch to allow a minimum shadow buffer
 size of 128 (down from 512).

---
 source/blender/makesrna/intern/rna_lamp.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'source')

diff --git a/source/blender/makesrna/intern/rna_lamp.c b/source/blender/makesrna/intern/rna_lamp.c
index af39500442d..660f6fc6ab7 100644
--- a/source/blender/makesrna/intern/rna_lamp.c
+++ b/source/blender/makesrna/intern/rna_lamp.c
@@ -54,7 +54,7 @@ static void rna_Lamp_buffer_size_set(PointerRNA *ptr, int value)
 {
 	Lamp *la = (Lamp *)ptr->data;
 
-	CLAMP(value, 512, 10240);
+	CLAMP(value, 128, 10240);
 	la->bufsize = value;
 	la->bufsize &= (~15); /* round to multiple of 16 */
 }
@@ -540,7 +540,7 @@ static void rna_def_lamp_shadow(StructRNA *srna, int spot, int area)
 
 	prop = RNA_def_property(srna, "shadow_buffer_size", PROP_INT, PROP_NONE);
 	RNA_def_property_int_sdna(prop, NULL, "bufsize");
-	RNA_def_property_range(prop, 512, 10240);
+	RNA_def_property_range(prop, 128, 10240);
 	RNA_def_property_ui_text(prop, "Shadow Buffer Size",
 	                         "Resolution of the shadow buffer, higher values give crisper shadows "
 	                         "but use more memory");
-- 
cgit v1.2.3


From f1270153e1efcd2c6ca1370a06691b0ccb3a9686 Mon Sep 17 00:00:00 2001
From: Mitchell Stokes 
Date: Tue, 25 Dec 2012 08:11:21 +0000
Subject: BGE: Some various tweaks to try and get async lib loading to be a bit
 more stable on more complex scenes.

---
 .../Converter/BL_BlenderDataConversion.cpp         | 10 +++++-----
 .../gameengine/Converter/KX_ConvertControllers.cpp |  6 +++++-
 source/gameengine/Ketsji/KX_Scene.cpp              | 23 ++++++++++++++++------
 3 files changed, 27 insertions(+), 12 deletions(-)

(limited to 'source')

diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index d0d6f9cb81c..a873f8ba281 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -1349,11 +1349,7 @@ static float my_boundbox_mesh(Mesh *me, float *loc, float *size)
 	int a;
 	
 	if (me->bb==0) {
-		// This can be called in a seperate (not main) thread when doing async libload,
-		// so lets try to be safe...
-		BLI_begin_threaded_malloc();
-		me->bb= (struct BoundBox *)MEM_callocN(sizeof(BoundBox), "boundbox");
-		BLI_end_threaded_malloc();
+		me->bb = BKE_boundbox_alloc_unit();
 	}
 	bb= me->bb;
 	
@@ -2364,6 +2360,10 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
 	set allblobj;	// all objects converted
 	set groupobj;	// objects from groups (never in active layer)
 
+	// This is bad, but we use this to make sure the first time this is called
+	// is not in a separate thread.
+	BL_Texture::GetMaxUnits();
+
 	if (alwaysUseExpandFraming) {
 		frame_type = RAS_FrameSettings::e_frame_extend;
 		aspect_width = canvas->GetWidth();
diff --git a/source/gameengine/Converter/KX_ConvertControllers.cpp b/source/gameengine/Converter/KX_ConvertControllers.cpp
index 769abd01ce0..5d3d0f33bec 100644
--- a/source/gameengine/Converter/KX_ConvertControllers.cpp
+++ b/source/gameengine/Converter/KX_ConvertControllers.cpp
@@ -157,7 +157,7 @@ void BL_ConvertControllers(
 				SCA_PythonController* pyctrl = new SCA_PythonController(gameobj, pycont->mode);
 				gamecontroller = pyctrl;
 #ifdef WITH_PYTHON
-
+				PyGILState_STATE gstate = PyGILState_Ensure();
 				pyctrl->SetNamespace(converter->GetPyNamespace());
 				
 				if (pycont->mode==SCA_PythonController::SCA_PYEXEC_SCRIPT) {
@@ -186,6 +186,7 @@ void BL_ConvertControllers(
 					}
 				}
 				
+				PyGILState_Release(gstate);
 #endif // WITH_PYTHON
 
 				break;
@@ -218,6 +219,7 @@ void BL_ConvertControllers(
 			converter->RegisterGameController(gamecontroller, bcontr);
 
 #ifdef WITH_PYTHON
+			PyGILState_STATE gstate = PyGILState_Ensure();
 			if (bcontr->type==CONT_PYTHON) {
 				SCA_PythonController *pyctrl= static_cast(gamecontroller);
 				/* not strictly needed but gives syntax errors early on and
@@ -232,6 +234,8 @@ void BL_ConvertControllers(
 					// pyctrl->Import();
 				}
 			}
+
+			PyGILState_Release(gstate);
 #endif // WITH_PYTHON
 
 			//done with gamecontroller
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index 72be5f57b95..9483b864d52 100644
--- a/source/gameengine/Ketsji/KX_Scene.cpp
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -227,7 +227,7 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice,
 	}
 	
 #ifdef WITH_PYTHON
-	m_attr_dict = PyDict_New(); /* new ref */
+	m_attr_dict = NULL;
 	m_draw_call_pre = NULL;
 	m_draw_call_post = NULL;
 #endif
@@ -287,9 +287,11 @@ KX_Scene::~KX_Scene()
 	}
 
 #ifdef WITH_PYTHON
-	PyDict_Clear(m_attr_dict);
-	/* Py_CLEAR: Py_DECREF's and NULL's */
-	Py_CLEAR(m_attr_dict);
+	if (m_attr_dict) {
+		PyDict_Clear(m_attr_dict);
+		/* Py_CLEAR: Py_DECREF's and NULL's */
+		Py_CLEAR(m_attr_dict);
+	}
 
 	/* these may be NULL but the macro checks */
 	Py_CLEAR(m_draw_call_pre);
@@ -2062,6 +2064,9 @@ static PyObject *Map_GetItem(PyObject *self_v, PyObject *item)
 		PyErr_SetString(PyExc_SystemError, "val = scene[key]: KX_Scene, "BGE_PROXY_ERROR_MSG);
 		return NULL;
 	}
+
+	if (!self->m_attr_dict)
+		self->m_attr_dict = PyDict_New();
 	
 	if (self->m_attr_dict && (pyconvert=PyDict_GetItem(self->m_attr_dict, item))) {
 		
@@ -2089,7 +2094,10 @@ static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val)
 		PyErr_SetString(PyExc_SystemError, "scene[key] = value: KX_Scene, "BGE_PROXY_ERROR_MSG);
 		return -1;
 	}
-	
+
+	if (!self->m_attr_dict)
+		self->m_attr_dict = PyDict_New();
+
 	if (val==NULL) { /* del ob["key"] */
 		int del= 0;
 		
@@ -2133,7 +2141,10 @@ static int Seq_Contains(PyObject *self_v, PyObject *value)
 		PyErr_SetString(PyExc_SystemError, "val in scene: KX_Scene, "BGE_PROXY_ERROR_MSG);
 		return -1;
 	}
-	
+
+	if (!self->m_attr_dict)
+		self->m_attr_dict = PyDict_New();
+
 	if (self->m_attr_dict && PyDict_GetItem(self->m_attr_dict, value))
 		return 1;
 	
-- 
cgit v1.2.3


From 7e580ed90642ec005fe434a96dc6200558c6343b Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Tue, 25 Dec 2012 14:03:28 +0000
Subject: weight paint without depth buffer option, works with vertex selection
 mode.

---
 source/blender/editors/sculpt_paint/paint_vertex.c | 182 +++++++++++++--------
 1 file changed, 114 insertions(+), 68 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 63f5b7e6904..3981114c349 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -2185,6 +2185,13 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
 	float alpha;
 	float mval[2];
 	int use_vert_sel;
+	int use_zbuf;
+
+	MDeformWeight *(*dw_func)(MDeformVert *, const int) =
+	        (brush->vertexpaint_tool == PAINT_BLEND_BLUR) ?
+	        ((wp->flag & VP_ONLYVGROUP) ?
+	             (MDeformWeight *(*)(MDeformVert *, const int))defvert_find_index :
+	              defvert_verify_index) : NULL;
 
 	const float pressure = RNA_float_get(itemptr, "pressure");
 	const float brush_size_pressure = BKE_brush_size_get(scene, brush) * (BKE_brush_use_size_pressure(scene, brush) ? pressure : 1.0f);
@@ -2242,31 +2249,37 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
 	swap_m4m4(wpd->vc.rv3d->persmat, mat);
 
 	use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
+	use_zbuf = use_vert_sel && (vc->v3d->flag & V3D_ZBUF_SELECT);
 
 	/* which faces are involved */
-	if (wp->flag & VP_AREA) {
-		/* Ugly hack, to avoid drawing vertex index when getting the face index buffer - campbell */
-		me->editflag &= ~ME_EDIT_PAINT_VERT_SEL;
-		totindex = sample_backbuf_area(vc, indexar, me->totpoly, mval[0], mval[1], brush_size_pressure);
-		me->editflag |= use_vert_sel ? ME_EDIT_PAINT_VERT_SEL : 0;
-	}
-	else {
-		indexar[0] = view3d_sample_backbuf(vc, mval[0], mval[1]);
-		if (indexar[0]) totindex = 1;
-		else totindex = 0;
-	}
+	if (use_zbuf) {
+		if (wp->flag & VP_AREA) {
+			/* Ugly hack, to avoid drawing vertex index when getting the face index buffer - campbell */
+			me->editflag &= ~ME_EDIT_PAINT_VERT_SEL;
+			totindex = sample_backbuf_area(vc, indexar, me->totpoly, mval[0], mval[1], brush_size_pressure);
+			me->editflag |= use_vert_sel ? ME_EDIT_PAINT_VERT_SEL : 0;
+		}
+		else {
+			indexar[0] = view3d_sample_backbuf(vc, mval[0], mval[1]);
+			if (indexar[0]) totindex = 1;
+			else totindex = 0;
+		}
 
-	if ((me->editflag & ME_EDIT_PAINT_FACE_SEL) && me->mpoly) {
-		for (index = 0; index < totindex; index++) {
-			if (indexar[index] && indexar[index] <= me->totpoly) {
-				MPoly *mpoly = ((MPoly *)me->mpoly) + (indexar[index] - 1);
-						
-				if ((mpoly->flag & ME_FACE_SEL) == 0) {
-					indexar[index] = 0;
+		if ((me->editflag & ME_EDIT_PAINT_FACE_SEL) && me->mpoly) {
+			for (index = 0; index < totindex; index++) {
+				if (indexar[index] && indexar[index] <= me->totpoly) {
+					MPoly *mpoly = ((MPoly *)me->mpoly) + (indexar[index] - 1);
+
+					if ((mpoly->flag & ME_FACE_SEL) == 0) {
+						indexar[index] = 0;
+					}
 				}
 			}
 		}
 	}
+	else {
+		indexar = NULL;
+	}
 
 	/* make sure each vertex gets treated only once */
 	/* and calculate filter weight */
@@ -2275,80 +2288,113 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
 		paintweight = 0.0f;
 	else
 		paintweight = BKE_brush_weight_get(scene, brush);
-			
-	for (index = 0; index < totindex; index++) {
-		if (indexar[index] && indexar[index] <= me->totpoly) {
-			MPoly *mpoly = me->mpoly + (indexar[index] - 1);
-			MLoop *ml = me->mloop + mpoly->loopstart;
-			int i;
 
-			if (use_vert_sel) {
-				for (i = 0; i < mpoly->totloop; i++, ml++) {
-					me->dvert[ml->v].flag = (me->mvert[ml->v].flag & SELECT);
+#define WP_BLUR_ACCUM(v_idx_var)  \
+	{ \
+		const unsigned int vidx = v_idx_var; \
+		const float fac = calc_vp_strength_dl(wp, vc, wpd->vertexcosnos[vidx].co, mval, brush_size_pressure); \
+		if (fac > 0.0f) { \
+			MDeformWeight *dw = dw_func(&me->dvert[vidx], wpi.vgroup_active); \
+			paintweight += dw ? (dw->weight * fac) : 0.0f; \
+			totw += fac; \
+		} \
+	} (void)0
+
+
+	if (use_zbuf) {
+		for (index = 0; index < totindex; index++) {
+			if (indexar[index] && indexar[index] <= me->totpoly) {
+				MPoly *mpoly = me->mpoly + (indexar[index] - 1);
+				MLoop *ml = me->mloop + mpoly->loopstart;
+				int i;
+
+				if (use_vert_sel) {
+					for (i = 0; i < mpoly->totloop; i++, ml++) {
+						me->dvert[ml->v].flag = (me->mvert[ml->v].flag & SELECT);
+					}
 				}
-			}
-			else {
-				for (i = 0; i < mpoly->totloop; i++, ml++) {
-					me->dvert[ml->v].flag = 1;
+				else {
+					for (i = 0; i < mpoly->totloop; i++, ml++) {
+						me->dvert[ml->v].flag = 1;
+					}
 				}
-			}
-					
-			if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
-				MDeformWeight *dw, *(*dw_func)(MDeformVert *, const int);
-						
-				if (wp->flag & VP_ONLYVGROUP)
-					dw_func = (MDeformWeight *(*)(MDeformVert *, const int))defvert_find_index;
-				else
-					dw_func = defvert_verify_index;
-						
-				ml = me->mloop + mpoly->loopstart;
-				for (i = 0; i < mpoly->totloop; i++, ml++) {
-					unsigned int vidx = ml->v;
-					const float fac = calc_vp_strength_dl(wp, vc, wpd->vertexcosnos[vidx].co, mval, brush_size_pressure);
-					if (fac > 0.0f) {
-						dw = dw_func(&me->dvert[vidx], wpi.vgroup_active);
-						paintweight += dw ? (dw->weight * fac) : 0.0f;
-						totw += fac;
+
+				if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
+					ml = me->mloop + mpoly->loopstart;
+					for (i = 0; i < mpoly->totloop; i++, ml++) {
+						WP_BLUR_ACCUM(ml->v);
 					}
 				}
 			}
 		}
 	}
-			
+	else {
+		const unsigned int totvert = me->totvert;
+		unsigned int       i;
+
+		for (i = 0; i < totvert; i++) {
+			me->dvert[i].flag = (me->mvert[i].flag & SELECT);
+		}
+
+		if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
+			for (i = 0; i < totvert; i++) {
+				WP_BLUR_ACCUM(i);
+			}
+		}
+	}
+
+#undef WP_BLUR_ACCUM
+
+
 	if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
 		paintweight /= totw;
 	}
 
-	for (index = 0; index < totindex; index++) {
+#define WP_PAINT(v_idx_var)  \
+	{ \
+		unsigned int vidx = v_idx_var; \
+		if (me->dvert[vidx].flag) { \
+			alpha = calc_vp_alpha_dl(wp, vc, wpd->wpimat, &wpd->vertexcosnos[vidx], \
+			                         mval, brush_size_pressure, brush_alpha_pressure); \
+			if (alpha) { \
+				do_weight_paint_vertex(wp, ob, &wpi, vidx, alpha, paintweight); \
+			} \
+			me->dvert[vidx].flag = 0; \
+		} \
+	} (void)0
+
+	if (use_zbuf) {
+		for (index = 0; index < totindex; index++) {
 
-		if (indexar[index] && indexar[index] <= me->totpoly) {
-			MPoly *mpoly = me->mpoly + (indexar[index] - 1);
-			MLoop *ml = me->mloop + mpoly->loopstart;
-			int i;
-
-			for (i = 0; i < mpoly->totloop; i++, ml++) {
-				unsigned int vidx = ml->v;
-
-				if (me->dvert[vidx].flag) {
-					alpha = calc_vp_alpha_dl(wp, vc, wpd->wpimat, &wpd->vertexcosnos[vidx],
-					                         mval, brush_size_pressure, brush_alpha_pressure);
-					if (alpha) {
-						do_weight_paint_vertex(wp, ob, &wpi, vidx, alpha, paintweight);
-					}
-					me->dvert[vidx].flag = 0;
+			if (indexar[index] && indexar[index] <= me->totpoly) {
+				MPoly *mpoly = me->mpoly + (indexar[index] - 1);
+				MLoop *ml = me->mloop + mpoly->loopstart;
+				int i;
+
+				for (i = 0; i < mpoly->totloop; i++, ml++) {
+					WP_PAINT(ml->v);
 				}
 			}
 		}
 	}
+	else {
+		const unsigned int totvert = me->totvert;
+		unsigned int       i;
+
+		for (i = 0; i < totvert; i++) {
+			WP_PAINT(i);
+		}
+	}
+#undef WP_PAINT
 
 
 	/* *** free wpi members */
 	MEM_freeN((void *)wpi.defbase_sel);
-	/* *** don't freeing wpi members */
+	/* *** done freeing wpi members */
 
 
 	swap_m4m4(vc->rv3d->persmat, mat);
-			
+
 	DAG_id_tag_update(ob->data, 0);
 	ED_region_tag_redraw(vc->ar);
 }
-- 
cgit v1.2.3


From 2c38c32661427b48e548f27f538a15ff2543b84a Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Tue, 25 Dec 2012 14:09:51 +0000
Subject: make weight paint respect box & near clipping.

also replace strncmp with BLI_path_ncmp for BLI_rebase_path, (so its case insensitive on windows)
---
 source/blender/blenlib/intern/path_util.c          | 2 +-
 source/blender/editors/sculpt_paint/paint_vertex.c | 5 ++++-
 2 files changed, 5 insertions(+), 2 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index 3c43fe2fb72..06b1f1f09b1 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -1619,7 +1619,7 @@ int BLI_rebase_path(char *abs, size_t abs_len, char *rel, size_t rel_len, const
 	rel_dir[0] = 0;
 
 	/* if image is "below" current .blend file directory */
-	if (!strncmp(path, blend_dir, len)) {
+	if (!BLI_path_ncmp(path, blend_dir, len)) {
 
 		/* if image is _in_ current .blend file directory */
 		if (BLI_path_cmp(dir, blend_dir) == 0) {
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 3981114c349..bc1d0cd2f69 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -868,7 +868,10 @@ static float calc_vp_strength_dl(VPaint *vp, ViewContext *vc, const float co[3],
 {
 	float vertco[2];
 
-	if (ED_view3d_project_float_global(vc->ar, co, vertco, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+	if (ED_view3d_project_float_global(vc->ar,
+	                                   co, vertco,
+	                                   V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
+	{
 		float delta[2];
 		float dist_squared;
 
-- 
cgit v1.2.3


From 13f49f31017f40c137f16183780e1c706598ab2a Mon Sep 17 00:00:00 2001
From: Mitchell Stokes 
Date: Wed, 26 Dec 2012 01:25:53 +0000
Subject: BGE: Adding a maxJumps to the character controller to adjust how many
 jumps a character can perform before having to touch the ground. By default
 this is set to 1, which means a character can only jump once before having to
 touch the ground again. Setting this to 2 allows for double jumping.

---
 source/gameengine/Ketsji/KX_CharacterWrapper.cpp   | 22 ++++++++
 source/gameengine/Ketsji/KX_CharacterWrapper.h     |  2 +
 .../Physics/Bullet/CcdPhysicsController.cpp        | 61 +++++++++++++++-------
 .../Physics/Bullet/CcdPhysicsController.h          | 23 +++++++-
 .../Physics/Bullet/CcdPhysicsEnvironment.cpp       | 16 ++++--
 source/gameengine/Physics/common/PHY_ICharacter.h  |  3 ++
 6 files changed, 104 insertions(+), 23 deletions(-)

(limited to 'source')

diff --git a/source/gameengine/Ketsji/KX_CharacterWrapper.cpp b/source/gameengine/Ketsji/KX_CharacterWrapper.cpp
index ce208f3a75f..dfd19a0d2bd 100644
--- a/source/gameengine/Ketsji/KX_CharacterWrapper.cpp
+++ b/source/gameengine/Ketsji/KX_CharacterWrapper.cpp
@@ -45,6 +45,7 @@ PyTypeObject KX_CharacterWrapper::Type = {
 PyAttributeDef KX_CharacterWrapper::Attributes[] = {
 	KX_PYATTRIBUTE_RO_FUNCTION("onGround", KX_CharacterWrapper, pyattr_get_onground),
 	KX_PYATTRIBUTE_RW_FUNCTION("gravity", KX_CharacterWrapper, pyattr_get_gravity, pyattr_set_gravity),
+	KX_PYATTRIBUTE_RW_FUNCTION("maxJumps", KX_CharacterWrapper, pyattr_get_max_jumps, pyattr_set_max_jumps),
 	{ NULL }	//Sentinel
 };
 
@@ -77,6 +78,27 @@ int KX_CharacterWrapper::pyattr_set_gravity(void *self_v, const KX_PYATTRIBUTE_D
 	return PY_SET_ATTR_SUCCESS;
 }
 
+PyObject *KX_CharacterWrapper::pyattr_get_max_jumps(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_CharacterWrapper* self = static_cast(self_v);
+
+	return PyLong_FromLong(self->m_character->GetMaxJumps());
+}
+
+int KX_CharacterWrapper::pyattr_set_max_jumps(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+	KX_CharacterWrapper* self = static_cast(self_v);
+	long param = PyLong_AsLong(value);
+
+	if (param == -1)
+	{
+		PyErr_SetString(PyExc_ValueError, "KX_CharacterWrapper.maxJumps: expected an integer");
+		return PY_SET_ATTR_FAIL;
+	}
+
+	self->m_character->SetMaxJumps((int)param);
+	return PY_SET_ATTR_SUCCESS;
+}
 PyMethodDef KX_CharacterWrapper::Methods[] = {
 	KX_PYMETHODTABLE_NOARGS(KX_CharacterWrapper, jump),
 	{NULL,NULL} //Sentinel
diff --git a/source/gameengine/Ketsji/KX_CharacterWrapper.h b/source/gameengine/Ketsji/KX_CharacterWrapper.h
index 3b0058aca6f..1161be2c611 100644
--- a/source/gameengine/Ketsji/KX_CharacterWrapper.h
+++ b/source/gameengine/Ketsji/KX_CharacterWrapper.h
@@ -26,6 +26,8 @@ public:
 	
 	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);
+	static PyObject*	pyattr_get_max_jumps(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static int			pyattr_set_max_jumps(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
 #endif // WITH_PYTHON
 
 private:
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
index a1b30ccb001..5a6e90cddd5 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
@@ -68,6 +68,48 @@ float gAngularSleepingTreshold;
 
 btVector3 startVel(0,0,0);//-10000);
 
+BlenderBulletCharacterController::BlenderBulletCharacterController(btMotionState *motionState, btPairCachingGhostObject *ghost, btConvexShape* shape, float stepHeight)
+	: btKinematicCharacterController(ghost,shape,stepHeight,2),
+		m_motionState(motionState),
+		m_jumps(0),
+		m_maxJumps(1)
+{
+}
+
+void BlenderBulletCharacterController::updateAction(btCollisionWorld *collisionWorld, btScalar dt)
+{
+	btKinematicCharacterController::updateAction(collisionWorld,dt);
+	m_motionState->setWorldTransform(getGhostObject()->getWorldTransform());
+}
+
+int BlenderBulletCharacterController::getMaxJumps() const
+{
+	return m_maxJumps;
+}
+
+void BlenderBulletCharacterController::setMaxJumps(int maxJumps)
+{
+	m_maxJumps = maxJumps;
+}
+
+bool BlenderBulletCharacterController::canJump() const
+{
+	return onGround() || m_jumps < m_maxJumps;
+}
+
+void BlenderBulletCharacterController::jump()
+{
+	if (onGround())
+		m_jumps = 0;
+
+	if (!canJump())
+		return;
+		
+	m_verticalVelocity = m_jumpSpeed;
+	m_wasJumping = true;
+	m_jumps++;
+}
+
 CcdPhysicsController::CcdPhysicsController (const CcdConstructionInfo& ci)
 :m_cci(ci)
 {
@@ -154,25 +196,6 @@ public:
 
 };
 
-class BlenderBulletCharacterController : public btKinematicCharacterController
-{
-private:
-	btMotionState* m_motionState;
-
-public:
-	BlenderBulletCharacterController(btMotionState *motionState, btPairCachingGhostObject *ghost, btConvexShape* shape, float stepHeight)
-		: btKinematicCharacterController(ghost,shape,stepHeight,2),
-		  m_motionState(motionState)
-	{
-	}
-
-	virtual void updateAction(btCollisionWorld *collisionWorld, btScalar dt)
-	{
-		btKinematicCharacterController::updateAction(collisionWorld,dt);
-		m_motionState->setWorldTransform(getGhostObject()->getWorldTransform());
-	}
-};
-
 btRigidBody* CcdPhysicsController::GetRigidBody()
 {
 	return btRigidBody::upcast(m_object);
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
index 6df5c85f5c0..91b2e558521 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
@@ -391,10 +391,31 @@ struct CcdConstructionInfo
 
 };
 
-
 class btRigidBody;
 class btCollisionObject;
 class btSoftBody;
+class btPairCachingGhostObject;
+
+class BlenderBulletCharacterController : public btKinematicCharacterController
+{
+private:
+	btMotionState* m_motionState;
+	int m_jumps;
+	int m_maxJumps;
+
+public:
+	BlenderBulletCharacterController(btMotionState *motionState, btPairCachingGhostObject *ghost, btConvexShape* shape, float stepHeight);
+
+	virtual void updateAction(btCollisionWorld *collisionWorld, btScalar dt);
+
+	int getMaxJumps() const;
+
+	void setMaxJumps(int maxJumps);
+
+	virtual bool canJump() const;
+
+	virtual void jump();
+};
 
 ///CcdPhysicsController is a physics object that supports continuous collision detection and time of impact based physics resolution.
 class CcdPhysicsController : public PHY_IPhysicsController
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
index 486411d7e35..f1224babcf7 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
@@ -270,10 +270,10 @@ public:
 class CharacterWrapper : public PHY_ICharacter
 {
 private:
-	btKinematicCharacterController* m_controller;
+	BlenderBulletCharacterController* m_controller;
 
 public:
-	CharacterWrapper(btKinematicCharacterController* cont)
+	CharacterWrapper(BlenderBulletCharacterController* cont)
 		: m_controller(cont)
 	{}
 
@@ -295,6 +295,16 @@ public:
 	{
 		m_controller->setGravity(gravity);
 	}
+
+	virtual int GetMaxJumps()
+	{
+		return m_controller->getMaxJumps();
+	}
+
+	virtual void SetMaxJumps(int maxJumps)
+	{
+		m_controller->setMaxJumps(maxJumps);
+	}
 };
 
 class CcdOverlapFilterCallBack : public btOverlapFilterCallback
@@ -2320,7 +2330,7 @@ PHY_ICharacter* CcdPhysicsEnvironment::getCharacterController(KX_GameObject *ob)
 {
 	CcdPhysicsController* controller = (CcdPhysicsController*)ob->GetPhysicsController()->GetUserData();
 	if (controller->GetCharacterController())
-		return new CharacterWrapper(controller->GetCharacterController());
+		return new CharacterWrapper((BlenderBulletCharacterController*)controller->GetCharacterController());
 
 	return NULL;
 }
diff --git a/source/gameengine/Physics/common/PHY_ICharacter.h b/source/gameengine/Physics/common/PHY_ICharacter.h
index e2fc5e45125..92c00949c4d 100644
--- a/source/gameengine/Physics/common/PHY_ICharacter.h
+++ b/source/gameengine/Physics/common/PHY_ICharacter.h
@@ -21,6 +21,9 @@ public:
 
 	virtual float GetGravity()= 0;
 	virtual void SetGravity(float gravity)= 0;
+	
+	virtual int GetMaxJumps()= 0;
+	virtual void SetMaxJumps(int maxJumps)= 0;
 
 #ifdef WITH_CXX_GUARDEDALLOC
 	MEM_CXX_CLASS_ALLOC_FUNCS("GE:PHY_ICharacter")
-- 
cgit v1.2.3


From 4e604642de11603ad1cff1b5b0e679e8a7c13bd9 Mon Sep 17 00:00:00 2001
From: Mitchell Stokes 
Date: Wed, 26 Dec 2012 01:50:01 +0000
Subject: BGE: Don't set the character controller's gravity when creating the
 controller. The default from Bullet works much better than what we were
 using.

---
 source/gameengine/Physics/Bullet/CcdPhysicsController.cpp | 3 ---
 1 file changed, 3 deletions(-)

(limited to 'source')

diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
index 5a6e90cddd5..66c6d1aa251 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
@@ -486,9 +486,6 @@ bool CcdPhysicsController::CreateCharacterController()
 
 	m_characterController = new BlenderBulletCharacterController(m_bulletMotionState,(btPairCachingGhostObject*)m_object,(btConvexShape*)m_collisionShape,m_cci.m_stepHeight);
 
-	PHY__Vector3 gravity;
-	m_cci.m_physicsEnv->getGravity(gravity);
-	m_characterController->setGravity(-gravity.m_vec[2]); // need positive gravity
 	m_characterController->setJumpSpeed(m_cci.m_jumpSpeed);
 	m_characterController->setFallSpeed(m_cci.m_fallSpeed);
 
-- 
cgit v1.2.3


From fa28e50ac2a79e4aa481f659b1457e99f2f17557 Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Wed, 26 Dec 2012 13:05:39 +0000
Subject: Region scrollbar fix!

Now scrollbars correctly hide and show, making space for the actual contents
in a region. It solves several old hacks, and puts view2d code a bit more
back in control as well.

Implementation notes:

- The view2d mask feature is working again
- The #define V2D_SCROLL_HORIZONTAL_HIDE means: "turn on hiding".
- Code for UI_view2d_region_reinit() is enforcing better standard view settings

But... two hack/patches needed to be added:

- Region panel drawing: if after generating the button panels it appears
  a scroller hides or reveils, it calls all the generating code again.
  (a simple scale doesn't work due to rounding differences in layout code)

- View2d code that maps 'tot' and 'cur' rects: if this code detects that
  the mask changes, it calcs the map code again.

Also a bugfix (issue in 2.65)

- The left/bottom area split widget was drawing 1 pixel too large sometimes,
  leaving bad trails on moving area dividers.
---
 source/blender/blenloader/intern/versioning_250.c  |   4 +-
 source/blender/editors/include/UI_interface.h      |   1 +
 source/blender/editors/include/UI_view2d.h         |   1 -
 source/blender/editors/interface/interface.c       |   2 +
 .../blender/editors/interface/interface_handlers.c |  21 +-
 source/blender/editors/interface/interface_panel.c |  30 +-
 source/blender/editors/interface/view2d.c          | 471 +++++++++++----------
 source/blender/editors/interface/view2d_ops.c      |   4 +-
 source/blender/editors/screen/area.c               | 222 +++++-----
 source/blender/editors/space_action/action_draw.c  |  16 +-
 source/blender/editors/space_action/space_action.c |   9 +-
 source/blender/editors/space_file/file_draw.c      |   3 +-
 source/blender/editors/space_graph/space_graph.c   |   6 +
 .../blender/editors/space_outliner/outliner_draw.c |  74 ++--
 .../editors/space_outliner/outliner_intern.h       |   4 +-
 .../editors/space_outliner/space_outliner.c        |  17 +-
 .../editors/space_userpref/space_userpref.c        |   6 +-
 source/blender/makesdna/DNA_view2d_types.h         |   6 +-
 source/blender/windowmanager/intern/wm_window.c    |   1 +
 19 files changed, 463 insertions(+), 435 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c
index 1521739258e..f4d841fd22a 100644
--- a/source/blender/blenloader/intern/versioning_250.c
+++ b/source/blender/blenloader/intern/versioning_250.c
@@ -292,7 +292,7 @@ static void area_add_window_regions(ScrArea *sa, SpaceLink *sl, ListBase *lb)
 					memcpy(&ar->v2d, &soops->v2d, sizeof(View2D));
 
 					ar->v2d.scroll &= ~V2D_SCROLL_LEFT;
-					ar->v2d.scroll |= (V2D_SCROLL_RIGHT|V2D_SCROLL_BOTTOM_O);
+					ar->v2d.scroll |= (V2D_SCROLL_RIGHT|V2D_SCROLL_BOTTOM);
 					ar->v2d.align = (V2D_ALIGN_NO_NEG_X|V2D_ALIGN_NO_POS_Y);
 					ar->v2d.keepzoom |= (V2D_LOCKZOOM_X|V2D_LOCKZOOM_Y|V2D_KEEPASPECT);
 					ar->v2d.keeptot = V2D_KEEPTOT_STRICT;
@@ -415,7 +415,7 @@ static void area_add_window_regions(ScrArea *sa, SpaceLink *sl, ListBase *lb)
 					ar->v2d.tot.ymax = ar->winy;
 					ar->v2d.cur = ar->v2d.tot;
 					ar->regiontype = RGN_TYPE_WINDOW;
-					ar->v2d.scroll = (V2D_SCROLL_RIGHT|V2D_SCROLL_BOTTOM_O);
+					ar->v2d.scroll = (V2D_SCROLL_RIGHT|V2D_SCROLL_BOTTOM);
 					ar->v2d.align = (V2D_ALIGN_NO_NEG_X|V2D_ALIGN_NO_POS_Y);
 					ar->v2d.keepzoom = (V2D_LOCKZOOM_X|V2D_LOCKZOOM_Y|V2D_LIMITZOOM|V2D_KEEPASPECT);
 					break;
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 90f8779b2c7..9a04138e72e 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -658,6 +658,7 @@ void uiDrawPanels(const struct bContext *C, struct ARegion *ar);
 
 struct Panel *uiBeginPanel(struct ScrArea *sa, struct ARegion *ar, uiBlock *block, struct PanelType *pt, int *open);
 void uiEndPanel(uiBlock *block, int width, int height);
+void uiScalePanels(struct ARegion *ar, float new_width);
 
 /* Handlers
  *
diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h
index 3ae1e93dc3d..81a0f526049 100644
--- a/source/blender/editors/include/UI_view2d.h
+++ b/source/blender/editors/include/UI_view2d.h
@@ -148,7 +148,6 @@ typedef struct View2DScrollers View2DScrollers;
 void UI_view2d_region_reinit(struct View2D *v2d, short type, int winx, int winy);
 
 void UI_view2d_curRect_validate(struct View2D *v2d);
-void UI_view2d_curRect_validate_resize(struct View2D *v2d, int resize);
 void UI_view2d_curRect_reset(struct View2D *v2d);
 void UI_view2d_sync(struct bScreen *screen, struct ScrArea *sa, struct View2D *v2dcur, int flag);
 
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 25f85883d9c..1d26cbd344b 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -2666,6 +2666,8 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str,
 	
 	/* we could do some more error checks here */
 	if ((type & BUTTYPE) == LABEL) {
+		if ((poin != NULL || min != 0.0f || max != 0.0f || (a1 == 0.0f && a2 != 0.0f) || (a1 != 0.0f && a1 != 1.0f)))
+			printf("blah\n");
 		BLI_assert((poin != NULL || min != 0.0f || max != 0.0f || (a1 == 0.0f && a2 != 0.0f) || (a1 != 0.0f && a1 != 1.0f)) == FALSE);
 	}
 
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 958334fb476..9988224e0ab 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -5248,32 +5248,15 @@ static int ui_mouse_inside_region(ARegion *ar, int x, int y)
 	 */
 	if (ar->v2d.mask.xmin != ar->v2d.mask.xmax) {
 		View2D *v2d = &ar->v2d;
-		rcti mask_rct;
 		int mx, my;
 		
 		/* convert window coordinates to region coordinates */
 		mx = x;
 		my = y;
 		ui_window_to_region(ar, &mx, &my);
-		
-		/* make a copy of the mask rect, and tweak accordingly for hidden scrollbars */
-		mask_rct = v2d->mask;
-		
-		if (v2d->scroll & (V2D_SCROLL_VERTICAL_HIDE | V2D_SCROLL_VERTICAL_FULLR)) {
-			if (v2d->scroll & V2D_SCROLL_LEFT)
-				mask_rct.xmin = v2d->vert.xmin;
-			else if (v2d->scroll & V2D_SCROLL_RIGHT)
-				mask_rct.xmax = v2d->vert.xmax;
-		}
-		if (v2d->scroll & (V2D_SCROLL_HORIZONTAL_HIDE | V2D_SCROLL_HORIZONTAL_FULLR)) {
-			if (v2d->scroll & (V2D_SCROLL_BOTTOM | V2D_SCROLL_BOTTOM_O))
-				mask_rct.ymin = v2d->hor.ymin;
-			else if (v2d->scroll & V2D_SCROLL_TOP)
-				mask_rct.ymax = v2d->hor.ymax;
-		}
-		
+
 		/* check if in the rect */
-		if (!BLI_rcti_isect_pt(&mask_rct, mx, my)) 
+		if (!BLI_rcti_isect_pt(&v2d->mask, mx, my))
 			return 0;
 	}
 	
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 5b6a609e4d2..9fbf2fe8898 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -112,7 +112,7 @@ static int panel_aligned(ScrArea *sa, ARegion *ar)
 	else if (sa->spacetype == SPACE_FILE && ar->regiontype == RGN_TYPE_CHANNELS)
 		return BUT_VERTICAL;
 	else if (sa->spacetype == SPACE_IMAGE && ar->regiontype == RGN_TYPE_PREVIEW)
-		return BUT_VERTICAL; 
+		return BUT_VERTICAL;
 	else if (ELEM3(ar->regiontype, RGN_TYPE_UI, RGN_TYPE_TOOLS, RGN_TYPE_TOOL_PROPS))
 		return BUT_VERTICAL;
 	
@@ -812,8 +812,8 @@ static void ui_panels_size(ScrArea *sa, ARegion *ar, int *x, int *y)
 {
 	Panel *pa;
 	int align = panel_aligned(sa, ar);
-	int sizex = UI_PANEL_WIDTH;
-	int sizey = UI_PANEL_WIDTH;
+	int sizex = 0;
+	int sizey = 0;
 
 	/* compute size taken up by panels, for setting in view2d */
 	for (pa = ar->panels.first; pa; pa = pa->next) {
@@ -834,6 +834,11 @@ static void ui_panels_size(ScrArea *sa, ARegion *ar, int *x, int *y)
 		}
 	}
 
+	if (sizex == 0)
+		sizex = UI_PANEL_WIDTH;
+	if (sizey == 0)
+		sizey = -UI_PANEL_WIDTH;
+	
 	*x = sizex;
 	*y = sizey;
 }
@@ -956,6 +961,25 @@ void uiDrawPanels(const bContext *C, ARegion *ar)
 	}
 }
 
+void uiScalePanels(ARegion *ar, float new_width)
+{
+	uiBlock *block;
+	uiBut *but;
+	
+	for (block = ar->uiblocks.first; block; block = block->next) {
+		if (block->panel) {
+			float fac = new_width / (float)block->panel->sizex;
+			printf("scaled %f\n", fac);
+			block->panel->sizex = new_width;
+			
+			for (but = block->buttons.first; but; but = but->next) {
+				but->rect.xmin *= fac;
+				but->rect.xmax *= fac;
+			}
+		}
+	}
+}
+
 /* ------------ panel merging ---------------- */
 
 static void check_panel_overlap(ARegion *ar, Panel *panel)
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index 190d90b3c36..d0d631e14a5 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -60,6 +60,8 @@
 
 #include "interface_intern.h"
 
+static void ui_view2d_curRect_validate_resize(View2D *v2d, int resize, int mask_scrollers);
+
 /* *********************************************************************** */
 
 /* XXX still unresolved: scrolls hide/unhide vs region mask handling */
@@ -73,15 +75,15 @@
  */
 static int view2d_scroll_mapped(int scroll)
 {
-	if (scroll & V2D_SCROLL_HORIZONTAL_HIDE)
+	if (scroll & V2D_SCROLL_HORIZONTAL_FULLR)
 		scroll &= ~(V2D_SCROLL_HORIZONTAL);
-	if (scroll & V2D_SCROLL_VERTICAL_HIDE)
+	if (scroll & V2D_SCROLL_VERTICAL_FULLR)
 		scroll &= ~(V2D_SCROLL_VERTICAL);
 	return scroll;
 }
 
 /* called each time cur changes, to dynamically update masks */
-static void view2d_masks(View2D *v2d)
+static void view2d_masks(View2D *v2d, int check_scrollers)
 {
 	int scroll;
 	
@@ -90,19 +92,26 @@ static void view2d_masks(View2D *v2d)
 	v2d->mask.xmax = v2d->winx - 1; /* -1 yes! masks are pixels */
 	v2d->mask.ymax = v2d->winy - 1;
 
-#if 0
-	/* XXX see above */
-	v2d->scroll &= ~(V2D_SCROLL_HORIZONTAL_HIDE | V2D_SCROLL_VERTICAL_HIDE);
-	/* check size if: */
-	if (v2d->scroll & V2D_SCROLL_HORIZONTAL)
-		if (!(v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL))
-			if (BLI_rctf_size_x(&v2d->tot) <= BLI_rcti_size_x(&v2d->cur))
-				v2d->scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
-	if (v2d->scroll & V2D_SCROLL_VERTICAL)
-		if (!(v2d->scroll & V2D_SCROLL_SCALE_VERTICAL))
-			if (BLI_rctf_size_y(&v2d->tot) <= BLI_rctf_size_y(&v2d->cur))
-				v2d->scroll |= V2D_SCROLL_VERTICAL_HIDE;
-#endif
+	if (check_scrollers) {
+		/* check size if hiding flag is set: */
+		if (v2d->scroll & V2D_SCROLL_HORIZONTAL_HIDE) {
+			if (!(v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL)) {
+				if (BLI_rctf_size_x(&v2d->tot) > BLI_rctf_size_x(&v2d->cur))
+					v2d->scroll &= ~V2D_SCROLL_HORIZONTAL_FULLR;
+				else
+					v2d->scroll |= V2D_SCROLL_HORIZONTAL_FULLR;
+			}
+		}
+		if (v2d->scroll & V2D_SCROLL_VERTICAL_HIDE) {
+			if (!(v2d->scroll & V2D_SCROLL_SCALE_VERTICAL)) {
+				if (BLI_rctf_size_y(&v2d->tot) + 0.01f > BLI_rctf_size_y(&v2d->cur))
+					v2d->scroll &= ~V2D_SCROLL_VERTICAL_FULLR;
+				else
+					v2d->scroll |= V2D_SCROLL_VERTICAL_FULLR;
+			}
+		}
+	}
+	
 	scroll = view2d_scroll_mapped(v2d->scroll);
 	
 	/* scrollers shrink mask area, but should be based off regionsize 
@@ -126,8 +135,8 @@ static void view2d_masks(View2D *v2d)
 		}
 		
 		/* horizontal scroller */
-		if (scroll & (V2D_SCROLL_BOTTOM | V2D_SCROLL_BOTTOM_O)) {
-			/* on bottom edge of region (V2D_SCROLL_BOTTOM_O is outliner, the other is for standard) */
+		if (scroll & (V2D_SCROLL_BOTTOM)) {
+			/* on bottom edge of region */
 			v2d->hor = v2d->mask;
 			v2d->hor.ymax = V2D_SCROLL_HEIGHT;
 			v2d->mask.ymin = v2d->hor.ymax + 1;
@@ -142,8 +151,8 @@ static void view2d_masks(View2D *v2d)
 		/* adjust vertical scroller if there's a horizontal scroller, to leave corner free */
 		if (scroll & V2D_SCROLL_VERTICAL) {
 			/* just set y min/max for vertical scroller to y min/max of mask as appropriate */
-			if (scroll & (V2D_SCROLL_BOTTOM | V2D_SCROLL_BOTTOM_O)) {
-				/* on bottom edge of region (V2D_SCROLL_BOTTOM_O is outliner, the other is for standard) */
+			if (scroll & (V2D_SCROLL_BOTTOM)) {
+				/* on bottom edge of region */
 				v2d->vert.ymin = v2d->mask.ymin;
 			}
 			else if (scroll & V2D_SCROLL_TOP) {
@@ -152,7 +161,6 @@ static void view2d_masks(View2D *v2d)
 			}
 		}
 	}
-	
 }
 
 /* Refresh and Validation */
@@ -165,163 +173,173 @@ static void view2d_masks(View2D *v2d)
  */
 void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
 {
-	short tot_changed = 0, init = 0;
+	short tot_changed = 0, do_init;
 	uiStyle *style = UI_GetStyle();
 
-	/* initialize data if there is a need for such */
-	if ((v2d->flag & V2D_IS_INITIALISED) == 0) {
-		/* set initialized flag so that View2D doesn't get reinitialised next time again */
-		v2d->flag |= V2D_IS_INITIALISED;
-
-		init = 1;
+	do_init = (v2d->flag & V2D_IS_INITIALISED) == 0;
 		
-		/* see eView2D_CommonViewTypes in UI_view2d.h for available view presets */
-		switch (type) {
-			/* 'standard view' - optimum setup for 'standard' view behavior,
-			 *  that should be used new views as basis for their
-			 *  own unique View2D settings, which should be used instead of this in most cases...
+	/* see eView2D_CommonViewTypes in UI_view2d.h for available view presets */
+	switch (type) {
+		/* 'standard view' - optimum setup for 'standard' view behavior,
+		 *  that should be used new views as basis for their
+		 *  own unique View2D settings, which should be used instead of this in most cases...
+		 */
+		case V2D_COMMONVIEW_STANDARD:
+		{
+			/* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */
+			v2d->keepzoom = (V2D_KEEPASPECT | V2D_LIMITZOOM);
+			v2d->minzoom = 0.01f;
+			v2d->maxzoom = 1000.0f;
+			
+			/* tot rect and cur should be same size, and aligned using 'standard' OpenGL coordinates for now 
+			 *	- region can resize 'tot' later to fit other data
+			 *	- keeptot is only within bounds, as strict locking is not that critical
+			 *	- view is aligned for (0,0) -> (winx-1, winy-1) setup
 			 */
-			case V2D_COMMONVIEW_STANDARD:
-			{
-				/* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */
-				v2d->keepzoom = (V2D_KEEPASPECT | V2D_LIMITZOOM);
-				v2d->minzoom = 0.01f;
-				v2d->maxzoom = 1000.0f;
-				
-				/* tot rect and cur should be same size, and aligned using 'standard' OpenGL coordinates for now 
-				 *	- region can resize 'tot' later to fit other data
-				 *	- keeptot is only within bounds, as strict locking is not that critical
-				 *	- view is aligned for (0,0) -> (winx-1, winy-1) setup
-				 */
-				v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y);
-				v2d->keeptot = V2D_KEEPTOT_BOUNDS;
-				
+			v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y);
+			v2d->keeptot = V2D_KEEPTOT_BOUNDS;
+			
+			if (do_init) {
 				v2d->tot.xmin = v2d->tot.ymin = 0.0f;
 				v2d->tot.xmax = (float)(winx - 1);
 				v2d->tot.ymax = (float)(winy - 1);
 				
 				v2d->cur = v2d->tot;
-				
-				/* scrollers - should we have these by default? */
-				/* XXX for now, we don't override this, or set it either! */
 			}
-			break;
+			/* scrollers - should we have these by default? */
+			/* XXX for now, we don't override this, or set it either! */
+		}
+		break;
+		
+		/* 'list/channel view' - zoom, aspect ratio, and alignment restrictions are set here */
+		case V2D_COMMONVIEW_LIST:
+		{
+			/* zoom + aspect ratio are locked */
+			v2d->keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
+			v2d->minzoom = v2d->maxzoom = 1.0f;
 			
-			/* 'list/channel view' - zoom, aspect ratio, and alignment restrictions are set here */
-			case V2D_COMMONVIEW_LIST:
-			{
-				/* zoom + aspect ratio are locked */
-				v2d->keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
-				v2d->minzoom = v2d->maxzoom = 1.0f;
-				
-				/* tot rect has strictly regulated placement, and must only occur in +/- quadrant */
-				v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
-				v2d->keeptot = V2D_KEEPTOT_STRICT;
-				tot_changed = 1;
-				
-				/* scroller settings are currently not set here... that is left for regions... */
-			}
-			break;
-				
-			/* 'stack view' - practically the same as list/channel view, except is located in the pos y half instead. 
-			 *  zoom, aspect ratio, and alignment restrictions are set here */
-			case V2D_COMMONVIEW_STACK:
-			{
-				/* zoom + aspect ratio are locked */
-				v2d->keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
-				v2d->minzoom = v2d->maxzoom = 1.0f;
-				
-				/* tot rect has strictly regulated placement, and must only occur in +/+ quadrant */
-				v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y);
-				v2d->keeptot = V2D_KEEPTOT_STRICT;
-				tot_changed = 1;
-				
-				/* scroller settings are currently not set here... that is left for regions... */
-			}
-			break;
+			/* tot rect has strictly regulated placement, and must only occur in +/- quadrant */
+			v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
+			v2d->keeptot = V2D_KEEPTOT_STRICT;
+			tot_changed = do_init;
+			
+			/* scroller settings are currently not set here... that is left for regions... */
+		}
+		break;
+			
+		/* 'stack view' - practically the same as list/channel view, except is located in the pos y half instead. 
+		 *  zoom, aspect ratio, and alignment restrictions are set here */
+		case V2D_COMMONVIEW_STACK:
+		{
+			/* zoom + aspect ratio are locked */
+			v2d->keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
+			v2d->minzoom = v2d->maxzoom = 1.0f;
+			
+			/* tot rect has strictly regulated placement, and must only occur in +/+ quadrant */
+			v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y);
+			v2d->keeptot = V2D_KEEPTOT_STRICT;
+			tot_changed = do_init;
+			
+			/* scroller settings are currently not set here... that is left for regions... */
+		}
+		break;
+			
+		/* 'header' regions - zoom, aspect ratio, alignment, and panning restrictions are set here */
+		case V2D_COMMONVIEW_HEADER:
+		{
+			/* zoom + aspect ratio are locked */
+			v2d->keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
+			v2d->minzoom = v2d->maxzoom = 1.0f;
+			
+			if (do_init) {
+				v2d->tot.xmin = 0.0f;
+				v2d->tot.xmax = winx;
+				v2d->tot.ymin = 0.0f;
+				v2d->tot.ymax = winy;
+				v2d->cur = v2d->tot;
 				
-			/* 'header' regions - zoom, aspect ratio, alignment, and panning restrictions are set here */
-			case V2D_COMMONVIEW_HEADER:
-			{
-				/* zoom + aspect ratio are locked */
-				v2d->keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
-				v2d->minzoom = v2d->maxzoom = 1.0f;
 				v2d->min[0] = v2d->max[0] = (float)(winx - 1);
 				v2d->min[1] = v2d->max[1] = (float)(winy - 1);
-				
-				/* tot rect has strictly regulated placement, and must only occur in +/+ quadrant */
-				v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y);
-				v2d->keeptot = V2D_KEEPTOT_STRICT;
-				tot_changed = 1;
-				
-				/* panning in y-axis is prohibited */
-				v2d->keepofs = V2D_LOCKOFS_Y;
-				
-				/* absolutely no scrollers allowed */
-				v2d->scroll = 0;
-				
 			}
-			break;
+			/* tot rect has strictly regulated placement, and must only occur in +/+ quadrant */
+			v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y);
+			v2d->keeptot = V2D_KEEPTOT_STRICT;
+			tot_changed = do_init;
+			
+			/* panning in y-axis is prohibited */
+			v2d->keepofs = V2D_LOCKOFS_Y;
+			
+			/* absolutely no scrollers allowed */
+			v2d->scroll = 0;
+			
+		}
+		break;
+		
+		/* panels view, with horizontal/vertical align */
+		case V2D_COMMONVIEW_PANELS_UI:
+		{
 			
-			/* panels view, with horizontal/vertical align */
-			case V2D_COMMONVIEW_PANELS_UI:
-			{
+			/* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */
+			v2d->keepzoom = (V2D_KEEPASPECT | V2D_LIMITZOOM | V2D_KEEPZOOM);
+			v2d->minzoom = 0.5f;
+			v2d->maxzoom = 2.0f;
+			
+			v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
+			v2d->keeptot = V2D_KEEPTOT_BOUNDS;
+			
+			/* note, scroll is being flipped in ED_region_panels() drawing */
+			v2d->scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
+			v2d->scroll |= V2D_SCROLL_VERTICAL_HIDE;
+
+			if (do_init) {
 				float panelzoom = (style) ? style->panelzoom : 1.0f;
+				float scrolw = v2d->scroll & V2D_SCROLL_RIGHT ? V2D_SCROLL_WIDTH : 0.0f;
 				
-				/* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */
-				v2d->keepzoom = (V2D_KEEPASPECT | V2D_LIMITZOOM | V2D_KEEPZOOM);
-				v2d->minzoom = 0.5f;
-				v2d->maxzoom = 2.0f;
-				//tot_changed = 1;
-				
-				v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
-				v2d->keeptot = V2D_KEEPTOT_BOUNDS;
-				
-				v2d->scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
-				v2d->scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
-				v2d->scroll &= ~V2D_SCROLL_VERTICAL_HIDE;
-
 				v2d->tot.xmin = 0.0f;
-				v2d->tot.xmax = winx;
+				v2d->tot.xmax = winx - scrolw;
 				
 				v2d->tot.ymax = 0.0f;
 				v2d->tot.ymin = -winy;
 				
 				v2d->cur.xmin = 0.0f;
-				/* bad workaround for keeping zoom level with scrollers */
-				v2d->cur.xmax = (winx - V2D_SCROLL_WIDTH) * panelzoom;
+				v2d->cur.xmax = (winx) * panelzoom - scrolw;
 				
 				v2d->cur.ymax = 0.0f;
 				v2d->cur.ymin = (-winy) * panelzoom;
 			}
-			break;
-				
-			/* other view types are completely defined using their own settings already */
-			default:
-				/* we don't do anything here, as settings should be fine, but just make sure that rect */
-				break;
 		}
+		break;
+			
+		/* other view types are completely defined using their own settings already */
+		default:
+			/* we don't do anything here, as settings should be fine, but just make sure that rect */
+			break;
 	}
 	
+	/* set initialized flag so that View2D doesn't get reinitialised next time again */
+	v2d->flag |= V2D_IS_INITIALISED;
+
 	/* store view size */
 	v2d->winx = winx;
 	v2d->winy = winy;
 	
-	/* set masks */
-	view2d_masks(v2d);
+	/* set masks (always do), but leave scroller scheck to totrect_set */
+	view2d_masks(v2d, 0);
 	
 	/* set 'tot' rect before setting cur? */
-	if (tot_changed) 
-		UI_view2d_totRect_set_resize(v2d, winx, winy, !init);
+	/* XXX confusing stuff here still - I made this function not check scroller hide - that happens in totrect_set */
+	if (tot_changed)
+		UI_view2d_totRect_set_resize(v2d, winx, winy, !do_init);
 	else
-		UI_view2d_curRect_validate_resize(v2d, !init);
+		ui_view2d_curRect_validate_resize(v2d, !do_init, 0);
+	
 }
 
 /* Ensure View2D rects remain in a viable configuration 
  *	- cur is not allowed to be: larger than max, smaller than min, or outside of tot
  */
 // XXX pre2.5 -> this used to be called  test_view2d()
-void UI_view2d_curRect_validate_resize(View2D *v2d, int resize)
+static void ui_view2d_curRect_validate_resize(View2D *v2d, int resize, int mask_scrollers)
 {
 	float totwidth, totheight, curwidth, curheight, width, height;
 	float winx, winy;
@@ -715,12 +733,12 @@ void UI_view2d_curRect_validate_resize(View2D *v2d, int resize)
 	}
 	
 	/* set masks */
-	view2d_masks(v2d);
+	view2d_masks(v2d, mask_scrollers);
 }
 
 void UI_view2d_curRect_validate(View2D *v2d)
 {
-	UI_view2d_curRect_validate_resize(v2d, 0);
+	ui_view2d_curRect_validate_resize(v2d, 0, 1);
 }
 
 /* ------------------ */
@@ -844,7 +862,7 @@ void UI_view2d_curRect_reset(View2D *v2d)
 /* Change the size of the maximum viewable area (i.e. 'tot' rect) */
 void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, int resize)
 {
-	int scroll = view2d_scroll_mapped(v2d->scroll);
+//	int scroll = view2d_scroll_mapped(v2d->scroll);
 	
 	/* don't do anything if either value is 0 */
 	width = abs(width);
@@ -853,10 +871,10 @@ void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, int resize
 	/* hrumf! */
 	/* XXX: there are work arounds for this in the panel and file browse code. */
 	/* round to int, because this is called with width + V2D_SCROLL_WIDTH */
-	if (scroll & V2D_SCROLL_HORIZONTAL) 
-		width -= (int)V2D_SCROLL_WIDTH;
-	if (scroll & V2D_SCROLL_VERTICAL) 
-		height -= (int)V2D_SCROLL_HEIGHT;
+//	if (scroll & V2D_SCROLL_HORIZONTAL)
+//		width -= (int)V2D_SCROLL_WIDTH;
+//	if (scroll & V2D_SCROLL_VERTICAL)
+//		height -= (int)V2D_SCROLL_HEIGHT;
 	
 	if (ELEM(0, width, height)) {
 		if (G.debug & G_DEBUG)
@@ -903,12 +921,21 @@ void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, int resize
 	}
 	
 	/* make sure that 'cur' rect is in a valid state as a result of these changes */
-	UI_view2d_curRect_validate_resize(v2d, resize);
+	ui_view2d_curRect_validate_resize(v2d, resize, 1);
+	
 }
 
 void UI_view2d_totRect_set(View2D *v2d, int width, int height)
 {
+	int scroll = view2d_scroll_mapped(v2d->scroll);
+
 	UI_view2d_totRect_set_resize(v2d, width, height, 0);
+	
+	/* solve bad recursion... if scroller state changed, mask is different, so you get different rects */
+	if (scroll != view2d_scroll_mapped(v2d->scroll)) {
+		UI_view2d_totRect_set_resize(v2d, width, height, 0);
+	}
+	
 }
 
 int UI_view2d_tab_set(View2D *v2d, int tab)
@@ -1494,15 +1521,6 @@ View2DScrollers *UI_view2d_scrollers_calc(const bContext *C, View2D *v2d,
 			CLAMP(scrollers->hor_min, hor.xmin, hor.xmax - V2D_SCROLLER_HANDLE_SIZE);
 		}
 		
-		/* check whether sliders can disappear due to the full-range being used */
-		if (v2d->keeptot) {
-			if ((fac1 <= 0.0f) && (fac2 >= 1.0f)) {
-				v2d->scroll |= V2D_SCROLL_HORIZONTAL_FULLR;
-				scrollers->horfull = 1;
-			}
-			else
-				v2d->scroll &= ~V2D_SCROLL_HORIZONTAL_FULLR;
-		}
 	}
 	
 	/* vertical scrollers */
@@ -1536,15 +1554,6 @@ View2DScrollers *UI_view2d_scrollers_calc(const bContext *C, View2D *v2d,
 			CLAMP(scrollers->vert_min, vert.ymin, vert.ymax - V2D_SCROLLER_HANDLE_SIZE);
 		}
 
-		/* check whether sliders can disappear due to the full-range being used */
-		if (v2d->keeptot) {
-			if ((fac1 <= 0.0f) && (fac2 >= 1.0f)) {
-				v2d->scroll |= V2D_SCROLL_VERTICAL_FULLR;
-				scrollers->vertfull = 1;
-			}
-			else
-				v2d->scroll &= ~V2D_SCROLL_VERTICAL_FULLR;
-		}
 	}
 	
 	/* grid markings on scrollbars */
@@ -1618,45 +1627,42 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
 	
 	/* horizontal scrollbar */
 	if (scroll & V2D_SCROLL_HORIZONTAL) {
-		/* only draw scrollbar when it doesn't fill the entire space */
-		if (vs->horfull == 0) {
-			bTheme *btheme = UI_GetTheme();
-			uiWidgetColors wcol = btheme->tui.wcol_scroll;
-			rcti slider;
-			int state;
-			unsigned char col[4];
-			
-			slider.xmin = vs->hor_min;
-			slider.xmax = vs->hor_max;
-			slider.ymin = hor.ymin;
-			slider.ymax = hor.ymax;
-			
-			state = (v2d->scroll_ui & V2D_SCROLL_H_ACTIVE) ? UI_SCROLL_PRESSED : 0;
-			
-			/* show zoom handles if:
-			 *	- zooming on x-axis is allowed (no scroll otherwise)
-			 *	- slider bubble is large enough (no overdraw confusion)
-			 *	- scale is shown on the scroller 
-			 *	  (workaround to make sure that button windows don't show these, 
-			 *		and only the time-grids with their zoomability can do so)
-			 */
-			if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0 &&
-			    (v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) &&
-			    (BLI_rcti_size_x(&slider) > V2D_SCROLLER_HANDLE_SIZE))
-			{
-				state |= UI_SCROLL_ARROWS;
-			}
-			
-			/* clean rect behind slider, but not with transparent background */
-			UI_GetThemeColor4ubv(TH_BACK, col);
-			if (col[3] == 255) {
-				glColor3ub(col[0], col[1], col[2]);
-				glRecti(v2d->hor.xmin, v2d->hor.ymin, v2d->hor.xmax, v2d->hor.ymax);
-			}
-			
-			uiWidgetScrollDraw(&wcol, &hor, &slider, state);
+		bTheme *btheme = UI_GetTheme();
+		uiWidgetColors wcol = btheme->tui.wcol_scroll;
+		rcti slider;
+		int state;
+		unsigned char col[4];
+		
+		slider.xmin = vs->hor_min;
+		slider.xmax = vs->hor_max;
+		slider.ymin = hor.ymin;
+		slider.ymax = hor.ymax;
+		
+		state = (v2d->scroll_ui & V2D_SCROLL_H_ACTIVE) ? UI_SCROLL_PRESSED : 0;
+		
+		/* show zoom handles if:
+		 *	- zooming on x-axis is allowed (no scroll otherwise)
+		 *	- slider bubble is large enough (no overdraw confusion)
+		 *	- scale is shown on the scroller 
+		 *	  (workaround to make sure that button windows don't show these, 
+		 *		and only the time-grids with their zoomability can do so)
+		 */
+		if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0 &&
+			(v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) &&
+			(BLI_rcti_size_x(&slider) > V2D_SCROLLER_HANDLE_SIZE))
+		{
+			state |= UI_SCROLL_ARROWS;
 		}
 		
+		/* clean rect behind slider, but not with transparent background */
+		UI_GetThemeColor4ubv(TH_BACK, col);
+		if (col[3] == 255) {
+			glColor3ub(col[0], col[1], col[2]);
+			glRecti(v2d->hor.xmin, v2d->hor.ymin, v2d->hor.xmax, v2d->hor.ymax);
+		}
+		
+		uiWidgetScrollDraw(&wcol, &hor, &slider, state);
+		
 		/* scale indicators */
 		if ((scroll & V2D_SCROLL_SCALE_HORIZONTAL) && (vs->grid)) {
 			View2DGrid *grid = vs->grid;
@@ -1734,45 +1740,42 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
 	
 	/* vertical scrollbar */
 	if (scroll & V2D_SCROLL_VERTICAL) {
-		/* only draw scrollbar when it doesn't fill the entire space */
-		if (vs->vertfull == 0) {
-			bTheme *btheme = UI_GetTheme();
-			uiWidgetColors wcol = btheme->tui.wcol_scroll;
-			rcti slider;
-			int state;
-			unsigned char col[4];
-			
-			slider.xmin = vert.xmin;
-			slider.xmax = vert.xmax;
-			slider.ymin = vs->vert_min;
-			slider.ymax = vs->vert_max;
-			
-			state = (v2d->scroll_ui & V2D_SCROLL_V_ACTIVE) ? UI_SCROLL_PRESSED : 0;
-			
-			/* show zoom handles if:
-			 *	- zooming on y-axis is allowed (no scroll otherwise)
-			 *	- slider bubble is large enough (no overdraw confusion)
-			 *	- scale is shown on the scroller 
-			 *	  (workaround to make sure that button windows don't show these, 
-			 *		and only the time-grids with their zoomability can do so)
-			 */
-			if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0 &&
-			    (v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) &&
-			    (BLI_rcti_size_y(&slider) > V2D_SCROLLER_HANDLE_SIZE))
-			{
-				state |= UI_SCROLL_ARROWS;
-			}
-			
-			/* clean rect behind slider, but not with transparent background */
-			UI_GetThemeColor4ubv(TH_BACK, col);
-			if (col[3] == 255) {
-				glColor3ub(col[0], col[1], col[2]);
-				glRecti(v2d->vert.xmin, v2d->vert.ymin, v2d->vert.xmax, v2d->vert.ymax);
-			}
-			
-			uiWidgetScrollDraw(&wcol, &vert, &slider, state);
+		bTheme *btheme = UI_GetTheme();
+		uiWidgetColors wcol = btheme->tui.wcol_scroll;
+		rcti slider;
+		int state;
+		unsigned char col[4];
+		
+		slider.xmin = vert.xmin;
+		slider.xmax = vert.xmax;
+		slider.ymin = vs->vert_min;
+		slider.ymax = vs->vert_max;
+		
+		state = (v2d->scroll_ui & V2D_SCROLL_V_ACTIVE) ? UI_SCROLL_PRESSED : 0;
+		
+		/* show zoom handles if:
+		 *	- zooming on y-axis is allowed (no scroll otherwise)
+		 *	- slider bubble is large enough (no overdraw confusion)
+		 *	- scale is shown on the scroller 
+		 *	  (workaround to make sure that button windows don't show these, 
+		 *		and only the time-grids with their zoomability can do so)
+		 */
+		if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0 &&
+			(v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) &&
+			(BLI_rcti_size_y(&slider) > V2D_SCROLLER_HANDLE_SIZE))
+		{
+			state |= UI_SCROLL_ARROWS;
 		}
 		
+		/* clean rect behind slider, but not with transparent background */
+		UI_GetThemeColor4ubv(TH_BACK, col);
+		if (col[3] == 255) {
+			glColor3ub(col[0], col[1], col[2]);
+			glRecti(v2d->vert.xmin, v2d->vert.ymin, v2d->vert.xmax, v2d->vert.ymax);
+		}
+		
+		uiWidgetScrollDraw(&wcol, &vert, &slider, state);
+		
 		
 		/* scale indiators */
 		if ((scroll & V2D_SCROLL_SCALE_VERTICAL) && (vs->grid)) {
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index 006644bf366..8bea308e90a 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -1744,8 +1744,8 @@ static int scroller_activate_invoke(bContext *C, wmOperator *op, wmEvent *event)
 		}
 		
 		/* zone is also inappropriate if scroller is not visible... */
-		if (((vsm->scroller == 'h') && (v2d->scroll & (V2D_SCROLL_HORIZONTAL_HIDE | V2D_SCROLL_HORIZONTAL_FULLR))) ||
-		    ((vsm->scroller == 'v') && (v2d->scroll & (V2D_SCROLL_VERTICAL_HIDE | V2D_SCROLL_VERTICAL_FULLR))) )
+		if (((vsm->scroller == 'h') && (v2d->scroll & (V2D_SCROLL_HORIZONTAL_FULLR))) ||
+		    ((vsm->scroller == 'v') && (v2d->scroll & (V2D_SCROLL_VERTICAL_FULLR))) )
 		{
 			/* free customdata initialized */
 			scroller_activate_exit(C, op);
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index fbdec3dd8ad..5d37765cd58 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -574,8 +574,8 @@ static void area_azone_initialize(bScreen *screen, ScrArea *sa)
 	az = (AZone *)MEM_callocN(sizeof(AZone), "actionzone");
 	BLI_addtail(&(sa->actionzones), az);
 	az->type = AZONE_AREA;
-	az->x1 = sa->totrct.xmin - 1;
-	az->y1 = sa->totrct.ymin - 1;
+	az->x1 = sa->totrct.xmin;
+	az->y1 = sa->totrct.ymin;
 	az->x2 = sa->totrct.xmin + (AZONESPOT - 1);
 	az->y2 = sa->totrct.ymin + (AZONESPOT - 1);
 	BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
@@ -1300,6 +1300,9 @@ void ED_region_init(bContext *C, ARegion *ar)
 	ar->winx = BLI_rcti_size_x(&ar->winrct) + 1;
 	ar->winy = BLI_rcti_size_y(&ar->winrct) + 1;
 	
+	/* v2d mask is used to subtract scrollbars from a 2d view. Needs initialize here. */
+	BLI_rcti_init(&ar->v2d.mask, 0, ar->winx - 1, 0, ar->winy -1);
+
 	/* UI convention */
 	wmOrtho2(-0.01f, ar->winx - 0.01f, -0.01f, ar->winy - 0.01f);
 	glLoadIdentity();
@@ -1612,86 +1615,141 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *
 	View2D *v2d = &ar->v2d;
 	View2DScrollers *scrollers;
 	int x, y, xco, yco, w, em, triangle, open, newcontext = 0;
-	
+	int redo;
+	int scroll;
+
 	if (contextnr >= 0)
 		newcontext = UI_view2d_tab_set(v2d, contextnr);
-
+	
+	/* before setting the view */
 	if (vertical) {
-		w = BLI_rctf_size_x(&v2d->cur);
-		em = (ar->type->prefsizex) ? UI_UNIT_Y / 2 : UI_UNIT_Y;
+		/* only allow scrolling in vertical direction */
+		v2d->keepofs |= V2D_LOCKOFS_X | V2D_KEEPOFS_Y;
+		v2d->keepofs &= ~(V2D_LOCKOFS_Y | V2D_KEEPOFS_X);
+		v2d->scroll &= ~(V2D_SCROLL_BOTTOM);
+		v2d->scroll |= (V2D_SCROLL_RIGHT);
 	}
 	else {
-		w = UI_PANEL_WIDTH;
-		em = (ar->type->prefsizex) ? UI_UNIT_Y / 2 : UI_UNIT_Y;
+		/* for now, allow scrolling in both directions (since layouts are optimized for vertical,
+		 * they often don't fit in horizontal layout)
+		 */
+		v2d->keepofs &= ~(V2D_LOCKOFS_X | V2D_LOCKOFS_Y | V2D_KEEPOFS_X | V2D_KEEPOFS_Y);
+		v2d->scroll |= (V2D_SCROLL_BOTTOM);
+		v2d->scroll &= ~(V2D_SCROLL_RIGHT);
 	}
 
-	/* create panels */
-	uiBeginPanels(C, ar);
+	scroll = v2d->scroll;
+	
+	/* sortof hack - but we cannot predict the height of panels, until it's being generated */
+	/* the layout engine works with fixed width (from v2d->cur), which is being set at end of the loop */
+	/* in case scroller settings (hide flags) differ from previous, the whole loop gets done again */
+	for (redo = 2; redo > 0; redo--) {
+		
+		if (vertical) {
+			w = BLI_rctf_size_x(&v2d->cur);
+			em = (ar->type->prefsizex) ? UI_UNIT_Y / 2 : UI_UNIT_Y;
+		}
+		else {
+			w = UI_PANEL_WIDTH;
+			em = (ar->type->prefsizex) ? UI_UNIT_Y / 2 : UI_UNIT_Y;
+		}
+		
+		/* create panels */
+		uiBeginPanels(C, ar);
 
-	/* set view2d view matrix for scrolling (without scrollers) */
-	UI_view2d_view_ortho(v2d);
+		/* set view2d view matrix  - uiBeginBlock() stores it */
+		UI_view2d_view_ortho(v2d);
 
-	for (pt = ar->type->paneltypes.first; pt; pt = pt->next) {
-		/* verify context */
-		if (context)
-			if (pt->context[0] && strcmp(context, pt->context) != 0)
-				continue;
+		for (pt = ar->type->paneltypes.first; pt; pt = pt->next) {
+			/* verify context */
+			if (context)
+				if (pt->context[0] && strcmp(context, pt->context) != 0)
+					continue;
 
-		/* draw panel */
-		if (pt->draw && (!pt->poll || pt->poll(C, pt))) {
-			block = uiBeginBlock(C, ar, pt->idname, UI_EMBOSS);
-			panel = uiBeginPanel(sa, ar, block, pt, &open);
+			/* draw panel */
+			if (pt->draw && (!pt->poll || pt->poll(C, pt))) {
+				block = uiBeginBlock(C, ar, pt->idname, UI_EMBOSS);
+				panel = uiBeginPanel(sa, ar, block, pt, &open);
 
-			/* bad fixed values */
-			triangle = (int)(UI_UNIT_Y * 1.1f);
+				/* bad fixed values */
+				triangle = (int)(UI_UNIT_Y * 1.1f);
 
-			if (pt->draw_header && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) {
-				/* for enabled buttons */
-				panel->layout = uiBlockLayout(block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER,
-				                              triangle, (UI_UNIT_Y * 1.1f) + style->panelspace, UI_UNIT_Y, 1, style);
+				if (pt->draw_header && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) {
+					/* for enabled buttons */
+					panel->layout = uiBlockLayout(block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER,
+												  triangle, (UI_UNIT_Y * 1.1f) + style->panelspace, UI_UNIT_Y, 1, style);
 
-				pt->draw_header(C, panel);
+					pt->draw_header(C, panel);
 
-				uiBlockLayoutResolve(block, &xco, &yco);
-				panel->labelofs = xco - triangle;
-				panel->layout = NULL;
-			}
-			else {
-				panel->labelofs = 0;
-			}
+					uiBlockLayoutResolve(block, &xco, &yco);
+					panel->labelofs = xco - triangle;
+					panel->layout = NULL;
+				}
+				else {
+					panel->labelofs = 0;
+				}
 
-			if (open) {
-				short panelContext;
-				
-				/* panel context can either be toolbar region or normal panels region */
-				if (ar->regiontype == RGN_TYPE_TOOLS)
-					panelContext = UI_LAYOUT_TOOLBAR;
-				else
-					panelContext = UI_LAYOUT_PANEL;
-				
-				panel->layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, panelContext,
-				                              style->panelspace, 0, w - 2 * style->panelspace, em, style);
+				if (open) {
+					short panelContext;
+					
+					/* panel context can either be toolbar region or normal panels region */
+					if (ar->regiontype == RGN_TYPE_TOOLS)
+						panelContext = UI_LAYOUT_TOOLBAR;
+					else
+						panelContext = UI_LAYOUT_PANEL;
+					
+					panel->layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, panelContext,
+												  style->panelspace, 0, w - 2 * style->panelspace, em, style);
 
-				pt->draw(C, panel);
+					pt->draw(C, panel);
 
-				uiBlockLayoutResolve(block, &xco, &yco);
-				panel->layout = NULL;
+					uiBlockLayoutResolve(block, &xco, &yco);
+					panel->layout = NULL;
 
-				yco -= 2 * style->panelspace;
-				uiEndPanel(block, w, -yco);
-			}
-			else {
-				yco = 0;
-				uiEndPanel(block, w, 0);
+					yco -= 2 * style->panelspace;
+					uiEndPanel(block, w, -yco);
+				}
+				else {
+					yco = 0;
+					uiEndPanel(block, w, 0);
+				}
+
+				uiEndBlock(C, block);
 			}
+		}
 
-			uiEndBlock(C, block);
+		/* align panels and return size */
+		uiEndPanels(C, ar, &x, &y);
+		
+		/* before setting the view */
+		if (vertical) {
+			/* we always keep the scroll offset - so the total view gets increased with the scrolled away part */
+			if (v2d->cur.ymax < - 0.001f)
+				y = min_ii(y, v2d->cur.ymin);
+			
+			y = -y;
+		}
+		else {
+			/* don't jump back when panels close or hide */
+			if (!newcontext)
+				x = max_ii(x, v2d->cur.xmax);
+			y = -y;
+		}
+		
+		/* this also changes the 'cur' */
+		UI_view2d_totRect_set(v2d, x, y);
+		
+		if (scroll != v2d->scroll) {
+			/* Note: this code scales fine, but because of rounding differences, positions of elements
+			 * flip +1 or -1 pixel compared to redoing the entire layout again.
+			 * Leaving in commented code for future tests */
+			/* uiScalePanels(ar, BLI_rctf_size_x(&v2d->cur));
+			   break; */
 		}
+		else break;
 	}
-
-	/* align panels and return size */
-	uiEndPanels(C, ar, &x, &y);
-
+	
+	
 	/* clear */
 	if (ar->overlap) {
 		/* view should be in pixelspace */
@@ -1706,36 +1764,6 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *
 		glClear(GL_COLOR_BUFFER_BIT);
 	}
 	
-	/* before setting the view */
-	if (vertical) {
-		/* only allow scrolling in vertical direction */
-		v2d->keepofs |= V2D_LOCKOFS_X | V2D_KEEPOFS_Y;
-		v2d->keepofs &= ~(V2D_LOCKOFS_Y | V2D_KEEPOFS_X);
-		v2d->scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
-		v2d->scroll &= ~V2D_SCROLL_VERTICAL_HIDE;
-
-		/* ensure tot is set correctly, to keep views on bottons, with sliders */
-		y = min_ii(y, v2d->cur.ymin);
-		y = -y;
-	}
-	else {
-		/* for now, allow scrolling in both directions (since layouts are optimized for vertical,
-		 * they often don't fit in horizontal layout)
-		 */
-		v2d->keepofs &= ~(V2D_LOCKOFS_X | V2D_LOCKOFS_Y | V2D_KEEPOFS_X | V2D_KEEPOFS_Y);
-		//v2d->keepofs |= V2D_LOCKOFS_Y|V2D_KEEPOFS_X;
-		//v2d->keepofs &= ~(V2D_LOCKOFS_X|V2D_KEEPOFS_Y);
-		v2d->scroll |= V2D_SCROLL_VERTICAL_HIDE;
-		v2d->scroll &= ~V2D_SCROLL_HORIZONTAL_HIDE;
-
-		/* don't jump back when panels close or hide */
-		if (!newcontext)
-			x = max_ii(x, v2d->cur.xmax);
-		y = -y;
-	}
-
-	/* +V2D_SCROLL_HEIGHT is workaround to set the actual height (needs to be int) */
-	UI_view2d_totRect_set(v2d, x + (int)V2D_SCROLL_WIDTH, y + (int)V2D_SCROLL_HEIGHT);
 
 	/* set the view */
 	UI_view2d_view_ortho(v2d);
@@ -1756,16 +1784,9 @@ void ED_region_panels_init(wmWindowManager *wm, ARegion *ar)
 {
 	wmKeyMap *keymap;
 	
-	/* XXX quick hacks for files saved with 2.5 already (i.e. the builtin defaults file)
-	 * scrollbars for button regions */
-	ar->v2d.scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
-	ar->v2d.scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
-	ar->v2d.scroll &= ~V2D_SCROLL_VERTICAL_HIDE;
-	ar->v2d.keepzoom |= V2D_KEEPZOOM;
-
-	/* correctly initialized User-Prefs? */
-	if (!(ar->v2d.align & V2D_ALIGN_NO_POS_Y))
-		ar->v2d.flag &= ~V2D_IS_INITIALISED;
+	/* used for correctly initialized User-Prefs only?  */
+//	if (!(ar->v2d.align & V2D_ALIGN_NO_POS_Y))
+//		ar->v2d.flag &= ~V2D_IS_INITIALISED;
 
 	UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_PANELS_UI, ar->winx, ar->winy);
 
@@ -1828,6 +1849,7 @@ void ED_region_header(const bContext *C, ARegion *ar)
 
 void ED_region_header_init(ARegion *ar)
 {
+	ar->v2d.flag &= ~V2D_IS_INITIALISED;
 	UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
 }
 
diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c
index 9bd7d2a44ca..4b1954c8889 100644
--- a/source/blender/editors/space_action/action_draw.c
+++ b/source/blender/editors/space_action/action_draw.c
@@ -82,13 +82,7 @@ void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
 	filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
 	items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
 	
-	/* Update max-extent of channels here (taking into account scrollers):
-	 *  - this is done to allow the channel list to be scrollable, but must be done here
-	 *    to avoid regenerating the list again and/or also because channels list is drawn first
-	 *	- offset of ACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for 
-	 *	  start of list offset, and the second is as a correction for the scrollers.
-	 */
-	height = ((items * ACHANNEL_STEP) + (ACHANNEL_HEIGHT * 2));
+	height = ((items * ACHANNEL_STEP) + (ACHANNEL_HEIGHT));
 	if (height > BLI_rcti_size_y(&v2d->mask)) {
 		/* don't use totrect set, as the width stays the same 
 		 * (NOTE: this is ok here, the configuration is pretty straightforward) 
@@ -199,13 +193,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
 	filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
 	items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
 	
-	/* Update max-extent of channels here (taking into account scrollers):
-	 *  - this is done to allow the channel list to be scrollable, but must be done here
-	 *    to avoid regenerating the list again and/or also because channels list is drawn first
-	 *	- offset of ACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for 
-	 *	  start of list offset, and the second is as a correction for the scrollers.
-	 */
-	height = ((items * ACHANNEL_STEP) + (ACHANNEL_HEIGHT * 2));
+	height = ((items * ACHANNEL_STEP) + (ACHANNEL_HEIGHT));
 	/* don't use totrect set, as the width stays the same 
 	 * (NOTE: this is ok here, the configuration is pretty straightforward) 
 	 */
diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c
index c5f3ccee101..e0ca589c1fb 100644
--- a/source/blender/editors/space_action/space_action.c
+++ b/source/blender/editors/space_action/space_action.c
@@ -219,6 +219,9 @@ static void action_channel_area_init(wmWindowManager *wm, ARegion *ar)
 {
 	wmKeyMap *keymap;
 	
+	/* ensure the 2d view sync works - main region has bottom scroller */
+	ar->v2d.scroll = V2D_SCROLL_BOTTOM;
+	
 	UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
 	
 	/* own keymap */
@@ -231,7 +234,6 @@ static void action_channel_area_draw(const bContext *C, ARegion *ar)
 	/* draw entirely, view changes should be handled here */
 	bAnimContext ac;
 	View2D *v2d = &ar->v2d;
-	View2DScrollers *scrollers;
 	
 	/* clear and setup matrix */
 	UI_ThemeClearColor(TH_BACK);
@@ -247,10 +249,7 @@ static void action_channel_area_draw(const bContext *C, ARegion *ar)
 	/* reset view matrix */
 	UI_view2d_view_restore(C);
 	
-	/* scrollers */
-	scrollers = UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
-	UI_view2d_scrollers_draw(C, v2d, scrollers);
-	UI_view2d_scrollers_free(scrollers);
+	/* no scrollers here */
 }
 
 
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index fb438ae45fb..08f01b47b52 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -321,8 +321,7 @@ void file_calc_previews(const bContext *C, ARegion *ar)
 	View2D *v2d = &ar->v2d;
 	
 	ED_fileselect_init_layout(sfile, ar);
-	/* +SCROLL_HEIGHT is bad hack to work around issue in UI_view2d_totRect_set */
-	UI_view2d_totRect_set(v2d, sfile->layout->width, sfile->layout->height + V2D_SCROLL_HEIGHT);
+	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, short dropshadow)
diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c
index fa7c6bd472a..734c0e6c479 100644
--- a/source/blender/editors/space_graph/space_graph.c
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -309,6 +309,12 @@ static void graph_channel_area_init(wmWindowManager *wm, ARegion *ar)
 {
 	wmKeyMap *keymap;
 	
+	/* make sure we keep the hide flags */
+	ar->v2d.scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
+	ar->v2d.scroll &= ~(V2D_SCROLL_LEFT | V2D_SCROLL_TOP);	/* prevent any noise of past */
+	ar->v2d.scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
+	ar->v2d.scroll |= V2D_SCROLL_VERTICAL_HIDE;
+	
 	UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
 	
 	/* own keymap */
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 222dcac454f..1a058104c78 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -421,17 +421,17 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
 				
 				uiBlockSetEmboss(block, UI_EMBOSSN);
 				bt = uiDefIconButR(block, ICONTOG, 0, ICON_RESTRICT_VIEW_OFF,
-				                   (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+				                   (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
 				                   &ptr, "hide", -1, 0, 0, -1, -1, NULL);
 				uiButSetFunc(bt, restrictbutton_view_cb, scene, ob);
 				
 				bt = uiDefIconButR(block, ICONTOG, 0, ICON_RESTRICT_SELECT_OFF,
-				                   (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+				                   (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
 				                   &ptr, "hide_select", -1, 0, 0, -1, -1, NULL);
 				uiButSetFunc(bt, restrictbutton_sel_cb, scene, ob);
 				
 				bt = uiDefIconButR(block, ICONTOG, 0, ICON_RESTRICT_RENDER_OFF,
-				                   (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+				                   (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
 				                   &ptr, "hide_render", -1, 0, 0, -1, -1, NULL);
 				uiButSetFunc(bt, restrictbutton_rend_cb, scene, ob);
 				
@@ -446,19 +446,19 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
 
 				restrict_bool = group_restrict_flag(gr, OB_RESTRICT_VIEW);
 				bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF,
-				                  (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+				                  (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
 				                  NULL, 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
 				uiButSetFunc(bt, restrictbutton_gr_restrict_view, scene, gr);
 
 				restrict_bool = group_restrict_flag(gr, OB_RESTRICT_SELECT);
 				bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_SELECT_ON : ICON_RESTRICT_SELECT_OFF,
-				                  (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+				                  (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
 				                  NULL, 0, 0, 0, 0, "Restrict/Allow selection in the 3D View");
 				uiButSetFunc(bt, restrictbutton_gr_restrict_select, scene, gr);
 
 				restrict_bool = group_restrict_flag(gr, OB_RESTRICT_RENDER);
 				bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_RENDER_ON : ICON_RESTRICT_RENDER_OFF,
-				                  (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+				                  (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
 				                  NULL, 0, 0, 0, 0, "Restrict/Allow renderability");
 				uiButSetFunc(bt, restrictbutton_gr_restrict_render, scene, gr);
 
@@ -469,7 +469,7 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
 				uiBlockSetEmboss(block, UI_EMBOSSN);
 				
 				bt = uiDefIconButBitI(block, ICONTOGN, SCE_LAY_DISABLE, 0, ICON_CHECKBOX_HLT - 1,
-				                      (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+				                      (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
 				                      te->directdata, 0, 0, 0, 0, "Render this RenderLayer");
 				uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
 				
@@ -483,7 +483,7 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
 				
 				
 				bt = uiDefIconButBitI(block, ICONTOG, passflag, 0, ICON_CHECKBOX_HLT - 1,
-				                      (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+				                      (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
 				                      layflag, 0, 0, 0, 0, "Render this Pass");
 				uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
 				
@@ -492,7 +492,7 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
 				          SCE_PASS_INDIRECT, SCE_PASS_EMIT, SCE_PASS_ENVIRONMENT))
 				{
 					bt = uiDefIconButBitI(block, TOG, passflag, 0, (*layflag & passflag) ? ICON_DOT : ICON_BLANK1,
-					                      (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+					                      (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
 					                      layflag, 0, 0, 0, 0, "Exclude this Pass from Combined");
 				}
 				uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
@@ -505,12 +505,12 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
 				
 				uiBlockSetEmboss(block, UI_EMBOSSN);
 				bt = uiDefIconButBitI(block, ICONTOGN, eModifierMode_Realtime, 0, ICON_RESTRICT_VIEW_OFF,
-				                      (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+				                      (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
 				                      &(md->mode), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
 				uiButSetFunc(bt, restrictbutton_modifier_cb, scene, ob);
 				
 				bt = uiDefIconButBitI(block, ICONTOGN, eModifierMode_Render, 0, ICON_RESTRICT_RENDER_OFF,
-				                      (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+				                      (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
 				                      &(md->mode), 0, 0, 0, 0, "Restrict/Allow renderability");
 				uiButSetFunc(bt, restrictbutton_modifier_cb, scene, ob);
 			}
@@ -520,12 +520,12 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
 				
 				uiBlockSetEmboss(block, UI_EMBOSSN);
 				bt = uiDefIconButBitI(block, ICONTOG, BONE_HIDDEN_P, 0, ICON_RESTRICT_VIEW_OFF,
-				                      (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+				                      (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
 				                      &(bone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
 				uiButSetFunc(bt, restrictbutton_bone_cb, NULL, bone);
 				
 				bt = uiDefIconButBitI(block, ICONTOG, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF,
-				                      (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+				                      (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
 				                      &(bone->flag), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View");
 				uiButSetFunc(bt, restrictbutton_bone_cb, NULL, NULL);
 			}
@@ -534,12 +534,12 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
 				
 				uiBlockSetEmboss(block, UI_EMBOSSN);
 				bt = uiDefIconButBitI(block, ICONTOG, BONE_HIDDEN_A, 0, ICON_RESTRICT_VIEW_OFF,
-				                      (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+				                      (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
 				                      &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
 				uiButSetFunc(bt, restrictbutton_ebone_cb, NULL, ebone);
 				
 				bt = uiDefIconButBitI(block, ICONTOG, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF,
-				                      (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+				                      (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
 				                      &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View");
 				uiButSetFunc(bt, restrictbutton_ebone_cb, NULL, NULL);
 			}
@@ -553,7 +553,7 @@ static void outliner_draw_rnacols(ARegion *ar, int sizex)
 {
 	View2D *v2d = &ar->v2d;
 
-	float miny = v2d->cur.ymin - V2D_SCROLL_HEIGHT;
+	float miny = v2d->cur.ymin;
 	if (miny < v2d->tot.ymin) miny = v2d->tot.ymin;
 
 	UI_ThemeColorShadeAlpha(TH_BACK, -15, -200);
@@ -850,7 +850,7 @@ static void outliner_draw_keymapbuts(uiBlock *block, ARegion *ar, SpaceOops *soo
 				
 				/* rna property */
 				if (kmi->ptr && kmi->ptr->data) {
-					uiDefBut(block, LABEL, 0, "(RNA property)", xstart, (int)te->ys + 1, butw2, UI_UNIT_Y - 1, &kmi->oskey, 0, 0, 0, 0, ""); xstart += butw2;
+					uiDefBut(block, LABEL, 0, "(RNA property)", xstart, (int)te->ys + 1, butw2, UI_UNIT_Y - 1, NULL, 0, 0, 0, 0, ""); xstart += butw2;
 				}
 
 				(void)xstart;
@@ -1533,13 +1533,13 @@ static void outliner_draw_struct_marks(ARegion *ar, SpaceOops *soops, ListBase *
 		/* selection status */
 		if (TSELEM_OPEN(tselem, soops))
 			if (tselem->type == TSE_RNA_STRUCT)
-				glRecti(0, *starty + 1, (int)ar->v2d.cur.xmax + V2D_SCROLL_WIDTH, *starty + UI_UNIT_Y - 1);
+				glRecti(0, *starty + 1, (int)ar->v2d.cur.xmax, *starty + UI_UNIT_Y - 1);
 
 		*starty -= UI_UNIT_Y;
 		if (TSELEM_OPEN(tselem, soops)) {
 			outliner_draw_struct_marks(ar, soops, &te->subtree, starty);
 			if (tselem->type == TSE_RNA_STRUCT)
-				fdrawline(0, (float)*starty + UI_UNIT_Y, ar->v2d.cur.xmax + V2D_SCROLL_WIDTH, (float)*starty + UI_UNIT_Y);
+				fdrawline(0, (float)*starty + UI_UNIT_Y, ar->v2d.cur.xmax, (float)*starty + UI_UNIT_Y);
 		}
 	}
 }
@@ -1608,7 +1608,7 @@ static void outliner_back(ARegion *ar)
 	ystart = UI_UNIT_Y * (ystart / (UI_UNIT_Y)) - OL_Y_OFFSET;
 	
 	while (ystart + 2 * UI_UNIT_Y > ar->v2d.cur.ymin) {
-		glRecti(0, ystart, (int)ar->v2d.cur.xmax + V2D_SCROLL_WIDTH, ystart + UI_UNIT_Y);
+		glRecti(0, ystart, (int)ar->v2d.cur.xmax, ystart + UI_UNIT_Y);
 		ystart -= 2 * UI_UNIT_Y;
 	}
 }
@@ -1619,10 +1619,8 @@ static void outliner_draw_restrictcols(ARegion *ar)
 	
 	/* background underneath */
 	UI_ThemeColor(TH_BACK);
-	glRecti((int)ar->v2d.cur.xmax - OL_TOGW,
-	        (int)ar->v2d.cur.ymin - V2D_SCROLL_HEIGHT - 1,
-	        (int)ar->v2d.cur.xmax + V2D_SCROLL_WIDTH,
-	        (int)ar->v2d.cur.ymax);
+	glRecti((int)(ar->v2d.cur.xmax - OL_TOGW),
+	        (int)(ar->v2d.cur.ymin - 1), (int)ar->v2d.cur.xmax, (int)ar->v2d.cur.ymax);
 	
 	UI_ThemeColorShade(TH_BACK, 6);
 	ystart = (int)ar->v2d.tot.ymax;
@@ -1636,22 +1634,22 @@ static void outliner_draw_restrictcols(ARegion *ar)
 	UI_ThemeColorShadeAlpha(TH_BACK, -15, -200);
 
 	/* view */
-	fdrawline(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX,
-	          ar->v2d.cur.ymax,
-	          ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX,
-	          ar->v2d.cur.ymin - V2D_SCROLL_HEIGHT);
+	sdrawline((int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
+	          (int)ar->v2d.cur.ymax,
+	          (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
+	          (int)ar->v2d.cur.ymin);
 
 	/* render */
-	fdrawline(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX,
-	          ar->v2d.cur.ymax,
-	          ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX,
-	          ar->v2d.cur.ymin - V2D_SCROLL_HEIGHT);
+	sdrawline((int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX),
+	          (int)ar->v2d.cur.ymax,
+	          (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX),
+	          (int)ar->v2d.cur.ymin);
 
 	/* render */
-	fdrawline(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX,
-	          ar->v2d.cur.ymax,
-	          ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX,
-	          ar->v2d.cur.ymin - V2D_SCROLL_HEIGHT);
+	sdrawline((int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX),
+	          (int)ar->v2d.cur.ymax,
+	          (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX),
+	          (int)ar->v2d.cur.ymin);
 }
 
 /* ****************************************************** */
@@ -1700,11 +1698,9 @@ void draw_outliner(const bContext *C)
 		// XXX this isn't that great yet...
 		if ((soops->flag & SO_HIDE_RESTRICTCOLS) == 0)
 			sizex += OL_TOGW * 3;
+		
 	}
 	
-	/* tweak to display last line (when list bigger than window) */
-	sizey += V2D_SCROLL_HEIGHT;
-	
 	/* adds vertical offset */
 	sizey += OL_Y_OFFSET;
 
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index f9fca378568..63452de18d0 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -116,8 +116,8 @@ typedef struct TreeElement {
 /* size constants */
 #define OL_Y_OFFSET 2
 
-#define OL_TOG_RESTRICT_VIEWX   (UI_UNIT_X * 3)
-#define OL_TOG_RESTRICT_SELECTX (UI_UNIT_X * 2)
+#define OL_TOG_RESTRICT_VIEWX   (UI_UNIT_X * 3.0f)
+#define OL_TOG_RESTRICT_SELECTX (UI_UNIT_X * 2.0f)
 #define OL_TOG_RESTRICT_RENDERX UI_UNIT_X
 
 #define OL_TOGW OL_TOG_RESTRICT_VIEWX
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index ecc09a35670..4bf88376b74 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -67,6 +67,17 @@ static void outliner_main_area_init(wmWindowManager *wm, ARegion *ar)
 	ListBase *lb;
 	wmKeyMap *keymap;
 	
+	/* make sure we keep the hide flags */
+	ar->v2d.scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
+	ar->v2d.scroll &= ~(V2D_SCROLL_LEFT | V2D_SCROLL_TOP);	/* prevent any noise of past */
+	ar->v2d.scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
+	ar->v2d.scroll |= V2D_SCROLL_VERTICAL_HIDE;
+
+	ar->v2d.align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
+	ar->v2d.keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
+	ar->v2d.keeptot = V2D_KEEPTOT_STRICT;
+	ar->v2d.minzoom = ar->v2d.maxzoom = 1.0f;
+
 	UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
 	
 	/* own keymap */
@@ -410,12 +421,6 @@ static SpaceLink *outliner_new(const bContext *UNUSED(C))
 	BLI_addtail(&soutliner->regionbase, ar);
 	ar->regiontype = RGN_TYPE_WINDOW;
 	
-	ar->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM_O);
-	ar->v2d.align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
-	ar->v2d.keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
-	ar->v2d.keeptot = V2D_KEEPTOT_STRICT;
-	ar->v2d.minzoom = ar->v2d.maxzoom = 1.0f;
-	
 	return (SpaceLink *)soutliner;
 }
 
diff --git a/source/blender/editors/space_userpref/space_userpref.c b/source/blender/editors/space_userpref/space_userpref.c
index 1ea3876f5cc..6560f218002 100644
--- a/source/blender/editors/space_userpref/space_userpref.c
+++ b/source/blender/editors/space_userpref/space_userpref.c
@@ -105,14 +105,14 @@ static SpaceLink *userpref_duplicate(SpaceLink *sl)
 /* add handlers, stuff you only do once or on area/region changes */
 static void userpref_main_area_init(wmWindowManager *wm, ARegion *ar)
 {
+	ar->v2d.flag &= ~V2D_IS_INITIALISED;
+	ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
+
 	ED_region_panels_init(wm, ar);
 }
 
 static void userpref_main_area_draw(const bContext *C, ARegion *ar)
 {
-	/* this solves "vibrating UI" bug #25422 */
-	UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_PANELS_UI, ar->winx, ar->winy);
-	
 	ED_region_panels(C, ar, 1, NULL, -1);
 }
 
diff --git a/source/blender/makesdna/DNA_view2d_types.h b/source/blender/makesdna/DNA_view2d_types.h
index 084496871bf..a7921be44d5 100644
--- a/source/blender/makesdna/DNA_view2d_types.h
+++ b/source/blender/makesdna/DNA_view2d_types.h
@@ -123,9 +123,9 @@ typedef struct View2D {
 	/* horizontal scrollbar */
 #define V2D_SCROLL_TOP 				(1<<2)
 #define V2D_SCROLL_BOTTOM 			(1<<3)
-	/* special hack for outliner hscroll - prevent hanging older versions of Blender */
-#define V2D_SCROLL_BOTTOM_O   		(1<<4)
-#define V2D_SCROLL_HORIZONTAL  		(V2D_SCROLL_TOP|V2D_SCROLL_BOTTOM|V2D_SCROLL_BOTTOM_O)
+
+/* UNUSED							(1<<4) */
+#define V2D_SCROLL_HORIZONTAL  		(V2D_SCROLL_TOP|V2D_SCROLL_BOTTOM)
 	/* scale markings - vertical */
 #define V2D_SCROLL_SCALE_VERTICAL	(1<<5)
 	/* scale markings - horizontal */
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index be202a23d33..ec94501c8be 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -544,6 +544,7 @@ void WM_window_open_temp(bContext *C, rcti *position, int type)
 	}
 	
 	ED_screen_set(C, win->screen);
+	ED_screen_refresh(CTX_wm_manager(C), win); /* test scale */
 	
 	if (sa->spacetype == SPACE_IMAGE)
 		GHOST_SetTitle(win->ghostwin, IFACE_("Blender Render"));
-- 
cgit v1.2.3


From 41753f4fddc69bee7b45baef79dff02288b0aeae Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Wed, 26 Dec 2012 13:25:13 +0000
Subject: Node editor: remove option to show overlapping Property region.

- The main window has sliders, which was drawn behind the region
- If property region had slider too, it got even worse.

Basically the node editor is UI view, so drawing another UI on top isn't
functioning well in general.
---
 source/blender/editors/screen/area.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 5d37765cd58..0e8628d47bf 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -917,7 +917,7 @@ static int region_is_overlap(wmWindow *win, ScrArea *sa, ARegion *ar)
 {
 	if (U.uiflag2 & USER_REGION_OVERLAP)
 		if (WM_is_draw_triple(win))
-			if (ELEM5(sa->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_SEQ, SPACE_CLIP, SPACE_NODE))
+			if (ELEM4(sa->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_SEQ, SPACE_CLIP))
 				if (ELEM3(ar->regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI, RGN_TYPE_TOOL_PROPS))
 					return 1;
 	return 0;
-- 
cgit v1.2.3


From 86134fd8c6056a568531fff7f71afe95450d97ec Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Wed, 26 Dec 2012 13:57:07 +0000
Subject: Bug fix #33633 (and irc report)

The function ui_popup_block_clip() didn't correct the buttons if a clip
happened, causing the items to draw outside.
---
 source/blender/editors/interface/interface_regions.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 57c126c31c5..a1ad7d6aaa7 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -1527,6 +1527,7 @@ static void ui_block_region_draw(const bContext *C, ARegion *ar)
 
 static void ui_popup_block_clip(wmWindow *window, uiBlock *block)
 {
+	uiBut *bt;
 	int width = UI_ThemeMenuShadowWidth();
 	int winx, winy;
 
@@ -1536,7 +1537,6 @@ static void ui_popup_block_clip(wmWindow *window, uiBlock *block)
 
 	winx = WM_window_pixels_x(window);
 	winy = WM_window_pixels_y(window);
-	// wm_window_get_size(window, &winx, &winy);
 	
 	if (block->rect.xmin < width)
 		block->rect.xmin = width;
@@ -1547,6 +1547,15 @@ static void ui_popup_block_clip(wmWindow *window, uiBlock *block)
 		block->rect.ymin = width;
 	if (block->rect.ymax > winy - MENU_TOP)
 		block->rect.ymax = winy - MENU_TOP;
+	
+	/* ensure menu items draw inside left/right boundary */
+	for (bt = block->buttons.first; bt; bt = bt->next) {
+		if (bt->rect.xmin < block->rect.xmin)
+			bt->rect.xmin = block->rect.xmin;
+		if (bt->rect.xmax > block->rect.xmax)
+			bt->rect.xmax = block->rect.xmax;
+	}
+
 }
 
 void ui_popup_block_scrolltest(uiBlock *block)
-- 
cgit v1.2.3


From 0bca6c1834e1515cbdc4681621f627eb98563f9f Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Wed, 26 Dec 2012 14:22:04 +0000
Subject: Bug fix #33673

Edge length display in standard files (1 blender unit == 1) only gave two
numbers precision for lengths > 1. Three is much nicer at least.

The guess-work here in the code remains a bit dubious :)
---
 source/blender/editors/space_view3d/drawobject.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 6edbd3fb0b3..c72cb2c4d8c 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -2591,10 +2591,10 @@ static void draw_em_measure_stats(View3D *v3d, Object *ob, BMEditMesh *em, UnitS
 
 	/* make the precision of the display value proportionate to the gridsize */
 
-	if (grid < 0.01f) conv_float = "%.6g";
-	else if (grid < 0.1f) conv_float = "%.5g";
-	else if (grid < 1.0f) conv_float = "%.4g";
-	else if (grid < 10.0f) conv_float = "%.3g";
+	if (grid <= 0.01f) conv_float = "%.6g";
+	else if (grid <= 0.1f) conv_float = "%.5g";
+	else if (grid <= 1.0f) conv_float = "%.4g";
+	else if (grid <= 10.0f) conv_float = "%.3g";
 	else conv_float = "%.2g";
 	
 	if (me->drawflag & ME_DRAWEXTRA_EDGELEN) {
-- 
cgit v1.2.3


From cffd10a7c8569c7ca6edf171b3a542dcbec628af Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Wed, 26 Dec 2012 16:24:50 +0000
Subject: Todo item:

- Drop group into 3d window now puts itself at mouse cursor location.
- Drop objects into 3d window now doesn't move the 3d cursor anymore.

Added new function ED_view3d_cursor3d_position() to handle this,
so the temporarily object-drop operator macro also could go away.
(Which was setting 3d cursor)
---
 source/blender/editors/include/ED_view3d.h         |  1 +
 source/blender/editors/object/object_add.c         | 12 ++++++++-
 source/blender/editors/object/object_ops.c         |  9 -------
 source/blender/editors/space_view3d/space_view3d.c | 10 ++------
 source/blender/editors/space_view3d/view3d_edit.c  | 30 ++++++++++++++++------
 5 files changed, 36 insertions(+), 26 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 4df49920bf7..3d13938c204 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -85,6 +85,7 @@ typedef struct ViewDepths {
 } ViewDepths;
 
 float *give_cursor(struct Scene *scene, struct View3D *v3d);
+void ED_view3d_cursor3d_position(struct bContext *C, float *fp, int mx, int my);
 
 void ED_view3d_to_m4(float mat[4][4], const float ofs[3], const float quat[4], const float dist);
 void ED_view3d_from_m4(float mat[4][4], float ofs[3], float quat[4], float *dist);
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 473119c90f3..4db416b6f72 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -808,9 +808,16 @@ static int group_instance_add_exec(bContext *C, wmOperator *op)
 	
 	if (RNA_struct_property_is_set(op->ptr, "name")) {
 		char name[MAX_ID_NAME - 2];
-
+		
 		RNA_string_get(op->ptr, "name", name);
 		group = (Group *)BKE_libblock_find_name(ID_GR, name);
+		
+		if (0 == RNA_struct_property_is_set(op->ptr, "location")) {
+			wmEvent *event = CTX_wm_window(C)->eventstate;
+			ED_object_location_from_view(C, loc);
+			ED_view3d_cursor3d_position(C, loc, event->x, event->y);
+			RNA_float_set_array(op->ptr, "location", loc);
+		}
 	}
 	else
 		group = BLI_findlink(&CTX_data_main(C)->group, RNA_enum_get(op->ptr, "group"));
@@ -1994,6 +2001,7 @@ void OBJECT_OT_duplicate(wmOperatorType *ot)
 
 static int add_named_exec(bContext *C, wmOperator *op)
 {
+	wmEvent *event = CTX_wm_window(C)->eventstate;
 	Main *bmain = CTX_data_main(C);
 	Scene *scene = CTX_data_scene(C);
 	Base *basen, *base;
@@ -2026,6 +2034,8 @@ static int add_named_exec(bContext *C, wmOperator *op)
 	basen->lay = basen->object->lay = scene->lay;
 
 	ED_object_location_from_view(C, basen->object->loc);
+	ED_view3d_cursor3d_position(C, basen->object->loc, event->x, event->y);
+	
 	ED_base_object_activate(C, basen);
 
 	copy_object_set_idnew(C, dupflag);
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index d19277d20a2..03b50c05071 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -252,15 +252,6 @@ void ED_operatormacros_object(void)
 		RNA_enum_set(otmacro->ptr, "proportional", PROP_EDIT_OFF);
 	}
 	
-	/* XXX */
-	ot = WM_operatortype_append_macro("OBJECT_OT_add_named_cursor", "Add Named At Cursor",
-	                                  "Add named object at cursor", OPTYPE_UNDO | OPTYPE_REGISTER);
-	if (ot) {
-		RNA_def_string(ot->srna, "name", "Cube", MAX_ID_NAME - 2, "Name", "Object name to add");
-
-		WM_operatortype_macro_define(ot, "VIEW3D_OT_cursor3d");
-		WM_operatortype_macro_define(ot, "OBJECT_OT_add_named");
-	}
 }
 
 static int object_mode_poll(bContext *C)
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 4ade47fbdc7..1d87895d64a 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -520,14 +520,8 @@ static int view3d_ima_ob_drop_poll(bContext *C, wmDrag *drag, wmEvent *event)
 static void view3d_ob_drop_copy(wmDrag *drag, wmDropBox *drop)
 {
 	ID *id = (ID *)drag->poin;
-	PointerRNA ptr;
 
-	/* need to put name in sub-operator in macro */
-	ptr = RNA_pointer_get(drop->ptr, "OBJECT_OT_add_named");
-	if (ptr.data)
-		RNA_string_set(&ptr, "name", id->name + 2);
-	else
-		RNA_string_set(drop->ptr, "name", id->name + 2);
+	RNA_string_set(drop->ptr, "name", id->name + 2);
 }
 
 static void view3d_group_drop_copy(wmDrag *drag, wmDropBox *drop)
@@ -561,7 +555,7 @@ static void view3d_dropboxes(void)
 {
 	ListBase *lb = WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW);
 	
-	WM_dropbox_add(lb, "OBJECT_OT_add_named_cursor", view3d_ob_drop_poll, view3d_ob_drop_copy);
+	WM_dropbox_add(lb, "OBJECT_OT_add_named", view3d_ob_drop_poll, view3d_ob_drop_copy);
 	WM_dropbox_add(lb, "OBJECT_OT_drop_named_material", view3d_mat_drop_poll, view3d_id_drop_copy);
 	WM_dropbox_add(lb, "MESH_OT_drop_named_image", view3d_ima_ob_drop_poll, view3d_id_path_drop_copy);
 	WM_dropbox_add(lb, "VIEW3D_OT_background_image_add", view3d_ima_bg_drop_poll, view3d_id_path_drop_copy);
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index adaad2557d4..913cf3087bb 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -3678,17 +3678,21 @@ void VIEW3D_OT_clip_border(wmOperatorType *ot)
 
 /* ***************** 3d cursor cursor op ******************* */
 
-/* mx my in region coords */
-static int view3d_cursor3d_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
+/* cursor position in vec, result in vec, mval in region coords */
+/* note: cannot use event->mval here (called by object_add() */
+void ED_view3d_cursor3d_position(bContext *C, float *fp, int mx, int my)
 {
 	Scene *scene = CTX_data_scene(C);
 	ARegion *ar = CTX_wm_region(C);
 	View3D *v3d = CTX_wm_view3d(C);
 	RegionView3D *rv3d = CTX_wm_region_view3d(C);
-	float *fp = give_cursor(scene, v3d);
 	float mval_fl[2];
+	int mval[2];
 	int flip;
 
+	mval[0] = mx - ar->winrct.xmin;
+	mval[1] = my - ar->winrct.ymin;
+	
 	flip = initgrabz(rv3d, fp[0], fp[1], fp[2]);
 	
 	/* reset the depth based on the view offset (we _know_ the offset is infront of us) */
@@ -3703,20 +3707,20 @@ static int view3d_cursor3d_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *
 
 		if (U.uiflag & USER_ZBUF_CURSOR) {  /* maybe this should be accessed some other way */
 			view3d_operator_needs_opengl(C);
-			if (ED_view3d_autodist(scene, ar, v3d, event->mval, fp))
+			if (ED_view3d_autodist(scene, ar, v3d, mval, fp))
 				depth_used = TRUE;
 		}
 
 		if (depth_used == FALSE) {
 			float dvec[3];
-			VECSUB2D(mval_fl, mval_fl, event->mval);
+			VECSUB2D(mval_fl, mval_fl, mval);
 			ED_view3d_win_to_delta(ar, mval_fl, dvec);
 			sub_v3_v3(fp, dvec);
 		}
 	}
 	else {
-		const float dx = ((float)(event->mval[0] - (ar->winx / 2))) * rv3d->zfac / (ar->winx / 2);
-		const float dy = ((float)(event->mval[1] - (ar->winy / 2))) * rv3d->zfac / (ar->winy / 2);
+		const float dx = ((float)(mval[0] - (ar->winx / 2))) * rv3d->zfac / (ar->winx / 2);
+		const float dy = ((float)(mval[1] - (ar->winy / 2))) * rv3d->zfac / (ar->winy / 2);
 		const float fz = (rv3d->persmat[0][3] * fp[0] +
 		                  rv3d->persmat[1][3] * fp[1] +
 		                  rv3d->persmat[2][3] * fp[2] +
@@ -3727,11 +3731,21 @@ static int view3d_cursor3d_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *
 		fp[2] = (rv3d->persinv[0][2] * dx + rv3d->persinv[1][2] * dy + rv3d->persinv[2][2] * fz) - rv3d->ofs[2];
 	}
 
+}
+
+static int view3d_cursor3d_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
+{
+	Scene *scene = CTX_data_scene(C);
+	View3D *v3d = CTX_wm_view3d(C);
+	float *fp = give_cursor(scene, v3d);
+
+	ED_view3d_cursor3d_position(C, fp, event->x, event->y);
+	
 	if (v3d && v3d->localvd)
 		WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
 	else
 		WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
-
+	
 	return OPERATOR_FINISHED;
 }
 
-- 
cgit v1.2.3


From 7b938abe2b85eae1fdfe8d584935f4ec4d94f297 Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Wed, 26 Dec 2012 17:36:51 +0000
Subject: Bugfix #33667

Mesh had invalid face indices (number too high).
On Separate in Edit Mode it crashed.

Two fixes:

- The Material properties viewer just showed the last material in the index array.
  Now it shows nothing, to indicate it's an invalid selected material.

- Crash was caused by array copy magic, not checking the active index properly.

(No assert, no warning prints, I think cases like this can happen too easily, and this
way user gets notified nicely and can fix it).
---
 source/blender/blenkernel/intern/material.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index f0327719372..bf64bd3d093 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -628,11 +628,14 @@ Material *give_current_material(Object *ob, short act)
 	if (totcolp == NULL || ob->totcol == 0) return NULL;
 	
 	if (act < 0) {
-		printf("no!\n");
+		printf("Negative material index!\n");
 	}
 	
-	if (act > ob->totcol) act = ob->totcol;
-	else if (act <= 0) act = 1;
+	/* return NULL for invalid 'act', can happen for mesh face indices */
+	if (act > ob->totcol)
+		return NULL;
+	else if (act <= 0)
+		return NULL;
 
 	if (ob->matbits && ob->matbits[act - 1]) {    /* in object */
 		ma = ob->mat[act - 1];
@@ -1234,6 +1237,11 @@ int object_remove_material_slot(Object *ob)
 
 	if (*matarar == NULL) return FALSE;
 
+	/* can happen on face selection in editmode */
+	if (ob->actcol > ob->totcol) {
+		ob->actcol = ob->totcol;
+	}
+	
 	/* we delete the actcol */
 	mao = (*matarar)[ob->actcol - 1];
 	if (mao) mao->id.us--;
-- 
cgit v1.2.3


From b28848063fec337443af9b77c13143f82d52a53f Mon Sep 17 00:00:00 2001
From: Antony Riakiotakis 
Date: Wed, 26 Dec 2012 20:38:20 +0000
Subject: Fix: after multires baking, gpu textures were not getting invalidated
 for images and viewport was not getting refreshed with new baked textures.
 Now made sure this happens. The image list is copied to the job custom data
 so that the custom data cleanup function can properly delete them (if gpu
 image texture deletion does not happen on main thread, image bindcodes will
 remain intact for original images)

---
 source/blender/editors/object/object_bake.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c
index d3ebd1dae0a..f36c6d79783 100644
--- a/source/blender/editors/object/object_bake.c
+++ b/source/blender/editors/object/object_bake.c
@@ -89,6 +89,7 @@ typedef struct MultiresBakerJobData {
 	struct MultiresBakerJobData *next, *prev;
 	DerivedMesh *lores_dm, *hires_dm;
 	int simple, lvl, tot_lvl;
+	ListBase images;
 } MultiresBakerJobData;
 
 /* data passing to multires-baker job */
@@ -429,7 +430,7 @@ static void multiresbake_startjob(void *bkv, short *stop, short *do_update, floa
 
 		RE_multires_bake_images(&bkr);
 
-		BLI_freelistN(&bkr.image);
+		data->images = bkr.image;
 
 		baked_objects++;
 	}
@@ -439,12 +440,22 @@ static void multiresbake_freejob(void *bkv)
 {
 	MultiresBakeJob *bkj = bkv;
 	MultiresBakerJobData *data, *next;
+	LinkData *link;
 
 	data = bkj->data.first;
 	while (data) {
 		next = data->next;
 		data->lores_dm->release(data->lores_dm);
 		data->hires_dm->release(data->hires_dm);
+
+		/* delete here, since this delete will be called from main thread */
+		for (link = data->images.first; link; link = link->next) {
+			Image *ima = (Image *)link->data;
+			GPU_free_image(ima);
+		}
+
+		BLI_freelistN(&data->images);
+
 		MEM_freeN(data);
 		data = next;
 	}
-- 
cgit v1.2.3


From 84361f602a98d2ac35c6cc81eb897d593977e743 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Thu, 27 Dec 2012 01:02:32 +0000
Subject: fix [#33651] Spin tool destroys unselected loose vertex

bmesh.ops.extrude_face_region() didn't check for isolated verts (not connected to geometry), and removed them, happened for Ctrl+LMB extrude too.
---
 source/blender/bmesh/operators/bmo_dupe.c    |  2 +-
 source/blender/bmesh/operators/bmo_extrude.c | 32 +++++++++++++++-------------
 2 files changed, 18 insertions(+), 16 deletions(-)

(limited to 'source')

diff --git a/source/blender/bmesh/operators/bmo_dupe.c b/source/blender/bmesh/operators/bmo_dupe.c
index 9a58d7acfb9..f288901c272 100644
--- a/source/blender/bmesh/operators/bmo_dupe.c
+++ b/source/blender/bmesh/operators/bmo_dupe.c
@@ -483,7 +483,7 @@ void bmo_spin_exec(BMesh *bm, BMOperator *op)
 {
 	BMOperator dupop, extop;
 	float cent[3], dvec[3];
-	float axis[3] = {0.0f, 0.0f, 1.0f};
+	float axis[3];
 	float rmat[3][3];
 	float phi;
 	int steps, do_dupli, a, usedvec;
diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c
index 956d9e5767e..2cca3fcb24a 100644
--- a/source/blender/bmesh/operators/bmo_extrude.c
+++ b/source/blender/bmesh/operators/bmo_extrude.c
@@ -315,27 +315,29 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
 
 	/* calculate verts to delete */
 	BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
-		found = FALSE;
+		if (v->e) {  /* only deal with verts attached to geometry [#33651] */
+			found = FALSE;
 
-		BM_ITER_ELEM (e, &viter, v, BM_EDGES_OF_VERT) {
-			if (!BMO_elem_flag_test(bm, e, EXT_INPUT) || !BMO_elem_flag_test(bm, e, EXT_DEL)) {
-				found = TRUE;
-				break;
-			}
-		}
-
-		/* avoid an extra loop */
-		if (found == TRUE) {
-			BM_ITER_ELEM (f, &viter, v, BM_FACES_OF_VERT) {
-				if (!BMO_elem_flag_test(bm, f, EXT_INPUT)) {
+			BM_ITER_ELEM (e, &viter, v, BM_EDGES_OF_VERT) {
+				if (!BMO_elem_flag_test(bm, e, EXT_INPUT) || !BMO_elem_flag_test(bm, e, EXT_DEL)) {
 					found = TRUE;
 					break;
 				}
 			}
-		}
 
-		if (found == FALSE) {
-			BMO_elem_flag_enable(bm, v, EXT_DEL);
+			/* avoid an extra loop */
+			if (found == TRUE) {
+				BM_ITER_ELEM (f, &viter, v, BM_FACES_OF_VERT) {
+					if (!BMO_elem_flag_test(bm, f, EXT_INPUT)) {
+						found = TRUE;
+						break;
+					}
+				}
+			}
+
+			if (found == FALSE) {
+				BMO_elem_flag_enable(bm, v, EXT_DEL);
+			}
 		}
 	}
 	
-- 
cgit v1.2.3


From 540cbbc1d0bc4fcb84e35dcd3991f7ef9e9a10a1 Mon Sep 17 00:00:00 2001
From: Antony Riakiotakis 
Date: Thu, 27 Dec 2012 02:52:45 +0000
Subject: Fix: rotation of uv islands during stitch did not take uv aspect
 ratio of image into account, distorting the islands. Now properly scale the
 components before rotating the island.

---
 source/blender/editors/uvedit/uvedit_intern.h       |  1 +
 source/blender/editors/uvedit/uvedit_smart_stitch.c | 18 ++++++++++++++----
 source/blender/editors/uvedit/uvedit_unwrap_ops.c   |  8 ++++----
 3 files changed, 19 insertions(+), 8 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h
index 27bbba11e75..4d52282d540 100644
--- a/source/blender/editors/uvedit/uvedit_intern.h
+++ b/source/blender/editors/uvedit/uvedit_intern.h
@@ -73,6 +73,7 @@ void uv_find_nearest_edge(struct Scene *scene, struct Image *ima, struct BMEditM
 /* utility tool functions */
 
 void uvedit_live_unwrap_update(struct SpaceImage *sima, struct Scene *scene, struct Object *obedit);
+void uvedit_get_aspect(struct Scene *scene, struct Object *ob, struct BMEditMesh *em, float *aspx, float *aspy);
 
 /* operators */
 
diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c
index bd50857c8b8..bc2d0e493f4 100644
--- a/source/blender/editors/uvedit/uvedit_smart_stitch.c
+++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c
@@ -136,6 +136,7 @@ typedef struct UvEdge {
 
 /* stitch state object */
 typedef struct StitchState {
+	float aspect;
 	/* use limit flag */
 	char use_limit;
 	/* limit to operator, same as original operator */
@@ -285,10 +286,12 @@ static int getNumOfIslandUvs(UvElementMap *elementMap, int island)
 	}
 }
 
-static void stitch_uv_rotate(float rotation, float medianPoint[2], float uv[2])
+static void stitch_uv_rotate(float rotation, float medianPoint[2], float uv[2], float aspect)
 {
 	float uv_rotation_result[2];
 
+	uv[1] /= aspect;
+
 	uv[0] -= medianPoint[0];
 	uv[1] -= medianPoint[1];
 
@@ -297,6 +300,8 @@ static void stitch_uv_rotate(float rotation, float medianPoint[2], float uv[2])
 
 	uv[0] = uv_rotation_result[0] + medianPoint[0];
 	uv[1] = uv_rotation_result[1] + medianPoint[1];
+
+	uv[1] *= aspect;
 }
 
 /* check if two uvelements are stitchable. This should only operate on -different- separate UvElements */
@@ -413,9 +418,11 @@ static void stitch_calculate_island_snapping(StitchState *state, PreviewPosition
 				island_stitch_data[i].rotation /= island_stitch_data[i].num_rot_elements;
 				island_stitch_data[i].medianPoint[0] /= island_stitch_data[i].numOfElements;
 				island_stitch_data[i].medianPoint[1] /= island_stitch_data[i].numOfElements;
+				island_stitch_data[i].medianPoint[1] /= state->aspect;
 			}
 			island_stitch_data[i].translation[0] /= island_stitch_data[i].numOfElements;
 			island_stitch_data[i].translation[1] /= island_stitch_data[i].numOfElements;
+
 			numOfIslandUVs = getNumOfIslandUvs(state->element_map, i);
 			element = &state->element_map->buf[state->element_map->islandIndices[i]];
 			for (j = 0; j < numOfIslandUVs; j++, element++) {
@@ -429,7 +436,7 @@ static void stitch_calculate_island_snapping(StitchState *state, PreviewPosition
 
 					if (final) {
 
-						stitch_uv_rotate(island_stitch_data[i].rotation, island_stitch_data[i].medianPoint, luv->uv);
+						stitch_uv_rotate(island_stitch_data[i].rotation, island_stitch_data[i].medianPoint, luv->uv, state->aspect);
 
 						add_v2_v2(luv->uv, island_stitch_data[i].translation);
 					}
@@ -438,7 +445,7 @@ static void stitch_calculate_island_snapping(StitchState *state, PreviewPosition
 						int face_preview_pos = preview_position[BM_elem_index_get(element->l->f)].data_position;
 
 						stitch_uv_rotate(island_stitch_data[i].rotation, island_stitch_data[i].medianPoint,
-						                 preview->preview_polys + face_preview_pos + 2 * element->tfindex);
+						                 preview->preview_polys + face_preview_pos + 2 * element->tfindex, state->aspect);
 
 						add_v2_v2(preview->preview_polys + face_preview_pos + 2 * element->tfindex,
 						          island_stitch_data[i].translation);
@@ -1541,7 +1548,7 @@ static int stitch_init(bContext *C, wmOperator *op)
 	Scene *scene = CTX_data_scene(C);
 	ToolSettings *ts = scene->toolsettings;
 	ARegion *ar = CTX_wm_region(C);
-
+	float aspx, aspy;
 	Object *obedit = CTX_data_edit_object(C);
 
 	if (!ar)
@@ -1595,6 +1602,9 @@ static int stitch_init(bContext *C, wmOperator *op)
 		return 0;
 	}
 
+	uvedit_get_aspect(scene, obedit, em, &aspx, &aspy);
+	state->aspect = aspx/aspy;
+
 	/* Entirely possible if redoing last operator that static island is bigger than total number of islands.
 	 * This ensures we get no hang in the island checking code in stitch_stitch_process_data. */
 	state->static_island %= state->element_map->totalIslands;
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index 2ca711a4a6a..ddd42ded769 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -196,7 +196,7 @@ static int uvedit_have_selection(Scene *scene, BMEditMesh *em, short implicit)
 	return 0;
 }
 
-static void ED_uvedit_get_aspect(Scene *scene, Object *ob, BMEditMesh *em, float *aspx, float *aspy)
+void uvedit_get_aspect(Scene *scene, Object *ob, BMEditMesh *em, float *aspx, float *aspy)
 {
 	int sloppy = TRUE;
 	int selected = FALSE;
@@ -238,7 +238,7 @@ static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMEditMesh
 	if (correct_aspect) {
 		float aspx, aspy;
 
-		ED_uvedit_get_aspect(scene, ob, em, &aspx, &aspy);
+		uvedit_get_aspect(scene, ob, em, &aspx, &aspy);
 
 		if (aspx != aspy)
 			param_aspect_ratio(handle, aspx, aspy);
@@ -423,7 +423,7 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, Object *ob, B
 	if (correct_aspect) {
 		float aspx, aspy;
 
-		ED_uvedit_get_aspect(scene, ob, em, &aspx, &aspy);
+		uvedit_get_aspect(scene, ob, em, &aspx, &aspy);
 
 		if (aspx != aspy)
 			param_aspect_ratio(handle, aspx, aspy);
@@ -1047,7 +1047,7 @@ static void correct_uv_aspect(Scene *scene, Object *ob, BMEditMesh *em)
 	BMFace *efa;
 	float scale, aspx, aspy;
 	
-	ED_uvedit_get_aspect(scene, ob, em, &aspx, &aspy);
+	uvedit_get_aspect(scene, ob, em, &aspx, &aspy);
 	
 	if (aspx == aspy)
 		return;
-- 
cgit v1.2.3


From 6586fd9c62784af5496c48e5eeebc9b128d1addd Mon Sep 17 00:00:00 2001
From: Antony Riakiotakis 
Date: Thu, 27 Dec 2012 03:14:11 +0000
Subject: Fix: edge uv stitch mode did not average final position of uvs in
 midpoint, non-snapping mode.

---
 source/blender/editors/uvedit/uvedit_smart_stitch.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c
index bc2d0e493f4..f7219f8bd1b 100644
--- a/source/blender/editors/uvedit/uvedit_smart_stitch.c
+++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c
@@ -1164,6 +1164,14 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
 		}
 	}
 
+	/* take mean position here. For edge case, this can't be done inside the loop for shared uvverts */
+	if (state->mode == STITCH_EDGE && stitch_midpoints) {
+		for (i = 0; i < state->total_separate_uvs; i++) {
+			final_position[i].uv[0] /= final_position[i].count;
+			final_position[i].uv[1] /= final_position[i].count;
+		}
+	}
+
 	/* second pass, calculate island rotation and translation before modifying any uvs */
 	if (state->snap_islands) {
 		if (state->mode == STITCH_VERT) {
@@ -1218,11 +1226,6 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
 			for (i = 0; i < state->total_separate_uvs; i++) {
 				UvElement *element = state->uvs[i];
 
-				if (stitch_midpoints) {
-					final_position[i].uv[0] /= final_position[i].count;
-					final_position[i].uv[1] /= final_position[i].count;
-				}
-
 				if (element->flag & STITCH_STITCHABLE) {
 					BMLoop *l;
 					MLoopUV *luv;
-- 
cgit v1.2.3


From 1d6c3ccf092c9c692db454f477435a814b81d30a Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Thu, 27 Dec 2012 03:51:45 +0000
Subject: display the number of tri's in object mode status, often requested
 feature from users who model for realtime/game-engine output, the total
 number of faces wasn't so useful and could be especially misleading with
 ngons.

---
 source/blender/blenkernel/BKE_displist.h         |  2 +-
 source/blender/blenkernel/intern/displist.c      | 37 ++++++++++++++-----
 source/blender/blenlib/BLI_math_geom.h           |  2 ++
 source/blender/blenlib/intern/math_geom_inline.c | 20 +++++++++++
 source/blender/editors/space_info/info_stats.c   | 46 +++++++++---------------
 5 files changed, 67 insertions(+), 40 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h
index 758a2a8a2e8..6b986cdceda 100644
--- a/source/blender/blenkernel/BKE_displist.h
+++ b/source/blender/blenkernel/BKE_displist.h
@@ -83,7 +83,7 @@ void BKE_displist_elem_free(DispList *dl);
 DispList *BKE_displist_find_or_create(struct ListBase *lb, int type);
 DispList *BKE_displist_find(struct ListBase *lb, int type);
 void BKE_displist_normals_add(struct ListBase *lb);
-void BKE_displist_count(struct ListBase *lb, int *totvert, int *totface);
+void BKE_displist_count(struct ListBase *lb, int *totvert, int *totface, int *tottri);
 void BKE_displist_free(struct ListBase *lb);
 int BKE_displist_has_faces(struct ListBase *lb);
 
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 083cb02fd3d..47cb18a7172 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -225,29 +225,48 @@ void BKE_displist_normals_add(ListBase *lb)
 	}
 }
 
-void BKE_displist_count(ListBase *lb, int *totvert, int *totface)
+void BKE_displist_count(ListBase *lb, int *totvert, int *totface, int *tottri)
 {
 	DispList *dl;
 
-	dl = lb->first;
-	while (dl) {
+	for (dl = lb->first; dl; dl = dl->next) {
+		int vert_tot = 0;
+		int face_tot = 0;
+		int tri_tot = 0;
+
 		switch (dl->type) {
 			case DL_SURF:
-				*totvert += dl->nr * dl->parts;
-				*totface += (dl->nr - 1) * (dl->parts - 1);
+			{
+				vert_tot = dl->nr * dl->parts;
+				face_tot = (dl->nr - 1) * (dl->parts - 1);
+				tri_tot  = face_tot * 2;
 				break;
+			}
 			case DL_INDEX3:
+			{
+				vert_tot = dl->nr;
+				face_tot = dl->parts;
+				tri_tot  = face_tot;
+				break;
+			}
 			case DL_INDEX4:
-				*totvert += dl->nr;
-				*totface += dl->parts;
+			{
+				vert_tot = dl->nr;
+				face_tot = dl->parts;
+				tri_tot  = face_tot * 2;
 				break;
+			}
 			case DL_POLY:
 			case DL_SEGM:
-				*totvert += dl->nr * dl->parts;
+			{
+				vert_tot = dl->nr * dl->parts;
 				break;
+			}
 		}
 
-		dl = dl->next;
+		*totvert += vert_tot;
+		*totface += face_tot;
+		*tottri  += tri_tot;
 	}
 }
 
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index 423765bad3d..2f3521fa030 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -262,6 +262,8 @@ void axis_dominant_v3(int *axis_a, int *axis_b, const float axis[3]);
 MINLINE int max_axis_v3(const float vec[3]);
 MINLINE int min_axis_v3(const float vec[3]);
 
+MINLINE int poly_to_tri_count(const int poly_count, const int corner_count);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/source/blender/blenlib/intern/math_geom_inline.c b/source/blender/blenlib/intern/math_geom_inline.c
index ba9770e1bd1..9bb824be85e 100644
--- a/source/blender/blenlib/intern/math_geom_inline.c
+++ b/source/blender/blenlib/intern/math_geom_inline.c
@@ -158,4 +158,24 @@ MINLINE int min_axis_v3(const float vec[3])
 	       ((y < z) ? 1 : 2));
 }
 
+/**
+ * Simple method to find how many tri's we need when we already know the corner+poly count.
+ *
+ * Formula is:
+ *
+ *   tri = ((corner_count / poly_count) - 2) * poly_count;
+ *
+ * Use doubles since this is used for allocating and we
+ * don't want float precision to give incorrect results.
+ *
+ * \param poly_count The number of ngon's/tris (1-2 sided faces will give incorrect results)
+ * \param corner_count - also known as loops in BMesh/DNA
+ */
+MINLINE int poly_to_tri_count(const int poly_count, const int corner_count)
+{
+	const double poly_count_d   = (double)poly_count;
+	const double corner_count_d = (double)corner_count;
+	return (int)((((corner_count_d / poly_count_d) - 2.0) * poly_count_d) + 0.5);
+}
+
 #endif /* __MATH_GEOM_INLINE_C__ */
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index 5e5e0c87feb..73a43ee35ed 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -39,6 +39,7 @@
 #include "DNA_scene_types.h"
 
 #include "BLI_utildefines.h"
+#include "BLI_math.h"
 
 #include "BKE_anim.h"
 #include "BKE_blender.h"
@@ -62,7 +63,7 @@ typedef struct SceneStats {
 	int totbone, totbonesel;
 	int totobj,  totobjsel;
 	int totlamp, totlampsel; 
-	int tottri, totmesh, totcurve;
+	int tottri, totmesh;
 
 	char infostr[512];
 } SceneStats;
@@ -74,7 +75,7 @@ static void stats_object(Object *ob, int sel, int totob, SceneStats *stats)
 		{
 			/* we assume derivedmesh is already built, this strictly does stats now. */
 			DerivedMesh *dm = ob->derivedFinal;
-			int totvert, totedge, totface;
+			int totvert, totedge, totface, totloop;
 
 			stats->totmesh += totob;
 
@@ -82,10 +83,12 @@ static void stats_object(Object *ob, int sel, int totob, SceneStats *stats)
 				totvert = dm->getNumVerts(dm);
 				totedge = dm->getNumEdges(dm);
 				totface = dm->getNumPolys(dm);
+				totloop = dm->getNumLoops(dm);
 
 				stats->totvert += totvert * totob;
 				stats->totedge += totedge * totob;
 				stats->totface += totface * totob;
+				stats->tottri  += poly_to_tri_count(totface, totloop) * totob;
 
 				if (sel) {
 					stats->totvertsel += totvert;
@@ -103,40 +106,23 @@ static void stats_object(Object *ob, int sel, int totob, SceneStats *stats)
 		case OB_SURF:
 		case OB_CURVE:
 		case OB_FONT:
-		{
-			int tot = 0, totf = 0;
-
-			stats->totcurve += totob;
-
-			if (ob->disp.first)
-				BKE_displist_count(&ob->disp, &tot, &totf);
-
-			tot *= totob;
-			totf *= totob;
-
-			stats->totvert += tot;
-			stats->totface += totf;
-
-			if (sel) {
-				stats->totvertsel += tot;
-				stats->totfacesel += totf;
-			}
-			break;
-		}
 		case OB_MBALL:
 		{
-			int tot = 0, totf = 0;
+			int totv = 0, totf = 0, tottri = 0;
 
-			BKE_displist_count(&ob->disp, &tot, &totf);
+			if (ob->disp.first)
+				BKE_displist_count(&ob->disp, &totv, &totf, &tottri);
 
-			tot *= totob;
-			totf *= totob;
+			totv   *= totob;
+			totf   *= totob;
+			tottri *= totob;
 
-			stats->totvert += tot;
+			stats->totvert += totv;
 			stats->totface += totf;
+			stats->tottri  += tottri;
 
 			if (sel) {
-				stats->totvertsel += tot;
+				stats->totvertsel += totv;
 				stats->totfacesel += totf;
 			}
 			break;
@@ -389,8 +375,8 @@ static void stats_string(Scene *scene)
 		             stats->totbonesel, stats->totbone, memstr);
 	}
 	else {
-		s += sprintf(s, "Verts:%d | Faces:%d | Objects:%d/%d | Lamps:%d/%d%s",
-		             stats->totvert, stats->totface, stats->totobjsel, stats->totobj, stats->totlampsel, stats->totlamp, memstr);
+		s += sprintf(s, "Verts:%d | Faces:%d| Tris:%d | Objects:%d/%d | Lamps:%d/%d%s",
+		             stats->totvert, stats->totface, stats->tottri, stats->totobjsel, stats->totobj, stats->totlampsel, stats->totlamp, memstr);
 	}
 
 	if (ob)
-- 
cgit v1.2.3


From 89364fd0fa5e55c42bee6c245c4b5e00b481338a Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Thu, 27 Dec 2012 04:18:22 +0000
Subject: remove realloc's during BMEdit_RecalcTessellation(), instead use
 poly_to_tri_count() to calculate how many triangles are needed.

---
 source/blender/blenkernel/intern/editderivedmesh.c | 30 ++++++++++++----------
 1 file changed, 16 insertions(+), 14 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
index 480ff23f100..fc0c40878db 100644
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ b/source/blender/blenkernel/intern/editderivedmesh.c
@@ -113,8 +113,13 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *em)
 #define USE_TESSFACE_SPEEDUP
 
 	BMesh *bm = em->bm;
-	BMLoop *(*looptris)[3] = NULL;
-	BLI_array_declare(looptris);
+
+	/* this assumes all faces can be scan-filled, which isn't always true,
+	 * worst case we over alloc a little which is acceptable */
+	const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop);
+	const int looptris_tot_prev_alloc = em->looptris ? (MEM_allocN_len(em->looptris) / sizeof(*em->looptris)) : 0;
+
+	BMLoop *(*looptris)[3];
 	BMIter iter;
 	BMFace *efa;
 	BMLoop *l;
@@ -135,17 +140,16 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *em)
 #else
 
 	/* this means no reallocs for quad dominant models, for */
-	if ( (em->looptris != NULL) &&
-	     (em->tottri != 0) &&
-	     /* (totrti <= bm->totface * 2) would be fine for all quads,
-	      * but in case there are some ngons, still re-use the array */
-	     (em->tottri <= bm->totface * 3))
+	if ((em->looptris != NULL) &&
+	    /* (em->tottri >= looptris_tot)) */
+	    /* check against alloc'd size incase we over alloc'd a little */
+	    ((looptris_tot_prev_alloc >= looptris_tot) && (looptris_tot_prev_alloc <= looptris_tot * 2)))
 	{
 		looptris = em->looptris;
 	}
 	else {
 		if (em->looptris) MEM_freeN(em->looptris);
-		BLI_array_reserve(looptris, bm->totface);
+		looptris = MEM_mallocN(sizeof(*looptris) * looptris_tot, __func__);
 	}
 
 #endif
@@ -163,14 +167,12 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *em)
 		else if (efa->len == 3) {
 #if 0
 			int j;
-			BLI_array_grow_one(looptris);
 			BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, j) {
 				looptris[i][j] = l;
 			}
 			i += 1;
 #else
 			/* more cryptic but faster */
-			BLI_array_grow_one(looptris);
 			{
 				BMLoop **l_ptr = looptris[i++];
 				l_ptr[0] = l = BM_FACE_FIRST_LOOP(efa);
@@ -199,7 +201,6 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *em)
 			i += 1;
 #else
 			/* more cryptic but faster */
-			BLI_array_grow_items(looptris, 2);
 			{
 				BMLoop **l_ptr_a = looptris[i++];
 				BMLoop **l_ptr_b = looptris[i++];
@@ -221,7 +222,7 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *em)
 			ScanFillVert *sf_vert, *sf_vert_last = NULL, *sf_vert_first = NULL;
 			/* ScanFillEdge *e; */ /* UNUSED */
 			ScanFillFace *sf_tri;
-			int totfilltri;
+			/* int totfilltri; */  /* UNUSED */
 
 			BLI_scanfill_begin(&sf_ctx);
 
@@ -249,8 +250,7 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *em)
 			/* complete the loop */
 			BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert);
 
-			totfilltri = BLI_scanfill_calc_ex(&sf_ctx, 0, efa->no);
-			BLI_array_grow_items(looptris, totfilltri);
+			/* totfilltri = */ BLI_scanfill_calc_ex(&sf_ctx, 0, efa->no);
 
 			for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
 				BMLoop *l1 = sf_tri->v1->tmp.p;
@@ -274,6 +274,8 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *em)
 	em->tottri = i;
 	em->looptris = looptris;
 
+	BLI_assert(em->tottri <= looptris_tot);
+
 #undef USE_TESSFACE_SPEEDUP
 
 }
-- 
cgit v1.2.3


From f9b2788ddc5ab09bac12c9e2da10213eb3383650 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Thu, 27 Dec 2012 05:08:16 +0000
Subject: correction for poly_to_tri_count() when given zero poly count.

---
 source/blender/blenlib/intern/math_geom_inline.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenlib/intern/math_geom_inline.c b/source/blender/blenlib/intern/math_geom_inline.c
index 9bb824be85e..f32b477787b 100644
--- a/source/blender/blenlib/intern/math_geom_inline.c
+++ b/source/blender/blenlib/intern/math_geom_inline.c
@@ -173,9 +173,16 @@ MINLINE int min_axis_v3(const float vec[3])
  */
 MINLINE int poly_to_tri_count(const int poly_count, const int corner_count)
 {
-	const double poly_count_d   = (double)poly_count;
-	const double corner_count_d = (double)corner_count;
-	return (int)((((corner_count_d / poly_count_d) - 2.0) * poly_count_d) + 0.5);
+	if (poly_count != 0) {
+		const double poly_count_d   = (double)poly_count;
+		const double corner_count_d = (double)corner_count;
+		BLI_assert(poly_count   > 0);
+		BLI_assert(corner_count > 0);
+		return (int)((((corner_count_d / poly_count_d) - 2.0) * poly_count_d) + 0.5);
+	}
+	else {
+		return 0;
+	}
 }
 
 #endif /* __MATH_GEOM_INLINE_C__ */
-- 
cgit v1.2.3


From f0c1bc830c790f46fbe971ab7242dfb7b1cad469 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Thu, 27 Dec 2012 06:39:27 +0000
Subject: add option to BLI_scanfill_calc() - BLI_SCANFILL_CALC_HOLES, gives
 some speedup for BMesh ngons which never have holes and ensures predictable
 triangle count (totvert - 2), which is needed for pre-calculating array size.

---
 source/blender/blenkernel/intern/displist.c        |   2 +-
 source/blender/blenkernel/intern/editderivedmesh.c |  37 ++++---
 source/blender/blenkernel/intern/mask_rasterize.c  |   2 +-
 source/blender/blenkernel/intern/mesh.c            |  54 +++++-----
 source/blender/blenlib/BLI_scanfill.h              |   4 +
 source/blender/blenlib/intern/scanfill.c           | 109 +++++++++++++--------
 source/blender/windowmanager/intern/wm_gesture.c   |   2 +-
 7 files changed, 117 insertions(+), 93 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 47cb18a7172..5fff8a51214 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -506,7 +506,7 @@ void BKE_displist_fill(ListBase *dispbase, ListBase *to, int flipnormal)
 		}
 
 		/* XXX (obedit && obedit->actcol)?(obedit->actcol-1):0)) { */
-		if (totvert && (tot = BLI_scanfill_calc(&sf_ctx, BLI_SCANFILL_CALC_REMOVE_DOUBLES))) {
+		if (totvert && (tot = BLI_scanfill_calc(&sf_ctx, BLI_SCANFILL_CALC_REMOVE_DOUBLES | BLI_SCANFILL_CALC_HOLES))) {
 			if (tot) {
 				dlnew = MEM_callocN(sizeof(DispList), "filldisplist");
 				dlnew->type = DL_INDEX3;
diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
index fc0c40878db..1c43b418a1c 100644
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ b/source/blender/blenkernel/intern/editderivedmesh.c
@@ -173,12 +173,10 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *em)
 			i += 1;
 #else
 			/* more cryptic but faster */
-			{
-				BMLoop **l_ptr = looptris[i++];
-				l_ptr[0] = l = BM_FACE_FIRST_LOOP(efa);
-				l_ptr[1] = l = l->next;
-				l_ptr[2] = l->next;
-			}
+			BMLoop **l_ptr = looptris[i++];
+			l_ptr[0] = l = BM_FACE_FIRST_LOOP(efa);
+			l_ptr[1] = l = l->next;
+			l_ptr[2] = l->next;
 #endif
 		}
 		else if (efa->len == 4) {
@@ -201,14 +199,12 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *em)
 			i += 1;
 #else
 			/* more cryptic but faster */
-			{
-				BMLoop **l_ptr_a = looptris[i++];
-				BMLoop **l_ptr_b = looptris[i++];
-				(l_ptr_a[0] = l_ptr_b[0] = l = BM_FACE_FIRST_LOOP(efa));
-				(l_ptr_a[1]              = l = l->next);
-				(l_ptr_a[2] = l_ptr_b[1] = l = l->next);
-				(             l_ptr_b[2] = l->next);
-			}
+			BMLoop **l_ptr_a = looptris[i++];
+			BMLoop **l_ptr_b = looptris[i++];
+			(l_ptr_a[0] = l_ptr_b[0] = l = BM_FACE_FIRST_LOOP(efa));
+			(l_ptr_a[1]              = l = l->next);
+			(l_ptr_a[2] = l_ptr_b[1] = l = l->next);
+			(             l_ptr_b[2] = l->next);
 #endif
 		}
 
@@ -222,7 +218,7 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *em)
 			ScanFillVert *sf_vert, *sf_vert_last = NULL, *sf_vert_first = NULL;
 			/* ScanFillEdge *e; */ /* UNUSED */
 			ScanFillFace *sf_tri;
-			/* int totfilltri; */  /* UNUSED */
+			int totfilltri;
 
 			BLI_scanfill_begin(&sf_ctx);
 
@@ -250,9 +246,11 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *em)
 			/* complete the loop */
 			BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert);
 
-			/* totfilltri = */ BLI_scanfill_calc_ex(&sf_ctx, 0, efa->no);
+			totfilltri = BLI_scanfill_calc_ex(&sf_ctx, 0, efa->no);
+			BLI_assert(totfilltri <= efa->len - 2);
 
 			for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
+				BMLoop **l_ptr = looptris[i++];
 				BMLoop *l1 = sf_tri->v1->tmp.p;
 				BMLoop *l2 = sf_tri->v2->tmp.p;
 				BMLoop *l3 = sf_tri->v3->tmp.p;
@@ -261,10 +259,9 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *em)
 				if (BM_elem_index_get(l2) > BM_elem_index_get(l3)) { SWAP(BMLoop *, l2, l3); }
 				if (BM_elem_index_get(l1) > BM_elem_index_get(l2)) { SWAP(BMLoop *, l1, l2); }
 
-				looptris[i][0] = l1;
-				looptris[i][1] = l2;
-				looptris[i][2] = l3;
-				i += 1;
+				l_ptr[0] = l1;
+				l_ptr[1] = l2;
+				l_ptr[2] = l3;
 			}
 
 			BLI_scanfill_end(&sf_ctx);
diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c
index 2fa928e7c07..73452b216ff 100644
--- a/source/blender/blenkernel/intern/mask_rasterize.c
+++ b/source/blender/blenkernel/intern/mask_rasterize.c
@@ -933,7 +933,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas
 			}
 
 			/* main scan-fill */
-			sf_tri_tot = BLI_scanfill_calc_ex(&sf_ctx, 0, zvec);
+			sf_tri_tot = BLI_scanfill_calc_ex(&sf_ctx, BLI_SCANFILL_CALC_HOLES, zvec);
 
 			face_array = MEM_mallocN(sizeof(*face_array) * (sf_tri_tot + tot_feather_quads), "maskrast_face_index");
 			face_index = 0;
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 3eb96f218e4..f788bbabf4d 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -2488,7 +2488,7 @@ void BKE_mesh_loops_to_mface_corners(CustomData *fdata, CustomData *ldata,
  */
 int BKE_mesh_recalc_tessellation(CustomData *fdata,
                                  CustomData *ldata, CustomData *pdata,
-                                 MVert *mvert, int totface, int UNUSED(totloop),
+                                 MVert *mvert, int totface, int totloop,
                                  int totpoly,
                                  /* when tessellating to recalculate normals after
                                   * we can skip copying here */
@@ -2503,15 +2503,15 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata,
 #define TESSFACE_SCANFILL (1 << 0)
 #define TESSFACE_IS_QUAD  (1 << 1)
 
+	const int looptris_tot = poly_to_tri_count(totpoly, totloop);
+
 	MPoly *mp, *mpoly;
 	MLoop *ml, *mloop;
-	MFace *mface = NULL, *mf;
-	BLI_array_declare(mface);
+	MFace *mface, *mf;
 	ScanFillContext sf_ctx;
 	ScanFillVert *sf_vert, *sf_vert_last, *sf_vert_first;
 	ScanFillFace *sf_tri;
-	int *mface_to_poly_map = NULL;
-	BLI_array_declare(mface_to_poly_map);
+	int *mface_to_poly_map;
 	int lindex[4]; /* only ever use 3 in this case */
 	int poly_index, j, mface_index;
 
@@ -2525,8 +2525,9 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata,
 
 	/* allocate the length of totfaces, avoid many small reallocs,
 	 * if all faces are tri's it will be correct, quads == 2x allocs */
-	BLI_array_reserve(mface_to_poly_map, totpoly);
-	BLI_array_reserve(mface, totpoly);
+	/* take care. we are _not_ calloc'ing so be sure to initialize each field */
+	mface_to_poly_map = MEM_mallocN(sizeof(*mface_to_poly_map) * looptris_tot, __func__);
+	mface             = MEM_mallocN(sizeof(*mface) *             looptris_tot, __func__);
 
 	mface_index = 0;
 	mp = mpoly;
@@ -2538,8 +2539,6 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata,
 #ifdef USE_TESSFACE_SPEEDUP
 
 #define ML_TO_MF(i1, i2, i3)                                                  \
-		BLI_array_grow_one(mface_to_poly_map);                                \
-		BLI_array_grow_one(mface);                                            \
 		mface_to_poly_map[mface_index] = poly_index;                          \
 		mf = &mface[mface_index];                                             \
 		/* set loop indices, transformed to vert indices later */             \
@@ -2549,12 +2548,11 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata,
 		mf->v4 = 0;                                                           \
 		mf->mat_nr = mp->mat_nr;                                              \
 		mf->flag = mp->flag;                                                  \
+		mf->edcode = 0;                                                       \
 		(void)0
 
 /* ALMOST IDENTICAL TO DEFINE ABOVE (see EXCEPTION) */
 #define ML_TO_MF_QUAD()                                                       \
-		BLI_array_grow_one(mface_to_poly_map);                                \
-		BLI_array_grow_one(mface);                                            \
 		mface_to_poly_map[mface_index] = poly_index;                          \
 		mf = &mface[mface_index];                                             \
 		/* set loop indices, transformed to vert indices later */             \
@@ -2564,7 +2562,7 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata,
 		mf->v4 = mp->loopstart + 3; /* EXCEPTION */                           \
 		mf->mat_nr = mp->mat_nr;                                              \
 		mf->flag = mp->flag;                                                  \
-		mf->edcode |= TESSFACE_IS_QUAD; /* EXCEPTION */                       \
+		mf->edcode = TESSFACE_IS_QUAD; /* EXCEPTION */                        \
 		(void)0
 
 
@@ -2607,29 +2605,26 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata,
 			BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert_first);
 			
 			totfilltri = BLI_scanfill_calc(&sf_ctx, 0);
-			if (totfilltri) {
-				BLI_array_grow_items(mface_to_poly_map, totfilltri);
-				BLI_array_grow_items(mface, totfilltri);
+			BLI_assert(totfilltri <= mp->totloop - 2);
 
-				for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next, mf++) {
-					mface_to_poly_map[mface_index] = poly_index;
-					mf = &mface[mface_index];
+			for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next, mf++) {
+				mface_to_poly_map[mface_index] = poly_index;
+				mf = &mface[mface_index];
 
-					/* set loop indices, transformed to vert indices later */
-					mf->v1 = sf_tri->v1->keyindex;
-					mf->v2 = sf_tri->v2->keyindex;
-					mf->v3 = sf_tri->v3->keyindex;
-					mf->v4 = 0;
+				/* set loop indices, transformed to vert indices later */
+				mf->v1 = sf_tri->v1->keyindex;
+				mf->v2 = sf_tri->v2->keyindex;
+				mf->v3 = sf_tri->v3->keyindex;
+				mf->v4 = 0;
 
-					mf->mat_nr = mp->mat_nr;
-					mf->flag = mp->flag;
+				mf->mat_nr = mp->mat_nr;
+				mf->flag = mp->flag;
 
 #ifdef USE_TESSFACE_SPEEDUP
-					mf->edcode |= TESSFACE_SCANFILL; /* tag for sorting loop indices */
+				mf->edcode = TESSFACE_SCANFILL; /* tag for sorting loop indices */
 #endif
 
-					mface_index++;
-				}
+				mface_index++;
 			}
 	
 			BLI_scanfill_end(&sf_ctx);
@@ -2639,9 +2634,10 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata,
 	CustomData_free(fdata, totface);
 	totface = mface_index;
 
+	BLI_assert(totface <= looptris_tot);
 
 	/* not essential but without this we store over-alloc'd memory in the CustomData layers */
-	if (LIKELY((MEM_allocN_len(mface) / sizeof(*mface)) != totface)) {
+	if (LIKELY(looptris_tot != totface)) {
 		mface = MEM_reallocN(mface, sizeof(*mface) * totface);
 		mface_to_poly_map = MEM_reallocN(mface_to_poly_map, sizeof(*mface_to_poly_map) * totface);
 	}
diff --git a/source/blender/blenlib/BLI_scanfill.h b/source/blender/blenlib/BLI_scanfill.h
index c8fd72bbbd2..5204e0dd718 100644
--- a/source/blender/blenlib/BLI_scanfill.h
+++ b/source/blender/blenlib/BLI_scanfill.h
@@ -101,6 +101,10 @@ enum {
 	 * Assumes ordered edges, otherwise we risk an eternal loop
 	 * removing double verts. - campbell */
 	BLI_SCANFILL_CALC_REMOVE_DOUBLES   = (1 << 1),
+
+	/* note: This flag removes checks for overlapping polygons.
+	 * when this flag is set, we'll never get back more faces then (totvert - 2)*/
+	BLI_SCANFILL_CALC_HOLES            = (1 << 2)
 };
 
 int BLI_scanfill_begin(ScanFillContext *sf_ctx);
diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c
index defe500cb21..45c6c5efbb3 100644
--- a/source/blender/blenlib/intern/scanfill.c
+++ b/source/blender/blenlib/intern/scanfill.c
@@ -630,7 +630,12 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag)
 
 	/* (temporal) security: never much more faces than vertices */
 	totface = 0;
-	maxface = 2 * verts;       /* 2*verts: based at a filled circle within a triangle */
+	if (flag & BLI_SCANFILL_CALC_HOLES) {
+		maxface = 2 * verts;       /* 2*verts: based at a filled circle within a triangle */
+	}
+	else {
+		maxface = verts - 2;       /* when we don't calc any holes, we assume face is a non overlapping loop */
+	}
 
 	sc = sf_ctx->_scdata;
 	for (a = 0; a < verts; a++) {
@@ -654,7 +659,7 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag)
 			
 			/* commented out... the ESC here delivers corrupted memory (and doesnt work during grab) */
 			/* if (callLocalInterruptCallBack()) break; */
-			if (totface > maxface) {
+			if (totface >= maxface) {
 				/* printf("Fill error: endless loop. Escaped at vert %d,  tot: %d.\n", a, verts); */
 				a = verts;
 				break;
@@ -684,15 +689,16 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag)
 				for (b = a + 1; b < verts; b++) {
 					if (sc1->vert->f == 0) {
 						if (sc1->vert->xy[1] <= miny) break;
-
-						if (testedgeside(v1->xy, v2->xy, sc1->vert->xy))
-							if (testedgeside(v2->xy, v3->xy, sc1->vert->xy))
+						if (testedgeside(v1->xy, v2->xy, sc1->vert->xy)) {
+							if (testedgeside(v2->xy, v3->xy, sc1->vert->xy)) {
 								if (testedgeside(v3->xy, v1->xy, sc1->vert->xy)) {
 									/* point in triangle */
-								
+
 									test = 1;
 									break;
 								}
+							}
+						}
 					}
 					sc1++;
 				}
@@ -773,12 +779,15 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag)
 				ed1 = nexted;
 			}
 		}
+
 		sc++;
 	}
 
 	MEM_freeN(sf_ctx->_scdata);
 	sf_ctx->_scdata = NULL;
 
+	BLI_assert(totface <= maxface);
+
 	return totface;
 }
 
@@ -910,50 +919,68 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float no
 
 
 	/* STEP 1: COUNT POLYS */
-	eve = sf_ctx->fillvertbase.first;
-	while (eve) {
-		eve->xy[0] = eve->co[co_x];
-		eve->xy[1] = eve->co[co_y];
+	if (flag & BLI_SCANFILL_CALC_HOLES) {
+		eve = sf_ctx->fillvertbase.first;
+		while (eve) {
+			eve->xy[0] = eve->co[co_x];
+			eve->xy[1] = eve->co[co_y];
+
+			/* get first vertex with no poly number */
+			if (eve->poly_nr == 0) {
+				poly++;
+				/* now a sort of select connected */
+				ok = 1;
+				eve->poly_nr = poly;
 
-		/* get first vertex with no poly number */
-		if (eve->poly_nr == 0) {
-			poly++;
-			/* now a sort of select connected */
-			ok = 1;
-			eve->poly_nr = poly;
-			
-			while (ok) {
-				
-				ok = 0;
-				toggle++;
-				if (toggle & 1) eed = sf_ctx->filledgebase.first;
-				else eed = sf_ctx->filledgebase.last;
-
-				while (eed) {
-					if (eed->v1->poly_nr == 0 && eed->v2->poly_nr == poly) {
-						eed->v1->poly_nr = poly;
-						eed->poly_nr = poly;
-						ok = 1;
-					}
-					else if (eed->v2->poly_nr == 0 && eed->v1->poly_nr == poly) {
-						eed->v2->poly_nr = poly;
-						eed->poly_nr = poly;
-						ok = 1;
-					}
-					else if (eed->poly_nr == 0) {
-						if (eed->v1->poly_nr == poly && eed->v2->poly_nr == poly) {
+				while (ok) {
+
+					ok = 0;
+					toggle++;
+					if (toggle & 1) eed = sf_ctx->filledgebase.first;
+					else eed = sf_ctx->filledgebase.last;
+
+					while (eed) {
+						if (eed->v1->poly_nr == 0 && eed->v2->poly_nr == poly) {
+							eed->v1->poly_nr = poly;
 							eed->poly_nr = poly;
 							ok = 1;
 						}
+						else if (eed->v2->poly_nr == 0 && eed->v1->poly_nr == poly) {
+							eed->v2->poly_nr = poly;
+							eed->poly_nr = poly;
+							ok = 1;
+						}
+						else if (eed->poly_nr == 0) {
+							if (eed->v1->poly_nr == poly && eed->v2->poly_nr == poly) {
+								eed->poly_nr = poly;
+								ok = 1;
+							}
+						}
+						if (toggle & 1) eed = eed->next;
+						else eed = eed->prev;
 					}
-					if (toggle & 1) eed = eed->next;
-					else eed = eed->prev;
 				}
 			}
+			eve = eve->next;
+		}
+		/* printf("amount of poly's: %d\n",poly); */
+	}
+	else {
+		poly = 1;
+
+		eve = sf_ctx->fillvertbase.first;
+		while (eve) {
+			eve->xy[0] = eve->co[co_x];
+			eve->xy[1] = eve->co[co_y];
+			eve->poly_nr = poly;
+			eve = eve->next;
+		}
+		eed = sf_ctx->filledgebase.first;
+		while (eed) {
+			eed->poly_nr = poly;
+			eed = eed->next;
 		}
-		eve = eve->next;
 	}
-	/* printf("amount of poly's: %d\n",poly); */
 
 	/* STEP 2: remove loose edges and strings of edges */
 	eed = sf_ctx->filledgebase.first;
diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c
index 1cf44a69c17..168c2312d9f 100644
--- a/source/blender/windowmanager/intern/wm_gesture.c
+++ b/source/blender/windowmanager/intern/wm_gesture.c
@@ -258,7 +258,7 @@ static void draw_filled_lasso(wmGesture *gt)
 	if (sf_vert_first) {
 		const float zvec[3] = {0.0f, 0.0f, 1.0f};
 		BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert);
-		BLI_scanfill_calc_ex(&sf_ctx, BLI_SCANFILL_CALC_REMOVE_DOUBLES, zvec);
+		BLI_scanfill_calc_ex(&sf_ctx, BLI_SCANFILL_CALC_REMOVE_DOUBLES | BLI_SCANFILL_CALC_HOLES, zvec);
 	
 		glEnable(GL_BLEND);
 		glColor4f(1.0, 1.0, 1.0, 0.05);
-- 
cgit v1.2.3


From daa2a0d1c3099c85b4235c6e3f9af0b5ee60de24 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Thu, 27 Dec 2012 07:27:28 +0000
Subject: use keyword args for bmesh.update_edit_mesh(...)

---
 source/blender/python/bmesh/bmesh_py_api.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

(limited to 'source')

diff --git a/source/blender/python/bmesh/bmesh_py_api.c b/source/blender/python/bmesh/bmesh_py_api.c
index 9abb13731af..ce8153fb994 100644
--- a/source/blender/python/bmesh/bmesh_py_api.c
+++ b/source/blender/python/bmesh/bmesh_py_api.c
@@ -110,14 +110,17 @@ PyDoc_STRVAR(bpy_bm_update_edit_mesh_doc,
 "   :arg destructive: Use when grometry has been added or removed.\n"
 "   :type destructive: boolean\n"
 );
-static PyObject *bpy_bm_update_edit_mesh(PyObject *UNUSED(self), PyObject *args)
+static PyObject *bpy_bm_update_edit_mesh(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
 {
+	static const char *kwlist[] = {"mesh", "tessface", "destructive", NULL};
 	PyObject *py_me;
 	Mesh *me;
 	int do_tessface = TRUE;
 	int is_destructive = TRUE;
 
-	if (!PyArg_ParseTuple(args, "O|ii:update_edit_mesh", &py_me, &do_tessface, &is_destructive)) {
+	if (!PyArg_ParseTupleAndKeywords(args, kw, "O|ii:update_edit_mesh", (char **)kwlist,
+	                                 &py_me, &do_tessface, &is_destructive))
+	{
 		return NULL;
 	}
 
@@ -144,7 +147,7 @@ static PyObject *bpy_bm_update_edit_mesh(PyObject *UNUSED(self), PyObject *args)
 static struct PyMethodDef BPy_BM_methods[] = {
 	{"new",            (PyCFunction)bpy_bm_new,            METH_NOARGS,  bpy_bm_new_doc},
 	{"from_edit_mesh", (PyCFunction)bpy_bm_from_edit_mesh, METH_O,       bpy_bm_from_edit_mesh_doc},
-	{"update_edit_mesh", (PyCFunction)bpy_bm_update_edit_mesh, METH_VARARGS, bpy_bm_update_edit_mesh_doc},
+	{"update_edit_mesh", (PyCFunction)bpy_bm_update_edit_mesh, METH_VARARGS | METH_KEYWORDS, bpy_bm_update_edit_mesh_doc},
 	{NULL, NULL, 0, NULL}
 };
 
-- 
cgit v1.2.3


From 1f4fda10ced4c6a10e93a5983eec544d364a5ca9 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Thu, 27 Dec 2012 12:40:02 +0000
Subject: validate operator names on startup (debug mode only)

---
 source/blender/makesrna/intern/rna_define.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

(limited to 'source')

diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c
index bb1ecea6a24..b8f791323a0 100644
--- a/source/blender/makesrna/intern/rna_define.c
+++ b/source/blender/makesrna/intern/rna_define.c
@@ -631,7 +631,7 @@ StructRNA *RNA_def_struct(BlenderRNA *brna, const char *identifier, const char *
 	if (DefRNA.preprocess) {
 		char error[512];
 
-		if (rna_validate_identifier(identifier, error, 0) == 0) {
+		if (rna_validate_identifier(identifier, error, FALSE) == 0) {
 			fprintf(stderr, "%s: struct identifier \"%s\" error - %s\n", __func__, identifier, error);
 			DefRNA.error = 1;
 		}
@@ -909,7 +909,7 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier
 	if (DefRNA.preprocess) {
 		char error[512];
 		
-		if (rna_validate_identifier(identifier, error, 1) == 0) {
+		if (rna_validate_identifier(identifier, error, TRUE) == 0) {
 			fprintf(stderr, "%s: property identifier \"%s.%s\" - %s\n", __func__,
 			        CONTAINER_RNA_ID(cont), identifier, error);
 			DefRNA.error = 1;
@@ -926,6 +926,16 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier
 		dprop = MEM_callocN(sizeof(PropertyDefRNA), "PropertyDefRNA");
 		rna_addtail(&dcont->properties, dprop);
 	}
+	else {
+#ifdef DEBUG
+		char error[512];
+		if (rna_validate_identifier(identifier, error, TRUE) == 0) {
+			fprintf(stderr, "%s: runtime property identifier \"%s.%s\" - %s\n", __func__,
+			        CONTAINER_RNA_ID(cont), identifier, error);
+			DefRNA.error = 1;
+		}
+#endif
+	}
 
 	prop = MEM_callocN(rna_property_type_sizeof(type), "PropertyRNA");
 
@@ -2674,7 +2684,7 @@ static FunctionRNA *rna_def_function(StructRNA *srna, const char *identifier)
 	if (DefRNA.preprocess) {
 		char error[512];
 
-		if (rna_validate_identifier(identifier, error, 0) == 0) {
+		if (rna_validate_identifier(identifier, error, FALSE) == 0) {
 			fprintf(stderr, "%s: function identifier \"%s\" - %s\n", __func__, identifier, error);
 			DefRNA.error = 1;
 		}
-- 
cgit v1.2.3


From 16411da41e40cc5205adef6052e95f6e587daf2c Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Thu, 27 Dec 2012 15:07:19 +0000
Subject: New features!

- Packing .blend files

If you work a lot with dynamic linked .blend files ("Libraries"), it's always hard to
share your work with others (or for bug reports!).
This new option packs all used external .blend files, and - on save - combines it together
in one .blend file. You can save that file on any location.

Loading a packed .blend file then loads all library data usual - not editable.

Just use unpack to save out all linked .blend files. This will only save out the files
according the directory structure as was used on linking - relative to the current .blend.
It will create new directories, so be careful with unpacking when relative paths go up.

This feature also works fine for linked compressed .blend files.

It also works for many levels deep linked .blend hierarchies.

Access is hidden for now - I need to get some people to give it serious testing first.
You can find the options via spacebar search (try pack or unpack).

- Packed data and Undo

Now all packed data is excluded from the Undo buffer storage. Keeps undo memory smaller
and makes faster redo possible.
---
 source/blender/blenkernel/BKE_packedFile.h       |   2 +
 source/blender/blenkernel/intern/bpath.c         |   7 +-
 source/blender/blenkernel/intern/packedFile.c    |  37 +++++
 source/blender/blenloader/intern/readblenentry.c |   6 +
 source/blender/blenloader/intern/readfile.c      | 180 ++++++++++++++++++++---
 source/blender/blenloader/intern/readfile.h      |   6 +
 source/blender/blenloader/intern/writefile.c     |  33 +++--
 source/blender/editors/space_info/info_intern.h  |   4 +
 source/blender/editors/space_info/info_ops.c     |  70 ++++++++-
 source/blender/editors/space_info/space_info.c   |   3 +
 source/blender/makesdna/DNA_ID.h                 |   3 +
 11 files changed, 314 insertions(+), 37 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/BKE_packedFile.h b/source/blender/blenkernel/BKE_packedFile.h
index 603cb1f22a6..9dcbb41c7dc 100644
--- a/source/blender/blenkernel/BKE_packedFile.h
+++ b/source/blender/blenkernel/BKE_packedFile.h
@@ -48,6 +48,7 @@ struct PackedFile *newPackedFile(struct ReportList *reports, const char *filenam
 struct PackedFile *newPackedFileMemory(void *mem, int memlen);
 
 void packAll(struct Main *bmain, struct ReportList *reports);
+void packLibraries(struct Main *bmain, struct ReportList *reports);
 
 /* unpack */
 char *unpackFile(struct ReportList *reports, const char *abs_name, const char *local_name, struct PackedFile *pf, int how);
@@ -55,6 +56,7 @@ int unpackVFont(struct ReportList *reports, struct VFont *vfont, int how);
 int unpackSound(struct Main *bmain, struct ReportList *reports, struct bSound *sound, int how);
 int unpackImage(struct ReportList *reports, struct Image *ima, int how);
 void unpackAll(struct Main *bmain, struct ReportList *reports, int how);
+int unpackLibraries(struct Main *bmain, struct ReportList *reports);
 
 int writePackedFile(struct ReportList *reports, const char *filename, struct PackedFile *pf, int guimode);
 
diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c
index f8ee955ab50..bb610ede9f7 100644
--- a/source/blender/blenkernel/intern/bpath.c
+++ b/source/blender/blenkernel/intern/bpath.c
@@ -588,8 +588,11 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
 		case ID_LI:
 		{
 			Library *lib = (Library *)id;
-			if (rewrite_path_fixed(lib->name, visit_cb, absbase, bpath_user_data)) {
-				BKE_library_filepath_set(lib, lib->name);
+			/* keep packedfile paths always relative to the blend */
+			if (lib->packedfile == NULL) {
+				if (rewrite_path_fixed(lib->name, visit_cb, absbase, bpath_user_data)) {
+					BKE_library_filepath_set(lib, lib->name);
+				}
 			}
 			break;
 		}
diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c
index dec49f417ae..9f77094994d 100644
--- a/source/blender/blenkernel/intern/packedFile.c
+++ b/source/blender/blenkernel/intern/packedFile.c
@@ -43,6 +43,7 @@
 #include "MEM_guardedalloc.h"
 
 #include "DNA_image_types.h"
+#include "DNA_ID.h"
 #include "DNA_sound_types.h"
 #include "DNA_vfont_types.h"
 #include "DNA_packedFile_types.h"
@@ -226,6 +227,7 @@ PackedFile *newPackedFile(ReportList *reports, const char *filename, const char
 	return (pf);
 }
 
+/* no libraries for now */
 void packAll(Main *bmain, ReportList *reports)
 {
 	Image *ima;
@@ -538,6 +540,41 @@ int unpackImage(ReportList *reports, Image *ima, int how)
 	return(ret_value);
 }
 
+int unpackLibraries(Main *bmain, ReportList *reports)
+{
+	Library *lib;
+	char *newname;
+	int ret_value = RET_ERROR;
+	
+	for (lib = bmain->library.first; lib; lib = lib->id.next) {
+		if (lib->packedfile && lib->name[0]) {
+			
+			newname = unpackFile(reports, lib->filepath, lib->filepath, lib->packedfile, PF_WRITE_ORIGINAL);
+			if (newname != NULL) {
+				ret_value = RET_OK;
+				
+				printf("Saved .blend library: %s\n", newname);
+				
+				freePackedFile(lib->packedfile);
+				lib->packedfile = NULL;
+
+				MEM_freeN(newname);
+			}
+		}
+	}
+	
+	return(ret_value);
+}
+
+void packLibraries(Main *bmain, ReportList *reports)
+{
+	Library *lib;
+	
+	for (lib = bmain->library.first; lib; lib = lib->id.next)
+		if (lib->packedfile == NULL)
+			lib->packedfile = newPackedFile(reports, lib->name, bmain->name);
+}
+
 void unpackAll(Main *bmain, ReportList *reports, int how)
 {
 	Image *ima;
diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c
index e9caa337129..b2d37e36004 100644
--- a/source/blender/blenloader/intern/readblenentry.c
+++ b/source/blender/blenloader/intern/readblenentry.c
@@ -311,6 +311,9 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain, const char *filename, MemFil
 		/* makes lookup of existing video clips in old main */
 		blo_make_movieclip_pointer_map(fd, oldmain);
 		
+		/* makes lookup of existing video clips in old main */
+		blo_make_packed_pointer_map(fd, oldmain);
+		
 		bfd = blo_read_file_internal(fd, filename);
 		
 		/* ensures relinked images are not freed */
@@ -319,6 +322,9 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain, const char *filename, MemFil
 		/* ensures relinked movie clips are not freed */
 		blo_end_movieclip_pointer_map(fd, oldmain);
 		
+		/* ensures relinked packed data is not freed */
+		blo_end_packed_pointer_map(fd, oldmain);
+		
 		/* move libraries from old main to new main */
 		if (bfd && mainlist.first != mainlist.last) {
 			
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 87eaab387a2..c62acb57fda 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -543,7 +543,9 @@ static Main *blo_find_main(FileData *fd, const char *filepath, const char *relab
 	
 	BLI_strncpy(name1, filepath, sizeof(name1));
 	cleanup_path(relabase, name1);
-//	printf("blo_find_main: original in  %s\n", name);
+	
+//	printf("blo_find_main: relabase  %s\n", relabase);
+//	printf("blo_find_main: original in  %s\n", filepath);
 //	printf("blo_find_main: converted to %s\n", name1);
 	
 	for (m = mainlist->first; m; m = m->next) {
@@ -1020,6 +1022,46 @@ FileData *blo_openblenderfile(const char *filepath, ReportList *reports)
 	}
 }
 
+static int fd_read_gzip_from_memory(FileData *filedata, void *buffer, unsigned int size)
+{
+	int err;
+	
+	filedata->strm.next_out = (Bytef *) buffer;
+    filedata->strm.avail_out = size;
+	
+    // Inflate another chunk.
+    err = inflate (&filedata->strm, Z_SYNC_FLUSH);
+	
+    if (err == Z_STREAM_END) {
+		return 0;
+	}
+    else if (err != Z_OK)  {
+		printf("fd_read_gzip_from_memory: zlib error\n");
+		return 0;
+    }
+	
+	filedata->seek += size;
+	
+	return (size);
+}
+
+static int fd_read_gzip_from_memory_init(FileData *fd)
+{
+
+	fd->strm.next_in = (Bytef *) fd->buffer;
+	fd->strm.avail_in = fd->buffersize;
+	fd->strm.total_out = 0;
+	fd->strm.zalloc = Z_NULL;
+	fd->strm.zfree = Z_NULL;
+	
+	if (inflateInit2(&fd->strm, (16+MAX_WBITS)) != Z_OK)
+		return 0;
+
+	fd->read = fd_read_gzip_from_memory;
+	
+	return 1;
+}
+
 FileData *blo_openblendermemory(void *mem, int memsize, ReportList *reports)
 {
 	if (!mem || memsizebuffer = mem;
 		fd->buffersize = memsize;
-		fd->read = fd_read_from_memory;
-		fd->flags |= FD_FLAGS_NOT_MY_BUFFER;
 		
+		/* test if gzip */
+		if (cp[0] == 0x1f && cp[1] == 0x8b) {
+			if (0 == fd_read_gzip_from_memory_init(fd)) {
+				blo_freefiledata(fd);
+				return NULL;
+			}
+		}
+		else
+			fd->read = fd_read_from_memory;
+			
+		fd->flags |= FD_FLAGS_NOT_MY_BUFFER;
+
 		return blo_decode_and_check(fd, reports);
 	}
 }
@@ -1066,6 +1120,12 @@ void blo_freefiledata(FileData *fd)
 			gzclose(fd->gzfiledes);
 		}
 		
+		if (fd->strm.next_in) {
+			if (inflateEnd (&fd->strm) != Z_OK) {
+				printf("close gzip stream error\n");
+			}
+		}
+		
 		if (fd->buffer && !(fd->flags & FD_FLAGS_NOT_MY_BUFFER)) {
 			MEM_freeN(fd->buffer);
 			fd->buffer = NULL;
@@ -1154,25 +1214,33 @@ static void *newdataadr(FileData *fd, void *adr)		/* only direct databocks */
 	return oldnewmap_lookup_and_inc(fd->datamap, adr);
 }
 
-static void *newglobadr(FileData *fd, void *adr)		/* direct datablocks with global linking */
+static void *newglobadr(FileData *fd, void *adr)	    /* direct datablocks with global linking */
 {
 	return oldnewmap_lookup_and_inc(fd->globmap, adr);
 }
 
-static void *newimaadr(FileData *fd, void *adr)		/* used to restore image data after undo */
+static void *newimaadr(FileData *fd, void *adr)		    /* used to restore image data after undo */
 {
 	if (fd->imamap && adr)
 		return oldnewmap_lookup_and_inc(fd->imamap, adr);
 	return NULL;
 }
 
-static void *newmclipadr(FileData *fd, void *adr)              /* used to restore movie clip data after undo */
+static void *newmclipadr(FileData *fd, void *adr)      /* used to restore movie clip data after undo */
 {
 	if (fd->movieclipmap && adr)
 		return oldnewmap_lookup_and_inc(fd->movieclipmap, adr);
 	return NULL;
 }
 
+static void *newpackedadr(FileData *fd, void *adr)      /* used to restore packed data after undo */
+{
+	if (fd->packedmap && adr)
+		return oldnewmap_lookup_and_inc(fd->packedmap, adr);
+	
+	return oldnewmap_lookup_and_inc(fd->datamap, adr);
+}
+
 
 static void *newlibadr(FileData *fd, void *lib, void *adr)		/* only lib data */
 {
@@ -1369,6 +1437,69 @@ void blo_end_movieclip_pointer_map(FileData *fd, Main *oldmain)
 	}
 }
 
+static void insert_packedmap(FileData *fd, PackedFile *pf)
+{
+	oldnewmap_insert(fd->packedmap, pf, pf, 0);
+	oldnewmap_insert(fd->packedmap, pf->data, pf->data, 0);
+}
+
+void blo_make_packed_pointer_map(FileData *fd, Main *oldmain)
+{
+	Image *ima;
+	VFont *vfont;
+	bSound *sound;
+	Library *lib;
+	
+	fd->packedmap = oldnewmap_new();
+	
+	for (ima = oldmain->image.first; ima; ima = ima->id.next)
+		if (ima->packedfile)
+			insert_packedmap(fd, ima->packedfile);
+			
+	for (vfont = oldmain->vfont.first; vfont; vfont = vfont->id.next)
+		if (vfont->packedfile)
+			insert_packedmap(fd, vfont->packedfile);
+	
+	for (sound = oldmain->sound.first; sound; sound = sound->id.next)
+		if (sound->packedfile)
+			insert_packedmap(fd, sound->packedfile);
+	
+	for (lib = oldmain->library.first; lib; lib = lib->id.next)
+		if (lib->packedfile)
+			insert_packedmap(fd, lib->packedfile);
+
+}
+
+/* set old main packed data to zero if it has been restored */
+/* this works because freeing old main only happens after this call */
+void blo_end_packed_pointer_map(FileData *fd, Main *oldmain)
+{
+	Image *ima;
+	VFont *vfont;
+	bSound *sound;
+	Library *lib;
+	OldNew *entry = fd->packedmap->entries;
+	int i;
+	
+	/* used entries were restored, so we put them to zero */
+	for (i=0; i < fd->packedmap->nentries; i++, entry++) {
+		if (entry->nr > 0)
+			entry->newp = NULL;
+	}
+	
+	for (ima = oldmain->image.first; ima; ima = ima->id.next)
+		ima->packedfile = newpackedadr(fd, ima->packedfile);
+	
+	for (vfont = oldmain->vfont.first; vfont; vfont = vfont->id.next)
+		vfont->packedfile = newpackedadr(fd, vfont->packedfile);
+
+	for (sound = oldmain->sound.first; sound; sound = sound->id.next)
+		sound->packedfile = newpackedadr(fd, sound->packedfile);
+		
+	for (lib = oldmain->library.first; lib; lib = lib->id.next)
+		lib->packedfile = newpackedadr(fd, lib->packedfile);
+}
+
 
 /* undo file support: add all library pointers in lookup */
 void blo_add_library_pointer_map(ListBase *mainlist, FileData *fd)
@@ -1708,10 +1839,10 @@ static void direct_link_script(FileData *UNUSED(fd), Script *script)
 
 static PackedFile *direct_link_packedfile(FileData *fd, PackedFile *oldpf)
 {
-	PackedFile *pf = newdataadr(fd, oldpf);
+	PackedFile *pf = newpackedadr(fd, oldpf);
 	
 	if (pf) {
-		pf->data = newdataadr(fd, pf->data);
+		pf->data = newpackedadr(fd, pf->data);
 	}
 	
 	return pf;
@@ -6031,6 +6162,7 @@ static void direct_link_library(FileData *fd, Library *lib, Main *main)
 {
 	Main *newmain;
 	
+	/* check if the library was already read */
 	for (newmain = fd->mainlist->first; newmain; newmain = newmain->next) {
 		if (newmain->curlib) {
 			if (BLI_path_cmp(newmain->curlib->filepath, lib->filepath) == 0) {
@@ -6049,14 +6181,14 @@ static void direct_link_library(FileData *fd, Library *lib, Main *main)
 			}
 		}
 	}
-	/* make sure we have full path in lib->filename */
+	/* make sure we have full path in lib->filepath */
 	BLI_strncpy(lib->filepath, lib->name, sizeof(lib->name));
 	cleanup_path(fd->relabase, lib->filepath);
 	
-#if 0
-	printf("direct_link_library: name %s\n", lib->name);
-	printf("direct_link_library: filename %s\n", lib->filename);
-#endif
+//	printf("direct_link_library: name %s\n", lib->name);
+//	printf("direct_link_library: filepath %s\n", lib->filepath);
+	
+	lib->packedfile = direct_link_packedfile(fd, lib->packedfile);
 	
 	/* new main */
 	newmain= MEM_callocN(sizeof(Main), "directlink");
@@ -10014,12 +10146,26 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
 				FileData *fd = mainptr->curlib->filedata;
 				
 				if (fd == NULL) {
+					
 					/* printf and reports for now... its important users know this */
-					BKE_reportf_wrap(basefd->reports, RPT_INFO, TIP_("Read library:  '%s', '%s'"),
-					                 mainptr->curlib->filepath, mainptr->curlib->name);
 					
-					fd = blo_openblenderfile(mainptr->curlib->filepath, basefd->reports);
-
+					/* if packed file... */
+					if (mainptr->curlib->packedfile) {
+						PackedFile *pf = mainptr->curlib->packedfile;
+						
+						BKE_reportf_wrap(basefd->reports, RPT_INFO, TIP_("Read packed library:  '%s'"),
+										 mainptr->curlib->name);
+						fd = blo_openblendermemory(pf->data, pf->size, basefd->reports);
+						
+						
+						/* needed for library_append and read_libraries */
+						BLI_strncpy(fd->relabase, mainptr->curlib->filepath, sizeof(fd->relabase));
+					}
+					else {
+						BKE_reportf_wrap(basefd->reports, RPT_INFO, TIP_("Read library:  '%s', '%s'"),
+										 mainptr->curlib->filepath, mainptr->curlib->name);
+						fd = blo_openblenderfile(mainptr->curlib->filepath, basefd->reports);
+					}
 					/* allow typing in a new lib path */
 					if (G.debug_value == -666) {
 						while (fd == NULL) {
diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h
index a979a16220d..a0895c92b24 100644
--- a/source/blender/blenloader/intern/readfile.h
+++ b/source/blender/blenloader/intern/readfile.h
@@ -69,6 +69,9 @@ typedef struct FileData {
 	char headerdone;
 	int inbuffer;
 	
+	// gzip stream for memory decompression
+	z_stream strm;
+	
 	// general reading variables
 	struct SDNA *filesdna;
 	struct SDNA *memsdna;
@@ -83,6 +86,7 @@ typedef struct FileData {
 	struct OldNewMap *libmap;
 	struct OldNewMap *imamap;
 	struct OldNewMap *movieclipmap;
+	struct OldNewMap *packedmap;
 	
 	struct BHeadSort *bheadmap;
 	int tot_bheadmap;
@@ -127,6 +131,8 @@ void blo_make_image_pointer_map(FileData *fd, Main *oldmain);
 void blo_end_image_pointer_map(FileData *fd, Main *oldmain);
 void blo_make_movieclip_pointer_map(FileData *fd, Main *oldmain);
 void blo_end_movieclip_pointer_map(FileData *fd, Main *oldmain);
+void blo_make_packed_pointer_map(FileData *fd, Main *oldmain);
+void blo_end_packed_pointer_map(FileData *fd, Main *oldmain);
 void blo_add_library_pointer_map(ListBase *mainlist, FileData *fd);
 
 void blo_freefiledata(FileData *fd);
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 7ce10d1815f..61b75a49374 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -1508,7 +1508,7 @@ static void write_vfonts(WriteData *wd, ListBase *idbase)
 
 			/* direct data */
 
-			if (vf->packedfile) {
+			if (vf->packedfile && !wd->current) {
 				pf = vf->packedfile;
 				writestruct(wd, DATA, "PackedFile", 1, pf);
 				writedata(wd, DATA, pf->size, pf->data);
@@ -1958,7 +1958,7 @@ 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) {
+			if (ima->packedfile && !wd->current) {
 				pf = ima->packedfile;
 				writestruct(wd, DATA, "PackedFile", 1, pf);
 				writedata(wd, DATA, pf->size, pf->data);
@@ -2531,20 +2531,31 @@ static void write_libraries(WriteData *wd, Main *main)
 		a=tot= set_listbasepointers(main, lbarray);
 
 		/* test: is lib being used */
-		foundone = FALSE;
-		while (tot--) {
-			for (id= lbarray[tot]->first; id; id= id->next) {
-				if (id->us>0 && (id->flag & LIB_EXTERN)) {
-					foundone = TRUE;
-					break;
+		if (main->curlib && main->curlib->packedfile)
+			foundone = TRUE;
+		else {
+			foundone = FALSE;
+			while (tot--) {
+				for (id= lbarray[tot]->first; id; id= id->next) {
+					if (id->us>0 && (id->flag & LIB_EXTERN)) {
+						foundone = TRUE;
+						break;
+					}
 				}
+				if (foundone) break;
 			}
-			if (foundone) break;
 		}
-
+		
 		if (foundone) {
 			writestruct(wd, ID_LI, "Library", 1, main->curlib);
 
+			if (main->curlib->packedfile && !wd->current) {
+				PackedFile *pf = main->curlib->packedfile;
+				writestruct(wd, DATA, "PackedFile", 1, pf);
+				writedata(wd, DATA, pf->size, pf->data);
+				printf("write packed .blend: %s\n", main->curlib->name);
+			}
+			
 			while (a--) {
 				for (id= lbarray[a]->first; id; id= id->next) {
 					if (id->us>0 && (id->flag & LIB_EXTERN)) {
@@ -2673,7 +2684,7 @@ static void write_sounds(WriteData *wd, ListBase *idbase)
 			writestruct(wd, ID_SO, "bSound", 1, sound);
 			if (sound->id.properties) IDP_WriteProperty(sound->id.properties, wd);
 
-			if (sound->packedfile) {
+			if (sound->packedfile && !wd->current) {
 				pf = sound->packedfile;
 				writestruct(wd, DATA, "PackedFile", 1, pf);
 				writedata(wd, DATA, pf->size, pf->data);
diff --git a/source/blender/editors/space_info/info_intern.h b/source/blender/editors/space_info/info_intern.h
index 80018e849d3..62e9a3a7f73 100644
--- a/source/blender/editors/space_info/info_intern.h
+++ b/source/blender/editors/space_info/info_intern.h
@@ -39,11 +39,15 @@ struct ReportList;
 
 void FILE_OT_pack_all(struct wmOperatorType *ot);
 void FILE_OT_unpack_all(struct wmOperatorType *ot);
+void FILE_OT_pack_libraries(struct wmOperatorType *ot);
+void FILE_OT_unpack_libraries(struct wmOperatorType *ot);
+
 void FILE_OT_make_paths_relative(struct wmOperatorType *ot);
 void FILE_OT_make_paths_absolute(struct wmOperatorType *ot);
 void FILE_OT_report_missing_files(struct wmOperatorType *ot);
 void FILE_OT_find_missing_files(struct wmOperatorType *ot);
 
+
 void INFO_OT_reports_display_update(struct wmOperatorType *ot);
 
 /* info_draw.c */
diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c
index e902a4ea6f4..104349e172a 100644
--- a/source/blender/editors/space_info/info_ops.c
+++ b/source/blender/editors/space_info/info_ops.c
@@ -66,15 +66,70 @@
 
 #include "info_intern.h"
 
+/********************* pack blend file libararies operator *********************/
+
+static int pack_libraries_exec(bContext *C, wmOperator *op)
+{
+	Main *bmain = CTX_data_main(C);
+
+	packLibraries(bmain, op->reports);
+
+	return OPERATOR_FINISHED;
+}
+
+void FILE_OT_pack_libraries(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name = "Pack Blender Libraries";
+	ot->idname = "FILE_OT_pack_libraries";
+	ot->description = "Pack all used Blender library files into the current .blend";
+	
+	/* api callbacks */
+	ot->exec = pack_libraries_exec;
+
+	/* flags */
+	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int unpack_libraries_exec(bContext *C, wmOperator *op)
+{
+	Main *bmain = CTX_data_main(C);
+	
+	unpackLibraries(bmain, op->reports);
+	
+	return OPERATOR_FINISHED;
+}
+
+static int unpack_libraries_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+{
+	return WM_operator_confirm_message(C, op, "Unpack Blender Libraries - creates directories, all new paths should work");
+}
+
+void FILE_OT_unpack_libraries(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name = "Unpack Blender Libraries";
+	ot->idname = "FILE_OT_unpack_libraries";
+	ot->description = "Unpack all used Blender library files from this .blend file";
+	
+	/* api callbacks */
+	ot->invoke = unpack_libraries_invoke;
+	ot->exec = unpack_libraries_exec;
+	
+	/* flags */
+	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+
 /********************* pack all operator *********************/
 
 static int pack_all_exec(bContext *C, wmOperator *op)
 {
 	Main *bmain = CTX_data_main(C);
-
+	
 	packAll(bmain, op->reports);
 	G.fileflags |= G_AUTOPACK;
-
+	
 	return OPERATOR_FINISHED;
 }
 
@@ -83,7 +138,7 @@ static int pack_all_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
 	Main *bmain = CTX_data_main(C);
 	Image *ima;
 	ImBuf *ibuf;
-
+	
 	// first check for dirty images
 	for (ima = bmain->image.first; ima; ima = ima->id.next) {
 		if (ima->ibufs.first) { /* XXX FIX */
@@ -93,16 +148,16 @@ static int pack_all_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
 				BKE_image_release_ibuf(ima, ibuf, NULL);
 				break;
 			}
-
+			
 			BKE_image_release_ibuf(ima, ibuf, NULL);
 		}
 	}
-
+	
 	if (ima) {
 		uiPupMenuOkee(C, "FILE_OT_pack_all", "Some images are painted on. These changes will be lost. Continue?");
 		return OPERATOR_CANCELLED;
 	}
-
+	
 	return pack_all_exec(C, op);
 }
 
@@ -116,11 +171,12 @@ void FILE_OT_pack_all(wmOperatorType *ot)
 	/* api callbacks */
 	ot->exec = pack_all_exec;
 	ot->invoke = pack_all_invoke;
-
+	
 	/* flags */
 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
+
 /********************* unpack all operator *********************/
 
 static const EnumPropertyItem unpack_all_method_items[] = {
diff --git a/source/blender/editors/space_info/space_info.c b/source/blender/editors/space_info/space_info.c
index db9be22eedb..60b04f7b029 100644
--- a/source/blender/editors/space_info/space_info.c
+++ b/source/blender/editors/space_info/space_info.c
@@ -178,7 +178,10 @@ static void info_main_area_draw(const bContext *C, ARegion *ar)
 static void info_operatortypes(void)
 {
 	WM_operatortype_append(FILE_OT_pack_all);
+	WM_operatortype_append(FILE_OT_pack_libraries);
 	WM_operatortype_append(FILE_OT_unpack_all);
+	WM_operatortype_append(FILE_OT_unpack_libraries);
+	
 	WM_operatortype_append(FILE_OT_make_paths_relative);
 	WM_operatortype_append(FILE_OT_make_paths_absolute);
 	WM_operatortype_append(FILE_OT_report_missing_files);
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index a769ce742c9..0c5e17c1c7d 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -42,6 +42,7 @@ extern "C" {
 struct Library;
 struct FileData;
 struct ID;
+struct PackedFile;
 
 typedef struct IDPropertyData {
 	void *pointer;
@@ -136,6 +137,8 @@ typedef struct Library {
 							 * setting 'name' directly and it will be kept in
 							 * sync - campbell */
 	struct Library *parent;	/* set for indirectly linked libs, used in the outliner and while reading */
+	
+	struct PackedFile *packedfile;
 } Library;
 
 enum eIconSizes {
-- 
cgit v1.2.3


From bfcb1d4cde934fb30102bba2ed789d57a1c2d81d Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Thu, 27 Dec 2012 15:55:37 +0000
Subject: Bug fix, own collection.

"Add Group" was excluding linked library objects.
---
 source/blender/editors/object/object_group.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c
index a3bf27a19d6..7bf1a5db3b1 100644
--- a/source/blender/editors/object/object_group.c
+++ b/source/blender/editors/object/object_group.c
@@ -313,7 +313,7 @@ static int group_create_exec(bContext *C, wmOperator *op)
 	
 	group = add_group(name);
 		
-	CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
+	CTX_DATA_BEGIN (C, Base *, base, selected_bases)
 	{
 		add_to_group(group, base->object, scene, base);
 	}
-- 
cgit v1.2.3


From f0b872e7f147365f673d5cc4ea045417a4891211 Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Thu, 27 Dec 2012 17:09:27 +0000
Subject: Fix in previous commit: forgot to free data from file reading.

(Campbell: we want the memory prints back!!!)
---
 source/blender/blenloader/intern/readfile.c | 2 ++
 1 file changed, 2 insertions(+)

(limited to 'source')

diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index c62acb57fda..e27f2464f9b 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -1149,6 +1149,8 @@ void blo_freefiledata(FileData *fd)
 			oldnewmap_free(fd->imamap);
 		if (fd->movieclipmap)
 			oldnewmap_free(fd->movieclipmap);
+		if (fd->packedmap)
+			oldnewmap_free(fd->packedmap);
 		if (fd->libmap && !(fd->flags & FD_FLAGS_NOT_MY_LIBMAP))
 			oldnewmap_free(fd->libmap);
 		if (fd->bheadmap)
-- 
cgit v1.2.3


From b931d2d0cdb3998e86d0dc828751cfd40be58110 Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Thu, 27 Dec 2012 17:15:45 +0000
Subject: Function IMB_onehalf was not freeing memory. (Used for icon mipmap)

---
 source/blender/imbuf/intern/scaling.c | 2 ++
 1 file changed, 2 insertions(+)

(limited to 'source')

diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c
index 1e701b8d615..af51b4448aa 100644
--- a/source/blender/imbuf/intern/scaling.c
+++ b/source/blender/imbuf/intern/scaling.c
@@ -360,6 +360,8 @@ ImBuf *IMB_onehalf(struct ImBuf *ibuf1)
 	
 	imb_onehalf_no_alloc(ibuf2, ibuf1);
 	
+	IMB_freeImBuf(ibuf1);
+	
 	return (ibuf2);
 }
 
-- 
cgit v1.2.3


From 5a907210989c82f415ceeaeee2e71b0ed27725d0 Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Thu, 27 Dec 2012 19:07:16 +0000
Subject: Outliner fix:

New "Blender file" viewer now shows names of libraries better.
---
 source/blender/editors/space_outliner/outliner_tree.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index d911818d0cb..f723fbedc7b 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -836,7 +836,11 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
 		/* pass */
 	}
 	else {
-		te->name = id->name + 2; // default, can be overridden by Library or non-ID data
+		/* do here too, for blend file viewer, own ID_LI then shows file name */
+		if (GS(id->name) == ID_LI)
+			te->name = ((Library *)id)->name;
+		else
+			te->name = id->name + 2; // default, can be overridden by Library or non-ID data
 		te->idcode = GS(id->name);
 	}
 	
-- 
cgit v1.2.3


From 6a0c8790d87877c875659dda4a4ad460193fb480 Mon Sep 17 00:00:00 2001
From: Pablo Vazquez 
Date: Thu, 27 Dec 2012 22:00:31 +0000
Subject: Better error report when no camera is found.

While trying to render a RenderLayer from a linked scene, I couldnt tell why it wasnt doing anything. It just stopped rendering. Until I look on the console and see the No Camera print.

This commit replaces the simple terminal printf with an actual error report, that shows in both terminal and to the user:
http://pasteall.org/pic/show.php?id=42499

I believe this commit is pretty harmless, and only adds functionality. But feel free to remove it.
---
 source/blender/render/intern/source/pipeline.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 35ac038f2f2..2d4e9513d0a 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -1237,7 +1237,7 @@ static void do_render_fields_blur_3d(Render *re)
 	Object *camera = RE_GetCamera(re);
 	/* also check for camera here */
 	if (camera == NULL) {
-		printf("ERROR: Cannot render, no camera\n");
+        BKE_report(re->reports, RPT_ERROR, "Cannot render, no camera");
 		G.is_break = TRUE;
 		return;
 	}
-- 
cgit v1.2.3


From 71dbd39891ad8109a208f389e518a446b487ef34 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Fri, 28 Dec 2012 00:54:22 +0000
Subject: remove workaround for [#31555], forcing PYTHONIOENCODING was causing
 stdout to be lost on exit - no MEM_printmemlist_stats()

---
 source/blender/python/intern/bpy_interface.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index cdecf64c93c..08eb29a2a3e 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -269,7 +269,8 @@ void BPY_python_start(int argc, const char **argv)
 	Py_Initialize();
 
 	/* THIS IS BAD: see http://bugs.python.org/issue16129 */
-#if 1
+	/* this clobbers the stdout on exit (no 'MEM_printmemlist_stats') */
+#if 0
 	/* until python provides a reliable way to set the env var */
 	PyRun_SimpleString("import sys, io\n"
 	                   "sys.__backup_stdio__ = sys.__stdout__, sys.__stderr__\n"  /* else we loose the FD's [#32720] */
-- 
cgit v1.2.3


From 1e3f98c000619e5fffd737df6d32f72ed313a443 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Fri, 28 Dec 2012 01:36:00 +0000
Subject: remove unneeded inline lookups and fix error with
 wpaint_stroke_test_start returning OPERATOR_PASS_THROUGH rather then a
 boolean.

---
 source/blender/blenkernel/intern/deform.c          | 30 +--------
 source/blender/editors/sculpt_paint/paint_stroke.c |  1 +
 source/blender/editors/sculpt_paint/paint_vertex.c | 73 ++++++++++++----------
 3 files changed, 45 insertions(+), 59 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index 7c13ca388e0..3f400155f7b 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -34,6 +34,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "MEM_guardedalloc.h"
 
@@ -337,37 +338,12 @@ void defvert_flip_merged(MDeformVert *dvert, const int *flip_map, const int flip
 
 bDeformGroup *defgroup_find_name(Object *ob, const char *name)
 {
-	/* return a pointer to the deform group with this name
-	 * or return NULL otherwise.
-	 */
-	bDeformGroup *curdef;
-
-	for (curdef = ob->defbase.first; curdef; curdef = curdef->next) {
-		if (!strcmp(curdef->name, name)) {
-			return curdef;
-		}
-	}
-	return NULL;
+	return BLI_findstring(&ob->defbase, name, offsetof(bDeformGroup, name));
 }
 
 int defgroup_name_index(Object *ob, const char *name)
 {
-	/* Return the location of the named deform group within the list of
-	 * deform groups. This function is a combination of BLI_findlink and
-	 * defgroup_find_name. The other two could be called instead, but that
-	 * require looping over the vertexgroups twice.
-	 */
-	bDeformGroup *curdef;
-	int def_nr;
-
-	if (name && name[0] != '\0') {
-		for (curdef = ob->defbase.first, def_nr = 0; curdef; curdef = curdef->next, def_nr++) {
-			if (!strcmp(curdef->name, name))
-				return def_nr;
-		}
-	}
-
-	return -1;
+	return BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name));
 }
 
 /* note, must be freed */
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 9ebeb61a7bb..2f4115dcd94 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -416,6 +416,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
 	if (!stroke->stroke_started) {
 		copy_v2_v2(stroke->last_mouse_position, sample_average.mouse);
 		stroke->stroke_started = stroke->test_start(C, op, sample_average.mouse);
+		BLI_assert((stroke->stroke_started & ~1) == 0);  /* 0/1 */
 
 		if (stroke->stroke_started) {
 			stroke->smooth_stroke_cursor =
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index bc1d0cd2f69..0ad7d144496 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -372,31 +372,22 @@ static int wpaint_mirror_vgroup_ensure(Object *ob, const int vgroup_active)
 	bDeformGroup *defgroup = BLI_findlink(&ob->defbase, vgroup_active);
 
 	if (defgroup) {
-		bDeformGroup *curdef;
 		int mirrdef;
 		char name[MAXBONENAME];
 
 		flip_side_name(name, defgroup->name, FALSE);
-
-		if (strcmp(name, defgroup->name) != 0) {
-			for (curdef = ob->defbase.first, mirrdef = 0; curdef; curdef = curdef->next, mirrdef++) {
-				if (!strcmp(curdef->name, name)) {
-					break;
-				}
-			}
-
-			if (curdef == NULL) {
-				int olddef = ob->actdef;  /* tsk, ED_vgroup_add sets the active defgroup */
-				curdef = ED_vgroup_add_name(ob, name);
-				ob->actdef = olddef;
-			}
-
-			/* curdef should never be NULL unless this is
-			 * a  lamp and ED_vgroup_add_name fails */
-			if (curdef) {
-				return mirrdef;
+		mirrdef = defgroup_name_index(ob, name);
+		if (mirrdef == -1) {
+			int olddef = ob->actdef;  /* tsk, ED_vgroup_add sets the active defgroup */
+			if (ED_vgroup_add_name(ob, name)) {
+				mirrdef = BLI_countlist(&ob->defbase) - 1;
 			}
+			ob->actdef = olddef;
 		}
+
+		/* curdef should never be NULL unless this is
+		 * a  lamp and ED_vgroup_add_name fails */
+		return mirrdef;
 	}
 
 	return -1;
@@ -2061,32 +2052,29 @@ struct WPaintData {
 	int vgroup_mirror;
 	DMCoNo *vertexcosnos;
 	float wpimat[3][3];
-	
+
 	/* variables for auto normalize */
 	const char *vgroup_validmap; /* stores if vgroups tie to deforming bones or not */
 	const char *lock_flags;
 	int defbase_tot;
 };
 
-static int wpaint_stroke_test_start(bContext *C, wmOperator *op, const float UNUSED(mouse[2]))
+/* ensure we have data on wpaint start, add if needed */
+static int wpaint_ensure_data(bContext *C, wmOperator *op)
 {
 	Scene *scene = CTX_data_scene(C);
-	struct PaintStroke *stroke = op->customdata;
-	ToolSettings *ts = scene->toolsettings;
-	VPaint *wp = ts->wpaint;
 	Object *ob = CTX_data_active_object(C);
-	struct WPaintData *wpd;
-	Mesh *me;
+	Mesh *me = BKE_mesh_from_object(ob);
 
-	float mat[4][4], imat[4][4];
-	
 	if (scene->obedit) {
 		return FALSE;
 	}
-	
+
 	me = BKE_mesh_from_object(ob);
-	if (me == NULL || me->totpoly == 0) return OPERATOR_PASS_THROUGH;
-	
+	if (me == NULL || me->totpoly == 0) {
+		return FALSE;
+	}
+
 	/* if nothing was added yet, we make dverts and a vertex deform group */
 	if (!me->dvert) {
 		ED_vgroup_data_create(&me->id);
@@ -2125,6 +2113,25 @@ static int wpaint_stroke_test_start(bContext *C, wmOperator *op, const float UNU
 		return FALSE;
 	}
 
+	return TRUE;
+}
+
+static int wpaint_stroke_test_start(bContext *C, wmOperator *op, const float UNUSED(mouse[2]))
+{
+	Scene *scene = CTX_data_scene(C);
+	struct PaintStroke *stroke = op->customdata;
+	ToolSettings *ts = scene->toolsettings;
+	VPaint *wp = ts->wpaint;
+	Object *ob = CTX_data_active_object(C);
+	Mesh *me = BKE_mesh_from_object(ob);
+	struct WPaintData *wpd;
+
+	float mat[4][4], imat[4][4];
+
+	if (wpaint_ensure_data(C, op) == FALSE) {
+		return FALSE;
+	}
+
 	{
 		/* check if we are attempting to paint onto a locked vertex group,
 		 * and other options disallow it from doing anything useful */
@@ -3208,7 +3215,9 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op)
 
 static int paint_weight_gradient_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
-	int ret = WM_gesture_straightline_invoke(C, op, event);
+	int ret;
+
+	ret = WM_gesture_straightline_invoke(C, op, event);
 	if (ret & OPERATOR_RUNNING_MODAL) {
 		struct ARegion *ar = CTX_wm_region(C);
 		if (ar->regiontype == RGN_TYPE_WINDOW) {
-- 
cgit v1.2.3


From 4e5d5e0d843095648e347a305c8314d302ca485a Mon Sep 17 00:00:00 2001
From: Howard Trickey 
Date: Fri, 28 Dec 2012 02:45:10 +0000
Subject: Add 'vertex_only' option to bevel tool. Right now, changing segments
 to > 1 doesn't do anything, but intend to work on making that cause rounded
 corners.

---
 source/blender/bmesh/intern/bmesh_opdefines.c |  1 +
 source/blender/bmesh/operators/bmo_bevel.c    |  3 ++-
 source/blender/bmesh/tools/bmesh_bevel.c      | 36 +++++++++++++++++----------
 source/blender/bmesh/tools/bmesh_bevel.h      |  2 +-
 source/blender/editors/mesh/editmesh_tools.c  |  6 +++--
 source/blender/modifiers/intern/MOD_bevel.c   |  2 +-
 6 files changed, 32 insertions(+), 18 deletions(-)

(limited to 'source')

diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index 3a7a1c4eaaa..83ed51163b5 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -1403,6 +1403,7 @@ static BMOpDefine bmo_bevel_def = {
 	{{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},     /* input edges and vertices */
 	 {"offset", BMO_OP_SLOT_FLT},           /* amount to offset beveled edge */
 	 {"segments", BMO_OP_SLOT_INT},         /* number of segments in bevel */
+	 {"vertex_only", BMO_OP_SLOT_BOOL},	/* only bevel vertices, not edges */
 	 {{'\0'}},
 	},
 	/* slots_out */
diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c
index 126d0f46119..eb8e84da63f 100644
--- a/source/blender/bmesh/operators/bmo_bevel.c
+++ b/source/blender/bmesh/operators/bmo_bevel.c
@@ -34,6 +34,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op)
 {
 	const float offset = BMO_slot_float_get(op->slots_in, "offset");
 	const int   seg    = BMO_slot_int_get(op->slots_in,   "segments");
+	const int   vonly  = BMO_slot_bool_get(op->slots_in,  "vertex_only");
 
 	if (offset > 0) {
 		BMOIter siter;
@@ -54,7 +55,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op)
 			}
 		}
 
-		BM_mesh_bevel(bm, offset, seg);
+		BM_mesh_bevel(bm, offset, seg, vonly);
 
 		BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG);
 	}
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index 50e59ab3e64..4bcdc7d24ff 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -119,6 +119,7 @@ typedef struct BevelParams {
 
 	float offset;           /* blender units to offset each side of a beveled edge */
 	int seg;                /* number of segments in beveled edge profile */
+	int vertex_only;	/* bevel vertices only */
 } BevelParams;
 
 // #pragma GCC diagnostic ignored "-Wpadded"
@@ -698,8 +699,9 @@ static void snap_to_edge_profile(EdgeHalf *e, const float va[3], const float vb[
  * of a vertex on the the boundary of the beveled vertex bv->v.
  * Also decide on the mesh pattern that will be used inside the boundary.
  * Doesn't make the actual BMVerts */
-static void build_boundary(MemArena *mem_arena, BevVert *bv)
+static void build_boundary(BevelParams *bp, BevVert *bv)
 {
+	MemArena *mem_arena = bp->mem_arena;
 	EdgeHalf *efirst, *e;
 	BoundVert *v;
 	VMesh *vm;
@@ -707,9 +709,13 @@ static void build_boundary(MemArena *mem_arena, BevVert *bv)
 	const float  *no;
 	float lastd;
 
-	e = efirst = next_bev(bv, NULL);
 	vm = bv->vmesh;
 
+	if (bp->vertex_only)
+		e = efirst = &bv->edges[0];
+	else
+		e = efirst = next_bev(bv, NULL);
+
 	BLI_assert(bv->edgecount >= 2);  /* since bevel edges incident to 2 faces */
 
 	if (bv->edgecount == 2 && bv->selcount == 1) {
@@ -734,7 +740,7 @@ static void build_boundary(MemArena *mem_arena, BevVert *bv)
 		return;
 	}
 
-	lastd = e->offset;
+	lastd = bp->vertex_only ? bp->offset : e->offset;
 	vm->boundstart = NULL;
 	do {
 		if (e->is_bev) {
@@ -1325,8 +1331,9 @@ static void bevel_build_quadstrip(BMesh *bm, BevVert *bv)
 
 /* Given that the boundary is built, now make the actual BMVerts
  * for the boundary and the interior of the vertex mesh. */
-static void build_vmesh(MemArena *mem_arena, BMesh *bm, BevVert *bv)
+static void build_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv)
 {
+	MemArena *mem_arena = bp->mem_arena;
 	VMesh *vm = bv->vmesh;
 	BoundVert *v, *weld1, *weld2;
 	int n, ns, ns2, i, k, weld;
@@ -1504,7 +1511,7 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
 	 */
 
 	BM_ITER_ELEM (bme, &iter, v, BM_EDGES_OF_VERT) {
-		if (BM_elem_flag_test(bme, BM_ELEM_TAG)) {
+		if (BM_elem_flag_test(bme, BM_ELEM_TAG) && !bp->vertex_only) {
 			BLI_assert(BM_edge_is_manifold(bme));
 			nsel++;
 		}
@@ -1513,7 +1520,7 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
 		BM_BEVEL_EDGE_TAG_DISABLE(bme);
 	}
 
-	if (nsel == 0) {
+	if ((nsel == 0 && !bp->vertex_only) || (ntot < 3 && bp->vertex_only)) {
 		/* signal this vert isn't being beveled */
 		BM_elem_flag_disable(v, BM_ELEM_TAG);
 		return;
@@ -1570,7 +1577,7 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
 		}
 		bme = e->e;
 		BM_BEVEL_EDGE_TAG_ENABLE(bme);
-		if (BM_elem_flag_test(bme, BM_ELEM_TAG)) {
+		if (BM_elem_flag_test(bme, BM_ELEM_TAG) && !bp->vertex_only) {
 			e->is_bev = TRUE;
 			e->seg = bp->seg;
 		}
@@ -1626,8 +1633,8 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
 		BM_BEVEL_EDGE_TAG_DISABLE(e->e);
 	}
 
-	build_boundary(bp->mem_arena, bv);
-	build_vmesh(bp->mem_arena, bm, bv);
+	build_boundary(bp, bv);
+	build_vmesh(bp, bm, bv);
 }
 
 /* Face f has at least one beveled vertex.  Rebuild f */
@@ -1790,7 +1797,7 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
  *
  * \warning all tagged edges _must_ be manifold.
  */
-void BM_mesh_bevel(BMesh *bm, const float offset, const float segments)
+void BM_mesh_bevel(BMesh *bm, const float offset, const float segments, const int vertex_only)
 {
 	BMIter iter;
 	BMVert *v;
@@ -1799,6 +1806,7 @@ void BM_mesh_bevel(BMesh *bm, const float offset, const float segments)
 
 	bp.offset = offset;
 	bp.seg    = segments;
+	bp.vertex_only = vertex_only;
 
 	if (bp.offset > 0) {
 		/* primary alloc */
@@ -1814,9 +1822,11 @@ void BM_mesh_bevel(BMesh *bm, const float offset, const float segments)
 		}
 
 		/* Build polygons for edges */
-		BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
-			if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
-				bevel_build_edge_polygons(bm, &bp, e);
+		if (!bp.vertex_only) {
+			BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+				if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+					bevel_build_edge_polygons(bm, &bp, e);
+				}
 			}
 		}
 
diff --git a/source/blender/bmesh/tools/bmesh_bevel.h b/source/blender/bmesh/tools/bmesh_bevel.h
index a80e4f3a4a2..d56aa13c984 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.h
+++ b/source/blender/bmesh/tools/bmesh_bevel.h
@@ -27,6 +27,6 @@
  *  \ingroup bmesh
  */
 
-void BM_mesh_bevel(BMesh *bm, const float offset, const float segments);
+void BM_mesh_bevel(BMesh *bm, const float offset, const float segments, const int vertex_only);
 
 #endif /* __BMESH_BEVEL_H__ */
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index a1978f110ac..26f54dee52d 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -4768,6 +4768,7 @@ static int edbm_bevel_calc(wmOperator *op)
 #ifdef NEW_BEVEL
 	float offset = RNA_float_get(op->ptr, "offset");
 	int segments = RNA_int_get(op->ptr, "segments");
+	int vertex_only = RNA_boolean_get(op->ptr, "vertex_only");
 
 	/* revert to original mesh */
 	if (opdata->is_modal) {
@@ -4775,8 +4776,8 @@ static int edbm_bevel_calc(wmOperator *op)
 	}
 
 	if (!EDBM_op_init(em, &bmop, op,
-		              "bevel geom=%hev offset=%f segments=%i",
-		              BM_ELEM_SELECT, offset, segments))
+		              "bevel geom=%hev offset=%f segments=%i vertex_only=%b",
+		              BM_ELEM_SELECT, offset, segments, vertex_only))
 	{
 		return 0;
 	}
@@ -5101,6 +5102,7 @@ void MESH_OT_bevel(wmOperatorType *ot)
 #ifdef NEW_BEVEL
 	RNA_def_float(ot->srna, "offset", 0.0f, -FLT_MAX, FLT_MAX, "Offset", "", 0.0f, 1.0f);
 	RNA_def_int(ot->srna, "segments", 1, 1, 50, "Segments", "Segments for curved edge", 1, 8);
+	RNA_def_boolean(ot->srna, "vertex_only", FALSE, "Vertex only", "Bevel only vertices");
 #else
 	/* take note, used as a factor _and_ a distance depending on 'use_dist' */
 	RNA_def_float(ot->srna, "percent", 0.0f, -FLT_MAX, FLT_MAX, "Percentage", "", 0.0f, 1.0f);
diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c
index 59befe4db05..776adb57c13 100644
--- a/source/blender/modifiers/intern/MOD_bevel.c
+++ b/source/blender/modifiers/intern/MOD_bevel.c
@@ -140,7 +140,7 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Object *UNUSED(ob),
 		}
 	}
 
-	BM_mesh_bevel(bm, bmd->value, segments);
+	BM_mesh_bevel(bm, bmd->value, segments, bmd->flags & BME_BEVEL_VERT);
 
 	result = CDDM_from_bmesh(bm, TRUE);
 
-- 
cgit v1.2.3


From 3f68790108e7a5ab9aa7253d495daded2a325c89 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Fri, 28 Dec 2012 09:00:05 +0000
Subject: fix for memory leak with weight painting and ensure vertex group is
 created before use.

---
 source/blender/editors/sculpt_paint/paint_vertex.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 0ad7d144496..c31d40e5474 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -405,7 +405,7 @@ static void free_vpaint_prev(VPaint *vp)
 static void free_wpaint_prev(VPaint *vp)
 {
 	if (vp->wpaint_prev) {
-		MEM_freeN(vp->wpaint_prev);
+		free_dverts(vp->wpaint_prev, vp->tot);
 		vp->wpaint_prev = NULL;
 		vp->tot = 0;
 	}
@@ -2498,7 +2498,7 @@ void PAINT_OT_weight_paint(wmOperatorType *ot)
 	RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
 }
 
-static int weight_paint_set_exec(bContext *C, wmOperator *UNUSED(op))
+static int weight_paint_set_exec(bContext *C, wmOperator *op)
 {
 	struct Scene *scene = CTX_data_scene(C);
 	Object *obact = CTX_data_active_object(C);
@@ -2506,6 +2506,10 @@ static int weight_paint_set_exec(bContext *C, wmOperator *UNUSED(op))
 	Brush *brush = paint_brush(&ts->wpaint->paint);
 	float vgroup_weight = BKE_brush_weight_get(scene, brush);
 
+	if (wpaint_ensure_data(C, op) == FALSE) {
+		return OPERATOR_CANCELLED;
+	}
+
 	wpaint_fill(scene->toolsettings->wpaint, obact, vgroup_weight);
 	ED_region_tag_redraw(CTX_wm_region(C)); /* XXX - should redraw all 3D views */
 	return OPERATOR_FINISHED;
@@ -3217,6 +3221,10 @@ static int paint_weight_gradient_invoke(bContext *C, wmOperator *op, wmEvent *ev
 {
 	int ret;
 
+	if (wpaint_ensure_data(C, op) == FALSE) {
+		return OPERATOR_CANCELLED;
+	}
+
 	ret = WM_gesture_straightline_invoke(C, op, event);
 	if (ret & OPERATOR_RUNNING_MODAL) {
 		struct ARegion *ar = CTX_wm_region(C);
-- 
cgit v1.2.3


From 7730ddb3d6211a9c03e4b2eebedefcfb6f709891 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Fri, 28 Dec 2012 09:06:48 +0000
Subject: code cleanup: - free_dverts -> BKE_defvert_array_free - copy_dverts
 -> BKE_defvert_array_copy

also move the functions from BKE_mesh into BKE_deform
---
 source/blender/blenkernel/BKE_deform.h             |  3 ++
 source/blender/blenkernel/BKE_mesh.h               |  2 --
 source/blender/blenkernel/intern/deform.c          | 40 ++++++++++++++++++++++
 source/blender/blenkernel/intern/lattice.c         |  8 ++---
 source/blender/blenkernel/intern/mesh.c            | 36 -------------------
 source/blender/editors/object/object_lattice.c     | 10 +++---
 source/blender/editors/sculpt_paint/paint_vertex.c |  6 ++--
 7 files changed, 55 insertions(+), 50 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h
index 8306da71432..ab27421b383 100644
--- a/source/blender/blenkernel/BKE_deform.h
+++ b/source/blender/blenkernel/BKE_deform.h
@@ -56,6 +56,9 @@ void                     defvert_remove_group(struct MDeformVert *dvert, struct
 void                     defvert_clear(struct MDeformVert *dvert);
 int                      defvert_find_shared(const struct MDeformVert *dvert_a, const struct MDeformVert *dvert_b);
 
+void BKE_defvert_array_free(struct MDeformVert *dvert, int totvert);
+void BKE_defvert_array_copy(struct MDeformVert *dst, const struct MDeformVert *src, int totvert);
+
 float  defvert_find_weight(const struct MDeformVert *dvert, const int defgroup);
 float  defvert_array_find_weight_safe(const struct MDeformVert *dvert, const int index, const int defgroup);
 
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index 320ced67a2f..db9f1228f76 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -162,8 +162,6 @@ void BKE_mesh_from_nurbs(struct Object *ob);
 void BKE_mesh_from_nurbs_displist(struct Object *ob, struct ListBase *dispbase,
                                   int **orco_index_ptr);
 void BKE_mesh_from_curve(struct Scene *scene, struct Object *ob);
-void free_dverts(struct MDeformVert *dvert, int totvert);
-void copy_dverts(struct MDeformVert *dst, const struct MDeformVert *src, int totvert);
 void BKE_mesh_delete_material_index(struct Mesh *me, short index);
 void BKE_mesh_smooth_flag_set(struct Object *meshOb, int enableSmooth);
 void BKE_mesh_convert_mfaces_to_mpolys(struct Mesh *mesh);
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index 3f400155f7b..b5280fdc039 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -786,3 +786,43 @@ int defvert_find_shared(const MDeformVert *dvert_a, const MDeformVert *dvert_b)
 
 	return -1;
 }
+
+/* -------------------------------------------------------------------- */
+/* Defvert Array functions */
+
+void BKE_defvert_array_copy(MDeformVert *dst, const MDeformVert *src, int copycount)
+{
+	/* Assumes dst is already set up */
+	int i;
+
+	if (!src || !dst)
+		return;
+
+	memcpy(dst, src, copycount * sizeof(MDeformVert));
+
+	for (i = 0; i < copycount; i++) {
+		if (src[i].dw) {
+			dst[i].dw = MEM_mallocN(sizeof(MDeformWeight) * src[i].totweight, "copy_deformWeight");
+			memcpy(dst[i].dw, src[i].dw, sizeof(MDeformWeight) * src[i].totweight);
+		}
+	}
+
+}
+
+void BKE_defvert_array_free(MDeformVert *dvert, int totvert)
+{
+	/* Instead of freeing the verts directly,
+	 * call this function to delete any special
+	 * vert data */
+	int i;
+
+	if (!dvert)
+		return;
+
+	/* Free any special data from the verts */
+	for (i = 0; i < totvert; i++) {
+		if (dvert[i].dw) MEM_freeN(dvert[i].dw);
+	}
+	MEM_freeN(dvert);
+}
+
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index d98188d8a6f..fa01e9fd933 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -88,7 +88,7 @@ void BKE_lattice_resize(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb)
 	
 	/* vertex weight groups are just freed all for now */
 	if (lt->dvert) {
-		free_dverts(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
+		BKE_defvert_array_free(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
 		lt->dvert = NULL;
 	}
 	
@@ -209,7 +209,7 @@ Lattice *BKE_lattice_copy(Lattice *lt)
 	if (lt->dvert) {
 		int tot = lt->pntsu * lt->pntsv * lt->pntsw;
 		ltn->dvert = MEM_mallocN(sizeof(MDeformVert) * tot, "Lattice MDeformVert");
-		copy_dverts(ltn->dvert, lt->dvert, tot);
+		BKE_defvert_array_copy(ltn->dvert, lt->dvert, tot);
 	}
 
 	ltn->editlatt = NULL;
@@ -220,12 +220,12 @@ Lattice *BKE_lattice_copy(Lattice *lt)
 void BKE_lattice_free(Lattice *lt)
 {
 	if (lt->def) MEM_freeN(lt->def);
-	if (lt->dvert) free_dverts(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
+	if (lt->dvert) BKE_defvert_array_free(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
 	if (lt->editlatt) {
 		Lattice *editlt = lt->editlatt->latt;
 
 		if (editlt->def) MEM_freeN(editlt->def);
-		if (editlt->dvert) free_dverts(editlt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
+		if (editlt->dvert) BKE_defvert_array_free(editlt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
 
 		MEM_freeN(editlt);
 		MEM_freeN(lt->editlatt);
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index f788bbabf4d..30e7cb3bb36 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -430,42 +430,6 @@ void BKE_mesh_free(Mesh *me, int unlink)
 	if (me->edit_btmesh) MEM_freeN(me->edit_btmesh);
 }
 
-void copy_dverts(MDeformVert *dst, const MDeformVert *src, int copycount)
-{
-	/* Assumes dst is already set up */
-	int i;
-
-	if (!src || !dst)
-		return;
-
-	memcpy(dst, src, copycount * sizeof(MDeformVert));
-	
-	for (i = 0; i < copycount; i++) {
-		if (src[i].dw) {
-			dst[i].dw = MEM_mallocN(sizeof(MDeformWeight) * src[i].totweight, "copy_deformWeight");
-			memcpy(dst[i].dw, src[i].dw, sizeof(MDeformWeight) * src[i].totweight);
-		}
-	}
-
-}
-
-void free_dverts(MDeformVert *dvert, int totvert)
-{
-	/* Instead of freeing the verts directly,
-	 * call this function to delete any special
-	 * vert data */
-	int i;
-
-	if (!dvert)
-		return;
-
-	/* Free any special data from the verts */
-	for (i = 0; i < totvert; i++) {
-		if (dvert[i].dw) MEM_freeN(dvert[i].dw);
-	}
-	MEM_freeN(dvert);
-}
-
 static void mesh_tessface_clear_intern(Mesh *mesh, int free_customdata)
 {
 	if (free_customdata) {
diff --git a/source/blender/editors/object/object_lattice.c b/source/blender/editors/object/object_lattice.c
index 4aa2e825954..c9eae776ac7 100644
--- a/source/blender/editors/object/object_lattice.c
+++ b/source/blender/editors/object/object_lattice.c
@@ -52,7 +52,7 @@
 #include "BKE_depsgraph.h"
 #include "BKE_key.h"
 #include "BKE_lattice.h"
-#include "BKE_mesh.h"
+#include "BKE_deform.h"
 
 #include "ED_lattice.h"
 #include "ED_object.h"
@@ -77,7 +77,7 @@ void free_editLatt(Object *ob)
 		if (editlt->def)
 			MEM_freeN(editlt->def);
 		if (editlt->dvert)
-			free_dverts(editlt->dvert, editlt->pntsu * editlt->pntsv * editlt->pntsw);
+			BKE_defvert_array_free(editlt->dvert, editlt->pntsu * editlt->pntsv * editlt->pntsw);
 
 		MEM_freeN(editlt);
 		MEM_freeN(lt->editlatt);
@@ -104,7 +104,7 @@ void make_editLatt(Object *obedit)
 	if (lt->dvert) {
 		int tot = lt->pntsu * lt->pntsv * lt->pntsw;
 		lt->editlatt->latt->dvert = MEM_mallocN(sizeof(MDeformVert) * tot, "Lattice MDeformVert");
-		copy_dverts(lt->editlatt->latt->dvert, lt->dvert, tot);
+		BKE_defvert_array_copy(lt->editlatt->latt->dvert, lt->dvert, tot);
 	}
 
 	if (lt->key) lt->editlatt->shapenr = obedit->shapenr;
@@ -156,7 +156,7 @@ void load_editLatt(Object *obedit)
 	}
 
 	if (lt->dvert) {
-		free_dverts(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
+		BKE_defvert_array_free(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
 		lt->dvert = NULL;
 	}
 
@@ -164,7 +164,7 @@ void load_editLatt(Object *obedit)
 		tot = lt->pntsu * lt->pntsv * lt->pntsw;
 
 		lt->dvert = MEM_mallocN(sizeof(MDeformVert) * tot, "Lattice MDeformVert");
-		copy_dverts(lt->dvert, editlt->dvert, tot);
+		BKE_defvert_array_copy(lt->dvert, editlt->dvert, tot);
 	}
 }
 
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index c31d40e5474..17bf5c841c3 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -405,7 +405,7 @@ static void free_vpaint_prev(VPaint *vp)
 static void free_wpaint_prev(VPaint *vp)
 {
 	if (vp->wpaint_prev) {
-		free_dverts(vp->wpaint_prev, vp->tot);
+		BKE_defvert_array_free(vp->wpaint_prev, vp->tot);
 		vp->wpaint_prev = NULL;
 		vp->tot = 0;
 	}
@@ -432,7 +432,7 @@ static void copy_wpaint_prev(VPaint *wp, MDeformVert *dverts, int dcount)
 		
 		wp->wpaint_prev = MEM_mallocN(sizeof(MDeformVert) * dcount, "wpaint prev");
 		wp->tot = dcount;
-		copy_dverts(wp->wpaint_prev, dverts, dcount);
+		BKE_defvert_array_copy(wp->wpaint_prev, dverts, dcount);
 	}
 }
 
@@ -3142,7 +3142,7 @@ static int paint_weight_gradient_modal(bContext *C, wmOperator *op, wmEvent *eve
 		VPaint *wp = ts->wpaint;
 		Object *ob = CTX_data_active_object(C);
 		Mesh *me = ob->data;
-		copy_dverts(me->dvert, wp->wpaint_prev, me->totvert);
+		BKE_defvert_array_copy(me->dvert, wp->wpaint_prev, me->totvert);
 		free_wpaint_prev(wp);
 
 		DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
-- 
cgit v1.2.3


From 7504cf34b470bec3b3fc7239d655738a09ed7624 Mon Sep 17 00:00:00 2001
From: Bastien Montagne 
Date: Fri, 28 Dec 2012 09:20:16 +0000
Subject: This commit frees list ui items from their dependencies to Panel, and
 hence from all the limitations this implied (mostly, the "only one list per
 panel" one).

It introduces a new (py-extendable and registrable) RNA type, UIList (roughly similar to Panel one), which currently contains only "standard" list's scroll pos and size (but may be expended to include e.g. some filtering data, etc.). This now makes lists completely independent from Panels!

This UIList has a draw_item callback which allows to customize items' drawing from python, that all addons can now use. Incidentally, this also greatly simplifies the C code of this widget, as we do not code any "special case" here anymore!

To make all this work, other changes were also necessary:

* Now all buttons (uiBut struct) have a 'custom_data' void pointer, used currently to store the uiList struct associated with a given uiLayoutListBox.

* DynamicPaintSurface now exposes a new bool, use_color_preview (readonly), saying whether that surface has some 3D view preview data or not.

* UILayout class has now four new (static) functions, to get the actual icon of any RNA object (important e.g. with materials or textures), and to get an enum item's UI name, description and icon.

* UILayout's label() func now takes an optional 'icon_value' integer parameter, which if not zero will override the 'icon' one (mandatory to use "custom" icons as generated for material/texture/... previews).
  Note: not sure whether we should add that one to all UILayout's prop funcs?

Note: will update addons using template list asap.
---
 source/blender/blenkernel/BKE_screen.h             |  18 +
 source/blender/blenloader/intern/readfile.c        |   9 +-
 source/blender/blenloader/intern/writefile.c       |   4 +
 source/blender/editors/include/UI_interface.h      |   7 +-
 .../blender/editors/include/UI_interface_icons.h   |   3 +
 .../blender/editors/interface/interface_handlers.c |  87 ++--
 source/blender/editors/interface/interface_icons.c |  39 ++
 .../blender/editors/interface/interface_intern.h   |   3 +
 .../blender/editors/interface/interface_layout.c   |   5 +-
 .../editors/interface/interface_templates.c        | 512 +++++++--------------
 source/blender/editors/space_node/drawnode.c       |   4 +-
 source/blender/makesdna/DNA_screen_types.h         |  30 +-
 source/blender/makesrna/RNA_access.h               |   2 +-
 source/blender/makesrna/RNA_enum_types.h           |   3 +
 source/blender/makesrna/intern/rna_dynamicpaint.c  |  22 +
 source/blender/makesrna/intern/rna_ui.c            | 164 +++++++
 source/blender/makesrna/intern/rna_ui_api.c        | 194 +++++++-
 source/blender/python/intern/bpy_rna.c             |   5 +-
 source/blender/windowmanager/WM_api.h              |   7 +
 source/blender/windowmanager/intern/wm.c           |  58 ++-
 source/blender/windowmanager/intern/wm_init_exit.c |   2 +
 source/blenderplayer/bad_level_call_stubs/stubs.c  |   4 +-
 22 files changed, 758 insertions(+), 424 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index 8aa08beec57..3c6f886b59a 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -46,6 +46,7 @@ struct bContext;
 struct bContextDataResult;
 struct bScreen;
 struct uiLayout;
+struct uiList;
 struct uiMenuItem;
 struct wmKeyConfig;
 struct wmNotifier;
@@ -181,6 +182,23 @@ typedef struct PanelType {
 	ExtensionRNA ext;
 } PanelType;
 
+/* uilist types */
+
+/* draw an item in the uiList */
+typedef void (*uiListDrawItemFunc)(struct uiList *, struct bContext *, struct uiLayout *, struct PointerRNA *,
+                                   struct PointerRNA *, int, struct PointerRNA *, const char *, int);
+
+typedef struct uiListType {
+	struct uiListType *next, *prev;
+
+	char idname[BKE_ST_MAXNAME];            /* unique name */
+
+	uiListDrawItemFunc draw_item;
+
+	/* RNA integration */
+	ExtensionRNA ext;
+} uiListType;
+
 /* header types */
 
 typedef struct HeaderType {
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index e27f2464f9b..520e4fd2c39 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -5832,6 +5832,7 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
 static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
 {
 	Panel *pa;
+	uiList *uilst;
 
 	link_list(fd, &ar->panels);
 
@@ -5841,7 +5842,13 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
 		pa->activedata = NULL;
 		pa->type = NULL;
 	}
-	
+
+	link_list(fd, &ar->uiLists);
+
+	for (uilst = ar->uiLists.first; uilst; uilst = uilst->next) {
+		uilst->type = NULL;
+	}
+
 	ar->regiondata = newdataadr(fd, ar->regiondata);
 	if (ar->regiondata) {
 		if (spacetype == SPACE_VIEW3D) {
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 61b75a49374..1b28504700b 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -2395,6 +2395,7 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
 		for (sa= sc->areabase.first; sa; sa= sa->next) {
 			SpaceLink *sl;
 			Panel *pa;
+			uiList *uilst;
 			ARegion *ar;
 			
 			writestruct(wd, DATA, "ScrArea", 1, sa);
@@ -2404,6 +2405,9 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
 				
 				for (pa= ar->panels.first; pa; pa= pa->next)
 					writestruct(wd, DATA, "Panel", 1, pa);
+				
+				for (uilst = ar->uiLists.first; uilst; uilst = uilst->next)
+					writestruct(wd, DATA, "uiList", 1, uilst);
 			}
 			
 			sl= sa->spacedata.first;
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 9a04138e72e..281d80a9d2b 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -56,6 +56,7 @@ struct PropertyRNA;
 struct ReportList;
 struct rcti;
 struct rctf;
+struct uiList;
 struct uiStyle;
 struct uiFontStyle;
 struct uiWidgetColors;
@@ -779,7 +780,7 @@ uiLayout *uiLayoutRow(uiLayout *layout, int align);
 uiLayout *uiLayoutColumn(uiLayout *layout, int align);
 uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, int align);
 uiLayout *uiLayoutBox(uiLayout *layout);
-uiLayout *uiLayoutListBox(uiLayout *layout, struct PointerRNA *ptr, struct PropertyRNA *prop,
+uiLayout *uiLayoutListBox(uiLayout *layout, struct uiList *uilst, struct PointerRNA *ptr, struct PropertyRNA *prop,
                           struct PointerRNA *actptr, struct PropertyRNA *actprop);
 uiLayout *uiLayoutAbsolute(uiLayout *layout, int align);
 uiLayout *uiLayoutSplit(uiLayout *layout, float percentage, int align);
@@ -825,7 +826,9 @@ void uiTemplateTextureImage(uiLayout *layout, struct bContext *C, struct Tex *te
 void uiTemplateReportsBanner(uiLayout *layout, struct bContext *C);
 void uiTemplateKeymapItemProperties(uiLayout *layout, struct PointerRNA *ptr);
 
-void uiTemplateList(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, struct PointerRNA *activeptr, const char *activeprop, const char *prop_list, int rows, int maxrows, int type);
+void uiTemplateList(uiLayout *layout, struct bContext *C, const char *listtype_name, const char *list_id,
+                    struct PointerRNA *dataptr, const char *propname, struct PointerRNA *active_dataptr,
+                    const char *active_propname, int rows, int maxrows, int layout_type);
 void uiTemplateNodeLink(uiLayout *layout, struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *input);
 void uiTemplateNodeView(uiLayout *layout, struct bContext *C, struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *input);
 void uiTemplateTextureUser(uiLayout *layout, struct bContext *C);
diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h
index aa94bdec724..f578d68b852 100644
--- a/source/blender/editors/include/UI_interface_icons.h
+++ b/source/blender/editors/include/UI_interface_icons.h
@@ -32,12 +32,14 @@
 #ifndef __UI_INTERFACE_ICONS_H__
 #define __UI_INTERFACE_ICONS_H__
 
+struct bContext;
 struct Image;
 struct ImBuf;
 struct World;
 struct Tex;
 struct Lamp;
 struct Material;
+struct PointerRNA;
 
 typedef struct IconFile {
 	struct IconFile *next, *prev;
@@ -74,5 +76,6 @@ void UI_icons_free_drawinfo(void *drawinfo);
 struct ListBase *UI_iconfile_list(void);
 int UI_iconfile_get_index(const char *filename);
 
+int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, int big);
 
 #endif /*  __UI_INTERFACE_ICONS_H__ */
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 9988224e0ab..ee6916822f0 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -44,6 +44,7 @@
 
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
 
 #include "BLI_math.h"
 #include "BLI_blenlib.h"
@@ -6094,63 +6095,65 @@ static int ui_handle_list_event(bContext *C, wmEvent *event, ARegion *ar)
 	int value, min, max;
 
 	if (but && (event->val == KM_PRESS)) {
-		Panel *pa = but->block->panel;
+		uiList *uilst = but->custom_data;
 
-		if (ELEM(event->type, UPARROWKEY, DOWNARROWKEY) ||
-		    ((ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->alt)))
-		{
-			/* activate up/down the list */
-			value = RNA_property_int_get(&but->rnapoin, but->rnaprop);
-
-			if (ELEM(event->type, UPARROWKEY, WHEELUPMOUSE))
-				value--;
-			else
-				value++;
-
-			CLAMP(value, 0, pa->list_last_len - 1);
-
-			if (value < pa->list_scroll)
-				pa->list_scroll = value;
-			else if (value >= pa->list_scroll + pa->list_size)
-				pa->list_scroll = value - pa->list_size + 1;
+		if (uilst) {
+			if (ELEM(event->type, UPARROWKEY, DOWNARROWKEY) ||
+				((ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->alt)))
+			{
+				/* activate up/down the list */
+				value = RNA_property_int_get(&but->rnapoin, but->rnaprop);
 
-			RNA_property_int_range(&but->rnapoin, but->rnaprop, &min, &max);
-			value = CLAMPIS(value, min, max);
+				if (ELEM(event->type, UPARROWKEY, WHEELUPMOUSE))
+					value--;
+				else
+					value++;
 
-			RNA_property_int_set(&but->rnapoin, but->rnaprop, value);
-			RNA_property_update(C, &but->rnapoin, but->rnaprop);
-			ED_region_tag_redraw(ar);
+				CLAMP(value, 0, uilst->list_last_len - 1);
 
-			retval = WM_UI_HANDLER_BREAK;
-		}
-		else if (ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->shift) {
-			/* silly replacement for proper grip */
-			if (pa->list_grip_size == 0)
-				pa->list_grip_size = pa->list_size;
+				if (value < uilst->list_scroll)
+					uilst->list_scroll = value;
+				else if (value >= uilst->list_scroll + uilst->list_size)
+					uilst->list_scroll = value - uilst->list_size + 1;
 
-			if (event->type == WHEELUPMOUSE)
-				pa->list_grip_size--;
-			else
-				pa->list_grip_size++;
+				RNA_property_int_range(&but->rnapoin, but->rnaprop, &min, &max);
+				value = CLAMPIS(value, min, max);
 
-			pa->list_grip_size = MAX2(pa->list_grip_size, 1);
+				RNA_property_int_set(&but->rnapoin, but->rnaprop, value);
+				RNA_property_update(C, &but->rnapoin, but->rnaprop);
+				ED_region_tag_redraw(ar);
 
-			ED_region_tag_redraw(ar);
+				retval = WM_UI_HANDLER_BREAK;
+			}
+			else if (ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->shift) {
+				/* silly replacement for proper grip */
+				if (uilst->list_grip_size == 0)
+					uilst->list_grip_size = uilst->list_size;
 
-			retval = WM_UI_HANDLER_BREAK;
-		}
-		else if (ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
-			if (pa->list_last_len > pa->list_size) {
-				/* list template will clamp */
 				if (event->type == WHEELUPMOUSE)
-					pa->list_scroll--;
+					uilst->list_grip_size--;
 				else
-					pa->list_scroll++;
+					uilst->list_grip_size++;
+
+				uilst->list_grip_size = MAX2(uilst->list_grip_size, 1);
 
 				ED_region_tag_redraw(ar);
 
 				retval = WM_UI_HANDLER_BREAK;
 			}
+			else if (ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
+				if (uilst->list_last_len > uilst->list_size) {
+					/* list template will clamp */
+					if (event->type == WHEELUPMOUSE)
+						uilst->list_scroll--;
+					else
+						uilst->list_scroll++;
+
+					ED_region_tag_redraw(ar);
+
+					retval = WM_UI_HANDLER_BREAK;
+				}
+			}
 		}
 	}
 
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 2928a5607c0..31d1ad7a955 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -49,6 +49,7 @@
 #include "BLI_utildefines.h"
 
 #include "DNA_brush_types.h"
+#include "DNA_dynamicpaint_types.h"
 #include "DNA_object_types.h"
 #include "DNA_screen_types.h"
 #include "DNA_space_types.h"
@@ -1179,6 +1180,44 @@ int ui_id_icon_get(bContext *C, ID *id, int big)
 	return iconid;
 }
 
+int UI_rnaptr_icon_get(bContext *C, PointerRNA *ptr, int rnaicon, int big)
+{
+	ID *id = NULL;
+
+	if (!ptr->data)
+		return rnaicon;
+
+	/* try ID, material, texture or dynapaint slot */
+	if (RNA_struct_is_ID(ptr->type)) {
+		id = ptr->id.data;
+	}
+	else if (RNA_struct_is_a(ptr->type, &RNA_MaterialSlot)) {
+		id = RNA_pointer_get(ptr, "material").data;
+	}
+	else if (RNA_struct_is_a(ptr->type, &RNA_TextureSlot)) {
+		id = RNA_pointer_get(ptr, "texture").data;
+	}
+	else if (RNA_struct_is_a(ptr->type, &RNA_DynamicPaintSurface)) {
+		DynamicPaintSurface *surface = (DynamicPaintSurface *)ptr->data;
+
+		if (surface->format == MOD_DPAINT_SURFACE_F_PTEX)
+			return ICON_TEXTURE_SHADED;
+		else if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX)
+			return ICON_OUTLINER_DATA_MESH;
+		else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ)
+			return ICON_FILE_IMAGE;
+	}
+
+	/* get icon from ID */
+	if (id) {
+		int icon = ui_id_icon_get(C, id, big);
+
+		return icon ? icon : rnaicon;
+	}
+
+	return rnaicon;
+}
+
 static void icon_draw_at_size(float x, float y, int icon_id, float aspect, float alpha, enum eIconSizes size, int nocreate)
 {
 	int draw_size = get_draw_size(size);
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index f088b3a54f4..8341307481d 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -271,6 +271,9 @@ struct uiBut {
 	/* active button data */
 	struct uiHandleButtonData *active;
 
+	/* Custom button data. */
+	void *custom_data;
+
 	char *editstr;
 	double *editval;
 	float *editvec;
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 2ba4c1355c0..19b44422ac0 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -2308,11 +2308,14 @@ uiLayout *uiLayoutBox(uiLayout *layout)
 	return (uiLayout *)ui_layout_box(layout, ROUNDBOX);
 }
 
-uiLayout *uiLayoutListBox(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *actptr, PropertyRNA *actprop)
+uiLayout *uiLayoutListBox(uiLayout *layout, uiList *uilist, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *actptr,
+                          PropertyRNA *actprop)
 {
 	uiLayoutItemBx *box = ui_layout_box(layout, LISTBOX);
 	uiBut *but = box->roundbox;
 
+	but->custom_data = uilist;
+
 	but->rnasearchpoin = *ptr;
 	but->rnasearchprop = prop;
 	but->rnapoin = *actptr;
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 5145c28a2cd..34f325abe76 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -31,18 +31,16 @@
 
 #include "MEM_guardedalloc.h"
 
-#include "DNA_anim_types.h"
 #include "DNA_dynamicpaint_types.h"
-#include "DNA_key_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_object_types.h"
-#include "DNA_userdef_types.h"
 
 #include "BLI_utildefines.h"
 #include "BLI_string.h"
 #include "BLI_ghash.h"
 #include "BLI_rect.h"
 
+#include "BLF_api.h"
 #include "BLF_translation.h"
 
 #include "BKE_animsys.h"
@@ -59,6 +57,7 @@
 #include "BKE_displist.h"
 #include "BKE_sca.h"
 #include "BKE_scene.h"
+#include "BKE_screen.h"
 
 #include "ED_screen.h"
 #include "ED_object.h"
@@ -71,11 +70,9 @@
 #include "WM_types.h"
 
 #include "UI_interface.h"
+#include "UI_interface_icons.h"
 #include "interface_intern.h"
 
-#include "BLF_api.h"
-#include "BLF_translation.h"
-
 void UI_template_fix_linking(void)
 {
 }
@@ -2331,254 +2328,28 @@ void uiTemplateGameStates(uiLayout *layout, PointerRNA *ptr, const char *propnam
 
 
 /************************* List Template **************************/
-
-static int list_item_icon_get(bContext *C, PointerRNA *itemptr, int rnaicon, int big)
+static void uilist_draw_item_default(struct uiList *uilst, struct bContext *UNUSED(C), struct uiLayout *layout,
+                                     struct PointerRNA *UNUSED(dataptr), struct PointerRNA *itemptr, int icon,
+                                     struct PointerRNA *UNUSED(active_dataptr), const char *UNUSED(active_propname),
+                                     int UNUSED(index))
 {
-	ID *id = NULL;
-	int icon;
-
-	if (!itemptr->data)
-		return rnaicon;
-
-	/* try ID, material or texture slot */
-	if (RNA_struct_is_ID(itemptr->type)) {
-		id = itemptr->id.data;
-	}
-	else if (RNA_struct_is_a(itemptr->type, &RNA_MaterialSlot)) {
-		id = RNA_pointer_get(itemptr, "material").data;
-	}
-	else if (RNA_struct_is_a(itemptr->type, &RNA_TextureSlot)) {
-		id = RNA_pointer_get(itemptr, "texture").data;
-	}
-	else if (RNA_struct_is_a(itemptr->type, &RNA_DynamicPaintSurface)) {
-		DynamicPaintSurface *surface = (DynamicPaintSurface *)itemptr->data;
-
-		if (surface->format == MOD_DPAINT_SURFACE_F_PTEX) return ICON_TEXTURE_SHADED;
-		else if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) return ICON_OUTLINER_DATA_MESH;
-		else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) return ICON_FILE_IMAGE;
-	}
-
-	/* get icon from ID */
-	if (id) {
-		icon = ui_id_icon_get(C, id, big);
-
-		if (icon)
-			return icon;
-	}
-
-	return rnaicon;
-}
-
-static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *itemptr, int i,
-                          int rnaicon, PointerRNA *activeptr, PropertyRNA *activeprop, const char *prop_list_id)
-{
-	uiBlock *block = uiLayoutGetBlock(layout);
-	uiBut *but;
-	uiLayout *split, *overlap, *sub, *row;
 	char *namebuf;
 	const char *name;
-	int icon;
-
-	overlap = uiLayoutOverlap(layout);
-
-	/* list item behind label & other buttons */
-	sub = uiLayoutRow(overlap, FALSE);
-
-	but = uiDefButR_prop(block, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, activeptr, activeprop,
-	                     0, 0, i, 0, 0, "");
-	uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
-
-	sub = uiLayoutRow(overlap, FALSE);
-
-	/* retrieve icon and name */
-	icon = list_item_icon_get(C, itemptr, rnaicon, 0);
-	if (icon == ICON_NONE || icon == ICON_DOT)
-		icon = 0;
 
 	namebuf = RNA_struct_name_get_alloc(itemptr, NULL, 0, NULL);
 	name = (namebuf) ? namebuf : "";
 
-	/* hardcoded types */
-	if (itemptr->type == &RNA_MeshTexturePolyLayer || itemptr->type == &RNA_MeshLoopColorLayer) {
-		uiItemL(sub, name, icon);
-		uiBlockSetEmboss(block, UI_EMBOSSN);
-		uiDefIconButR(block, TOG, 0, ICON_SCENE, 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "active_render",
-		              0, 0, 0, 0, 0, NULL);
-		uiBlockSetEmboss(block, UI_EMBOSS);
+	/* Simplest one! */
+	switch (uilst->layout_type) {
+	case UILST_LAYOUT_GRID:
+		uiItemL(layout, "", icon);
+		break;
+	case UILST_LAYOUT_DEFAULT:
+	case UILST_LAYOUT_COMPACT:
+	default:
+		uiItemL(layout, name, icon);
+		break;
 	}
-	else if (RNA_struct_is_a(itemptr->type, &RNA_MaterialTextureSlot)) {
-		uiItemL(sub, name, icon);
-		uiBlockSetEmboss(block, UI_EMBOSS);
-		uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, ptr, "use_textures", i, 0, 0, 0, 0,  NULL);
-	}
-	else if (RNA_struct_is_a(itemptr->type, &RNA_SceneRenderLayer)) {
-		uiItemL(sub, name, icon);
-		uiBlockSetEmboss(block, UI_EMBOSS);
-		uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "use", 0, 0, 0, 0, 0,  NULL);
-	}
-	else if (RNA_struct_is_a(itemptr->type, &RNA_MaterialSlot)) {
-		/* provision to draw active node name */
-		Material *ma, *manode;
-		Scene *scene = CTX_data_scene(C);
-		Object *ob = (Object *)ptr->id.data;
-		int index = (Material **)itemptr->data - ob->mat;
-		
-		/* default item with material base name */
-		uiItemL(sub, name, icon);
-		
-		ma = give_current_material(ob, index + 1);
-		if (ma && !BKE_scene_use_new_shading_nodes(scene)) {
-			manode = give_node_material(ma);
-			if (manode) {
-				char str[MAX_ID_NAME + 12];
-				BLI_snprintf(str, sizeof(str), IFACE_("Node %s"), manode->id.name + 2);
-				uiItemL(sub, str, ui_id_icon_get(C, &manode->id, 1));
-			}
-			else if (ma->use_nodes) {
-				uiItemL(sub, IFACE_("Node "), ICON_NONE);
-			}
-		}
-	}
-	else if (itemptr->type == &RNA_ShapeKey) {
-		Object *ob = (Object *)activeptr->data;
-		Key *key = (Key *)itemptr->id.data;
-		KeyBlock *kb = (KeyBlock *)itemptr->data;
-
-		split = uiLayoutSplit(sub, 0.66f, FALSE);
-
-		uiItemL(split, name, icon);
-
-		uiBlockSetEmboss(block, UI_EMBOSSN);
-		row = uiLayoutRow(split, TRUE);
-		if (i == 0 || (key->type != KEY_RELATIVE)) uiItemL(row, "", ICON_NONE);
-		else uiItemR(row, itemptr, "value", 0, "", ICON_NONE);
-		uiItemR(row, itemptr, "mute", 0, "", ICON_NONE);
-
-		if ((kb->flag & KEYBLOCK_MUTE) ||
-		    (ob->mode == OB_MODE_EDIT && !((ob->shapeflag & OB_SHAPE_EDIT_MODE) && ob->type == OB_MESH)))
-		{
-			uiLayoutSetActive(row, FALSE);
-		}
-		uiBlockSetEmboss(block, UI_EMBOSS);
-	}
-	else if (itemptr->type == &RNA_VertexGroup) {
-		bDeformGroup *dg = (bDeformGroup *)itemptr->data;
-		uiItemL(sub, name, icon);
-		/* RNA does not allow nice lock icons, use lower level buttons */
-#if 0
-		uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "lock_weight", 0, 0, 0, 0, 0,  NULL);
-#else
-		uiBlockSetEmboss(block, UI_EMBOSSN);
-		uiDefIconButBitC(block, TOG, DG_LOCK_WEIGHT, 0, (dg->flag & DG_LOCK_WEIGHT) ? ICON_LOCKED : ICON_UNLOCKED,
-		                 0, 0, UI_UNIT_X, UI_UNIT_Y, &dg->flag, 0, 0, 0, 0,
-		                 TIP_("Maintain relative weights while painting"));
-		uiBlockSetEmboss(block, UI_EMBOSS);
-#endif
-	}
-	else if (itemptr->type == &RNA_KeyingSetPath) {
-		KS_Path *ksp = (KS_Path *)itemptr->data;
-		
-		/* icon needs to be the type of ID which is currently active */
-		RNA_enum_icon_from_value(id_type_items, ksp->idtype, &icon);
-		
-		/* nothing else special to do... */
-		uiItemL(sub, name, icon); /* fails, backdrop LISTROW... */
-	}
-	else if (itemptr->type == &RNA_DynamicPaintSurface) {
-		char name_final[96];
-		const char *enum_name;
-		PropertyRNA *prop = RNA_struct_find_property(itemptr, "surface_type");
-		DynamicPaintSurface *surface = (DynamicPaintSurface *)itemptr->data;
-
-		RNA_property_enum_name(C, itemptr, prop, RNA_property_enum_get(itemptr, prop), &enum_name);
-
-		BLI_snprintf(name_final, sizeof(name_final), "%s (%s)", name, enum_name);
-		uiItemL(sub, name_final, icon);
-		if (dynamicPaint_surfaceHasColorPreview(surface)) {
-			uiBlockSetEmboss(block, UI_EMBOSSN);
-			uiDefIconButR(block, OPTION, 0,
-			              (surface->flags & MOD_DPAINT_PREVIEW) ? ICON_RESTRICT_VIEW_OFF : ICON_RESTRICT_VIEW_ON,
-			              0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "show_preview", 0, 0, 0, 0, 0, NULL);
-			uiBlockSetEmboss(block, UI_EMBOSS);
-		}
-		uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "is_active", i, 0, 0, 0, 0,  NULL);
-	}
-	else if (itemptr->type == &RNA_MovieTrackingObject) {
-		MovieTrackingObject *tracking_object = (MovieTrackingObject *)itemptr->data;
-
-		split = uiLayoutSplit(sub, 0.75f, FALSE);
-		if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
-			uiItemL(split, name, ICON_CAMERA_DATA);
-		}
-		else {
-			uiItemL(split, name, ICON_OBJECT_DATA);
-		}
-	}
-	else if (itemptr->type == &RNA_MaskLayer) {
-		split = uiLayoutRow(sub, FALSE);
-
-		uiItemL(split, name, icon);
-
-		uiBlockSetEmboss(block, UI_EMBOSSN);
-		row = uiLayoutRow(split, TRUE);
-		uiItemR(row, itemptr, "alpha", 0, "", ICON_NONE);
-		uiItemR(row, itemptr, "hide", 0, "", ICON_NONE);
-		uiItemR(row, itemptr, "hide_select", 0, "", ICON_NONE);
-		uiItemR(row, itemptr, "hide_render", 0, "", ICON_NONE);
-
-		uiBlockSetEmboss(block, UI_EMBOSS);
-	}
-
-	/* There is a last chance to display custom controls (in addition to the name/label):
-	 * If the given item property group features a string property named as prop_list,
-	 * this tries to add controls for all properties of the item listed in that string property.
-	 * (colon-separated names).
-	 *
-	 * This is especially useful for python. E.g., if you list a collection of this property
-	 * group:
-	 *
-	 * class TestPropertyGroup(bpy.types.PropertyGroup):
-	 *     bool    = BoolProperty(default=False)
-	 *     integer = IntProperty()
-	 *     string  = StringProperty()
-	 * 
-	 *     # A string of all identifiers (colon-separated) which property's controls should be
-	 *     # displayed in a template_list.
-	 *     template_list_controls = StringProperty(default="integer:bool:string", options={"HIDDEN"})
-	 *
-	 * ... you'll get a numfield for the integer prop, a check box for the bool prop, and a textfield
-	 * for the string prop, after the name of each item of the collection.
-	 */
-	else if (prop_list_id) {
-		row = uiLayoutRow(sub, TRUE);
-		uiItemL(row, name, icon);
-
-		/* XXX: Check, as sometimes we get an itemptr looking like
-		 *      {id = {data = 0x0}, type = 0x0, data = 0x0}
-		 *      which would obviously produce a sigsev... */
-		if (itemptr->type) {
-			/* If the special property is set for the item, and it is a collection... */
-			PropertyRNA *prop_list = RNA_struct_find_property(itemptr, prop_list_id);
-
-			if (prop_list && RNA_property_type(prop_list) == PROP_STRING) {
-				int prop_names_len;
-				char *prop_names = RNA_property_string_get_alloc(itemptr, prop_list, NULL, 0, &prop_names_len);
-				char *prop_names_end = prop_names + prop_names_len;
-				char *id = prop_names;
-				char *id_next;
-				while (id < prop_names_end) {
-					if ((id_next = strchr(id, ':'))) *id_next++ = '\0';
-					else id_next = prop_names_end;
-					uiItemR(row, itemptr, id, 0, NULL, ICON_NONE);
-					id = id_next;
-				}
-				MEM_freeN(prop_names);
-			}
-		}
-	}
-
-	else
-		uiItemL(sub, name, icon);  /* fails, backdrop LISTROW... */
 
 	/* free name */
 	if (namebuf) {
@@ -2586,177 +2357,166 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe
 	}
 }
 
-void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *activeptr,
-                    const char *activepropname, const char *prop_list, int rows, int maxrows, int listtype)
+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, int rows, int maxrows, int layout_type)
 {
+	uiListType *ult;
+	uiList *uilst = NULL;
+	ARegion *ar;
+	uiListDrawItemFunc draw_item;
+
 	PropertyRNA *prop = NULL, *activeprop;
 	PropertyType type, activetype;
 	StructRNA *ptype;
-	uiLayout *box, *row, *col;
-	uiBlock *block;
+	uiLayout *box, *row, *col, *sub, *overlap;
+	uiBlock *block, *subblock;
 	uiBut *but;
-	Panel *pa;
-	const char *name;
+
+	char uilst_id[UI_MAX_NAME_STR];
 	char numstr[32];
-	int rnaicon = 0, icon = 0, i = 0, activei = 0, len = 0, items, found, min, max;
+	int rnaicon = ICON_NONE, icon = ICON_NONE;
+	int i = 0, activei = 0;
+	int len = 0;
+	int items;
+	int found;
+	int min, max;
 
 	/* validate arguments */
 	block = uiLayoutGetBlock(layout);
-	pa = block->panel;
 
-	if (!pa) {
-		RNA_warning("Only works inside a panel");
+	if (!active_dataptr->data) {
+		RNA_warning("No active data");
 		return;
 	}
 
-	if (!activeptr->data)
-		return;
-	
-	if (ptr->data) {
-		prop = RNA_struct_find_property(ptr, propname);
+	if (dataptr->data) {
+		prop = RNA_struct_find_property(dataptr, propname);
 		if (!prop) {
-			RNA_warning("Property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+			RNA_warning("Property not found: %s.%s", RNA_struct_identifier(dataptr->type), propname);
 			return;
 		}
 	}
 
-	activeprop = RNA_struct_find_property(activeptr, activepropname);
+	activeprop = RNA_struct_find_property(active_dataptr, active_propname);
 	if (!activeprop) {
-		RNA_warning("Property not found: %s.%s", RNA_struct_identifier(ptr->type), activepropname);
+		RNA_warning("Property not found: %s.%s", RNA_struct_identifier(active_dataptr->type), active_propname);
 		return;
 	}
 
 	if (prop) {
 		type = RNA_property_type(prop);
 		if (type != PROP_COLLECTION) {
-			RNA_warning("uiExpected collection property");
+			RNA_warning("Expected a collection data property");
 			return;
 		}
 	}
 
 	activetype = RNA_property_type(activeprop);
 	if (activetype != PROP_INT) {
-		RNA_warning("Expected integer property");
+		RNA_warning("Expected an integer active data property");
 		return;
 	}
 
 	/* get icon */
-	if (ptr->data && prop) {
-		ptype = RNA_property_pointer_type(ptr, prop);
+	if (dataptr->data && prop) {
+		ptype = RNA_property_pointer_type(dataptr, prop);
 		rnaicon = RNA_struct_ui_icon(ptype);
 	}
 
 	/* get active data */
-	activei = RNA_property_int_get(activeptr, activeprop);
+	activei = RNA_property_int_get(active_dataptr, activeprop);
 
-	if (listtype == 'i') {
-		box = uiLayoutListBox(layout, ptr, prop, activeptr, activeprop);
-		col = uiLayoutColumn(box, TRUE);
-		row = uiLayoutRow(col, FALSE);
+	/* Find the uiList type. */
+	ult = WM_uilisttype_find(listtype_name, FALSE);
 
-		if (ptr->data && prop) {
-			/* create list items */
-			RNA_PROP_BEGIN (ptr, itemptr, prop)
-			{
-				/* create button */
-				if (!(i % 9))
-					row = uiLayoutRow(col, FALSE);
-
-				icon = list_item_icon_get(C, &itemptr, rnaicon, 1);
-				but = uiDefIconButR_prop(block, LISTROW, 0, icon, 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, activeptr,
-				                         activeprop, 0, 0, i, 0, 0, "");
-				uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
-				
-
-				i++;
-			}
-			RNA_PROP_END;
-		}
+	if (ult == NULL) {
+		RNA_warning("List type %s not found", listtype_name);
+		return;
 	}
-	else if (listtype == 'c') {
-		/* compact layout */
-
-		row = uiLayoutRow(layout, TRUE);
 
-		if (ptr->data && prop) {
-			/* create list items */
-			RNA_PROP_BEGIN (ptr, itemptr, prop)
-			{
-				found = (activei == i);
+	draw_item = ult->draw_item ? ult->draw_item : uilist_draw_item_default;
 
-				if (found) {
-					/* create button */
-					name = RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL);
-					icon = list_item_icon_get(C, &itemptr, rnaicon, 0);
-					uiItemL(row, (name) ? name : "", icon);
+	/* Find or add the uiList to the current Region. */
+	/* We tag the list id with the list type... */
+	BLI_snprintf(uilst_id, sizeof(uilst_id), "%s_%s", ult->idname, list_id ? list_id : "");
 
-					if (name) {
-						MEM_freeN((void *)name);
-					}
-				}
+	ar = CTX_wm_region(C);
+	uilst = BLI_findstring(&ar->uiLists, uilst_id, offsetof(uiList, list_id));
 
-				i++;
-			}
-			RNA_PROP_END;
-		}
+	if (!uilst) {
+		uilst = MEM_callocN(sizeof(uiList), __func__);
+		BLI_strncpy(uilst->list_id, uilst_id, sizeof(uilst->list_id));
+		BLI_addtail(&ar->uiLists, uilst);
+	}
 
-		/* if not found, add in dummy button */
-		if (i == 0)
-			uiItemL(row, "", ICON_NONE);
+	/* Because we can't actually pass type across save&load... */
+	uilst->type = ult;
+	uilst->layout_type = layout_type;
 
-		/* next/prev button */
-		BLI_snprintf(numstr, sizeof(numstr), "%d :", i);
-		but = uiDefIconTextButR_prop(block, NUM, 0, 0, numstr, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, activeptr,
-		                             activeprop, 0, 0, 0, 0, 0, "");
-		if (i == 0)
-			uiButSetFlag(but, UI_BUT_DISABLED);
-	}
-	else {
+	switch (layout_type) {
+	case UILST_LAYOUT_DEFAULT:
 		/* default rows */
 		if (rows == 0)
 			rows = 5;
 		if (maxrows == 0)
 			maxrows = 5;
-		if (pa->list_grip_size != 0)
-			rows = pa->list_grip_size;
+		if (uilst->list_grip_size != 0)
+			rows = uilst->list_grip_size;
 
 		/* layout */
-		box = uiLayoutListBox(layout, ptr, prop, activeptr, activeprop);
+		box = uiLayoutListBox(layout, uilst, dataptr, prop, active_dataptr, activeprop);
 		row = uiLayoutRow(box, FALSE);
 		col = uiLayoutColumn(row, TRUE);
 
 		/* init numbers */
-		RNA_property_int_range(activeptr, activeprop, &min, &max);
+		RNA_property_int_range(active_dataptr, activeprop, &min, &max);
 
 		if (prop)
-			len = RNA_property_collection_length(ptr, prop);
+			len = RNA_property_collection_length(dataptr, prop);
 		items = CLAMPIS(len, rows, MAX2(rows, maxrows));
 
 		/* if list length changes and active is out of view, scroll to it */
-		if (pa->list_last_len != len)
-			if ((activei < pa->list_scroll || activei >= pa->list_scroll + items))
-				pa->list_scroll = activei;
+		if ((uilst->list_last_len != len) &&
+		    (activei < uilst->list_scroll || activei >= uilst->list_scroll + items)) {
+			uilst->list_scroll = activei;
+		}
 
-		pa->list_scroll = MIN2(pa->list_scroll, len - items);
-		pa->list_scroll = MAX2(pa->list_scroll, 0);
-		pa->list_size = items;
-		pa->list_last_len = len;
+		uilst->list_scroll = MIN2(uilst->list_scroll, len - items);
+		uilst->list_scroll = MAX2(uilst->list_scroll, 0);
+		uilst->list_size = items;
+		uilst->list_last_len = len;
 
-		if (ptr->data && prop) {
+		if (dataptr->data && prop) {
 			/* create list items */
-			RNA_PROP_BEGIN (ptr, itemptr, prop)
+			RNA_PROP_BEGIN (dataptr, itemptr, prop)
 			{
-				if (i >= pa->list_scroll && i < pa->list_scroll + items)
-					list_item_row(C, col, ptr, &itemptr, i, rnaicon, activeptr, activeprop, prop_list);
+				if (i >= uilst->list_scroll && i < uilst->list_scroll + items) {
+					subblock = uiLayoutGetBlock(col);
+					overlap = uiLayoutOverlap(col);
+
+					/* list item behind label & other buttons */
+					sub = uiLayoutRow(overlap, FALSE);
+
+					but = uiDefButR_prop(subblock, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
+					                     active_dataptr, activeprop, 0, 0, i, 0, 0, "");
+					uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
+
+					sub = uiLayoutRow(overlap, FALSE);
 
+					icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, FALSE);
+					if (icon == ICON_DOT)
+						icon = ICON_NONE;
+					draw_item(uilst, C, sub, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
+				}
 				i++;
 			}
 			RNA_PROP_END;
 		}
 
 		/* add dummy buttons to fill space */
-		while (i < pa->list_scroll + items) {
-			if (i >= pa->list_scroll)
+		while (i < uilst->list_scroll + items) {
+			if (i >= uilst->list_scroll)
 				uiItemL(col, "", ICON_NONE);
 			i++;
 		}
@@ -2764,9 +2524,75 @@ void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *
 		/* add scrollbar */
 		if (len > items) {
 			col = uiLayoutColumn(row, FALSE);
-			uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * items, &pa->list_scroll,
+			uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * items, &uilst->list_scroll,
 			          0, len - items, items, 0, "");
 		}
+		break;
+	case UILST_LAYOUT_COMPACT:
+		row = uiLayoutRow(layout, TRUE);
+
+		if (dataptr->data && prop) {
+			/* create list items */
+			RNA_PROP_BEGIN (dataptr, itemptr, prop)
+			{
+				found = (activei == i);
+
+				if (found) {
+					icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, FALSE);
+					if (icon == ICON_DOT)
+						icon = ICON_NONE;
+					draw_item(uilst, C, row, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
+				}
+
+				i++;
+			}
+			RNA_PROP_END;
+		}
+
+		/* if list is empty, add in dummy button */
+		if (i == 0)
+			uiItemL(row, "", ICON_NONE);
+
+		/* next/prev button */
+		BLI_snprintf(numstr, sizeof(numstr), "%d :", i);
+		but = uiDefIconTextButR_prop(block, NUM, 0, 0, numstr, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y,
+		                             active_dataptr, activeprop, 0, 0, 0, 0, 0, "");
+		if (i == 0)
+			uiButSetFlag(but, UI_BUT_DISABLED);
+		break;
+	case UILST_LAYOUT_GRID:
+		box = uiLayoutListBox(layout, uilst, dataptr, prop, active_dataptr, activeprop);
+		col = uiLayoutColumn(box, TRUE);
+		row = uiLayoutRow(col, FALSE);
+
+		if (dataptr->data && prop) {
+			/* create list items */
+			RNA_PROP_BEGIN (dataptr, itemptr, prop)
+			{
+				/* create button */
+				if (!(i % 9))
+					row = uiLayoutRow(col, FALSE);
+
+				subblock = uiLayoutGetBlock(row);
+				overlap = uiLayoutOverlap(row);
+
+				/* list item behind label & other buttons */
+				sub = uiLayoutRow(overlap, FALSE);
+
+				but = uiDefButR_prop(subblock, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
+				                     active_dataptr, activeprop, 0, 0, i, 0, 0, "");
+				uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
+
+				sub = uiLayoutRow(overlap, FALSE);
+
+				icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, FALSE);
+				draw_item(uilst, C, sub, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
+
+				i++;
+			}
+			RNA_PROP_END;
+		}
+		break;
 	}
 }
 
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 59dd66a0207..b702dc4c0bc 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -2152,12 +2152,12 @@ static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C
 	active_index = RNA_int_get(ptr, "active_input_index");
 	/* using different collection properties if multilayer format is enabled */
 	if (multilayer) {
-		uiTemplateList(col, C, ptr, "layer_slots", ptr, "active_input_index", NULL, 0, 0, 0);
+		uiTemplateList(col, C, "UI_UL_list", "", ptr, "layer_slots", ptr, "active_input_index", 0, 0, 0);
 		RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "layer_slots"),
 		                                   active_index, &active_input_ptr);
 	}
 	else {
-		uiTemplateList(col, C, ptr, "file_slots", ptr, "active_input_index", NULL, 0, 0, 0);
+		uiTemplateList(col, C, "UI_UL_list", "", ptr, "file_slots", ptr, "active_input_index", 0, 0, 0);
 		RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "file_slots"),
 		                                   active_index, &active_input_ptr);
 	}
diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h
index de6ddb4b896..5d8176c8021 100644
--- a/source/blender/makesdna/DNA_screen_types.h
+++ b/source/blender/makesdna/DNA_screen_types.h
@@ -110,12 +110,26 @@ typedef struct Panel {		/* the part from uiBlock that needs saved in file */
 	int sortorder;			/* panels are aligned according to increasing sortorder */
 	struct Panel *paneltab;		/* this panel is tabbed in *paneltab */
 	void *activedata;			/* runtime for panel manipulation */
-
-	int list_scroll, list_size;
-	int list_last_len, list_grip_size;
-	char list_search[64];
 } Panel;
 
+typedef struct uiList {				/* some list UI data need to be saved in file */
+	struct uiList *next, *prev;
+
+	struct uiListType *type;		/* runtime */
+	void *padp;
+
+	char list_id[64];				/* defined as UI_MAX_NAME_STR */
+
+	int layout_type;				/* How items are layedout in the list */
+	int padi;
+
+	int list_scroll;
+	int list_size;
+	int list_last_len;
+	int list_grip_size;
+/*	char list_search[64]; */
+} uiList;
+
 typedef struct ScrArea {
 	struct ScrArea *next, *prev;
 	
@@ -167,6 +181,7 @@ typedef struct ARegion {
 	
 	ListBase uiblocks;			/* uiBlock */
 	ListBase panels;			/* Panel */
+	ListBase uiLists;			/* uiList */
 	ListBase handlers;			/* wmEventHandler */
 	
 	struct wmTimer *regiontimer; /* blend in/out */
@@ -216,6 +231,13 @@ typedef struct ARegion {
 #define PNL_DEFAULT_CLOSED		1
 #define PNL_NO_HEADER			2
 
+/* uilist layout_type */
+enum {
+	UILST_LAYOUT_DEFAULT          = 0,
+	UILST_LAYOUT_COMPACT          = 1,
+	UILST_LAYOUT_GRID             = 2,
+};
+
 /* regiontype, first two are the default set */
 /* Do NOT change order, append on end. Types are hardcoded needed */
 enum {
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 7625605c5fb..bf78c622cbd 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -587,7 +587,7 @@ extern StructRNA RNA_TrackToConstraint;
 extern StructRNA RNA_TransformConstraint;
 extern StructRNA RNA_TransformSequence;
 extern StructRNA RNA_UILayout;
-extern StructRNA RNA_UIListItem;
+extern StructRNA RNA_UIList;
 extern StructRNA RNA_UVWarpModifier;
 extern StructRNA RNA_UVProjectModifier;
 extern StructRNA RNA_UVProjector;
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index 9d08cf2d364..49f881ce285 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -133,6 +133,9 @@ extern EnumPropertyItem prop_dynamicpaint_type_items[];
 
 extern EnumPropertyItem clip_editor_mode_items[];
 
+extern EnumPropertyItem icon_items[];
+extern EnumPropertyItem uilist_layout_type_items[];
+
 struct bContext;
 struct PointerRNA;
 struct PropertyRNA;
diff --git a/source/blender/makesrna/intern/rna_dynamicpaint.c b/source/blender/makesrna/intern/rna_dynamicpaint.c
index 4f9f2009a14..030325494ff 100644
--- a/source/blender/makesrna/intern/rna_dynamicpaint.c
+++ b/source/blender/makesrna/intern/rna_dynamicpaint.c
@@ -32,6 +32,8 @@
 
 #include "rna_internal.h"
 
+#include "BLI_math_base.h"
+
 #include "BKE_modifier.h"
 #include "BKE_dynamicpaint.h"
 
@@ -219,6 +221,14 @@ static int rna_DynamicPaint_is_cache_user_get(PointerRNA *ptr)
 	return (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ) ?  1 : 0;
 }
 
+/* is some 3D view preview available */
+static int rna_DynamicPaint_use_color_preview_get(PointerRNA *ptr)
+{
+	DynamicPaintSurface *surface = (DynamicPaintSurface *)ptr->data;
+
+	return dynamicPaint_surfaceHasColorPreview(surface);
+}
+
 /* does output layer exist*/
 static int rna_DynamicPaint_is_output_exists(DynamicPaintSurface *surface, Object *ob, int index)
 {
@@ -239,6 +249,7 @@ static EnumPropertyItem *rna_DynamicPaint_surface_type_itemf(bContext *C, Pointe
 	tmp.value = MOD_DPAINT_SURFACE_T_PAINT;
 	tmp.identifier = "PAINT";
 	tmp.name = "Paint";
+	tmp.icon = ICON_TPAINT_HLT;
 	RNA_enum_item_add(&item, &totitem, &tmp);
 
 	/* Displace */
@@ -248,6 +259,7 @@ static EnumPropertyItem *rna_DynamicPaint_surface_type_itemf(bContext *C, Pointe
 		tmp.value = MOD_DPAINT_SURFACE_T_DISPLACE;
 		tmp.identifier = "DISPLACE";
 		tmp.name = "Displace";
+		tmp.icon = ICON_MOD_DISPLACE;
 		RNA_enum_item_add(&item, &totitem, &tmp);
 	}
 
@@ -256,6 +268,7 @@ static EnumPropertyItem *rna_DynamicPaint_surface_type_itemf(bContext *C, Pointe
 		tmp.value = MOD_DPAINT_SURFACE_T_WEIGHT;
 		tmp.identifier = "WEIGHT";
 		tmp.name = "Weight";
+		tmp.icon = ICON_MOD_VERTEX_WEIGHT;
 		RNA_enum_item_add(&item, &totitem, &tmp);
 	}
 
@@ -264,6 +277,7 @@ static EnumPropertyItem *rna_DynamicPaint_surface_type_itemf(bContext *C, Pointe
 		tmp.value = MOD_DPAINT_SURFACE_T_WAVE;
 		tmp.identifier = "WAVE";
 		tmp.name = "Waves";
+		tmp.icon = ICON_MOD_WAVE;
 		RNA_enum_item_add(&item, &totitem, &tmp);
 	}
 
@@ -705,6 +719,14 @@ static void rna_def_canvas_surface(BlenderRNA *brna)
 	RNA_def_property_boolean_funcs(prop, "rna_DynamicPaint_is_cache_user_get", NULL);
 	RNA_def_property_ui_text(prop, "Use Cache", "");
 	RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
+
+	/* whether this surface has preview data for 3D view */
+	RNA_define_verify_sdna(FALSE);
+	prop = RNA_def_property(srna, "use_color_preview", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_funcs(prop, "rna_DynamicPaint_use_color_preview_get", NULL);
+	RNA_def_property_ui_text(prop, "Use Corlor Preview", "Whether this surface has some color preview for 3D view");
+	RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
+	RNA_define_verify_sdna(TRUE);
 }
 
 static void rna_def_dynamic_paint_canvas_settings(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c
index de359fd6413..e6e953c412b 100644
--- a/source/blender/makesrna/intern/rna_ui.c
+++ b/source/blender/makesrna/intern/rna_ui.c
@@ -55,6 +55,16 @@ EnumPropertyItem operator_context_items[] = {
 	{0, NULL, 0, NULL, NULL}
 };
 
+EnumPropertyItem uilist_layout_type_items[] = {
+	{UILST_LAYOUT_DEFAULT, "DEFAULT", 0, "Default Layout",
+	                       "Use the default, multi-rows layout"},
+	{UILST_LAYOUT_COMPACT, "COMPACT", 0, "Compact Layout",
+	                       "Use the compact, single-row layout"},
+	{UILST_LAYOUT_GRID, "GRID", 0, "Grid Layout",
+	                    "Use the grid-based layout"},
+	{0, NULL, 0, NULL, NULL}
+};
+
 #ifdef RNA_RUNTIME
 
 #include 
@@ -252,6 +262,105 @@ static StructRNA *rna_Panel_refine(PointerRNA *ptr)
 	return (hdr->type && hdr->type->ext.srna) ? hdr->type->ext.srna : &RNA_Panel;
 }
 
+/* UIList */
+static void uilist_draw_item(uiList *uilst, bContext *C, uiLayout *layout, PointerRNA *dataptr, PointerRNA *itemptr,
+                             int icon, PointerRNA *active_dataptr, const char *active_propname, int index)
+{
+	extern FunctionRNA rna_UIList_draw_item_func;
+
+	PointerRNA ultr;
+	ParameterList list;
+	FunctionRNA *func;
+
+	RNA_pointer_create(&CTX_wm_screen(C)->id, uilst->type->ext.srna, uilst, &ultr);
+	func = &rna_UIList_draw_item_func; /* RNA_struct_find_function(&ultr, "draw_item"); */
+
+	RNA_parameter_list_create(&list, &ultr, func);
+	RNA_parameter_set_lookup(&list, "context", &C);
+	RNA_parameter_set_lookup(&list, "layout", &layout);
+	RNA_parameter_set_lookup(&list, "data", dataptr);
+	RNA_parameter_set_lookup(&list, "item", itemptr);
+	RNA_parameter_set_lookup(&list, "icon", &icon);
+	RNA_parameter_set_lookup(&list, "active_data", active_dataptr);
+	RNA_parameter_set_lookup(&list, "active_property", &active_propname);
+	RNA_parameter_set_lookup(&list, "index", &index);
+	uilst->type->ext.call((bContext *)C, &ultr, func, &list);
+
+	RNA_parameter_list_free(&list);
+}
+
+static void rna_UIList_unregister(Main *UNUSED(bmain), StructRNA *type)
+{
+	uiListType *ult = RNA_struct_blender_type_get(type);
+
+	if (!ult)
+		return;
+
+	RNA_struct_free_extension(type, &ult->ext);
+
+	WM_uilisttype_freelink(ult);
+
+	RNA_struct_free(&BLENDER_RNA, type);
+
+	/* update while blender is running */
+	WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
+}
+
+static StructRNA *rna_UIList_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
+                                      StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+	uiListType *ult, dummyult = {NULL};
+	uiList dummyuilist = {NULL};
+	PointerRNA dummyultr;
+	int have_function[1];
+	size_t over_alloc = 0; /* warning, if this becomes a bess, we better do another alloc */
+
+	/* setup dummy menu & menu type to store static properties in */
+	dummyuilist.type = &dummyult;
+	RNA_pointer_create(NULL, &RNA_UIList, &dummyuilist, &dummyultr);
+
+	/* validate the python class */
+	if (validate(&dummyultr, data, have_function) != 0)
+		return NULL;
+
+	if (strlen(identifier) >= sizeof(dummyult.idname)) {
+		BKE_reportf(reports, RPT_ERROR, "Registering uilist class: '%s' is too long, maximum length is %d",
+		            identifier, (int)sizeof(dummyult.idname));
+		return NULL;
+	}
+
+	/* check if we have registered this uilist type before, and remove it */
+	ult = WM_uilisttype_find(dummyult.idname, TRUE);
+	if (ult && ult->ext.srna)
+		rna_UIList_unregister(bmain, ult->ext.srna);
+
+	/* create a new menu type */
+	ult = MEM_callocN(sizeof(uiListType) + over_alloc, "python uilist");
+	memcpy(ult, &dummyult, sizeof(dummyult));
+
+	ult->ext.srna = RNA_def_struct(&BLENDER_RNA, ult->idname, "UIList");
+	ult->ext.data = data;
+	ult->ext.call = call;
+	ult->ext.free = free;
+	RNA_struct_blender_type_set(ult->ext.srna, ult);
+	RNA_def_struct_flag(ult->ext.srna, STRUCT_NO_IDPROPERTIES);
+
+	ult->draw_item = (have_function[0]) ? uilist_draw_item : NULL;
+
+	WM_uilisttype_add(ult);
+
+	/* update while blender is running */
+	WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
+
+	return ult->ext.srna;
+}
+
+static StructRNA *rna_UIList_refine(PointerRNA *ptr)
+{
+	uiList *uilst = (uiList *)ptr->data;
+	return (uilst->type && uilst->type->ext.srna) ? uilst->type->ext.srna : &RNA_UIList;
+}
+
 /* Header */
 
 static void header_draw(const bContext *C, Header *hdr)
@@ -495,6 +604,8 @@ static void rna_Menu_bl_description_set(PointerRNA *ptr, const char *value)
 	else assert(!"setting the bl_description on a non-builtin menu");
 }
 
+/* UILayout */
+
 static int rna_UILayout_active_get(PointerRNA *ptr)
 {
 	return uiLayoutGetActive(ptr->data);
@@ -738,6 +849,58 @@ static void rna_def_panel(BlenderRNA *brna)
 	RNA_def_property_ui_text(prop, "Options",  "Options for this panel type");
 }
 
+static void rna_def_uilist(BlenderRNA *brna)
+{
+	StructRNA *srna;
+	PropertyRNA *prop;
+	PropertyRNA *parm;
+	FunctionRNA *func;
+
+	srna = RNA_def_struct(brna, "UIList", NULL);
+	RNA_def_struct_ui_text(srna, "UIList", "UI list containing the elements of a collection");
+	RNA_def_struct_sdna(srna, "uiList");
+	RNA_def_struct_refine_func(srna, "rna_UIList_refine");
+	RNA_def_struct_register_funcs(srna, "rna_UIList_register", "rna_UIList_unregister", NULL);
+
+	/* draw */
+	func = RNA_def_function(srna, "draw_item", NULL);
+	RNA_def_function_ui_description(func, "Draw an item in the list (NOTE: when you define your own draw_item "
+	                                      "function, you may want to check given 'item' is of the right type...)");
+	RNA_def_function_flag(func, FUNC_REGISTER);
+	parm = RNA_def_pointer(func, "context", "Context", "", "");
+	RNA_def_property_flag(parm, PROP_REQUIRED);
+	parm = RNA_def_pointer(func, "layout", "UILayout", "", "Layout to draw the item");
+	RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+	parm = RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take Collection property");
+	RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR);
+	parm = RNA_def_pointer(func, "item", "AnyType", "", "Item of the collection property");
+	RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR);
+	parm = RNA_def_int(func, "icon", 0, 0, INT_MAX, "", "Icon of the item in the collection", 0, INT_MAX);
+	RNA_def_property_flag(parm, PROP_REQUIRED);
+	parm = RNA_def_pointer(func, "active_data", "AnyType", "",
+	                       "Data from which to take property for the active element");
+	RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL);
+	parm = RNA_def_string(func, "active_property", "", 0, "",
+	                      "Identifier of property in active_data, for the active element");
+	RNA_def_property_flag(parm, PROP_REQUIRED);
+	RNA_def_int(func, "index", 0, 0, INT_MAX, "", "Index of the item in the collection", 0, INT_MAX);
+	RNA_def_property_flag(parm, PROP_REQUIRED);
+
+	prop = RNA_def_property(srna, "layout_type", PROP_ENUM, PROP_NONE);
+	RNA_def_property_enum_items(prop, uilist_layout_type_items);
+	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+	/* registration */
+	prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
+	RNA_def_property_string_sdna(prop, NULL, "type->idname");
+	RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
+	RNA_def_property_ui_text(prop, "ID Name",
+	                         "If this is set, the uilist gets a custom ID, otherwise it takes the "
+	                         "name of the class used to define the uilist (for example, if the "
+	                         "class name is \"OBJECT_UL_vgroups\", and bl_idname is not set by the "
+	                         "script, then bl_idname = \"OBJECT_UL_vgroups\")");
+}
+
 static void rna_def_header(BlenderRNA *brna)
 {
 	StructRNA *srna;
@@ -852,6 +1015,7 @@ void RNA_def_ui(BlenderRNA *brna)
 {
 	rna_def_ui_layout(brna);
 	rna_def_panel(brna);
+	rna_def_uilist(brna);
 	rna_def_header(brna);
 	rna_def_menu(brna);
 }
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index 548539e3395..366d0dc1fd9 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -33,8 +33,12 @@
 #include 
 
 #include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "DNA_screen_types.h"
 
 #include "UI_resources.h"
+#include "UI_interface_icons.h"
 
 #include "rna_internal.h"
 
@@ -70,12 +74,117 @@ static PointerRNA rna_uiItemO(uiLayout *layout, const char *opname, const char *
 	return uiItemFullO(layout, opname, name, icon, NULL, uiLayoutGetOperatorContext(layout), flag);
 }
 
+static void rna_uiItemL(uiLayout *layout, const char *name, int icon, int icon_value)
+{
+	if (icon_value && !icon) {
+		icon = icon_value;
+	}
+
+	uiItemL(layout, name, icon);
+}
+
+static int rna_ui_get_rnaptr_icon(bContext *C, PointerRNA *ptr_icon)
+{
+	return UI_rnaptr_icon_get(C, ptr_icon, RNA_struct_ui_icon(ptr_icon->type), FALSE);
+}
+
+static const char *rna_ui_get_enum_name(bContext *C, PointerRNA *ptr, const char *propname, const char *identifier)
+{
+	PropertyRNA *prop = NULL;
+	EnumPropertyItem *items = NULL, *item;
+	int free;
+	const char *name = "";
+
+	prop = RNA_struct_find_property(ptr, propname);
+	if (!prop || (RNA_property_type(prop) != PROP_ENUM)) {
+		RNA_warning("Property not found or not an enum: %s.%s", RNA_struct_identifier(ptr->type), propname);
+		return name;
+	}
+
+	RNA_property_enum_items_gettexted(C, ptr, prop, &items, NULL, &free);
+
+	if (items) {
+		for (item = items; item->identifier; item++) {
+			if (item->identifier[0] && strcmp(item->identifier, identifier) == 0) {
+				name = item->name;
+				break;
+			}
+		}
+		if (free) {
+			MEM_freeN(items);
+		}
+	}
+
+	return name;
+}
+
+static const char *rna_ui_get_enum_description(bContext *C, PointerRNA *ptr, const char *propname,
+                                               const char *identifier)
+{
+	PropertyRNA *prop = NULL;
+	EnumPropertyItem *items = NULL, *item;
+	int free;
+	const char *desc = "";
+
+	prop = RNA_struct_find_property(ptr, propname);
+	if (!prop || (RNA_property_type(prop) != PROP_ENUM)) {
+		RNA_warning("Property not found or not an enum: %s.%s", RNA_struct_identifier(ptr->type), propname);
+		return desc;
+	}
+
+	RNA_property_enum_items_gettexted(C, ptr, prop, &items, NULL, &free);
+
+	if (items) {
+		for (item = items; item->identifier; item++) {
+			if (item->identifier[0] && strcmp(item->identifier, identifier) == 0) {
+				desc = item->description;
+				break;
+			}
+		}
+		if (free) {
+			MEM_freeN(items);
+		}
+	}
+
+	return desc;
+}
+
+static int rna_ui_get_enum_icon(bContext *C, PointerRNA *ptr, const char *propname, const char *identifier)
+{
+	PropertyRNA *prop = NULL;
+	EnumPropertyItem *items = NULL, *item;
+	int free;
+	int icon = ICON_NONE;
+
+	prop = RNA_struct_find_property(ptr, propname);
+	if (!prop || (RNA_property_type(prop) != PROP_ENUM)) {
+		RNA_warning("Property not found or not an enum: %s.%s", RNA_struct_identifier(ptr->type), propname);
+		return icon;
+	}
+
+	RNA_property_enum_items(C, ptr, prop, &items, NULL, &free);
+
+	if (items) {
+		for (item = items; item->identifier; item++) {
+			if (item->identifier[0] && strcmp(item->identifier, identifier) == 0) {
+				icon = item->icon;
+				break;
+			}
+		}
+		if (free) {
+			MEM_freeN(items);
+		}
+	}
+
+	return icon;
+}
+
 #else
 
 #define DEF_ICON_BLANK_SKIP
 #define DEF_ICON(name) {ICON_##name, (#name), 0, (#name), ""},
 #define DEF_VICO(name) {VICO_##name, (#name), 0, (#name), ""},
-static EnumPropertyItem icon_items[] = {
+EnumPropertyItem icon_items[] = {
 #include "UI_icons.h"
 	{0, NULL, 0, NULL, NULL}
 };
@@ -92,7 +201,6 @@ static void api_ui_item_common(FunctionRNA *func)
 	prop = RNA_def_property(func, "icon", PROP_ENUM, PROP_NONE);
 	RNA_def_property_enum_items(prop, icon_items);
 	RNA_def_property_ui_text(prop, "Icon", "Override automatic icon of the item");
-
 }
 
 static void api_ui_item_op(FunctionRNA *func)
@@ -130,13 +238,6 @@ void RNA_api_ui_layout(StructRNA *srna)
 		{'h', "HUE", 0, "Hue", ""},
 		{0, NULL, 0, NULL, NULL}
 	};
-	
-	static EnumPropertyItem list_type_items[] = {
-		{0, "DEFAULT", 0, "None", ""},
-		{'c', "COMPACT", 0, "Compact", ""},
-		{'i', "ICONS", 0, "Icons", ""},
-		{0, NULL, 0, NULL, NULL}
-	};
 
 	/* simple layout specifiers */
 	func = RNA_def_function(srna, "row", "uiLayoutRow");
@@ -175,6 +276,44 @@ void RNA_api_ui_layout(StructRNA *srna)
 	RNA_def_float(func, "percentage", 0.0f, 0.0f, 1.0f, "Percentage", "Percentage of width to split at", 0.0f, 1.0f);
 	RNA_def_boolean(func, "align", 0, "", "Align buttons to each other");
 
+	/* Icon of a rna pointer */
+	func = RNA_def_function(srna, "icon", "rna_ui_get_rnaptr_icon");
+	parm = RNA_def_int(func, "icon_value", ICON_NONE, 0, INT_MAX, "", "Icon identifier", 0, INT_MAX);
+	RNA_def_function_return(func, parm);
+	RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT);
+	parm = RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take the icon");
+	RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL);
+	RNA_def_function_ui_description(func, "Return the custom icon for this data, "
+	                                      "use it e.g. to get materials or texture icons");
+
+	/* UI name, description and icon of an enum item */
+	func = RNA_def_function(srna, "enum_item_name", "rna_ui_get_enum_name");
+	parm = RNA_def_string(func, "name", "", 0, "", "UI name of the enum item");
+	RNA_def_function_return(func, parm);
+	RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT);
+	api_ui_item_rna_common(func);
+	parm = RNA_def_string(func, "identifier", "", 0, "", "Identifier of the enum item");
+	RNA_def_property_flag(parm, PROP_REQUIRED);
+	RNA_def_function_ui_description(func, "Return the UI name for this enum item");
+
+	func = RNA_def_function(srna, "enum_item_description", "rna_ui_get_enum_description");
+	parm = RNA_def_string(func, "description", "", 0, "", "UI description of the enum item");
+	RNA_def_function_return(func, parm);
+	RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT);
+	api_ui_item_rna_common(func);
+	parm = RNA_def_string(func, "identifier", "", 0, "", "Identifier of the enum item");
+	RNA_def_property_flag(parm, PROP_REQUIRED);
+	RNA_def_function_ui_description(func, "Return the UI description for this enum item");
+
+	func = RNA_def_function(srna, "enum_item_icon", "rna_ui_get_enum_icon");
+	parm = RNA_def_int(func, "icon_value", ICON_NONE, 0, INT_MAX, "", "Icon identifier", 0, INT_MAX);
+	RNA_def_function_return(func, parm);
+	RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT);
+	api_ui_item_rna_common(func);
+	parm = RNA_def_string(func, "identifier", "", 0, "", "Identifier of the enum item");
+	RNA_def_property_flag(parm, PROP_REQUIRED);
+	RNA_def_function_ui_description(func, "Return the icon for this enum item");
+
 	/* items */
 	func = RNA_def_function(srna, "prop", "rna_uiItemR");
 	RNA_def_function_ui_description(func, "Item. Exposes an RNA item and places it into the layout");
@@ -274,9 +413,13 @@ void RNA_api_ui_layout(StructRNA *srna)
 	RNA_def_property_flag(parm, PROP_REQUIRED);
 #endif
 
-	func = RNA_def_function(srna, "label", "uiItemL");
-	RNA_def_function_ui_description(func, "Item. Display text in the layout");
+	func = RNA_def_function(srna, "label", "rna_uiItemL");
+	RNA_def_function_ui_description(func, "Item. Display text and/or icon in the layout");
 	api_ui_item_common(func);
+	parm = RNA_def_property(func, "icon_value", PROP_INT, PROP_UNSIGNED);
+	RNA_def_property_ui_text(parm, "Icon Value",
+	                         "Override automatic icon of the item "
+	                         "(use it e.g. with custom material icons returned by icon()...)");
 
 	func = RNA_def_function(srna, "menu", "uiItemM");
 	RNA_def_function_flag(func, FUNC_USE_CONTEXT);
@@ -439,26 +582,29 @@ void RNA_api_ui_layout(StructRNA *srna)
 	RNA_def_boolean(func, "compact", 0, "", "Use more compact layout");
 
 	func = RNA_def_function(srna, "template_list", "uiTemplateList");
-	RNA_def_function_ui_description(func, "Item. A list widget to display data, e.g. vertexgroups "
-	                                      "(WARNING: only one per panel allowed!).");
+	RNA_def_function_ui_description(func, "Item. A list widget to display data, e.g. vertexgroups.");
 	RNA_def_function_flag(func, FUNC_USE_CONTEXT);
-	parm = RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take property");
+	parm = RNA_def_string(func, "listtype_name", "", 0, "", "Identifier of the list type to use");
+	RNA_def_property_flag(parm, PROP_REQUIRED);
+	parm = RNA_def_string(func, "list_id", "", 0, "",
+	                      "Identifier of this list widget. "
+	                      "If this is set, the uilist gets a custom ID, otherwise it takes the "
+	                      "name of the class used to define the uilist (for example, if the "
+	                      "class name is \"OBJECT_UL_vgroups\", and list_id is not set by the "
+	                      "script, then bl_idname = \"OBJECT_UL_vgroups\")");
+	parm = RNA_def_pointer(func, "dataptr", "AnyType", "", "Data from which to take the Collection property");
 	RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR);
-	parm = RNA_def_string(func, "property", "", 0, "", "Identifier of property in data");
+	parm = RNA_def_string(func, "propname", "", 0, "", "Identifier of the Collection property in data");
 	RNA_def_property_flag(parm, PROP_REQUIRED);
-	parm = RNA_def_pointer(func, "active_data", "AnyType", "",
-	                       "Data from which to take property for the active element");
+	parm = RNA_def_pointer(func, "active_dataptr", "AnyType", "",
+	                       "Data from which to take the integer property, index of the active item");
 	RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL);
-	parm = RNA_def_string(func, "active_property", "", 0, "",
-	                      "Identifier of property in data, for the active element");
+	parm = RNA_def_string(func, "active_propname", "", 0, "",
+	                      "Identifier of the integer property in active_data, index of the active item");
 	RNA_def_property_flag(parm, PROP_REQUIRED);
-	RNA_def_string(func, "prop_list", "", 0, "",
-	               "Identifier of a string property in each data member, specifying which "
-	               "of its properties should have a widget displayed in its row "
-	               "(format: \"propname1:propname2:propname3:...\")");
 	RNA_def_int(func, "rows", 5, 0, INT_MAX, "", "Number of rows to display", 0, INT_MAX);
 	RNA_def_int(func, "maxrows", 5, 0, INT_MAX, "", "Maximum number of rows to display", 0, INT_MAX);
-	RNA_def_enum(func, "type", list_type_items, 0, "Type", "Type of list to use");
+	RNA_def_enum(func, "type", uilist_layout_type_items, UILST_LAYOUT_DEFAULT, "Type", "Type of layout to use");
 
 	func = RNA_def_function(srna, "template_running_jobs", "uiTemplateRunningJobs");
 	RNA_def_function_flag(func, FUNC_USE_CONTEXT);
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 2de477c46c3..bc245ecda5c 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -7373,8 +7373,9 @@ PyDoc_STRVAR(pyrna_register_class_doc,
 ".. method:: register_class(cls)\n"
 "\n"
 "   Register a subclass of a blender type in (:class:`bpy.types.Panel`,\n"
-"   :class:`bpy.types.Menu`, :class:`bpy.types.Header`, :class:`bpy.types.Operator`,\n"
-"   :class:`bpy.types.KeyingSetInfo`, :class:`bpy.types.RenderEngine`).\n"
+"   :class:`bpy.types.UIList`, :class:`bpy.types.Menu`, :class:`bpy.types.Header`,\n"
+"   :class:`bpy.types.Operator`, :class:`bpy.types.KeyingSetInfo`,\n"
+"   :class:`bpy.types.RenderEngine`).\n"
 "\n"
 "   If the class has a *register* class method it will be called\n"
 "   before registration.\n"
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index c418b07401d..eee4b5a3a57 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -265,6 +265,13 @@ char		*WM_prop_pystring_assign(struct bContext *C, struct PointerRNA *ptr, struc
 void		WM_operator_bl_idname(char *to, const char *from);
 void		WM_operator_py_idname(char *to, const char *from);
 
+/* *************** uilist types ******************** */
+void                WM_uilisttype_init(void);
+struct uiListType  *WM_uilisttype_find(const char *idname, int quiet);
+int                 WM_uilisttype_add(struct uiListType *ult);
+void                WM_uilisttype_freelink(struct uiListType *ult);
+void                WM_uilisttype_free(void);
+
 /* *************** menu types ******************** */
 void                WM_menutype_init(void);
 struct MenuType    *WM_menutype_find(const char *idname, int quiet);
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index 8fe387765ce..53e67e91bd2 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -149,7 +149,63 @@ void WM_operator_stack_clear(wmWindowManager *wm)
 	WM_main_add_notifier(NC_WM | ND_HISTORY, NULL);
 }
 
-/* ****************************************** */
+
+/* ************ uiListType handling ************** */
+
+static GHash *uilisttypes_hash = NULL;
+
+uiListType *WM_uilisttype_find(const char *idname, int quiet)
+{
+	uiListType *ult;
+
+	if (idname[0]) {
+		ult = BLI_ghash_lookup(uilisttypes_hash, idname);
+		if (ult) {
+			return ult;
+		}
+	}
+
+	if (!quiet) {
+		printf("search for unknown uilisttype %s\n", idname);
+	}
+
+	return NULL;
+}
+
+int WM_uilisttype_add(uiListType *ult)
+{
+	BLI_ghash_insert(uilisttypes_hash, (void *)ult->idname, ult);
+	return 1;
+}
+
+void WM_uilisttype_freelink(uiListType *ult)
+{
+	BLI_ghash_remove(uilisttypes_hash, ult->idname, NULL, (GHashValFreeFP)MEM_freeN);
+}
+
+/* called on initialize WM_init() */
+void WM_uilisttype_init(void)
+{
+	uilisttypes_hash = BLI_ghash_str_new("uilisttypes_hash gh");
+}
+
+void WM_uilisttype_free(void)
+{
+	GHashIterator *iter = BLI_ghashIterator_new(uilisttypes_hash);
+
+	for (; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) {
+		uiListType *ult = BLI_ghashIterator_getValue(iter);
+		if (ult->ext.free) {
+			ult->ext.free(ult->ext.data);
+		}
+	}
+	BLI_ghashIterator_free(iter);
+
+	BLI_ghash_free(uilisttypes_hash, NULL, (GHashValFreeFP)MEM_freeN);
+	uilisttypes_hash = NULL;
+}
+
+/* ************ MenuType handling ************** */
 
 static GHash *menutypes_hash = NULL;
 
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 3cffa143ebc..aae44f51f18 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -137,6 +137,7 @@ void WM_init(bContext *C, int argc, const char **argv)
 	GHOST_CreateSystemPaths();
 	wm_operatortype_init();
 	WM_menutype_init();
+	WM_uilisttype_init();
 
 	set_free_windowmanager_cb(wm_close_and_free);   /* library.c */
 	set_blender_test_break_cb(wm_window_testbreak); /* blender.c */
@@ -403,6 +404,7 @@ void WM_exit_ext(bContext *C, const short do_python)
 	wm_operatortype_free();
 	wm_dropbox_free();
 	WM_menutype_free();
+	WM_uilisttype_free();
 	
 	/* all non-screen and non-space stuff editors did, like editmode */
 	if (C)
diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index 2b29129c0f7..4b8b7460f00 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -414,7 +414,9 @@ void uiTemplateCurveMapping(struct uiLayout *layout, struct CurveMapping *cumap,
 void uiTemplateColorRamp(struct uiLayout *layout, struct ColorBand *coba, int expand) {}
 void uiTemplateLayers(struct uiLayout *layout, struct PointerRNA *ptr, char *propname) {}
 void uiTemplateImageLayers(struct uiLayout *layout, struct bContext *C, struct Image *ima, struct ImageUser *iuser) {}
-ListBase uiTemplateList(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname, struct PointerRNA *activeptr, char *activepropname, int rows, int listtype) {struct ListBase b = {0,0}; return b;}
+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, int rows, int maxrows, int layout_type) {}
 void uiTemplateRunningJobs(struct uiLayout *layout, struct bContext *C) {}
 void uiTemplateOperatorSearch(struct uiLayout *layout) {}
 void uiTemplateHeader3D(struct uiLayout *layout, struct bContext *C) {}
-- 
cgit v1.2.3


From 67b76a70bce8331c8c65bdd4c493011b320e380a Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Fri, 28 Dec 2012 09:48:35 +0000
Subject: The new feature printing changed properties in python history list
 didn't free a list of context properties. Give lots of leaked small blocks...

---
 source/blender/blenkernel/intern/context.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index 7009f1235c9..44687d5925c 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -371,8 +371,10 @@ PointerRNA CTX_data_pointer_get(const bContext *C, const char *member)
 {
 	bContextDataResult result;
 
-	if (ctx_data_get((bContext *)C, member, &result) == 1)
+	if (ctx_data_get((bContext *)C, member, &result) == 1) {
+		BLI_freelistN(&result.list);
 		return result.ptr;
+	}
 	else
 		return PointerRNA_NULL;
 }
-- 
cgit v1.2.3


From 08fbc48ee56f5ff9ff7ba32401f22420434d718d Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Fri, 28 Dec 2012 10:08:17 +0000
Subject: revert r53356, this stopped the leak but still wasn't working nice.

Add asserts when CTX_data_pointer_get/CTX_data_collection_get are incorrectly used.

disable context inspection for now, Will enable again when its working properly.
---
 source/blender/blenkernel/intern/context.c         | 18 +++++++++++++-----
 source/blender/windowmanager/intern/wm_operators.c |  2 +-
 2 files changed, 14 insertions(+), 6 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index 44687d5925c..a45afa5e69a 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -29,6 +29,7 @@
 
 
 #include 
+#include 
 #include 
 
 #include "MEM_guardedalloc.h"
@@ -327,10 +328,13 @@ static void *ctx_data_pointer_get(const bContext *C, const char *member)
 {
 	bContextDataResult result;
 
-	if (C && ctx_data_get((bContext *)C, member, &result) == 1)
+	if (C && ctx_data_get((bContext *)C, member, &result) == 1) {
+		BLI_assert(result.type == CTX_DATA_TYPE_POINTER);
 		return result.ptr.data;
-
-	return NULL;
+	}
+	else {
+		return NULL;
+	}
 }
 
 static int ctx_data_pointer_verify(const bContext *C, const char *member, void **pointer)
@@ -343,6 +347,7 @@ static int ctx_data_pointer_verify(const bContext *C, const char *member, void *
 		return 1;
 	}
 	else if (ctx_data_get((bContext *)C, member, &result) == 1) {
+		BLI_assert(result.type == CTX_DATA_TYPE_POINTER);
 		*pointer = result.ptr.data;
 		return 1;
 	}
@@ -357,6 +362,7 @@ static int ctx_data_collection_get(const bContext *C, const char *member, ListBa
 	bContextDataResult result;
 
 	if (ctx_data_get((bContext *)C, member, &result) == 1) {
+		BLI_assert(result.type == CTX_DATA_TYPE_COLLECTION);
 		*list = result.list;
 		return 1;
 	}
@@ -372,11 +378,12 @@ PointerRNA CTX_data_pointer_get(const bContext *C, const char *member)
 	bContextDataResult result;
 
 	if (ctx_data_get((bContext *)C, member, &result) == 1) {
-		BLI_freelistN(&result.list);
+		BLI_assert(result.type == CTX_DATA_TYPE_POINTER);
 		return result.ptr;
 	}
-	else
+	else {
 		return PointerRNA_NULL;
+	}
 }
 
 PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type)
@@ -401,6 +408,7 @@ ListBase CTX_data_collection_get(const bContext *C, const char *member)
 	bContextDataResult result;
 
 	if (ctx_data_get((bContext *)C, member, &result) == 1) {
+		BLI_assert(result.type == CTX_DATA_TYPE_COLLECTION);
 		return result.list;
 	}
 	else {
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 8867101779a..39164995cc5 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -583,7 +583,7 @@ static char *wm_prop_pystring_from_context(bContext *C, PointerRNA *ptr, Propert
 
 	for (link = lb.first; link; link = link->next) {
 		const char *identifier = link->data;
-		PointerRNA ctx_item_ptr = CTX_data_pointer_get(C, identifier);
+		PointerRNA ctx_item_ptr = {{0}}; // CTX_data_pointer_get(C, identifier);
 
 		if (ctx_item_ptr.type == NULL) {
 			continue;
-- 
cgit v1.2.3


From 37760c0ad0a8f86362b3af9bacba620fd888df6c Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Fri, 28 Dec 2012 10:23:06 +0000
Subject: fix for memory leaks in own recent changes.

---
 source/blender/makesrna/intern/rna_access.c | 6 ++++++
 1 file changed, 6 insertions(+)

(limited to 'source')

diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index caa53a23d77..641507a4136 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -4204,6 +4204,8 @@ char *RNA_path_full_struct_py(struct PointerRNA *ptr)
 	ret = BLI_sprintfN("%s.%s",
 	                   id_path, data_path);
 
+	MEM_freeN(data_path);
+
 	return ret;
 }
 
@@ -4235,6 +4237,8 @@ char *RNA_path_full_property_py(PointerRNA *ptr, PropertyRNA *prop, int index)
 		ret = BLI_sprintfN("%s.%s[%d]",
 		                   id_path, data_path, index);
 	}
+	MEM_freeN(id_path);
+	MEM_freeN(data_path);
 
 	return ret;
 }
@@ -4264,6 +4268,8 @@ char *RNA_path_struct_property_py(PointerRNA *ptr, PropertyRNA *prop, int index)
 		                   data_path, index);
 	}
 
+	MEM_freeN(data_path);
+
 	return ret;
 }
 
-- 
cgit v1.2.3


From 8c00c57187bcba069231e49e096a1982c330528a Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Fri, 28 Dec 2012 10:32:49 +0000
Subject: style cleanup: var naming for ui list

---
 source/blender/blenloader/intern/readfile.c        |  8 +--
 source/blender/blenloader/intern/writefile.c       |  6 +-
 source/blender/editors/include/UI_interface.h      |  2 +-
 .../blender/editors/interface/interface_handlers.c | 30 +++++-----
 .../blender/editors/interface/interface_layout.c   |  4 +-
 .../editors/interface/interface_templates.c        | 68 +++++++++++-----------
 source/blender/makesdna/DNA_screen_types.h         |  2 +-
 source/blender/makesrna/intern/rna_ui.c            | 22 +++----
 8 files changed, 71 insertions(+), 71 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 520e4fd2c39..458b6424799 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -5832,7 +5832,7 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
 static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
 {
 	Panel *pa;
-	uiList *uilst;
+	uiList *ui_list;
 
 	link_list(fd, &ar->panels);
 
@@ -5843,10 +5843,10 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
 		pa->type = NULL;
 	}
 
-	link_list(fd, &ar->uiLists);
+	link_list(fd, &ar->ui_lists);
 
-	for (uilst = ar->uiLists.first; uilst; uilst = uilst->next) {
-		uilst->type = NULL;
+	for (ui_list = ar->ui_lists.first; ui_list; ui_list = ui_list->next) {
+		ui_list->type = NULL;
 	}
 
 	ar->regiondata = newdataadr(fd, ar->regiondata);
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 1b28504700b..b1dce046438 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -2395,7 +2395,7 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
 		for (sa= sc->areabase.first; sa; sa= sa->next) {
 			SpaceLink *sl;
 			Panel *pa;
-			uiList *uilst;
+			uiList *ui_list;
 			ARegion *ar;
 			
 			writestruct(wd, DATA, "ScrArea", 1, sa);
@@ -2406,8 +2406,8 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
 				for (pa= ar->panels.first; pa; pa= pa->next)
 					writestruct(wd, DATA, "Panel", 1, pa);
 				
-				for (uilst = ar->uiLists.first; uilst; uilst = uilst->next)
-					writestruct(wd, DATA, "uiList", 1, uilst);
+				for (ui_list = ar->ui_lists.first; ui_list; ui_list = ui_list->next)
+					writestruct(wd, DATA, "uiList", 1, ui_list);
 			}
 			
 			sl= sa->spacedata.first;
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 281d80a9d2b..080367c4325 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -780,7 +780,7 @@ uiLayout *uiLayoutRow(uiLayout *layout, int align);
 uiLayout *uiLayoutColumn(uiLayout *layout, int align);
 uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, int align);
 uiLayout *uiLayoutBox(uiLayout *layout);
-uiLayout *uiLayoutListBox(uiLayout *layout, struct uiList *uilst, struct PointerRNA *ptr, struct PropertyRNA *prop,
+uiLayout *uiLayoutListBox(uiLayout *layout, struct uiList *ui_list, struct PointerRNA *ptr, struct PropertyRNA *prop,
                           struct PointerRNA *actptr, struct PropertyRNA *actprop);
 uiLayout *uiLayoutAbsolute(uiLayout *layout, int align);
 uiLayout *uiLayoutSplit(uiLayout *layout, float percentage, int align);
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index ee6916822f0..8df47f033c4 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -6095,9 +6095,9 @@ static int ui_handle_list_event(bContext *C, wmEvent *event, ARegion *ar)
 	int value, min, max;
 
 	if (but && (event->val == KM_PRESS)) {
-		uiList *uilst = but->custom_data;
+		uiList *ui_list = but->custom_data;
 
-		if (uilst) {
+		if (ui_list) {
 			if (ELEM(event->type, UPARROWKEY, DOWNARROWKEY) ||
 				((ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->alt)))
 			{
@@ -6109,12 +6109,12 @@ static int ui_handle_list_event(bContext *C, wmEvent *event, ARegion *ar)
 				else
 					value++;
 
-				CLAMP(value, 0, uilst->list_last_len - 1);
+				CLAMP(value, 0, ui_list->list_last_len - 1);
 
-				if (value < uilst->list_scroll)
-					uilst->list_scroll = value;
-				else if (value >= uilst->list_scroll + uilst->list_size)
-					uilst->list_scroll = value - uilst->list_size + 1;
+				if (value < ui_list->list_scroll)
+					ui_list->list_scroll = value;
+				else if (value >= ui_list->list_scroll + ui_list->list_size)
+					ui_list->list_scroll = value - ui_list->list_size + 1;
 
 				RNA_property_int_range(&but->rnapoin, but->rnaprop, &min, &max);
 				value = CLAMPIS(value, min, max);
@@ -6127,27 +6127,27 @@ static int ui_handle_list_event(bContext *C, wmEvent *event, ARegion *ar)
 			}
 			else if (ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->shift) {
 				/* silly replacement for proper grip */
-				if (uilst->list_grip_size == 0)
-					uilst->list_grip_size = uilst->list_size;
+				if (ui_list->list_grip_size == 0)
+					ui_list->list_grip_size = ui_list->list_size;
 
 				if (event->type == WHEELUPMOUSE)
-					uilst->list_grip_size--;
+					ui_list->list_grip_size--;
 				else
-					uilst->list_grip_size++;
+					ui_list->list_grip_size++;
 
-				uilst->list_grip_size = MAX2(uilst->list_grip_size, 1);
+				ui_list->list_grip_size = MAX2(ui_list->list_grip_size, 1);
 
 				ED_region_tag_redraw(ar);
 
 				retval = WM_UI_HANDLER_BREAK;
 			}
 			else if (ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
-				if (uilst->list_last_len > uilst->list_size) {
+				if (ui_list->list_last_len > ui_list->list_size) {
 					/* list template will clamp */
 					if (event->type == WHEELUPMOUSE)
-						uilst->list_scroll--;
+						ui_list->list_scroll--;
 					else
-						uilst->list_scroll++;
+						ui_list->list_scroll++;
 
 					ED_region_tag_redraw(ar);
 
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 19b44422ac0..f4af1f036a3 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -2308,13 +2308,13 @@ uiLayout *uiLayoutBox(uiLayout *layout)
 	return (uiLayout *)ui_layout_box(layout, ROUNDBOX);
 }
 
-uiLayout *uiLayoutListBox(uiLayout *layout, uiList *uilist, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *actptr,
+uiLayout *uiLayoutListBox(uiLayout *layout, uiList *ui_list, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *actptr,
                           PropertyRNA *actprop)
 {
 	uiLayoutItemBx *box = ui_layout_box(layout, LISTBOX);
 	uiBut *but = box->roundbox;
 
-	but->custom_data = uilist;
+	but->custom_data = ui_list;
 
 	but->rnasearchpoin = *ptr;
 	but->rnasearchprop = prop;
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 34f325abe76..a190f3dbacb 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -2328,7 +2328,7 @@ void uiTemplateGameStates(uiLayout *layout, PointerRNA *ptr, const char *propnam
 
 
 /************************* List Template **************************/
-static void uilist_draw_item_default(struct uiList *uilst, struct bContext *UNUSED(C), struct uiLayout *layout,
+static void uilist_draw_item_default(struct uiList *ui_list, struct bContext *UNUSED(C), struct uiLayout *layout,
                                      struct PointerRNA *UNUSED(dataptr), struct PointerRNA *itemptr, int icon,
                                      struct PointerRNA *UNUSED(active_dataptr), const char *UNUSED(active_propname),
                                      int UNUSED(index))
@@ -2340,7 +2340,7 @@ static void uilist_draw_item_default(struct uiList *uilst, struct bContext *UNUS
 	name = (namebuf) ? namebuf : "";
 
 	/* Simplest one! */
-	switch (uilst->layout_type) {
+	switch (ui_list->layout_type) {
 	case UILST_LAYOUT_GRID:
 		uiItemL(layout, "", icon);
 		break;
@@ -2361,8 +2361,8 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
                     PointerRNA *dataptr, const char *propname, PointerRNA *active_dataptr,
                     const char *active_propname, int rows, int maxrows, int layout_type)
 {
-	uiListType *ult;
-	uiList *uilst = NULL;
+	uiListType *ui_list_type;
+	uiList *ui_list = NULL;
 	ARegion *ar;
 	uiListDrawItemFunc draw_item;
 
@@ -2373,7 +2373,7 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
 	uiBlock *block, *subblock;
 	uiBut *but;
 
-	char uilst_id[UI_MAX_NAME_STR];
+	char ui_list_id[UI_MAX_NAME_STR];
 	char numstr[32];
 	int rnaicon = ICON_NONE, icon = ICON_NONE;
 	int i = 0, activei = 0;
@@ -2428,31 +2428,31 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
 	activei = RNA_property_int_get(active_dataptr, activeprop);
 
 	/* Find the uiList type. */
-	ult = WM_uilisttype_find(listtype_name, FALSE);
+	ui_list_type = WM_uilisttype_find(listtype_name, FALSE);
 
-	if (ult == NULL) {
+	if (ui_list_type == NULL) {
 		RNA_warning("List type %s not found", listtype_name);
 		return;
 	}
 
-	draw_item = ult->draw_item ? ult->draw_item : uilist_draw_item_default;
+	draw_item = ui_list_type->draw_item ? ui_list_type->draw_item : uilist_draw_item_default;
 
 	/* Find or add the uiList to the current Region. */
 	/* We tag the list id with the list type... */
-	BLI_snprintf(uilst_id, sizeof(uilst_id), "%s_%s", ult->idname, list_id ? list_id : "");
+	BLI_snprintf(ui_list_id, sizeof(ui_list_id), "%s_%s", ui_list_type->idname, list_id ? list_id : "");
 
 	ar = CTX_wm_region(C);
-	uilst = BLI_findstring(&ar->uiLists, uilst_id, offsetof(uiList, list_id));
+	ui_list = BLI_findstring(&ar->ui_lists, ui_list_id, offsetof(uiList, list_id));
 
-	if (!uilst) {
-		uilst = MEM_callocN(sizeof(uiList), __func__);
-		BLI_strncpy(uilst->list_id, uilst_id, sizeof(uilst->list_id));
-		BLI_addtail(&ar->uiLists, uilst);
+	if (!ui_list) {
+		ui_list = MEM_callocN(sizeof(uiList), __func__);
+		BLI_strncpy(ui_list->list_id, ui_list_id, sizeof(ui_list->list_id));
+		BLI_addtail(&ar->ui_lists, ui_list);
 	}
 
 	/* Because we can't actually pass type across save&load... */
-	uilst->type = ult;
-	uilst->layout_type = layout_type;
+	ui_list->type = ui_list_type;
+	ui_list->layout_type = layout_type;
 
 	switch (layout_type) {
 	case UILST_LAYOUT_DEFAULT:
@@ -2461,11 +2461,11 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
 			rows = 5;
 		if (maxrows == 0)
 			maxrows = 5;
-		if (uilst->list_grip_size != 0)
-			rows = uilst->list_grip_size;
+		if (ui_list->list_grip_size != 0)
+			rows = ui_list->list_grip_size;
 
 		/* layout */
-		box = uiLayoutListBox(layout, uilst, dataptr, prop, active_dataptr, activeprop);
+		box = uiLayoutListBox(layout, ui_list, dataptr, prop, active_dataptr, activeprop);
 		row = uiLayoutRow(box, FALSE);
 		col = uiLayoutColumn(row, TRUE);
 
@@ -2477,21 +2477,21 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
 		items = CLAMPIS(len, rows, MAX2(rows, maxrows));
 
 		/* if list length changes and active is out of view, scroll to it */
-		if ((uilst->list_last_len != len) &&
-		    (activei < uilst->list_scroll || activei >= uilst->list_scroll + items)) {
-			uilst->list_scroll = activei;
+		if ((ui_list->list_last_len != len) &&
+		    (activei < ui_list->list_scroll || activei >= ui_list->list_scroll + items)) {
+			ui_list->list_scroll = activei;
 		}
 
-		uilst->list_scroll = MIN2(uilst->list_scroll, len - items);
-		uilst->list_scroll = MAX2(uilst->list_scroll, 0);
-		uilst->list_size = items;
-		uilst->list_last_len = len;
+		ui_list->list_scroll = min_ii(ui_list->list_scroll, len - items);
+		ui_list->list_scroll = max_ii(ui_list->list_scroll, 0);
+		ui_list->list_size = items;
+		ui_list->list_last_len = len;
 
 		if (dataptr->data && prop) {
 			/* create list items */
 			RNA_PROP_BEGIN (dataptr, itemptr, prop)
 			{
-				if (i >= uilst->list_scroll && i < uilst->list_scroll + items) {
+				if (i >= ui_list->list_scroll && i < ui_list->list_scroll + items) {
 					subblock = uiLayoutGetBlock(col);
 					overlap = uiLayoutOverlap(col);
 
@@ -2507,7 +2507,7 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
 					icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, FALSE);
 					if (icon == ICON_DOT)
 						icon = ICON_NONE;
-					draw_item(uilst, C, sub, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
+					draw_item(ui_list, C, sub, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
 				}
 				i++;
 			}
@@ -2515,8 +2515,8 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
 		}
 
 		/* add dummy buttons to fill space */
-		while (i < uilst->list_scroll + items) {
-			if (i >= uilst->list_scroll)
+		while (i < ui_list->list_scroll + items) {
+			if (i >= ui_list->list_scroll)
 				uiItemL(col, "", ICON_NONE);
 			i++;
 		}
@@ -2524,7 +2524,7 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
 		/* add scrollbar */
 		if (len > items) {
 			col = uiLayoutColumn(row, FALSE);
-			uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * items, &uilst->list_scroll,
+			uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * items, &ui_list->list_scroll,
 			          0, len - items, items, 0, "");
 		}
 		break;
@@ -2541,7 +2541,7 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
 					icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, FALSE);
 					if (icon == ICON_DOT)
 						icon = ICON_NONE;
-					draw_item(uilst, C, row, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
+					draw_item(ui_list, C, row, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
 				}
 
 				i++;
@@ -2561,7 +2561,7 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
 			uiButSetFlag(but, UI_BUT_DISABLED);
 		break;
 	case UILST_LAYOUT_GRID:
-		box = uiLayoutListBox(layout, uilst, dataptr, prop, active_dataptr, activeprop);
+		box = uiLayoutListBox(layout, ui_list, dataptr, prop, active_dataptr, activeprop);
 		col = uiLayoutColumn(box, TRUE);
 		row = uiLayoutRow(col, FALSE);
 
@@ -2586,7 +2586,7 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
 				sub = uiLayoutRow(overlap, FALSE);
 
 				icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, FALSE);
-				draw_item(uilst, C, sub, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
+				draw_item(ui_list, C, sub, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
 
 				i++;
 			}
diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h
index 5d8176c8021..d6100dcdbce 100644
--- a/source/blender/makesdna/DNA_screen_types.h
+++ b/source/blender/makesdna/DNA_screen_types.h
@@ -181,7 +181,7 @@ typedef struct ARegion {
 	
 	ListBase uiblocks;			/* uiBlock */
 	ListBase panels;			/* Panel */
-	ListBase uiLists;			/* uiList */
+	ListBase ui_lists;			/* uiList */
 	ListBase handlers;			/* wmEventHandler */
 	
 	struct wmTimer *regiontimer; /* blend in/out */
diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c
index e6e953c412b..14789a437b7 100644
--- a/source/blender/makesrna/intern/rna_ui.c
+++ b/source/blender/makesrna/intern/rna_ui.c
@@ -263,19 +263,19 @@ static StructRNA *rna_Panel_refine(PointerRNA *ptr)
 }
 
 /* UIList */
-static void uilist_draw_item(uiList *uilst, bContext *C, uiLayout *layout, PointerRNA *dataptr, PointerRNA *itemptr,
+static void uilist_draw_item(uiList *ui_list, bContext *C, uiLayout *layout, PointerRNA *dataptr, PointerRNA *itemptr,
                              int icon, PointerRNA *active_dataptr, const char *active_propname, int index)
 {
 	extern FunctionRNA rna_UIList_draw_item_func;
 
-	PointerRNA ultr;
+	PointerRNA ul_ptr;
 	ParameterList list;
 	FunctionRNA *func;
 
-	RNA_pointer_create(&CTX_wm_screen(C)->id, uilst->type->ext.srna, uilst, &ultr);
-	func = &rna_UIList_draw_item_func; /* RNA_struct_find_function(&ultr, "draw_item"); */
+	RNA_pointer_create(&CTX_wm_screen(C)->id, ui_list->type->ext.srna, ui_list, &ul_ptr);
+	func = &rna_UIList_draw_item_func; /* RNA_struct_find_function(&ul_ptr, "draw_item"); */
 
-	RNA_parameter_list_create(&list, &ultr, func);
+	RNA_parameter_list_create(&list, &ul_ptr, func);
 	RNA_parameter_set_lookup(&list, "context", &C);
 	RNA_parameter_set_lookup(&list, "layout", &layout);
 	RNA_parameter_set_lookup(&list, "data", dataptr);
@@ -284,7 +284,7 @@ static void uilist_draw_item(uiList *uilst, bContext *C, uiLayout *layout, Point
 	RNA_parameter_set_lookup(&list, "active_data", active_dataptr);
 	RNA_parameter_set_lookup(&list, "active_property", &active_propname);
 	RNA_parameter_set_lookup(&list, "index", &index);
-	uilst->type->ext.call((bContext *)C, &ultr, func, &list);
+	ui_list->type->ext.call((bContext *)C, &ul_ptr, func, &list);
 
 	RNA_parameter_list_free(&list);
 }
@@ -311,16 +311,16 @@ static StructRNA *rna_UIList_register(Main *bmain, ReportList *reports, void *da
 {
 	uiListType *ult, dummyult = {NULL};
 	uiList dummyuilist = {NULL};
-	PointerRNA dummyultr;
+	PointerRNA dummyul_ptr;
 	int have_function[1];
 	size_t over_alloc = 0; /* warning, if this becomes a bess, we better do another alloc */
 
 	/* setup dummy menu & menu type to store static properties in */
 	dummyuilist.type = &dummyult;
-	RNA_pointer_create(NULL, &RNA_UIList, &dummyuilist, &dummyultr);
+	RNA_pointer_create(NULL, &RNA_UIList, &dummyuilist, &dummyul_ptr);
 
 	/* validate the python class */
-	if (validate(&dummyultr, data, have_function) != 0)
+	if (validate(&dummyul_ptr, data, have_function) != 0)
 		return NULL;
 
 	if (strlen(identifier) >= sizeof(dummyult.idname)) {
@@ -357,8 +357,8 @@ static StructRNA *rna_UIList_register(Main *bmain, ReportList *reports, void *da
 
 static StructRNA *rna_UIList_refine(PointerRNA *ptr)
 {
-	uiList *uilst = (uiList *)ptr->data;
-	return (uilst->type && uilst->type->ext.srna) ? uilst->type->ext.srna : &RNA_UIList;
+	uiList *ui_list = (uiList *)ptr->data;
+	return (ui_list->type && ui_list->type->ext.srna) ? ui_list->type->ext.srna : &RNA_UIList;
 }
 
 /* Header */
-- 
cgit v1.2.3


From 6061ecca0baa0e67aa299ede7ecaf46bc833875c Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Fri, 28 Dec 2012 10:36:25 +0000
Subject: add missing free for ui lists

---
 source/blender/blenkernel/intern/screen.c | 1 +
 1 file changed, 1 insertion(+)

(limited to 'source')

diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index 56fddfdaa2b..81bcdc4b06e 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -279,6 +279,7 @@ void BKE_area_region_free(SpaceType *st, ARegion *ar)
 	}
 
 	BLI_freelistN(&ar->panels);
+	BLI_freelistN(&ar->ui_lists);
 }
 
 /* not area itself */
-- 
cgit v1.2.3


From 914b0aafa5693f5808f14522dcc57d9f2a695db0 Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Fri, 28 Dec 2012 10:38:07 +0000
Subject: Yesterday's memory free error fix in IMB_onehalf was wrong, it should
 be fixed in the icons code!

---
 source/blender/editors/interface/interface_icons.c | 8 +++++---
 source/blender/imbuf/intern/scaling.c              | 2 --
 2 files changed, 5 insertions(+), 5 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 31d1ad7a955..d146fe25187 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -575,9 +575,11 @@ static void init_internal_icons(void)
 				glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, b16buf->x, b16buf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, b16buf->rect);
 				
 				while (b16buf->x > 1) {
-					b16buf = IMB_onehalf(b16buf);
-					glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, b16buf->x, b16buf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, b16buf->rect);
+					ImBuf *nbuf = IMB_onehalf(b16buf);
+					glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, nbuf->x, nbuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, nbuf->rect);
 					level++;
+					IMB_freeImBuf(b16buf);
+					b16buf = nbuf;
 				}
 				
 				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
@@ -598,7 +600,7 @@ static void init_internal_icons(void)
 	else
 		icontype = ICON_TYPE_BUFFER;
 	
-	if (b16buf) {
+	if (b32buf) {
 		for (y = 0; y < ICON_GRID_ROWS; y++) {
 			for (x = 0; x < ICON_GRID_COLS; x++) {
 				def_internal_icon(b32buf, BIFICONID_FIRST + y * ICON_GRID_COLS + x,
diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c
index af51b4448aa..1e701b8d615 100644
--- a/source/blender/imbuf/intern/scaling.c
+++ b/source/blender/imbuf/intern/scaling.c
@@ -360,8 +360,6 @@ ImBuf *IMB_onehalf(struct ImBuf *ibuf1)
 	
 	imb_onehalf_no_alloc(ibuf2, ibuf1);
 	
-	IMB_freeImBuf(ibuf1);
-	
 	return (ibuf2);
 }
 
-- 
cgit v1.2.3


From 4e88bfca1bb75c4654a27ebd0725d911c568b07f Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Fri, 28 Dec 2012 11:12:46 +0000
Subject: fix [#33677] Lambda is un-settable for mesh.vertices_smooth_laplacian

lambda is python keyword.
---
 source/blender/bmesh/intern/bmesh_opdefines.c         |  2 +-
 source/blender/bmesh/operators/bmo_smooth_laplacian.c |  8 ++++----
 source/blender/editors/mesh/editmesh_tools.c          | 10 +++++-----
 source/blender/makesrna/intern/rna_access.c           |  8 ++++++--
 4 files changed, 16 insertions(+), 12 deletions(-)

(limited to 'source')

diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index 83ed51163b5..8461ec6fe08 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -128,7 +128,7 @@ static BMOpDefine bmo_smooth_laplacian_vert_def = {
 	"smooth_laplacian_vert",
 	/* slots_in */
 	{{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},    /* input vertices */
-	 {"lambda", BMO_OP_SLOT_FLT},           /* lambda param */
+	 {"lambda_factor", BMO_OP_SLOT_FLT},           /* lambda param */
 	 {"lambda_border", BMO_OP_SLOT_FLT},    /* lambda param in border */
 	 {"use_x", BMO_OP_SLOT_BOOL},           /* Smooth object along X axis */
 	 {"use_y", BMO_OP_SLOT_BOOL},           /* Smooth object along Y axis */
diff --git a/source/blender/bmesh/operators/bmo_smooth_laplacian.c b/source/blender/bmesh/operators/bmo_smooth_laplacian.c
index 4a367a8fd6f..ce584686757 100644
--- a/source/blender/bmesh/operators/bmo_smooth_laplacian.c
+++ b/source/blender/bmesh/operators/bmo_smooth_laplacian.c
@@ -538,7 +538,7 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op)
 	int i;
 	int m_vertex_id;
 	int usex, usey, usez, preserve_volume;
-	float lambda, lambda_border;
+	float lambda_factor, lambda_border;
 	float w;
 	BMOIter siter;
 	BMVert *v;
@@ -553,7 +553,7 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op)
 	memset_laplacian_system(sys, 0);
 
 	BM_mesh_elem_index_ensure(bm, BM_VERT);
-	lambda = BMO_slot_float_get(op->slots_in, "lambda");
+	lambda_factor = BMO_slot_float_get(op->slots_in, "lambda_factor");
 	lambda_border = BMO_slot_float_get(op->slots_in, "lambda_border");
 	sys->min_area = 0.00001f;
 	usex = BMO_slot_bool_get(op->slots_in, "use_x");
@@ -592,12 +592,12 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op)
 		i = m_vertex_id;
 		if (sys->zerola[i] == 0) {
 			w = sys->vweights[i] * sys->ring_areas[i];
-			sys->vweights[i] = (w == 0.0f) ? 0.0f : -lambda  / (4.0f * w);
+			sys->vweights[i] = (w == 0.0f) ? 0.0f : -lambda_factor  / (4.0f * w);
 			w = sys->vlengths[i];
 			sys->vlengths[i] = (w == 0.0f) ? 0.0f : -lambda_border  * 2.0f / w;
 
 			if (!vert_is_boundary(v)) {
-				nlMatrixAdd(i, i,  1.0f + lambda / (4.0f * sys->ring_areas[i]));
+				nlMatrixAdd(i, i,  1.0f + lambda_factor / (4.0f * sys->ring_areas[i]));
 			}
 			else {
 				nlMatrixAdd(i, i,  1.0f + lambda_border * 2.0f);
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 26f54dee52d..12475c61bca 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -1674,7 +1674,7 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op)
 	BMEditMesh *em = BMEdit_FromObject(obedit);
 	int usex = TRUE, usey = TRUE, usez = TRUE, preserve_volume = TRUE;
 	int i, repeat;
-	float lambda;
+	float lambda_factor;
 	float lambda_border;
 	BMIter fiter;
 	BMFace *f;
@@ -1695,7 +1695,7 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op)
 	}
 
 	repeat = RNA_int_get(op->ptr, "repeat");
-	lambda = RNA_float_get(op->ptr, "lambda");
+	lambda_factor = RNA_float_get(op->ptr, "lambda_factor");
 	lambda_border = RNA_float_get(op->ptr, "lambda_border");
 	usex = RNA_boolean_get(op->ptr, "use_x");
 	usey = RNA_boolean_get(op->ptr, "use_y");
@@ -1706,8 +1706,8 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op)
 	
 	for (i = 0; i < repeat; i++) {
 		if (!EDBM_op_callf(em, op,
-		                   "smooth_laplacian_vert verts=%hv lambda=%f lambda_border=%f use_x=%b use_y=%b use_z=%b preserve_volume=%b",
-		                   BM_ELEM_SELECT, lambda, lambda_border, usex, usey, usez, preserve_volume))
+		                   "smooth_laplacian_vert verts=%hv lambda_factor=%f lambda_border=%f use_x=%b use_y=%b use_z=%b preserve_volume=%b",
+		                   BM_ELEM_SELECT, lambda_factor, lambda_border, usex, usey, usez, preserve_volume))
 		{
 			return OPERATOR_CANCELLED;
 		}
@@ -1740,7 +1740,7 @@ void MESH_OT_vertices_smooth_laplacian(wmOperatorType *ot)
 
 	RNA_def_int(ot->srna, "repeat", 1, 1, 200,
 	            "Number of iterations to smooth the mesh", "", 1, 200);
-	RNA_def_float(ot->srna, "lambda", 0.00005f, 0.0000001f, 1000.0f,
+	RNA_def_float(ot->srna, "lambda_factor", 0.00005f, 0.0000001f, 1000.0f,
 	              "Lambda factor", "", 0.0000001f, 1000.0f);
 	RNA_def_float(ot->srna, "lambda_border", 0.00005f, 0.0000001f, 1000.0f,
 	              "Lambda factor in border", "", 0.0000001f, 1000.0f);
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index 641507a4136..0048e1c60c2 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -4238,7 +4238,9 @@ char *RNA_path_full_property_py(PointerRNA *ptr, PropertyRNA *prop, int index)
 		                   id_path, data_path, index);
 	}
 	MEM_freeN(id_path);
-	MEM_freeN(data_path);
+	if (data_path) {
+		MEM_freeN(data_path);
+	}
 
 	return ret;
 }
@@ -4268,7 +4270,9 @@ char *RNA_path_struct_property_py(PointerRNA *ptr, PropertyRNA *prop, int index)
 		                   data_path, index);
 	}
 
-	MEM_freeN(data_path);
+	if (data_path) {
+		MEM_freeN(data_path);
+	}
 
 	return ret;
 }
-- 
cgit v1.2.3


From 6522aba6151949785d64aa36aac637153399eef1 Mon Sep 17 00:00:00 2001
From: Antony Riakiotakis 
Date: Fri, 28 Dec 2012 11:19:33 +0000
Subject: Fix blenderplayer compilation.

---
 source/blenderplayer/bad_level_call_stubs/stubs.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index 4b8b7460f00..576c0f341b1 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -203,6 +203,12 @@ void WM_jobs_kill_all_except(struct wmWindowManager *wm) {}
 char *WM_clipboard_text_get(int selection) {return (char*)0;}
 void WM_clipboard_text_set(char *buf, int selection) {}
 
+void                WM_uilisttype_init(void) {}
+struct uiListType  *WM_uilisttype_find(const char *idname, int quiet) {return (struct uiListType *)NULL;}
+int                 WM_uilisttype_add(struct uiListType *ult) {return 0;}
+void                WM_uilisttype_freelink(struct uiListType *ult) {}
+void                WM_uilisttype_free(void) {}
+
 struct wmKeyMapItem *WM_keymap_item_find_id(struct wmKeyMap *keymap, int id) {return (struct wmKeyMapItem *) NULL;}
 int WM_enum_search_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event) {return 0;}
 void WM_event_add_notifier(const struct bContext *C, unsigned int type, void *reference) {}
@@ -400,6 +406,7 @@ void uiItemFullR(struct uiLayout *layout, struct PointerRNA *ptr, struct Propert
 void uiLayoutSetContextPointer(struct uiLayout *layout, char *name, struct PointerRNA *ptr) {}
 char *uiLayoutIntrospect(struct uiLayout *layout) {return (char *)NULL;}
 void UI_reinit_font(void) {}
+int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, int big) {return 0;}
 
 /* rna template */
 void uiTemplateAnyID(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname, char *text) {}
@@ -414,7 +421,7 @@ void uiTemplateCurveMapping(struct uiLayout *layout, struct CurveMapping *cumap,
 void uiTemplateColorRamp(struct uiLayout *layout, struct ColorBand *coba, int expand) {}
 void uiTemplateLayers(struct uiLayout *layout, struct PointerRNA *ptr, char *propname) {}
 void uiTemplateImageLayers(struct uiLayout *layout, struct bContext *C, struct Image *ima, struct ImageUser *iuser) {}
-void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, const char *list_id,
+void uiTemplateList(struct uiLayout *layout, struct bContext *C, const char *listtype_name, const char *list_id,
                     PointerRNA *dataptr, const char *propname, PointerRNA *active_dataptr,
                     const char *active_propname, int rows, int maxrows, int layout_type) {}
 void uiTemplateRunningJobs(struct uiLayout *layout, struct bContext *C) {}
-- 
cgit v1.2.3


From 5e4bc5a4f8d1fd5fa6e10afe4091fed77a39768e Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Fri, 28 Dec 2012 11:24:07 +0000
Subject: patch [#33687] select similar lamp by Saurabh Wankhade (sauraedron),
 with some edits.

---
 source/blender/editors/object/object_select.c | 28 ++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index 2aa737d204d..07eca749a74 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -42,6 +42,7 @@
 #include "DNA_property_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_armature_types.h"
+#include "DNA_lamp_types.h"
 
 #include "BLI_math.h"
 #include "BLI_listbase.h"
@@ -525,6 +526,7 @@ static EnumPropertyItem prop_select_grouped_types[] = {
 	{10, "COLOR", 0, "Color", "Object Color"},
 	{11, "PROPERTIES", 0, "Properties", "Game Properties"},
 	{12, "KEYINGSET", 0, "Keying Set", "Objects included in active Keying Set"},
+	{13, "LAMP_TYPE", 0, "Lamp Type", "Matching lamp types"},
 	{0, NULL, 0, NULL, NULL}
 };
 
@@ -656,7 +658,25 @@ static short select_grouped_siblings(bContext *C, Object *ob)
 	CTX_DATA_END;
 	return changed;
 }
+static short select_similar_lamps(bContext *C, Object *ob)
+{
+	Lamp *la = ob->data;
+
+	short changed = 0;
 
+	CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
+	{
+		if (base->object->type == OB_LAMP) {
+			Lamp *la_test = base->object->data;
+			if ((la->type == la_test->type) && !(base->flag & SELECT)) {
+				ED_base_object_select(base, BA_SELECT);
+				changed = 1;
+			}
+		}
+	}
+	CTX_DATA_END;
+	return changed;
+}
 static short select_grouped_type(bContext *C, Object *ob)
 {
 	short changed = 0;
@@ -803,7 +823,12 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op)
 		BKE_report(op->reports, RPT_ERROR, "No active object");
 		return OPERATOR_CANCELLED;
 	}
-	
+
+	if (nr == 13 && ob->type != OB_LAMP) {
+		BKE_report(op->reports, RPT_ERROR, "Active object must be a lamp");
+		return OPERATOR_CANCELLED;
+	}
+
 	if      (nr == 1) changed |= select_grouped_children(C, ob, 1);
 	else if (nr == 2) changed |= select_grouped_children(C, ob, 0);
 	else if (nr == 3) changed |= select_grouped_parent(C);
@@ -816,6 +841,7 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op)
 	else if (nr == 10) changed |= select_grouped_color(C, ob);
 	else if (nr == 11) changed |= select_grouped_gameprops(C, ob);
 	else if (nr == 12) changed |= select_grouped_keyingset(C, ob);
+	else if (nr == 13) changed |= select_similar_lamps(C, ob);
 	
 	if (changed) {
 		WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
-- 
cgit v1.2.3


From 921750149bdd303ad7d93922d4ce739867c1013c Mon Sep 17 00:00:00 2001
From: Bastien Montagne 
Date: Fri, 28 Dec 2012 13:21:57 +0000
Subject: Expose BKE_constraint_mat_convertspace() as object's convert_space()
 func in RNA. Converting between various standard spaces (like local, pose,
 world, etc.) can become quite hairy (especially with bones), as we already
 have this code in C, let's help py devs' life.

Thanks to Campbell for the review and advices.
---
 source/blender/makesrna/intern/rna_object_api.c | 93 ++++++++++++++++++++-----
 1 file changed, 75 insertions(+), 18 deletions(-)

(limited to 'source')

diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index 87fc3be28a2..d7115256fe5 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -36,42 +36,79 @@
 
 #include "RNA_define.h"
 
-#include "DNA_object_types.h"
+#include "DNA_constraint_types.h"
 #include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
 
 #include "rna_internal.h"  /* own include */
 
+static EnumPropertyItem space_items[] = {
+	{CONSTRAINT_SPACE_WORLD,    "WORLD", 0, "World Space",
+	                            "The most gobal space in Blender"},
+	{CONSTRAINT_SPACE_POSE,     "POSE", 0, "Pose Space",
+	                            "The pose space of a bone (its armature's object space)"},
+	{CONSTRAINT_SPACE_PARLOCAL, "LOCAL_WITH_PARENT", 0, "Local With Parent",
+	                            "The local space of a bone's parent bone"},
+	{CONSTRAINT_SPACE_LOCAL,    "LOCAL", 0, "Local Space",
+	                            "The local space of an object/bone"},
+	{0, NULL, 0, NULL, NULL}
+};
+
 #ifdef RNA_RUNTIME
+
 #include "BLI_math.h"
 
-#include "BKE_main.h"
-#include "BKE_global.h"
-#include "BKE_context.h"
-#include "BKE_report.h"
-#include "BKE_object.h"
-#include "BKE_mesh.h"
-#include "BKE_DerivedMesh.h"
+#include "BKE_anim.h"
 #include "BKE_bvhutils.h"
-
+#include "BKE_cdderivedmesh.h"
+#include "BKE_constraint.h"
+#include "BKE_context.h"
 #include "BKE_customdata.h"
-#include "BKE_anim.h"
 #include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
 #include "BKE_displist.h"
 #include "BKE_font.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_mesh.h"
 #include "BKE_mball.h"
 #include "BKE_modifier.h"
-#include "BKE_cdderivedmesh.h"
+#include "BKE_object.h"
+#include "BKE_report.h"
 
+#include "DNA_curve_types.h"
 #include "DNA_mesh_types.h"
-#include "DNA_scene_types.h"
 #include "DNA_meshdata_types.h"
-#include "DNA_curve_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_constraint_types.h"
+#include "DNA_scene_types.h"
 #include "DNA_view3d_types.h"
 
 #include "MEM_guardedalloc.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)
+{
+	copy_m4_m4((float (*)[4])mat_ret, (float (*)[4])mat);
+
+	/* Error in case of invalid from/to values when pchan is NULL */
+	if (pchan == NULL) {
+		if (ELEM(from, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_PARLOCAL)) {
+			const char *identifier = NULL;
+			RNA_enum_identifier(space_items, from, &identifier);
+			BKE_reportf(reports, RPT_ERROR, "'from_space' '%s' is invalid when no pose bone is given!", identifier);
+			return;
+		}
+		if (ELEM(to, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_PARLOCAL)) {
+			const char *identifier = NULL;
+			RNA_enum_identifier(space_items, to, &identifier);
+			BKE_reportf(reports, RPT_ERROR, "'to_space' '%s' is invalid when no pose bone is given!", identifier);
+			return;
+		}
+	}
+
+	BKE_constraint_mat_convertspace(ob, pchan, (float (*)[4])mat_ret, from, to);
+}
+
 /* copied from Mesh_getFromObject and adapted to RNA interface */
 /* settings: 0 - preview, 1 - render */
 static Mesh *rna_Object_to_mesh(Object *ob, ReportList *reports, Scene *sce, int apply_modifiers, int settings)
@@ -570,7 +607,7 @@ void rna_Object_dm_info(struct Object *ob, int type, char *result)
 }
 #endif /* NDEBUG */
 
-#else
+#else /* RNA_RUNTIME */
 
 void RNA_api_object(StructRNA *srna)
 {
@@ -583,6 +620,8 @@ void RNA_api_object(StructRNA *srna)
 		{0, NULL, 0, NULL, NULL}
 	};
 
+	static int rna_matrix_dimsize_4x4[] = {4, 4};
+
 #ifndef NDEBUG
 	static EnumPropertyItem mesh_dm_info_items[] = {
 		{0, "SOURCE", 0, "Source", "Source mesh"},
@@ -592,6 +631,25 @@ void RNA_api_object(StructRNA *srna)
 	};
 #endif
 
+	/* Matrix space conversion */
+	func = RNA_def_function(srna, "convert_space", "rna_Scene_mat_convert_space");
+	RNA_def_function_ui_description(func, "Convert (transform) the given matrix from one space to another");
+	RNA_def_function_flag(func, FUNC_USE_REPORTS);
+	parm = RNA_def_pointer(func, "pose_bone", "PoseBone", "",
+	                       "Bone to use to define spaces (may be None, in which case only the two 'WORLD' and "
+	                       "'LOCAL' spaces are usable)");
+	parm = RNA_def_property(func, "matrix", PROP_FLOAT, PROP_MATRIX);
+	RNA_def_property_multi_array(parm, 2, rna_matrix_dimsize_4x4);
+	RNA_def_property_ui_text(parm, "", "The matrix to transform");
+	parm = RNA_def_property(func, "matrix_return", PROP_FLOAT, PROP_MATRIX);
+	RNA_def_property_multi_array(parm, 2, rna_matrix_dimsize_4x4);
+	RNA_def_property_ui_text(parm, "", "The transformed matrix");
+	RNA_def_function_output(func, parm);
+	parm = RNA_def_enum(func, "from_space", space_items, CONSTRAINT_SPACE_WORLD, "",
+	                    "The space in which 'matrix' is currently");
+	parm = RNA_def_enum(func, "to_space", space_items, CONSTRAINT_SPACE_WORLD, "",
+	                    "The space to which you want to transform 'matrix'");
+
 	/* mesh */
 	func = RNA_def_function(srna, "to_mesh", "rna_Object_to_mesh");
 	RNA_def_function_ui_description(func, "Create a Mesh datablock with modifiers applied");
@@ -737,5 +795,4 @@ void RNA_api_object_base(StructRNA *srna)
 	RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
 }
 
-#endif
-
+#endif /* RNA_RUNTIME */
-- 
cgit v1.2.3


From 6ac7ab48f455d51d34763b807733454de742bfbd Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Fri, 28 Dec 2012 13:44:44 +0000
Subject: Small fix: increased precision print of color sampling float images
 with 1 digit. Now it prints 5, which shows better whether a buffer is float,
 or half float.

---
 source/blender/editors/space_image/image_draw.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index d565e6f9e9a..e85ff016745 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -146,7 +146,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_def
 	if (channels >= 3) {
 		glColor3ubv(red);
 		if (fp)
-			BLI_snprintf(str, sizeof(str), "  R:%-.4f", fp[0]);
+			BLI_snprintf(str, sizeof(str), "  R:%-.5f", fp[0]);
 		else if (cp)
 			BLI_snprintf(str, sizeof(str), "  R:%-3d", cp[0]);
 		else
@@ -157,7 +157,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_def
 		
 		glColor3ubv(green);
 		if (fp)
-			BLI_snprintf(str, sizeof(str), "  G:%-.4f", fp[1]);
+			BLI_snprintf(str, sizeof(str), "  G:%-.5f", fp[1]);
 		else if (cp)
 			BLI_snprintf(str, sizeof(str), "  G:%-3d", cp[1]);
 		else
@@ -168,7 +168,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_def
 		
 		glColor3ubv(blue);
 		if (fp)
-			BLI_snprintf(str, sizeof(str), "  B:%-.4f", fp[2]);
+			BLI_snprintf(str, sizeof(str), "  B:%-.5f", fp[2]);
 		else if (cp)
 			BLI_snprintf(str, sizeof(str), "  B:%-3d", cp[2]);
 		else
-- 
cgit v1.2.3


From ddf39a87aa704240a0cb0cac584893ba34700e5d Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Fri, 28 Dec 2012 13:48:30 +0000
Subject: code cleanup: move view3d buffer bones loop into a static function
 (was not breaking out of the loop when a bone was found).

---
 .../blender/editors/space_view3d/view3d_select.c   | 31 +++++++++++++---------
 1 file changed, 18 insertions(+), 13 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index b337d703192..6cca5b298fe 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -1187,31 +1187,42 @@ static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int
 	}
 }
 
+static int selectbuffer_has_bones(const unsigned int *buffer, const unsigned int hits)
+{
+	unsigned int i;
+	for (i = 0; i < hits; i++) {
+		if (buffer[(4 * i) + 3] & 0xFFFF0000) {
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
 /* we want a select buffer with bones, if there are... */
 /* so check three selection levels and compare */
 static short mixed_bones_object_selectbuffer(ViewContext *vc, unsigned int *buffer, const int mval[2])
 {
 	rcti rect;
 	int offs;
-	short a, hits15, hits9 = 0, hits5 = 0;
-	short has_bones15 = 0, has_bones9 = 0, has_bones5 = 0;
+	short hits15, hits9 = 0, hits5 = 0;
+	short has_bones15 = FALSE, has_bones9 = FALSE, has_bones5 = FALSE;
 	
 	BLI_rcti_init(&rect, mval[0] - 14, mval[0] + 14, mval[1] - 14, mval[1] + 14);
 	hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect);
 	if (hits15 > 0) {
-		for (a = 0; a < hits15; a++) if (buffer[4 * a + 3] & 0xFFFF0000) has_bones15 = 1;
+		has_bones15 = selectbuffer_has_bones(buffer, hits15);
 
 		offs = 4 * hits15;
 		BLI_rcti_init(&rect, mval[0] - 9, mval[0] + 9, mval[1] - 9, mval[1] + 9);
 		hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect);
 		if (hits9 > 0) {
-			for (a = 0; a < hits9; a++) if (buffer[offs + 4 * a + 3] & 0xFFFF0000) has_bones9 = 1;
+			has_bones9 = selectbuffer_has_bones(buffer + offs, hits9);
 
 			offs += 4 * hits9;
 			BLI_rcti_init(&rect, mval[0] - 5, mval[0] + 5, mval[1] - 5, mval[1] + 5);
 			hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect);
 			if (hits5 > 0) {
-				for (a = 0; a < hits5; a++) if (buffer[offs + 4 * a + 3] & 0xFFFF0000) has_bones5 = 1;
+				has_bones5 = selectbuffer_has_bones(buffer + offs, hits5);
 			}
 		}
 		
@@ -1353,10 +1364,7 @@ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2])
 	hits = mixed_bones_object_selectbuffer(&vc, buffer, mval);
 	
 	if (hits > 0) {
-		int a, has_bones = 0;
-		
-		for (a = 0; a < hits; a++) if (buffer[4 * a + 3] & 0xFFFF0000) has_bones = 1;
-		
+		const int has_bones = selectbuffer_has_bones(buffer, hits);
 		basact = mouse_select_eval_buffer(&vc, buffer, hits, mval, vc.scene->base.first, has_bones);
 	}
 	
@@ -1390,7 +1398,6 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese
 	View3D *v3d = CTX_wm_view3d(C);
 	Scene *scene = CTX_data_scene(C);
 	Base *base, *startbase = NULL, *basact = NULL, *oldbasact = NULL;
-	int  a;
 	float dist = 100.0f;
 	int retval = 0;
 	short hits;
@@ -1443,10 +1450,8 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese
 		hits = mixed_bones_object_selectbuffer(&vc, buffer, mval);
 		
 		if (hits > 0) {
-			int has_bones = 0;
-			
 			/* note: bundles are handling in the same way as bones */
-			for (a = 0; a < hits; a++) if (buffer[4 * a + 3] & 0xFFFF0000) has_bones = 1;
+			const int has_bones = selectbuffer_has_bones(buffer, hits);
 
 			/* note; shift+alt goes to group-flush-selecting */
 			if (has_bones == 0 && enumerate) {
-- 
cgit v1.2.3


From 857df8065face58eff5556953cdf2dd72e09f2b6 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Fri, 28 Dec 2012 14:19:05 +0000
Subject: style cleanup

---
 source/blender/blenfont/intern/blf_lang.c          |  8 ++--
 source/blender/blenkernel/intern/cloth.c           |  2 +-
 source/blender/blenkernel/intern/collision.c       |  6 +--
 source/blender/blenkernel/intern/image.c           |  2 +-
 source/blender/blenkernel/intern/node.c            | 10 ++---
 source/blender/blenkernel/intern/pointcache.c      |  4 +-
 source/blender/bmesh/intern/bmesh_operator_api.h   |  2 +-
 source/blender/editors/screen/area.c               |  4 +-
 source/blender/editors/sculpt_paint/paint_vertex.c |  1 -
 source/blender/editors/space_logic/logic_window.c  |  4 +-
 source/blender/editors/space_logic/space_logic.c   |  2 +-
 source/blender/editors/space_node/drawnode.c       |  4 +-
 .../blender/editors/uvedit/uvedit_smart_stitch.c   |  2 +-
 source/blender/gpu/intern/gpu_draw.c               |  4 +-
 source/blender/gpu/intern/gpu_extensions.c         |  8 ++--
 source/blender/ikplugin/intern/itasc_plugin.cpp    |  2 +-
 source/blender/imbuf/intern/IMB_metadata.h         |  2 +-
 source/blender/imbuf/intern/dds/dds_api.cpp        |  2 +-
 source/blender/imbuf/intern/imageprocess.c         |  4 +-
 source/blender/makesrna/intern/makesrna.c          | 50 +++++++++++-----------
 source/blender/makesrna/intern/rna_modifier.c      |  4 +-
 source/blender/makesrna/intern/rna_nodetree.c      |  2 +-
 source/blender/makesrna/intern/rna_object.c        |  8 ++--
 source/blender/makesrna/intern/rna_scene.c         |  2 +-
 source/blender/nodes/intern/node_common.c          |  8 ++--
 source/blender/nodes/intern/node_exec.c            |  6 +--
 source/blender/nodes/shader/node_shader_util.c     | 44 +++++++++----------
 .../nodes/shader/nodes/node_shader_common.c        |  8 ++--
 .../nodes/shader/nodes/node_shader_mapping.c       |  2 +-
 source/blender/python/generic/py_capi_utils.h      |  2 +-
 .../render/intern/raytrace/rayobject_instance.cpp  |  4 +-
 .../blender/render/intern/source/convertblender.c  |  2 +-
 source/blender/render/intern/source/rayshade.c     | 14 +++---
 source/blender/render/intern/source/rendercore.c   |  8 ++--
 .../blender/render/intern/source/renderdatabase.c  |  8 ++--
 source/blender/render/intern/source/shadbuf.c      |  2 +-
 source/blender/render/intern/source/strand.c       |  2 +-
 .../blender/render/intern/source/volume_precache.c |  2 +-
 source/blenderplayer/bad_level_call_stubs/stubs.c  |  2 +-
 39 files changed, 126 insertions(+), 127 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenfont/intern/blf_lang.c b/source/blender/blenfont/intern/blf_lang.c
index 4d066ea8740..9086799f984 100644
--- a/source/blender/blenfont/intern/blf_lang.c
+++ b/source/blender/blenfont/intern/blf_lang.c
@@ -100,7 +100,7 @@ static void fill_locales(void)
 	/* First loop to find highest locale ID */
 	while (line) {
 		int t;
-		str = (char*) line->link;
+		str = (char *)line->link;
 		if (str[0] == '#' || str[0] == '\0') {
 			line = line->next;
 			continue; /* Comment or void... */
@@ -118,12 +118,12 @@ static void fill_locales(void)
 	line = lines;
 	/* Do not allocate locales with zero-sized mem, as LOCALE macro uses NULL locales as invalid marker! */
 	if (num_locales > 0) {
-		locales = MEM_callocN(num_locales * sizeof(char*), __func__);
+		locales = MEM_callocN(num_locales * sizeof(char *), __func__);
 		while (line) {
 			int id;
 			char *loc, *sep1, *sep2, *sep3;
 
-			str = (char*) line->link;
+			str = (char *)line->link;
 			if (str[0] == '#' || str[0] == '\0') {
 				line = line->next;
 				continue;
@@ -230,7 +230,7 @@ void BLF_lang_set(const char *str)
 	bl_locale_set(short_locale_utf8);
 
 	if (short_locale[0]) {
-		MEM_freeN((void*)short_locale_utf8);
+		MEM_freeN((void *)short_locale_utf8);
 	}
 }
 
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index f1d73c7777a..fdd7dc94979 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -1153,7 +1153,7 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
 		if ( !mface[i].v4 )
 			continue;
 
-		spring = ( ClothSpring *) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );
+		spring = (ClothSpring *)MEM_callocN(sizeof(ClothSpring), "cloth spring");
 		
 		if (!spring) {
 			cloth_free_errorsprings(cloth, edgehash, edgelist);
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index f0043d9fa77..60bf67e19e3 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -528,7 +528,7 @@ static void add_collision_object(Object ***objs, unsigned int *numobj, unsigned
 		/* extend array */
 		if (*numobj >= *maxobj) {
 			*maxobj *= 2;
-			*objs= MEM_reallocN(*objs, sizeof(Object*)*(*maxobj));
+			*objs= MEM_reallocN(*objs, sizeof(Object *)*(*maxobj));
 		}
 		
 		(*objs)[*numobj] = ob;
@@ -740,7 +740,7 @@ int cloth_bvh_objcollision(Object *ob, ClothModifierData * clmd, float step, flo
 	/* move object to position (step) in time */
 	for (i = 0; i < numcollobj; i++) {
 		Object *collob= collobjs[i];
-		CollisionModifierData *collmd = (CollisionModifierData*)modifiers_findByType(collob, eModifierType_Collision);
+		CollisionModifierData *collmd = (CollisionModifierData *)modifiers_findByType(collob, eModifierType_Collision);
 
 		if (!collmd->bvhtree)
 			continue;
@@ -760,7 +760,7 @@ int cloth_bvh_objcollision(Object *ob, ClothModifierData * clmd, float step, flo
 		// check all collision objects
 		for (i = 0; i < numcollobj; i++) {
 			Object *collob= collobjs[i];
-			CollisionModifierData *collmd = (CollisionModifierData*)modifiers_findByType(collob, eModifierType_Collision);
+			CollisionModifierData *collmd = (CollisionModifierData *)modifiers_findByType(collob, eModifierType_Collision);
 			BVHTreeOverlap *overlap = NULL;
 			unsigned int result = 0;
 			
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 7782afaca25..22995e5a7ee 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -1996,7 +1996,7 @@ int BKE_imbuf_write_stamp(Scene *scene, struct Object *camera, ImBuf *ibuf, cons
 
 
 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)
 {
 	if (string == NULL) return;
 	BLI_strncpy(string, base, FILE_MAX - 10);   /* weak assumption */
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 8babdf2402f..a6ec1f33edc 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -1161,11 +1161,11 @@ void ntreeSetOutput(bNodeTree *ntree)
 bNodeTree *ntreeFromID(ID *id)
 {
 	switch (GS(id->name)) {
-		case ID_MA: return ((Material*)id)->nodetree;
-		case ID_LA: return ((Lamp*)id)->nodetree;
-		case ID_WO: return ((World*)id)->nodetree;
-		case ID_TE: return ((Tex*)id)->nodetree;
-		case ID_SCE: return ((Scene*)id)->nodetree;
+		case ID_MA:  return ((Material *)id)->nodetree;
+		case ID_LA:  return ((Lamp *)id)->nodetree;
+		case ID_WO:  return ((World *)id)->nodetree;
+		case ID_TE:  return ((Tex *)id)->nodetree;
+		case ID_SCE: return ((Scene *)id)->nodetree;
 		default: return NULL;
 	}
 }
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 2eadfe73858..9c3c1b0e508 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -1540,7 +1540,7 @@ void BKE_ptcache_mem_pointers_incr(PTCacheMem *pm)
 
 	for (i=0; icur[i])
-			pm->cur[i] = (char*)pm->cur[i] + ptcache_data_size[i];
+			pm->cur[i] = (char *)pm->cur[i] + ptcache_data_size[i];
 	}
 }
 int  BKE_ptcache_mem_pointers_seek(int point_index, PTCacheMem *pm)
@@ -1558,7 +1558,7 @@ int  BKE_ptcache_mem_pointers_seek(int point_index, PTCacheMem *pm)
 	}
 
 	for (i=0; icur[i] = data_types & (1<data[i] + index * ptcache_data_size[i] : NULL;
+		pm->cur[i] = data_types & (1<data[i] + index * ptcache_data_size[i] : NULL;
 
 	return 1;
 }
diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h
index 7df9c94a2f1..b8fbfbee37f 100644
--- a/source/blender/bmesh/intern/bmesh_operator_api.h
+++ b/source/blender/bmesh/intern/bmesh_operator_api.h
@@ -435,7 +435,7 @@ void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_
  *        //whether it's a float, pointer, whatever.
  *        //
  *        // so to get a pointer, for example, use:
- *        //  *((void**)BMO_iter_map_value(&oiter));
+ *        //  *((void **)BMO_iter_map_value(&oiter));
  *        //or something like that.
  *    }
  * \endcode
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 0e8628d47bf..827f19307b8 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -1677,7 +1677,7 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *
 				if (pt->draw_header && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) {
 					/* for enabled buttons */
 					panel->layout = uiBlockLayout(block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER,
-												  triangle, (UI_UNIT_Y * 1.1f) + style->panelspace, UI_UNIT_Y, 1, style);
+					                              triangle, (UI_UNIT_Y * 1.1f) + style->panelspace, UI_UNIT_Y, 1, style);
 
 					pt->draw_header(C, panel);
 
@@ -1699,7 +1699,7 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *
 						panelContext = UI_LAYOUT_PANEL;
 					
 					panel->layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, panelContext,
-												  style->panelspace, 0, w - 2 * style->panelspace, em, style);
+					                              style->panelspace, 0, w - 2 * style->panelspace, em, style);
 
 					pt->draw(C, panel);
 
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 17bf5c841c3..6a61a6c45dc 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -2070,7 +2070,6 @@ static int wpaint_ensure_data(bContext *C, wmOperator *op)
 		return FALSE;
 	}
 
-	me = BKE_mesh_from_object(ob);
 	if (me == NULL || me->totpoly == 0) {
 		return FALSE;
 	}
diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c
index 00745062582..a7599f21ad5 100644
--- a/source/blender/editors/space_logic/logic_window.c
+++ b/source/blender/editors/space_logic/logic_window.c
@@ -1006,7 +1006,7 @@ static void draw_sensor_actuator(uiLayout *layout, PointerRNA *ptr)
 
 static void draw_sensor_armature(uiLayout *layout, PointerRNA *ptr)
 {
-	bSensor *sens = (bSensor*)ptr->data;
+	bSensor *sens = (bSensor *)ptr->data;
 	bArmatureSensor *as = (bArmatureSensor *) sens->data;
 	Object *ob = (Object *)ptr->id.data;
 	PointerRNA pose_ptr, pchan_ptr;
@@ -1476,7 +1476,7 @@ static void draw_actuator_action(uiLayout *layout, PointerRNA *ptr)
 
 static void draw_actuator_armature(uiLayout *layout, PointerRNA *ptr)
 {
-	bActuator *act = (bActuator*)ptr->data;
+	bActuator *act = (bActuator *)ptr->data;
 	bArmatureActuator *aa = (bArmatureActuator *) act->data;
 	Object *ob = (Object *)ptr->id.data;
 	bConstraint *constraint = NULL;
diff --git a/source/blender/editors/space_logic/space_logic.c b/source/blender/editors/space_logic/space_logic.c
index 4cd53215697..8795d655e77 100644
--- a/source/blender/editors/space_logic/space_logic.c
+++ b/source/blender/editors/space_logic/space_logic.c
@@ -148,7 +148,7 @@ static SpaceLink *logic_new(const bContext *C)
 /* not spacelink itself */
 static void logic_free(SpaceLink *UNUSED(sl))
 {	
-//	Spacelogic *slogic= (SpaceLogic*) sl;
+//	Spacelogic *slogic= (SpaceLogic *) sl;
 	
 //	if (slogic->gpd)
 // XXX		BKE_gpencil_free(slogic->gpd);
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index b702dc4c0bc..8797cb4a459 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -399,8 +399,8 @@ static void node_buts_curvecol(uiLayout *layout, bContext *UNUSED(C), PointerRNA
 
 static void node_buts_normal(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
 {
-	bNodeTree *ntree = (bNodeTree*)ptr->id.data;
-	bNode *node = (bNode*)ptr->data;
+	bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+	bNode *node = (bNode *)ptr->data;
 	bNodeSocket *sock = node->outputs.first;     /* first socket stores normal */
 	PointerRNA sockptr;
 
diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c
index f7219f8bd1b..96e43dafa2f 100644
--- a/source/blender/editors/uvedit/uvedit_smart_stitch.c
+++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c
@@ -1606,7 +1606,7 @@ static int stitch_init(bContext *C, wmOperator *op)
 	}
 
 	uvedit_get_aspect(scene, obedit, em, &aspx, &aspy);
-	state->aspect = aspx/aspy;
+	state->aspect = aspx / aspy;
 
 	/* Entirely possible if redoing last operator that static island is bigger than total number of islands.
 	 * This ensures we get no hang in the island checking code in stitch_stitch_process_data. */
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index 07462302700..a633b39cb32 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -92,7 +92,7 @@ void GPU_render_text(MTFace *tface, int mode,
 	float *v1, float *v2, float *v3, float *v4, int glattrib)
 {
 	if ((mode & GEMAT_TEXT) && (textlen>0) && tface->tpage) {
-		Image* ima = (Image*)tface->tpage;
+		Image* ima = (Image *)tface->tpage;
 		int index, character;
 		float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance;
 		float advance_tab;
@@ -813,7 +813,7 @@ void GPU_create_gl_tex_compressed(unsigned int *bind, unsigned int *pix, int x,
 	glBindTexture(GL_TEXTURE_2D, *bind);
 
 	if (GPU_upload_dxt_texture(ibuf) == 0) {
-		glDeleteTextures(1, (GLuint*)bind);
+		glDeleteTextures(1, (GLuint *)bind);
 		GPU_create_gl_tex(bind, pix, NULL, x, y, mipmap, 0, ima);
 	}
 #endif
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index 7a0ac29c9ab..bc859d0ec07 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -134,8 +134,8 @@ void GPU_extensions_init(void)
 	glGetIntegerv(GL_BLUE_BITS, &b);
 	GG.colordepth = r+g+b; /* assumes same depth for RGB */
 
-	vendor = (const char*)glGetString(GL_VENDOR);
-	renderer = (const char*)glGetString(GL_RENDERER);
+	vendor = (const char *)glGetString(GL_VENDOR);
+	renderer = (const char *)glGetString(GL_RENDERER);
 
 	if (strstr(vendor, "ATI")) {
 		GG.device = GPU_DEVICE_ATI;
@@ -916,7 +916,7 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b
 	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, blurfb->object);
 
 	GPU_shader_bind(blur_shader);
-	GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, (float*)scaleh);
+	GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, (float *)scaleh);
 	GPU_shader_uniform_texture(blur_shader, texture_source_uniform, tex);
 	glViewport(0, 0, GPU_texture_opengl_width(blurtex), GPU_texture_opengl_height(blurtex));
 
@@ -942,7 +942,7 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b
 
 	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
 	glViewport(0, 0, GPU_texture_opengl_width(tex), GPU_texture_opengl_height(tex));
-	GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, (float*)scalev);
+	GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, (float *)scalev);
 	GPU_shader_uniform_texture(blur_shader, texture_source_uniform, blurtex);
 	GPU_texture_bind(blurtex, 0);
 
diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp
index ef992e1d010..f940d2635dc 100644
--- a/source/blender/ikplugin/intern/itasc_plugin.cpp
+++ b/source/blender/ikplugin/intern/itasc_plugin.cpp
@@ -370,7 +370,7 @@ static int initialize_chain(Object *ob, bPoseChannel *pchan_tip, bConstraint *co
 
 static bool is_cartesian_constraint(bConstraint *con)
 {
-	//bKinematicConstraint* data=(bKinematicConstraint*)con->data;
+	//bKinematicConstraint* data=(bKinematicConstraint *)con->data;
 
 	return true;
 }
diff --git a/source/blender/imbuf/intern/IMB_metadata.h b/source/blender/imbuf/intern/IMB_metadata.h
index a68d7a7813e..f731fd69620 100644
--- a/source/blender/imbuf/intern/IMB_metadata.h
+++ b/source/blender/imbuf/intern/IMB_metadata.h
@@ -42,7 +42,7 @@ typedef struct ImMetaData {
 	int len;
 } ImMetaData;
 
-/** The metadata is a list of key/value pairs (both char*) that can me
+/** The metadata is a list of key/value pairs (both char *) that can me
  * saved in the header of several image formats.
  * Apart from some common keys like
  * 'Software' and 'Description' (png standard) we'll use keys within the
diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp
index 5459cffe590..c41bbd594b3 100644
--- a/source/blender/imbuf/intern/dds/dds_api.cpp
+++ b/source/blender/imbuf/intern/dds/dds_api.cpp
@@ -164,7 +164,7 @@ struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags, char colo
 		}
 
 		if (ibuf->dds_data.fourcc != FOURCC_DDS) {
-			ibuf->dds_data.data = (unsigned char*)dds.readData(ibuf->dds_data.size);
+			ibuf->dds_data.data = (unsigned char *)dds.readData(ibuf->dds_data.size);
 
 			/* flip compressed texture */
 			FlipDXTCImage(dds.width(), dds.height(), dds.mipmapCount(), dds.fourCC(), ibuf->dds_data.data);
diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c
index 92b8dd8c724..1eac6236829 100644
--- a/source/blender/imbuf/intern/imageprocess.c
+++ b/source/blender/imbuf/intern/imageprocess.c
@@ -104,7 +104,7 @@ void bicubic_interpolation_color(struct ImBuf *in, unsigned char outI[4], float
 		BLI_bicubic_interpolation_fl(in->rect_float, outF, in->x, in->y, 4, u, v);
 	}
 	else {
-		BLI_bicubic_interpolation_char((unsigned char*) in->rect, outI, in->x, in->y, 4, u, v);
+		BLI_bicubic_interpolation_char((unsigned char *) in->rect, outI, in->x, in->y, 4, u, v);
 	}
 }
 
@@ -130,7 +130,7 @@ void bilinear_interpolation_color(struct ImBuf *in, unsigned char outI[4], float
 		BLI_bilinear_interpolation_fl(in->rect_float, outF, in->x, in->y, 4, u, v);
 	}
 	else {
-		BLI_bilinear_interpolation_char((unsigned char*) in->rect, outI, in->x, in->y, 4, u, v);
+		BLI_bilinear_interpolation_char((unsigned char *) in->rect, outI, in->x, in->y, 4, u, v);
 	}
 }
 
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index 2785a95ddb0..6b1f496b593 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -415,10 +415,10 @@ static const char *rna_type_type_name(PropertyRNA *prop)
 			return "float";
 		case PROP_STRING:
 			if (prop->flag & PROP_THICK_WRAP) {
-				return "char*";
+				return "char *";
 			}
 			else {
-				return "const char*";
+				return "const char *";
 			}
 		default:
 			return NULL;
@@ -870,16 +870,16 @@ static char *rna_def_property_set_func(FILE *f, StructRNA *srna, PropertyRNA *pr
 
 				if (prop->flag & PROP_ID_REFCOUNT) {
 					fprintf(f, "\n	if (data->%s)\n", dp->dnaname);
-					fprintf(f, "		id_us_min((ID*)data->%s);\n", dp->dnaname);
+					fprintf(f, "		id_us_min((ID *)data->%s);\n", dp->dnaname);
 					fprintf(f, "	if (value.data)\n");
-					fprintf(f, "		id_us_plus((ID*)value.data);\n\n");
+					fprintf(f, "		id_us_plus((ID *)value.data);\n\n");
 				}
 				else {
 					PointerPropertyRNA *pprop = (PointerPropertyRNA *)dp->prop;
 					StructRNA *type = rna_find_struct((const char *)pprop->type);
 					if (type && (type->flag & STRUCT_ID)) {
 						fprintf(f, "	if (value.data)\n");
-						fprintf(f, "		id_lib_extern((ID*)value.data);\n\n");
+						fprintf(f, "		id_lib_extern((ID *)value.data);\n\n");
 					}
 				}
 
@@ -1084,7 +1084,7 @@ static char *rna_def_property_begin_func(FILE *f, StructRNA *srna, PropertyRNA *
 
 	fprintf(f, "\n	memset(iter, 0, sizeof(*iter));\n");
 	fprintf(f, "	iter->parent= *ptr;\n");
-	fprintf(f, "	iter->prop= (PropertyRNA*)&rna_%s_%s;\n", srna->identifier, prop->identifier);
+	fprintf(f, "	iter->prop= (PropertyRNA *)&rna_%s_%s;\n", srna->identifier, prop->identifier);
 
 	if (dp->dnalengthname || dp->dnalengthfixed) {
 		if (manualfunc) {
@@ -1768,7 +1768,7 @@ static void rna_def_property_funcs_header_cpp(FILE *f, StructRNA *srna, Property
 			const char *collection_funcs = "DefaultCollectionFunctions";
 
 			if (!(dp->prop->flag & (PROP_IDPROPERTY | PROP_BUILTIN)) && cprop->property.srna)
-				collection_funcs  = (char*)cprop->property.srna;
+				collection_funcs  = (char *)cprop->property.srna;
 
 			if (cprop->item_type)
 				fprintf(f, "\tCOLLECTION_PROPERTY(%s, %s, %s, %s, %s, %s, %s)", collection_funcs, (const char *)cprop->item_type, srna->identifier,
@@ -2906,9 +2906,9 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
 	        rna_property_structname(prop->type),
 	        srna->identifier, strnest, prop->identifier);
 
-	if (prop->next) fprintf(f, "\t{(PropertyRNA*)&rna_%s%s_%s, ", srna->identifier, strnest, prop->next->identifier);
+	if (prop->next) fprintf(f, "\t{(PropertyRNA *)&rna_%s%s_%s, ", srna->identifier, strnest, prop->next->identifier);
 	else fprintf(f, "\t{NULL, ");
-	if (prop->prev) fprintf(f, "(PropertyRNA*)&rna_%s%s_%s,\n", srna->identifier, strnest, prop->prev->identifier);
+	if (prop->prev) fprintf(f, "(PropertyRNA *)&rna_%s%s_%s,\n", srna->identifier, strnest, prop->prev->identifier);
 	else fprintf(f, "NULL,\n");
 	fprintf(f, "\t%d, ", prop->magic);
 	rna_print_c_string(f, prop->identifier);
@@ -3080,12 +3080,12 @@ static void rna_generate_struct(BlenderRNA *UNUSED(brna), StructRNA *srna, FILE
 		fprintf(f, "%s%s rna_%s_%s_func = {\n", "", "FunctionRNA", srna->identifier, func->identifier);
 
 		if (func->cont.next)
-			fprintf(f, "\t{(FunctionRNA*)&rna_%s_%s_func, ", srna->identifier,
+			fprintf(f, "\t{(FunctionRNA *)&rna_%s_%s_func, ", srna->identifier,
 			        ((FunctionRNA *)func->cont.next)->identifier);
 		else
 			fprintf(f, "\t{NULL, ");
 		if (func->cont.prev)
-			fprintf(f, "(FunctionRNA*)&rna_%s_%s_func,\n", srna->identifier,
+			fprintf(f, "(FunctionRNA *)&rna_%s_%s_func,\n", srna->identifier,
 			        ((FunctionRNA *)func->cont.prev)->identifier);
 		else
 			fprintf(f, "NULL,\n");
@@ -3093,11 +3093,11 @@ static void rna_generate_struct(BlenderRNA *UNUSED(brna), StructRNA *srna, FILE
 		fprintf(f, "\tNULL,\n");
 
 		parm = func->cont.properties.first;
-		if (parm) fprintf(f, "\t{(PropertyRNA*)&rna_%s_%s_%s, ", srna->identifier, func->identifier, parm->identifier);
+		if (parm) fprintf(f, "\t{(PropertyRNA *)&rna_%s_%s_%s, ", srna->identifier, func->identifier, parm->identifier);
 		else fprintf(f, "\t{NULL, ");
 
 		parm = func->cont.properties.last;
-		if (parm) fprintf(f, "(PropertyRNA*)&rna_%s_%s_%s}},\n", srna->identifier, func->identifier, parm->identifier);
+		if (parm) fprintf(f, "(PropertyRNA *)&rna_%s_%s_%s}},\n", srna->identifier, func->identifier, parm->identifier);
 		else fprintf(f, "NULL}},\n");
 
 		fprintf(f, "\t");
@@ -3110,7 +3110,7 @@ static void rna_generate_struct(BlenderRNA *UNUSED(brna), StructRNA *srna, FILE
 		else fprintf(f, "\tNULL,\n");
 
 		if (func->c_ret)
-			fprintf(f, "\t(PropertyRNA*)&rna_%s_%s_%s\n", srna->identifier, func->identifier, func->c_ret->identifier);
+			fprintf(f, "\t(PropertyRNA *)&rna_%s_%s_%s\n", srna->identifier, func->identifier, func->c_ret->identifier);
 		else
 			fprintf(f, "\tNULL\n");
 
@@ -3128,11 +3128,11 @@ static void rna_generate_struct(BlenderRNA *UNUSED(brna), StructRNA *srna, FILE
 	fprintf(f, "\tNULL,\n");
 
 	prop = srna->cont.properties.first;
-	if (prop) fprintf(f, "\t{(PropertyRNA*)&rna_%s_%s, ", srna->identifier, prop->identifier);
+	if (prop) fprintf(f, "\t{(PropertyRNA *)&rna_%s_%s, ", srna->identifier, prop->identifier);
 	else fprintf(f, "\t{NULL, ");
 
 	prop = srna->cont.properties.last;
-	if (prop) fprintf(f, "(PropertyRNA*)&rna_%s_%s}},\n", srna->identifier, prop->identifier);
+	if (prop) fprintf(f, "(PropertyRNA *)&rna_%s_%s}},\n", srna->identifier, prop->identifier);
 	else fprintf(f, "NULL}},\n");
 	fprintf(f, "\t");
 	rna_print_c_string(f, srna->identifier);
@@ -3151,7 +3151,7 @@ static void rna_generate_struct(BlenderRNA *UNUSED(brna), StructRNA *srna, FILE
 		while (base->base && base->base->nameproperty == prop)
 			base = base->base;
 
-		fprintf(f, "\t(PropertyRNA*)&rna_%s_%s, ", base->identifier, prop->identifier);
+		fprintf(f, "\t(PropertyRNA *)&rna_%s_%s, ", base->identifier, prop->identifier);
 	}
 	else fprintf(f, "\tNULL, ");
 
@@ -3159,7 +3159,7 @@ static void rna_generate_struct(BlenderRNA *UNUSED(brna), StructRNA *srna, FILE
 	base = srna;
 	while (base->base && base->base->iteratorproperty == prop)
 		base = base->base;
-	fprintf(f, "(PropertyRNA*)&rna_%s_rna_properties,\n", base->identifier);
+	fprintf(f, "(PropertyRNA *)&rna_%s_rna_properties,\n", base->identifier);
 
 	if (srna->base) fprintf(f, "\t&RNA_%s,\n", srna->base->identifier);
 	else fprintf(f, "\tNULL,\n");
@@ -3181,11 +3181,11 @@ static void rna_generate_struct(BlenderRNA *UNUSED(brna), StructRNA *srna, FILE
 	}
 
 	func = srna->functions.first;
-	if (func) fprintf(f, "\t{(FunctionRNA*)&rna_%s_%s_func, ", srna->identifier, func->identifier);
+	if (func) fprintf(f, "\t{(FunctionRNA *)&rna_%s_%s_func, ", srna->identifier, func->identifier);
 	else fprintf(f, "\t{NULL, ");
 
 	func = srna->functions.last;
-	if (func) fprintf(f, "(FunctionRNA*)&rna_%s_%s_func}\n", srna->identifier, func->identifier);
+	if (func) fprintf(f, "(FunctionRNA *)&rna_%s_%s_func}\n", srna->identifier, func->identifier);
 	else fprintf(f, "NULL}\n");
 
 	fprintf(f, "};\n");
@@ -3575,7 +3575,7 @@ static const char *cpp_classes = ""
 "	int length;\n"
 "\n"
 "	DynamicArray() : data(NULL), length(0) {}\n"
-"	DynamicArray(int new_length) : data(NULL), length(new_length) { data = (float*)malloc(sizeof(T) * new_length); }\n"
+"	DynamicArray(int new_length) : data(NULL), length(new_length) { data = (float *)malloc(sizeof(T) * new_length); }\n"
 "	DynamicArray(const DynamicArray& other) { copy_from(other); }\n"
 "	const DynamicArray& operator=(const DynamicArray& other) { copy_from(other); return *this; }\n"
 "\n"
@@ -3586,7 +3586,7 @@ static const char *cpp_classes = ""
 "protected:\n"
 "	void copy_from(const DynamicArray& other) {\n"
 "		if (data) free(data);\n"
-"		data = (float*)malloc(sizeof(T) * other.length);\n"
+"		data = (float *)malloc(sizeof(T) * other.length);\n"
 "		memcpy(data, other.data, sizeof(T) * other.length);\n"
 "		length = other.length;\n"
 "	}\n"
@@ -3617,7 +3617,7 @@ static const char *cpp_classes = ""
 "{ return iter.valid != other.iter.valid; }\n"
 "\n"
 "	void begin(const Pointer &ptr)\n"
-"	{ if (init) Tend(&iter); Tbegin(&iter, (PointerRNA*)&ptr.ptr); t = T(iter.ptr); init = true; }\n"
+"	{ if (init) Tend(&iter); Tbegin(&iter, (PointerRNA *)&ptr.ptr); t = T(iter.ptr); init = true; }\n"
 "\n"
 "private:\n"
 "	const CollectionIterator& operator="
@@ -3751,13 +3751,13 @@ static void rna_generate_header_cpp(BlenderRNA *UNUSED(brna), FILE *f)
 					if (first_collection_func_struct == NULL)
 						first_collection_func_struct = ds->srna->identifier;
 
-					if (!rna_is_collection_functions_struct(collection_func_structs, (char*)prop->srna)) {
+					if (!rna_is_collection_functions_struct(collection_func_structs, (char *)prop->srna)) {
 						if (all_collection_func_structs >= max_collection_func_structs) {
 							printf("Array size to store all collection structures names is too small\n");
 							exit(1);
 						}
 
-						collection_func_structs[all_collection_func_structs++] = (char*)prop->srna;
+						collection_func_structs[all_collection_func_structs++] = (char *)prop->srna;
 					}
 				}
 			}
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index e1489d821a0..dda9a2b0494 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -748,13 +748,13 @@ static void rna_BevelModifier_angle_limit_set(PointerRNA *ptr, float value)
 
 static void rna_UVWarpModifier_vgroup_set(PointerRNA *ptr, const char *value)
 {
-	UVWarpModifierData *umd = (UVWarpModifierData*)ptr->data;
+	UVWarpModifierData *umd = (UVWarpModifierData *)ptr->data;
 	rna_object_vgroup_name_set(ptr, value, umd->vgroup_name, sizeof(umd->vgroup_name));
 }
 
 static void rna_UVWarpModifier_uvlayer_set(PointerRNA *ptr, const char *value)
 {
-	UVWarpModifierData *umd = (UVWarpModifierData*)ptr->data;
+	UVWarpModifierData *umd = (UVWarpModifierData *)ptr->data;
 	rna_object_uvlayer_name_set(ptr, value, umd->uvlayer_name, sizeof(umd->uvlayer_name));
 }
 
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 3e9f5f1b88f..05dba0c0f68 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -1101,7 +1101,7 @@ static void rna_ShaderNodeScript_mode_set(PointerRNA *ptr, int value)
 
 		/* replace text datablock by filepath */
 		if (node->id) {
-			Text *text = (Text*)node->id;
+			Text *text = (Text *)node->id;
 
 			if (value == NODE_SCRIPT_EXTERNAL && text->name) {
 				BLI_strncpy(nss->filepath, text->name, sizeof(nss->filepath));
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 8a67d9270e8..4918aabdb1f 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -1123,7 +1123,7 @@ static void rna_GameObjectSettings_used_state_get(PointerRNA *ptr, int *values)
 
 static void rna_GameObjectSettings_col_group_get(PointerRNA *ptr, int *values)
 {
-	Object *ob = (Object*)ptr->data;
+	Object *ob = (Object *)ptr->data;
 	int i;
 
 	for (i = 0; i < OB_MAX_COL_MASKS; i++) {
@@ -1133,7 +1133,7 @@ static void rna_GameObjectSettings_col_group_get(PointerRNA *ptr, int *values)
 
 static void rna_GameObjectSettings_col_group_set(PointerRNA *ptr, const int *values)
 {
-	Object *ob = (Object*)ptr->data;
+	Object *ob = (Object *)ptr->data;
 	int i, tot = 0;
 
 	/* ensure we always have some group selected */
@@ -1152,7 +1152,7 @@ static void rna_GameObjectSettings_col_group_set(PointerRNA *ptr, const int *val
 
 static void rna_GameObjectSettings_col_mask_get(PointerRNA *ptr, int *values)
 {
-	Object *ob = (Object*)ptr->data;
+	Object *ob = (Object *)ptr->data;
 	int i;
 
 	for (i = 0; i < OB_MAX_COL_MASKS; i++) {
@@ -1162,7 +1162,7 @@ static void rna_GameObjectSettings_col_mask_get(PointerRNA *ptr, int *values)
 
 static void rna_GameObjectSettings_col_mask_set(PointerRNA *ptr, const int *values)
 {
-	Object *ob = (Object*)ptr->data;
+	Object *ob = (Object *)ptr->data;
 	int i, tot = 0;
 
 	/* ensure we always have some mask selected */
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index a15bbb7e988..75164a38239 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -1131,7 +1131,7 @@ static void rna_SceneRenderLayer_name_set(PointerRNA *ptr, const char *value)
 
 static char *rna_SceneRenderLayer_path(PointerRNA *ptr)
 {
-	SceneRenderLayer *srl = (SceneRenderLayer*)ptr->data;
+	SceneRenderLayer *srl = (SceneRenderLayer *)ptr->data;
 	return BLI_sprintfN("render.layers[\"%s\"]", srl->name);
 }
 
diff --git a/source/blender/nodes/intern/node_common.c b/source/blender/nodes/intern/node_common.c
index 86ef8a14c12..dc8d427c0ae 100644
--- a/source/blender/nodes/intern/node_common.c
+++ b/source/blender/nodes/intern/node_common.c
@@ -305,7 +305,7 @@ void node_group_verify(struct bNodeTree *ntree, struct bNode *node, struct ID *i
 {
 	/* check inputs and outputs, and remove or insert them */
 	if (node->id==id) {
-		bNodeTree *ngroup= (bNodeTree*)node->id;
+		bNodeTree *ngroup= (bNodeTree *)node->id;
 		group_verify_socket_list(ntree, node, &node->inputs, SOCK_IN, &ngroup->inputs);
 		group_verify_socket_list(ntree, node, &node->outputs, SOCK_OUT, &ngroup->outputs);
 	}
@@ -314,7 +314,7 @@ void node_group_verify(struct bNodeTree *ntree, struct bNode *node, struct ID *i
 struct bNodeTree *node_group_edit_get(bNode *node)
 {
 	if (node->flag & NODE_GROUP_EDIT)
-		return (bNodeTree*)node->id;
+		return (bNodeTree *)node->id;
 	else
 		return NULL;
 }
@@ -322,7 +322,7 @@ struct bNodeTree *node_group_edit_get(bNode *node)
 struct bNodeTree *node_group_edit_set(bNode *node, int edit)
 {
 	if (edit) {
-		bNodeTree *ngroup= (bNodeTree*)node->id;
+		bNodeTree *ngroup= (bNodeTree *)node->id;
 		if (ngroup) {
 			if (ngroup->id.lib)
 				ntreeMakeLocal(ngroup);
@@ -339,7 +339,7 @@ struct bNodeTree *node_group_edit_set(bNode *node, int edit)
 
 void node_group_edit_clear(bNode *node)
 {
-	bNodeTree *ngroup= (bNodeTree*)node->id;
+	bNodeTree *ngroup= (bNodeTree *)node->id;
 	bNode *inode;
 	
 	node->flag &= ~NODE_GROUP_EDIT;
diff --git a/source/blender/nodes/intern/node_exec.c b/source/blender/nodes/intern/node_exec.c
index 3cc7ebf9337..86f8f4dfbbf 100644
--- a/source/blender/nodes/intern/node_exec.c
+++ b/source/blender/nodes/intern/node_exec.c
@@ -114,13 +114,13 @@ static struct bNodeStack *setup_stack(bNodeStack *stack, bNodeSocket *sock)
 	if (sock->default_value) {
 		switch (sock->type) {
 		case SOCK_FLOAT:
-			ns->vec[0] = ((bNodeSocketValueFloat*)sock->default_value)->value;
+			ns->vec[0] = ((bNodeSocketValueFloat *)sock->default_value)->value;
 			break;
 		case SOCK_VECTOR:
-			copy_v3_v3(ns->vec, ((bNodeSocketValueVector*)sock->default_value)->value);
+			copy_v3_v3(ns->vec, ((bNodeSocketValueVector *)sock->default_value)->value);
 			break;
 		case SOCK_RGBA:
-			copy_v4_v4(ns->vec, ((bNodeSocketValueRGBA*)sock->default_value)->value);
+			copy_v4_v4(ns->vec, ((bNodeSocketValueRGBA *)sock->default_value)->value);
 			break;
 		}
 	}
diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c
index 6130fe72af3..544ccb8fda6 100644
--- a/source/blender/nodes/shader/node_shader_util.c
+++ b/source/blender/nodes/shader/node_shader_util.c
@@ -139,49 +139,49 @@ void nodeShaderSynchronizeID(bNode *node, int copyto)
 				if (copyto) {
 					switch (a) {
 						case MAT_IN_COLOR:
-							copy_v3_v3(&ma->r, ((bNodeSocketValueRGBA*)sock->default_value)->value); break;
+							copy_v3_v3(&ma->r, ((bNodeSocketValueRGBA *)sock->default_value)->value); break;
 						case MAT_IN_SPEC:
-							copy_v3_v3(&ma->specr, ((bNodeSocketValueRGBA*)sock->default_value)->value); break;
+							copy_v3_v3(&ma->specr, ((bNodeSocketValueRGBA *)sock->default_value)->value); break;
 						case MAT_IN_REFL:
-							ma->ref= ((bNodeSocketValueFloat*)sock->default_value)->value; break;
+							ma->ref= ((bNodeSocketValueFloat *)sock->default_value)->value; break;
 						case MAT_IN_MIR:
-							copy_v3_v3(&ma->mirr, ((bNodeSocketValueRGBA*)sock->default_value)->value); break;
+							copy_v3_v3(&ma->mirr, ((bNodeSocketValueRGBA *)sock->default_value)->value); break;
 						case MAT_IN_AMB:
-							ma->amb= ((bNodeSocketValueFloat*)sock->default_value)->value; break;
+							ma->amb = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
 						case MAT_IN_EMIT:
-							ma->emit= ((bNodeSocketValueFloat*)sock->default_value)->value; break;
+							ma->emit = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
 						case MAT_IN_SPECTRA:
-							ma->spectra= ((bNodeSocketValueFloat*)sock->default_value)->value; break;
+							ma->spectra = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
 						case MAT_IN_RAY_MIRROR:
-							ma->ray_mirror= ((bNodeSocketValueFloat*)sock->default_value)->value; break;
+							ma->ray_mirror = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
 						case MAT_IN_ALPHA:
-							ma->alpha= ((bNodeSocketValueFloat*)sock->default_value)->value; break;
+							ma->alpha = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
 						case MAT_IN_TRANSLUCENCY:
-							ma->translucency= ((bNodeSocketValueFloat*)sock->default_value)->value; break;
+							ma->translucency = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
 					}
 				}
 				else {
 					switch (a) {
 						case MAT_IN_COLOR:
-							copy_v3_v3(((bNodeSocketValueRGBA*)sock->default_value)->value, &ma->r); break;
+							copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, &ma->r); break;
 						case MAT_IN_SPEC:
-							copy_v3_v3(((bNodeSocketValueRGBA*)sock->default_value)->value, &ma->specr); break;
+							copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, &ma->specr); break;
 						case MAT_IN_REFL:
-							((bNodeSocketValueFloat*)sock->default_value)->value= ma->ref; break;
+							((bNodeSocketValueFloat *)sock->default_value)->value= ma->ref; break;
 						case MAT_IN_MIR:
-							copy_v3_v3(((bNodeSocketValueRGBA*)sock->default_value)->value, &ma->mirr); break;
+							copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, &ma->mirr); break;
 						case MAT_IN_AMB:
-							((bNodeSocketValueFloat*)sock->default_value)->value= ma->amb; break;
+							((bNodeSocketValueFloat *)sock->default_value)->value = ma->amb; break;
 						case MAT_IN_EMIT:
-							((bNodeSocketValueFloat*)sock->default_value)->value= ma->emit; break;
+							((bNodeSocketValueFloat *)sock->default_value)->value = ma->emit; break;
 						case MAT_IN_SPECTRA:
-							((bNodeSocketValueFloat*)sock->default_value)->value= ma->spectra; break;
+							((bNodeSocketValueFloat *)sock->default_value)->value = ma->spectra; break;
 						case MAT_IN_RAY_MIRROR:
-							((bNodeSocketValueFloat*)sock->default_value)->value= ma->ray_mirror; break;
+							((bNodeSocketValueFloat *)sock->default_value)->value = ma->ray_mirror; break;
 						case MAT_IN_ALPHA:
-							((bNodeSocketValueFloat*)sock->default_value)->value= ma->alpha; break;
+							((bNodeSocketValueFloat *)sock->default_value)->value = ma->alpha; break;
 						case MAT_IN_TRANSLUCENCY:
-							((bNodeSocketValueFloat*)sock->default_value)->value= ma->translucency; break;
+							((bNodeSocketValueFloat *)sock->default_value)->value = ma->translucency; break;
 					}
 				}
 			}
@@ -259,7 +259,7 @@ bNode *nodeGetActiveTexture(bNodeTree *ntree)
 			break;
 
 	if (node)
-		ntree= (bNodeTree*)node->id;
+		ntree = (bNodeTree *)node->id;
 
 	for (node= ntree->nodes.first; node; node= node->next)
 		if (node->flag & NODE_ACTIVE_TEXTURE)
@@ -320,7 +320,7 @@ void node_shader_gpu_tex_mapping(GPUMaterial *mat, bNode *node, GPUNodeStack *in
 	float domax= (texmap->flag & TEXMAP_CLIP_MAX) != 0;
 
 	if (domin || domax || !(texmap->flag & TEXMAP_UNIT_MATRIX)) {
-		GPUNodeLink *tmat = GPU_uniform((float*)texmap->mat);
+		GPUNodeLink *tmat = GPU_uniform((float *)texmap->mat);
 		GPUNodeLink *tmin = GPU_uniform(texmap->min);
 		GPUNodeLink *tmax = GPU_uniform(texmap->max);
 		GPUNodeLink *tdomin = GPU_uniform(&domin);
diff --git a/source/blender/nodes/shader/nodes/node_shader_common.c b/source/blender/nodes/shader/nodes/node_shader_common.c
index 688d77d8350..cf6f778bbf5 100644
--- a/source/blender/nodes/shader/nodes/node_shader_common.c
+++ b/source/blender/nodes/shader/nodes/node_shader_common.c
@@ -70,7 +70,7 @@ static void move_stack(bNodeStack *to, bNodeStack *from)
 
 static void *group_initexec(bNode *node)
 {
-	bNodeTree *ngroup= (bNodeTree*)node->id;
+	bNodeTree *ngroup = (bNodeTree *)node->id;
 	bNodeTreeExec *exec;
 	
 	if (!ngroup)
@@ -84,7 +84,7 @@ static void *group_initexec(bNode *node)
 
 static void group_freeexec(bNode *UNUSED(node), void *nodedata)
 {
-	bNodeTreeExec*gexec= (bNodeTreeExec*)nodedata;
+	bNodeTreeExec*gexec = (bNodeTreeExec *)nodedata;
 	
 	ntreeShaderEndExecTree(gexec, 0);
 }
@@ -121,7 +121,7 @@ static void group_move_outputs(bNode *node, bNodeStack **out, bNodeStack *gstack
 
 static void group_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out)
 {
-	bNodeTreeExec *exec= (bNodeTreeExec*)nodedata;
+	bNodeTreeExec *exec = (bNodeTreeExec *)nodedata;
 	bNodeThreadStack *nts;
 	
 	if (!exec)
@@ -177,7 +177,7 @@ static void group_gpu_move_outputs(bNode *node, GPUNodeStack *out, bNodeStack *g
 
 static int gpu_group_execute(GPUMaterial *mat, bNode *node, void *nodedata, GPUNodeStack *in, GPUNodeStack *out)
 {
-	bNodeTreeExec *exec= (bNodeTreeExec*)nodedata;
+	bNodeTreeExec *exec = (bNodeTreeExec *)nodedata;
 	
 	group_gpu_copy_inputs(node, in, exec->stack);
 	ntreeExecGPUNodes(exec, mat, (node->flag & NODE_GROUP_EDIT));
diff --git a/source/blender/nodes/shader/nodes/node_shader_mapping.c b/source/blender/nodes/shader/nodes/node_shader_mapping.c
index cedd3a4910c..396c1ac60bf 100644
--- a/source/blender/nodes/shader/nodes/node_shader_mapping.c
+++ b/source/blender/nodes/shader/nodes/node_shader_mapping.c
@@ -77,7 +77,7 @@ static int gpu_shader_mapping(GPUMaterial *mat, bNode *node, GPUNodeStack *in, G
 	TexMapping *texmap= node->storage;
 	float domin= (texmap->flag & TEXMAP_CLIP_MIN) != 0;
 	float domax= (texmap->flag & TEXMAP_CLIP_MAX) != 0;
-	GPUNodeLink *tmat = GPU_uniform((float*)texmap->mat);
+	GPUNodeLink *tmat = GPU_uniform((float *)texmap->mat);
 	GPUNodeLink *tmin = GPU_uniform(texmap->min);
 	GPUNodeLink *tmax = GPU_uniform(texmap->max);
 	GPUNodeLink *tdomin = GPU_uniform(&domin);
diff --git a/source/blender/python/generic/py_capi_utils.h b/source/blender/python/generic/py_capi_utils.h
index 935a5f9030b..45c9247d710 100644
--- a/source/blender/python/generic/py_capi_utils.h
+++ b/source/blender/python/generic/py_capi_utils.h
@@ -53,7 +53,7 @@ void PyC_MainModule_Restore(PyObject *main_mod);
 
 void PyC_SetHomePath(const char *py_path_bundle);
 
-#define PYC_INTERPRETER_ACTIVE (((PyThreadState*)_Py_atomic_load_relaxed(&_PyThreadState_Current)) != NULL)
+#define PYC_INTERPRETER_ACTIVE (((PyThreadState *)_Py_atomic_load_relaxed(&_PyThreadState_Current)) != NULL)
 
 void *PyC_RNA_AsPointer(PyObject *value, const char *type_name);
 
diff --git a/source/blender/render/intern/raytrace/rayobject_instance.cpp b/source/blender/render/intern/raytrace/rayobject_instance.cpp
index f9ed012b117..01e592cba0c 100644
--- a/source/blender/render/intern/raytrace/rayobject_instance.cpp
+++ b/source/blender/render/intern/raytrace/rayobject_instance.cpp
@@ -173,13 +173,13 @@ static int  RE_rayobject_instance_intersect(RayObject *o, Isect *isec)
 
 static void RE_rayobject_instance_free(RayObject *o)
 {
-	InstanceRayObject *obj = (InstanceRayObject*)o;
+	InstanceRayObject *obj = (InstanceRayObject *)o;
 	MEM_freeN(obj);
 }
 
 static float RE_rayobject_instance_cost(RayObject *o)
 {
-	InstanceRayObject *obj = (InstanceRayObject*)o;
+	InstanceRayObject *obj = (InstanceRayObject *)o;
 	return RE_rayobject_cost(obj->target) + RE_COST_INSTANCE;
 }
 
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index fc1a9b2f755..76d67765424 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -161,7 +161,7 @@ static HaloRen *initstar(Render *re, ObjectRen *obr, const float vec[3], float h
  */
 
 void RE_make_stars(Render *re, Scene *scenev3d, void (*initfunc)(void),
-                   void (*vertexfunc)(float*),  void (*termfunc)(void))
+                   void (*vertexfunc)(float *),  void (*termfunc)(void))
 {
 	extern unsigned char hash[512];
 	ObjectRen *obr= NULL;
diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c
index fb9eb59cbbf..bef5902588c 100644
--- a/source/blender/render/intern/source/rayshade.c
+++ b/source/blender/render/intern/source/rayshade.c
@@ -81,7 +81,7 @@ extern struct Render R;
 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
 static int test_break(void *data)
 {
-	Render *re = (Render*)data;
+	Render *re = (Render *)data;
 	return re->test_break(re->tbh);
 }
 
@@ -250,9 +250,9 @@ RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi)
 		//Create Ray cast accelaration structure
 		raytree = rayobject_create( re,  re->r.raytrace_structure, faces );
 		if (  (re->r.raytrace_options & R_RAYTRACE_USE_LOCAL_COORDS) )
-			vlakprimitive = obr->rayprimitives = (VlakPrimitive*)MEM_callocN(faces*sizeof(VlakPrimitive), "ObjectRen primitives");
+			vlakprimitive = obr->rayprimitives = (VlakPrimitive *)MEM_callocN(faces * sizeof(VlakPrimitive), "ObjectRen primitives");
 		else
-			face = obr->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "ObjectRen faces");
+			face = obr->rayfaces = (RayFace *)MEM_callocN(faces * sizeof(RayFace), "ObjectRen faces");
 
 		obr->rayobi = obi;
 		
@@ -345,10 +345,10 @@ static void makeraytree_single(Render *re)
 	raytree = re->raytree = rayobject_create( re, re->r.raytrace_structure, faces+special );
 
 	if ( (re->r.raytrace_options & R_RAYTRACE_USE_LOCAL_COORDS) ) {
-		vlakprimitive = re->rayprimitives = (VlakPrimitive*)MEM_callocN(faces*sizeof(VlakPrimitive), "Raytrace vlak-primitives");
+		vlakprimitive = re->rayprimitives = (VlakPrimitive *)MEM_callocN(faces * sizeof(VlakPrimitive), "Raytrace vlak-primitives");
 	}
 	else {
-		face = re->rayfaces	= (RayFace*)MEM_callocN(faces*sizeof(RayFace), "Render ray faces");
+		face = re->rayfaces	= (RayFace *)MEM_callocN(faces * sizeof(RayFace), "Render ray faces");
 	}
 	
 	for (obi=re->instancetable.first; obi; obi=obi->next)
@@ -496,8 +496,8 @@ static void shade_ray_set_derivative(ShadeInput *shi)
 
 void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr)
 {
-	ObjectInstanceRen *obi= (ObjectInstanceRen*)is->hit.ob;
-	VlakRen *vlr= (VlakRen*)is->hit.face;
+	ObjectInstanceRen *obi = (ObjectInstanceRen *)is->hit.ob;
+	VlakRen *vlr = (VlakRen *)is->hit.face;
 	
 	/* set up view vector */
 	copy_v3_v3(shi->view, is->dir);
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index bd0061c0e68..9f171ba71db 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -1172,7 +1172,7 @@ typedef struct ZbufSolidData {
 
 static void make_pixelstructs(RenderPart *pa, ZSpan *zspan, int sample, void *data)
 {
-	ZbufSolidData *sdata= (ZbufSolidData*)data;
+	ZbufSolidData *sdata = (ZbufSolidData *)data;
 	ListBase *lb= sdata->psmlist;
 	intptr_t *rd= pa->rectdaps;
 	int *ro= zspan->recto;
@@ -1740,7 +1740,7 @@ void zbufshade_sss_tile(RenderPart *pa)
 #if 0
 			if (rs) {
 				/* for each sample in this pixel, shade it */
-				for (ps=(PixStr*)*rs; ps; ps=ps->next) {
+				for (ps = (PixStr *)(*rs); ps; ps=ps->next) {
 					ObjectInstanceRen *obi= &re->objectinstance[ps->obi];
 					ObjectRen *obr= obi->obr;
 					vlr= RE_findOrAddVlak(obr, (ps->facenr-1) & RE_QUAD_MASK);
@@ -2461,8 +2461,8 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v)
 
 		/* if hit, we shade from the new point, otherwise from point one starting face */
 		if (hit) {
-			obi= (ObjectInstanceRen*)minisec.hit.ob;
-			vlr= (VlakRen*)minisec.hit.face;
+			obi = (ObjectInstanceRen *)minisec.hit.ob;
+			vlr = (VlakRen *)minisec.hit.face;
 			quad= (minisec.isect == 2);
 			copy_v3_v3(shi->co, minco);
 			
diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c
index e189d8bdaea..a4e5b9eb7a2 100644
--- a/source/blender/render/intern/source/renderdatabase.c
+++ b/source/blender/render/intern/source/renderdatabase.c
@@ -370,7 +370,7 @@ RadFace **RE_vlakren_get_radface(ObjectRen *obr, VlakRen *vlak, int verify)
 	radface= obr->vlaknodes[nr].radface;
 	if (radface==NULL) {
 		if (verify) 
-			radface= obr->vlaknodes[nr].radface= MEM_callocN(256*RE_RADFACE_ELEMS*sizeof(void*), "radface table");
+			radface = obr->vlaknodes[nr].radface= MEM_callocN(256 * RE_RADFACE_ELEMS * sizeof(void *), "radface table");
 		else
 			return NULL;
 	}
@@ -888,9 +888,9 @@ HaloRen *RE_findOrAddHalo(ObjectRen *obr, int nr)
 		//	TABLEINITSIZE, obr->blohalen+TABLEINITSIZE );
 		temp=obr->bloha;
 		
-		obr->bloha=(HaloRen**)MEM_callocN(sizeof(void*)*(obr->blohalen+TABLEINITSIZE), "Bloha");
-		if (temp) memcpy(obr->bloha, temp, obr->blohalen*sizeof(void*));
-		memset(&(obr->bloha[obr->blohalen]), 0, TABLEINITSIZE*sizeof(void*));
+		obr->bloha = (HaloRen**)MEM_callocN(sizeof(void *) * (obr->blohalen + TABLEINITSIZE), "Bloha");
+		if (temp) memcpy(obr->bloha, temp, obr->blohalen*sizeof(void *));
+		memset(&(obr->bloha[obr->blohalen]), 0, TABLEINITSIZE * sizeof(void *));
 		obr->blohalen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
 		if (temp) MEM_freeN(temp);
 	}
diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c
index 078c11a2061..87912f546e8 100644
--- a/source/blender/render/intern/source/shadbuf.c
+++ b/source/blender/render/intern/source/shadbuf.c
@@ -812,7 +812,7 @@ void makeshadowbuf(Render *re, LampRen *lar)
 
 static void *do_shadow_thread(void *re_v)
 {
-	Render *re= (Render*)re_v;
+	Render *re = (Render *)re_v;
 	LampRen *lar;
 
 	do {
diff --git a/source/blender/render/intern/source/strand.c b/source/blender/render/intern/source/strand.c
index 569bac29205..a37ffb1eb28 100644
--- a/source/blender/render/intern/source/strand.c
+++ b/source/blender/render/intern/source/strand.c
@@ -522,7 +522,7 @@ static APixstrand *addpsAstrand(ZSpan *zspan)
 
 static void do_strand_fillac(void *handle, int x, int y, float u, float v, float z)
 {
-	StrandPart *spart= (StrandPart*)handle;
+	StrandPart *spart= (StrandPart *)handle;
 	StrandShadeCache *cache= spart->cache;
 	StrandSegment *sseg= spart->segment;
 	APixstrand *apn, *apnew;
diff --git a/source/blender/render/intern/source/volume_precache.c b/source/blender/render/intern/source/volume_precache.c
index 549148f4e29..a9db197ed48 100644
--- a/source/blender/render/intern/source/volume_precache.c
+++ b/source/blender/render/intern/source/volume_precache.c
@@ -493,7 +493,7 @@ typedef struct VolPrecacheQueue {
  */
 static void *vol_precache_part(void *data)
 {
-	VolPrecacheQueue *queue = (VolPrecacheQueue*)data;
+	VolPrecacheQueue *queue = (VolPrecacheQueue *)data;
 	VolPrecachePart *pa;
 
 	while ((pa = BLI_thread_queue_pop(queue->work))) {
diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index 576c0f341b1..ce0576c68d1 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -200,7 +200,7 @@ void WM_operator_stack_clear(struct bContext *C) {}
 void WM_autosave_init(struct bContext *C) {}
 void WM_jobs_kill_all_except(struct wmWindowManager *wm) {}
 
-char *WM_clipboard_text_get(int selection) {return (char*)0;}
+char *WM_clipboard_text_get(int selection) {return (char *)0;}
 void WM_clipboard_text_set(char *buf, int selection) {}
 
 void                WM_uilisttype_init(void) {}
-- 
cgit v1.2.3


From e9ba345c46c93a193193f01d4bfac714a666d384 Mon Sep 17 00:00:00 2001
From: Stuart Broadfoot 
Date: Fri, 28 Dec 2012 14:21:30 +0000
Subject: New feature

Patch [#33445] - Experimental Cycles Hair Rendering (CPU only)

This patch allows hair data to be exported to cycles and introduces a new line segment primitive to render with.

The UI appears under the particle tab and there is a new hair info node available.

It is only available under the experimental feature set and for cpu rendering.
---
 source/blender/blenkernel/BKE_node.h               |   1 +
 source/blender/blenkernel/intern/node.c            |   1 +
 .../blender/makesrna/intern/rna_nodetree_types.h   |   1 +
 source/blender/makesrna/intern/rna_particle.c      | 267 ++++++++++++++++++++-
 source/blender/nodes/CMakeLists.txt                |   1 +
 source/blender/nodes/NOD_shader.h                  |   1 +
 .../nodes/shader/nodes/node_shader_hair_info.c     |  58 +++++
 7 files changed, 328 insertions(+), 2 deletions(-)
 create mode 100644 source/blender/nodes/shader/nodes/node_shader_hair_info.c

(limited to 'source')

diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index b8f168cbdea..0a2f757b38e 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -557,6 +557,7 @@ struct ShadeResult;
 #define SH_NODE_BSDF_REFRACTION			173
 #define SH_NODE_TANGENT					174
 #define SH_NODE_NORMAL_MAP				175
+#define SH_NODE_HAIR_INFO				176
 
 /* custom defines options for Material node */
 #define SH_NODE_MAT_DIFF   1
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index a6ec1f33edc..84e280034ed 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -2323,6 +2323,7 @@ static void registerShaderNodes(bNodeTreeType *ttype)
 	register_node_type_sh_layer_weight(ttype);
 	register_node_type_sh_tex_coord(ttype);
 	register_node_type_sh_particle_info(ttype);
+	register_node_type_sh_hair_info(ttype);
 	register_node_type_sh_bump(ttype);
 	register_node_type_sh_script(ttype);
 	register_node_type_sh_tangent(ttype);
diff --git a/source/blender/makesrna/intern/rna_nodetree_types.h b/source/blender/makesrna/intern/rna_nodetree_types.h
index de535156199..46f2306f284 100644
--- a/source/blender/makesrna/intern/rna_nodetree_types.h
+++ b/source/blender/makesrna/intern/rna_nodetree_types.h
@@ -84,6 +84,7 @@ DefNode( ShaderNode,     SH_NODE_LIGHT_PATH,         0,                      "LI
 DefNode( ShaderNode,     SH_NODE_LIGHT_FALLOFF,      0,                      "LIGHT_FALLOFF",      LightFalloff,     "Light Falloff",     ""       )
 DefNode( ShaderNode,     SH_NODE_OBJECT_INFO,        0,                      "OBJECT_INFO",        ObjectInfo,       "Object Info",       ""       )
 DefNode( ShaderNode,     SH_NODE_PARTICLE_INFO,      0,                      "PARTICLE_INFO",      ParticleInfo,     "Particle Info",     ""       )
+DefNode( ShaderNode,     SH_NODE_HAIR_INFO,          0,                      "HAIR_INFO",          HairInfo,         "Hair Info",         ""       )
 DefNode( ShaderNode,     SH_NODE_BUMP,               0,                      "BUMP",               Bump,             "Bump",              ""       )
 DefNode( ShaderNode,     SH_NODE_NORMAL_MAP,         def_sh_normal_map,      "NORMAL_MAP",         NormalMap,        "Normal Map",        ""       )
 DefNode( ShaderNode,     SH_NODE_TANGENT,            def_sh_tangent,         "TANGENT",            Tangent,          "Tangent",           ""       )
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index 93f940b1aa3..b0b68b11ec9 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -238,7 +238,220 @@ static void rna_ParticleHairKey_location_object_set(PointerRNA *ptr, const float
 	}
 }
 
-/* property update functions */
+static void rna_ParticleHairKey_co_object(HairKey *hairkey, Object *object, ParticleSystemModifierData *modifier, ParticleData *particle,
+                                             float n_co[3])
+{
+
+	DerivedMesh *hairdm = (modifier->psys->flag & PSYS_HAIR_DYNAMICS) ? modifier->psys->hair_out_dm : NULL;
+	if (particle) {
+		if (hairdm) {
+			MVert *mvert = CDDM_get_vert(hairdm, particle->hair_index + (hairkey - particle->hair));
+			copy_v3_v3(n_co, mvert->co);
+		}
+		else {
+			float hairmat[4][4];
+			psys_mat_hair_to_object(object, modifier->dm, modifier->psys->part->from, particle, hairmat);
+			copy_v3_v3(n_co, hairkey->co);
+			mul_m4_v3(hairmat, n_co);
+		}
+	}
+	else {
+		zero_v3(n_co);
+	}
+}
+
+static void rna_Particle_uv_on_emitter(ParticleData *particle, ParticleSystemModifierData *modifier, float n_uv[2])
+{
+	/*psys_particle_on_emitter(psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co, nor, 0, 0, sd.orco, 0);*/
+
+	/* get uvco & mcol */
+	int num = particle->num_dmcache;
+	int from = modifier->psys->part->from;
+
+	if (num == DMCACHE_NOTFOUND)
+		if (particle->num < modifier->dm->getNumTessFaces(modifier->dm))
+			num = particle->num;
+
+	/* get uvco */
+	if (n_uv && ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) {
+		
+		if (num != DMCACHE_NOTFOUND) {
+			MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
+			MTFace *mtface = (MTFace*)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, 0);
+			mtface += num;
+			
+			psys_interpolate_uvs(mtface, mface->v4, particle->fuv, n_uv);
+		}
+		else {
+			n_uv[0] = 0.0f;
+			n_uv[1] = 0.0f;
+		}
+	}
+}
+
+static void rna_ParticleSystem_co_hair(ParticleSystem *particlesystem, Object *object, ParticleSystemModifierData *modifier, int particle_no, int step,
+                                             float n_co[3])
+{
+	ParticleSettings *part = 0;
+	ParticleData *pars = 0;
+	ParticleCacheKey *cache = 0;
+	int totchild=0;
+	int path_nbr=0;
+	int totpart;
+	int max_k = 0;
+
+	if (particlesystem == NULL)
+		return;
+
+	part = particlesystem->part;
+	pars = particlesystem->particles;
+
+	if (part == NULL || pars == NULL || !psys_check_enabled(object, particlesystem))
+		return;
+	
+	if (part->ren_as==PART_DRAW_OB || part->ren_as==PART_DRAW_GR || part->ren_as==PART_DRAW_NOT)
+		return;
+
+	totchild = particlesystem->totchild * part->disp / 100;
+
+	/* can happen for disconnected/global hair */
+	if (part->type == PART_HAIR && !particlesystem->childcache)
+		totchild = 0;
+
+	totpart = particlesystem->totpart;
+
+	if (particle_no >= totpart + totchild)
+		return;
+
+	if (part->ren_as == PART_DRAW_PATH && particlesystem->pathcache)
+		path_nbr=(int)pow(2.0, part->draw_step);
+
+	if (particle_nopathcache[particle_no];
+			max_k = (int)cache->steps;
+		}
+
+	}
+	else {
+
+		if (path_nbr) {
+			cache = particlesystem->childcache[particle_no-totpart];
+
+			if (cache->steps < 0)
+				max_k = 0;
+			else
+				max_k = (int)cache->steps;
+		}
+	}
+
+	/*strands key loop data stored in cache + step->co*/
+	if (path_nbr) {
+		if (step>=0 && step<=path_nbr) {
+			if (step<=max_k)
+				copy_v3_v3(n_co, (cache+step)->co);
+		}
+	}
+
+}
+
+static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, ParticleSystemModifierData *modifier, ParticleData *particle, int particle_no,
+                                              float n_uv[2])
+{
+	ParticleSettings *part = 0;
+	int totpart;
+	int totchild = 0;
+	int num;
+
+	/* 1. check that everything is ok & updated */
+	if (particlesystem == NULL)
+		return;
+
+	part=particlesystem->part;
+
+		totchild = particlesystem->totchild;
+
+	/* can happen for disconnected/global hair */
+	if (part->type == PART_HAIR && !particlesystem->childcache)
+		totchild = 0;
+
+	totpart = particlesystem->totpart;
+
+	if (particle_no >= totpart + totchild)
+		return;
+
+/* 3. start creating renderable things */
+	/* setup per particle individual stuff */
+	if (particle_nonum_dmcache;
+
+		if (num == DMCACHE_NOTFOUND)
+			if (particle->num < modifier->dm->getNumTessFaces(modifier->dm))
+				num = particle->num;
+
+		if (n_uv && ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
+			if (num != DMCACHE_NOTFOUND) {
+				MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
+				MTFace *mtface = (MTFace*)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, 0);
+				mtface += num;
+				
+				psys_interpolate_uvs(mtface, mface->v4, particle->fuv, n_uv);
+			}
+			else {
+				n_uv[0] = 0.0f;
+				n_uv[1] = 0.0f;
+			}
+		}
+	}
+	else {
+		ChildParticle *cpa = particlesystem->child + particle_no-totpart;
+
+		num = cpa->num;
+
+		/* get uvco & mcol */
+		if (part->childtype == PART_CHILD_FACES) {
+			if (n_uv && ELEM(PART_FROM_FACE, PART_FROM_FACE, PART_FROM_VOLUME)) {
+				if (cpa->num != DMCACHE_NOTFOUND) {
+					MFace *mface = modifier->dm->getTessFaceData(modifier->dm, cpa->num, CD_MFACE);
+					MTFace *mtface = (MTFace*)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, 0);
+					mtface += cpa->num;
+					
+					psys_interpolate_uvs(mtface, mface->v4, cpa->fuv, n_uv);
+				}
+				else {
+					n_uv[0] = 0.0f;
+					n_uv[1] = 0.0f;
+				}
+			}
+		}
+		else {
+			ParticleData *parent = particlesystem->particles + cpa->parent;
+			num = parent->num_dmcache;
+
+			if (num == DMCACHE_NOTFOUND)
+				if (parent->num < modifier->dm->getNumTessFaces(modifier->dm))
+					num = parent->num;
+
+			if (n_uv && ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
+				if (num != DMCACHE_NOTFOUND) {
+					MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
+					MTFace *mtface = (MTFace*)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, 0);
+					mtface += num;
+					
+					psys_interpolate_uvs(mtface, mface->v4, parent->fuv, n_uv);
+				}
+				else {
+					n_uv[0] = 0.0f;
+					n_uv[1] = 0.0f;
+				}
+			}
+		}
+	}
+}
+
 static void particle_recalc(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr, short flag)
 {
 	if (ptr->type == &RNA_ParticleSystem) {
@@ -905,6 +1118,7 @@ static void rna_def_particle_hair_key(BlenderRNA *brna)
 {
 	StructRNA *srna;
 	PropertyRNA *prop;
+	FunctionRNA *func;
 
 	srna = RNA_def_struct(brna, "ParticleHairKey", NULL);
 	RNA_def_struct_sdna(srna, "HairKey");
@@ -928,6 +1142,19 @@ static void rna_def_particle_hair_key(BlenderRNA *brna)
 	RNA_def_property_ui_text(prop, "Location",
 	                         "Location of the hair key in its internal coordinate system, "
 	                         "relative to the emitting face");
+
+	/* Aided co func */
+	func = RNA_def_function(srna, "co_object", "rna_ParticleHairKey_co_object");
+	RNA_def_function_ui_description(func, "Obtain hairkey location with particle and modifier data");
+
+	prop = RNA_def_pointer(func, "object", "Object", "", "Object");
+	prop = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier");
+	prop = RNA_def_pointer(func, "particle", "Particle", "", "hair particle");
+	
+	prop = RNA_def_float_vector(func, "co", 3, NULL, -FLT_MAX, FLT_MAX, "Co",
+	                            "Exported hairkey location", -1e4, 1e4);
+	RNA_def_property_flag(prop, PROP_THICK_WRAP);
+	RNA_def_function_output(func, prop);
 }
 
 static void rna_def_particle_key(BlenderRNA *brna)
@@ -979,6 +1206,7 @@ static void rna_def_particle(BlenderRNA *brna)
 {
 	StructRNA *srna;
 	PropertyRNA *prop;
+	FunctionRNA *func;
 
 	static EnumPropertyItem alive_items[] = {
 		/*{PARS_KILLED, "KILLED", 0, "Killed", ""}, */
@@ -1083,6 +1311,15 @@ static void rna_def_particle(BlenderRNA *brna)
 	RNA_def_property_ui_text(prop, "Alive State", "");
 
 /*	short rt2; */
+
+/* UVs */
+	func = RNA_def_function(srna, "uv_on_emitter", "rna_Particle_uv_on_emitter");
+	RNA_def_function_ui_description(func, "Obtain uv for particle on derived mesh");
+	prop = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier");
+	prop = RNA_def_property(func, "uv", PROP_FLOAT, PROP_COORDS);
+	RNA_def_property_array(prop, 2);
+	RNA_def_property_flag(prop, PROP_THICK_WRAP);
+	RNA_def_function_output(func, prop);
 }
 
 static void rna_def_particle_dupliweight(BlenderRNA *brna)
@@ -2696,6 +2933,7 @@ static void rna_def_particle_system(BlenderRNA *brna)
 {
 	StructRNA *srna;
 	PropertyRNA *prop;
+	FunctionRNA *func;
 
 	srna = RNA_def_struct(brna, "ParticleSystem", NULL);
 	RNA_def_struct_ui_text(srna, "Particle System", "Particle system in an object");
@@ -2793,7 +3031,6 @@ static void rna_def_particle_system(BlenderRNA *brna)
 	                           "rna_ParticleSystem_active_particle_target_index_range");
 	RNA_def_property_ui_text(prop, "Active Particle Target Index", "");
 
-
 	/* billboard */
 	prop = RNA_def_property(srna, "billboard_normal_uv", PROP_STRING, PROP_NONE);
 	RNA_def_property_string_sdna(prop, NULL, "bb_uvname[0]");
@@ -2995,6 +3232,32 @@ static void rna_def_particle_system(BlenderRNA *brna)
 	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
 
 	RNA_def_struct_path_func(srna, "rna_ParticleSystem_path");
+
+	/* extract cached hair location data */
+	func = RNA_def_function(srna, "co_hair", "rna_ParticleSystem_co_hair");
+	RNA_def_function_ui_description(func, "Obtain cache hair data");
+
+	prop = RNA_def_pointer(func, "object", "Object", "", "Object");
+	prop = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier");
+	prop = RNA_def_int(func, "particle_no", 0, INT_MIN, INT_MAX, "Particle no", "", INT_MIN, INT_MAX);
+	prop = RNA_def_int(func, "step", 0, INT_MIN, INT_MAX, "step no", "", INT_MIN, INT_MAX);
+
+	prop = RNA_def_float_vector(func, "co", 3, NULL, -FLT_MAX, FLT_MAX, "Co",
+	                            "Exported hairkey location", -1e4, 1e4);
+	RNA_def_property_flag(prop, PROP_THICK_WRAP);
+	RNA_def_function_output(func, prop);
+
+	/* extract hair UVs */
+	func = RNA_def_function(srna, "uv_on_emitter", "rna_ParticleSystem_uv_on_emitter");
+	RNA_def_function_ui_description(func, "Obtain uv for all particles");
+	prop = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier");
+	prop = RNA_def_pointer(func, "particle", "Particle", "", "Particle");
+	prop = RNA_def_int(func, "particle_no", 0, INT_MIN, INT_MAX, "Particle no", "", INT_MIN, INT_MAX);
+	prop = RNA_def_property(func, "uv", PROP_FLOAT, PROP_COORDS);
+	RNA_def_property_array(prop, 2);
+	RNA_def_property_flag(prop, PROP_THICK_WRAP);
+	RNA_def_function_output(func, prop);
+
 }
 
 void RNA_def_particle(BlenderRNA *brna)
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 141a3680df2..a7b491cf42b 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -168,6 +168,7 @@ set(SRC
 	shader/nodes/node_shader_mix_shader.c
 	shader/nodes/node_shader_normal_map.c
 	shader/nodes/node_shader_object_info.c
+	shader/nodes/node_shader_hair_info.c
 	shader/nodes/node_shader_output_lamp.c
 	shader/nodes/node_shader_output_material.c
 	shader/nodes/node_shader_output_world.c
diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h
index 74135776c9c..0a7a11e4506 100644
--- a/source/blender/nodes/NOD_shader.h
+++ b/source/blender/nodes/NOD_shader.h
@@ -78,6 +78,7 @@ void register_node_type_sh_fresnel(struct bNodeTreeType *ttype);
 void register_node_type_sh_layer_weight(struct bNodeTreeType *ttype);
 void register_node_type_sh_tex_coord(struct bNodeTreeType *ttype);
 void register_node_type_sh_particle_info(struct bNodeTreeType *ttype);
+void register_node_type_sh_hair_info(struct bNodeTreeType *ttype);
 void register_node_type_sh_script(struct bNodeTreeType *ttype);
 void register_node_type_sh_normal_map(struct bNodeTreeType *ttype);
 void register_node_type_sh_tangent(struct bNodeTreeType *ttype);
diff --git a/source/blender/nodes/shader/nodes/node_shader_hair_info.c b/source/blender/nodes/shader/nodes/node_shader_hair_info.c
new file mode 100644
index 00000000000..8e6f40faf24
--- /dev/null
+++ b/source/blender/nodes/shader/nodes/node_shader_hair_info.c
@@ -0,0 +1,58 @@
+/*
+ * ***** 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) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../node_shader_util.h"
+
+static bNodeSocketTemplate outputs[] = {
+	{	SOCK_FLOAT,  0, N_("Is Strand"),			0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+	{	SOCK_FLOAT,  0, N_("Intercept"),		0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+	{	SOCK_FLOAT,  0, N_("Thickness"),			0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+	{	SOCK_VECTOR, 0, N_("Tangent Normal"),	0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+	{	-1, 0, ""	}
+};
+
+static int node_shader_gpu_curve_attrib(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+{
+	return GPU_stack_link(mat, "NODE_HAIR_INFO", in, out);
+}
+
+/* node type definition */
+void register_node_type_sh_hair_info(bNodeTreeType *ttype)
+{
+	static bNodeType ntype;
+
+	node_type_base(ttype, &ntype, SH_NODE_HAIR_INFO, "Hair Info", NODE_CLASS_INPUT, 0);
+	node_type_compatibility(&ntype, NODE_NEW_SHADING);
+	node_type_socket_templates(&ntype, NULL, outputs);
+	node_type_size(&ntype, 150, 60, 200);
+	node_type_init(&ntype, NULL);
+	node_type_storage(&ntype, "", NULL, NULL);
+	node_type_exec(&ntype, NULL);
+	node_type_gpu(&ntype, node_shader_gpu_curve_attrib);
+
+	nodeRegisterType(ttype, &ntype);
+}
-- 
cgit v1.2.3


From c2dfcd9208a6afe03b108e682cc4d47fadb5f2bf Mon Sep 17 00:00:00 2001
From: Brecht Van Lommel 
Date: Fri, 28 Dec 2012 14:46:32 +0000
Subject: Convert alpha node: rename "key alpha" to "straight alpha" for
 consistency.

---
 source/blender/compositor/CMakeLists.txt           |  8 +--
 .../compositor/nodes/COM_ConvertAlphaNode.cpp      |  8 +--
 .../operations/COM_ConvertKeyToPremulOperation.cpp | 55 --------------------
 .../operations/COM_ConvertKeyToPremulOperation.h   | 49 ------------------
 .../operations/COM_ConvertPremulToKeyOperation.cpp | 60 ----------------------
 .../operations/COM_ConvertPremulToKeyOperation.h   | 48 -----------------
 .../COM_ConvertPremulToStraightOperation.cpp       | 60 ++++++++++++++++++++++
 .../COM_ConvertPremulToStraightOperation.h         | 48 +++++++++++++++++
 .../COM_ConvertStraightToPremulOperation.cpp       | 55 ++++++++++++++++++++
 .../COM_ConvertStraightToPremulOperation.h         | 49 ++++++++++++++++++
 source/blender/makesrna/intern/rna_nodetree.c      |  4 +-
 11 files changed, 222 insertions(+), 222 deletions(-)
 delete mode 100644 source/blender/compositor/operations/COM_ConvertKeyToPremulOperation.cpp
 delete mode 100644 source/blender/compositor/operations/COM_ConvertKeyToPremulOperation.h
 delete mode 100644 source/blender/compositor/operations/COM_ConvertPremulToKeyOperation.cpp
 delete mode 100644 source/blender/compositor/operations/COM_ConvertPremulToKeyOperation.h
 create mode 100644 source/blender/compositor/operations/COM_ConvertPremulToStraightOperation.cpp
 create mode 100644 source/blender/compositor/operations/COM_ConvertPremulToStraightOperation.h
 create mode 100644 source/blender/compositor/operations/COM_ConvertStraightToPremulOperation.cpp
 create mode 100644 source/blender/compositor/operations/COM_ConvertStraightToPremulOperation.h

(limited to 'source')

diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt
index 8259cb6f297..0e8ddf4068c 100644
--- a/source/blender/compositor/CMakeLists.txt
+++ b/source/blender/compositor/CMakeLists.txt
@@ -491,10 +491,10 @@ set(SRC
 	operations/COM_ColorMatteOperation.h
 	operations/COM_ChannelMatteOperation.cpp
 	operations/COM_ChannelMatteOperation.h
-	operations/COM_ConvertPremulToKeyOperation.cpp
-	operations/COM_ConvertPremulToKeyOperation.h
-	operations/COM_ConvertKeyToPremulOperation.cpp
-	operations/COM_ConvertKeyToPremulOperation.h
+	operations/COM_ConvertPremulToStraightOperation.cpp
+	operations/COM_ConvertPremulToStraightOperation.h
+	operations/COM_ConvertStraightToPremulOperation.cpp
+	operations/COM_ConvertStraightToPremulOperation.h
 
 	operations/COM_ReadBufferOperation.cpp
 	operations/COM_ReadBufferOperation.h
diff --git a/source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp b/source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp
index 254dfb7b9c7..a7149cc63b2 100644
--- a/source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp
+++ b/source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp
@@ -20,8 +20,8 @@
  */
 
 #include "COM_ConvertAlphaNode.h"
-#include "COM_ConvertPremulToKeyOperation.h"
-#include "COM_ConvertKeyToPremulOperation.h"
+#include "COM_ConvertPremulToStraightOperation.h"
+#include "COM_ConvertStraightToPremulOperation.h"
 #include "COM_ExecutionSystem.h"
 
 void ConvertAlphaNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
@@ -31,10 +31,10 @@ void ConvertAlphaNode::convertToOperations(ExecutionSystem *graph, CompositorCon
 
 	/* value hardcoded in rna_nodetree.c */
 	if (node->custom1 == 1) {
-		operation = new ConvertPremulToKeyOperation();
+		operation = new ConvertPremulToStraightOperation();
 	}
 	else {
-		operation = new ConvertKeyToPremulOperation();
+		operation = new ConvertStraightToPremulOperation();
 	}
 
 	this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph);
diff --git a/source/blender/compositor/operations/COM_ConvertKeyToPremulOperation.cpp b/source/blender/compositor/operations/COM_ConvertKeyToPremulOperation.cpp
deleted file mode 100644
index 4497db52a0f..00000000000
--- a/source/blender/compositor/operations/COM_ConvertKeyToPremulOperation.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2012, 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_ConvertKeyToPremulOperation.h"
-#include "BLI_math.h"
-
-ConvertKeyToPremulOperation::ConvertKeyToPremulOperation() : NodeOperation()
-{
-	this->addInputSocket(COM_DT_COLOR);
-	this->addOutputSocket(COM_DT_COLOR);
-
-	this->m_inputColor = NULL;
-}
-
-void ConvertKeyToPremulOperation::initExecution()
-{
-	this->m_inputColor = getInputSocketReader(0);
-}
-
-void ConvertKeyToPremulOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
-	float inputValue[4];
-	float alpha;
-
-	this->m_inputColor->read(inputValue, x, y, sampler);
-	alpha = inputValue[3];
-
-	mul_v3_v3fl(output, inputValue, alpha);
-
-	/* never touches the alpha */
-	output[3] = alpha;
-}
-
-void ConvertKeyToPremulOperation::deinitExecution()
-{
-	this->m_inputColor = NULL;
-}
diff --git a/source/blender/compositor/operations/COM_ConvertKeyToPremulOperation.h b/source/blender/compositor/operations/COM_ConvertKeyToPremulOperation.h
deleted file mode 100644
index 502674e26db..00000000000
--- a/source/blender/compositor/operations/COM_ConvertKeyToPremulOperation.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2012, 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_ConvertKeyToPremulOperation_h
-#define _COM_ConvertKeyToPremulOperation_h
-#include "COM_NodeOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class ConvertKeyToPremulOperation : public NodeOperation {
-private:
-	SocketReader *m_inputColor;
-public:
-	/**
-	 * Default constructor
-	 */
-	ConvertKeyToPremulOperation();
-
-	/**
-	 * the inner loop of this program
-	 */
-	void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
-	void initExecution();
-	void deinitExecution();
-
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_ConvertPremulToKeyOperation.cpp b/source/blender/compositor/operations/COM_ConvertPremulToKeyOperation.cpp
deleted file mode 100644
index b92da4c324f..00000000000
--- a/source/blender/compositor/operations/COM_ConvertPremulToKeyOperation.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2012, 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_ConvertPremulToKeyOperation.h"
-#include "BLI_math.h"
-
-ConvertPremulToKeyOperation::ConvertPremulToKeyOperation() : NodeOperation()
-{
-	this->addInputSocket(COM_DT_COLOR);
-	this->addOutputSocket(COM_DT_COLOR);
-
-	this->m_inputColor = NULL;
-}
-
-void ConvertPremulToKeyOperation::initExecution()
-{
-	this->m_inputColor = getInputSocketReader(0);
-}
-
-void ConvertPremulToKeyOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
-	float inputValue[4];
-	float alpha;
-
-	this->m_inputColor->read(inputValue, x, y, sampler);
-	alpha = inputValue[3];
-
-	if (fabsf(alpha) < 1e-5f) {
-		zero_v3(output);
-	}
-	else {
-		mul_v3_v3fl(output, inputValue, 1.0f / alpha);
-	}
-
-	/* never touches the alpha */
-	output[3] = alpha;
-}
-
-void ConvertPremulToKeyOperation::deinitExecution()
-{
-	this->m_inputColor = NULL;
-}
diff --git a/source/blender/compositor/operations/COM_ConvertPremulToKeyOperation.h b/source/blender/compositor/operations/COM_ConvertPremulToKeyOperation.h
deleted file mode 100644
index 04a9965858d..00000000000
--- a/source/blender/compositor/operations/COM_ConvertPremulToKeyOperation.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2012, 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_ConvertPremulToKeyOperation_h
-#define _COM_ConvertPremulToKeyOperation_h
-#include "COM_NodeOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class ConvertPremulToKeyOperation : public NodeOperation {
-private:
-	SocketReader *m_inputColor;
-public:
-	/**
-	 * Default constructor
-	 */
-	ConvertPremulToKeyOperation();
-
-	/**
-	 * the inner loop of this program
-	 */
-	void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
-	void initExecution();
-	void deinitExecution();
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_ConvertPremulToStraightOperation.cpp b/source/blender/compositor/operations/COM_ConvertPremulToStraightOperation.cpp
new file mode 100644
index 00000000000..2af4b55de1a
--- /dev/null
+++ b/source/blender/compositor/operations/COM_ConvertPremulToStraightOperation.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2012, 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_ConvertPremulToStraightOperation.h"
+#include "BLI_math.h"
+
+ConvertPremulToStraightOperation::ConvertPremulToStraightOperation() : NodeOperation()
+{
+	this->addInputSocket(COM_DT_COLOR);
+	this->addOutputSocket(COM_DT_COLOR);
+
+	this->m_inputColor = NULL;
+}
+
+void ConvertPremulToStraightOperation::initExecution()
+{
+	this->m_inputColor = getInputSocketReader(0);
+}
+
+void ConvertPremulToStraightOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+	float inputValue[4];
+	float alpha;
+
+	this->m_inputColor->read(inputValue, x, y, sampler);
+	alpha = inputValue[3];
+
+	if (fabsf(alpha) < 1e-5f) {
+		zero_v3(output);
+	}
+	else {
+		mul_v3_v3fl(output, inputValue, 1.0f / alpha);
+	}
+
+	/* never touches the alpha */
+	output[3] = alpha;
+}
+
+void ConvertPremulToStraightOperation::deinitExecution()
+{
+	this->m_inputColor = NULL;
+}
diff --git a/source/blender/compositor/operations/COM_ConvertPremulToStraightOperation.h b/source/blender/compositor/operations/COM_ConvertPremulToStraightOperation.h
new file mode 100644
index 00000000000..9d3ab156555
--- /dev/null
+++ b/source/blender/compositor/operations/COM_ConvertPremulToStraightOperation.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2012, 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_ConvertPremulToStraightOperation_h
+#define _COM_ConvertPremulToStraightOperation_h
+#include "COM_NodeOperation.h"
+
+
+/**
+ * this program converts an input color to an output value.
+ * it assumes we are in sRGB color space.
+ */
+class ConvertPremulToStraightOperation : public NodeOperation {
+private:
+	SocketReader *m_inputColor;
+public:
+	/**
+	 * Default constructor
+	 */
+	ConvertPremulToStraightOperation();
+
+	/**
+	 * the inner loop of this program
+	 */
+	void executePixel(float output[4], float x, float y, PixelSampler sampler);
+
+	void initExecution();
+	void deinitExecution();
+};
+#endif
diff --git a/source/blender/compositor/operations/COM_ConvertStraightToPremulOperation.cpp b/source/blender/compositor/operations/COM_ConvertStraightToPremulOperation.cpp
new file mode 100644
index 00000000000..ae55d949ff2
--- /dev/null
+++ b/source/blender/compositor/operations/COM_ConvertStraightToPremulOperation.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2012, 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_ConvertStraightToPremulOperation.h"
+#include "BLI_math.h"
+
+ConvertStraightToPremulOperation::ConvertStraightToPremulOperation() : NodeOperation()
+{
+	this->addInputSocket(COM_DT_COLOR);
+	this->addOutputSocket(COM_DT_COLOR);
+
+	this->m_inputColor = NULL;
+}
+
+void ConvertStraightToPremulOperation::initExecution()
+{
+	this->m_inputColor = getInputSocketReader(0);
+}
+
+void ConvertStraightToPremulOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+	float inputValue[4];
+	float alpha;
+
+	this->m_inputColor->read(inputValue, x, y, sampler);
+	alpha = inputValue[3];
+
+	mul_v3_v3fl(output, inputValue, alpha);
+
+	/* never touches the alpha */
+	output[3] = alpha;
+}
+
+void ConvertStraightToPremulOperation::deinitExecution()
+{
+	this->m_inputColor = NULL;
+}
diff --git a/source/blender/compositor/operations/COM_ConvertStraightToPremulOperation.h b/source/blender/compositor/operations/COM_ConvertStraightToPremulOperation.h
new file mode 100644
index 00000000000..d0191f292d2
--- /dev/null
+++ b/source/blender/compositor/operations/COM_ConvertStraightToPremulOperation.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2012, 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_ConvertStraightToPremulOperation_h
+#define _COM_ConvertStraightToPremulOperation_h
+#include "COM_NodeOperation.h"
+
+
+/**
+ * this program converts an input color to an output value.
+ * it assumes we are in sRGB color space.
+ */
+class ConvertStraightToPremulOperation : public NodeOperation {
+private:
+	SocketReader *m_inputColor;
+public:
+	/**
+	 * Default constructor
+	 */
+	ConvertStraightToPremulOperation();
+
+	/**
+	 * the inner loop of this program
+	 */
+	void executePixel(float output[4], float x, float y, PixelSampler sampler);
+
+	void initExecution();
+	void deinitExecution();
+
+};
+#endif
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 05dba0c0f68..18dfd8aa6f9 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -3217,8 +3217,8 @@ static void def_cmp_premul_key(StructRNA *srna)
 	PropertyRNA *prop;
 	
 	static EnumPropertyItem type_items[] = {
-		{0, "KEY_TO_PREMUL", 0, "Key to Premul", ""},
-		{1, "PREMUL_TO_KEY", 0, "Premul to Key", ""},
+		{0, "STRAIGHT_TO_PREMUL", 0, "Straight to Premul", ""},
+		{1, "PREMUL_TO_STRAIGHT", 0, "Premul to Straight", ""},
 		{0, NULL, 0, NULL, NULL}
 	};
 	
-- 
cgit v1.2.3


From 4a427d8e0dad2e252fedf55c5941d5877e139b09 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Sat, 29 Dec 2012 01:54:58 +0000
Subject: style cleanup

---
 source/blender/avi/intern/avi_intern.h             |  24 ++-
 source/blender/blenkernel/intern/bmfont.c          |   4 +-
 source/blender/blenkernel/intern/booleanops_mesh.c |  24 +--
 source/blender/blenkernel/intern/fcurve.c          |   6 +-
 source/blender/blenkernel/intern/paint.c           |   2 +-
 source/blender/blenkernel/intern/particle_system.c |   6 +-
 source/blender/blenkernel/intern/sequencer.c       |   2 +-
 source/blender/blenkernel/intern/smoke.c           |   2 +-
 source/blender/blenlib/intern/jitter.c             |   2 +-
 source/blender/blenlib/intern/math_geom.c          |  30 +--
 source/blender/blenlib/intern/scanfill.c           |  16 +-
 source/blender/blenloader/intern/readfile.c        |  22 +-
 source/blender/collada/AnimationImporter.cpp       |   4 +-
 source/blender/collada/MeshImporter.cpp            |   8 +-
 source/blender/editors/interface/resources.c       |   4 +-
 source/blender/editors/space_image/image_buttons.c |   4 +-
 source/blender/editors/space_text/text_format_py.c |   3 +
 .../blender/editors/space_view3d/view3d_select.c   |   2 +-
 .../editors/transform/transform_orientations.c     |   2 +-
 source/blender/imbuf/intern/jpeg.c                 |   4 +-
 source/blender/makesrna/intern/rna_define.c        |   4 +-
 source/blender/modifiers/intern/MOD_screw.c        |   2 +-
 .../modifiers/intern/MOD_weightvgproximity.c       |   6 +-
 source/blender/render/intern/source/pipeline.c     |   2 +-
 source/blender/windowmanager/intern/wm_apple.c     |   2 +-
 source/creator/creator.c                           |   2 +-
 source/gameengine/Expressions/PyObjectPlus.cpp     |  28 +--
 source/gameengine/Expressions/PyObjectPlus.h       | 224 ++++++++++-----------
 source/gameengine/GameLogic/SCA_PythonJoystick.cpp |   6 +-
 29 files changed, 235 insertions(+), 212 deletions(-)

(limited to 'source')

diff --git a/source/blender/avi/intern/avi_intern.h b/source/blender/avi/intern/avi_intern.h
index c8d54fe99e9..5dc48657831 100644
--- a/source/blender/avi/intern/avi_intern.h
+++ b/source/blender/avi/intern/avi_intern.h
@@ -37,9 +37,27 @@
 unsigned int GET_FCC (FILE *fp);
 unsigned int GET_TCC (FILE *fp);
 
-#define PUT_FCC(ch4, fp) putc(ch4[0],fp); putc(ch4[1],fp); putc(ch4[2],fp); putc(ch4[3],fp)
-#define PUT_FCCN(num, fp) putc((num>>0)&0377,fp); putc((num>>8)&0377,fp); putc((num>>16)&0377,fp); putc((num>>24)&0377,fp)
-#define PUT_TCC(ch2, fp) putc(ch2[0],fp); putc(ch2[1],fp)
+#define PUT_FCC(ch4, fp) \
+{ \
+	putc(ch4[0], fp); \
+	putc(ch4[1], fp); \
+	putc(ch4[2], fp); \
+	putc(ch4[3], fp); \
+} (void)0
+
+#define PUT_FCCN(num, fp) \
+{ \
+	putc((num >> 0)  & 0377, fp); \
+	putc((num >> 8)  & 0377, fp); \
+	putc((num >> 16) & 0377, fp); \
+	putc((num >> 24) & 0377, fp); \
+} (void)0
+
+#define PUT_TCC(ch2, fp) \
+{ \
+	putc(ch2[0], fp); \
+	putc(ch2[1], fp); \
+} (void)0
 
 void *avi_format_convert (AviMovie *movie, int stream, void *buffer, AviFormat from, AviFormat to, int *size);
 
diff --git a/source/blender/blenkernel/intern/bmfont.c b/source/blender/blenkernel/intern/bmfont.c
index 0495e729937..fc83b24da5b 100644
--- a/source/blender/blenkernel/intern/bmfont.c
+++ b/source/blender/blenkernel/intern/bmfont.c
@@ -65,8 +65,8 @@ void printfGlyph(bmGlyph * glyph)
 	printf(" advan: %3d reser: %3d\n", glyph->advance, glyph->reserved);
 }
 
-#define MAX2(x,y)          ((x) > (y) ? (x) : (y))
-#define MAX3(x,y,z)         MAX2(MAX2((x), (y)), (z))
+#define MAX2(x, y)          ((x) > (y) ? (x) : (y))
+#define MAX3(x, y, z)       (MAX2(MAX2((x), (y)), (z)))
 
 void calcAlpha(ImBuf * ibuf)
 {
diff --git a/source/blender/blenkernel/intern/booleanops_mesh.c b/source/blender/blenkernel/intern/booleanops_mesh.c
index 461b945282f..f53a89fccfd 100644
--- a/source/blender/blenkernel/intern/booleanops_mesh.c
+++ b/source/blender/blenkernel/intern/booleanops_mesh.c
@@ -56,7 +56,7 @@ CSG_DestroyBlenderMeshInternals(
 	CSG_MeshDescriptor *mesh
 ) {
 	/* Free face and vertex iterators. */
-	FreeMeshDescriptors(&(mesh->m_face_iterator),&(mesh->m_vertex_iterator));
+	FreeMeshDescriptors(&(mesh->m_face_iterator), &(mesh->m_vertex_iterator));
 }
 
 
@@ -138,7 +138,7 @@ CSG_AddMeshToBlender(
 	if (mesh == NULL) return 0;
 	if (mesh->base == NULL) return 0;
 
-	invert_m4_m4(inv_mat,mesh->base->object->obmat);
+	invert_m4_m4(inv_mat, mesh->base->object->obmat);
 
 	/* Create a new blender mesh object - using 'base' as
 	 * a template for the new object. */
@@ -191,7 +191,7 @@ CSG_PerformOp(
 		default : op_type = e_csg_intersection;
 	}
 	
-	output->m_descriptor = CSG_DescibeOperands(bool_op,mesh1->m_descriptor,mesh2->m_descriptor);
+	output->m_descriptor = CSG_DescibeOperands(bool_op, mesh1->m_descriptor, mesh2->m_descriptor);
 	output->base = mesh1->base;
 
 	if (output->m_descriptor.user_face_vertex_data_size) {
@@ -228,8 +228,8 @@ CSG_PerformOp(
 
 	/* get the ouput mesh descriptors. */
 
-	CSG_OutputFaceDescriptor(bool_op,&(output->m_face_iterator));
-	CSG_OutputVertexDescriptor(bool_op,&(output->m_vertex_iterator));
+	CSG_OutputFaceDescriptor(bool_op, &(output->m_face_iterator));
+	CSG_OutputVertexDescriptor(bool_op, &(output->m_vertex_iterator));
 	output->m_destroy_func = CSG_DestroyCSGMeshInternals;
 
 	return 1;
@@ -242,20 +242,20 @@ NewBooleanMeshTest(
 	int op_type
 ) {
 
-	CSG_MeshDescriptor m1,m2,output;
-	CSG_MeshDescriptor output2,output3;
+	CSG_MeshDescriptor m1, m2, output;
+	CSG_MeshDescriptor output2, output3;
 	
-	if (!MakeCSGMeshFromBlenderBase(base,&m1)) {
+	if (!MakeCSGMeshFromBlenderBase(base, &m1)) {
 		return 0;
 	}
 	
-	if (!MakeCSGMeshFromBlenderBase(base_select,&m2)) {
+	if (!MakeCSGMeshFromBlenderBase(base_select, &m2)) {
 		return 0;
 	}
 	
-	CSG_PerformOp(&m1,&m2,1,&output);
-	CSG_PerformOp(&m1,&m2,2,&output2);
-	CSG_PerformOp(&m1,&m2,3,&output3);
+	CSG_PerformOp(&m1, &m2, 1, &output);
+	CSG_PerformOp(&m1, &m2, 2, &output2);
+	CSG_PerformOp(&m1, &m2, 3, &output3);
 
 	if (!CSG_AddMeshToBlender(&output)) {
 		return 0;
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index 1511ac5bb3f..23f3a3ad3fd 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -859,7 +859,7 @@ void testhandles_fcurve(FCurve *fcu, const short use_handle)
 		short flag = 0;
 		
 		/* flag is initialized as selection status
-		 * of beztriple control-points (labelled 0,1,2)
+		 * of beztriple control-points (labelled 0, 1, 2)
 		 */
 		if (bezt->f2 & SELECT) flag |= (1 << 1);  // == 2
 		if (use_handle == FALSE) {
@@ -2022,12 +2022,12 @@ static float fcurve_eval_keyframes(FCurve *fcu, BezTriple *bezts, float evaltime
 				}
 				else {
 					/* bezier interpolation */
-					/* v1,v2 are the first keyframe and its 2nd handle */
+					/* (v1, v2) are the first keyframe and its 2nd handle */
 					v1[0] = prevbezt->vec[1][0];
 					v1[1] = prevbezt->vec[1][1];
 					v2[0] = prevbezt->vec[2][0];
 					v2[1] = prevbezt->vec[2][1];
-					/* v3,v4 are the last keyframe's 1st handle + the last keyframe */
+					/* (v3, v4) are the last keyframe's 1st handle + the last keyframe */
 					v3[0] = bezt->vec[0][0];
 					v3[1] = bezt->vec[0][1];
 					v4[0] = bezt->vec[1][0];
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index fa5268e039e..5847e7508f0 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -212,7 +212,7 @@ int paint_is_face_hidden(const MFace *f, const MVert *mvert)
 }
 
 /* returns non-zero if any of the corners of the grid
- * face whose inner corner is at (x,y) are hidden,
+ * face whose inner corner is at (x, y) are hidden,
  * zero otherwise */
 int paint_is_grid_face_hidden(const unsigned int *grid_hidden,
                               int gridsize, int x, int y)
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 090082b333d..3b897e94241 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -522,9 +522,9 @@ static void distribute_grid(DerivedMesh *dm, ParticleSystem *psys)
 			vec[0]/=delta[0];
 			vec[1]/=delta[1];
 			vec[2]/=delta[2];
-			(pa	+ ((int)(vec[0] * (size[0] - 1)) * res +
-			       (int)(vec[1] * (size[1] - 1))) * res +
-			        (int)(vec[2] * (size[2] - 1)))->flag &= ~PARS_UNEXIST;
+			pa[((int)(vec[0] * (size[0] - 1))  * res +
+			    (int)(vec[1] * (size[1] - 1))) * res +
+			    (int)(vec[2] * (size[2] - 1))].flag &= ~PARS_UNEXIST;
 		}
 	}
 	else if (ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)) {
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 5e44f2d6d9e..a82704d9e38 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -4176,7 +4176,7 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup
 
 		seqn->seqbase.first = seqn->seqbase.last = NULL;
 		/* WATCH OUT!!! - This metastrip is not recursively duplicated here - do this after!!! */
-		/* - seq_dupli_recursive(&seq->seqbase,&seqn->seqbase);*/
+		/* - seq_dupli_recursive(&seq->seqbase, &seqn->seqbase);*/
 	}
 	else if (seq->type == SEQ_TYPE_SCENE) {
 		seqn->strip->stripdata = NULL;
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index 629b2c989d3..2563fc268b1 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -2407,7 +2407,7 @@ static void smoke_calc_transparency(SmokeDomainSettings *sds, Scene *scene)
 	bv[3] = (float)sds->res[1]; // y
 	bv[5] = (float)sds->res[2]; // z
 
-// #pragma omp parallel for schedule(static,1)
+// #pragma omp parallel for schedule(static, 1)
 	for (z = 0; z < sds->res[2]; z++)
 	{
 		size_t index = z * slabsize;
diff --git a/source/blender/blenlib/intern/jitter.c b/source/blender/blenlib/intern/jitter.c
index 6203a98828b..3fe0ef158df 100644
--- a/source/blender/blenlib/intern/jitter.c
+++ b/source/blender/blenlib/intern/jitter.c
@@ -165,7 +165,7 @@ void BLI_jitter_init(float *jitarr, int num)
 
 	MEM_freeN(jit2);
 	
-	/* finally, move jittertab to be centered around (0,0) */
+	/* finally, move jittertab to be centered around (0, 0) */
 	for (i = 0; i < 2 * num; i += 2) {
 		jitarr[i] -= 0.5f;
 		jitarr[i + 1] -= 0.5f;
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index 10a9a2df9f5..24c4e87d6ab 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -1037,7 +1037,7 @@ int isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const flo
 
 		if (t0 > 1.0f || t1 < 0.0f) return 0;
 
-		/* clamp to [0,1] */
+		/* clamp to [0, 1] */
 		CLAMP(t0, 0.0f, 1.0f);
 		CLAMP(t1, 0.0f, 1.0f);
 
@@ -1157,10 +1157,10 @@ int isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const flo
 	}
 
 	/*e3*/
-	/* sub_v3_v3v3(bv,v0,p1); */ /* UNUSED */
-	/* elen2 = dot_v3v3(e1,e1); */ /* UNUSED */
-	/* edotv = dot_v3v3(e1,vel); */ /* UNUSED */
-	/* edotbv = dot_v3v3(e1,bv); */ /* UNUSED */
+	/* sub_v3_v3v3(bv, v0, p1); */ /* UNUSED */
+	/* elen2 = dot_v3v3(e1, e1); */ /* UNUSED */
+	/* edotv = dot_v3v3(e1, vel); */ /* UNUSED */
+	/* edotbv = dot_v3v3(e1, bv); */ /* UNUSED */
 
 	sub_v3_v3v3(bv, v1, p1);
 	elen2 = dot_v3v3(e3, e3);
@@ -1195,7 +1195,7 @@ int isect_axial_line_tri_v3(const int axis, const float p1[3], const float p2[3]
 	int a0 = axis, a1 = (axis + 1) % 3, a2 = (axis + 2) % 3;
 
 #if 0
-	return isect_line_tri_v3(p1,p2,v0,v1,v2,lambda);
+	return isect_line_tri_v3(p1, p2, v0, v1, v2, lambda);
 
 	/* first a simple bounding box test */
 	if (min_fff(v0[a1], v1[a1], v2[a1]) > p1[a1]) return 0;
@@ -1415,8 +1415,8 @@ int isect_ray_aabb(const IsectRayAABBData *data, const float bb_min[3],
 	return TRUE;
 }
 
-/* find closest point to p on line through l1,l2 and return lambda,
- * where (0 <= lambda <= 1) when cp is in the line segment l1,l2
+/* find closest point to p on line through (l1, l2) and return lambda,
+ * where (0 <= lambda <= 1) when cp is in the line segment (l1, l2)
  */
 float closest_to_line_v3(float cp[3], const float p[3], const float l1[3], const float l2[3])
 {
@@ -1702,9 +1702,9 @@ static int point_in_slice(const float p[3], const float v1[3], const float l1[3]
 	/*
 	 * what is a slice ?
 	 * some maths:
-	 * a line including l1,l2 and a point not on the line
+	 * a line including (l1, l2) and a point not on the line
 	 * define a subset of R3 delimited by planes parallel to the line and orthogonal
-	 * to the (point --> line) distance vector,one plane on the line one on the point,
+	 * to the (point --> line) distance vector, one plane on the line one on the point,
 	 * the room inside usually is rather small compared to R3 though still infinite
 	 * useful for restricting (speeding up) searches
 	 * e.g. all points of triangular prism are within the intersection of 3 'slices'
@@ -2304,7 +2304,7 @@ void interp_weights_poly_v2(float *w, float v[][2], const int n, const float co[
 	}
 }
 
-/* (x1,v1)(t1=0)------(x2,v2)(t2=1), 0 (x,v)(t) */
+/* (x1, v1)(t1=0)------(x2, v2)(t2=1), 0 (x, v)(t) */
 void interp_cubic_v3(float x[3], float v[3], const float x1[3], const float v1[3], const float x2[3], const float v2[3], const float t)
 {
 	float a[3], b[3];
@@ -2791,8 +2791,8 @@ void tangent_from_uv(float uv1[2], float uv2[2], float uv3[3], float co1[3], flo
 /****************************** Vector Clouds ********************************/
 
 /* vector clouds */
-/* void vcloud_estimate_transform(int list_size, float (*pos)[3], float *weight,float (*rpos)[3], float *rweight,
- *                                float lloc[3],float rloc[3],float lrot[3][3],float lscale[3][3])
+/* void vcloud_estimate_transform(int list_size, float (*pos)[3], float *weight, float (*rpos)[3], float *rweight,
+ *                                float lloc[3], float rloc[3], float lrot[3][3], float lscale[3][3])
  *
  * input
  * (
@@ -2881,9 +2881,9 @@ void vcloud_estimate_transform(int list_size, float (*pos)[3], float *weight, fl
 			/* build 'projection' matrix */
 			for (a = 0; a < list_size; a++) {
 				sub_v3_v3v3(va, rpos[a], accu_rcom);
-				/* mul_v3_fl(va,bp->mass);  mass needs renormalzation here ?? */
+				/* mul_v3_fl(va, bp->mass);  mass needs renormalzation here ?? */
 				sub_v3_v3v3(vb, pos[a], accu_com);
-				/* mul_v3_fl(va,rp->mass); */
+				/* mul_v3_fl(va, rp->mass); */
 				m[0][0] += va[0] * vb[0];
 				m[0][1] += va[0] * vb[1];
 				m[0][2] += va[0] * vb[2];
diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c
index 45c6c5efbb3..771295b4b78 100644
--- a/source/blender/blenlib/intern/scanfill.c
+++ b/source/blender/blenlib/intern/scanfill.c
@@ -459,7 +459,7 @@ static void testvertexnearedge(ScanFillContext *sf_ctx)
 								/* new edge */
 								ed1 = BLI_scanfill_edge_add(sf_ctx, eed->v1, eve);
 								
-								/* printf("fill: vertex near edge %x\n",eve); */
+								/* printf("fill: vertex near edge %x\n", eve); */
 								ed1->f = 0;
 								ed1->poly_nr = eed->poly_nr;
 								eed->v1 = eve;
@@ -639,7 +639,7 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag)
 
 	sc = sf_ctx->_scdata;
 	for (a = 0; a < verts; a++) {
-		/* printf("VERTEX %d %x\n",a,sc->v1); */
+		/* printf("VERTEX %d %x\n", a, sc->v1); */
 		ed1 = sc->edge_first;
 		while (ed1) {   /* set connectflags  */
 			nexted = ed1->next;
@@ -680,9 +680,9 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag)
 				v3 = ed2->v2;
 				/* this happens with a serial of overlapping edges */
 				if (v1 == v2 || v2 == v3) break;
-				/* printf("test verts %x %x %x\n",v1,v2,v3); */
+				/* printf("test verts %x %x %x\n", v1, v2, v3); */
 				miny = min_ff(v1->xy[1], v3->xy[1]);
-				/*  miny = min_ff(v1->xy[1],v3->xy[1]); */
+				/*  miny = min_ff(v1->xy[1], v3->xy[1]); */
 				sc1 = sc + 1;
 				test = 0;
 
@@ -704,7 +704,7 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag)
 				}
 				if (test) {
 					/* make new edge, and start over */
-					/* printf("add new edge %x %x and start again\n",v2,sc1->vert); */
+					/* printf("add new edge %x %x and start again\n", v2, sc1->vert); */
 
 					ed3 = BLI_scanfill_edge_add(sf_ctx, v2, sc1->vert);
 					BLI_remlink(&sf_ctx->filledgebase, ed3);
@@ -716,7 +716,7 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag)
 				}
 				else {
 					/* new triangle */
-					/* printf("add face %x %x %x\n",v1,v2,v3); */
+					/* printf("add face %x %x %x\n", v1, v2, v3); */
 					addfillface(sf_ctx, v1, v2, v3);
 					totface++;
 					BLI_remlink((ListBase *)&(sc->edge_first), ed1);
@@ -740,7 +740,7 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag)
 					ed3->v1->h++; 
 					ed3->v2->h++;
 					
-					/* printf("add new edge %x %x\n",v1,v3); */
+					/* printf("add new edge %x %x\n", v1, v3); */
 					sc1 = addedgetoscanlist(sf_ctx, ed3, verts);
 					
 					if (sc1) {  /* ed3 already exists: remove if a boundary */
@@ -963,7 +963,7 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float no
 			}
 			eve = eve->next;
 		}
-		/* printf("amount of poly's: %d\n",poly); */
+		/* printf("amount of poly's: %d\n", poly); */
 	}
 	else {
 		poly = 1;
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 458b6424799..eda2cb4243a 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -1025,23 +1025,23 @@ FileData *blo_openblenderfile(const char *filepath, ReportList *reports)
 static int fd_read_gzip_from_memory(FileData *filedata, void *buffer, unsigned int size)
 {
 	int err;
-	
+
 	filedata->strm.next_out = (Bytef *) buffer;
-    filedata->strm.avail_out = size;
-	
-    // Inflate another chunk.
-    err = inflate (&filedata->strm, Z_SYNC_FLUSH);
-	
-    if (err == Z_STREAM_END) {
+	filedata->strm.avail_out = size;
+
+	// Inflate another chunk.
+	err = inflate (&filedata->strm, Z_SYNC_FLUSH);
+
+	if (err == Z_STREAM_END) {
 		return 0;
 	}
-    else if (err != Z_OK)  {
+	else if (err != Z_OK)  {
 		printf("fd_read_gzip_from_memory: zlib error\n");
 		return 0;
-    }
-	
+	}
+
 	filedata->seek += size;
-	
+
 	return (size);
 }
 
diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp
index 44e74e320cc..3d0ceb560ed 100644
--- a/source/blender/collada/AnimationImporter.cpp
+++ b/source/blender/collada/AnimationImporter.cpp
@@ -1194,7 +1194,7 @@ void AnimationImporter::add_bone_animation_sampled(Object *ob, std::vectordata;
 		if (me->id.us==1) {
-			bc_copy_materials_to_data(ob,me);
-			bc_remove_materials_from_object(ob,me);
+			bc_copy_materials_to_data(ob, me);
+			bc_remove_materials_from_object(ob, me);
 			bc_remove_mark(ob);
 		}
 		else if (me->id.us > 1)
@@ -1101,10 +1101,10 @@ void MeshImporter::optimize_material_assignments()
 					}
 				}
 				if (can_move) {
-					bc_copy_materials_to_data(ref_ob,me);
+					bc_copy_materials_to_data(ref_ob, me);
 					for (int index = 0; index < mesh_users.size(); index++) {
 						Object *object = mesh_users[index];
-						bc_remove_materials_from_object(object,me);
+						bc_remove_materials_from_object(object, me);
 						bc_remove_mark(object);
 					}
 				}
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 4127c1b9abc..f605616dc50 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -869,8 +869,8 @@ void ui_theme_init_default(void)
 	rgba_char_args_set_fl(btheme->tima.preview_stitch_vert, 0.0, 0.0, 1.0, 0.2);
 	rgba_char_args_set_fl(btheme->tima.preview_stitch_stitchable, 0.0, 1.0, 0.0, 1.0);
 	rgba_char_args_set_fl(btheme->tima.preview_stitch_unstitchable, 1.0, 0.0, 0.0, 1.0);
-    rgba_char_args_set_fl(btheme->tima.preview_stitch_active, 0.886, 0.824, 0.765, 0.140);
-    
+	rgba_char_args_set_fl(btheme->tima.preview_stitch_active, 0.886, 0.824, 0.765, 0.140);
+
 	/* space text */
 	btheme->text = btheme->tv3d;
 	rgba_char_args_set(btheme->text.back,   153, 153, 153, 255);
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index 51fbbacc07c..09d203784e4 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -219,7 +219,7 @@ static void preview_cb(ScrArea *sa, struct uiBlock *block)
 	BLI_rcti_translate(disprect, -curarea->winrct.xmin, -curarea->winrct.ymin);
 	
 	calc_image_view(sima, 'p');
-//	printf("winrct %d %d %d %d\n", disprect->xmin, disprect->ymin,disprect->xmax, disprect->ymax);
+//	printf("winrct %d %d %d %d\n", disprect->xmin, disprect->ymin, disprect->xmax, disprect->ymax);
 	/* map to image space coordinates */
 	mval[0] = disprect->xmin; mval[1] = disprect->ymin;
 	areamouseco_to_ipoco(v2d, mval, &dispf.xmin, &dispf.ymin);
@@ -236,7 +236,7 @@ static void preview_cb(ScrArea *sa, struct uiBlock *block)
 	CLAMP(disprect->xmax, 0, winx);
 	CLAMP(disprect->ymin, 0, winy);
 	CLAMP(disprect->ymax, 0, winy);
-//	printf("drawrct %d %d %d %d\n", disprect->xmin, disprect->ymin,disprect->xmax, disprect->ymax);
+//	printf("drawrct %d %d %d %d\n", disprect->xmin, disprect->ymin, disprect->xmax, disprect->ymax);
 
 }
 
diff --git a/source/blender/editors/space_text/text_format_py.c b/source/blender/editors/space_text/text_format_py.c
index 2a0f483d80c..c4d4b6b1c2f 100644
--- a/source/blender/editors/space_text/text_format_py.c
+++ b/source/blender/editors/space_text/text_format_py.c
@@ -56,6 +56,9 @@
 static int txtfmt_py_find_builtinfunc(char *string)
 {
 	int a, i;
+	/* list is from...
+	 * ", ".join(['"%s"' % kw for kw in  __import__("keyword").kwlist if kw not in {"False", "None", "True"}])
+	 */
 	const char *builtinfuncs[] = {
 		/* "False", "None", "True", */ /* see find_bool() */
 		"and", "as", "assert", "break",
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 6cca5b298fe..dac887f7f13 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -1477,7 +1477,7 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese
 							}
 
 							/* index of bundle is 1<<16-based. if there's no "bone" index
-							 * in height word, this buffer value belongs to camera,. not to bundle */
+							 * in height word, this buffer value belongs to camera. not to bundle */
 							if (buffer[4 * i + 3] & 0xFFFF0000) {
 								MovieClip *clip = BKE_object_movieclip_get(scene, basact->object, 0);
 								MovieTracking *tracking = &clip->tracking;
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index c9c4f7e2c7b..4bd6496e083 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -764,7 +764,7 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
 			EditBone *ebone;
 			int ok = FALSE;
 			
-			/* grr,.but better then duplicate code */
+			/* grr. but better then duplicate code */
 #define EBONE_CALC_NORMAL_PLANE  { \
 			float tmat[3][3]; \
 			float vec[3]; \
diff --git a/source/blender/imbuf/intern/jpeg.c b/source/blender/imbuf/intern/jpeg.c
index 758617bdd48..6a5b534c688 100644
--- a/source/blender/imbuf/intern/jpeg.c
+++ b/source/blender/imbuf/intern/jpeg.c
@@ -234,7 +234,7 @@ static void memory_source(j_decompress_ptr cinfo, unsigned char *buffer, size_t
  * If must suspend, take the specified action (typically "return FALSE").
  */
 #define INPUT_BYTE(cinfo, V, action)  \
-	MAKESTMT(MAKE_BYTE_AVAIL(cinfo,action); \
+	MAKESTMT(MAKE_BYTE_AVAIL(cinfo, action); \
 	         bytes_in_buffer--; \
 	         V = GETJOCTET(*next_input_byte++); )
 
@@ -242,7 +242,7 @@ static void memory_source(j_decompress_ptr cinfo, unsigned char *buffer, size_t
  * V should be declared unsigned int or perhaps INT32.
  */
 #define INPUT_2BYTES(cinfo, V, action)  \
-	MAKESTMT(MAKE_BYTE_AVAIL(cinfo,action); \
+	MAKESTMT(MAKE_BYTE_AVAIL(cinfo, action); \
 	      bytes_in_buffer--; \
 	      V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \
 	      MAKE_BYTE_AVAIL(cinfo, action); \
diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c
index b8f791323a0..727b1e44931 100644
--- a/source/blender/makesrna/intern/rna_define.c
+++ b/source/blender/makesrna/intern/rna_define.c
@@ -391,7 +391,9 @@ static int rna_validate_identifier(const char *identifier, char *error, int prop
 {
 	int a = 0;
 	
-	/*  list from http://docs.python.org/py3k/reference/lexical_analysis.html#keywords */
+	/* list is from...
+	 * ", ".join(['"%s"' % kw for kw in  __import__("keyword").kwlist if kw not in {"False", "None", "True"}])
+	 */
 	static const char *kwlist[] = {
 		/* "False", "None", "True", */
 		"and", "as", "assert", "break",
diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c
index 93b5e36e5a4..ff88cd97197 100644
--- a/source/blender/modifiers/intern/MOD_screw.c
+++ b/source/blender/modifiers/intern/MOD_screw.c
@@ -225,7 +225,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
 
 		/* angle */
 
-#if 0   // cant incluide this, not predictable enough, though quite fun,.
+#if 0   /* cant incluide this, not predictable enough, though quite fun. */
 		if (ltmd->flag & MOD_SCREW_OBJECT_ANGLE) {
 			float mtx3_tx[3][3];
 			copy_m3_m4(mtx3_tx, mtx_tx);
diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c
index e936e571a5b..71d6d4880ad 100644
--- a/source/blender/modifiers/intern/MOD_weightvgproximity.c
+++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c
@@ -107,9 +107,9 @@ static void get_vert2geom_distance(int numVerts, float (*v_cos)[3],
 	/*nearest_v.dist  = nearest_e.dist  = nearest_f.dist  = FLT_MAX;*/
 	/* Find the nearest vert/edge/face. */
 #ifndef __APPLE__
-#pragma omp parallel for default(none) private(i) firstprivate(nearest_v,nearest_e,nearest_f) \
-                         shared(treeData_v,treeData_e,treeData_f,numVerts,v_cos,dist_v,dist_e, \
-                                dist_f,loc2trgt) \
+#pragma omp parallel for default(none) private(i) firstprivate(nearest_v, nearest_e, nearest_f) \
+                         shared(treeData_v, treeData_e, treeData_f, numVerts, v_cos, dist_v, dist_e, \
+                                dist_f, loc2trgt) \
                          schedule(static)
 #endif
 	for (i = 0; i < numVerts; i++) {
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 2d4e9513d0a..0545d2940ab 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -1237,7 +1237,7 @@ static void do_render_fields_blur_3d(Render *re)
 	Object *camera = RE_GetCamera(re);
 	/* also check for camera here */
 	if (camera == NULL) {
-        BKE_report(re->reports, RPT_ERROR, "Cannot render, no camera");
+		BKE_report(re->reports, RPT_ERROR, "Cannot render, no camera");
 		G.is_break = TRUE;
 		return;
 	}
diff --git a/source/blender/windowmanager/intern/wm_apple.c b/source/blender/windowmanager/intern/wm_apple.c
index a7bd43986dd..842fc353699 100644
--- a/source/blender/windowmanager/intern/wm_apple.c
+++ b/source/blender/windowmanager/intern/wm_apple.c
@@ -77,7 +77,7 @@ static int checkAppleVideoCard(void)
 					if ((theErr == 0) && (value != 0)) {
 						theErr = CGLDescribeRenderer(rend, j, kCGLRPCompliant, &value);
 						if ((theErr == 0) && (value != 0)) {
-							/*fprintf(stderr,"make it big\n");*/
+							/*fprintf(stderr, "make it big\n");*/
 							CGLDestroyRendererInfo(rend);
 							macPrefState = 8;
 							return 1;
diff --git a/source/creator/creator.c b/source/creator/creator.c
index a05fcac4c89..158ce8f2eeb 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -1405,7 +1405,7 @@ int main(int argc, const char **argv)
 	WM_main(C);
 
 	return 0;
-} /* end of int main(argc,argv)	*/
+} /* end of int main(argc, argv)	*/
 
 #ifdef WITH_PYTHON_MODULE
 void main_python_exit(void)
diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp
index 11b00b7bbf5..4e910a885eb 100644
--- a/source/gameengine/Expressions/PyObjectPlus.cpp
+++ b/source/gameengine/Expressions/PyObjectPlus.cpp
@@ -118,16 +118,16 @@ PyTypeObject PyObjectPlus::Type = {
 	0,								/* setattrfunc tp_setattr; */
 	0,								/* tp_compare */ /* DEPRECATED in python 3.0! */
 	py_base_repr,					/* tp_repr */
-	0,0,0,0,0,0,0,0,0,				/* Method suites for standard classes */
-	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,/* long tp_flags; */
-	0,0,0,0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0,		/* Method suites for standard classes */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* long tp_flags; */
+	0, 0, 0, 0,
 	/* weak reference enabler */
 #ifdef USE_WEAKREFS
 	offsetof(PyObjectPlus_Proxy, in_weakreflist),	/* long tp_weaklistoffset; */
 #else
 	0,
 #endif
-	0,0,
+	0, 0,
 	Methods,
 	0,
 	0,
@@ -311,14 +311,14 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
 				{
 					bool *val = reinterpret_cast(ptr);
 					ptr += sizeof(bool);
-					PyList_SET_ITEM(resultlist,i,PyBool_FromLong(*val));
+					PyList_SET_ITEM(resultlist, i, PyBool_FromLong(*val));
 					break;
 				}
 			case KX_PYATTRIBUTE_TYPE_SHORT:
 				{
 					short int *val = reinterpret_cast(ptr);
 					ptr += sizeof(short int);
-					PyList_SET_ITEM(resultlist,i,PyLong_FromLong(*val));
+					PyList_SET_ITEM(resultlist, i, PyLong_FromLong(*val));
 					break;
 				}
 			case KX_PYATTRIBUTE_TYPE_ENUM:
@@ -333,14 +333,14 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
 				{
 					int *val = reinterpret_cast(ptr);
 					ptr += sizeof(int);
-					PyList_SET_ITEM(resultlist,i,PyLong_FromLong(*val));
+					PyList_SET_ITEM(resultlist, i, PyLong_FromLong(*val));
 					break;
 				}
 			case KX_PYATTRIBUTE_TYPE_FLOAT:
 				{
 					float *val = reinterpret_cast(ptr);
 					ptr += sizeof(float);
-					PyList_SET_ITEM(resultlist,i,PyFloat_FromDouble(*val));
+					PyList_SET_ITEM(resultlist, i, PyFloat_FromDouble(*val));
 					break;
 				}
 			default:
@@ -423,7 +423,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
 						PyObject *resultlist = PyList_New(attrdef->m_imax);
 						for (unsigned int i=0; im_imax; i++)
 						{
-							PyList_SET_ITEM(resultlist,i,PyFloat_FromDouble(val[i]));
+							PyList_SET_ITEM(resultlist, i, PyFloat_FromDouble(val[i]));
 						}
 						return resultlist;
 #endif
@@ -443,9 +443,9 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
 						PyObject *col = PyList_New(attrdef->m_imax);
 						for (unsigned int j=0; jm_imax; j++)
 						{
-							PyList_SET_ITEM(col,j,PyFloat_FromDouble(val[j]));
+							PyList_SET_ITEM(col, j, PyFloat_FromDouble(val[j]));
 						}
-						PyList_SET_ITEM(collist,i,col);
+						PyList_SET_ITEM(collist, i, col);
 						val += attrdef->m_imax;
 					}
 					return collist;
@@ -463,7 +463,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
 				PyObject *resultlist = PyList_New(3);
 				for (unsigned int i=0; i<3; i++)
 				{
-					PyList_SET_ITEM(resultlist,i,PyFloat_FromDouble((*val)[i]));
+					PyList_SET_ITEM(resultlist, i, PyFloat_FromDouble((*val)[i]));
 				}
 				return resultlist;
 #endif
@@ -1110,7 +1110,7 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt
 ------------------------------*/
 PyObject *PyObjectPlus::py_repr(void)
 {
-	PyErr_SetString(PyExc_SystemError, "Representation not overridden by object.");  
+	PyErr_SetString(PyExc_SystemError, "Representation not overridden by object.");
 	return NULL;
 }
 
@@ -1187,7 +1187,7 @@ void PyObjectPlus::SetDeprecationWarnings(bool ignoreDeprecationWarnings)
 	m_ignore_deprecation_warnings = ignoreDeprecationWarnings;
 }
 
-void PyObjectPlus::ShowDeprecationWarning_func(const char* old_way,const char* new_way)
+void PyObjectPlus::ShowDeprecationWarning_func(const char *old_way, const char *new_way)
 {
 	printf("Method %s is deprecated, please use %s instead.\n", old_way, new_way);
 	PyC_LineSpit();
diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h
index 37e26e88750..e2e7c248795 100644
--- a/source/gameengine/Expressions/PyObjectPlus.h
+++ b/source/gameengine/Expressions/PyObjectPlus.h
@@ -389,139 +389,139 @@ typedef struct KX_PYATTRIBUTE_DEF {
 	} m_typeCheck;
 } PyAttributeDef;
 
-#define KX_PYATTRIBUTE_BOOL_RW(name,object,field) \
-	{ name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, false, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_BOOL_RW_CHECK(name,object,field,function) \
-	{ name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, false, false, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_BOOL_RO(name,object,field) \
-	{ name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RO, 0, 1, 0.f, 0.f, false, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_BOOL_RW(name, object, field) \
+	{ name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, false, false, offsetof(object, field), 0, 1, NULL, NULL, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_BOOL_RW_CHECK(name, object, field, function) \
+	{ name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, false, false, offsetof(object, field), 0, 1, &object::function, NULL, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_BOOL_RO(name, object, field) \
+	{ name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RO, 0, 1, 0.f, 0.f, false, false, offsetof(object, field), 0, 1, NULL, NULL, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL, NULL, NULL} }
 
 /* attribute points to a single bit of an integer field, attribute=true if bit is set */
-#define KX_PYATTRIBUTE_FLAG_RW(name,object,field,bit) \
-	{ name, KX_PYATTRIBUTE_TYPE_FLAG, KX_PYATTRIBUTE_RW, bit, 0, 0.f, 0.f, false, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_FLAG_RW_CHECK(name,object,field,bit,function) \
-	{ name, KX_PYATTRIBUTE_TYPE_FLAG, KX_PYATTRIBUTE_RW, bit, 0, 0.f, 0.f, false, false, offsetof(object,field), sizeof(((object *)0)->field), 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_FLAG_RO(name,object,field,bit) \
-	{ name, KX_PYATTRIBUTE_TYPE_FLAG, KX_PYATTRIBUTE_RO, bit, 0, 0.f, 0.f, false, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLAG_RW(name, object, field, bit) \
+	{ name, KX_PYATTRIBUTE_TYPE_FLAG, KX_PYATTRIBUTE_RW, bit, 0, 0.f, 0.f, false, false, offsetof(object, field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLAG_RW_CHECK(name, object, field, bit, function) \
+	{ name, KX_PYATTRIBUTE_TYPE_FLAG, KX_PYATTRIBUTE_RW, bit, 0, 0.f, 0.f, false, false, offsetof(object, field), sizeof(((object *)0)->field), 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLAG_RO(name, object, field, bit) \
+	{ name, KX_PYATTRIBUTE_TYPE_FLAG, KX_PYATTRIBUTE_RO, bit, 0, 0.f, 0.f, false, false, offsetof(object, field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
 
 /* attribute points to a single bit of an integer field, attribute=true if bit is set*/
-#define KX_PYATTRIBUTE_FLAG_NEGATIVE_RW(name,object,field,bit) \
-	{ name, KX_PYATTRIBUTE_TYPE_FLAG, KX_PYATTRIBUTE_RW, bit, 1, 0.f, 0.f, false, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_FLAG_NEGATIVE_RW_CHECK(name,object,field,bit,function) \
-	{ name, KX_PYATTRIBUTE_TYPE_FLAG, KX_PYATTRIBUTE_RW, bit, 1, 0.f, 0.f, false, false, offsetof(object,field), sizeof(((object *)0)->field), 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_FLAG_NEGATIVE_RO(name,object,field,bit) \
-	{ name, KX_PYATTRIBUTE_TYPE_FLAG, KX_PYATTRIBUTE_RO, bit, 1, 0.f, 0.f, false, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLAG_NEGATIVE_RW(name, object, field, bit) \
+	{ name, KX_PYATTRIBUTE_TYPE_FLAG, KX_PYATTRIBUTE_RW, bit, 1, 0.f, 0.f, false, false, offsetof(object, field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLAG_NEGATIVE_RW_CHECK(name, object, field, bit, function) \
+	{ name, KX_PYATTRIBUTE_TYPE_FLAG, KX_PYATTRIBUTE_RW, bit, 1, 0.f, 0.f, false, false, offsetof(object, field), sizeof(((object *)0)->field), 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLAG_NEGATIVE_RO(name, object, field, bit) \
+	{ name, KX_PYATTRIBUTE_TYPE_FLAG, KX_PYATTRIBUTE_RO, bit, 1, 0.f, 0.f, false, false, offsetof(object, field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
 
 // enum field cannot be mapped to pointer (because we would need a pointer for each enum)
 // use field size to verify mapping at runtime only, assuming enum size is equal to int size.
-#define KX_PYATTRIBUTE_ENUM_RW(name,min,max,clamp,object,field) \
-	{ name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_ENUM_RW_CHECK(name,min,max,clamp,object,field,function) \
-	{ name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), sizeof(((object *)0)->field), 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_ENUM_RO(name,object,field) \
-	{ name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
-
-#define KX_PYATTRIBUTE_SHORT_RW(name,min,max,clamp,object,field) \
-	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_SHORT_RW_CHECK(name,min,max,clamp,object,field,function) \
-	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_SHORT_RO(name,object,field) \
-	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_SHORT_ARRAY_RW(name,min,max,clamp,object,field,length) \
-	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_SHORT_ARRAY_RW_CHECK(name,min,max,clamp,object,field,length,function) \
-	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_SHORT_ARRAY_RO(name,object,field,length) \
-	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_ENUM_RW(name, min, max, clamp, object, field) \
+	{ name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_ENUM_RW_CHECK(name, min, max, clamp, object, field, function) \
+	{ name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), sizeof(((object *)0)->field), 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_ENUM_RO(name, object, field) \
+	{ name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object, field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
+
+#define KX_PYATTRIBUTE_SHORT_RW(name, min, max, clamp, object, field) \
+	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), 0, 1, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_SHORT_RW_CHECK(name, min, max, clamp, object, field, function) \
+	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), 0, 1, &object::function, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_SHORT_RO(name, object, field) \
+	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object, field), 0, 1, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_SHORT_ARRAY_RW(name, min, max, clamp, object, field, length) \
+	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), 0, length, NULL, NULL, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_SHORT_ARRAY_RW_CHECK(name, min, max, clamp, object, field, length, function) \
+	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), 0, length, &object::function, NULL, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_SHORT_ARRAY_RO(name, object, field, length) \
+	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object, field), 0, length, NULL, NULL, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
 // SHORT_LIST
-#define KX_PYATTRIBUTE_SHORT_LIST_RW(name,min,max,clamp,object,field,length) \
-	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_SHORT_LIST_RW_CHECK(name,min,max,clamp,object,field,length,function) \
-	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_SHORT_LIST_RO(name,object,field,length) \
-	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
-
-#define KX_PYATTRIBUTE_INT_RW(name,min,max,clamp,object,field) \
-	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_INT_RW_CHECK(name,min,max,clamp,object,field,function) \
-	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_INT_RO(name,object,field) \
-	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_INT_ARRAY_RW(name,min,max,clamp,object,field,length) \
-	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_INT_ARRAY_RW_CHECK(name,min,max,clamp,object,field,length,function) \
-	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_INT_ARRAY_RO(name,object,field,length) \
-	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_SHORT_LIST_RW(name, min, max, clamp, object, field, length) \
+	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), 0, length, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_SHORT_LIST_RW_CHECK(name, min, max, clamp, object, field, length, function) \
+	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), 0, length, &object::function, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_SHORT_LIST_RO(name, object, field, length) \
+	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object, field), 0, length, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
+
+#define KX_PYATTRIBUTE_INT_RW(name, min, max, clamp, object, field) \
+	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), 0, 1, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_INT_RW_CHECK(name, min, max, clamp, object, field, function) \
+	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_INT_RO(name, object, field) \
+	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object, field), 0, 1, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_INT_ARRAY_RW(name, min, max, clamp, object, field, length) \
+	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), 0, length, NULL, NULL, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_INT_ARRAY_RW_CHECK(name, min, max, clamp, object, field, length, function) \
+	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), 0, length, &object::function, NULL, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_INT_ARRAY_RO(name, object, field, length) \
+	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object, field), 0, length, NULL, NULL, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL, NULL, NULL} }
 // INT_LIST
-#define KX_PYATTRIBUTE_INT_LIST_RW(name,min,max,clamp,object,field,length) \
-	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_INT_LIST_RW_CHECK(name,min,max,clamp,object,field,length,function) \
-	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_INT_LIST_RO(name,object,field,length) \
-	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_INT_LIST_RW(name, min, max, clamp, object, field, length) \
+	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), 0, length, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_INT_LIST_RW_CHECK(name, min, max, clamp, object, field, length, function) \
+	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), 0, length, &object::function, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_INT_LIST_RO(name, object, field, length) \
+	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object, field), 0, length, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
 
 // always clamp for float
-#define KX_PYATTRIBUTE_FLOAT_RW(name,min,max,object,field) \
-	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_FLOAT_RW_CHECK(name,min,max,object,field,function) \
-	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, false, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_FLOAT_RO(name,object,field) \
-	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLOAT_RW(name, min, max, object, field) \
+	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, false, offsetof(object, field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLOAT_RW_CHECK(name, min, max, object, field, function) \
+	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, false, offsetof(object, field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLOAT_RO(name, object, field) \
+	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object, field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL, NULL, NULL} }
 // field must be float[n], returns a sequence
-#define KX_PYATTRIBUTE_FLOAT_ARRAY_RW(name,min,max,object,field,length) \
-	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_FLOAT_ARRAY_RW_CHECK(name,min,max,object,field,length,function) \
-	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, false, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_FLOAT_ARRAY_RO(name,object,field,length) \
-	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLOAT_ARRAY_RW(name, min, max, object, field, length) \
+	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, false, offsetof(object, field), 0, length, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLOAT_ARRAY_RW_CHECK(name, min, max, object, field, length, function) \
+	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, false, offsetof(object, field), 0, length, &object::function, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLOAT_ARRAY_RO(name, object, field, length) \
+	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object, field), 0, length, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} }
 // field must be float[n], returns a vector
-#define KX_PYATTRIBUTE_FLOAT_VECTOR_RW(name,min,max,object,field,length) \
-	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, length, min, max, true, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_FLOAT_VECTOR_RW_CHECK(name,min,max,object,field,length,function) \
-	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, length, min, max, true, false, offsetof(object,field), sizeof(((object *)0)->field), 1, &object::function, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_FLOAT_VECTOR_RO(name,object,field,length) \
-	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, length, 0.f, 0.f, false, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLOAT_VECTOR_RW(name, min, max, object, field, length) \
+	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, length, min, max, true, false, offsetof(object, field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLOAT_VECTOR_RW_CHECK(name, min, max, object, field, length, function) \
+	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, length, min, max, true, false, offsetof(object, field), sizeof(((object *)0)->field), 1, &object::function, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLOAT_VECTOR_RO(name, object, field, length) \
+	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, length, 0.f, 0.f, false, false, offsetof(object, field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} }
 // field must be float[n][n], returns a matrix
-#define KX_PYATTRIBUTE_FLOAT_MATRIX_RW(name,min,max,object,field,length) \
-	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, length, length, min, max, true, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field[0], NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_FLOAT_MATRIX_RW_CHECK(name,min,max,object,field,length,function) \
-	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, length, length, min, max, true, false, offsetof(object,field), sizeof(((object *)0)->field), 1, &object::function, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field[0], NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_FLOAT_MATRIX_RO(name,object,field,length) \
-	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, length, length, 0.f, 0.f, false, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field[0], NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLOAT_MATRIX_RW(name, min, max, object, field, length) \
+	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, length, length, min, max, true, false, offsetof(object, field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field[0], NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLOAT_MATRIX_RW_CHECK(name, min, max, object, field, length, function) \
+	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, length, length, min, max, true, false, offsetof(object, field), sizeof(((object *)0)->field), 1, &object::function, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field[0], NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLOAT_MATRIX_RO(name, object, field, length) \
+	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, length, length, 0.f, 0.f, false, false, offsetof(object, field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field[0], NULL, NULL, NULL} }
 
 // only for STR_String member
-#define KX_PYATTRIBUTE_STRING_RW(name,min,max,clamp,object,field) \
-	{ name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field, NULL, NULL} }
-#define KX_PYATTRIBUTE_STRING_RW_CHECK(name,min,max,clamp,object,field,function) \
-	{ name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field, NULL, NULL} }
-#define KX_PYATTRIBUTE_STRING_RO(name,object,field) \
-	{ name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object,field), 0, 1 , NULL, NULL, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field, NULL, NULL} }
+#define KX_PYATTRIBUTE_STRING_RW(name, min, max, clamp, object, field) \
+	{ name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field, NULL, NULL} }
+#define KX_PYATTRIBUTE_STRING_RW_CHECK(name, min, max, clamp, object, field, function) \
+	{ name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field, NULL, NULL} }
+#define KX_PYATTRIBUTE_STRING_RO(name, object, field) \
+	{ name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object, field), 0, 1 , NULL, NULL, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field, NULL, NULL} }
 
 // only for char [] array 
-#define KX_PYATTRIBUTE_CHAR_RW(name,object,field) \
-	{ name, KX_PYATTRIBUTE_TYPE_CHAR, KX_PYATTRIBUTE_RW, 0, 0, 0.f, 0.f, true, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, ((object *)0)->field} }
-#define KX_PYATTRIBUTE_CHAR_RW_CHECK(name,object,field,function) \
-	{ name, KX_PYATTRIBUTE_TYPE_CHAR, KX_PYATTRIBUTE_RW, 0, 0, 0.f, 0.f, true, false, offsetof(object,field), sizeof(((object *)0)->field), 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, ((object *)0)->field} }
-#define KX_PYATTRIBUTE_CHAR_RO(name,object,field) \
-	{ name, KX_PYATTRIBUTE_TYPE_CHAR, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object,field), sizeof(((object *)0)->field), 1 , NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, ((object *)0)->field} }
+#define KX_PYATTRIBUTE_CHAR_RW(name, object, field) \
+	{ name, KX_PYATTRIBUTE_TYPE_CHAR, KX_PYATTRIBUTE_RW, 0, 0, 0.f, 0.f, true, false, offsetof(object, field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, ((object *)0)->field} }
+#define KX_PYATTRIBUTE_CHAR_RW_CHECK(name, object, field, function) \
+	{ name, KX_PYATTRIBUTE_TYPE_CHAR, KX_PYATTRIBUTE_RW, 0, 0, 0.f, 0.f, true, false, offsetof(object, field), sizeof(((object *)0)->field), 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, ((object *)0)->field} }
+#define KX_PYATTRIBUTE_CHAR_RO(name, object, field) \
+	{ name, KX_PYATTRIBUTE_TYPE_CHAR, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object, field), sizeof(((object *)0)->field), 1 , NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, ((object *)0)->field} }
 
 // for MT_Vector3 member
-#define KX_PYATTRIBUTE_VECTOR_RW(name,min,max,object,field) \
-	{ name, KX_PYATTRIBUTE_TYPE_VECTOR, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, &((object *)0)->field, NULL} }
-#define KX_PYATTRIBUTE_VECTOR_RW_CHECK(name,min,max,clamp,object,field,function) \
-	{ name, KX_PYATTRIBUTE_TYPE_VECTOR, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, false, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, &((object *)0)->field, NULL} }
-#define KX_PYATTRIBUTE_VECTOR_RO(name,object,field) \
-	{ name, KX_PYATTRIBUTE_TYPE_VECTOR, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object,field), 0, 1 , NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, &((object *)0)->field, NULL} }
-
-#define KX_PYATTRIBUTE_RW_FUNCTION(name,object,getfunction,setfunction) \
+#define KX_PYATTRIBUTE_VECTOR_RW(name, min, max, object, field) \
+	{ name, KX_PYATTRIBUTE_TYPE_VECTOR, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, false, offsetof(object, field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, &((object *)0)->field, NULL} }
+#define KX_PYATTRIBUTE_VECTOR_RW_CHECK(name, min, max, clamp, object, field, function) \
+	{ name, KX_PYATTRIBUTE_TYPE_VECTOR, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, false, offsetof(object, field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, &((object *)0)->field, NULL} }
+#define KX_PYATTRIBUTE_VECTOR_RO(name, object, field) \
+	{ name, KX_PYATTRIBUTE_TYPE_VECTOR, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object, field), 0, 1 , NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, &((object *)0)->field, NULL} }
+
+#define KX_PYATTRIBUTE_RW_FUNCTION(name, object, getfunction, setfunction) \
 	{ name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RW, 0, 0, 0.f, 0.f, false, false, 0, 0, 1, NULL, &object::setfunction, &object::getfunction, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_RO_FUNCTION(name,object,getfunction) \
+#define KX_PYATTRIBUTE_RO_FUNCTION(name, object, getfunction) \
 	{ name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, 0, 0, 1, NULL, NULL, &object::getfunction, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_ARRAY_RW_FUNCTION(name,object,length,getfunction,setfunction) \
-	{ name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RW, 0, 0, 0.f, 0,f, false, false, 0, 0, length, NULL, &object::setfunction, &object::getfunction, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_ARRAY_RO_FUNCTION(name,object,length,getfunction) \
-	{ name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0,f, false, false, 0, 0, length, NULL, NULL, &object::getfunction, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_ARRAY_RW_FUNCTION(name, object, length, getfunction, setfunction) \
+	{ name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RW, 0, 0, 0.f, 0, f, false, false, 0, 0, length, NULL, &object::setfunction, &object::getfunction, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_ARRAY_RO_FUNCTION(name, object, length, getfunction) \
+	{ name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0, f, false, false, 0, 0, length, NULL, NULL, &object::getfunction, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
 
 
 /*------------------------------
@@ -614,7 +614,7 @@ public:
 	/** enable/disable display of deprecation warnings */
 	static void			SetDeprecationWarnings(bool ignoreDeprecationWarnings);
 	/** Shows a deprecation warning */
-	static void			ShowDeprecationWarning_func(const char* method,const char* prop);
+	static void			ShowDeprecationWarning_func(const char *method, const char *prop);
 	static void			ClearDeprecationWarning();
 	
 #endif
diff --git a/source/gameengine/GameLogic/SCA_PythonJoystick.cpp b/source/gameengine/GameLogic/SCA_PythonJoystick.cpp
index ee792111705..8c0a0c5ae33 100644
--- a/source/gameengine/GameLogic/SCA_PythonJoystick.cpp
+++ b/source/gameengine/GameLogic/SCA_PythonJoystick.cpp
@@ -122,14 +122,14 @@ PyObject* SCA_PythonJoystick::pyattr_get_active_buttons(void *self_v, const KX_P
 {
 	SCA_PythonJoystick* self = static_cast(self_v);
 	
-	int button_index = self->m_joystick->GetNumberOfButtons();
+	const int button_number = self->m_joystick->GetNumberOfButtons();
 
 	PyObject *list = PyList_New(0);
 	PyObject *value;
 
-	for (int i=0; i < self->m_joystick->GetNumberOfButtons(); i++) {
+	for (int i=0; i < button_number; i++) {
 		if (self->m_joystick->aButtonPressIsPositive(i)) {
-			value = PyLong_FromSsize_t(i);
+			value = PyLong_FromLong(i);
 			PyList_Append(list, value);
 			Py_DECREF(value);
 		}
-- 
cgit v1.2.3


From c157f815a84b039a59d80fa5ece89c11b59274c9 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Sat, 29 Dec 2012 02:57:52 +0000
Subject: code cleanup

---
 source/blender/editors/space_text/text_format.c    |  8 ++++
 source/blender/editors/space_text/text_format.h    |  2 +
 source/blender/editors/space_text/text_format_py.c | 48 ++++++++++------------
 3 files changed, 31 insertions(+), 27 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/space_text/text_format.c b/source/blender/editors/space_text/text_format.c
index 0b3856f4414..f7940fc7894 100644
--- a/source/blender/editors/space_text/text_format.c
+++ b/source/blender/editors/space_text/text_format.c
@@ -113,6 +113,14 @@ void flatten_string_free(FlattenString *fs)
 		MEM_freeN(fs->accum);
 }
 
+/* takes a string within fs->buf and returns its length */
+int flatten_string_strlen(FlattenString *fs, const char *str)
+{
+	const int len = (fs->pos - (int)(str - fs->buf)) - 1;
+	BLI_assert(strlen(str) == len);
+	return len;
+}
+
 /* Ensures the format string for the given line is long enough, reallocating
  * as needed. Allocation is done here, alone, to ensure consistency. */
 int text_check_format_len(TextLine *line, unsigned int len)
diff --git a/source/blender/editors/space_text/text_format.h b/source/blender/editors/space_text/text_format.h
index 7b5b326db6a..02c5f433b57 100644
--- a/source/blender/editors/space_text/text_format.h
+++ b/source/blender/editors/space_text/text_format.h
@@ -43,6 +43,8 @@ typedef struct FlattenString {
 
 int  flatten_string(struct SpaceText *st, FlattenString *fs, const char *in);
 void flatten_string_free(FlattenString *fs);
+int  flatten_string_strlen(FlattenString *fs, const char *str);
+
 int  text_check_format_len(TextLine *line, unsigned int len);
 
 
diff --git a/source/blender/editors/space_text/text_format_py.c b/source/blender/editors/space_text/text_format_py.c
index c4d4b6b1c2f..656c4dbaa93 100644
--- a/source/blender/editors/space_text/text_format_py.c
+++ b/source/blender/editors/space_text/text_format_py.c
@@ -53,7 +53,7 @@
  * http://docs.python.org/py3k/reference/lexical_analysis.html#keywords
  */
 
-static int txtfmt_py_find_builtinfunc(char *string)
+static int txtfmt_py_find_builtinfunc(const char *string)
 {
 	int a, i;
 	/* list is from...
@@ -98,22 +98,20 @@ static int txtfmt_py_find_builtinfunc(char *string)
  * If a special name is found, the length of the matching name is returned.
  * Otherwise, -1 is returned. */
 
-static int txtfmt_py_find_specialvar(char *string)
+static int txtfmt_py_find_specialvar(const char *string)
 {
-	int i = 0;
-	/* Check for "def" */
-	if (string[0] == 'd' && string[1] == 'e' && string[2] == 'f')
-		i = 3;
-	/* Check for "class" */
-	else if (string[0] == 'c' && string[1] == 'l' && string[2] == 'a' && string[3] == 's' && string[4] == 's')
-		i = 5;
+	int i;
+	if      (strncmp(string, "def",   3) == 0) i = 3;
+	else if (strncmp(string, "class", 5) == 0) i = 5;
+	else                                       i = 0;
+
 	/* If next source char is an identifier (eg. 'i' in "definate") no match */
 	if (i == 0 || text_check_identifier(string[i]))
 		return -1;
 	return i;
 }
 
-static int txtfmt_py_find_decorator(char *string)
+static int txtfmt_py_find_decorator(const char *string)
 {
 	if (string[0] == '@') {
 		int i = 1;
@@ -125,28 +123,26 @@ static int txtfmt_py_find_decorator(char *string)
 	return -1;
 }
 
-static int txtfmt_py_find_bool(char *string)
+static int txtfmt_py_find_bool(const char *string)
 {
-	int i = 0;
-	/* Check for "False" */
-	if (string[0] == 'F' && string[1] == 'a' && string[2] == 'l' && string[3] == 's' && string[4] == 'e')
-		i = 5;
-	/* Check for "True" */
-	else if (string[0] == 'T' && string[1] == 'r' && string[2] == 'u' && string[3] == 'e')
-		i = 4;
-	/* Check for "None" */
-	else if (string[0] == 'N' && string[1] == 'o' && string[2] == 'n' && string[3] == 'e')
-		i = 4;
-	/* If next source char is an identifier (eg. 'i' in "definate") no match */
+	int i;
+	if      (strncmp(string, "None",  4) == 0) i = 4;
+	else if (strncmp(string, "True",  4) == 0) i = 4;
+	else if (strncmp(string, "False", 5) == 0) i = 5;
+	else                                       i = 0;
+
+	/* If next source char is an identifier (eg. 'i' in "Nonetheless") no match */
 	if (i == 0 || text_check_identifier(string[i]))
 		return -1;
 	return i;
 }
 
-static void txtfmt_py_format_line(SpaceText *st, TextLine *line, int do_next)
+static void txtfmt_py_format_line(SpaceText *st, TextLine *line, const int do_next)
 {
 	FlattenString fs;
-	char *str, *fmt, orig, cont, find, prev = ' ';
+	const char *str;
+	char *fmt;
+	char orig, cont, find, prev = ' ';
 	int len, i;
 
 	/* Get continuation from previous line */
@@ -270,9 +266,7 @@ static void txtfmt_py_format_line(SpaceText *st, TextLine *line, int do_next)
 				}
 			}
 		}
-		prev = *fmt;
-		fmt++;
-		str++;
+		prev = *fmt; fmt++; str++;
 	}
 
 	/* Terminate and add continuation char */
-- 
cgit v1.2.3


From 7d68b37032d4eaa42520a5722c62708983df890d Mon Sep 17 00:00:00 2001
From: Mitchell Stokes 
Date: Sat, 29 Dec 2012 04:03:25 +0000
Subject: BGE: Fix for [#33685] "2D Filters Partially Offset" reported by
 Josiah Lane (solarlune). This bug was caused by me in a recent change to
 clean up the 2D filters a bit. I forgot that canvas->SetViewPort already
 handles some viewport calculations, and thus I ended up doubling up on
 calculations, which caused the offset.

---
 source/gameengine/Rasterizer/RAS_2DFilterManager.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp
index 152c6bcce4e..a379b851293 100644
--- a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp
+++ b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp
@@ -428,7 +428,7 @@ void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas)
 
 	// reverting to texunit 0, without this we get bug [#28462]
 	glActiveTextureARB(GL_TEXTURE0);
-	canvas->SetViewPort(rect.GetLeft(), rect.GetBottom(), rect_width, rect_height);
+	canvas->SetViewPort(0, 0, rect_width, rect_height);
 
 	glDisable(GL_DEPTH_TEST);
 	// in case the previous material was wire
-- 
cgit v1.2.3


From 0cb07bcabcad6a8090750470cd834210cce08318 Mon Sep 17 00:00:00 2001
From: Mitchell Stokes 
Date: Sat, 29 Dec 2012 08:36:41 +0000
Subject: BGE: An off-by-one error when setting up the viewport for 2D filters
 caused a blurring effect when using 2D filters. This is now fixed.

---
 source/gameengine/Rasterizer/RAS_2DFilterManager.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp
index a379b851293..ab0f62c84c7 100644
--- a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp
+++ b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp
@@ -428,7 +428,7 @@ void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas)
 
 	// reverting to texunit 0, without this we get bug [#28462]
 	glActiveTextureARB(GL_TEXTURE0);
-	canvas->SetViewPort(0, 0, rect_width, rect_height);
+	canvas->SetViewPort(0, 0, rect_width-1, rect_height-1);
 
 	glDisable(GL_DEPTH_TEST);
 	// in case the previous material was wire
-- 
cgit v1.2.3


From 7d6ea8cddf326332679255c4b3dfe89cd4617cc2 Mon Sep 17 00:00:00 2001
From: Mitchell Stokes 
Date: Sat, 29 Dec 2012 09:44:19 +0000
Subject: Finally fixing the issue where the bezier curve drawn while creating
 a link between two logic bricks doesn't match the mouse cursor location. The
 issue was the last line segment for the bezier curve was not getting drawn.
 This is why the error increased as the curve got longer.

---
 source/blender/editors/interface/interface_widgets.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 7fa5ceb5fe3..eb19812876e 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -2319,7 +2319,7 @@ void ui_draw_link_bezier(const rcti *rect)
 
 		glEnableClientState(GL_VERTEX_ARRAY);
 		glVertexPointer(2, GL_FLOAT, 0, coord_array);
-		glDrawArrays(GL_LINE_STRIP, 0, LINK_RESOL);
+		glDrawArrays(GL_LINE_STRIP, 0, LINK_RESOL+1);
 		glDisableClientState(GL_VERTEX_ARRAY);
 
 		glDisable(GL_BLEND);
-- 
cgit v1.2.3


From 18f134304c0c6181668a0a8c22289fcaeb472432 Mon Sep 17 00:00:00 2001
From: Mitchell Stokes 
Date: Sat, 29 Dec 2012 10:22:19 +0000
Subject: BGE: Adding a jumpCount to KX_CharacterWrapper. This can be used to
 have different logic for a single jump versus a double jump. For example, a
 different animation for the second jump.

---
 source/gameengine/Ketsji/KX_CharacterWrapper.cpp           | 9 +++++++++
 source/gameengine/Ketsji/KX_CharacterWrapper.h             | 1 +
 source/gameengine/Physics/Bullet/CcdPhysicsController.cpp  | 5 +++++
 source/gameengine/Physics/Bullet/CcdPhysicsController.h    | 2 ++
 source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp | 5 +++++
 source/gameengine/Physics/common/PHY_ICharacter.h          | 2 ++
 6 files changed, 24 insertions(+)

(limited to 'source')

diff --git a/source/gameengine/Ketsji/KX_CharacterWrapper.cpp b/source/gameengine/Ketsji/KX_CharacterWrapper.cpp
index dfd19a0d2bd..64bbbb7d344 100644
--- a/source/gameengine/Ketsji/KX_CharacterWrapper.cpp
+++ b/source/gameengine/Ketsji/KX_CharacterWrapper.cpp
@@ -46,6 +46,7 @@ PyAttributeDef KX_CharacterWrapper::Attributes[] = {
 	KX_PYATTRIBUTE_RO_FUNCTION("onGround", KX_CharacterWrapper, pyattr_get_onground),
 	KX_PYATTRIBUTE_RW_FUNCTION("gravity", KX_CharacterWrapper, pyattr_get_gravity, pyattr_set_gravity),
 	KX_PYATTRIBUTE_RW_FUNCTION("maxJumps", KX_CharacterWrapper, pyattr_get_max_jumps, pyattr_set_max_jumps),
+	KX_PYATTRIBUTE_RO_FUNCTION("jumpCount", KX_CharacterWrapper, pyattr_get_jump_count),
 	{ NULL }	//Sentinel
 };
 
@@ -99,6 +100,14 @@ int KX_CharacterWrapper::pyattr_set_max_jumps(void *self_v, const KX_PYATTRIBUTE
 	self->m_character->SetMaxJumps((int)param);
 	return PY_SET_ATTR_SUCCESS;
 }
+
+PyObject *KX_CharacterWrapper::pyattr_get_jump_count(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_CharacterWrapper* self = static_cast(self_v);
+
+	return PyLong_FromLong(self->m_character->GetJumpCount());
+}
+
 PyMethodDef KX_CharacterWrapper::Methods[] = {
 	KX_PYMETHODTABLE_NOARGS(KX_CharacterWrapper, jump),
 	{NULL,NULL} //Sentinel
diff --git a/source/gameengine/Ketsji/KX_CharacterWrapper.h b/source/gameengine/Ketsji/KX_CharacterWrapper.h
index 1161be2c611..f1c977f4e5d 100644
--- a/source/gameengine/Ketsji/KX_CharacterWrapper.h
+++ b/source/gameengine/Ketsji/KX_CharacterWrapper.h
@@ -28,6 +28,7 @@ public:
 	static int			pyattr_set_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
 	static PyObject*	pyattr_get_max_jumps(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
 	static int			pyattr_set_max_jumps(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+	static PyObject*	pyattr_get_jump_count(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
 #endif // WITH_PYTHON
 
 private:
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
index 66c6d1aa251..cf96f22a345 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
@@ -92,6 +92,11 @@ void BlenderBulletCharacterController::setMaxJumps(int maxJumps)
 	m_maxJumps = maxJumps;
 }
 
+int BlenderBulletCharacterController::getJumpCount() const
+{
+	return m_jumps;
+}
+
 bool BlenderBulletCharacterController::canJump() const
 {
 	return onGround() || m_jumps < m_maxJumps;
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
index 91b2e558521..b151c2f6b59 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
@@ -412,6 +412,8 @@ public:
 
 	void setMaxJumps(int maxJumps);
 
+	int getJumpCount() const;
+
 	virtual bool canJump() const;
 
 	virtual void jump();
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
index f1224babcf7..cadba97023e 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
@@ -305,6 +305,11 @@ public:
 	{
 		m_controller->setMaxJumps(maxJumps);
 	}
+
+	virtual int GetJumpCount()
+	{
+		return m_controller->getJumpCount();
+	}
 };
 
 class CcdOverlapFilterCallBack : public btOverlapFilterCallback
diff --git a/source/gameengine/Physics/common/PHY_ICharacter.h b/source/gameengine/Physics/common/PHY_ICharacter.h
index 92c00949c4d..63f6c0bd18a 100644
--- a/source/gameengine/Physics/common/PHY_ICharacter.h
+++ b/source/gameengine/Physics/common/PHY_ICharacter.h
@@ -25,6 +25,8 @@ public:
 	virtual int GetMaxJumps()= 0;
 	virtual void SetMaxJumps(int maxJumps)= 0;
 
+	virtual int GetJumpCount()= 0;
+
 #ifdef WITH_CXX_GUARDEDALLOC
 	MEM_CXX_CLASS_ALLOC_FUNCS("GE:PHY_ICharacter")
 #endif
-- 
cgit v1.2.3


From 79c2571e56e79c28d6f22984112387d83782162a Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Sat, 29 Dec 2012 10:24:42 +0000
Subject: user-preferences for addons. currently unused, example & docs still
 to come.

---
 source/blender/blenkernel/BKE_addon.h              |  42 +++++++
 source/blender/blenkernel/CMakeLists.txt           |   2 +
 source/blender/blenkernel/intern/addon.c           |  84 ++++++++++++++
 source/blender/blenkernel/intern/blender.c         |  11 +-
 source/blender/blenloader/intern/readfile.c        |  10 +-
 source/blender/blenloader/intern/writefile.c       |   6 +-
 source/blender/makesdna/DNA_userdef_types.h        |   1 +
 source/blender/makesrna/RNA_access.h               |   1 +
 source/blender/makesrna/intern/rna_userdef.c       | 128 +++++++++++++++++++++
 source/blender/windowmanager/intern/wm_init_exit.c |   6 +
 10 files changed, 288 insertions(+), 3 deletions(-)
 create mode 100644 source/blender/blenkernel/BKE_addon.h
 create mode 100644 source/blender/blenkernel/intern/addon.c

(limited to 'source')

diff --git a/source/blender/blenkernel/BKE_addon.h b/source/blender/blenkernel/BKE_addon.h
new file mode 100644
index 00000000000..eafaec3e605
--- /dev/null
+++ b/source/blender/blenkernel/BKE_addon.h
@@ -0,0 +1,42 @@
+/*
+ * ***** 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): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef __BKE_ADDON_H__
+#define __BKE_ADDON_H__
+
+#include "RNA_types.h"
+
+typedef struct bAddonPrefType {
+	/* type info */
+	char idname[64]; // best keep the same size as BKE_ST_MAXNAME
+
+	/* RNA integration */
+	ExtensionRNA ext;
+} bAddonPrefType;
+
+bAddonPrefType *BKE_addon_pref_type_find(const char *idname, int quiet);
+void            BKE_addon_pref_type_add(bAddonPrefType *apt);
+void            BKE_addon_pref_type_remove(bAddonPrefType *apt);
+
+void            BKE_addon_pref_type_init(void);
+void            BKE_addon_pref_type_free(void);
+
+#endif  /* __BKE_ADDON_H__ */
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index b350cb718c8..2502773e7f5 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -58,6 +58,7 @@ set(SRC
 	intern/CCGSubSurf.c
 	intern/DerivedMesh.c
 	intern/action.c
+	intern/addon.c
 	intern/anim.c
 	intern/anim_sys.c
 	intern/armature.c
@@ -152,6 +153,7 @@ set(SRC
 
 	BKE_DerivedMesh.h
 	BKE_action.h
+	BKE_addon.h
 	BKE_anim.h
 	BKE_animsys.h
 	BKE_armature.h
diff --git a/source/blender/blenkernel/intern/addon.c b/source/blender/blenkernel/intern/addon.c
new file mode 100644
index 00000000000..a1b9eb8d970
--- /dev/null
+++ b/source/blender/blenkernel/intern/addon.c
@@ -0,0 +1,84 @@
+/*
+ * ***** 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): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include 
+
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+#include "BLI_string.h"
+
+#include "BKE_addon.h"  /* own include */
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "BLF_translation.h"
+
+#include "MEM_guardedalloc.h"
+
+static GHash *global_addonpreftype_hash = NULL;
+
+
+bAddonPrefType *BKE_addon_pref_type_find(const char *idname, int quiet)
+{
+	if (idname[0]) {
+		bAddonPrefType *apt;
+
+		apt = BLI_ghash_lookup(global_addonpreftype_hash, idname);
+		if (apt) {
+			return apt;
+		}
+
+		if (!quiet) {
+			printf("search for unknown addon-ref '%s'\n", idname);
+		}
+	}
+	else {
+		if (!quiet) {
+			printf("search for empty addon");
+		}
+	}
+
+	return NULL;
+}
+
+void BKE_addon_pref_type_add(bAddonPrefType *apt)
+{
+	BLI_ghash_insert(global_addonpreftype_hash, (void *)apt->idname, apt);
+}
+
+void BKE_addon_pref_type_remove(bAddonPrefType *apt)
+{
+	BLI_ghash_remove(global_addonpreftype_hash, (void *)apt->idname, NULL, (GHashValFreeFP)MEM_freeN);
+}
+
+void BKE_addon_pref_type_init(void)
+{
+	BLI_assert(global_addonpreftype_hash == NULL);
+	global_addonpreftype_hash = BLI_ghash_str_new(__func__);
+}
+
+void BKE_addon_pref_type_free(void)
+{
+	BLI_ghash_free(global_addonpreftype_hash, NULL, (GHashValFreeFP)MEM_freeN);
+	global_addonpreftype_hash = NULL;
+}
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index 5c0856bc95b..11ae242023c 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -387,6 +387,7 @@ void BKE_userdef_free(void)
 	wmKeyMap *km;
 	wmKeyMapItem *kmi;
 	wmKeyMapDiffItem *kmdi;
+	bAddon *addon, *addon_next;
 
 	for (km = U.user_keymaps.first; km; km = km->next) {
 		for (kmdi = km->diff_items.first; kmdi; kmdi = kmdi->next) {
@@ -407,11 +408,19 @@ void BKE_userdef_free(void)
 		BLI_freelistN(&km->items);
 	}
 	
+	for (addon = U.addons.first; addon; addon = addon_next) {
+		addon_next = addon->next;
+		if (addon->prop) {
+			IDP_FreeProperty(addon->prop);
+			MEM_freeN(addon->prop);
+		}
+		MEM_freeN(addon);
+	}
+
 	BLI_freelistN(&U.uistyles);
 	BLI_freelistN(&U.uifonts);
 	BLI_freelistN(&U.themes);
 	BLI_freelistN(&U.user_keymaps);
-	BLI_freelistN(&U.addons);
 }
 
 /* handle changes in settings that need recalc */
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index eda2cb4243a..8ddd69f2f03 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -8646,6 +8646,7 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead)
 	wmKeyMap *keymap;
 	wmKeyMapItem *kmi;
 	wmKeyMapDiffItem *kmdi;
+	bAddon *addon;
 	
 	bfd->user = user= read_struct(fd, bhead, "user def");
 	
@@ -8683,7 +8684,14 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead)
 		for (kmi=keymap->items.first; kmi; kmi=kmi->next)
 			direct_link_keymapitem(fd, kmi);
 	}
-	
+
+	for (addon = user->addons.first; addon; addon = addon->next) {
+		addon->prop = newdataadr(fd, addon->prop);
+		if (addon->prop) {
+			IDP_DirectLinkProperty(addon->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+		}
+	}
+
 	// XXX
 	user->uifonts.first = user->uifonts.last= NULL;
 	
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index b1dce046438..680a02eed30 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -850,8 +850,12 @@ static void write_userdef(WriteData *wd)
 			write_keymapitem(wd, kmi);
 	}
 
-	for (bext= U.addons.first; bext; bext=bext->next)
+	for (bext= U.addons.first; bext; bext=bext->next) {
 		writestruct(wd, DATA, "bAddon", 1, bext);
+		if (bext->prop) {
+			IDP_WriteProperty(bext->prop, wd);
+		}
+	}
 	
 	for (style= U.uistyles.first; style; style= style->next) {
 		writestruct(wd, DATA, "uiStyle", 1, style);
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index acd789e7aae..1dc25e0ab5e 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -343,6 +343,7 @@ typedef struct bTheme {
 typedef struct bAddon {
 	struct bAddon *next, *prev;
 	char module[64];
+	IDProperty *prop;  /* User-Defined Properties on this  Addon (for storing preferences) */
 } bAddon;
 
 typedef struct SolidLight {
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index bf78c622cbd..e2f72ca339d 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -54,6 +54,7 @@ extern StructRNA RNA_ActionPoseMarkers;
 extern StructRNA RNA_Actuator;
 extern StructRNA RNA_ActuatorSensor;
 extern StructRNA RNA_Addon;
+extern StructRNA RNA_AddonPreferences;
 extern StructRNA RNA_AdjustmentSequence;
 extern StructRNA RNA_AlwaysSensor;
 extern StructRNA RNA_AndController;
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index bb7f7cb8820..83076f3a903 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -47,6 +47,7 @@
 #include "BLF_translation.h"
 
 #include "BKE_sound.h"
+#include "BKE_addon.h"
 
 #ifdef WITH_CYCLES
 static EnumPropertyItem compute_device_type_items[] = {
@@ -67,6 +68,7 @@ static EnumPropertyItem compute_device_type_items[] = {
 #include "BKE_depsgraph.h"
 #include "BKE_global.h"
 #include "BKE_main.h"
+#include "BKE_idprop.h"
 
 #include "GPU_draw.h"
 
@@ -79,6 +81,8 @@ static EnumPropertyItem compute_device_type_items[] = {
 
 #include "CCL_api.h"
 
+#include "BKE_addon.h"
+
 static void rna_userdef_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
 {
 	WM_main_add_notifier(NC_WINDOW, NULL);
@@ -428,6 +432,103 @@ static EnumPropertyItem *rna_lang_enum_properties_itemf(bContext *UNUSED(C), Poi
 }
 #endif
 
+static IDProperty *rna_AddonPref_idprops(PointerRNA *ptr, int create)
+{
+	if (create && !ptr->data) {
+		IDPropertyTemplate val = {0};
+		ptr->data = IDP_New(IDP_GROUP, &val, "RNA_AddonPreferences group");
+	}
+
+	return ptr->data;
+}
+
+static PointerRNA rna_Addon_preferences_get(PointerRNA *ptr)
+{
+	bAddon *addon = (bAddon *)ptr->data;
+	bAddonPrefType *apt = BKE_addon_pref_type_find(addon->module, TRUE);
+	if (apt) {
+		if (addon->prop == NULL) {
+			IDPropertyTemplate val = {0};
+			addon->prop = IDP_New(IDP_GROUP, &val, addon->module); /* name is unimportant  */
+		}
+		return rna_pointer_inherit_refine(ptr, apt->ext.srna, addon->prop);
+	}
+	else {
+		return PointerRNA_NULL;
+	}
+}
+
+static void rna_AddonPref_unregister(Main *UNUSED(bmain), StructRNA *type)
+{
+	bAddonPrefType *apt = RNA_struct_blender_type_get(type);
+
+	if (!apt)
+		return;
+
+	RNA_struct_free_extension(type, &apt->ext);
+
+	BKE_addon_pref_type_remove(apt);
+	RNA_struct_free(&BLENDER_RNA, type);
+
+	/* update while blender is running */
+	WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
+}
+
+static StructRNA *rna_AddonPref_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
+                                         StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+	bAddonPrefType *apt, dummyapt = {{'\0'}};
+	bAddon dummyaddon = {NULL};
+	PointerRNA dummyhtr;
+	// int have_function[1];
+
+	/* setup dummy header & header type to store static properties in */
+	RNA_pointer_create(NULL, &RNA_AddonPreferences, &dummyaddon, &dummyhtr);
+
+	/* validate the python class */
+	if (validate(&dummyhtr, data, NULL /* have_function */ ) != 0)
+		return NULL;
+
+	BLI_strncpy(dummyapt.idname, dummyaddon.module, sizeof(dummyapt.idname));
+	if (strlen(identifier) >= sizeof(dummyapt.idname)) {
+		BKE_reportf(reports, RPT_ERROR, "Registering addon-prefs class: '%s' is too long, maximum length is %d",
+		            identifier, (int)sizeof(dummyapt.idname));
+		return NULL;
+	}
+
+	/* check if we have registered this header type before, and remove it */
+	apt = BKE_addon_pref_type_find(dummyaddon.module, TRUE);
+	if (apt) {
+		if (apt->ext.srna) {
+			rna_AddonPref_unregister(bmain, apt->ext.srna);
+		}
+	}
+
+	/* create a new header type */
+	apt = MEM_mallocN(sizeof(bAddonPrefType), "addonpreftype");
+	memcpy(apt, &dummyapt, sizeof(dummyapt));
+	BKE_addon_pref_type_add(apt);
+
+	apt->ext.srna = RNA_def_struct(&BLENDER_RNA, identifier, "AddonPreferences");
+	apt->ext.data = data;
+	apt->ext.call = call;
+	apt->ext.free = free;
+	RNA_struct_blender_type_set(apt->ext.srna, apt);
+
+//	apt->draw = (have_function[0]) ? header_draw : NULL;
+
+	/* update while blender is running */
+	WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
+
+	return apt->ext.srna;
+}
+
+/* placeholder, doesn't do anything useful yet */
+static StructRNA *rna_AddonPref_refine(PointerRNA *ptr)
+{
+	return (ptr->type) ? ptr->type : &RNA_AddonPreferences;
+}
+
 #else
 
 static void rna_def_userdef_theme_ui_font_style(BlenderRNA *brna)
@@ -2381,6 +2482,32 @@ static void rna_def_userdef_addon(BlenderRNA *brna)
 	prop = RNA_def_property(srna, "module", PROP_STRING, PROP_NONE);
 	RNA_def_property_ui_text(prop, "Module", "Module name");
 	RNA_def_struct_name_property(srna, prop);
+
+	/* Collection active property */
+	prop = RNA_def_property(srna, "preferences", PROP_POINTER, PROP_NONE);
+	RNA_def_property_struct_type(prop, "AddonPreferences");
+	RNA_def_property_pointer_funcs(prop, "rna_Addon_preferences_get", NULL, NULL, NULL);
+}
+
+static void rna_def_userdef_addon_pref(BlenderRNA *brna)
+{
+	StructRNA *srna;
+	PropertyRNA *prop;
+
+	srna = RNA_def_struct(brna, "AddonPreferences", NULL);
+	RNA_def_struct_ui_text(srna, "Addon Preferences", "");
+	RNA_def_struct_sdna(srna, "bAddon");  /* WARNING: only a bAddon during registration */
+
+	RNA_def_struct_refine_func(srna, "rna_AddonPref_refine");
+	RNA_def_struct_register_funcs(srna, "rna_AddonPref_register", "rna_AddonPref_unregister", NULL);
+	RNA_def_struct_idprops_func(srna, "rna_AddonPref_idprops");
+
+	/* registration */
+	RNA_define_verify_sdna(0);
+	prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
+	RNA_def_property_string_sdna(prop, NULL, "module");
+	RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
+	RNA_define_verify_sdna(1);
 }
 
 
@@ -3736,6 +3863,7 @@ void RNA_def_userdef(BlenderRNA *brna)
 	rna_def_userdef_filepaths(brna);
 	rna_def_userdef_system(brna);
 	rna_def_userdef_addon(brna);
+	rna_def_userdef_addon_pref(brna);
 	
 }
 
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index aae44f51f18..de0da3df868 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -66,6 +66,7 @@
 #include "BKE_node.h"
 #include "BKE_report.h"
 
+#include "BKE_addon.h"
 #include "BKE_packedFile.h"
 #include "BKE_sequencer.h" /* free seq clipboard */
 #include "BKE_material.h" /* clear_matcopybuf */
@@ -135,6 +136,9 @@ void WM_init(bContext *C, int argc, const char **argv)
 		wm_init_cursor_data();
 	}
 	GHOST_CreateSystemPaths();
+
+	BKE_addon_pref_type_init();
+
 	wm_operatortype_init();
 	WM_menutype_init();
 	WM_uilisttype_init();
@@ -401,6 +405,8 @@ void WM_exit_ext(bContext *C, const short do_python)
 			ED_screen_exit(C, win, win->screen);
 		}
 	}
+
+	BKE_addon_pref_type_free();
 	wm_operatortype_free();
 	wm_dropbox_free();
 	WM_menutype_free();
-- 
cgit v1.2.3


From 415c8ed81133a3532bc3499eec9541b49e5df869 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Sat, 29 Dec 2012 11:03:03 +0000
Subject: add include missing from last commit

---
 source/blender/blenkernel/intern/addon.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/intern/addon.c b/source/blender/blenkernel/intern/addon.c
index a1b9eb8d970..7f475cd4732 100644
--- a/source/blender/blenkernel/intern/addon.c
+++ b/source/blender/blenkernel/intern/addon.c
@@ -21,6 +21,7 @@
  */
 
 #include 
+#include 
 
 #include "BLI_utildefines.h"
 #include "BLI_ghash.h"
@@ -49,12 +50,12 @@ bAddonPrefType *BKE_addon_pref_type_find(const char *idname, int quiet)
 		}
 
 		if (!quiet) {
-			printf("search for unknown addon-ref '%s'\n", idname);
+			printf("search for unknown addon-pref '%s'\n", idname);
 		}
 	}
 	else {
 		if (!quiet) {
-			printf("search for empty addon");
+			printf("search for empty addon-pref");
 		}
 	}
 
-- 
cgit v1.2.3


From 31933e747f32c8d2d5f60a523ed063d0b8e96697 Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Sat, 29 Dec 2012 12:33:24 +0000
Subject: Bug fix #32806

In 2.64, input for using an NDOF device included all 6 DOFs - including panning.
That makes using it for many people (including beginners like me) too hard, you
very quickly lose the 3d view rotation pivot, as if you are in free fly mode.

Fredrik provided an updated patch, which restores the 2.63 method to only
dolly and rotate by default. The new "all dof" operator is hidden in the keymaps
behind modifier keys SHIFT + CTRL. Users can set this in their configs of course.

As usual, we should be careful changing accepted defaults, and provide new
options as additional choice only.

A useful todo is to make user preference "around selection" work well.
Will check on this now too.
---
 source/blender/editors/space_view3d/view3d_edit.c  | 170 +++++++++++++++++++++
 .../blender/editors/space_view3d/view3d_intern.h   |   1 +
 source/blender/editors/space_view3d/view3d_ops.c   |   4 +-
 3 files changed, 174 insertions(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 913cf3087bb..f846abdf859 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -1161,6 +1161,176 @@ void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot)
 	ot->flag = 0;
 }
 
+
+static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+	ViewOpsData *vod = op->customdata;
+	
+	if (event->type != NDOF_MOTION)
+		return OPERATOR_CANCELLED;
+	else {
+		View3D *v3d = CTX_wm_view3d(C);
+		RegionView3D *rv3d = CTX_wm_region_view3d(C);
+		wmNDOFMotionData *ndof = (wmNDOFMotionData *) event->customdata;
+
+		ED_view3d_camera_lock_init(v3d, rv3d);
+
+		rv3d->rot_angle = 0.f; /* off by default, until changed later this function */
+
+		if (ndof->progress != P_FINISHING) {
+			const float dt = ndof->dt;
+
+			/* tune these until everything feels right */
+			const float rot_sensitivity = 1.f;
+
+			const float zoom_sensitivity = 1.f;
+
+			const float pan_sensitivity = 1.f;
+			const int has_rotation = rv3d->viewlock != RV3D_LOCKED && !is_zero_v3(ndof->rvec);
+
+			float view_inv[4];
+			invert_qt_qt(view_inv, rv3d->viewquat);
+
+			/* #define DEBUG_NDOF_MOTION */
+			#ifdef DEBUG_NDOF_MOTION
+			printf("ndof: T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f delivered to 3D view\n",
+			       ndof->tx, ndof->ty, ndof->tz, ndof->rx, ndof->ry, ndof->rz, ndof->dt);
+			#endif
+
+			if (ndof->tz) {
+				/* Zoom!
+				 * velocity should be proportional to the linear velocity attained by rotational motion of same strength
+				 * [got that?]
+				 * proportional to arclength = radius * angle
+				 */
+				float zoom_distance = zoom_sensitivity * rv3d->dist * dt * ndof->tz;
+
+				if (U.ndof_flag & NDOF_ZOOM_INVERT)
+					zoom_distance = -zoom_distance;
+
+				rv3d->dist += zoom_distance;
+			}
+			
+			if (rv3d->viewlock == RV3D_LOCKED) {
+				/* rotation not allowed -- explore panning options instead */
+				float pan_vec[3] = {ndof->tx, ndof->ty, 0.0f};
+				mul_v3_fl(pan_vec, pan_sensitivity * rv3d->dist * dt);
+
+				/* transform motion from view to world coordinates */
+				invert_qt_qt(view_inv, rv3d->viewquat);
+				mul_qt_v3(view_inv, pan_vec);
+
+				/* move center of view opposite of hand motion (this is camera mode, not object mode) */
+				sub_v3_v3(rv3d->ofs, pan_vec);
+			}
+
+			if (has_rotation) {
+
+				rv3d->view = RV3D_VIEW_USER;
+
+				if (U.ndof_flag & NDOF_TURNTABLE) {
+
+					/* turntable view code by John Aughey, adapted for 3D mouse by [mce] */
+					float angle, rot[4];
+					float xvec[3] = {1, 0, 0};
+
+					/* Determine the direction of the x vector (for rotating up and down) */
+					mul_qt_v3(view_inv, xvec);
+
+					/* Perform the up/down rotation */
+					angle = rot_sensitivity * dt * ndof->rx;
+					if (U.ndof_flag & NDOF_TILT_INVERT_AXIS)
+						angle = -angle;
+					rot[0] = cos(angle);
+					mul_v3_v3fl(rot + 1, xvec, sin(angle));
+					mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot);
+
+					/* Perform the orbital rotation */
+					angle = rot_sensitivity * dt * ndof->ry;
+					if (U.ndof_flag & NDOF_ROTATE_INVERT_AXIS)
+						angle = -angle;
+
+					/* update the onscreen doo-dad */
+					rv3d->rot_angle = angle;
+					rv3d->rot_axis[0] = 0;
+					rv3d->rot_axis[1] = 0;
+					rv3d->rot_axis[2] = 1;
+
+					rot[0] = cos(angle);
+					rot[1] = rot[2] = 0.0;
+					rot[3] = sin(angle);
+					mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot);
+					
+				}
+				else {
+					float rot[4];
+					float axis[3];
+					float angle = rot_sensitivity * ndof_to_axis_angle(ndof, axis);
+
+					if (U.ndof_flag & NDOF_ROLL_INVERT_AXIS)
+						axis[2] = -axis[2];
+
+					if (U.ndof_flag & NDOF_TILT_INVERT_AXIS)
+						axis[0] = -axis[0];
+
+					if (U.ndof_flag & NDOF_ROTATE_INVERT_AXIS)
+						axis[1] = -axis[1];
+					
+
+					/* transform rotation axis from view to world coordinates */
+					mul_qt_v3(view_inv, axis);
+
+					/* update the onscreen doo-dad */
+					rv3d->rot_angle = angle;
+					copy_v3_v3(rv3d->rot_axis, axis);
+
+					axis_angle_to_quat(rot, axis, angle);
+
+					/* apply rotation */
+					mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot);
+					
+				}
+				
+				/* rotate around custom center */
+				if (vod && vod->use_dyn_ofs) {
+					float q1[4];
+					
+					/* compute the post multiplication quat, to rotate the offset correctly */
+					conjugate_qt_qt(q1, vod->oldquat);
+					mul_qt_qtqt(q1, q1, rv3d->viewquat);
+					
+					conjugate_qt(q1); /* conj == inv for unit quat */
+					copy_v3_v3(rv3d->ofs, vod->ofs);
+					sub_v3_v3(rv3d->ofs, vod->dyn_ofs);
+					mul_qt_v3(q1, rv3d->ofs);
+					add_v3_v3(rv3d->ofs, vod->dyn_ofs);
+				}
+			}
+		}
+
+		ED_view3d_camera_lock_sync(v3d, rv3d);
+
+		ED_region_tag_redraw(CTX_wm_region(C));
+
+		return OPERATOR_FINISHED;
+	}
+}
+
+void VIEW3D_OT_ndof_orbit_zoom(struct wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name = "NDOF Orbit View with zoom";
+	ot->description = "Explore every angle of an object using the 3D mouse";
+	ot->idname = "VIEW3D_OT_ndof_orbit_zoom";
+
+	/* api callbacks */
+	ot->invoke = ndof_orbit_zoom_invoke;
+	ot->poll = ED_operator_view3d_active;
+
+	/* flags */
+	ot->flag = 0;
+}
+
 /* -- "pan" navigation
  * -- zoom or dolly?
  */
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index f8a7cdde8a5..a6daf610052 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -77,6 +77,7 @@ void VIEW3D_OT_zoom_camera_1_to_1(struct wmOperatorType *ot);
 void VIEW3D_OT_move(struct wmOperatorType *ot);
 void VIEW3D_OT_rotate(struct wmOperatorType *ot);
 void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot);
+void VIEW3D_OT_ndof_orbit_zoom(struct wmOperatorType *ot);
 void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot);
 void VIEW3D_OT_ndof_all(struct wmOperatorType *ot);
 void VIEW3D_OT_view_all(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index 4101ced616a..79561ee7566 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -131,6 +131,7 @@ void view3d_operatortypes(void)
 	WM_operatortype_append(VIEW3D_OT_zoom);
 	WM_operatortype_append(VIEW3D_OT_zoom_camera_1_to_1);
 	WM_operatortype_append(VIEW3D_OT_dolly);
+	WM_operatortype_append(VIEW3D_OT_ndof_orbit_zoom);
 	WM_operatortype_append(VIEW3D_OT_ndof_orbit);
 	WM_operatortype_append(VIEW3D_OT_ndof_pan);
 	WM_operatortype_append(VIEW3D_OT_ndof_all);
@@ -199,9 +200,10 @@ void view3d_keymap(wmKeyConfig *keyconf)
 	/* NDOF: begin */
 	/* note: positioned here so keymaps show keyboard keys if assigned */
 	/* 3D mouse */
+	WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_orbit_zoom", NDOF_MOTION, 0, 0, 0);
 	WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_orbit", NDOF_MOTION, 0, KM_CTRL, 0);
 	WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_pan", NDOF_MOTION, 0, KM_SHIFT, 0);
-	WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_all", NDOF_MOTION, 0, 0, 0);
+	WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_all", NDOF_MOTION, 0, KM_CTRL | KM_SHIFT, 0);
 	WM_keymap_add_item(keymap, "VIEW3D_OT_view_selected", NDOF_BUTTON_FIT, KM_PRESS, 0, 0);
 	RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_FRONT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_FRONT);
 	RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_BACK, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_BACK);
-- 
cgit v1.2.3


From dfc63e98bc4b00f28b183bfde23c1c43f9fe3ae6 Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Sat, 29 Dec 2012 13:21:01 +0000
Subject: Trackpad fixes & changes:

- UV Image editor and other 2d views didn't zoom for CTRL+swipe yet.
  (2 finger trackpad, 1 finger mighty mouse)

- Switched defaults for 3D window swiping...
  - default rotate view
  - SHIFT for translate
  - CTRL for zooms

This makes all editors use 'swipe' like 'middle mouse', and not
like scrollwheel (as in releases).

This is nice for consistancy, but it still feels a bit weird...

Of course users can config this in keymaps. We need a sensible
default though, and to make a 2D input input device behave like
middle mouse seeems more sensible than like a 1D wheel...

Proposal therefore for defaults:

- 1D scrollwheels: zoom in 3d, zoom in 2d, but scroll for list views.

- 2D trackpads: pan for all 2d views, rotate for 3D

I'll check with frequent trackpad users about this and we can freeze it
before release. Give it a try :)
---
 source/blender/editors/interface/view2d_ops.c    | 6 +++++-
 source/blender/editors/space_image/image_ops.c   | 2 +-
 source/blender/editors/space_image/space_image.c | 1 +
 source/blender/editors/space_view3d/view3d_ops.c | 4 ++--
 4 files changed, 9 insertions(+), 4 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index 8bea308e90a..cc473998340 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -937,7 +937,7 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, wmEvent *event)
 	vzd = op->customdata;
 	v2d = vzd->v2d;
 	
-	if (event->type == MOUSEZOOM) {
+	if (event->type == MOUSEZOOM || event->type == MOUSEPAN) {
 		float dx, dy, fac;
 		
 		vzd->lastx = event->prevx;
@@ -948,6 +948,8 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, wmEvent *event)
 		 */
 		fac = 0.01f * (event->x - event->prevx);
 		dx = fac * BLI_rctf_size_x(&v2d->cur) / 10.0f;
+		if (event->type == MOUSEPAN)
+			fac = 0.01f * (event->y - event->prevy);
 		dy = fac * BLI_rctf_size_y(&v2d->cur) / 10.0f;
 
 		RNA_float_set(op->ptr, "deltax", dx);
@@ -1903,6 +1905,7 @@ void UI_view2d_keymap(wmKeyConfig *keyconf)
 	WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_in", WHEELINMOUSE, KM_PRESS, 0, 0);
 	WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_out", PADMINUS, KM_PRESS, 0, 0);
 	WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_in", PADPLUSKEY, KM_PRESS, 0, 0);
+	WM_keymap_add_item(keymap, "VIEW2D_OT_zoom", MOUSEPAN, 0, KM_CTRL, 0);
 	
 	WM_keymap_verify_item(keymap, "VIEW2D_OT_smoothview", TIMER1, KM_ANY, KM_ANY, 0);
 
@@ -1951,6 +1954,7 @@ void UI_view2d_keymap(wmKeyConfig *keyconf)
 	
 	WM_keymap_add_item(keymap, "VIEW2D_OT_zoom", MIDDLEMOUSE, KM_PRESS, KM_CTRL, 0);
 	WM_keymap_add_item(keymap, "VIEW2D_OT_zoom", MOUSEZOOM, 0, 0, 0);
+	WM_keymap_add_item(keymap, "VIEW2D_OT_zoom", MOUSEPAN, 0, KM_CTRL, 0);
 	WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_out", PADMINUS, KM_PRESS, 0, 0);
 	WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_in", PADPLUSKEY, KM_PRESS, 0, 0);
 	WM_keymap_add_item(keymap, "VIEW2D_OT_reset", HOMEKEY, KM_PRESS, 0, 0);
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 070330c2d47..f1662bc254d 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -457,7 +457,7 @@ enum {
 
 static int image_view_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
-	if (event->type == MOUSEZOOM) {
+	if (event->type == MOUSEZOOM || event->type == MOUSEPAN) {
 		SpaceImage *sima = CTX_wm_space_image(C);
 		ARegion *ar = CTX_wm_region(C);
 		float delta, factor, location[2];
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index b0e9f8bcf99..9492e29734d 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -292,6 +292,7 @@ static void image_keymap(struct wmKeyConfig *keyconf)
 	WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_out", PADMINUS, KM_PRESS, 0, 0);
 	WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom", MIDDLEMOUSE, KM_PRESS, KM_CTRL, 0);
 	WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom", MOUSEZOOM, 0, 0, 0);
+	WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom", MOUSEPAN, 0, KM_CTRL, 0);
 
 	/* ctrl now works as well, shift + numpad works as arrow keys on Windows */
 	RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD8, KM_PRESS, KM_CTRL, 0)->ptr, "ratio", 8.0f);
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index 79561ee7566..37ee778c576 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -250,9 +250,9 @@ void view3d_keymap(wmKeyConfig *keyconf)
 
 	WM_keymap_verify_item(keymap, "VIEW3D_OT_smoothview", TIMER1, KM_ANY, KM_ANY, 0);
 	
-	WM_keymap_add_item(keymap, "VIEW3D_OT_rotate", MOUSEPAN, 0, KM_ALT, 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);
-	WM_keymap_add_item(keymap, "VIEW3D_OT_move", MOUSEPAN, 0, 0, 0);
+	WM_keymap_add_item(keymap, "VIEW3D_OT_move", MOUSEPAN, 0, KM_SHIFT, 0);
 	WM_keymap_add_item(keymap, "VIEW3D_OT_zoom", MOUSEZOOM, 0, 0, 0);
 	WM_keymap_add_item(keymap, "VIEW3D_OT_zoom", MOUSEPAN, 0, KM_CTRL, 0);
 	
-- 
cgit v1.2.3


From 1b8db641998377b250057ec74778573bc171f62d Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Sat, 29 Dec 2012 15:17:26 +0000
Subject: Fixes for NDOF device:

User preference "Rotate around selection" now works for all input operators.
(Didnt for new default)

Note: the default will only rotate around selection, zooms remain to view center.
Our view pivot methods are not well definied at all...
---
 source/blender/editors/space_view3d/view3d_edit.c | 29 +++++++++++++----------
 1 file changed, 17 insertions(+), 12 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index f846abdf859..db4f550e0b1 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -1008,17 +1008,20 @@ void ndof_to_quat(struct wmNDOFMotionData *ndof, float q[4])
  */
 static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
-	ViewOpsData *vod = op->customdata;
 	
 	if (event->type != NDOF_MOTION)
 		return OPERATOR_CANCELLED;
 	else {
 		View3D *v3d = CTX_wm_view3d(C);
+		ViewOpsData *vod;
 		RegionView3D *rv3d = CTX_wm_region_view3d(C);
 		wmNDOFMotionData *ndof = (wmNDOFMotionData *) event->customdata;
 
 		ED_view3d_camera_lock_init(v3d, rv3d);
 
+		viewops_data_create(C, op, event);
+		vod = op->customdata;
+
 		rv3d->rot_angle = 0.f; /* off by default, until changed later this function */
 
 		if (ndof->progress != P_FINISHING) {
@@ -1138,8 +1141,10 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event)
 			}
 		}
 
+		viewops_data_free(C, op);
+		
 		ED_view3d_camera_lock_sync(v3d, rv3d);
-
+		
 		ED_region_tag_redraw(CTX_wm_region(C));
 
 		return OPERATOR_FINISHED;
@@ -1164,11 +1169,11 @@ void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot)
 
 static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
-	ViewOpsData *vod = op->customdata;
 	
 	if (event->type != NDOF_MOTION)
 		return OPERATOR_CANCELLED;
 	else {
+		ViewOpsData *vod;
 		View3D *v3d = CTX_wm_view3d(C);
 		RegionView3D *rv3d = CTX_wm_region_view3d(C);
 		wmNDOFMotionData *ndof = (wmNDOFMotionData *) event->customdata;
@@ -1177,6 +1182,9 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event)
 
 		rv3d->rot_angle = 0.f; /* off by default, until changed later this function */
 
+		viewops_data_create(C, op, event);
+		vod = op->customdata;
+
 		if (ndof->progress != P_FINISHING) {
 			const float dt = ndof->dt;
 
@@ -1308,6 +1316,8 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event)
 			}
 		}
 
+		viewops_data_free(C, op);
+		
 		ED_view3d_camera_lock_sync(v3d, rv3d);
 
 		ED_region_tag_redraw(CTX_wm_region(C));
@@ -1460,16 +1470,8 @@ static int ndof_all_invoke(bContext *C, wmOperator *op, wmEvent *event)
 			const float forward_sensitivity = 1.f;
 			const float vertical_sensitivity = 0.4f;
 			const float lateral_sensitivity = 0.6f;
-
 			float pan_vec[3];
 			const float rot_sensitivity = 1.f;
-#if 0
-			const float zoom_sensitivity = 1.f;
-			const float pan_sensitivity = 1.f;
-			float rot[4];
-			float angle = rot_sensitivity * ndof_to_axis_angle(ndof, axis);
-			float axis[3];
-#endif
 
 			/* inverse view */
 			invert_qt_qt(view_inv, rv3d->viewquat);
@@ -1575,10 +1577,13 @@ static int ndof_all_invoke(bContext *C, wmOperator *op, wmEvent *event)
 			}
 
 		}
+		
+		viewops_data_free(C, op);
+		
 		ED_view3d_camera_lock_sync(v3d, rv3d);
 
 		ED_region_tag_redraw(CTX_wm_region(C));
-		viewops_data_free(C, op);
+		
 		return OPERATOR_FINISHED;
 	}
 }
-- 
cgit v1.2.3


From a7d4ea32f0207a1dc1a42787e93a52a124ca5852 Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Sat, 29 Dec 2012 15:25:03 +0000
Subject: And another NDOF fix:

The dolly factor (fly in/out) now correctly scales for distance to view center.
This allows working on details or huge scenes.
---
 source/blender/editors/space_view3d/view3d_edit.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index db4f550e0b1..8b7601dc491 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -1377,8 +1377,7 @@ static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
 
 			mul_v3_fl(pan_vec, pan_sensitivity * rv3d->dist * dt);
 #else /* ------------------------------------------------------- dolly with Z */
-			float speed = 10.f; /* blender units per second */
-			/* ^^ this is ok for default cube scene, but should scale with.. something */
+			float speed = rv3d->dist; /* uses distance from pivot to define dolly */
 
 			/* tune these until everything feels right */
 			const float forward_sensitivity = 1.f;
@@ -1463,8 +1462,7 @@ static int ndof_all_invoke(bContext *C, wmOperator *op, wmEvent *event)
 			const float dt = ndof->dt;
 			float view_inv[4];
 
-			float speed = 10.f; /* blender units per second */
-			/* ^^ this is ok for default cube scene, but should scale with.. something */
+			float speed = rv3d->dist; /* uses distance from pivot to define dolly */
 
 			/* tune these until everything feels right */
 			const float forward_sensitivity = 1.f;
-- 
cgit v1.2.3


From 1cffa7f339d51a62fba0b9d273b906a522c24b65 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Sat, 29 Dec 2012 15:55:37 +0000
Subject: style cleanup

---
 .../blender/editors/interface/interface_widgets.c  |  2 +-
 source/blender/makesrna/intern/rna_particle.c      | 26 +++++++++++-----------
 2 files changed, 14 insertions(+), 14 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index eb19812876e..eb1c1a64e68 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -2319,7 +2319,7 @@ void ui_draw_link_bezier(const rcti *rect)
 
 		glEnableClientState(GL_VERTEX_ARRAY);
 		glVertexPointer(2, GL_FLOAT, 0, coord_array);
-		glDrawArrays(GL_LINE_STRIP, 0, LINK_RESOL+1);
+		glDrawArrays(GL_LINE_STRIP, 0, LINK_RESOL + 1);
 		glDisableClientState(GL_VERTEX_ARRAY);
 
 		glDisable(GL_BLEND);
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index b0b68b11ec9..0704e29925e 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -295,8 +295,8 @@ static void rna_ParticleSystem_co_hair(ParticleSystem *particlesystem, Object *o
 	ParticleSettings *part = 0;
 	ParticleData *pars = 0;
 	ParticleCacheKey *cache = 0;
-	int totchild=0;
-	int path_nbr=0;
+	int totchild = 0;
+	int path_nbr = 0;
 	int totpart;
 	int max_k = 0;
 
@@ -309,7 +309,7 @@ static void rna_ParticleSystem_co_hair(ParticleSystem *particlesystem, Object *o
 	if (part == NULL || pars == NULL || !psys_check_enabled(object, particlesystem))
 		return;
 	
-	if (part->ren_as==PART_DRAW_OB || part->ren_as==PART_DRAW_GR || part->ren_as==PART_DRAW_NOT)
+	if (part->ren_as == PART_DRAW_OB || part->ren_as == PART_DRAW_GR || part->ren_as == PART_DRAW_NOT)
 		return;
 
 	totchild = particlesystem->totchild * part->disp / 100;
@@ -324,9 +324,9 @@ static void rna_ParticleSystem_co_hair(ParticleSystem *particlesystem, Object *o
 		return;
 
 	if (part->ren_as == PART_DRAW_PATH && particlesystem->pathcache)
-		path_nbr=(int)pow(2.0, part->draw_step);
+		path_nbr = (int)pow(2.0, part->draw_step);
 
-	if (particle_nopathcache[particle_no];
@@ -337,7 +337,7 @@ static void rna_ParticleSystem_co_hair(ParticleSystem *particlesystem, Object *o
 	else {
 
 		if (path_nbr) {
-			cache = particlesystem->childcache[particle_no-totpart];
+			cache = particlesystem->childcache[particle_no - totpart];
 
 			if (cache->steps < 0)
 				max_k = 0;
@@ -348,16 +348,16 @@ static void rna_ParticleSystem_co_hair(ParticleSystem *particlesystem, Object *o
 
 	/*strands key loop data stored in cache + step->co*/
 	if (path_nbr) {
-		if (step>=0 && step<=path_nbr) {
-			if (step<=max_k)
-				copy_v3_v3(n_co, (cache+step)->co);
+		if (step >= 0 && step <= path_nbr) {
+			if (step <= max_k)
+				copy_v3_v3(n_co, (cache + step)->co);
 		}
 	}
 
 }
 
 static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, ParticleSystemModifierData *modifier, ParticleData *particle, int particle_no,
-                                              float n_uv[2])
+                                             float n_uv[2])
 {
 	ParticleSettings *part = 0;
 	int totpart;
@@ -368,7 +368,7 @@ static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, Par
 	if (particlesystem == NULL)
 		return;
 
-	part=particlesystem->part;
+	part = particlesystem->part;
 
 		totchild = particlesystem->totchild;
 
@@ -383,7 +383,7 @@ static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, Par
 
 /* 3. start creating renderable things */
 	/* setup per particle individual stuff */
-	if (particle_nonum_dmcache;
@@ -407,7 +407,7 @@ static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, Par
 		}
 	}
 	else {
-		ChildParticle *cpa = particlesystem->child + particle_no-totpart;
+		ChildParticle *cpa = particlesystem->child + particle_no - totpart;
 
 		num = cpa->num;
 
-- 
cgit v1.2.3


From 4fc84b8f15e6ac308614799a7a7b06bb55c23385 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Sat, 29 Dec 2012 16:04:45 +0000
Subject: text editor: replace strncmp() and hard coded size with
 STR_LITERAL_STARTSWITH() macro that gets the size from sizeof().

---
 source/blender/editors/space_text/text_format.h    |  3 +
 source/blender/editors/space_text/text_format_py.c | 91 ++++++++++++----------
 2 files changed, 55 insertions(+), 39 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/space_text/text_format.h b/source/blender/editors/space_text/text_format.h
index 02c5f433b57..0e6c0937579 100644
--- a/source/blender/editors/space_text/text_format.h
+++ b/source/blender/editors/space_text/text_format.h
@@ -76,4 +76,7 @@ void            ED_text_format_register(TextFormatType *tft);
 /* formatters */
 void ED_text_format_register_py(void);
 
+#define STR_LITERAL_STARTSWITH(str, str_literal, len_var) \
+	(strncmp(str, str_literal, len_var = (sizeof(str_literal) - 1)) == 0)
+
 #endif  /* __TEXT_FORMAT_H__ */
diff --git a/source/blender/editors/space_text/text_format_py.c b/source/blender/editors/space_text/text_format_py.c
index 656c4dbaa93..80616c64689 100644
--- a/source/blender/editors/space_text/text_format_py.c
+++ b/source/blender/editors/space_text/text_format_py.c
@@ -41,7 +41,6 @@
 
 /* *** Local Functions (for format_line) *** */
 
-
 /* Checks the specified source string for a Python built-in function name. This
  * name must start at the beginning of the source string and must be followed by
  * a non-identifier (see text_check_identifier(char)) or null character.
@@ -55,39 +54,51 @@
 
 static int txtfmt_py_find_builtinfunc(const char *string)
 {
-	int a, i;
+	int i, len;
 	/* list is from...
-	 * ", ".join(['"%s"' % kw for kw in  __import__("keyword").kwlist if kw not in {"False", "None", "True"}])
+	 * ", ".join(['"%s"' % kw
+	 *            for kw in  __import__("keyword").kwlist
+	 *            if kw not in {"False", "None", "True", "def", "class"}])
+	 *
+	 * ... and for this code:
+	 * print("\n".join(['else if (STR_LITERAL_STARTSWITH(string, "%s", len)) i = len;' % kw
+	 *                  for kw in  __import__("keyword").kwlist
+	 *                  if kw not in {"False", "None", "True", "def", "class"}]))
 	 */
-	const char *builtinfuncs[] = {
-		/* "False", "None", "True", */ /* see find_bool() */
-		"and", "as", "assert", "break",
-		"class", "continue", "def", "del", "elif", "else", "except",
-		"finally", "for", "from", "global", "if", "import", "in",
-		"is", "lambda", "nonlocal", "not", "or", "pass", "raise",
-		"return", "try", "while", "with", "yield",
-	};
 
-	for (a = 0; a < sizeof(builtinfuncs) / sizeof(builtinfuncs[0]); a++) {
-		i = 0;
-		while (1) {
-			/* If we hit the end of a keyword... (eg. "def") */
-			if (builtinfuncs[a][i] == '\0') {
-				/* If we still have identifier chars in the source (eg. "definate") */
-				if (text_check_identifier(string[i]))
-					i = -1;  /* No match */
-				break; /* Next keyword if no match, otherwise we're done */
+	if      (STR_LITERAL_STARTSWITH(string, "and",      len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "as",       len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "assert",   len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "break",    len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "continue", len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "del",      len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "elif",     len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "else",     len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "except",   len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "finally",  len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "for",      len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "from",     len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "global",   len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "if",       len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "import",   len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "in",       len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "is",       len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "lambda",   len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "nonlocal", len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "not",      len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "or",       len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "pass",     len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "raise",    len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "return",   len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "try",      len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "while",    len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "with",     len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "yield",    len)) i = len;
+	else                                                      i = 0;
 
-				/* If chars mismatch, move on to next keyword */
-			}
-			else if (string[i] != builtinfuncs[a][i]) {
-				i = -1;
-				break; /* Break inner loop, start next keyword */
-			}
-			i++;
-		}
-		if (i > 0) break;  /* If we have a match, we're done */
-	}
+	/* If next source char is an identifier (eg. 'i' in "definate") no match */
+	if (i == 0 || text_check_identifier(string[i]))
+		return -1;
 	return i;
 }
 
@@ -100,10 +111,11 @@ static int txtfmt_py_find_builtinfunc(const char *string)
 
 static int txtfmt_py_find_specialvar(const char *string)
 {
-	int i;
-	if      (strncmp(string, "def",   3) == 0) i = 3;
-	else if (strncmp(string, "class", 5) == 0) i = 5;
-	else                                       i = 0;
+	int i, len;
+
+	if      (STR_LITERAL_STARTSWITH(string, "def", len))   i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "class", len)) i = len;
+	else                                                   i = 0;
 
 	/* If next source char is an identifier (eg. 'i' in "definate") no match */
 	if (i == 0 || text_check_identifier(string[i]))
@@ -125,11 +137,12 @@ static int txtfmt_py_find_decorator(const char *string)
 
 static int txtfmt_py_find_bool(const char *string)
 {
-	int i;
-	if      (strncmp(string, "None",  4) == 0) i = 4;
-	else if (strncmp(string, "True",  4) == 0) i = 4;
-	else if (strncmp(string, "False", 5) == 0) i = 5;
-	else                                       i = 0;
+	int i, len;
+
+	if      (STR_LITERAL_STARTSWITH(string, "None",  len))  i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "True",  len))  i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "False", len))  i = len;
+	else                                                    i = 0;
 
 	/* If next source char is an identifier (eg. 'i' in "Nonetheless") no match */
 	if (i == 0 || text_check_identifier(string[i]))
-- 
cgit v1.2.3


From 8c29f611e93838f36d810a57b11a9ee1d1a13886 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Sat, 29 Dec 2012 16:18:03 +0000
Subject: code cleanup: text editor syntax highlighting - avoid loops using
 memset()

---
 source/blender/editors/space_text/text_format_py.c | 36 ++++++++++------------
 1 file changed, 16 insertions(+), 20 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/space_text/text_format_py.c b/source/blender/editors/space_text/text_format_py.c
index 80616c64689..7c5d0231d63 100644
--- a/source/blender/editors/space_text/text_format_py.c
+++ b/source/blender/editors/space_text/text_format_py.c
@@ -231,27 +231,28 @@ static void txtfmt_py_format_line(SpaceText *st, TextLine *line, const int do_ne
 				*fmt = 'l';
 			}
 			/* Whitespace (all ws. has been converted to spaces) */
-			else if (*str == ' ')
+			else if (*str == ' ') {
 				*fmt = '_';
+			}
 			/* Numbers (digits not part of an identifier and periods followed by digits) */
-			else if ((prev != 'q' && text_check_digit(*str)) || (*str == '.' && text_check_digit(*(str + 1))))
+			else if ((prev != 'q' && text_check_digit(*str)) || (*str == '.' && text_check_digit(*(str + 1)))) {
 				*fmt = 'n';
+			}
 			/* Booleans */
-			else if (prev != 'q' && (i = txtfmt_py_find_bool(str)) != -1)
+			else if (prev != 'q' && (i = txtfmt_py_find_bool(str)) != -1) {
 				if (i > 0) {
-					while (i > 1) {
-						*fmt = 'n'; fmt++; str++;
-						i--;
-					}
-					*fmt = 'n';
+					memset(fmt, 'n', i);
+					i--; fmt += i; str += i;
 				}
 				else {
 					str += BLI_str_utf8_size_safe(str) - 1;
 					*fmt = 'q';
 				}
+			}
 			/* Punctuation */
-			else if (text_check_delim(*str))
+			else if (text_check_delim(*str)) {
 				*fmt = '!';
+			}
 			/* Identifiers and other text (no previous ws. or delims. so text continues) */
 			else if (prev == 'q') {
 				str += BLI_str_utf8_size_safe(str) - 1;
@@ -260,18 +261,13 @@ static void txtfmt_py_format_line(SpaceText *st, TextLine *line, const int do_ne
 			/* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
 			else {
 				/* Special vars(v) or built-in keywords(b) */
-				if ((i = txtfmt_py_find_specialvar(str)) != -1)
-					prev = 'v';
-				else if ((i = txtfmt_py_find_builtinfunc(str)) != -1)
-					prev = 'b';
-				else if ((i = txtfmt_py_find_decorator(str)) != -1)
-					prev = 'v';  /* could have a new color for this */
+				if      ((i = txtfmt_py_find_specialvar(str))   != -1) prev = 'v';
+				else if ((i = txtfmt_py_find_builtinfunc(str))  != -1) prev = 'b';
+				else if ((i = txtfmt_py_find_decorator(str))    != -1) prev = 'v';  /* could have a new color for this */
+
 				if (i > 0) {
-					while (i > 1) {
-						*fmt = prev; fmt++; str++;
-						i--;
-					}
-					*fmt = prev;
+					memset(fmt, prev, i);
+					i--; fmt += i; str += i;
 				}
 				else {
 					str += BLI_str_utf8_size_safe(str) - 1;
-- 
cgit v1.2.3


From abc5a6c3c8cb491abb1245225f164c1024f66da2 Mon Sep 17 00:00:00 2001
From: Pablo Vazquez 
Date: Sat, 29 Dec 2012 17:49:43 +0000
Subject: Long ago we used to be able to bake physics from negative frames,
 feature that got lost at some point. Now we can do it again.

Example is for physics like Cloth or Hair Dynamics that start on a shaky state for a few frames until they settle (for say baking subtle grass or hair movement).

Reviewed on IRC by kaito, Uncle_Entity and DingTo.
---
 source/blender/makesrna/intern/rna_object_force.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c
index 6d7187da7d9..88a1441d34c 100644
--- a/source/blender/makesrna/intern/rna_object_force.c
+++ b/source/blender/makesrna/intern/rna_object_force.c
@@ -763,7 +763,8 @@ static void rna_def_pointcache(BlenderRNA *brna)
 	
 	prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_TIME);
 	RNA_def_property_int_sdna(prop, NULL, "startframe");
-	RNA_def_property_range(prop, 1, MAXFRAME);
+    RNA_def_property_range(prop, -MAXFRAME, MAXFRAME);
+    RNA_def_property_ui_range(prop, -1000, MAXFRAME, 1, 1);
 	RNA_def_property_ui_text(prop, "Start", "Frame on which the simulation starts");
 	
 	prop = RNA_def_property(srna, "frame_end", PROP_INT, PROP_TIME);
-- 
cgit v1.2.3


From 14ea0845807dc98a9d4601fcb5d7b232262be5dd Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Sat, 29 Dec 2012 18:20:14 +0000
Subject: fix for 2 errors in python syntax highlighting, no space was allowed
 in decorators and decorators where being skipped.

---
 source/blender/editors/space_text/text_format_py.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/editors/space_text/text_format_py.c b/source/blender/editors/space_text/text_format_py.c
index 7c5d0231d63..44c4fc7d03b 100644
--- a/source/blender/editors/space_text/text_format_py.c
+++ b/source/blender/editors/space_text/text_format_py.c
@@ -127,6 +127,10 @@ static int txtfmt_py_find_decorator(const char *string)
 {
 	if (string[0] == '@') {
 		int i = 1;
+		/* whitespace is ok '@  foo' */
+		while (string[i] == '\t' || string[i] == ' ') {
+			i++;
+		}
 		while (text_check_identifier(string[i])) {
 			i++;
 		}
@@ -250,7 +254,7 @@ static void txtfmt_py_format_line(SpaceText *st, TextLine *line, const int do_ne
 				}
 			}
 			/* Punctuation */
-			else if (text_check_delim(*str)) {
+			else if ((*str != '@') && text_check_delim(*str)) {
 				*fmt = '!';
 			}
 			/* Identifiers and other text (no previous ws. or delims. so text continues) */
-- 
cgit v1.2.3


From e9c7aaaa3ccd83ee0bb6076f1f9fb2ac5653187f Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Sat, 29 Dec 2012 18:25:03 +0000
Subject: patch [#33609] Syntax highlighting for OSL in Text Editor from
 Patrick Boelens (senshi). with modifications to split it into its own
 function.

also added C style multi-line comment support /* ... */

I've left out the part of this patch that sets the language in the space, since I think this might be better stored in the text block.

For now it simply uses OSL syntax highlighting when the extension is '.osl'.
---
 source/blender/blenkernel/BKE_blender.h            |   2 +-
 source/blender/editors/include/UI_resources.h      |   2 +
 source/blender/editors/interface/resources.c       |  22 +-
 source/blender/editors/space_text/CMakeLists.txt   |   1 +
 source/blender/editors/space_text/space_text.c     |   1 +
 source/blender/editors/space_text/text_draw.c      |   6 +
 source/blender/editors/space_text/text_format.c    |  10 +-
 source/blender/editors/space_text/text_format.h    |   3 +
 .../blender/editors/space_text/text_format_osl.c   | 331 +++++++++++++++++++++
 source/blender/makesdna/DNA_text_types.h           |   2 +
 source/blender/makesdna/DNA_userdef_types.h        |   1 +
 source/blender/makesrna/intern/rna_userdef.c       |  14 +-
 12 files changed, 387 insertions(+), 8 deletions(-)
 create mode 100644 source/blender/editors/space_text/text_format_osl.c

(limited to 'source')

diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index 11759a82e60..ecd38403d72 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         265
-#define BLENDER_SUBVERSION      3
+#define BLENDER_SUBVERSION      4
 
 /* 262 was the last editmesh release but it has compatibility code for bmesh data */
 #define BLENDER_MINVERSION      262
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index 119c26b2fd5..a114981a700 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -122,8 +122,10 @@ enum {
 
 	TH_SYNTAX_B,
 	TH_SYNTAX_V,
+	TH_SYNTAX_R,
 	TH_SYNTAX_C,
 	TH_SYNTAX_L,
+	TH_SYNTAX_D,
 	TH_SYNTAX_N,
 	
 	TH_BONE_SOLID,
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index f605616dc50..b0781256126 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -358,6 +358,10 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
 					cp = ts->syntaxc; break;
 				case TH_SYNTAX_L:
 					cp = ts->syntaxl; break;
+				case TH_SYNTAX_D:
+					cp = ts->syntaxd; break;
+				case TH_SYNTAX_R:
+					cp = ts->syntaxr; break;
 				case TH_SYNTAX_N:
 					cp = ts->syntaxn; break;
 
@@ -880,10 +884,12 @@ void ui_theme_init_default(void)
 	
 	/* syntax highlighting */
 	rgba_char_args_set(btheme->text.syntaxn,    0, 0, 200, 255);    /* Numbers  Blue*/
-	rgba_char_args_set(btheme->text.syntaxl,    100, 0, 0, 255);    /* Strings  red */
-	rgba_char_args_set(btheme->text.syntaxc,    0, 100, 50, 255);   /* Comments greenish */
-	rgba_char_args_set(btheme->text.syntaxv,    95, 95, 0, 255);    /* Special */
-	rgba_char_args_set(btheme->text.syntaxb,    128, 0, 80, 255);   /* Builtin, red-purple */
+	rgba_char_args_set(btheme->text.syntaxl,    100, 0, 0, 255);    /* Strings  Red */
+	rgba_char_args_set(btheme->text.syntaxc,    0, 100, 50, 255);   /* Comments  Greenish */
+	rgba_char_args_set(btheme->text.syntaxv,    95, 95, 0, 255);    /* Special  Yellow*/
+	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 */
 	
 	/* space oops */
 	btheme->toops = btheme->tv3d;
@@ -2081,6 +2087,14 @@ void init_userdef_do_versions(void)
 			}
 		}
 	}
+
+	if (!MAIN_VERSION_ATLEAST(bmain, 266, 4)) {
+		bTheme *btheme;
+		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 */
+		}
+	}
 	
 	if (U.pixelsize == 0.0f)
 		U.pixelsize = 1.0f;
diff --git a/source/blender/editors/space_text/CMakeLists.txt b/source/blender/editors/space_text/CMakeLists.txt
index 6aaf4212779..b9e4e2f0afa 100644
--- a/source/blender/editors/space_text/CMakeLists.txt
+++ b/source/blender/editors/space_text/CMakeLists.txt
@@ -38,6 +38,7 @@ set(SRC
 	space_text.c
 	text_draw.c
 	text_format.c
+	text_format_osl.c
 	text_format_py.c
 	text_header.c
 	text_ops.c
diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c
index 9ac66ca1698..6ebadb3b921 100644
--- a/source/blender/editors/space_text/space_text.c
+++ b/source/blender/editors/space_text/space_text.c
@@ -555,5 +555,6 @@ void ED_spacetype_text(void)
 
 	/* register formatters */
 	ED_text_format_register_py();
+	ED_text_format_register_osl();
 }
 
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index 7d4c9e5af98..01df223630a 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -131,9 +131,15 @@ static void format_draw_color(char formatchar)
 		case 'l': /* Strings */
 			UI_ThemeColor(TH_SYNTAX_L);
 			break;
+		case 'd': /* Preprocessor directive */
+			UI_ThemeColor(TH_SYNTAX_D);
+			break;
 		case 'v': /* Specials: class, def */
 			UI_ThemeColor(TH_SYNTAX_V);
 			break;
+		case 'r': /* Reserved keywords */
+			UI_ThemeColor(TH_SYNTAX_R);
+			break;
 		case 'b': /* Keywords: for, print, etc. */
 			UI_ThemeColor(TH_SYNTAX_B);
 			break;
diff --git a/source/blender/editors/space_text/text_format.c b/source/blender/editors/space_text/text_format.c
index f7940fc7894..9a52cacb1f9 100644
--- a/source/blender/editors/space_text/text_format.c
+++ b/source/blender/editors/space_text/text_format.c
@@ -147,10 +147,16 @@ void ED_text_format_register(TextFormatType *tft)
 	BLI_addtail(&tft_lb, tft);
 }
 
-TextFormatType *ED_text_format_get(Text *UNUSED(text))
+TextFormatType *ED_text_format_get(Text *text)
 {
 	/* NOTE: once more types are added we'll need to return some type based on 'text'
 	 * for now this function is more of a placeholder */
 
-	return tft_lb.first;
+	/* XXX, wrong, but OK for testing */
+	if (BLI_testextensie(text->id.name + 2, ".osl")) {
+		return tft_lb.last;
+	}
+	else {
+		return tft_lb.first;
+	}
 }
diff --git a/source/blender/editors/space_text/text_format.h b/source/blender/editors/space_text/text_format.h
index 0e6c0937579..dc7f35f8eaf 100644
--- a/source/blender/editors/space_text/text_format.h
+++ b/source/blender/editors/space_text/text_format.h
@@ -60,7 +60,9 @@ typedef struct TextFormatType {
 	 *  '!'  Punctuation and other symbols
 	 *  'n'  Numerals
 	 *  'l'  String letters
+	 *  'd'  Decorator / Preprocessor directive
 	 *  'v'  Special variables (class, def)
+	 *  'r'  Reserved keywords currently not in use, but still prohibited (OSL -> switch e.g.)
 	 *  'b'  Built-in names (print, for, etc.)
 	 *  'q'  Other text (identifiers, etc.)
 	 * It is terminated with a null-terminator '\0' followed by a continuation
@@ -75,6 +77,7 @@ void            ED_text_format_register(TextFormatType *tft);
 
 /* formatters */
 void ED_text_format_register_py(void);
+void ED_text_format_register_osl(void);
 
 #define STR_LITERAL_STARTSWITH(str, str_literal, len_var) \
 	(strncmp(str, str_literal, len_var = (sizeof(str_literal) - 1)) == 0)
diff --git a/source/blender/editors/space_text/text_format_osl.c b/source/blender/editors/space_text/text_format_osl.c
new file mode 100644
index 00000000000..2d536ca1109
--- /dev/null
+++ b/source/blender/editors/space_text/text_format_osl.c
@@ -0,0 +1,331 @@
+/*
+ * ***** 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
+ * 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 blender/editors/space_text/text_format_py.c
+ *  \ingroup sptext
+ */
+
+#include 
+
+#include "BLI_blenlib.h"
+
+#include "DNA_text_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_text.h"
+
+#include "text_format.h"
+
+/* *** Local Functions (for format_line) *** */
+
+static int txtfmt_osl_find_builtinfunc(const char *string)
+{
+	int i, len;
+	/* list is from...
+	 * XXX - link to docs!
+	 */
+	if      (STR_LITERAL_STARTSWITH(string, "break",        len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "closure",      len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "color",        len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "continue",     len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "do",           len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "else",         len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "emit",         len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "float",        len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "for",          len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "if",           len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "illuminance",  len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "illuminate",   len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "int",          len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "matrix",       len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "normal",       len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "output",       len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "point",        len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "public",       len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "return",       len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "string",       len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "struct",       len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "vector",       len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "void",         len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "while",        len)) i = len;
+	else                                                          i = 0;
+
+	/* If next source char is an identifier (eg. 'i' in "definate") no match */
+	if (i == 0 || text_check_identifier(string[i]))
+		return -1;
+	return i;
+}
+
+static int txtfmt_osl_find_reserved(const char *string)
+{
+	int i, len;
+	/* list is from...
+	 * XXX - link to docs!
+	 */
+	if      (STR_LITERAL_STARTSWITH(string, "bool",         len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "case",         len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "catch",        len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "char",         len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "const",        len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "delete",       len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "default",      len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "double",       len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "enum",         len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "extern",       len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "false",        len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "friend",       len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "goto",         len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "inline",       len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "long",         len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "new",          len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "operator",     len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "private",      len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "protected",    len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "short",        len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "signed",       len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "sizeof",       len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "static",       len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "switch",       len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "template",     len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "this",         len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "throw",        len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "true",         len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "try",          len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "typedef",      len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "uniform",      len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "union",        len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "unsigned",     len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "varying",      len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "virtual",      len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "volatile",     len)) i = len;
+
+	/* If next source char is an identifier (eg. 'i' in "definate") no match */
+	if (i == 0 || text_check_identifier(string[i]))
+		return -1;
+	return i;
+}
+
+/* Checks the specified source string for a Python special name. This name must
+ * start at the beginning of the source string and must be followed by a non-
+ * identifier (see text_check_identifier(char)) or null character.
+ *
+ * If a special name is found, the length of the matching name is returned.
+ * Otherwise, -1 is returned. */
+
+static int txtfmt_osl_find_specialvar(const char *string)
+{
+	int i, len;
+
+	if      (STR_LITERAL_STARTSWITH(string, "shader", len)) i = len;
+	else                                                    i = 0;
+
+	/* If next source char is an identifier (eg. 'i' in "definate") no match */
+	if (i == 0 || text_check_identifier(string[i]))
+		return -1;
+	return i;
+}
+
+/* matches py 'txtfmt_osl_find_decorator' */
+static int txtfmt_osl_find_preprocessor(const char *string)
+{
+	if (string[0] == '#') {
+		int i = 1;
+		/* whitespace is ok '#  foo' */
+		while (string[i] == '\t' || string[i] == ' ') {
+			i++;
+		}
+		while (text_check_identifier(string[i])) {
+			i++;
+		}
+		return i;
+	}
+	return -1;
+}
+
+/* not in OSL, keep for now though */
+#if 0
+static int txtfmt_osl_find_bool(const char *string)
+{
+	int i, len;
+
+	if      (STR_LITERAL_STARTSWITH(string, "None",  len))  i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "True",  len))  i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "False", len))  i = len;
+	else                                                    i = 0;
+
+	/* If next source char is an identifier (eg. 'i' in "Nonetheless") no match */
+	if (i == 0 || text_check_identifier(string[i]))
+		return -1;
+	return i;
+}
+#endif
+
+static void txtfmt_osl_format_line(SpaceText *st, TextLine *line, const int do_next)
+{
+	FlattenString fs;
+	const char *str;
+	char *fmt;
+	char orig, cont, find, prev = ' ';
+	int len, i;
+
+	/* Get continuation from previous line */
+	if (line->prev && line->prev->format != NULL) {
+		fmt = line->prev->format;
+		cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+	}
+	else {
+		cont = 0;
+	}
+
+	/* Get original continuation from this line */
+	if (line->format != NULL) {
+		fmt = line->format;
+		orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+	}
+	else {
+		orig = 0xFF;
+	}
+
+	len = flatten_string(st, &fs, line->line);
+	str = fs.buf;
+	if (!text_check_format_len(line, len)) {
+		flatten_string_free(&fs);
+		return;
+	}
+	fmt = line->format;
+
+	while (*str) {
+		/* Handle escape sequences by skipping both \ and next char */
+		if (*str == '\\') {
+			*fmt = prev; fmt++; str++;
+			if (*str == '\0') break;
+			*fmt = prev; fmt++; str += BLI_str_utf8_size_safe(str);
+			continue;
+		}
+		/* Handle continuations */
+		else if (cont) {
+			/* C-Style comments */
+			if (cont & TXT_CONT_COMMENT_CXX) {
+				*fmt = '#';
+			}
+			else if (cont & TXT_CONT_COMMENT_C) {
+				if (*str == '*' && *(str + 1) == '/') {
+					*fmt = '#'; fmt++; str++;
+					*fmt = '#';
+					cont = 0;
+				}
+				else {
+					*fmt = '#';
+				}
+				/* Handle other comments */
+			}
+			else {
+				find = (cont & TXT_DBLQUOTSTR) ? '"' : '\'';
+				if (*str == find) cont = 0;
+				*fmt = 'l';
+			}
+
+			str += BLI_str_utf8_size_safe(str) - 1;
+		}
+		/* Not in a string... */
+		else {
+			/* Deal with comments first */
+			if (*str == '/' && *(str + 1) == '/') {
+				cont = TXT_CONT_COMMENT_CXX;
+				*fmt = '#';
+			}
+			/* C-Style (multi-line) comments */
+			else if (*str == '/' && *(str + 1) == '*') {
+				cont = TXT_CONT_COMMENT_C;
+				*fmt = '#'; fmt++; str++;
+				*fmt = '#';
+			}
+			else if (*str == '"' || *str == '\'') {
+				/* Strings */
+				find = *str;
+				cont = (*str == '"') ? TXT_DBLQUOTSTR : TXT_SNGQUOTSTR;
+				*fmt = 'l';
+			}
+			/* Whitespace (all ws. has been converted to spaces) */
+			else if (*str == ' ') {
+				*fmt = '_';
+			}
+			/* Numbers (digits not part of an identifier and periods followed by digits) */
+			else if ((prev != 'q' && text_check_digit(*str)) || (*str == '.' && text_check_digit(*(str + 1)))) {
+				*fmt = 'n';
+			}
+			/* Punctuation */
+			else if ((*str != '#') && text_check_delim(*str)) {
+				*fmt = '!';
+			}
+			/* Identifiers and other text (no previous ws. or delims. so text continues) */
+			else if (prev == 'q') {
+				str += BLI_str_utf8_size_safe(str) - 1;
+				*fmt = 'q';
+			}
+			/* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
+			else {
+				/* Special vars(v) or built-in keywords(b) */
+				if      ((i = txtfmt_osl_find_specialvar(str))   != -1) prev = 'v';
+				else if ((i = txtfmt_osl_find_builtinfunc(str))  != -1) prev = 'b';
+				else if ((i = txtfmt_osl_find_reserved(str))     != -1) prev = 'r';
+				else if ((i = txtfmt_osl_find_preprocessor(str)) != -1) prev = 'd';
+
+				if (i > 0) {
+					memset(fmt, prev, i);
+					i--; fmt += i; str += i;
+				}
+				else {
+					str += BLI_str_utf8_size_safe(str) - 1;
+					*fmt = 'q';
+				}
+			}
+		}
+		prev = *fmt; fmt++; str++;
+	}
+
+	/* Terminate and add continuation char */
+	*fmt = '\0'; fmt++;
+	*fmt = cont;
+
+	/* If continuation has changed and we're allowed, process the next line */
+	if (cont != orig && do_next && line->next) {
+		txtfmt_osl_format_line(st, line->next, do_next);
+	}
+
+	flatten_string_free(&fs);
+}
+
+void ED_text_format_register_osl(void)
+{
+	static TextFormatType tft = {0};
+	static const char *ext[] = {"osl", NULL};
+
+	tft.format_line = txtfmt_osl_format_line;
+	tft.ext = ext;
+
+	ED_text_format_register(&tft);
+}
diff --git a/source/blender/makesdna/DNA_text_types.h b/source/blender/makesdna/DNA_text_types.h
index 6ce883905d4..cd4e31c2521 100644
--- a/source/blender/makesdna/DNA_text_types.h
+++ b/source/blender/makesdna/DNA_text_types.h
@@ -82,5 +82,7 @@ typedef struct Text {
 #define TXT_TRISTR				0x04 /* triplets of quotes: """ or ''' */
 #define TXT_SNGTRISTR			0x05 /*(TXT_TRISTR | TXT_SNGQUOTSTR)*/
 #define TXT_DBLTRISTR			0x06 /*(TXT_TRISTR | TXT_DBLQUOTSTR)*/
+#define TXT_CONT_COMMENT_C		0x08 /* multi-line comments, OSL only (C style) */
+#define TXT_CONT_COMMENT_CXX	0x10 /* single-line comments, OSL only (C++ style) */
 
 #endif
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 1dc25e0ab5e..530caeca910 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -248,6 +248,7 @@ typedef struct ThemeSpace {
 
 	char syntaxl[4], syntaxn[4], syntaxb[4]; /* syntax for textwindow and nodes */
 	char syntaxv[4], syntaxc[4];
+	char syntaxd[4], syntaxr[4];
 	
 	char movie[4], movieclip[4], mask[4], image[4], scene[4], audio[4];		/* for sequence editor */
 	char effect[4], hpad0[4], transition[4], meta[4];
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 83076f3a903..79d6a1d7d6b 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -1639,7 +1639,19 @@ static void rna_def_userdef_theme_space_text(BlenderRNA *brna)
 	prop = RNA_def_property(srna, "syntax_special", PROP_FLOAT, PROP_COLOR_GAMMA);
 	RNA_def_property_float_sdna(prop, NULL, "syntaxv");
 	RNA_def_property_array(prop, 3);
-	RNA_def_property_ui_text(prop, "Decorator", "");
+	RNA_def_property_ui_text(prop, "Syntax Special", "");
+	RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+	prop = RNA_def_property(srna, "syntax_preprocessor", PROP_FLOAT, PROP_COLOR_GAMMA);
+	RNA_def_property_float_sdna(prop, NULL, "syntaxd");
+	RNA_def_property_array(prop, 3);
+	RNA_def_property_ui_text(prop, "Syntax PreProcessor", "");
+	RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+	prop = RNA_def_property(srna, "syntax_reserved", PROP_FLOAT, PROP_COLOR_GAMMA);
+	RNA_def_property_float_sdna(prop, NULL, "syntaxr");
+	RNA_def_property_array(prop, 3);
+	RNA_def_property_ui_text(prop, "Syntax Reserved", "");
 	RNA_def_property_update(prop, 0, "rna_userdef_update");
 
 	prop = RNA_def_property(srna, "syntax_comment", PROP_FLOAT, PROP_COLOR_GAMMA);
-- 
cgit v1.2.3


From 0028418fe85c737c2122285d5968a432091bf0d2 Mon Sep 17 00:00:00 2001
From: Benoit Bolsee 
Date: Sat, 29 Dec 2012 19:43:08 +0000
Subject: fix bug #33275: iTaSC ignores location of disconnected bones when
 they are changed in pose mode.

Disconnected bones can be translated in pose mode but this translation
cannot be applied to the iTaSC representation of the armature because
there is no joint associated with it. As a result, moving disconnected
bones had no effect. The bug fix is in two parts:
1) manual or rna change in the armature pose will cause automatic
   rebuilding of the iTaSC scene
2) the iTaSC scene is now built from the current pose instead of
   armature rest pose
---
 .../blender/editors/transform/transform_generics.c |  4 ++
 source/blender/ikplugin/intern/itasc_plugin.cpp    | 55 ++++++++++++++++++----
 source/blender/makesrna/intern/rna_pose.c          |  4 +-
 3 files changed, 51 insertions(+), 12 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 8f1d6a7b46e..2591c61c5ab 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -61,6 +61,8 @@
 #include "BIF_gl.h"
 #include "BIF_glutil.h"
 
+#include "BIK_api.h"
+
 #include "BKE_animsys.h"
 #include "BKE_action.h"
 #include "BKE_armature.h"
@@ -847,6 +849,8 @@ static void recalcData_view3d(TransInfo *t)
 		/* old optimize trick... this enforces to bypass the depgraph */
 		if (!(arm->flag & ARM_DELAYDEFORM)) {
 			DAG_id_tag_update(&ob->id, OB_RECALC_DATA);  /* sets recalc flags */
+			/* transformation of pose may affect IK tree, make sure it is rebuilt */
+			BIK_clear_data(ob->pose);
 		}
 		else
 			BKE_pose_where_is(t->scene, ob);
diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp
index f940d2635dc..e1ef7d92bd0 100644
--- a/source/blender/ikplugin/intern/itasc_plugin.cpp
+++ b/source/blender/ikplugin/intern/itasc_plugin.cpp
@@ -864,7 +864,7 @@ static bool joint_callback(const iTaSC::Timestamp& timestamp, iTaSC::ConstraintV
 }
 
 // build array of joint corresponding to IK chain
-static int convert_channels(IK_Scene *ikscene, PoseTree *tree)
+static int convert_channels(IK_Scene *ikscene, PoseTree *tree, float ctime)
 {
 	IK_Channel *ikchan;
 	bPoseChannel *pchan;
@@ -877,6 +877,14 @@ static int convert_channels(IK_Scene *ikscene, PoseTree *tree)
 		ikchan->parent = (a > 0) ? tree->parent[a] : -1;
 		ikchan->owner = ikscene->blArmature;
 
+		// the constraint and channels must be applied before we build the iTaSC scene,
+		// this is because some of the pose data (e.g. pose head) don't have corresponding 
+		// joint angles and can't be applied to the iTaSC armature dynamically
+		if (!(pchan->flag & POSE_DONE))
+			BKE_pose_where_is_bone(ikscene->blscene, ikscene->blArmature, pchan, ctime, 1);
+		// tell blender that this channel was controlled by IK, it's cleared on each BKE_pose_where_is()
+		pchan->flag |= (POSE_DONE | POSE_CHAIN);
+
 		/* set DoF flag */
 		flag = 0;
 		if (!(pchan->ikflag & BONE_IK_NO_XDOF) && !(pchan->ikflag & BONE_IK_NO_XDOF_TEMP) &&
@@ -1049,7 +1057,7 @@ static void BKE_pose_rest(IK_Scene *ikscene)
 	}
 }
 
-static IK_Scene *convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan)
+static IK_Scene *convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan, float ctime)
 {
 	PoseTree *tree = (PoseTree *)pchan->iktree.first;
 	PoseTarget *target;
@@ -1068,6 +1076,7 @@ static IK_Scene *convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan)
 	float length;
 	bool ret = true, ingame;
 	double *rot;
+	float start[3];
 
 	if (tree->totchannel == 0)
 		return NULL;
@@ -1126,7 +1135,7 @@ static IK_Scene *convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan)
 	std::vector weights;
 	double weight[3];
 	// build the array of joints corresponding to the IK chain
-	convert_channels(ikscene, tree);
+	convert_channels(ikscene, tree, ctime);
 	if (ingame) {
 		// in the GE, set the initial joint angle to match the current pose
 		// this will update the jointArray in ikscene
@@ -1137,17 +1146,37 @@ static IK_Scene *convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan)
 		BKE_pose_rest(ikscene);
 	}
 	rot = ikscene->jointArray(0);
+
 	for (a = 0, ikchan = ikscene->channels; a < tree->totchannel; ++a, ++ikchan) {
 		pchan = ikchan->pchan;
 		bone = pchan->bone;
 
 		KDL::Frame tip(iTaSC::F_identity);
+		// compute the position and rotation of the head from previous segment
 		Vector3 *fl = bone->bone_mat;
 		KDL::Rotation brot(
 		    fl[0][0], fl[1][0], fl[2][0],
 		    fl[0][1], fl[1][1], fl[2][1],
 		    fl[0][2], fl[1][2], fl[2][2]);
-		KDL::Vector bpos(bone->head[0], bone->head[1], bone->head[2]);
+		// if the bone is disconnected, the head is movable in pose mode
+		// take that into account by using pose matrix instead of bone
+		// Note that pose is expressed in armature space, convert to previous bone space
+		{
+			float R_parmat[3][3];
+			float iR_parmat[3][3];
+			if (pchan->parent)
+				copy_m3_m4(R_parmat, pchan->parent->pose_mat);
+			else
+				unit_m3(R_parmat);
+			if (pchan->parent)
+				sub_v3_v3v3(start, pchan->pose_head, pchan->parent->pose_tail);
+			else
+				start[0] = start[1] = start[2] = 0.0f;
+			invert_m3_m3(iR_parmat, R_parmat);
+			normalize_m3(iR_parmat);
+			mul_m3_v3(iR_parmat, start);
+		}
+		KDL::Vector bpos(start[0], start[1], start[2]);
 		bpos *= ikscene->blScale;
 		KDL::Frame head(brot, bpos);
 
@@ -1155,7 +1184,7 @@ static IK_Scene *convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan)
 		length = bone->length * ikscene->blScale;
 		parent = (a > 0) ? ikscene->channels[tree->parent[a]].tail : root;
 		// first the fixed segment to the bone head
-		if (head.p.Norm() > KDL::epsilon || head.M.GetRot().Norm() > KDL::epsilon) {
+		if (!(ikchan->pchan->bone->flag & BONE_CONNECTED) || head.M.GetRot().Norm() > KDL::epsilon) {
 			joint = bone->name;
 			joint += ":H";
 			ret = arm->addSegment(joint, parent, KDL::Joint::None, 0.0, head);
@@ -1497,7 +1526,7 @@ static IK_Scene *convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan)
 	return ikscene;
 }
 
-static void create_scene(Scene *scene, Object *ob)
+static void create_scene(Scene *scene, Object *ob, float ctime)
 {
 	bPoseChannel *pchan;
 
@@ -1508,7 +1537,7 @@ static void create_scene(Scene *scene, Object *ob)
 		if (tree) {
 			IK_Data *ikdata = get_ikdata(ob->pose);
 			// convert tree in iTaSC::Scene
-			IK_Scene *ikscene = convert_tree(scene, ob, pchan);
+			IK_Scene *ikscene = convert_tree(scene, ob, pchan, ctime);
 			if (ikscene) {
 				ikscene->next = ikdata->first;
 				ikdata->first = ikscene;
@@ -1732,15 +1761,21 @@ void itasc_initialize_tree(struct Scene *scene, Object *ob, float ctime)
 			count += initialize_scene(ob, pchan);
 	}
 	// if at least one tree, create the scenes from the PoseTree stored in the channels
-	if (count)
-		create_scene(scene, ob);
-	itasc_update_param(ob->pose);
+	// postpone until execute_tree: this way the pose constraint are included
+	//if (count)
+	//	create_scene(scene, ob, ctime);
+	//itasc_update_param(ob->pose);
 	// make sure we don't rebuilt until the user changes something important
 	ob->pose->flag &= ~POSE_WAS_REBUILT;
 }
 
 void itasc_execute_tree(struct Scene *scene, struct Object *ob,  struct bPoseChannel *pchan, float ctime)
 {
+	if (!ob->pose->ikdata) {
+		// IK tree not yet created, no it now
+		create_scene(scene, ob, ctime);
+		itasc_update_param(ob->pose);
+	}
 	if (ob->pose->ikdata) {
 		IK_Data *ikdata = (IK_Data *)ob->pose->ikdata;
 		bItasc *ikparam = (bItasc *) ob->pose->ikparam;
diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c
index 87ef3c983aa..23f61282b78 100644
--- a/source/blender/makesrna/intern/rna_pose.c
+++ b/source/blender/makesrna/intern/rna_pose.c
@@ -786,14 +786,14 @@ static void rna_def_pose_channel(BlenderRNA *brna)
 	RNA_def_property_editable_array_func(prop, "rna_PoseChannel_location_editable");
 	RNA_def_property_ui_text(prop, "Location", "");
 	RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
-	RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
+	RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_IK_update");
 
 	prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_XYZ);
 	RNA_def_property_float_sdna(prop, NULL, "size");
 	RNA_def_property_editable_array_func(prop, "rna_PoseChannel_scale_editable");
 	RNA_def_property_float_array_default(prop, default_scale);
 	RNA_def_property_ui_text(prop, "Scale", "");
-	RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
+	RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_IK_update");
 
 	prop = RNA_def_property(srna, "rotation_quaternion", PROP_FLOAT, PROP_QUATERNION);
 	RNA_def_property_float_sdna(prop, NULL, "quat");
-- 
cgit v1.2.3


From 76fd28c25d07a6acb746be09a0eda4201fce892f Mon Sep 17 00:00:00 2001
From: Dan Eicher 
Date: Sat, 29 Dec 2012 20:16:21 +0000
Subject: Missing NULL check which crashes on opening the Text Editor without
 an active Text object

---
 source/blender/editors/space_text/text_format.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/editors/space_text/text_format.c b/source/blender/editors/space_text/text_format.c
index 9a52cacb1f9..294f94dd4b7 100644
--- a/source/blender/editors/space_text/text_format.c
+++ b/source/blender/editors/space_text/text_format.c
@@ -153,7 +153,7 @@ TextFormatType *ED_text_format_get(Text *text)
 	 * for now this function is more of a placeholder */
 
 	/* XXX, wrong, but OK for testing */
-	if (BLI_testextensie(text->id.name + 2, ".osl")) {
+	if (text && BLI_testextensie(text->id.name + 2, ".osl")) {
 		return tft_lb.last;
 	}
 	else {
-- 
cgit v1.2.3


From 1fd05207256c13ea9a7c10db2ac6afc9334586dd Mon Sep 17 00:00:00 2001
From: Dan Eicher 
Date: Sat, 29 Dec 2012 22:06:44 +0000
Subject: Infinite loop caused by using an uninitialized variable in a
 compairison statement

---
 source/blender/editors/space_text/text_format_osl.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/editors/space_text/text_format_osl.c b/source/blender/editors/space_text/text_format_osl.c
index 2d536ca1109..9d5dc5bea1a 100644
--- a/source/blender/editors/space_text/text_format_osl.c
+++ b/source/blender/editors/space_text/text_format_osl.c
@@ -81,7 +81,7 @@ static int txtfmt_osl_find_builtinfunc(const char *string)
 
 static int txtfmt_osl_find_reserved(const char *string)
 {
-	int i, len;
+	int i = 0, len;
 	/* list is from...
 	 * XXX - link to docs!
 	 */
-- 
cgit v1.2.3


From 4ed9cea8ce210588f374fabeb75e0d70364f5b08 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Sun, 30 Dec 2012 00:46:17 +0000
Subject: code cleanup: text editor formatting enums were named crypticly, also
 add asserts if the continuation values are wrong (which can happen with
 buffer overflows on formatting).

---
 source/blender/editors/space_text/text_format.h    | 14 +++++++++++
 .../blender/editors/space_text/text_format_osl.c   | 29 ++++++++++++----------
 source/blender/editors/space_text/text_format_py.c | 26 ++++++++++---------
 source/blender/makesdna/DNA_text_types.h           | 10 --------
 source/blender/makesrna/intern/rna_object_force.c  |  4 +--
 5 files changed, 46 insertions(+), 37 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/space_text/text_format.h b/source/blender/editors/space_text/text_format.h
index dc7f35f8eaf..e5c3db4f121 100644
--- a/source/blender/editors/space_text/text_format.h
+++ b/source/blender/editors/space_text/text_format.h
@@ -41,6 +41,20 @@ typedef struct FlattenString {
 	int pos, len;
 } FlattenString;
 
+/* format continuation flags (stored just after the NULL terminator) */
+enum {
+	FMT_CONT_NOP                = 0,  /* no continuation */
+	FMT_CONT_QUOTESINGLE        = (1 << 0),  /* single quotes */
+	FMT_CONT_QUOTEDOUBLE        = (1 << 1),  /* double quotes */
+	FMT_CONT_TRIPLE             = (1 << 2),  /* triplets of quotes: """ or ''' */
+	FMT_CONT_QUOTESINGLE_TRIPLE = (FMT_CONT_TRIPLE | FMT_CONT_QUOTESINGLE),
+	FMT_CONT_QUOTEDOUBLE_TRIPLE = (FMT_CONT_TRIPLE | FMT_CONT_QUOTEDOUBLE),
+	FMT_CONT_COMMENT_C          = (1 << 3),  /* multi-line comments, OSL only (C style) */
+	FMT_CONT_COMMENT_CXX        = (1 << 4),  /* single-line comments, OSL only (C++ style) */
+};
+#define FMT_CONT_ALL \
+	(FMT_CONT_QUOTESINGLE | FMT_CONT_QUOTEDOUBLE | FMT_CONT_TRIPLE | FMT_CONT_COMMENT_C | FMT_CONT_COMMENT_CXX)
+
 int  flatten_string(struct SpaceText *st, FlattenString *fs, const char *in);
 void flatten_string_free(FlattenString *fs);
 int  flatten_string_strlen(FlattenString *fs, const char *str);
diff --git a/source/blender/editors/space_text/text_format_osl.c b/source/blender/editors/space_text/text_format_osl.c
index 9d5dc5bea1a..3896daf9809 100644
--- a/source/blender/editors/space_text/text_format_osl.c
+++ b/source/blender/editors/space_text/text_format_osl.c
@@ -81,7 +81,7 @@ static int txtfmt_osl_find_builtinfunc(const char *string)
 
 static int txtfmt_osl_find_reserved(const char *string)
 {
-	int i = 0, len;
+	int i, len;
 	/* list is from...
 	 * XXX - link to docs!
 	 */
@@ -121,6 +121,7 @@ static int txtfmt_osl_find_reserved(const char *string)
 	else if (STR_LITERAL_STARTSWITH(string, "varying",      len)) i = len;
 	else if (STR_LITERAL_STARTSWITH(string, "virtual",      len)) i = len;
 	else if (STR_LITERAL_STARTSWITH(string, "volatile",     len)) i = len;
+	else                                                          i = 0;
 
 	/* If next source char is an identifier (eg. 'i' in "definate") no match */
 	if (i == 0 || text_check_identifier(string[i]))
@@ -188,25 +189,27 @@ static void txtfmt_osl_format_line(SpaceText *st, TextLine *line, const int do_n
 	FlattenString fs;
 	const char *str;
 	char *fmt;
-	char orig, cont, find, prev = ' ';
+	char cont_orig, cont, find, prev = ' ';
 	int len, i;
 
 	/* Get continuation from previous line */
 	if (line->prev && line->prev->format != NULL) {
 		fmt = line->prev->format;
 		cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+		BLI_assert((FMT_CONT_ALL & cont) == cont);
 	}
 	else {
-		cont = 0;
+		cont = FMT_CONT_NOP;
 	}
 
 	/* Get original continuation from this line */
 	if (line->format != NULL) {
 		fmt = line->format;
-		orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+		cont_orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+		BLI_assert((FMT_CONT_ALL & cont_orig) == cont_orig);
 	}
 	else {
-		orig = 0xFF;
+		cont_orig = 0xFF;
 	}
 
 	len = flatten_string(st, &fs, line->line);
@@ -228,14 +231,14 @@ static void txtfmt_osl_format_line(SpaceText *st, TextLine *line, const int do_n
 		/* Handle continuations */
 		else if (cont) {
 			/* C-Style comments */
-			if (cont & TXT_CONT_COMMENT_CXX) {
+			if (cont & FMT_CONT_COMMENT_CXX) {
 				*fmt = '#';
 			}
-			else if (cont & TXT_CONT_COMMENT_C) {
+			else if (cont & FMT_CONT_COMMENT_C) {
 				if (*str == '*' && *(str + 1) == '/') {
 					*fmt = '#'; fmt++; str++;
 					*fmt = '#';
-					cont = 0;
+					cont = FMT_CONT_NOP;
 				}
 				else {
 					*fmt = '#';
@@ -243,7 +246,7 @@ static void txtfmt_osl_format_line(SpaceText *st, TextLine *line, const int do_n
 				/* Handle other comments */
 			}
 			else {
-				find = (cont & TXT_DBLQUOTSTR) ? '"' : '\'';
+				find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
 				if (*str == find) cont = 0;
 				*fmt = 'l';
 			}
@@ -254,19 +257,19 @@ static void txtfmt_osl_format_line(SpaceText *st, TextLine *line, const int do_n
 		else {
 			/* Deal with comments first */
 			if (*str == '/' && *(str + 1) == '/') {
-				cont = TXT_CONT_COMMENT_CXX;
+				cont = FMT_CONT_COMMENT_CXX;
 				*fmt = '#';
 			}
 			/* C-Style (multi-line) comments */
 			else if (*str == '/' && *(str + 1) == '*') {
-				cont = TXT_CONT_COMMENT_C;
+				cont = FMT_CONT_COMMENT_C;
 				*fmt = '#'; fmt++; str++;
 				*fmt = '#';
 			}
 			else if (*str == '"' || *str == '\'') {
 				/* Strings */
 				find = *str;
-				cont = (*str == '"') ? TXT_DBLQUOTSTR : TXT_SNGQUOTSTR;
+				cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE;
 				*fmt = 'l';
 			}
 			/* Whitespace (all ws. has been converted to spaces) */
@@ -312,7 +315,7 @@ static void txtfmt_osl_format_line(SpaceText *st, TextLine *line, const int do_n
 	*fmt = cont;
 
 	/* If continuation has changed and we're allowed, process the next line */
-	if (cont != orig && do_next && line->next) {
+	if (cont != cont_orig && do_next && line->next) {
 		txtfmt_osl_format_line(st, line->next, do_next);
 	}
 
diff --git a/source/blender/editors/space_text/text_format_py.c b/source/blender/editors/space_text/text_format_py.c
index 44c4fc7d03b..4f8f277f6da 100644
--- a/source/blender/editors/space_text/text_format_py.c
+++ b/source/blender/editors/space_text/text_format_py.c
@@ -159,25 +159,27 @@ static void txtfmt_py_format_line(SpaceText *st, TextLine *line, const int do_ne
 	FlattenString fs;
 	const char *str;
 	char *fmt;
-	char orig, cont, find, prev = ' ';
+	char cont_orig, cont, find, prev = ' ';
 	int len, i;
 
 	/* Get continuation from previous line */
 	if (line->prev && line->prev->format != NULL) {
 		fmt = line->prev->format;
 		cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+		BLI_assert((FMT_CONT_ALL & cont) == cont);
 	}
 	else {
-		cont = 0;
+		cont = FMT_CONT_NOP;
 	}
 
 	/* Get original continuation from this line */
 	if (line->format != NULL) {
 		fmt = line->format;
-		orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+		cont_orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+		BLI_assert((FMT_CONT_ALL & cont_orig) == cont_orig);
 	}
 	else {
-		orig = 0xFF;
+		cont_orig = 0xFF;
 	}
 
 	len = flatten_string(st, &fs, line->line);
@@ -199,18 +201,18 @@ static void txtfmt_py_format_line(SpaceText *st, TextLine *line, const int do_ne
 		/* Handle continuations */
 		else if (cont) {
 			/* Triple strings ("""...""" or '''...''') */
-			if (cont & TXT_TRISTR) {
-				find = (cont & TXT_DBLQUOTSTR) ? '"' : '\'';
+			if (cont & FMT_CONT_TRIPLE) {
+				find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
 				if (*str == find && *(str + 1) == find && *(str + 2) == find) {
 					*fmt = 'l'; fmt++; str++;
 					*fmt = 'l'; fmt++; str++;
-					cont = 0;
+					cont = FMT_CONT_NOP;
 				}
 				/* Handle other strings */
 			}
 			else {
-				find = (cont & TXT_DBLQUOTSTR) ? '"' : '\'';
-				if (*str == find) cont = 0;
+				find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
+				if (*str == find) cont = FMT_CONT_NOP;
 			}
 
 			*fmt = 'l';
@@ -226,11 +228,11 @@ static void txtfmt_py_format_line(SpaceText *st, TextLine *line, const int do_ne
 			else if (*str == '"' || *str == '\'') {
 				/* Strings */
 				find = *str;
-				cont = (*str == '"') ? TXT_DBLQUOTSTR : TXT_SNGQUOTSTR;
+				cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE;
 				if (*(str + 1) == find && *(str + 2) == find) {
 					*fmt = 'l'; fmt++; str++;
 					*fmt = 'l'; fmt++; str++;
-					cont |= TXT_TRISTR;
+					cont |= FMT_CONT_TRIPLE;
 				}
 				*fmt = 'l';
 			}
@@ -287,7 +289,7 @@ static void txtfmt_py_format_line(SpaceText *st, TextLine *line, const int do_ne
 	*fmt = cont;
 
 	/* If continuation has changed and we're allowed, process the next line */
-	if (cont != orig && do_next && line->next) {
+	if (cont != cont_orig && do_next && line->next) {
 		txtfmt_py_format_line(st, line->next, do_next);
 	}
 
diff --git a/source/blender/makesdna/DNA_text_types.h b/source/blender/makesdna/DNA_text_types.h
index cd4e31c2521..3194adba3a0 100644
--- a/source/blender/makesdna/DNA_text_types.h
+++ b/source/blender/makesdna/DNA_text_types.h
@@ -75,14 +75,4 @@ typedef struct Text {
 #define TXT_FOLLOW              0x0200 /* always follow cursor (console) */
 #define TXT_TABSTOSPACES        0x0400 /* use space instead of tabs */
 
-/* format continuation flags */
-#define TXT_NOCONT				0x00 /* no continuation */
-#define TXT_SNGQUOTSTR			0x01 /* single quotes */
-#define TXT_DBLQUOTSTR			0x02 /* double quotes */
-#define TXT_TRISTR				0x04 /* triplets of quotes: """ or ''' */
-#define TXT_SNGTRISTR			0x05 /*(TXT_TRISTR | TXT_SNGQUOTSTR)*/
-#define TXT_DBLTRISTR			0x06 /*(TXT_TRISTR | TXT_DBLQUOTSTR)*/
-#define TXT_CONT_COMMENT_C		0x08 /* multi-line comments, OSL only (C style) */
-#define TXT_CONT_COMMENT_CXX	0x10 /* single-line comments, OSL only (C++ style) */
-
 #endif
diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c
index 88a1441d34c..0c2944b3966 100644
--- a/source/blender/makesrna/intern/rna_object_force.c
+++ b/source/blender/makesrna/intern/rna_object_force.c
@@ -763,8 +763,8 @@ static void rna_def_pointcache(BlenderRNA *brna)
 	
 	prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_TIME);
 	RNA_def_property_int_sdna(prop, NULL, "startframe");
-    RNA_def_property_range(prop, -MAXFRAME, MAXFRAME);
-    RNA_def_property_ui_range(prop, -1000, MAXFRAME, 1, 1);
+	RNA_def_property_range(prop, -MAXFRAME, MAXFRAME);
+	RNA_def_property_ui_range(prop, -1000, MAXFRAME, 1, 1);
 	RNA_def_property_ui_text(prop, "Start", "Frame on which the simulation starts");
 	
 	prop = RNA_def_property(srna, "frame_end", PROP_INT, PROP_TIME);
-- 
cgit v1.2.3


From 099d8c93904747fa39857684dce2bd228c3462eb Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Sun, 30 Dec 2012 01:12:21 +0000
Subject: code cleanup: enum for formatting char (avoid confusion when '#' is a
 comment for // in OSL)

---
 source/blender/editors/space_text/text_draw.c      | 26 ++++++-------
 source/blender/editors/space_text/text_format.h    | 29 ++++++++------
 .../blender/editors/space_text/text_format_osl.c   | 42 +++++++++++----------
 source/blender/editors/space_text/text_format_py.c | 44 +++++++++++-----------
 4 files changed, 76 insertions(+), 65 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index 01df223630a..01adf6a4107 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -117,33 +117,33 @@ static void txt_format_text(SpaceText *st)
 static void format_draw_color(char formatchar)
 {
 	switch (formatchar) {
-		case '_': /* Whitespace */
+		case FMT_TYPE_WHITESPACE:
 			break;
-		case '!': /* Symbols */
+		case FMT_TYPE_SYMBOL:
 			UI_ThemeColorBlend(TH_TEXT, TH_BACK, 0.5f);
 			break;
-		case '#': /* Comments */
+		case FMT_TYPE_COMMENT:
 			UI_ThemeColor(TH_SYNTAX_C);
 			break;
-		case 'n': /* Numerals */
+		case FMT_TYPE_NUMERAL:
 			UI_ThemeColor(TH_SYNTAX_N);
 			break;
-		case 'l': /* Strings */
+		case FMT_TYPE_STRING:
 			UI_ThemeColor(TH_SYNTAX_L);
 			break;
-		case 'd': /* Preprocessor directive */
+		case FMT_TYPE_DIRECTIVE:
 			UI_ThemeColor(TH_SYNTAX_D);
 			break;
-		case 'v': /* Specials: class, def */
+		case FMT_TYPE_SPECIAL:
 			UI_ThemeColor(TH_SYNTAX_V);
 			break;
-		case 'r': /* Reserved keywords */
+		case FMT_TYPE_RESERVED:
 			UI_ThemeColor(TH_SYNTAX_R);
 			break;
-		case 'b': /* Keywords: for, print, etc. */
+		case FMT_TYPE_KEYWORD:
 			UI_ThemeColor(TH_SYNTAX_B);
 			break;
-		case 'q': /* Other text (identifiers) */
+		case FMT_TYPE_DEFAULT:
 		default:
 			UI_ThemeColor(TH_TEXT);
 			break;
@@ -1174,7 +1174,7 @@ static void draw_brackets(SpaceText *st, ARegion *ar)
 	stack = 0;
 	
 	/* Don't highlight backets if syntax HL is off or bracket in string or comment. */
-	if (!linep->format || linep->format[fc] == 'l' || linep->format[fc] == '#')
+	if (!linep->format || linep->format[fc] == FMT_TYPE_STRING || linep->format[fc] == FMT_TYPE_COMMENT)
 		return;
 
 	if (b > 0) {
@@ -1183,7 +1183,7 @@ static void draw_brackets(SpaceText *st, ARegion *ar)
 		c += BLI_str_utf8_size_safe(linep->line + c);
 		while (linep) {
 			while (c < linep->len) {
-				if (linep->format && linep->format[fc] != 'l' && linep->format[fc] != '#') {
+				if (linep->format && linep->format[fc] != FMT_TYPE_STRING && linep->format[fc] != FMT_TYPE_COMMENT) {
 					b = text_check_bracket(linep->line[c]);
 					if (b == find) {
 						if (stack == 0) {
@@ -1212,7 +1212,7 @@ static void draw_brackets(SpaceText *st, ARegion *ar)
 		if (c > 0) c -= linep->line + c - BLI_str_prev_char_utf8(linep->line + c);
 		while (linep) {
 			while (fc >= 0) {
-				if (linep->format && linep->format[fc] != 'l' && linep->format[fc] != '#') {
+				if (linep->format && linep->format[fc] != FMT_TYPE_STRING && linep->format[fc] != FMT_TYPE_COMMENT) {
 					b = text_check_bracket(linep->line[c]);
 					if (b == find) {
 						if (stack == 0) {
diff --git a/source/blender/editors/space_text/text_format.h b/source/blender/editors/space_text/text_format.h
index e5c3db4f121..99cd20149cf 100644
--- a/source/blender/editors/space_text/text_format.h
+++ b/source/blender/editors/space_text/text_format.h
@@ -69,23 +69,30 @@ typedef struct TextFormatType {
 	/* Formats the specified line. If do_next is set, the process will move on to
 	 * the succeeding line if it is affected (eg. multiline strings). Format strings
 	 * may contain any of the following characters:
-	 *  '_'  Whitespace
-	 *  '#'  Comment text
-	 *  '!'  Punctuation and other symbols
-	 *  'n'  Numerals
-	 *  'l'  String letters
-	 *  'd'  Decorator / Preprocessor directive
-	 *  'v'  Special variables (class, def)
-	 *  'r'  Reserved keywords currently not in use, but still prohibited (OSL -> switch e.g.)
-	 *  'b'  Built-in names (print, for, etc.)
-	 *  'q'  Other text (identifiers, etc.)
+	 *
 	 * It is terminated with a null-terminator '\0' followed by a continuation
-	 * flag indicating whether the line is part of a multi-line string. */
+	 * flag indicating whether the line is part of a multi-line string.
+	 *
+	 * See: FMT_TYPE_ enums below
+	 */
 	void (*format_line)(SpaceText *st, TextLine *line, int do_next);
 
 	const char **ext;  /* NULL terminated extensions */
 } TextFormatType;
 
+enum {
+	FMT_TYPE_WHITESPACE = '_',  /* Whitespace */
+	FMT_TYPE_COMMENT    = '#',  /* Comment text */
+	FMT_TYPE_SYMBOL     = '!',  /* Punctuation and other symbols */
+	FMT_TYPE_NUMERAL    = 'n',  /* Numerals */
+	FMT_TYPE_STRING     = 'l',  /* String letters */
+	FMT_TYPE_DIRECTIVE  = 'd',  /* Decorator / Preprocessor directive */
+	FMT_TYPE_SPECIAL    = 'v',  /* Special variables (class, def) */
+	FMT_TYPE_RESERVED   = 'r',  /* Reserved keywords currently not in use, but still prohibited (OSL -> switch e.g.) */
+	FMT_TYPE_KEYWORD    = 'b',  /* Built-in names (return, for, etc.) */
+	FMT_TYPE_DEFAULT    = 'q',  /* Regular text (identifiers, etc.) */
+};
+
 TextFormatType *ED_text_format_get(Text *text);
 void            ED_text_format_register(TextFormatType *tft);
 
diff --git a/source/blender/editors/space_text/text_format_osl.c b/source/blender/editors/space_text/text_format_osl.c
index 3896daf9809..433ff0a035b 100644
--- a/source/blender/editors/space_text/text_format_osl.c
+++ b/source/blender/editors/space_text/text_format_osl.c
@@ -232,23 +232,23 @@ static void txtfmt_osl_format_line(SpaceText *st, TextLine *line, const int do_n
 		else if (cont) {
 			/* C-Style comments */
 			if (cont & FMT_CONT_COMMENT_CXX) {
-				*fmt = '#';
+				*fmt = FMT_TYPE_COMMENT;
 			}
 			else if (cont & FMT_CONT_COMMENT_C) {
 				if (*str == '*' && *(str + 1) == '/') {
-					*fmt = '#'; fmt++; str++;
-					*fmt = '#';
+					*fmt = FMT_TYPE_COMMENT; fmt++; str++;
+					*fmt = FMT_TYPE_COMMENT;
 					cont = FMT_CONT_NOP;
 				}
 				else {
-					*fmt = '#';
+					*fmt = FMT_TYPE_COMMENT;
 				}
 				/* Handle other comments */
 			}
 			else {
 				find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
 				if (*str == find) cont = 0;
-				*fmt = 'l';
+				*fmt = FMT_TYPE_STRING;
 			}
 
 			str += BLI_str_utf8_size_safe(str) - 1;
@@ -258,44 +258,46 @@ static void txtfmt_osl_format_line(SpaceText *st, TextLine *line, const int do_n
 			/* Deal with comments first */
 			if (*str == '/' && *(str + 1) == '/') {
 				cont = FMT_CONT_COMMENT_CXX;
-				*fmt = '#';
+				*fmt = FMT_TYPE_COMMENT;
 			}
 			/* C-Style (multi-line) comments */
 			else if (*str == '/' && *(str + 1) == '*') {
 				cont = FMT_CONT_COMMENT_C;
-				*fmt = '#'; fmt++; str++;
-				*fmt = '#';
+				*fmt = FMT_TYPE_COMMENT; fmt++; str++;
+				*fmt = FMT_TYPE_COMMENT;
 			}
 			else if (*str == '"' || *str == '\'') {
 				/* Strings */
 				find = *str;
 				cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE;
-				*fmt = 'l';
+				*fmt = FMT_TYPE_STRING;
 			}
 			/* Whitespace (all ws. has been converted to spaces) */
 			else if (*str == ' ') {
-				*fmt = '_';
+				*fmt = FMT_TYPE_WHITESPACE;
 			}
 			/* Numbers (digits not part of an identifier and periods followed by digits) */
-			else if ((prev != 'q' && text_check_digit(*str)) || (*str == '.' && text_check_digit(*(str + 1)))) {
-				*fmt = 'n';
+			else if ((prev != FMT_TYPE_DEFAULT && text_check_digit(*str)) ||
+			         (*str == '.' && text_check_digit(*(str + 1))))
+			{
+				*fmt = FMT_TYPE_NUMERAL;
 			}
 			/* Punctuation */
 			else if ((*str != '#') && text_check_delim(*str)) {
-				*fmt = '!';
+				*fmt = FMT_TYPE_SYMBOL;
 			}
 			/* Identifiers and other text (no previous ws. or delims. so text continues) */
-			else if (prev == 'q') {
+			else if (prev == FMT_TYPE_DEFAULT) {
 				str += BLI_str_utf8_size_safe(str) - 1;
-				*fmt = 'q';
+				*fmt = FMT_TYPE_DEFAULT;
 			}
 			/* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
 			else {
 				/* Special vars(v) or built-in keywords(b) */
-				if      ((i = txtfmt_osl_find_specialvar(str))   != -1) prev = 'v';
-				else if ((i = txtfmt_osl_find_builtinfunc(str))  != -1) prev = 'b';
-				else if ((i = txtfmt_osl_find_reserved(str))     != -1) prev = 'r';
-				else if ((i = txtfmt_osl_find_preprocessor(str)) != -1) prev = 'd';
+				if      ((i = txtfmt_osl_find_specialvar(str))   != -1) prev = FMT_TYPE_SPECIAL;
+				else if ((i = txtfmt_osl_find_builtinfunc(str))  != -1) prev = FMT_TYPE_KEYWORD;
+				else if ((i = txtfmt_osl_find_reserved(str))     != -1) prev = FMT_TYPE_RESERVED;
+				else if ((i = txtfmt_osl_find_preprocessor(str)) != -1) prev = FMT_TYPE_DIRECTIVE;
 
 				if (i > 0) {
 					memset(fmt, prev, i);
@@ -303,7 +305,7 @@ static void txtfmt_osl_format_line(SpaceText *st, TextLine *line, const int do_n
 				}
 				else {
 					str += BLI_str_utf8_size_safe(str) - 1;
-					*fmt = 'q';
+					*fmt = FMT_TYPE_DEFAULT;
 				}
 			}
 		}
diff --git a/source/blender/editors/space_text/text_format_py.c b/source/blender/editors/space_text/text_format_py.c
index 4f8f277f6da..02b67c32052 100644
--- a/source/blender/editors/space_text/text_format_py.c
+++ b/source/blender/editors/space_text/text_format_py.c
@@ -204,8 +204,8 @@ static void txtfmt_py_format_line(SpaceText *st, TextLine *line, const int do_ne
 			if (cont & FMT_CONT_TRIPLE) {
 				find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
 				if (*str == find && *(str + 1) == find && *(str + 2) == find) {
-					*fmt = 'l'; fmt++; str++;
-					*fmt = 'l'; fmt++; str++;
+					*fmt = FMT_TYPE_STRING; fmt++; str++;
+					*fmt = FMT_TYPE_STRING; fmt++; str++;
 					cont = FMT_CONT_NOP;
 				}
 				/* Handle other strings */
@@ -215,14 +215,14 @@ static void txtfmt_py_format_line(SpaceText *st, TextLine *line, const int do_ne
 				if (*str == find) cont = FMT_CONT_NOP;
 			}
 
-			*fmt = 'l';
+			*fmt = FMT_TYPE_STRING;
 			str += BLI_str_utf8_size_safe(str) - 1;
 		}
 		/* Not in a string... */
 		else {
 			/* Deal with comments first */
-			if (prev == '#' || *str == '#') {
-				*fmt = '#';
+			if (prev == FMT_TYPE_COMMENT || *str == '#') {
+				*fmt = FMT_TYPE_COMMENT;
 				str += BLI_str_utf8_size_safe(str) - 1;
 			}
 			else if (*str == '"' || *str == '\'') {
@@ -230,46 +230,48 @@ static void txtfmt_py_format_line(SpaceText *st, TextLine *line, const int do_ne
 				find = *str;
 				cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE;
 				if (*(str + 1) == find && *(str + 2) == find) {
-					*fmt = 'l'; fmt++; str++;
-					*fmt = 'l'; fmt++; str++;
+					*fmt = FMT_TYPE_STRING; fmt++; str++;
+					*fmt = FMT_TYPE_STRING; fmt++; str++;
 					cont |= FMT_CONT_TRIPLE;
 				}
-				*fmt = 'l';
+				*fmt = FMT_TYPE_STRING;
 			}
 			/* Whitespace (all ws. has been converted to spaces) */
 			else if (*str == ' ') {
-				*fmt = '_';
+				*fmt = FMT_TYPE_WHITESPACE;
 			}
 			/* Numbers (digits not part of an identifier and periods followed by digits) */
-			else if ((prev != 'q' && text_check_digit(*str)) || (*str == '.' && text_check_digit(*(str + 1)))) {
-				*fmt = 'n';
+			else if ((prev != FMT_TYPE_DEFAULT && text_check_digit(*str)) ||
+			         (*str == '.' && text_check_digit(*(str + 1))))
+			{
+				*fmt = FMT_TYPE_NUMERAL;
 			}
 			/* Booleans */
-			else if (prev != 'q' && (i = txtfmt_py_find_bool(str)) != -1) {
+			else if (prev != FMT_TYPE_DEFAULT && (i = txtfmt_py_find_bool(str)) != -1) {
 				if (i > 0) {
-					memset(fmt, 'n', i);
+					memset(fmt, FMT_TYPE_NUMERAL, i);
 					i--; fmt += i; str += i;
 				}
 				else {
 					str += BLI_str_utf8_size_safe(str) - 1;
-					*fmt = 'q';
+					*fmt = FMT_TYPE_DEFAULT;
 				}
 			}
 			/* Punctuation */
 			else if ((*str != '@') && text_check_delim(*str)) {
-				*fmt = '!';
+				*fmt = FMT_TYPE_SYMBOL;
 			}
 			/* Identifiers and other text (no previous ws. or delims. so text continues) */
-			else if (prev == 'q') {
+			else if (prev == FMT_TYPE_DEFAULT) {
 				str += BLI_str_utf8_size_safe(str) - 1;
-				*fmt = 'q';
+				*fmt = FMT_TYPE_DEFAULT;
 			}
 			/* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
 			else {
 				/* Special vars(v) or built-in keywords(b) */
-				if      ((i = txtfmt_py_find_specialvar(str))   != -1) prev = 'v';
-				else if ((i = txtfmt_py_find_builtinfunc(str))  != -1) prev = 'b';
-				else if ((i = txtfmt_py_find_decorator(str))    != -1) prev = 'v';  /* could have a new color for this */
+				if      ((i = txtfmt_py_find_specialvar(str))   != -1) prev = FMT_TYPE_SPECIAL;
+				else if ((i = txtfmt_py_find_builtinfunc(str))  != -1) prev = FMT_TYPE_KEYWORD;
+				else if ((i = txtfmt_py_find_decorator(str))    != -1) prev = FMT_TYPE_SPECIAL;  /* could have a new color for this */
 
 				if (i > 0) {
 					memset(fmt, prev, i);
@@ -277,7 +279,7 @@ static void txtfmt_py_format_line(SpaceText *st, TextLine *line, const int do_ne
 				}
 				else {
 					str += BLI_str_utf8_size_safe(str) - 1;
-					*fmt = 'q';
+					*fmt = FMT_TYPE_DEFAULT;
 				}
 			}
 		}
-- 
cgit v1.2.3


From e12354c4c5850864f925d22f53ec31578384bc63 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Sun, 30 Dec 2012 01:26:31 +0000
Subject: add syntax highlighting color for symbols

---
 source/blender/editors/include/UI_resources.h      |  1 +
 source/blender/editors/interface/resources.c       |  4 ++++
 source/blender/editors/space_text/text_draw.c      |  2 +-
 .../blender/editors/space_text/text_format_osl.c   | 22 ++--------------------
 source/blender/editors/space_text/text_format_py.c |  4 ++--
 source/blender/makesdna/DNA_userdef_types.h        |  6 ++++--
 source/blender/makesrna/intern/rna_userdef.c       |  6 ++++++
 7 files changed, 20 insertions(+), 25 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index a114981a700..e575d9ac924 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -127,6 +127,7 @@ enum {
 	TH_SYNTAX_L,
 	TH_SYNTAX_D,
 	TH_SYNTAX_N,
+	TH_SYNTAX_S,
 	
 	TH_BONE_SOLID,
 	TH_BONE_POSE,
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index b0781256126..25e7a4b58ba 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -364,6 +364,8 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
 					cp = ts->syntaxr; break;
 				case TH_SYNTAX_N:
 					cp = ts->syntaxn; break;
+				case TH_SYNTAX_S:
+					cp = ts->syntaxs; break;
 
 				case TH_NODE:
 					cp = ts->syntaxl; break;
@@ -890,6 +892,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) */
 	
 	/* space oops */
 	btheme->toops = btheme->tv3d;
@@ -2093,6 +2096,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) */
 		}
 	}
 	
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index 01adf6a4107..2256c1c7e25 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -120,7 +120,7 @@ static void format_draw_color(char formatchar)
 		case FMT_TYPE_WHITESPACE:
 			break;
 		case FMT_TYPE_SYMBOL:
-			UI_ThemeColorBlend(TH_TEXT, TH_BACK, 0.5f);
+			UI_ThemeColor(TH_SYNTAX_S);
 			break;
 		case FMT_TYPE_COMMENT:
 			UI_ThemeColor(TH_SYNTAX_C);
diff --git a/source/blender/editors/space_text/text_format_osl.c b/source/blender/editors/space_text/text_format_osl.c
index 433ff0a035b..38903d65ec0 100644
--- a/source/blender/editors/space_text/text_format_osl.c
+++ b/source/blender/editors/space_text/text_format_osl.c
@@ -154,8 +154,8 @@ static int txtfmt_osl_find_preprocessor(const char *string)
 {
 	if (string[0] == '#') {
 		int i = 1;
-		/* whitespace is ok '#  foo' */
-		while (string[i] == '\t' || string[i] == ' ') {
+		/* Whitespace is ok '#  foo' */
+		while (text_check_whitespace(string[i])) {
 			i++;
 		}
 		while (text_check_identifier(string[i])) {
@@ -166,24 +166,6 @@ static int txtfmt_osl_find_preprocessor(const char *string)
 	return -1;
 }
 
-/* not in OSL, keep for now though */
-#if 0
-static int txtfmt_osl_find_bool(const char *string)
-{
-	int i, len;
-
-	if      (STR_LITERAL_STARTSWITH(string, "None",  len))  i = len;
-	else if (STR_LITERAL_STARTSWITH(string, "True",  len))  i = len;
-	else if (STR_LITERAL_STARTSWITH(string, "False", len))  i = len;
-	else                                                    i = 0;
-
-	/* If next source char is an identifier (eg. 'i' in "Nonetheless") no match */
-	if (i == 0 || text_check_identifier(string[i]))
-		return -1;
-	return i;
-}
-#endif
-
 static void txtfmt_osl_format_line(SpaceText *st, TextLine *line, const int do_next)
 {
 	FlattenString fs;
diff --git a/source/blender/editors/space_text/text_format_py.c b/source/blender/editors/space_text/text_format_py.c
index 02b67c32052..a78dabbfb9b 100644
--- a/source/blender/editors/space_text/text_format_py.c
+++ b/source/blender/editors/space_text/text_format_py.c
@@ -127,8 +127,8 @@ static int txtfmt_py_find_decorator(const char *string)
 {
 	if (string[0] == '@') {
 		int i = 1;
-		/* whitespace is ok '@  foo' */
-		while (string[i] == '\t' || string[i] == ' ') {
+		/* Whitespace is ok '@  foo' */
+		while (text_check_whitespace(string[i])) {
 			i++;
 		}
 		while (text_check_identifier(string[i])) {
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 530caeca910..38848e30bf6 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -246,12 +246,14 @@ typedef struct ThemeSpace {
 	char vertex_size, outline_width, facedot_size;
 	char noodle_curving;
 
-	char syntaxl[4], syntaxn[4], syntaxb[4]; /* syntax for textwindow and nodes */
+	/* syntax for textwindow and nodes */
+	char syntaxl[4], syntaxs[4];
+	char syntaxb[4], syntaxn[4];
 	char syntaxv[4], syntaxc[4];
 	char syntaxd[4], syntaxr[4];
 	
 	char movie[4], movieclip[4], mask[4], image[4], scene[4], audio[4];		/* for sequence editor */
-	char effect[4], hpad0[4], transition[4], meta[4];
+	char effect[4], transition[4], meta[4];
 	char editmesh_active[4]; 
 
 	char handle_vertex[4];
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 79d6a1d7d6b..21b81e3e16a 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -1636,6 +1636,12 @@ static void rna_def_userdef_theme_space_text(BlenderRNA *brna)
 	RNA_def_property_ui_text(prop, "Syntax Built-in", "");
 	RNA_def_property_update(prop, 0, "rna_userdef_update");
 	
+	prop = RNA_def_property(srna, "syntax_symbols", PROP_FLOAT, PROP_COLOR_GAMMA);
+	RNA_def_property_float_sdna(prop, NULL, "syntaxs");
+	RNA_def_property_array(prop, 3);
+	RNA_def_property_ui_text(prop, "Syntax Symbols", "");
+	RNA_def_property_update(prop, 0, "rna_userdef_update");
+
 	prop = RNA_def_property(srna, "syntax_special", PROP_FLOAT, PROP_COLOR_GAMMA);
 	RNA_def_property_float_sdna(prop, NULL, "syntaxv");
 	RNA_def_property_array(prop, 3);
-- 
cgit v1.2.3


From 33955940e4931e2184434393e0f8c15c36a5c3c6 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Sun, 30 Dec 2012 01:39:55 +0000
Subject: add templates menu for OSL, use preprocessor directive color for
 decorators in python.

---
 source/blender/editors/space_text/text_format_py.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/editors/space_text/text_format_py.c b/source/blender/editors/space_text/text_format_py.c
index a78dabbfb9b..d68d6ae0e78 100644
--- a/source/blender/editors/space_text/text_format_py.c
+++ b/source/blender/editors/space_text/text_format_py.c
@@ -271,7 +271,7 @@ static void txtfmt_py_format_line(SpaceText *st, TextLine *line, const int do_ne
 				/* Special vars(v) or built-in keywords(b) */
 				if      ((i = txtfmt_py_find_specialvar(str))   != -1) prev = FMT_TYPE_SPECIAL;
 				else if ((i = txtfmt_py_find_builtinfunc(str))  != -1) prev = FMT_TYPE_KEYWORD;
-				else if ((i = txtfmt_py_find_decorator(str))    != -1) prev = FMT_TYPE_SPECIAL;  /* could have a new color for this */
+				else if ((i = txtfmt_py_find_decorator(str))    != -1) prev = FMT_TYPE_DIRECTIVE;
 
 				if (i > 0) {
 					memset(fmt, prev, i);
-- 
cgit v1.2.3


From 398da25b1b51cc2966791ca2f672617bc3677980 Mon Sep 17 00:00:00 2001
From: Thomas Dinges 
Date: Sun, 30 Dec 2012 02:51:29 +0000
Subject: OSL Syntax Highlighting: * Added the remaining shader types * Some
 comment and link fixes.

---
 source/blender/editors/space_text/text_format_osl.c | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/space_text/text_format_osl.c b/source/blender/editors/space_text/text_format_osl.c
index 38903d65ec0..a815fb2c34d 100644
--- a/source/blender/editors/space_text/text_format_osl.c
+++ b/source/blender/editors/space_text/text_format_osl.c
@@ -24,7 +24,7 @@
  * ***** END GPL LICENSE BLOCK *****
  */
 
-/** \file blender/editors/space_text/text_format_py.c
+/** \file blender/editors/space_text/text_format_osl.c
  *  \ingroup sptext
  */
 
@@ -44,8 +44,8 @@
 static int txtfmt_osl_find_builtinfunc(const char *string)
 {
 	int i, len;
-	/* list is from...
-	 * XXX - link to docs!
+	/* list is from
+	 * https://github.com/imageworks/OpenShadingLanguage/raw/master/src/doc/osl-languagespec.pdf
 	 */
 	if      (STR_LITERAL_STARTSWITH(string, "break",        len)) i = len;
 	else if (STR_LITERAL_STARTSWITH(string, "closure",      len)) i = len;
@@ -83,7 +83,7 @@ static int txtfmt_osl_find_reserved(const char *string)
 {
 	int i, len;
 	/* list is from...
-	 * XXX - link to docs!
+	 * https://github.com/imageworks/OpenShadingLanguage/raw/master/src/doc/osl-languagespec.pdf
 	 */
 	if      (STR_LITERAL_STARTSWITH(string, "bool",         len)) i = len;
 	else if (STR_LITERAL_STARTSWITH(string, "case",         len)) i = len;
@@ -129,7 +129,7 @@ static int txtfmt_osl_find_reserved(const char *string)
 	return i;
 }
 
-/* Checks the specified source string for a Python special name. This name must
+/* Checks the specified source string for a OSL special name. This name must
  * start at the beginning of the source string and must be followed by a non-
  * identifier (see text_check_identifier(char)) or null character.
  *
@@ -139,8 +139,12 @@ static int txtfmt_osl_find_reserved(const char *string)
 static int txtfmt_osl_find_specialvar(const char *string)
 {
 	int i, len;
-
-	if      (STR_LITERAL_STARTSWITH(string, "shader", len)) i = len;
+	
+	/* OSL shader types */
+	if      (STR_LITERAL_STARTSWITH(string, "shader", 		len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "surface", 		len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "volume", 		len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "displacement", len)) i = len;
 	else                                                    i = 0;
 
 	/* If next source char is an identifier (eg. 'i' in "definate") no match */
-- 
cgit v1.2.3


From f7e8ffdb857e349283585143084c5a6c8a8be042 Mon Sep 17 00:00:00 2001
From: Thomas Dinges 
Date: Sun, 30 Dec 2012 03:11:52 +0000
Subject: OSL Templates: * Add 3 simple templates: ** empty_shader.osl: A basic
 shader declaration to start with ** wireframe.osl: Simple wireframe shader **
 noise.osl: Simple noise shader, with 3 noise types.

---
 source/blender/editors/space_text/text_format_osl.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/editors/space_text/text_format_osl.c b/source/blender/editors/space_text/text_format_osl.c
index a815fb2c34d..f313e9a5f2a 100644
--- a/source/blender/editors/space_text/text_format_osl.c
+++ b/source/blender/editors/space_text/text_format_osl.c
@@ -144,7 +144,7 @@ static int txtfmt_osl_find_specialvar(const char *string)
 	if      (STR_LITERAL_STARTSWITH(string, "shader", 		len)) i = len;
 	else if (STR_LITERAL_STARTSWITH(string, "surface", 		len)) i = len;
 	else if (STR_LITERAL_STARTSWITH(string, "volume", 		len)) i = len;
-	else if (STR_LITERAL_STARTSWITH(string, "displacement", len)) i = len;
+	else if (STR_LITERAL_STARTSWITH(string, "displacement",	len)) i = len;
 	else                                                    i = 0;
 
 	/* If next source char is an identifier (eg. 'i' in "definate") no match */
-- 
cgit v1.2.3


From f62fc79da05b1b3568871adaff8b246eb6b30793 Mon Sep 17 00:00:00 2001
From: Sergey Sharybin 
Date: Sun, 30 Dec 2012 13:01:47 +0000
Subject: 16 bit PNG write support

This commit adds a support of saving 16bit PNG files.

Alpha for such files would be premultiplied, would be corrected
with an upcoming alpha premul cleanup (it's not the only format
which will output 16bit image with premul alpha).
---
 source/blender/blenkernel/intern/image.c |  14 +++-
 source/blender/imbuf/IMB_imbuf_types.h   |   6 +-
 source/blender/imbuf/intern/filetype.c   |   2 +-
 source/blender/imbuf/intern/png.c        | 108 ++++++++++++++++++++++++-------
 4 files changed, 102 insertions(+), 28 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 22995e5a7ee..8630ace4edf 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -1119,6 +1119,8 @@ char BKE_imtype_valid_depths(const char imtype)
 			return R_IMF_CHAN_DEPTH_10;
 		case R_IMF_IMTYPE_JP2:
 			return R_IMF_CHAN_DEPTH_8 | R_IMF_CHAN_DEPTH_12 | R_IMF_CHAN_DEPTH_16;
+		case R_IMF_IMTYPE_PNG:
+			return R_IMF_CHAN_DEPTH_8 | R_IMF_CHAN_DEPTH_16;
 		/* most formats are 8bit only */
 		default:
 			return R_IMF_CHAN_DEPTH_8;
@@ -1313,9 +1315,13 @@ void BKE_imbuf_to_image_format(struct ImageFormatData *im_format, const ImBuf *i
 		im_format->imtype = R_IMF_IMTYPE_RADHDR;
 #endif
 
-	else if (ftype == PNG)
+	else if (ftype == PNG) {
 		im_format->imtype = R_IMF_IMTYPE_PNG;
 
+		if (custom_flags & PNG_16BIT)
+			im_format->depth = R_IMF_CHAN_DEPTH_16;
+	}
+
 #ifdef WITH_DDS
 	else if (ftype == DDS)
 		im_format->imtype = R_IMF_IMTYPE_DDS;
@@ -1847,8 +1853,12 @@ int BKE_imbuf_write(ImBuf *ibuf, const char *name, ImageFormatData *imf)
 	else if (ELEM5(imtype, R_IMF_IMTYPE_PNG, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_THEORA, R_IMF_IMTYPE_XVID)) {
 		ibuf->ftype = PNG;
 
-		if (imtype == R_IMF_IMTYPE_PNG)
+		if (imtype == R_IMF_IMTYPE_PNG) {
+			if (imf->depth == R_IMF_CHAN_DEPTH_16)
+				ibuf->ftype |= PNG_16BIT;
+
 			ibuf->ftype |= compress;
+		}
 
 	}
 #ifdef WITH_DDS
diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h
index 433123914ce..9fe66b562d1 100644
--- a/source/blender/imbuf/IMB_imbuf_types.h
+++ b/source/blender/imbuf/IMB_imbuf_types.h
@@ -172,9 +172,9 @@ typedef struct ImBuf {
 
 /*
  * The bit flag is stored in the ImBuf.ftype variable.
- * Note that the lower 10 bits is used for storing custom flags
+ * Note that the lower 11 bits is used for storing custom flags
  */
-#define IB_CUSTOM_FLAGS_MASK 0x3ff
+#define IB_CUSTOM_FLAGS_MASK 0x400
 
 #define PNG				(1 << 30)
 #define TGA				(1 << 28)
@@ -221,6 +221,8 @@ typedef struct ImBuf {
 #define JP2_J2K	(1 << 11)
 #endif
 
+#define PNG_16BIT			(1 << 10)
+
 #define RAWTGA	        (TGA | 1)
 
 #define JPG_STD	        (JPG | (0 << 8))
diff --git a/source/blender/imbuf/intern/filetype.c b/source/blender/imbuf/intern/filetype.c
index 5c2dc0c7df9..6d1f2abab0b 100644
--- a/source/blender/imbuf/intern/filetype.c
+++ b/source/blender/imbuf/intern/filetype.c
@@ -69,7 +69,7 @@ void quicktime_exit(void);
 
 ImFileType IMB_FILE_TYPES[] = {
 	{NULL, NULL, imb_is_a_jpeg, imb_ftype_default, imb_load_jpeg, imb_savejpeg, NULL, 0, JPG, COLOR_ROLE_DEFAULT_BYTE},
-	{NULL, NULL, imb_is_a_png, imb_ftype_default, imb_loadpng, imb_savepng, NULL, 0, PNG, COLOR_ROLE_DEFAULT_BYTE},
+	{NULL, NULL, imb_is_a_png, imb_ftype_default, imb_loadpng, imb_savepng, NULL, IM_FTYPE_FLOAT, PNG, COLOR_ROLE_DEFAULT_BYTE},
 	{NULL, NULL, imb_is_a_bmp, imb_ftype_default, imb_bmp_decode, imb_savebmp, NULL, 0, BMP, COLOR_ROLE_DEFAULT_BYTE},
 	{NULL, NULL, imb_is_a_targa, imb_ftype_default, imb_loadtarga, imb_savetarga, NULL, 0, TGA, COLOR_ROLE_DEFAULT_BYTE},
 	{NULL, NULL, imb_is_a_iris, imb_ftype_iris, imb_loadiris, imb_saveiris, NULL, 0, IMAGIC, COLOR_ROLE_DEFAULT_BYTE},
diff --git a/source/blender/imbuf/intern/png.c b/source/blender/imbuf/intern/png.c
index dcfebb95b87..c0737fadffa 100644
--- a/source/blender/imbuf/intern/png.c
+++ b/source/blender/imbuf/intern/png.c
@@ -109,10 +109,14 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
 
 	unsigned char *pixels = NULL;
 	unsigned char *from, *to;
+	unsigned short *pixels16 = NULL, *to16;
+	float *from_float;
 	png_bytepp row_pointers = NULL;
 	int i, bytesperpixel, color_type = PNG_COLOR_TYPE_GRAY;
 	FILE *fp = NULL;
 
+	int is_16bit = (ibuf->ftype & PNG_16BIT) && ibuf->rect_float;
+
 	/* use the jpeg quality setting for compression */
 	int compression;
 	compression = (int)(((float)(ibuf->ftype & 0xff) / 11.1111f));
@@ -150,8 +154,12 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
 
 	/* copy image data */
 
-	pixels = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned char), "pixels");
-	if (pixels == NULL) {
+	if (is_16bit)
+		pixels16 = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned short), "png 16bit pixels");
+	else
+		pixels = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned char), "png 8bit pixels");
+
+	if (pixels == NULL && pixels16 == NULL) {
 		png_destroy_write_struct(&png_ptr, &info_ptr);
 		printf("imb_savepng: Cannot allocate pixels array of %dx%d, %d bytes per pixel for file: '%s'\n", ibuf->x, ibuf->y, bytesperpixel, name);
 		return 0;
@@ -159,32 +167,63 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
 
 	from = (unsigned char *) ibuf->rect;
 	to = pixels;
+	from_float = ibuf->rect_float;
+	to16 = pixels16;
 
 	switch (bytesperpixel) {
 		case 4:
 			color_type = PNG_COLOR_TYPE_RGBA;
-			for (i = ibuf->x * ibuf->y; i > 0; i--) {
-				to[0] = from[0];
-				to[1] = from[1];
-				to[2] = from[2];
-				to[3] = from[3];
-				to += 4; from += 4;
+			if (is_16bit) {
+				for (i = ibuf->x * ibuf->y; i > 0; i--) {
+					to16[0] = FTOUSHORT(from_float[0]);
+					to16[1] = FTOUSHORT(from_float[1]);
+					to16[2] = FTOUSHORT(from_float[2]);
+					to16[3] = FTOUSHORT(from_float[3]);
+					to16 += 4; from_float += 4;
+				}
+			}
+			else {
+				for (i = ibuf->x * ibuf->y; i > 0; i--) {
+					to[0] = from[0];
+					to[1] = from[1];
+					to[2] = from[2];
+					to[3] = from[3];
+					to += 4; from += 4;
+				}
 			}
 			break;
 		case 3:
 			color_type = PNG_COLOR_TYPE_RGB;
-			for (i = ibuf->x * ibuf->y; i > 0; i--) {
-				to[0] = from[0];
-				to[1] = from[1];
-				to[2] = from[2];
-				to += 3; from += 4;
+			if (is_16bit) {
+				for (i = ibuf->x * ibuf->y; i > 0; i--) {
+					to16[0] = FTOUSHORT(from_float[0]);
+					to16[1] = FTOUSHORT(from_float[1]);
+					to16[2] = FTOUSHORT(from_float[2]);
+					to16 += 3; from_float += 4;
+				}
+			}
+			else {
+				for (i = ibuf->x * ibuf->y; i > 0; i--) {
+					to[0] = from[0];
+					to[1] = from[1];
+					to[2] = from[2];
+					to += 3; from += 4;
+				}
 			}
 			break;
 		case 1:
 			color_type = PNG_COLOR_TYPE_GRAY;
-			for (i = ibuf->x * ibuf->y; i > 0; i--) {
-				to[0] = from[0];
-				to++; from += 4;
+			if (is_16bit) {
+				for (i = ibuf->x * ibuf->y; i > 0; i--) {
+					to16[0] = FTOUSHORT(from_float[0]);
+					to16++; from_float += 4;
+				}
+			}
+			else {
+				for (i = ibuf->x * ibuf->y; i > 0; i--) {
+					to[0] = from[0];
+					to++; from += 4;
+				}
 			}
 			break;
 	}
@@ -203,7 +242,10 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
 		fp = BLI_fopen(name, "wb");
 		if (!fp) {
 			png_destroy_write_struct(&png_ptr, &info_ptr);
-			MEM_freeN(pixels);
+			if (pixels)
+				MEM_freeN(pixels);
+			if (pixels16)
+				MEM_freeN(pixels16);
 			printf("imb_savepng: Cannot open file for writing: '%s'\n", name);
 			return 0;
 		}
@@ -227,7 +269,7 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
 	             info_ptr,
 	             ibuf->x,
 	             ibuf->y,
-	             8,
+	             is_16bit ? 16 : 8,
 	             color_type,
 	             PNG_INTERLACE_NONE,
 	             PNG_COMPRESSION_TYPE_DEFAULT,
@@ -268,12 +310,19 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
 	/* write the file header information */
 	png_write_info(png_ptr, info_ptr);
 
+#ifdef __LITTLE_ENDIAN__
+	png_set_swap(png_ptr);
+#endif
+
 	/* allocate memory for an array of row-pointers */
 	row_pointers = (png_bytepp) MEM_mallocN(ibuf->y * sizeof(png_bytep), "row_pointers");
 	if (row_pointers == NULL) {
 		printf("imb_savepng: Cannot allocate row-pointers array for file '%s'\n", name);
 		png_destroy_write_struct(&png_ptr, &info_ptr);
-		MEM_freeN(pixels);
+		if (pixels)
+			MEM_freeN(pixels);
+		if (pixels16)
+			MEM_freeN(pixels16);
 		if (fp) {
 			fclose(fp);
 		}
@@ -281,9 +330,17 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
 	}
 
 	/* 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));
+	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);
+		}
+	}
+	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));
+		}
 	}
 
 	/* write out the entire image data in one call */
@@ -293,7 +350,10 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
 	png_write_end(png_ptr, info_ptr);
 
 	/* clean up */
-	MEM_freeN(pixels);
+	if (pixels)
+		MEM_freeN(pixels);
+	if (pixels16)
+		MEM_freeN(pixels16);
 	MEM_freeN(row_pointers);
 	png_destroy_write_struct(&png_ptr, &info_ptr);
 
@@ -394,6 +454,8 @@ ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags, char colorspace[I
 
 	if (ibuf) {
 		ibuf->ftype = PNG;
+		if (bit_depth == 16)
+			ibuf->ftype |= PNG_16BIT;
 
 		if (png_get_valid(png_ptr, info_ptr, PNG_INFO_pHYs)) {
 			int unit_type;
-- 
cgit v1.2.3


From 82d6b176620c3d34e16bb8b0b10e9465898bd080 Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Sun, 30 Dec 2012 14:31:34 +0000
Subject: More trackpad woes:

Rotate with two-finger trackpad swipes should follow same principle as
for panning. This is first commit - for clarity.

Remaining issue is that for each system preset (in your OS) blender should
work as you expect too... pan, rotate and zoom gestures might need
each an own direction preset. Might be also messy, but then things can at
least work for everyone. Thinking it over and testing more now.
---
 source/blender/editors/space_view3d/view3d_edit.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 8b7601dc491..e984a3f5cfd 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -921,7 +921,8 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, wmEvent *event)
 	}
 	
 	if (event->type == MOUSEPAN) {
-		viewrotate_apply(vod, event->prevx, event->prevy);
+		/* invert it, trackpad scroll then follows how you mapped it globally */
+		viewrotate_apply(vod, 2 * event->x - event->prevx, 2 * event->y - event->prevy);
 		ED_view3d_depth_tag_update(rv3d);
 		
 		viewops_data_free(C, op);
-- 
cgit v1.2.3


From 3de85a87973ea9b8a5371cc025b8cb87fcbcde9a Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Sun, 30 Dec 2012 15:16:08 +0000
Subject: style cleanup: casts, some casts had odd formatting, but very few.
 Style checker script detects this now so easy to detect this if new code is
 added that doesnt follow blenders style.

---
 source/blender/editors/interface/interface_regions.c |  8 ++++----
 source/blender/makesrna/intern/rna_particle.c        | 10 +++++-----
 source/blender/makesrna/intern/rna_render.c          |  2 +-
 source/blender/makesrna/intern/rna_tracking.c        |  4 ++--
 4 files changed, 12 insertions(+), 12 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index a1ad7d6aaa7..329e1aabe67 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -651,10 +651,10 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
 	ofsx = 0; //(but->block->panel) ? but->block->panel->ofsx : 0;
 	ofsy = 0; //(but->block->panel) ? but->block->panel->ofsy : 0;
 
-	rect_fl.xmin = (but->rect.xmin + but->rect.xmax) * 0.5f + ofsx - (TIP_BORDER_X );
-	rect_fl.xmax = rect_fl.xmin + fontw + (TIP_BORDER_X );
-	rect_fl.ymax = but->rect.ymin + ofsy - (TIP_BORDER_Y );
-	rect_fl.ymin = rect_fl.ymax - fonth  - (TIP_BORDER_Y );
+	rect_fl.xmin = (but->rect.xmin + but->rect.xmax) * 0.5f + ofsx - TIP_BORDER_X;
+	rect_fl.xmax = rect_fl.xmin + fontw + TIP_BORDER_X;
+	rect_fl.ymax = but->rect.ymin + ofsy - TIP_BORDER_Y;
+	rect_fl.ymin = rect_fl.ymax - fonth  - TIP_BORDER_Y;
 
 #undef TIP_MARGIN_Y
 #undef TIP_BORDER_X
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index 0704e29925e..c6d1adac19a 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -277,7 +277,7 @@ static void rna_Particle_uv_on_emitter(ParticleData *particle, ParticleSystemMod
 		
 		if (num != DMCACHE_NOTFOUND) {
 			MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
-			MTFace *mtface = (MTFace*)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, 0);
+			MTFace *mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, 0);
 			mtface += num;
 			
 			psys_interpolate_uvs(mtface, mface->v4, particle->fuv, n_uv);
@@ -290,7 +290,7 @@ static void rna_Particle_uv_on_emitter(ParticleData *particle, ParticleSystemMod
 }
 
 static void rna_ParticleSystem_co_hair(ParticleSystem *particlesystem, Object *object, ParticleSystemModifierData *modifier, int particle_no, int step,
-                                             float n_co[3])
+                                       float n_co[3])
 {
 	ParticleSettings *part = 0;
 	ParticleData *pars = 0;
@@ -395,7 +395,7 @@ static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, Par
 		if (n_uv && ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
 			if (num != DMCACHE_NOTFOUND) {
 				MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
-				MTFace *mtface = (MTFace*)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, 0);
+				MTFace *mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, 0);
 				mtface += num;
 				
 				psys_interpolate_uvs(mtface, mface->v4, particle->fuv, n_uv);
@@ -416,7 +416,7 @@ static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, Par
 			if (n_uv && ELEM(PART_FROM_FACE, PART_FROM_FACE, PART_FROM_VOLUME)) {
 				if (cpa->num != DMCACHE_NOTFOUND) {
 					MFace *mface = modifier->dm->getTessFaceData(modifier->dm, cpa->num, CD_MFACE);
-					MTFace *mtface = (MTFace*)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, 0);
+					MTFace *mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, 0);
 					mtface += cpa->num;
 					
 					psys_interpolate_uvs(mtface, mface->v4, cpa->fuv, n_uv);
@@ -438,7 +438,7 @@ static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, Par
 			if (n_uv && ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
 				if (num != DMCACHE_NOTFOUND) {
 					MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
-					MTFace *mtface = (MTFace*)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, 0);
+					MTFace *mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, 0);
 					mtface += num;
 					
 					psys_interpolate_uvs(mtface, mface->v4, parent->fuv, n_uv);
diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c
index 46b22cd0963..03dc58233d5 100644
--- a/source/blender/makesrna/intern/rna_render.c
+++ b/source/blender/makesrna/intern/rna_render.c
@@ -137,7 +137,7 @@ static void engine_update_script_node(RenderEngine *engine, struct bNodeTree *nt
 	FunctionRNA *func;
 
 	RNA_pointer_create(NULL, engine->type->ext.srna, engine, &ptr);
-	RNA_pointer_create((ID*)ntree, &RNA_Node, node, &nodeptr);
+	RNA_pointer_create((ID *)ntree, &RNA_Node, node, &nodeptr);
 	func = &rna_RenderEngine_update_script_node_func;
 
 	RNA_parameter_list_create(&list, &ptr, func);
diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c
index f5bcab3e530..7cc57947671 100644
--- a/source/blender/makesrna/intern/rna_tracking.c
+++ b/source/blender/makesrna/intern/rna_tracking.c
@@ -280,7 +280,7 @@ static void rna_tracking_flushUpdate(Main *UNUSED(bmain), Scene *scene, PointerR
 
 static void rna_trackingObject_tracks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
 {
-	MovieTrackingObject *object = (MovieTrackingObject * )ptr->data;
+	MovieTrackingObject *object = (MovieTrackingObject *)ptr->data;
 
 	if (object->flag & TRACKING_OBJECT_CAMERA) {
 		MovieClip *clip = (MovieClip *)ptr->id.data;
@@ -294,7 +294,7 @@ static void rna_trackingObject_tracks_begin(CollectionPropertyIterator *iter, Po
 
 static PointerRNA rna_trackingObject_reconstruction_get(PointerRNA *ptr)
 {
-	MovieTrackingObject *object = (MovieTrackingObject * )ptr->data;
+	MovieTrackingObject *object = (MovieTrackingObject *)ptr->data;
 
 	if (object->flag & TRACKING_OBJECT_CAMERA) {
 		MovieClip *clip = (MovieClip *)ptr->id.data;
-- 
cgit v1.2.3


From e54b95d1c935f7a21c9cdffc0c06d883e5eecb67 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Sun, 30 Dec 2012 15:40:49 +0000
Subject: optimization for text drawing: - dont set the color for each
 character, check if it changes from the previous one. - dont memcpy text into
 a null terminated string to draw, instead rely on the length argument to
 BLF_draw().

---
 source/blender/editors/space_text/text_draw.c | 32 +++++++++++++--------------
 1 file changed, 15 insertions(+), 17 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index 2256c1c7e25..a5e81ecd535 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -77,26 +77,17 @@ static int text_font_draw(SpaceText *UNUSED(st), int x, int y, const char *str)
 
 static int text_font_draw_character(SpaceText *st, int x, int y, char c)
 {
-	char str[2];
-	str[0] = c;
-	str[1] = '\0';
-
 	BLF_position(mono, x, y, 0);
-	BLF_draw(mono, str, 1);
+	BLF_draw(mono, &c, 1);
 
 	return st->cwidth;
 }
 
 static int text_font_draw_character_utf8(SpaceText *st, int x, int y, const char *c)
 {
-	char str[BLI_UTF8_MAX + 1];
-	size_t len = BLI_str_utf8_size_safe(c);
-	memcpy(str, c, len);
-	str[len] = '\0';
-
+	const size_t len = BLI_str_utf8_size_safe(c);
 	BLF_position(mono, x, y, 0);
-	BLF_draw(mono, str, len);
-
+	BLF_draw(mono, c, len);
 	return st->cwidth;
 }
 
@@ -365,6 +356,7 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w
 	FlattenString fs;
 	int basex, i, a, start, end, max, lines; /* view */
 	int mi, ma, mstart, mend;                /* mem */
+	char fmt_prev = 0xff;
 	
 	flatten_string(st, &fs, str);
 	str = fs.buf;
@@ -388,7 +380,9 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w
 
 			/* Draw the visible portion of text on the overshot line */
 			for (a = start, ma = mstart; a < end; a++, ma += BLI_str_utf8_size_safe(str + ma)) {
-				if (st->showsyntax && format) format_draw_color(format[a]);
+				if (st->showsyntax && format) {
+					if (fmt_prev != format[a]) format_draw_color(fmt_prev = format[a]);
+				}
 				x += text_font_draw_character_utf8(st, x, y, str + ma);
 			}
 			y -= st->lheight_dpi + TXT_LINE_SPACING;
@@ -406,8 +400,9 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w
 
 	/* Draw the remaining text */
 	for (a = start, ma = mstart; str[ma] && y > 0; a++, ma += BLI_str_utf8_size_safe(str + ma)) {
-		if (st->showsyntax && format)
-			format_draw_color(format[a]);
+		if (st->showsyntax && format) {
+			if (fmt_prev != format[a]) format_draw_color(fmt_prev = format[a]);
+		}
 
 		x += text_font_draw_character_utf8(st, x, y, str + ma);
 	}
@@ -438,15 +433,18 @@ static int text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int dra
 		
 		if (st->showsyntax && format) {
 			int a, str_shift = 0;
+			char fmt_prev = 0xff;
 			format = format + cshift;
 
 			for (a = 0; a < amount; a++) {
-				format_draw_color(format[a]);
+				if (format[a] != fmt_prev) format_draw_color(fmt_prev = format[a]);
 				x += text_font_draw_character_utf8(st, x, y, in + str_shift);
 				str_shift += BLI_str_utf8_size_safe(in + str_shift);
 			}
 		}
-		else text_font_draw(st, x, y, in);
+		else {
+			text_font_draw(st, x, y, in);
+		}
 	}
 	else {
 		while (w-- && *acc++ < maxwidth)
-- 
cgit v1.2.3


From feb0d1d698ee827c181fb199a341410db7577a29 Mon Sep 17 00:00:00 2001
From: Brecht Van Lommel 
Date: Sun, 30 Dec 2012 18:17:20 +0000
Subject: Fix crash in syntax color code when drawing a text editor with no
 text.

---
 source/blender/editors/space_text/text_draw.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index a5e81ecd535..11a5687915b 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -1275,7 +1275,7 @@ static void draw_brackets(SpaceText *st, ARegion *ar)
 void draw_text_main(SpaceText *st, ARegion *ar)
 {
 	Text *text = st->text;
-	TextFormatType *tft = ED_text_format_get(text);
+	TextFormatType *tft;
 	TextLine *tmp;
 	rcti scroll, back;
 	char linenr[12];
@@ -1303,6 +1303,7 @@ void draw_text_main(SpaceText *st, ARegion *ar)
 	calc_text_rcts(st, ar, &scroll, &back); /* scroll will hold the entire bar size */
 
 	/* update syntax formatting if needed */
+	tft = ED_text_format_get(text);
 	tmp = text->lines.first;
 	lineno = 0;
 	for (i = 0; i < st->top && tmp; i++) {
-- 
cgit v1.2.3


From a8811094ea9241ac8678a7d4c3fff4ab2ac5bf20 Mon Sep 17 00:00:00 2001
From: Nicholas Bishop 
Date: Sun, 30 Dec 2012 18:20:52 +0000
Subject: Import the RangeTree library into extern

RangeTree is a simple C++ tree set for storing non-overlapping scalar
ranges. Original source from:
https://github.com/nicholasbishop/RangeTree

Also update the build systems to include RangeTree.
---
 source/blenderplayer/CMakeLists.txt | 1 +
 source/creator/CMakeLists.txt       | 1 +
 2 files changed, 2 insertions(+)

(limited to 'source')

diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt
index 85bb07d6e83..d606605e8d5 100644
--- a/source/blenderplayer/CMakeLists.txt
+++ b/source/blenderplayer/CMakeLists.txt
@@ -149,6 +149,7 @@ endif()
 		bf_intern_raskter
 		bf_intern_opencolorio
 		bf_intern_opennl
+		extern_rangetree
 	)
 
 	if(WITH_MOD_CLOTH_ELTOPO)
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index b66c000ac89..c53f27c7326 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -914,6 +914,7 @@ endif()
 		cycles_subd
 		bf_intern_raskter
 		bf_intern_opencolorio
+		extern_rangetree
 	)
 
 	if(WITH_COMPOSITOR)
-- 
cgit v1.2.3


From 2d39e4641428d4557fb6f2fcb7f13c64aef3ff3e Mon Sep 17 00:00:00 2001
From: Nicholas Bishop 
Date: Sun, 30 Dec 2012 18:22:21 +0000
Subject: Add BM_edge_calc_squared_length() query function

Same as BM_edge_calc_length(), but avoids square root for cases where
only comparison is needed.
---
 source/blender/bmesh/intern/bmesh_queries.c | 10 +++++++++-
 source/blender/bmesh/intern/bmesh_queries.h |  1 +
 2 files changed, 10 insertions(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c
index 5f5c60dde3f..d723e6464df 100644
--- a/source/blender/bmesh/intern/bmesh_queries.c
+++ b/source/blender/bmesh/intern/bmesh_queries.c
@@ -468,13 +468,21 @@ BMEdge *BM_vert_other_disk_edge(BMVert *v, BMEdge *e_first)
 }
 
 /**
- * Returms edge length
+ * Returns edge length
  */
 float BM_edge_calc_length(BMEdge *e)
 {
 	return len_v3v3(e->v1->co, e->v2->co);
 }
 
+/**
+ * Returns edge length squared (for comparisons)
+ */
+float BM_edge_calc_squared_length(BMEdge *e)
+{
+	return len_squared_v3v3(e->v1->co, e->v2->co);
+}
+
 /**
  * Utility function, since enough times we have an edge
  * and want to access 2 connected faces.
diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h
index 9af792417bf..59c3fae8c5d 100644
--- a/source/blender/bmesh/intern/bmesh_queries.h
+++ b/source/blender/bmesh/intern/bmesh_queries.h
@@ -37,6 +37,7 @@ int     BM_vert_in_edge(BMEdge *e, BMVert *v);
 int     BM_verts_in_edge(BMVert *v1, BMVert *v2, BMEdge *e);
 
 float   BM_edge_calc_length(BMEdge *e);
+float   BM_edge_calc_squared_length(BMEdge *e);
 int     BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb);
 int     BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb);
 BMVert *BM_edge_other_vert(BMEdge *e, BMVert *v);
-- 
cgit v1.2.3


From 66e70e6caa9fe68574e829c7a8d43aed64d47900 Mon Sep 17 00:00:00 2001
From: Nicholas Bishop 
Date: Sun, 30 Dec 2012 18:23:03 +0000
Subject: Add function to find closest point in triangle to another point

New function is closest_to_tri_v3() in BLI_math_geom.
---
 source/blender/blenlib/BLI_math_geom.h    |  3 ++
 source/blender/blenlib/intern/math_geom.c | 82 +++++++++++++++++++++++++++++++
 2 files changed, 85 insertions(+)

(limited to 'source')

diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index 2f3521fa030..b322d9d7aef 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -72,6 +72,9 @@ float closest_to_line_v2(float r[2], const float p[2], const float l1[2], const
 void closest_to_line_segment_v3(float r[3], const float p[3], const float l1[3], const float l2[3]);
 void closest_to_plane_v3(float r[3], const float plane_co[3], const float plane_no_unit[3], const float pt[3]);
 
+/* Set 'r' to the point in triangle (t1, t2, t3) closest to point 'p' */
+void closest_on_tri_to_point_v3(float r[3], const float p[3], const float t1[3], const float t2[3], const float t3[3]);
+
 
 float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3]);
 float line_point_factor_v2(const float p[2], const float l1[2], const float l2[2]);
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index 24c4e87d6ab..eec59e47ea6 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -296,6 +296,88 @@ float dist_to_line_segment_v3(const float v1[3], const float v2[3], const float
 	return len_v3v3(closest, v1);
 }
 
+/* Adapted from "Real-Time Collision Detection" by Christer Ericson,
+ * published by Morgan Kaufmann Publishers, copyright 2005 Elsevier Inc.
+ * 
+ * Set 'r' to the point in triangle (a, b, c) closest to point 'p' */
+void closest_on_tri_to_point_v3(float r[3], const float p[3],
+					   const float a[3], const float b[3], const float c[3])
+{
+	float ab[3], ac[3], ap[3], d1, d2;
+	float bp[3], d3, d4, vc, cp[3], d5, d6, vb, va;
+	float denom, v, w;
+
+	/* Check if P in vertex region outside A */
+	sub_v3_v3v3(ab, b, a);
+	sub_v3_v3v3(ac, c, a);
+	sub_v3_v3v3(ap, p, a);
+	d1 = dot_v3v3(ab, ap);
+	d2 = dot_v3v3(ac, ap);
+	if (d1 <= 0.0f && d2 <= 0.0f) {
+		/* barycentric coordinates (1,0,0) */
+		copy_v3_v3(r, a);
+		return;
+	}
+
+	/* Check if P in vertex region outside B */
+	sub_v3_v3v3(bp, p, b);
+	d3 = dot_v3v3(ab, bp);
+	d4 = dot_v3v3(ac, bp);
+	if (d3 >= 0.0f && d4 <= d3) {
+		/* barycentric coordinates (0,1,0) */
+		copy_v3_v3(r, b);
+		return;
+	}
+	/* Check if P in edge region of AB, if so return projection of P onto AB */
+	vc = d1*d4 - d3*d2;
+	if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f) {
+		float v = d1 / (d1 - d3);
+		/* barycentric coordinates (1-v,v,0) */
+		madd_v3_v3v3fl(r, a, ab, v);
+		return;
+	}
+	/* Check if P in vertex region outside C */
+	sub_v3_v3v3(cp, p, c);
+	d5 = dot_v3v3(ab, cp);
+	d6 = dot_v3v3(ac, cp);
+	if (d6 >= 0.0f && d5 <= d6) {
+		/* barycentric coordinates (0,0,1) */
+		copy_v3_v3(r, c);
+		return;
+	}
+	/* Check if P in edge region of AC, if so return projection of P onto AC */
+	vb = d5*d2 - d1*d6;
+	if (vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f) {
+		float w = d2 / (d2 - d6);
+		/* barycentric coordinates (1-w,0,w) */
+		madd_v3_v3v3fl(r, a, ac, w);
+		return;
+	}
+	/* Check if P in edge region of BC, if so return projection of P onto BC */
+	va = d3*d6 - d5*d4;
+	if (va <= 0.0f && (d4 - d3) >= 0.0f && (d5 - d6) >= 0.0f) {
+		float w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
+		/* barycentric coordinates (0,1-w,w) */
+		sub_v3_v3v3(r, c, b);
+		mul_v3_fl(r, w);
+		add_v3_v3(r, b);
+		return;
+	}
+
+	/* P inside face region. Compute Q through its barycentric coordinates (u,v,w) */
+	denom = 1.0f / (va + vb + vc);
+	v = vb * denom;
+	w = vc * denom;
+
+	/* = u*a + v*b + w*c, u = va * denom = 1.0f - v - w */
+	/* ac * w */
+	mul_v3_fl(ac, w);
+	/* a + ab * v */
+	madd_v3_v3v3fl(r, a, ab, v);
+	/* a + ab * v + ac * w */
+	add_v3_v3(r, ac);
+}
+
 /******************************* Intersection ********************************/
 
 /* intersect Line-Line, shorts */
-- 
cgit v1.2.3


From 1b4b5f98cb2f568c55d00ca546878b1a6959dad9 Mon Sep 17 00:00:00 2001
From: Nicholas Bishop 
Date: Sun, 30 Dec 2012 18:23:42 +0000
Subject: Disable fall through to global undo from paint/sculpt undo

Undoing/redoing in sculpt and other paint modes should only use the
mode-specific undo, not global undo. It is now consistent with edit
mode and avoids tricky interaction between the two systems.
---
 source/blender/editors/util/undo.c | 42 +++++++++++++++++---------------------
 1 file changed, 19 insertions(+), 23 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c
index 1753a564a3c..1dc7e0c90e8 100644
--- a/source/blender/editors/util/undo.c
+++ b/source/blender/editors/util/undo.c
@@ -162,15 +162,18 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
 		}
 	}
 	else {
-		int do_glob_undo = FALSE;
-		
+		/* Note: we used to do a fall-through here where if the
+		 * mode-specific undo system had no more steps to undo (or
+		 * redo), the global undo would run.
+		 *
+		 * That was inconsistent with editmode, and also makes for
+		 * unecessarily tricky interaction with the other undo
+		 * systems. */
 		if (obact && obact->mode & OB_MODE_TEXTURE_PAINT) {
-			if (!ED_undo_paint_step(C, UNDO_PAINT_IMAGE, step, undoname))
-				do_glob_undo = TRUE;
+			ED_undo_paint_step(C, UNDO_PAINT_IMAGE, step, undoname);
 		}
 		else if (obact && obact->mode & OB_MODE_SCULPT) {
-			if (!ED_undo_paint_step(C, UNDO_PAINT_MESH, step, undoname))
-				do_glob_undo = TRUE;
+			ED_undo_paint_step(C, UNDO_PAINT_MESH, step, undoname);
 		}
 		else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) {
 			if (step == 1)
@@ -178,24 +181,17 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
 			else
 				PE_redo(CTX_data_scene(C));
 		}
-		else {
-			do_glob_undo = TRUE;
-		}
-		
-		if (do_glob_undo) {
-			if (U.uiflag & USER_GLOBALUNDO) {
-				// note python defines not valid here anymore.
-				//#ifdef WITH_PYTHON
-				// XXX		BPY_scripts_clear_pyobjects();
-				//#endif
-				if (undoname)
-					BKE_undo_name(C, undoname);
-				else
-					BKE_undo_step(C, step);
+		else if (U.uiflag & USER_GLOBALUNDO) {
+			// note python defines not valid here anymore.
+			//#ifdef WITH_PYTHON
+			// XXX		BPY_scripts_clear_pyobjects();
+			//#endif
+			if (undoname)
+				BKE_undo_name(C, undoname);
+			else
+				BKE_undo_step(C, step);
 				
-				WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, CTX_data_scene(C));
-			}
-			
+			WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, CTX_data_scene(C));
 		}
 	}
 	
-- 
cgit v1.2.3


From 2e9cb31c02378fd5b9b3f26f6f26501d1aa999a2 Mon Sep 17 00:00:00 2001
From: Nicholas Bishop 
Date: Sun, 30 Dec 2012 18:24:08 +0000
Subject: Add BMLog for efficiently storing changes to vertices and faces

The BMLog is an interface for storing undo/redo steps as a BMesh is
modified. It only stores changes to the BMesh, not full copies.

Currently it supports the following types of changes:
- Adding and removing vertices
- Adding and removing faces
- Moving vertices
- Setting vertex paint-mask values
- Setting vertex hflags
---
 source/blender/bmesh/CMakeLists.txt     |   3 +
 source/blender/bmesh/SConscript         |   4 +-
 source/blender/bmesh/bmesh.h            |   1 +
 source/blender/bmesh/intern/bmesh_log.c | 962 ++++++++++++++++++++++++++++++++
 source/blender/bmesh/intern/bmesh_log.h | 102 ++++
 5 files changed, 1071 insertions(+), 1 deletion(-)
 create mode 100644 source/blender/bmesh/intern/bmesh_log.c
 create mode 100644 source/blender/bmesh/intern/bmesh_log.h

(limited to 'source')

diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt
index c41b0703240..955b18c3db7 100644
--- a/source/blender/bmesh/CMakeLists.txt
+++ b/source/blender/bmesh/CMakeLists.txt
@@ -31,6 +31,7 @@ set(INC
 	../makesdna
 	../../../intern/guardedalloc
 	../../../extern/bullet2/src
+	../../../extern/rangetree
 	../../../intern/opennl/extern
 )
 
@@ -74,6 +75,8 @@ set(SRC
 	intern/bmesh_iterators.c
 	intern/bmesh_iterators.h
 	intern/bmesh_iterators_inline.h
+	intern/bmesh_log.c
+	intern/bmesh_log.h
 	intern/bmesh_marking.c
 	intern/bmesh_marking.h
 	intern/bmesh_mesh.c
diff --git a/source/blender/bmesh/SConscript b/source/blender/bmesh/SConscript
index 722b7518630..a8ca514297e 100644
--- a/source/blender/bmesh/SConscript
+++ b/source/blender/bmesh/SConscript
@@ -41,7 +41,9 @@ incs = [
 	'../blenkernel',
 	'#/intern/guardedalloc',
 	'#/extern/bullet2/src',
-	'#/intern/opennl/extern',	]
+        '#/extern/rangetree',
+	'#/intern/opennl/extern'
+	]
 
 defs = []
 
diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h
index 6257aa4bf3e..60d38719ddb 100644
--- a/source/blender/bmesh/bmesh.h
+++ b/source/blender/bmesh/bmesh.h
@@ -254,6 +254,7 @@ extern "C" {
 #include "intern/bmesh_core.h"
 #include "intern/bmesh_interp.h"
 #include "intern/bmesh_iterators.h"
+#include "intern/bmesh_log.h"
 #include "intern/bmesh_marking.h"
 #include "intern/bmesh_mesh.h"
 #include "intern/bmesh_mesh_conv.h"
diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c
new file mode 100644
index 00000000000..1e94e81e6d7
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_log.c
@@ -0,0 +1,962 @@
+/*
+ * ***** 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 *****
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_ghash.h"
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_mempool.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_customdata.h"
+
+#include "bmesh.h"
+#include "bmesh_log.h"
+#include "range_tree_c_api.h"
+
+struct BMLogEntry {
+	struct BMLogEntry *next, *prev;
+
+	/* The following GHashes map from an element ID to one of the log
+	 * types above */
+
+	/* Elements that were in the previous entry, but have been
+	 * deleted */
+	GHash *deleted_verts;
+	GHash *deleted_faces;
+	/* Elements that were not in the previous entry, but are in the
+	 * result of this entry */
+	GHash *added_verts;
+	GHash *added_faces;
+
+	/* Vertices whose coordinates, mask value, or hflag have changed */
+	GHash *modified_verts;
+
+	BLI_mempool *pool_verts;
+	BLI_mempool *pool_faces;
+
+	/* This is only needed for dropping BMLogEntries while still in
+	 * dynamic-topology mode, as that should release vert/face IDs
+	 * back to the BMLog but no BMLog pointer is available at that
+	 * time.
+	 *
+	 * This field is not guaranteed to be valid, any use of it should
+	 * check for NULL. */
+	BMLog *log;
+};
+
+struct BMLog {
+	/* Tree of free IDs */
+	struct RangeTreeUInt *unused_ids;
+
+	/* Mapping from unique IDs to vertices and faces
+	 *
+	 * Each vertex and face in the log gets a unique unsigned integer
+	 * assigned. That ID is taken from the set managed by the
+	 * unused_ids range tree.
+	 *
+	 * The ID is needed because element pointers will change as they
+	 * are created and deleted.
+	 */
+	GHash *id_to_elem;
+	GHash *elem_to_id;
+
+	/* All BMLogEntrys, ordered from earliest to most recent */
+	ListBase entries;
+
+	/* The current log entry from entries list
+	 *
+	 * If null, then the original mesh from before any of the log
+	 * entries is current (i.e. there is nothing left to undo.)
+	 *
+	 * If equal to the last entry in the entries list, then all log
+	 * entries have been applied (i.e. there is nothing left to redo.)
+	 */
+	BMLogEntry *current_entry;
+};
+
+typedef struct {
+	float co[3];
+	float mask;
+	char hflag;
+} BMLogVert;
+
+typedef struct {
+	unsigned int v_ids[3];
+} BMLogFace;
+
+/************************* Get/set element IDs ************************/
+
+/* Get the vertex's unique ID from the log */
+static unsigned int bm_log_vert_id_get(BMLog *log, BMVert *v)
+{
+	BLI_assert(BLI_ghash_haskey(log->elem_to_id, v));
+	return GET_INT_FROM_POINTER(BLI_ghash_lookup(log->elem_to_id, v));
+}
+
+/* Set the vertex's unique ID in the log */
+static void bm_log_vert_id_set(BMLog *log, BMVert *v, unsigned int id)
+{
+	void *vid = SET_INT_IN_POINTER(id);
+	
+	BLI_ghash_remove(log->id_to_elem, vid, NULL, NULL);
+	BLI_ghash_insert(log->id_to_elem, vid, v);
+	BLI_ghash_remove(log->elem_to_id, v, NULL, NULL);
+	BLI_ghash_insert(log->elem_to_id, v, vid);
+}
+
+/* Get a vertex from its unique ID */
+static BMVert *bm_log_vert_from_id(BMLog *log, unsigned int id)
+{
+	void *key = SET_INT_IN_POINTER(id);
+	BLI_assert(BLI_ghash_haskey(log->id_to_elem, key));
+	return BLI_ghash_lookup(log->id_to_elem, key);
+}
+
+/* Get the face's unique ID from the log */
+static unsigned int bm_log_face_id_get(BMLog *log, BMFace *f)
+{
+	BLI_assert(BLI_ghash_haskey(log->elem_to_id, f));
+	return GET_INT_FROM_POINTER(BLI_ghash_lookup(log->elem_to_id, f));
+}
+
+/* Set the face's unique ID in the log */
+static void bm_log_face_id_set(BMLog *log, BMFace *f, unsigned int id)
+{
+	void *fid = SET_INT_IN_POINTER(id);
+	
+	BLI_ghash_remove(log->id_to_elem, fid, NULL, NULL);
+	BLI_ghash_insert(log->id_to_elem, fid, f);
+	BLI_ghash_remove(log->elem_to_id, f, NULL, NULL);
+	BLI_ghash_insert(log->elem_to_id, f, fid);
+}
+
+/* Get a face from its unique ID */
+static BMFace *bm_log_face_from_id(BMLog *log, unsigned int id)
+{
+	void *key = SET_INT_IN_POINTER(id);
+	BLI_assert(BLI_ghash_haskey(log->id_to_elem, key));
+	return BLI_ghash_lookup(log->id_to_elem, key);
+}
+
+
+/************************ BMLogVert / BMLogFace ***********************/
+
+/* Get a vertex's paint-mask value
+ *
+ * Returns zero if no paint-mask layer is present */
+static float vert_mask_get(BMesh *bm, BMVert *v)
+{
+	CustomData *cd = &bm->vdata;
+	if (CustomData_has_layer(&bm->vdata, CD_PAINT_MASK)) {
+		float *mask = CustomData_bmesh_get(cd, v->head.data, CD_PAINT_MASK);
+		return *mask;
+	}
+	else {
+		return 0;
+	}
+}
+
+/* Set a vertex's paint-mask value
+ *
+ * Has no effect is no paint-mask layer is present */
+static void vert_mask_set(BMesh *bm, BMVert *v, float new_mask)
+{
+	CustomData *cd = &bm->vdata;
+	if (CustomData_has_layer(cd, CD_PAINT_MASK)) {
+		float *mask = CustomData_bmesh_get(cd, v->head.data, CD_PAINT_MASK);
+		(*mask) = new_mask;
+	}
+}
+
+/* Update a BMLogVert with data from a BMVert */
+static void bm_log_vert_bmvert_copy(BMesh *bm, BMLogVert *lv, BMVert *v)
+{
+	copy_v3_v3(lv->co, v->co);
+	lv->mask = vert_mask_get(bm, v);
+	lv->hflag = v->head.hflag;
+}
+
+/* Allocate and initialize a BMLogVert */
+static BMLogVert *bm_log_vert_alloc(BMesh *bm, BMLog *log, BMVert *v)
+{
+	BMLogEntry *entry = log->current_entry;
+	BMLogVert *lv = BLI_mempool_alloc(entry->pool_verts);
+
+	bm_log_vert_bmvert_copy(bm, lv, v);
+
+	return lv;
+}
+
+/* Allocate and initialize a BMLogFace */
+static BMLogFace *bm_log_face_alloc(BMLog *log, BMFace *f)
+{
+	BMLogEntry *entry = log->current_entry;
+	BMLogFace *lf = BLI_mempool_alloc(entry->pool_faces);
+	BMVert *v[3];
+
+	BLI_assert(f->len == 3);
+
+	BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3);
+
+	lf->v_ids[0] = bm_log_vert_id_get(log, v[0]);
+	lf->v_ids[1] = bm_log_vert_id_get(log, v[1]);
+	lf->v_ids[2] = bm_log_vert_id_get(log, v[2]);
+
+	return lf;
+}
+
+
+/************************ Helpers for undo/redo ***********************/
+
+static void bm_log_verts_unmake(BMesh *bm, BMLog *log, GHash *verts)
+{
+	GHashIterator gh_iter;
+	GHASH_ITER (gh_iter, verts) {
+		void *key = BLI_ghashIterator_getKey(&gh_iter);
+		BMLogVert *lv = BLI_ghashIterator_getValue(&gh_iter);
+		unsigned int id = GET_INT_FROM_POINTER(key);
+		BMVert *v = bm_log_vert_from_id(log, id);
+
+		/* Ensure the log has the final values of the vertex before
+		 * deleting it */
+		bm_log_vert_bmvert_copy(bm, lv, v);
+
+		BM_vert_kill(bm, v);
+	}
+}
+
+static void bm_log_faces_unmake(BMesh *bm, BMLog *log, GHash *faces)
+{
+	GHashIterator gh_iter;
+	GHASH_ITER (gh_iter, faces) {
+		void *key = BLI_ghashIterator_getKey(&gh_iter);
+		unsigned int id = GET_INT_FROM_POINTER(key);
+		BMFace *f = bm_log_face_from_id(log, id);
+
+		BM_face_kill(bm, f);
+	}
+}
+
+static void bm_log_verts_restore(BMesh *bm, BMLog *log, GHash *verts)
+{
+	GHashIterator gh_iter;
+	GHASH_ITER (gh_iter, verts) {
+		void *key = BLI_ghashIterator_getKey(&gh_iter);
+		BMLogVert *lv = BLI_ghashIterator_getValue(&gh_iter);
+		BMVert *v = BM_vert_create(bm, lv->co, NULL, 0);
+		v->head.hflag = lv->hflag;
+		vert_mask_set(bm, v, lv->mask);
+		bm_log_vert_id_set(log, v, GET_INT_FROM_POINTER(key));
+	}
+}
+
+static void bm_log_faces_restore(BMesh *bm, BMLog *log, GHash *faces)
+{
+	GHashIterator gh_iter;
+	GHASH_ITER (gh_iter, faces) {
+		void *key = BLI_ghashIterator_getKey(&gh_iter);
+		BMLogFace *lf = BLI_ghashIterator_getValue(&gh_iter);
+		BMVert *v[3] = {bm_log_vert_from_id(log, lf->v_ids[0]),
+						bm_log_vert_from_id(log, lf->v_ids[1]),
+						bm_log_vert_from_id(log, lf->v_ids[2])};
+		BMFace *f;
+
+		f = BM_face_create_quad_tri_v(bm, v, 3, NULL, FALSE);
+		bm_log_face_id_set(log, f, GET_INT_FROM_POINTER(key));
+	}
+}
+
+static void bm_log_vert_values_swap(BMesh *bm, BMLog *log, GHash *verts)
+{
+	GHashIterator gh_iter;
+	GHASH_ITER (gh_iter, verts) {
+		void *key = BLI_ghashIterator_getKey(&gh_iter);
+		BMLogVert *lv = BLI_ghashIterator_getValue(&gh_iter);
+		unsigned int id = GET_INT_FROM_POINTER(key);
+		BMVert *v = bm_log_vert_from_id(log, id);
+		float mask;
+
+		swap_v3_v3(v->co, lv->co);
+		SWAP(char, v->head.hflag, lv->hflag);
+		mask = lv->mask;
+		lv->mask = vert_mask_get(bm, v);
+		vert_mask_set(bm, v, mask);
+	}
+}
+
+
+/**********************************************************************/
+
+/* Assign unique IDs to all vertices and faces already in the BMesh */
+static void bm_log_assign_ids(BMesh *bm, BMLog *log)
+{
+	BMIter iter;
+	BMVert *v;
+	BMFace *f;
+
+	/* Generate vertex IDs */
+	BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+		unsigned int id = range_tree_uint_take_any(log->unused_ids);
+		bm_log_vert_id_set(log, v, id);
+	}
+
+	/* Generate face IDs */
+	BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+		unsigned int id = range_tree_uint_take_any(log->unused_ids);
+		bm_log_face_id_set(log, f, id);
+	}
+}
+
+/* Allocate an empty log entry */
+static BMLogEntry *bm_log_entry_create(void)
+{
+	BMLogEntry *entry = MEM_callocN(sizeof(BMLogEntry), AT);
+
+	entry->deleted_verts = BLI_ghash_ptr_new(AT);
+	entry->deleted_faces = BLI_ghash_ptr_new(AT);
+	entry->added_verts = BLI_ghash_ptr_new(AT);
+	entry->added_faces = BLI_ghash_ptr_new(AT);
+	entry->modified_verts = BLI_ghash_ptr_new(AT);
+
+	entry->pool_verts = BLI_mempool_create(sizeof(BMLogVert), 1, 64, 0);
+	entry->pool_faces = BLI_mempool_create(sizeof(BMLogFace), 1, 64, 0);
+
+	return entry;
+}
+
+/* Free the data in a log entry
+ *
+ * Note: does not free the log entry itself */
+static void bm_log_entry_free(BMLogEntry *entry)
+{
+	BLI_ghash_free(entry->deleted_verts, NULL, NULL);
+	BLI_ghash_free(entry->deleted_faces, NULL, NULL);
+	BLI_ghash_free(entry->added_verts, NULL, NULL);
+	BLI_ghash_free(entry->added_faces, NULL, NULL);
+	BLI_ghash_free(entry->modified_verts, NULL, NULL);
+
+	BLI_mempool_destroy(entry->pool_verts);
+	BLI_mempool_destroy(entry->pool_faces);
+}
+
+static void bm_log_id_ghash_retake(RangeTreeUInt *unused_ids, GHash *id_ghash)
+{
+	GHashIterator gh_iter;
+
+	GHASH_ITER (gh_iter, id_ghash) {
+		void *key = BLI_ghashIterator_getKey(&gh_iter);
+		unsigned int id = GET_INT_FROM_POINTER(key);
+
+		if (range_tree_uint_has(unused_ids, id)) {
+			range_tree_uint_take(unused_ids, id);
+		}
+	}
+}
+
+static int uint_compare(const void *a_v, const void *b_v)
+{
+	const unsigned int *a = a_v;
+	const unsigned int *b = b_v;
+	return (*a) < (*b);
+}
+
+/* Remap IDs to contiguous indices
+ *
+ * E.g. if the vertex IDs are (4, 1, 10, 3), the mapping will be:
+ *    4 -> 2
+ *    1 -> 0
+ *   10 -> 3
+ *    3 -> 1
+ */
+static GHash *bm_log_compress_ids_to_indices(unsigned int *ids, int totid)
+{
+	GHash *map = BLI_ghash_int_new(AT);
+	int i;
+
+	qsort(ids, totid, sizeof(*ids), uint_compare);
+
+	for (i = 0; i < totid; i++) {
+		void *key = SET_INT_IN_POINTER(ids[i]);
+		void *val = SET_INT_IN_POINTER(i);
+		BLI_ghash_insert(map, key, val);
+	}
+
+	return map;
+}
+
+/* Release all ID keys in id_ghash */
+static void bm_log_id_ghash_release(BMLog *log, GHash *id_ghash)
+{
+	GHashIterator gh_iter;
+
+	GHASH_ITER (gh_iter, id_ghash) {
+		void *key = BLI_ghashIterator_getKey(&gh_iter);
+		unsigned int id = GET_INT_FROM_POINTER(key);
+		range_tree_uint_release(log->unused_ids, id);
+	}
+}
+
+/***************************** Public API *****************************/
+
+/* Allocate, initialize, and assign a new BMLog */
+BMLog *BM_log_create(BMesh *bm)
+{
+	BMLog *log = MEM_callocN(sizeof(*log), AT);
+
+	log->unused_ids = range_tree_uint_alloc(0, (unsigned)-1);
+	log->id_to_elem = BLI_ghash_ptr_new(AT);
+	log->elem_to_id = BLI_ghash_ptr_new(AT);
+
+	/* Assign IDs to all existing vertices and faces */
+	bm_log_assign_ids(bm, log);
+
+	return log;
+}
+
+/* Allocate and initialize a new BMLog using existing BMLogEntries
+ *
+ * The 'entry' should be the last entry in the BMLog. Its prev pointer
+ * will be followed back to find the first entry.
+ *
+ * The unused IDs field of the log will be initialized by taking all
+ * keys from all GHashes in the log entry.
+ */
+BMLog *BM_log_from_existing_entries_create(BMesh *bm, BMLogEntry *entry)
+{
+	BMLog *log = BM_log_create(bm);
+
+	if (entry->prev)
+		log->current_entry = entry;
+	else
+		log->current_entry = NULL;
+
+	/* Let BMLog manage the entry list again */
+	log->entries.first = log->entries.last = entry;
+	if (entry) {
+		while (entry->prev) {
+			entry = entry->prev;
+			log->entries.first = entry;
+		}
+		entry = log->entries.last;
+		while (entry->next) {
+			entry = entry->next;
+			log->entries.last = entry;
+		}
+	}
+
+	for (entry = log->entries.first; entry; entry = entry->next) {
+		entry->log = log;
+
+		/* Take all used IDs */
+		bm_log_id_ghash_retake(log->unused_ids, entry->deleted_verts);
+		bm_log_id_ghash_retake(log->unused_ids, entry->deleted_faces);
+		bm_log_id_ghash_retake(log->unused_ids, entry->added_verts);
+		bm_log_id_ghash_retake(log->unused_ids, entry->added_faces);
+		bm_log_id_ghash_retake(log->unused_ids, entry->modified_verts);
+	}
+
+	return log;
+}
+
+/* Free all the data in a BMLog including the log itself */
+void BM_log_free(BMLog *log)
+{
+	BMLogEntry *entry;
+
+	if (log->unused_ids)
+		range_tree_uint_free(log->unused_ids);
+
+	if (log->id_to_elem)
+		BLI_ghash_free(log->id_to_elem, NULL, NULL);
+
+	if (log->elem_to_id)
+		BLI_ghash_free(log->elem_to_id, NULL, NULL);
+
+	/* Clear the BMLog references within each entry, but do not free
+	 * the entries themselves */
+	for (entry = log->entries.first; entry; entry = entry->next)
+		entry->log = NULL;
+
+	MEM_freeN(log);
+}
+
+/* Get the number of log entries */
+int BM_log_length(const BMLog *log)
+{
+	return BLI_countlist(&log->entries);
+}
+
+/* Apply a consistent ordering to BMesh vertices */
+void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log)
+{
+	void *varr;
+	void *farr;
+
+	GHash *id_to_idx;
+
+	BMIter bm_iter;
+	BMVert *v;
+	BMFace *f;
+
+	int i;
+
+	/* Put all vertex IDs into an array */
+	i = 0;
+	varr = MEM_mallocN(sizeof(int) * bm->totvert, AT);
+	BM_ITER_MESH (v, &bm_iter, bm, BM_VERTS_OF_MESH) {
+		((unsigned int*)varr)[i++] = bm_log_vert_id_get(log, v);
+	}
+
+	/* Put all face IDs into an array */
+	i = 0;
+	farr = MEM_mallocN(sizeof(int) * bm->totface, AT);
+	BM_ITER_MESH (f, &bm_iter, bm, BM_FACES_OF_MESH) {
+		((unsigned int*)farr)[i++] = bm_log_face_id_get(log, f);
+	}
+
+	/* Create BMVert index remap array */
+	id_to_idx = bm_log_compress_ids_to_indices(varr, bm->totvert);
+	i = 0;
+	BM_ITER_MESH (v, &bm_iter, bm, BM_VERTS_OF_MESH) {
+		const unsigned id = bm_log_vert_id_get(log, v);
+		const void *key = SET_INT_IN_POINTER(id);
+		const void *val = BLI_ghash_lookup(id_to_idx, key);
+		((int*)varr)[i++] = GET_INT_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, bm->totface);
+	i = 0;
+	BM_ITER_MESH (f, &bm_iter, bm, BM_FACES_OF_MESH) {
+		const unsigned id = bm_log_face_id_get(log, f);
+		const void *key = SET_INT_IN_POINTER(id);
+		const void *val = BLI_ghash_lookup(id_to_idx, key);
+		((int*)farr)[i++] = GET_INT_FROM_POINTER(val);
+	}
+	BLI_ghash_free(id_to_idx, NULL, NULL);
+
+	BM_mesh_remap(bm, varr, NULL, farr);
+
+	MEM_freeN(varr);
+	MEM_freeN(farr);
+}
+
+/* Start a new log entry and update the log entry list
+ *
+ * If the log entry list is empty, or if the current log entry is the
+ * last entry, the new entry is simply appended to the end.
+ *
+ * Otherwise, the new entry is added after the current entry and all
+ * following entries are deleted.
+ *
+ * In either case, the new entry is set as the current log entry.
+ */
+BMLogEntry *BM_log_entry_add(BMLog *log)
+{
+	BMLogEntry *entry, *next;
+
+	/* Delete any entries after the current one */
+	entry = log->current_entry;
+	if (entry) {
+		for (entry = entry->next; entry; entry = next) {
+			next = entry->next;
+			bm_log_entry_free(entry);
+			BLI_freelinkN(&log->entries, entry);
+		}
+	}
+
+	/* Create and append the new entry */
+	entry = bm_log_entry_create();
+	BLI_addtail(&log->entries, entry);
+	entry->log = log;
+	log->current_entry = entry;
+
+	return entry;
+}
+
+/* Remove an entry from the log
+ *
+ * Uses entry->log as the log. If the log is NULL, the entry will be
+ * free'd but not removed from any list, nor shall its IDs be
+ * released.
+ *
+ * This operation is only valid on the first and last entries in the
+ * log. Deleting from the middle will assert.
+ */
+void BM_log_entry_drop(BMLogEntry *entry)
+{
+	BMLog *log = entry->log;
+
+	if (!log) {
+		/* Unlink */
+		BLI_assert(!(entry->prev && entry->next));
+		if (entry->prev)
+			entry->prev->next = NULL;
+		else if (entry->next)
+			entry->next->prev = NULL;
+
+		bm_log_entry_free(entry);
+		MEM_freeN(entry);
+		return;
+	}
+
+	if (!entry->prev) {
+		/* Release IDs of elements that are deleted by this
+		 * entry. Since the entry is at the beginning of the undo
+		 * stack, and it's being deleted, those elements can never be
+		 * restored. Their IDs can go back into the pool. */
+		bm_log_id_ghash_release(log, entry->deleted_faces);
+		bm_log_id_ghash_release(log, entry->deleted_verts);
+	}
+	else if (!entry->next) {
+		/* Release IDs of elements that are added by this entry. Since
+		 * the entry is at the end of the undo stack, and it's being
+		 * deleted, those elements can never be restored. Their IDs
+		 * can go back into the pool. */
+		bm_log_id_ghash_release(log, entry->added_faces);
+		bm_log_id_ghash_release(log, entry->added_verts);
+	}
+	else {
+		BLI_assert(!"Cannot drop BMLogEntry from middle");
+	}
+
+	if (log->current_entry == entry)
+		log->current_entry = entry->prev;
+
+	bm_log_entry_free(entry);
+	BLI_freelinkN(&log->entries, entry);
+}
+
+/* Undo one BMLogEntry
+ *
+ * Has no effect if there's nothing left to undo */
+void BM_log_undo(BMesh *bm, BMLog *log)
+{
+	BMLogEntry *entry = log->current_entry;
+
+	if (entry) {
+		log->current_entry = entry->prev;
+
+		/* Delete added faces and verts */
+		bm_log_faces_unmake(bm, log, entry->added_faces);
+		bm_log_verts_unmake(bm, log, entry->added_verts);
+
+		/* Restore deleted verts and faces */
+		bm_log_verts_restore(bm, log, entry->deleted_verts);
+		bm_log_faces_restore(bm, log, entry->deleted_faces);
+
+		/* Restore vertex coordinates, mask, and hflag */
+		bm_log_vert_values_swap(bm, log, entry->modified_verts);
+	}
+}
+
+/* Redo one BMLogEntry
+ *
+ * Has no effect if there's nothing left to redo */
+void BM_log_redo(BMesh *bm, BMLog *log)
+{
+	BMLogEntry *entry = log->current_entry;
+
+	if (!entry) {
+		/* Currently at the beginning of the undo stack, move to first entry */
+		entry = log->entries.first;
+	}
+	else if (entry && entry->next) {
+		/* Move to next undo entry */
+		entry = entry->next;
+	}
+	else {
+		/* Currently at the end of the undo stack, nothing left to redo */
+		return;
+	}
+
+	log->current_entry = entry;
+
+	if (entry) {
+		/* Re-delete previously deleted faces and verts */
+		bm_log_faces_unmake(bm, log, entry->deleted_faces);
+		bm_log_verts_unmake(bm, log, entry->deleted_verts);
+
+		/* Restore previously added verts and faces */
+		bm_log_verts_restore(bm, log, entry->added_verts);
+		bm_log_faces_restore(bm, log, entry->added_faces);
+
+		/* Restore vertex coordinates, mask, and hflag */
+		bm_log_vert_values_swap(bm, log, entry->modified_verts);
+	}
+}
+
+/* Log a vertex before it is modified
+ *
+ * Before modifying vertex coordinates, masks, or hflags, call this
+ * function to log it's current values. This is better than logging
+ * after the coordinates have been modified, because only those
+ * vertices that are modified need to have their original values
+ * stored.
+ *
+ * Handles two separate cases:
+ *
+ * If the vertex was added in the current log entry, update the
+ * vertex in the map of added vertices.
+ *
+ * If the vertex already existed prior to the current log entry, a
+ * seperate key/value map of modified vertices is used (using the
+ * vertex's ID as the key). The values stored in that case are
+ * the vertex's original state so that an undo can restore the
+ * previous state.
+ *
+ * On undo, the current vertex state will be swapped with the stored
+ * state so that a subsequent redo operation will restore the newer
+ * vertex state.
+ */
+void BM_log_vert_before_modified(BMesh *bm, BMLog *log, BMVert *v)
+{
+	BMLogEntry *entry = log->current_entry;
+	BMLogVert *lv;
+	unsigned int v_id = bm_log_vert_id_get(log, v);
+	void *key = SET_INT_IN_POINTER(v_id);
+
+	/* Find or create the BMLogVert entry */
+	if ((lv = BLI_ghash_lookup(entry->added_verts, key))) {
+		bm_log_vert_bmvert_copy(bm, lv, v);
+	}
+	else if (!BLI_ghash_haskey(entry->modified_verts, key)) {
+		lv = bm_log_vert_alloc(bm, log, v);
+		BLI_ghash_insert(entry->modified_verts, key, lv);
+	}
+}
+
+/* Log a new vertex as added to the BMesh
+ *
+ * The new vertex gets a unique ID assigned. It is then added to a map
+ * of added vertices, with the key being its ID and the value
+ * containing everything needed to reconstruct that vertex.
+ */
+void BM_log_vert_added(BMesh *bm, BMLog *log, BMVert *v)
+{
+	BMLogVert *lv;
+	unsigned int v_id = range_tree_uint_take_any(log->unused_ids);
+	void *key = SET_INT_IN_POINTER(v_id);
+
+	bm_log_vert_id_set(log, v, v_id);
+	lv = bm_log_vert_alloc(bm, log, v);
+	BLI_ghash_insert(log->current_entry->added_verts, key, lv);
+}
+
+/* Log a new face as added to the BMesh
+ *
+ * The new face gets a unique ID assigned. It is then added to a map
+ * of added faces, with the key being its ID and the value containing
+ * everything needed to reconstruct that face.
+ */
+void BM_log_face_added(BMLog *log, BMFace *f)
+{
+	BMLogFace *lf;
+	unsigned int f_id = range_tree_uint_take_any(log->unused_ids);
+	void *key = SET_INT_IN_POINTER(f_id);
+
+	/* Only triangles are supported for now */
+	BLI_assert(f->len == 3);
+
+	bm_log_face_id_set(log, f, f_id);
+	lf = bm_log_face_alloc(log, f);
+	BLI_ghash_insert(log->current_entry->added_faces, key, lf);
+}
+
+/* Log a vertex as removed from the BMesh
+ *
+ * A couple things can happen here:
+ * 
+ * If the vertex was added as part of the current log entry, then it's
+ * deleted and forgotten about entirely. Its unique ID is returned to
+ * the unused pool.
+ *
+ * If the vertex was already part of the BMesh before the current log
+ * entry, it is added to a map of deleted vertices, with the key being
+ * its ID and the value containing everything needed to reconstruct
+ * that vertex.
+ *
+ * If there's a move record for the vertex, that's used as the
+ * vertices original location, then the move record is deleted.
+ */
+void BM_log_vert_removed(BMesh *bm, BMLog *log, BMVert *v)
+{
+	BMLogEntry *entry = log->current_entry;
+	unsigned int v_id = bm_log_vert_id_get(log, v);
+	void *key = SET_INT_IN_POINTER(v_id);
+
+	if (BLI_ghash_lookup(entry->added_verts, key)) {
+		BLI_ghash_remove(entry->added_verts, key, NULL, NULL);
+		range_tree_uint_release(log->unused_ids, v_id);
+	}
+	else {
+		BMLogVert *lv, *lv_mod;
+
+		lv = bm_log_vert_alloc(bm, log, v);
+		BLI_ghash_insert(entry->deleted_verts, key, lv);
+
+		/* If the vertex was modified before deletion, ensure that the
+		 * original vertex values are stored */
+		if ((lv_mod = BLI_ghash_lookup(entry->modified_verts, key))) {
+			(*lv) = (*lv_mod);
+			BLI_ghash_remove(entry->modified_verts, key, NULL, NULL);
+		}
+	}
+}
+
+/* Log a face as removed from the BMesh
+ *
+ * A couple things can happen here:
+ * 
+ * If the face was added as part of the current log entry, then it's
+ * deleted and forgotten about entirely. Its unique ID is returned to
+ * the unused pool.
+ *
+ * If the face was already part of the BMesh before the current log
+ * entry, it is added to a map of deleted faces, with the key being
+ * its ID and the value containing everything needed to reconstruct
+ * that face.
+ */
+void BM_log_face_removed(BMLog *log, BMFace *f)
+{
+	BMLogEntry *entry = log->current_entry;
+	unsigned int f_id = bm_log_face_id_get(log, f);
+	void *key = SET_INT_IN_POINTER(f_id);
+
+	if (BLI_ghash_lookup(entry->added_faces, key)) {
+		BLI_ghash_remove(entry->added_faces, key, NULL, NULL);
+		range_tree_uint_release(log->unused_ids, f_id);
+	}
+	else {
+		BMLogFace *lf;
+
+		lf = bm_log_face_alloc(log, f);
+		BLI_ghash_insert(entry->deleted_faces, key, lf);
+	}
+}
+
+/* Log all vertices/faces in the BMesh as added */
+void BM_log_all_added(BMesh *bm, BMLog *log)
+{
+	BMIter bm_iter;
+	BMVert *v;
+	BMFace *f;
+
+	/* Log all vertices as newly created */
+	BM_ITER_MESH (v, &bm_iter, bm, BM_VERTS_OF_MESH) {
+		BM_log_vert_added(bm, log, v);
+	}
+
+	/* Log all faces as newly created */
+	BM_ITER_MESH (f, &bm_iter, bm, BM_FACES_OF_MESH) {
+		BM_log_face_added(log, f);
+	}
+}
+
+/* Log all vertices/faces in the BMesh as removed */
+void BM_log_before_all_removed(BMesh *bm, BMLog *log)
+{
+	BMIter bm_iter;
+	BMVert *v;
+	BMFace *f;
+
+	/* Log deletion of all faces */
+	BM_ITER_MESH (f, &bm_iter, bm, BM_FACES_OF_MESH) {
+		BM_log_face_removed(log, f);
+	}
+
+	/* Log deletion of all vertices */
+	BM_ITER_MESH (v, &bm_iter, bm, BM_VERTS_OF_MESH) {
+		BM_log_vert_removed(bm, log, v);
+	}
+}
+
+/* Get the logged coordinates of a vertex
+ *
+ * Does not modify the log or the vertex */
+const float *BM_log_original_vert_co(BMLog *log, BMVert *v)
+{
+	BMLogEntry *entry = log->current_entry;
+	const BMLogVert *lv;
+	unsigned v_id = bm_log_vert_id_get(log, v);
+	void *key = SET_INT_IN_POINTER(v_id);
+
+	BLI_assert(entry);
+
+	BLI_assert(BLI_ghash_haskey(entry->modified_verts, key));
+
+	lv = BLI_ghash_lookup(entry->modified_verts, key);
+	return lv->co;
+}
+
+/* Get the logged mask of a vertex
+ *
+ * Does not modify the log or the vertex */
+float BM_log_original_mask(BMLog *log, BMVert *v)
+{
+	BMLogEntry *entry = log->current_entry;
+	const BMLogVert *lv;
+	unsigned v_id = bm_log_vert_id_get(log, v);
+	void *key = SET_INT_IN_POINTER(v_id);
+
+	BLI_assert(entry);
+
+	BLI_assert(BLI_ghash_haskey(entry->modified_verts, key));
+
+	lv = BLI_ghash_lookup(entry->modified_verts, key);
+	return lv->mask;
+}
+
+/************************ Debugging and Testing ***********************/
+
+/* For internal use only (unit testing) */
+BMLogEntry *BM_log_current_entry(BMLog *log)
+{
+	return log->current_entry;
+}
+
+/* For internal use only (unit testing) */
+RangeTreeUInt *BM_log_unused_ids(BMLog *log)
+{
+	return log->unused_ids;
+}
+
+#if 0
+/* Print the list of entries, marking the current one
+ *
+ * Keep around for debugging */
+void bm_log_print(const BMLog *log, const char *description)
+{
+	const BMLogEntry *entry;
+	const char *current = " <-- current";
+	int i;
+
+	printf("%s:\n", description);
+	printf("    % 2d: [ initial ]%s\n", 0,
+		   (!log->current_entry) ? current : "");
+	for (entry = log->entries.first, i = 1; entry; entry = entry->next, i++) {
+		printf("    % 2d: [%p]%s\n", i, entry,
+			   (entry == log->current_entry) ? current : "");
+	}
+}
+#endif
diff --git a/source/blender/bmesh/intern/bmesh_log.h b/source/blender/bmesh/intern/bmesh_log.h
new file mode 100644
index 00000000000..958ff340b43
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_log.h
@@ -0,0 +1,102 @@
+/*
+ * ***** 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 __BMESH_LOG_H__
+#define __BMESH_LOG_H__
+
+/* The BMLog is an interface for storing undo/redo steps as a BMesh is
+ * modified. It only stores changes to the BMesh, not full copies.
+ *
+ * Currently it supports the following types of changes:
+ * 
+ * - Adding and removing vertices
+ * - Adding and removing faces
+ * - Moving vertices
+ * - Setting vertex paint-mask values
+ * - Setting vertex hflags
+ */
+
+struct BMFace;
+struct BMVert;
+struct BMesh;
+struct RangeTreeUInt;
+
+typedef struct BMLog BMLog;
+typedef struct BMLogEntry BMLogEntry;
+
+/* Allocate and initialize a new BMLog */
+BMLog *BM_log_create(BMesh *bm);
+
+/* Allocate and initialize a new BMLog using existing BMLogEntries */
+BMLog *BM_log_from_existing_entries_create(BMesh *bm, BMLogEntry *entry);
+
+/* Free all the data in a BMLog including the log itself */
+void BM_log_free(BMLog *log);
+
+/* Get the number of log entries */
+int BM_log_length(const BMLog *log);
+
+/* Apply a consistent ordering to BMesh vertices and faces */
+void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log);
+
+/* Start a new log entry and update the log entry list */
+BMLogEntry *BM_log_entry_add(BMLog *log);
+
+/* Remove an entry from the log */
+void BM_log_entry_drop(BMLogEntry *entry);
+
+/* Undo one BMLogEntry */
+void BM_log_undo(BMesh *bm, BMLog *log);
+
+/* Redo one BMLogEntry */
+void BM_log_redo(BMesh *bm, BMLog *log);
+
+/* Log a vertex before it is modified */
+void BM_log_vert_before_modified(BMesh *bm, BMLog *log, struct BMVert *v);
+
+/* Log a new vertex as added to the BMesh */
+void BM_log_vert_added(BMesh *bm, BMLog *log, struct BMVert *v);
+
+/* Log a new face as added to the BMesh */
+void BM_log_face_added(BMLog *log, struct BMFace *f);
+
+/* Log a vertex as removed from the BMesh */
+void BM_log_vert_removed(BMesh *bm, BMLog *log, struct BMVert *v);
+
+/* Log a face as removed from the BMesh */
+void BM_log_face_removed(BMLog *log, struct BMFace *f);
+
+/* Log all vertices/faces in the BMesh as added */
+void BM_log_all_added(BMesh *bm, BMLog *log);
+
+/* Log all vertices/faces in the BMesh as removed */
+void BM_log_before_all_removed(BMesh *bm, BMLog *log);
+
+/* Get the logged coordinates of a vertex */
+const float *BM_log_original_vert_co(BMLog *log, BMVert *v);
+
+/* Get the logged mask of a vertex */
+float BM_log_original_mask(BMLog *log, BMVert *v);
+
+/* For internal use only (unit testing) */
+BMLogEntry *BM_log_current_entry(BMLog *log);
+struct RangeTreeUInt *BM_log_unused_ids(BMLog *log);
+
+#endif
-- 
cgit v1.2.3


From d383c324131f6b295512403c367dc3b932a1de90 Mon Sep 17 00:00:00 2001
From: Nicholas Bishop 
Date: Sun, 30 Dec 2012 18:24:54 +0000
Subject: Add GPU_buffers support for drawing dynamic topology nodes

The GPU interface for PBVH drawing gets a new pair of build/update
buffers functions for drawing BMFaces and BMVerts.

TODO: the diffuse color is hardcoded to 0.8 gray rather than using
material color.

TODO: only VBO drawing is implemented, no immediate mode.
---
 source/blender/gpu/CMakeLists.txt       |   1 +
 source/blender/gpu/GPU_buffers.h        |  11 ++
 source/blender/gpu/SConscript           |   2 +-
 source/blender/gpu/intern/gpu_buffers.c | 252 ++++++++++++++++++++++++++++++++
 4 files changed, 265 insertions(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 9ce42d9e0bb..6abc41759e7 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -28,6 +28,7 @@ set(INC
 	../blenkernel
 	../blenlib
 	../blenloader
+	../bmesh
 	../imbuf
 	../makesdna
 	../makesrna
diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h
index 36fbd818f11..70ca44c2a3a 100644
--- a/source/blender/gpu/GPU_buffers.h
+++ b/source/blender/gpu/GPU_buffers.h
@@ -39,12 +39,15 @@
 #define DEBUG_VBO(X)
 #endif
 
+struct BMesh;
 struct CCGElem;
 struct CCGKey;
 struct CustomData;
 struct DMFlagMat;
 struct DerivedMesh;
+struct GHash;
 struct GPUVertPointLink;
+struct PBVH;
 
 typedef struct GPUBuffer {
 	int size;	/* in bytes */
@@ -168,6 +171,14 @@ void GPU_update_mesh_buffers(GPU_Buffers *buffers, MVert *mvert,
 GPU_Buffers *GPU_build_grid_buffers(int *grid_indices, int totgrid,
                                     unsigned int **grid_hidden, int gridsize);
 
+GPU_Buffers *GPU_build_bmesh_buffers(int smooth_shading);
+
+void GPU_update_bmesh_buffers(GPU_Buffers *buffers,
+							  struct BMesh *bm,
+							  struct GHash *bm_faces,
+							  struct GHash *bm_unique_verts,
+							  struct GHash *bm_other_verts);
+
 void GPU_update_grid_buffers(GPU_Buffers *buffers, struct CCGElem **grids,
                              const struct DMFlagMat *grid_flag_mats,
                              int *grid_indices, int totgrid, const struct CCGKey *key,
diff --git a/source/blender/gpu/SConscript b/source/blender/gpu/SConscript
index aeb7edc2c56..f7db3dfeaa0 100644
--- a/source/blender/gpu/SConscript
+++ b/source/blender/gpu/SConscript
@@ -33,7 +33,7 @@ sources += env.Glob('shaders/*.c')
 defs = [ 'GLEW_STATIC' ]
 
 incs = '../blenlib ../blenkernel ../makesdna ../makesrna ../include ../blenloader ../nodes ../nodes/intern'
-incs += ' #/extern/glew/include #intern/guardedalloc #intern/smoke/extern ../imbuf .'
+incs += ' #/extern/glew/include #intern/guardedalloc #intern/smoke/extern ../imbuf ../bmesh .'
 
 if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
     incs += ' ' + env['BF_PTHREADS_INC']
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index daf97c4841f..ba090137118 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -57,6 +57,8 @@
 #include "GPU_buffers.h"
 #include "GPU_draw.h"
 
+#include "bmesh.h"
+
 typedef enum {
 	GPU_BUFFER_VERTEX_STATE = 1,
 	GPU_BUFFER_NORMAL_STATE = 2,
@@ -1269,6 +1271,8 @@ struct GPU_Buffers {
 	int totgrid;
 	int has_hidden;
 
+	int use_bmesh;
+
 	unsigned int tot_tri, tot_quad;
 
 	/* The PBVH ensures that either all faces in the node are
@@ -1862,6 +1866,254 @@ GPU_Buffers *GPU_build_grid_buffers(int *grid_indices, int totgrid,
 
 #undef FILL_QUAD_BUFFER
 
+/* Output a BMVert into a VertexBufferFormat array
+ *
+ * The vertex is skipped if hidden, otherwise the output goes into
+ * index '*v_index' in the 'vert_data' array and '*v_index' is
+ * incremented.
+ */
+static void gpu_bmesh_vert_to_buffer_copy(BMVert *v, BMesh *bm,
+										  VertexBufferFormat *vert_data,
+										  int *v_index,
+										  const float fno[3],
+										  const float *fmask)
+{
+	VertexBufferFormat *vd = &vert_data[*v_index];
+	float *mask;
+
+	if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
+		/* TODO: should use material color */
+		float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f};
+
+		/* Set coord, normal, and mask */
+		copy_v3_v3(vd->co, v->co);
+		normal_float_to_short_v3(vd->no, fno ? fno : v->no);
+		mask = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_PAINT_MASK);
+		gpu_color_from_mask_copy(fmask ? *fmask : *mask,
+								 diffuse_color,
+								 vd->color);
+		
+
+		/* Assign index for use in the triangle index buffer */
+		BM_elem_index_set(v, (*v_index)); /* set_dirty! */
+
+		(*v_index)++;
+	}
+}
+
+/* Return the total number of vertices that don't have BM_ELEM_HIDDEN set */
+static int gpu_bmesh_vert_visible_count(GHash *bm_unique_verts,
+										GHash *bm_other_verts)
+{
+	GHashIterator gh_iter;
+	int totvert = 0;
+
+	GHASH_ITER (gh_iter, bm_unique_verts) {
+		BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+		if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN))
+			totvert++;
+	}
+	GHASH_ITER (gh_iter, bm_other_verts) {
+		BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+		if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN))
+			totvert++;
+	}
+
+	return totvert;
+}
+
+/* Return TRUE if all vertices in the face are visible, FALSE otherwise */
+static int gpu_bmesh_face_visible(BMFace *f)
+{
+	BMIter bm_iter;
+	BMVert *v;
+
+	BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) {
+		if (BM_elem_flag_test(v, BM_ELEM_HIDDEN))
+			return FALSE;
+	}
+
+	return TRUE;
+}
+
+/* Return the total number of visible faces */
+static int gpu_bmesh_face_visible_count(GHash *bm_faces)
+{
+	GHashIterator gh_iter;
+	int totface = 0;
+
+	GHASH_ITER (gh_iter, bm_faces) {
+		BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+
+		if (gpu_bmesh_face_visible(f))
+			totface++;
+	}
+
+	return totface;
+}
+
+/* Creates a vertex buffer (coordinate, normal, color) and, if smooth
+   shading, an element index buffer. */
+void GPU_update_bmesh_buffers(GPU_Buffers *buffers,
+							  BMesh *bm,
+							  GHash *bm_faces,
+							  GHash *bm_unique_verts,
+							  GHash *bm_other_verts)
+{
+	VertexBufferFormat *vert_data;
+	void *tri_data;
+	int tottri, totvert, maxvert = 0;
+
+	if (!buffers->vert_buf || (buffers->smooth && !buffers->index_buf))
+		return;
+
+	/* Count visible triangles */
+	tottri = gpu_bmesh_face_visible_count(bm_faces);
+
+	if (buffers->smooth) {
+		/* Count visible vertices */
+		totvert = gpu_bmesh_vert_visible_count(bm_unique_verts, bm_other_verts);
+	}
+	else
+		totvert = tottri * 3;
+
+	/* Initialize vertex buffer */
+	glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf);
+	glBufferDataARB(GL_ARRAY_BUFFER_ARB,
+					sizeof(VertexBufferFormat) * totvert,
+					NULL, GL_STATIC_DRAW_ARB);
+
+	/* Fill vertex buffer */
+	vert_data = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+	if (vert_data) {
+		GHashIterator gh_iter;
+		int v_index = 0;
+
+		if (buffers->smooth) {
+			/* Vertices get an index assigned for use in the triangle
+			   index buffer */
+			bm->elem_index_dirty |= BM_VERT;
+
+			GHASH_ITER (gh_iter, bm_unique_verts) {
+				gpu_bmesh_vert_to_buffer_copy(BLI_ghashIterator_getKey(&gh_iter),
+											  bm, vert_data, &v_index, NULL, NULL);
+			}
+
+			GHASH_ITER (gh_iter, bm_other_verts) {
+				gpu_bmesh_vert_to_buffer_copy(BLI_ghashIterator_getKey(&gh_iter),
+											  bm, vert_data, &v_index, NULL, NULL);
+			}
+
+			maxvert = v_index;
+		}
+		else {
+			GHASH_ITER (gh_iter, bm_faces) {
+				BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+
+				BLI_assert(f->len == 3);
+
+				if (gpu_bmesh_face_visible(f)) {
+					BMVert *v[3];
+					float fmask = 0;
+					int i;
+
+					BM_iter_as_array(bm, BM_VERTS_OF_FACE, f, (void**)v, 3);
+
+					/* Average mask value */
+					for (i = 0; i < 3; i++) {
+						fmask += *((float*)CustomData_bmesh_get(&bm->vdata,
+																v[i]->head.data,
+																CD_PAINT_MASK));
+					}
+					fmask /= 3.0f;
+					
+					for (i = 0; i < 3; i++) {
+						gpu_bmesh_vert_to_buffer_copy(v[i], bm, vert_data,
+													  &v_index, f->no, &fmask);
+					}
+				}
+			}
+
+			buffers->tot_tri = tottri;
+		}
+
+		glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
+	}
+	else {
+		/* Memory map failed */
+		glDeleteBuffersARB(1, &buffers->vert_buf);
+		buffers->vert_buf = 0;
+		return;
+	}
+
+	if (buffers->smooth) {
+		const int use_short = (maxvert < USHRT_MAX);
+
+		/* Initialize triangle index buffer */
+		glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
+		glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
+						(use_short ?
+						 sizeof(unsigned short) :
+						 sizeof(unsigned int)) * 3 * tottri,
+						NULL, GL_STATIC_DRAW_ARB);
+
+		/* Fill triangle index buffer */
+		tri_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+		if (tri_data) {
+			GHashIterator gh_iter;
+
+			GHASH_ITER (gh_iter, bm_faces) {
+				BMIter bm_iter;
+				BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+				BMVert *v;
+
+				if (gpu_bmesh_face_visible(f)) {
+					BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) {
+						if (use_short) {
+							unsigned short *elem = tri_data;
+							(*elem) = BM_elem_index_get(v);
+							elem++;
+							tri_data = elem;
+						}
+						else {
+							unsigned int *elem = tri_data;
+							(*elem) = BM_elem_index_get(v);
+							elem++;
+							tri_data = elem;
+						}
+					}
+				}
+			}
+
+			glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
+
+			buffers->tot_tri = tottri;
+			buffers->index_type = (use_short ?
+								   GL_UNSIGNED_SHORT :
+								   GL_UNSIGNED_INT);
+		}
+		else {
+			/* Memory map failed */
+			glDeleteBuffersARB(1, &buffers->index_buf);
+			buffers->index_buf = 0;
+		}
+	}
+}
+
+GPU_Buffers *GPU_build_bmesh_buffers(int smooth_shading)
+{
+	GPU_Buffers *buffers;
+
+	buffers = MEM_callocN(sizeof(GPU_Buffers), "GPU_Buffers");
+	if (smooth_shading)
+		glGenBuffersARB(1, &buffers->index_buf);
+	glGenBuffersARB(1, &buffers->vert_buf);
+	buffers->use_bmesh = TRUE;
+	buffers->smooth = smooth_shading;
+
+	return buffers;
+}
+
 static void gpu_draw_buffers_legacy_mesh(GPU_Buffers *buffers)
 {
 	const MVert *mvert = buffers->mvert;
-- 
cgit v1.2.3


From ec258542e2b537c4292fd9214d898fa5d3864ef9 Mon Sep 17 00:00:00 2001
From: Nicholas Bishop 
Date: Sun, 30 Dec 2012 18:25:36 +0000
Subject: Code cleanup: move PBVH/PBVHNode structs into new header file

---
 source/blender/blenkernel/CMakeLists.txt       |   1 +
 source/blender/blenkernel/intern/pbvh.c        | 116 +--------------------
 source/blender/blenkernel/intern/pbvh_intern.h | 138 +++++++++++++++++++++++++
 3 files changed, 141 insertions(+), 114 deletions(-)
 create mode 100644 source/blender/blenkernel/intern/pbvh_intern.h

(limited to 'source')

diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 2502773e7f5..6d53f9e7dd5 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -244,6 +244,7 @@ set(SRC
 	depsgraph_private.h
 	nla_private.h
 	intern/CCGSubSurf.h
+	intern/pbvh_intern.h
 )
 
 add_definitions(-DGLEW_STATIC)
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 209461bad2f..4341e701810 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -41,124 +41,12 @@
 
 #include "GPU_buffers.h"
 
+#include "pbvh_intern.h"
+
 #define LEAF_LIMIT 10000
 
 //#define PERFCNTRS
 
-/* Axis-aligned bounding box */
-typedef struct {
-	float bmin[3], bmax[3];
-} BB;
-
-/* Axis-aligned bounding box with centroid */
-typedef struct {
-	float bmin[3], bmax[3], bcentroid[3];
-} BBC;
-
-struct PBVHNode {
-	/* Opaque handle for drawing code */
-	GPU_Buffers *draw_buffers;
-
-	/* Voxel bounds */
-	BB vb;
-	BB orig_vb;
-
-	/* For internal nodes, the offset of the children in the PBVH
-	 * 'nodes' array. */
-	int children_offset;
-
-	/* Pointer into the PBVH prim_indices array and the number of
-	 * primitives used by this leaf node.
-	 *
-	 * Used for leaf nodes in both mesh- and multires-based PBVHs.
-	 */
-	int *prim_indices;
-	unsigned int totprim;
-
-	/* Array of indices into the mesh's MVert array. Contains the
-	 * indices of all vertices used by faces that are within this
-	 * node's bounding box.
-	 *
-	 * Note that a vertex might be used by a multiple faces, and
-	 * these faces might be in different leaf nodes. Such a vertex
-	 * will appear in the vert_indices array of each of those leaf
-	 * nodes.
-	 *
-	 * In order to support cases where you want access to multiple
-	 * nodes' vertices without duplication, the vert_indices array
-	 * is ordered such that the first part of the array, up to
-	 * index 'uniq_verts', contains "unique" vertex indices. These
-	 * vertices might not be truly unique to this node, but if
-	 * they appear in another node's vert_indices array, they will
-	 * be above that node's 'uniq_verts' value.
-	 *
-	 * Used for leaf nodes in a mesh-based PBVH (not multires.)
-	 */
-	int *vert_indices;
-	unsigned int uniq_verts, face_verts;
-
-	/* An array mapping face corners into the vert_indices
-	 * array. The array is sized to match 'totprim', and each of
-	 * the face's corners gets an index into the vert_indices
-	 * array, in the same order as the corners in the original
-	 * MFace. The fourth value should not be used if the original
-	 * face is a triangle.
-	 *
-	 * Used for leaf nodes in a mesh-based PBVH (not multires.)
-	 */
-	int (*face_vert_indices)[4];
-
-	/* Indicates whether this node is a leaf or not; also used for
-	 * marking various updates that need to be applied. */
-	PBVHNodeFlags flag : 8;
-
-	/* Used for raycasting: how close bb is to the ray point. */
-	float tmin;
-
-	int proxy_count;
-	PBVHProxyNode *proxies;
-};
-
-struct PBVH {
-	PBVHType type;
-
-	PBVHNode *nodes;
-	int node_mem_count, totnode;
-
-	int *prim_indices;
-	int totprim;
-	int totvert;
-
-	int leaf_limit;
-
-	/* Mesh data */
-	MVert *verts;
-	MFace *faces;
-	CustomData *vdata;
-
-	/* Grid Data */
-	CCGKey gridkey;
-	CCGElem **grids;
-	DMGridAdjacency *gridadj;
-	void **gridfaces;
-	const DMFlagMat *grid_flag_mats;
-	int totgrid;
-	BLI_bitmap *grid_hidden;
-
-	/* Only used during BVH build and update,
-	 * don't need to remain valid after */
-	BLI_bitmap vert_bitmap;
-
-#ifdef PERFCNTRS
-	int perf_modified;
-#endif
-
-	/* flag are verts/faces deformed */
-	int deformed;
-
-	int show_diffuse_color;
-};
-
 #define STACK_FIXED_DEPTH   100
 
 typedef struct PBVHStack {
diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h
new file mode 100644
index 00000000000..fe996536609
--- /dev/null
+++ b/source/blender/blenkernel/intern/pbvh_intern.h
@@ -0,0 +1,138 @@
+/*
+ * ***** 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 __PBVH_INTERN_H__
+#define __PBVH_INTERN_H__
+
+/* Axis-aligned bounding box */
+typedef struct {
+	float bmin[3], bmax[3];
+} BB;
+
+/* Axis-aligned bounding box with centroid */
+typedef struct {
+	float bmin[3], bmax[3], bcentroid[3];
+} BBC;
+
+struct PBVHNode {
+	/* Opaque handle for drawing code */
+	GPU_Buffers *draw_buffers;
+
+	/* Voxel bounds */
+	BB vb;
+	BB orig_vb;
+
+	/* For internal nodes, the offset of the children in the PBVH
+	 * 'nodes' array. */
+	int children_offset;
+
+	/* Pointer into the PBVH prim_indices array and the number of
+	 * primitives used by this leaf node.
+	 *
+	 * Used for leaf nodes in both mesh- and multires-based PBVHs.
+	 */
+	int *prim_indices;
+	unsigned int totprim;
+
+	/* Array of indices into the mesh's MVert array. Contains the
+	 * indices of all vertices used by faces that are within this
+	 * node's bounding box.
+	 *
+	 * Note that a vertex might be used by a multiple faces, and
+	 * these faces might be in different leaf nodes. Such a vertex
+	 * will appear in the vert_indices array of each of those leaf
+	 * nodes.
+	 *
+	 * In order to support cases where you want access to multiple
+	 * nodes' vertices without duplication, the vert_indices array
+	 * is ordered such that the first part of the array, up to
+	 * index 'uniq_verts', contains "unique" vertex indices. These
+	 * vertices might not be truly unique to this node, but if
+	 * they appear in another node's vert_indices array, they will
+	 * be above that node's 'uniq_verts' value.
+	 *
+	 * Used for leaf nodes in a mesh-based PBVH (not multires.)
+	 */
+	int *vert_indices;
+	unsigned int uniq_verts, face_verts;
+
+	/* An array mapping face corners into the vert_indices
+	 * array. The array is sized to match 'totprim', and each of
+	 * the face's corners gets an index into the vert_indices
+	 * array, in the same order as the corners in the original
+	 * MFace. The fourth value should not be used if the original
+	 * face is a triangle.
+	 *
+	 * Used for leaf nodes in a mesh-based PBVH (not multires.)
+	 */
+	int (*face_vert_indices)[4];
+
+	/* Indicates whether this node is a leaf or not; also used for
+	 * marking various updates that need to be applied. */
+	PBVHNodeFlags flag : 8;
+
+	/* Used for raycasting: how close bb is to the ray point. */
+	float tmin;
+
+	int proxy_count;
+	PBVHProxyNode *proxies;
+};
+
+struct PBVH {
+	PBVHType type;
+
+	PBVHNode *nodes;
+	int node_mem_count, totnode;
+
+	int *prim_indices;
+	int totprim;
+	int totvert;
+
+	int leaf_limit;
+
+	/* Mesh data */
+	MVert *verts;
+	MFace *faces;
+	CustomData *vdata;
+
+	/* Grid Data */
+	CCGKey gridkey;
+	CCGElem **grids;
+	DMGridAdjacency *gridadj;
+	void **gridfaces;
+	const DMFlagMat *grid_flag_mats;
+	int totgrid;
+	BLI_bitmap *grid_hidden;
+
+	/* Only used during BVH build and update,
+	 * don't need to remain valid after */
+	BLI_bitmap vert_bitmap;
+
+#ifdef PERFCNTRS
+	int perf_modified;
+#endif
+
+	/* flag are verts/faces deformed */
+	int deformed;
+
+	int show_diffuse_color;
+};
+
+#endif
-- 
cgit v1.2.3


From 31f978c8efdfd88d2cf2b5d9ae7c5d91c81e13d3 Mon Sep 17 00:00:00 2001
From: Nicholas Bishop 
Date: Sun, 30 Dec 2012 18:26:11 +0000
Subject: Move layer displacements from SculptUndoNode to PBVHNode

* This doesn't make much difference for regular mesh/multires
  sculpting, but for dynamic topology sculpting the undo stack isn't
  split up by PBVH nodes, so it's more convenient to store the layer
  data in PBVH nodes.

* Note that the life cycle of the layer displacement data is
  unchanged -- it's only valid during a stroke with the layer brush,
  gets free'd when the undo step ends.
---
 source/blender/blenkernel/BKE_pbvh.h                |  8 ++++++++
 source/blender/blenkernel/intern/pbvh.c             | 21 +++++++++++++++++++++
 source/blender/blenkernel/intern/pbvh_intern.h      |  3 +++
 source/blender/editors/sculpt_paint/sculpt.c        | 11 +++++------
 source/blender/editors/sculpt_paint/sculpt_intern.h |  3 ---
 source/blender/editors/sculpt_paint/sculpt_undo.c   |  8 ++------
 6 files changed, 39 insertions(+), 15 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 302de593963..5b6acdb9752 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -156,6 +156,14 @@ void BLI_pbvh_grids_update(PBVH *bvh, struct CCGElem **grid_elems,
                            struct DMGridAdjacency *gridadj, void **gridfaces,
                            struct DMFlagMat *flagmats, unsigned int **grid_hidden);
 
+/* Layer displacement */
+
+/* Get the node's displacement layer, creating it if necessary */
+float *BLI_pbvh_node_layer_disp_get(PBVH *pbvh, PBVHNode *node);
+
+/* If the node has a displacement layer, free it and set to null */
+void BLI_pbvh_node_layer_disp_free(PBVHNode *node);
+
 /* vertex deformer */
 float (*BLI_pbvh_get_vertCos(struct PBVH *pbvh))[3];
 void BLI_pbvh_apply_vertCos(struct PBVH *pbvh, float (*vertCos)[3]);
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 4341e701810..e9009050d4b 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -600,6 +600,7 @@ void BLI_pbvh_free(PBVH *bvh)
 				MEM_freeN(node->vert_indices);
 			if (node->face_vert_indices)
 				MEM_freeN(node->face_vert_indices);
+			BLI_pbvh_node_layer_disp_free(node);
 		}
 	}
 
@@ -1611,6 +1612,26 @@ void BLI_pbvh_grids_update(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj,
 	}
 }
 
+/* Get the node's displacement layer, creating it if necessary */
+float *BLI_pbvh_node_layer_disp_get(PBVH *bvh, PBVHNode *node)
+{
+	if (!node->layer_disp) {
+		int totvert = 0;
+		BLI_pbvh_node_num_verts(bvh, node, &totvert, NULL);
+		node->layer_disp = MEM_callocN(sizeof(float) * totvert, "layer disp");
+	}
+	return node->layer_disp;
+}
+
+/* If the node has a displacement layer, free it and set to null */
+void BLI_pbvh_node_layer_disp_free(PBVHNode *node)
+{
+	if (node->layer_disp) {
+		MEM_freeN(node->layer_disp);
+		node->layer_disp = NULL;
+	}
+}
+
 float (*BLI_pbvh_get_vertCos(PBVH * pbvh))[3]
 {
 	int a;
diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h
index fe996536609..d3539245d11 100644
--- a/source/blender/blenkernel/intern/pbvh_intern.h
+++ b/source/blender/blenkernel/intern/pbvh_intern.h
@@ -91,6 +91,9 @@ struct PBVHNode {
 	/* Used for raycasting: how close bb is to the ray point. */
 	float tmin;
 
+	/* Scalar displacements for sculpt mode's layer brush. */
+	float *layer_disp;
+
 	int proxy_count;
 	PBVHProxyNode *proxies;
 };
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 8325b47beab..2f0d69bfd98 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -1908,13 +1908,12 @@ static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
 		
 		unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS);
 		origco = unode->co;
-		if (!unode->layer_disp) {
-			#pragma omp critical 
-			unode->layer_disp = MEM_callocN(sizeof(float) * unode->totvert, "layer disp");
-		}
-
-		layer_disp = unode->layer_disp;
 
+		#pragma omp critical
+		{
+			layer_disp = BLI_pbvh_node_layer_disp_get(ss->pbvh, nodes[n]);
+		}
+		
 		sculpt_brush_test_init(ss, &test);
 
 		BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index 44068122b89..cfc908bf453 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -101,9 +101,6 @@ typedef struct SculptUndoNode {
 	int *grids;                 /* to restore into right location */
 	BLI_bitmap *grid_hidden;
 
-	/* layer brush */
-	float *layer_disp;
-
 	/* shape keys */
 	char shapeName[sizeof(((KeyBlock *)0))->name];
 } SculptUndoNode;
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index 1b3fd24ae22..053e17cde07 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -374,8 +374,6 @@ static void sculpt_undo_free(ListBase *lb)
 			MEM_freeN(unode->index);
 		if (unode->grids)
 			MEM_freeN(unode->grids);
-		if (unode->layer_disp)
-			MEM_freeN(unode->layer_disp);
 		if (unode->orig_co)
 			MEM_freeN(unode->orig_co);
 		if (unode->vert_hidden)
@@ -612,10 +610,8 @@ void sculpt_undo_push_end(void)
 			unode->no = NULL;
 		}
 
-		if (unode->layer_disp) {
-			MEM_freeN(unode->layer_disp);
-			unode->layer_disp = NULL;
-		}
+		if (unode->node)
+			BLI_pbvh_node_layer_disp_free(unode->node);
 	}
 
 	undo_paint_push_end(UNDO_PAINT_MESH);
-- 
cgit v1.2.3


From fc442dbd51a5ef71757a1a179222f358b6efdc8c Mon Sep 17 00:00:00 2001
From: Nicholas Bishop 
Date: Sun, 30 Dec 2012 18:27:33 +0000
Subject: Add DNA/RNA/BKE infrastructure for dynamic-topology sculpt mode

* Add a detail_size field to the Sculpt struct, two new sculpt flags,
  and a Mesh flag for dynamic-topology mode; that's it for file-level
  changes needed by dynamic topology

* Add RNA for the new DNA field and flags

* Add a new icon for dynamic-topology created by Julio Iglesias. TODO:
  update the icon for the new SVG icon format

* Add a SculptSession function for converting from BMesh to Mesh,
  handles reordering mesh elements and setting face shading
---
 source/blender/blenkernel/BKE_paint.h             |  8 ++++++
 source/blender/blenkernel/intern/object.c         | 30 +++++++++++++++++++++++
 source/blender/editors/include/UI_icons.h         |  4 +--
 source/blender/makesdna/DNA_mesh_types.h          |  1 +
 source/blender/makesdna/DNA_scene_types.h         | 11 ++++++++-
 source/blender/makesrna/intern/rna_object.c       | 13 ++++++++++
 source/blender/makesrna/intern/rna_sculpt_paint.c | 22 +++++++++++++++++
 7 files changed, 85 insertions(+), 4 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index c452c177143..0a4a7f75e25 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -33,6 +33,7 @@
  */
 
 struct bContext;
+struct BMesh;
 struct Brush;
 struct MDisps;
 struct MeshElemMap;
@@ -92,6 +93,12 @@ typedef struct SculptSession {
 	/* Mesh connectivity */
 	const struct MeshElemMap *pmap;
 
+	/* BMesh for dynamic topology sculpting */
+	struct BMesh *bm;
+	int bm_smooth_shading;
+	/* Undo/redo log for dynamic topology sculpting */
+	struct BMLog *bm_log;
+
 	/* PBVH acceleration structure */
 	struct PBVH *pbvh;
 	int show_diffuse_color;
@@ -121,5 +128,6 @@ typedef struct SculptSession {
 
 void free_sculptsession(struct Object *ob);
 void free_sculptsession_deformMats(struct SculptSession *ss);
+void sculptsession_bm_to_me(struct Object *ob, int reorder);
 
 #endif
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 99b163ce45b..92b2c8231d3 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -264,14 +264,44 @@ void free_sculptsession_deformMats(SculptSession *ss)
 	ss->deform_imats = NULL;
 }
 
+/* Write out the sculpt dynamic-topology BMesh to the Mesh */
+void sculptsession_bm_to_me(struct Object *ob, int reorder)
+{
+	if (ob && ob->sculpt) {
+		SculptSession *ss = ob->sculpt;
+
+		if (ss->bm) {
+			if (ob->data) {
+				BMIter iter;
+				BMFace *efa;
+				BM_ITER_MESH (efa, &iter, ss->bm, BM_FACES_OF_MESH) {
+					BM_elem_flag_set(efa, BM_ELEM_SMOOTH,
+									 ss->bm_smooth_shading);
+				}
+				if (reorder)
+					BM_log_mesh_elems_reorder(ss->bm, ss->bm_log);
+				BM_mesh_bm_to_me(ss->bm, ob->data, FALSE);
+			}
+		}
+	}
+}
+
 void free_sculptsession(Object *ob)
 {
 	if (ob && ob->sculpt) {
 		SculptSession *ss = ob->sculpt;
 		DerivedMesh *dm = ob->derivedFinal;
 
+		if (ss->bm) {
+			sculptsession_bm_to_me(ob, TRUE);
+			BM_mesh_free(ss->bm);
+		}
+
 		if (ss->pbvh)
 			BLI_pbvh_free(ss->pbvh);
+		if (ss->bm_log)
+ 			BM_log_free(ss->bm_log);
+
 		if (dm && dm->getPBVH)
 			dm->getPBVH(NULL, dm);  /* signal to clear */
 
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index 99f7f0856b3..0a794040692 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -699,9 +699,7 @@ DEF_ICON(RNDCURVE)
 DEF_ICON(PROP_OFF)
 DEF_ICON(PROP_ON)
 DEF_ICON(PROP_CON)
-#ifndef DEF_ICON_BLANK_SKIP
-	DEF_ICON(BLANK212)
-#endif
+DEF_ICON(SCULPT_DYNTOPO)
 DEF_ICON(PARTICLE_POINT)
 DEF_ICON(PARTICLE_TIP)
 DEF_ICON(PARTICLE_PATH)
diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h
index 05f8d2645ad..4c9f6014445 100644
--- a/source/blender/makesdna/DNA_mesh_types.h
+++ b/source/blender/makesdna/DNA_mesh_types.h
@@ -170,6 +170,7 @@ typedef struct TFace {
 #define ME_SUBSURF		128
 #define ME_OPT_EDGES	256
 #define ME_DS_EXPAND	512
+#define ME_SCULPT_DYNAMIC_TOPOLOGY 1024
 
 /* me->drawflag, short */
 #define ME_DRAWEDGES	(1 << 0)
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 5af116df772..0d1ef7af591 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -830,7 +830,8 @@ typedef struct Sculpt {
 
 	float special_rotation;
 
-	int pad;
+	/* Maximum edge length for dynamic topology sculpting (in pixels) */
+	int detail_size;
 } Sculpt;
 
 typedef struct UvSculpt {
@@ -1479,6 +1480,14 @@ typedef enum SculptFlags {
 	SCULPT_USE_OPENMP = (1<<7),
 	SCULPT_ONLY_DEFORM = (1<<8),
 	SCULPT_SHOW_DIFFUSE = (1<<9),
+
+	/* If set, the mesh will be drawn with smooth-shading in
+	   dynamic-topology mode */
+	SCULPT_DYNTOPO_SMOOTH_SHADING = (1<<10),
+
+	/* If set, dynamic-topology brushes will collapse short edges in
+	   addition to subdividing long ones */
+	SCULPT_DYNTOPO_COLLAPSE = (1<<11)
 } SculptFlags;
 
 /* ImagePaintSettings.flag */
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 4918aabdb1f..6e81e866118 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -48,6 +48,7 @@
 
 #include "BLI_utildefines.h"
 
+#include "BKE_paint.h"
 #include "BKE_tessmesh.h"
 #include "BKE_group.h" /* needed for object_in_group() */
 
@@ -1436,6 +1437,12 @@ int rna_DupliObject_index_get(PointerRNA *ptr)
 	return dob->persistent_id[0];
 }
 
+int rna_Object_use_dynamic_topology_sculpting_get(PointerRNA *ptr)
+{
+	SculptSession *ss = ((Object*)ptr->id.data)->sculpt;
+	return (ss && ss->bm);
+}
+
 #else
 
 static int rna_matrix_dimsize_4x4[] = {4, 4};
@@ -2629,6 +2636,12 @@ static void rna_def_object(BlenderRNA *brna)
 	RNA_def_property_ui_text(prop, "Active Shape Key Index", "Current shape key index");
 	RNA_def_property_update(prop, 0, "rna_Object_active_shape_update");
 
+	/* sculpt */
+	prop = RNA_def_property(srna, "use_dynamic_topology_sculpting", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_funcs(prop, "rna_Object_use_dynamic_topology_sculpting_get", NULL);
+	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+	RNA_def_property_ui_text(prop, "Dynamic Topology Sculpting", NULL);
+
 	RNA_api_object(srna);
 }
 
diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c
index f717c83075a..e3b41222a38 100644
--- a/source/blender/makesrna/intern/rna_sculpt_paint.c
+++ b/source/blender/makesrna/intern/rna_sculpt_paint.c
@@ -204,6 +204,11 @@ static void rna_Sculpt_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNU
 	if (ob) {
 		DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 		WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
+
+		if (ob->sculpt) {
+			ob->sculpt->bm_smooth_shading = (scene->toolsettings->sculpt->flags &
+											 SCULPT_DYNTOPO_SMOOTH_SHADING);
+		}
 	}
 }
 
@@ -319,6 +324,23 @@ static void rna_def_sculpt(BlenderRNA  *brna)
 	RNA_def_property_ui_text(prop, "Show Diffuse Color",
 	                         "Show diffuse color of object and overlay sculpt mask on top of it");
 	RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Sculpt_ShowDiffuseColor_update");
+
+	prop = RNA_def_property(srna, "detail_size", PROP_INT, PROP_DISTANCE);
+	RNA_def_property_ui_range(prop, 2, 100, 0, 0);
+	RNA_def_property_ui_text(prop, "Detail Size", "Maximum edge length for dynamic topology sculpting (in pixels)");
+
+	prop = RNA_def_property(srna, "use_smooth_shading", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "flags", SCULPT_DYNTOPO_SMOOTH_SHADING);
+	RNA_def_property_ui_text(prop, "Smooth Shading",
+							 "Show faces in dynamic-topology mode with smooth "
+							 "shading rather than flat shaded");
+	RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Sculpt_update");
+
+	prop = RNA_def_property(srna, "use_edge_collapse", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "flags", SCULPT_DYNTOPO_COLLAPSE);
+	RNA_def_property_ui_text(prop, "Collapse Short Edges",
+							 "In dynamic-topology mode, collapse short edges "
+							 "in addition to subdividing long ones");
 }
 
 
-- 
cgit v1.2.3


From 2c9d22fe31dc20df9fecc6322bdb7cbe56783164 Mon Sep 17 00:00:00 2001
From: Nicholas Bishop 
Date: Sun, 30 Dec 2012 18:28:10 +0000
Subject: Add BLI_buffer, an alternative to BLI_array

BLI_buffer is a dynamic homogeneous array similar to BLI_array, but it
allocates a structure that can be passed around making it possible to
resize the array outside the function it was declared in.
---
 source/blender/blenlib/BLI_buffer.h    | 69 ++++++++++++++++++++++++++++++++++
 source/blender/blenlib/CMakeLists.txt  |  2 +
 source/blender/blenlib/intern/buffer.c | 58 ++++++++++++++++++++++++++++
 3 files changed, 129 insertions(+)
 create mode 100644 source/blender/blenlib/BLI_buffer.h
 create mode 100644 source/blender/blenlib/intern/buffer.c

(limited to 'source')

diff --git a/source/blender/blenlib/BLI_buffer.h b/source/blender/blenlib/BLI_buffer.h
new file mode 100644
index 00000000000..7c14736ec40
--- /dev/null
+++ b/source/blender/blenlib/BLI_buffer.h
@@ -0,0 +1,69 @@
+/*
+ * ***** 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_BUFFER_H__
+#define __BLI_BUFFER_H__
+
+/* Note: this more or less fills same purpose as BLI_array, but makes
+ * it much easier to resize the array outside of the function it was
+ * declared in since */
+
+/* Usage examples:
+ *
+ * { 
+ *     BLI_buffer_declare(int, my_int_array, 32);
+ *
+ *     BLI_buffer_append(my_int_array, int, 42);
+ *     assert(my_int_array.count == 1);
+ *     assert(BLI_buffer_at(my_int_array, int, 0) == 42);
+ *
+ *     BLI_buffer_free(&my_int_array);
+ * }
+ */
+
+typedef struct {
+	void *data;
+	const int elem_size;
+	int count, alloc_count;
+	int using_static;
+} BLI_Buffer;
+
+#define BLI_buffer_declare(type_, name_, static_count_) \
+	type_ *name_ ## _static_[static_count_]; \
+	BLI_Buffer name_ = {name_ ## _static_, \
+						sizeof(type_), \
+						0, \
+						static_count_, \
+						TRUE}
+
+#define BLI_buffer_at(buffer_, type_, index_) \
+	(((type_*)(buffer_)->data)[index_])
+
+#define BLI_buffer_append(buffer_, type_, val_) \
+	BLI_buffer_resize(buffer_, (buffer_)->count + 1); \
+	BLI_buffer_at(buffer_, type_, (buffer_)->count - 1) = val_
+
+/* Never decreases the amount of memory allocated */
+void BLI_buffer_resize(BLI_Buffer *buffer, int new_count);
+
+/* Does not free the buffer structure itself */
+void BLI_buffer_free(BLI_Buffer *buffer);
+
+#endif
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index 6644c58611f..49e3db0e62c 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -48,6 +48,7 @@ set(SRC
 	intern/BLI_mempool.c
 	intern/DLRB_tree.c
 	intern/boxpack2d.c
+	intern/buffer.c
 	intern/callbacks.c
 	intern/cpu.c
 	intern/dynlib.c
@@ -96,6 +97,7 @@ set(SRC
 	BLI_array.h
 	BLI_bitmap.h
 	BLI_blenlib.h
+	BLI_buffer.h
 	BLI_boxpack2d.h
 	BLI_callbacks.h
 	BLI_cpu.h
diff --git a/source/blender/blenlib/intern/buffer.c b/source/blender/blenlib/intern/buffer.c
new file mode 100644
index 00000000000..98151c8eebf
--- /dev/null
+++ b/source/blender/blenlib/intern/buffer.c
@@ -0,0 +1,58 @@
+/*
+ * ***** 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 *****
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_buffer.h"
+#include "BLI_utildefines.h"
+
+#include 
+
+void BLI_buffer_resize(BLI_Buffer *buffer, int new_count)
+{
+	if (new_count > buffer->alloc_count) {
+		if (buffer->using_static) {
+			void *orig = buffer->data;
+			buffer->data = MEM_callocN(buffer->elem_size * new_count,
+									   "BLI_Buffer.data");
+			memcpy(buffer->data, orig, buffer->elem_size * buffer->count);
+			buffer->alloc_count = new_count;
+			buffer->using_static = FALSE;
+		}
+		else {
+			if (new_count < buffer->alloc_count * 2)
+				buffer->alloc_count *= 2;
+			else
+				buffer->alloc_count = new_count;
+			buffer->data = MEM_reallocN(buffer->data,
+										(buffer->elem_size *
+										 buffer->alloc_count));
+		}
+	}
+
+	buffer->count = new_count;
+}
+
+void BLI_buffer_free(BLI_Buffer *buffer)
+{
+	if (!buffer->using_static)
+		MEM_freeN(buffer->data);
+	memset(buffer, 0, sizeof(*buffer));
+}
-- 
cgit v1.2.3


From 2e69b0cd0b26fb1e641536de5a81a02f4478065c Mon Sep 17 00:00:00 2001
From: Nicholas Bishop 
Date: Sun, 30 Dec 2012 18:28:36 +0000
Subject: Add dynamic topology support to the PBVH

* Add BLI_pbvh_build_bmesh(), similar to the other PBVH builders but
  specialized for BMesh. Whereas the PBVH leaf nodes for mesh and
  grids only store a start-index and count into the primitive indices
  array, the BMesh version uses GHashes to store the full set of faces
  and vertices in leaf nodes

* Update PBVH iterator to handle BMesh

* Make some of the pbvh.c functions non-static so they can be used by
  the new pbvh_bmesh code

* The BLI_pbvh_bmesh_update_topology() function is the main reason for
  adding BMesh support to the PBVH. This function is used during a
  sculpt stroke to dynamically collapse edges that are particular
  short and subdivide edges that are particularly long.
---
 source/blender/blenkernel/BKE_pbvh.h           |   61 +-
 source/blender/blenkernel/CMakeLists.txt       |    1 +
 source/blender/blenkernel/intern/pbvh.c        |   81 +-
 source/blender/blenkernel/intern/pbvh_bmesh.c  | 1414 ++++++++++++++++++++++++
 source/blender/blenkernel/intern/pbvh_intern.h |   47 +-
 5 files changed, 1582 insertions(+), 22 deletions(-)
 create mode 100644 source/blender/blenkernel/intern/pbvh_bmesh.c

(limited to 'source')

diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 5b6acdb9752..4abeed513df 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -27,13 +27,18 @@
  */
 
 #include "BLI_bitmap.h"
+#include "BLI_ghash.h"
+#include "BLI_utildefines.h"
+
+/* Needed for BMesh functions used in the PBVH iterator macro */
+#include "bmesh.h"
 
 struct CCGElem;
 struct CCGKey;
 struct CustomData;
 struct DMFlagMat;
 struct DMGridAdjacency;
-struct ListBase;
+struct GHash;
 struct MFace;
 struct MVert;
 struct PBVH;
@@ -63,6 +68,9 @@ void BLI_pbvh_build_grids(PBVH *bvh, struct CCGElem **grid_elems,
                           struct DMGridAdjacency *gridadj, int totgrid,
                           struct CCGKey *key, void **gridfaces, struct DMFlagMat *flagmats,
                           unsigned int **grid_hidden);
+void BLI_pbvh_build_bmesh(PBVH *bvh, struct BMesh *bm, int smooth_shading,
+						  struct BMLog *log);
+
 void BLI_pbvh_free(PBVH *bvh);
 
 /* Hierarchical Search in the BVH, two methods:
@@ -86,7 +94,7 @@ void BLI_pbvh_raycast(PBVH *bvh, BLI_pbvh_HitOccludedCallback cb, void *data,
                       const float ray_start[3], const float ray_normal[3],
                       int original);
 
-int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3],
+int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3], int use_origco,
                           const float ray_start[3], const float ray_normal[3],
                           float *dist);
 
@@ -100,6 +108,7 @@ void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
 typedef enum {
 	PBVH_FACES,
 	PBVH_GRIDS,
+	PBVH_BMESH
 } PBVHType;
 
 PBVHType BLI_pbvh_type(const PBVH *bvh);
@@ -110,6 +119,17 @@ unsigned int **BLI_pbvh_grid_hidden(const PBVH *bvh);
 /* multires level, only valid for type == PBVH_GRIDS */
 void BLI_pbvh_get_grid_key(const PBVH *pbvh, struct CCGKey *key);
 
+/* Only valid for type == PBVH_BMESH */
+BMesh *BLI_pbvh_get_bmesh(PBVH *pbvh);
+void BLI_pbvh_bmesh_detail_size_set(PBVH *pbvh, float detail_size);
+
+typedef enum {
+	PBVH_Subdivide = 1,
+	PBVH_Collapse = 2,
+} PBVHTopologyUpdateMode;
+int BLI_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode,
+								   const float center[3], float radius);
+
 /* Node Access */
 
 typedef enum {
@@ -122,12 +142,15 @@ typedef enum {
 	PBVH_UpdateRedraw = 32,
 
 	PBVH_RebuildDrawBuffers = 64,
-	PBVH_FullyHidden = 128
+	PBVH_FullyHidden = 128,
+
+	PBVH_UpdateTopology = 256,
 } PBVHNodeFlags;
 
 void BLI_pbvh_node_mark_update(PBVHNode *node);
 void BLI_pbvh_node_mark_rebuild_draw(PBVHNode *node);
 void BLI_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden);
+void BLI_pbvh_node_mark_topology_update(PBVHNode *node);
 
 void BLI_pbvh_node_get_grids(PBVH *bvh, PBVHNode *node,
                              int **grid_indices, int *totgrid, int *maxgrid, int *gridsize,
@@ -147,6 +170,11 @@ int BLI_pbvh_node_planes_contain_AABB(PBVHNode *node, void *data);
 /* test if AABB is at least partially outside the planes' volume */
 int BLI_pbvh_node_planes_exclude_AABB(PBVHNode *node, void *data);
 
+struct GHash *BLI_pbvh_bmesh_node_unique_verts(PBVHNode *node);
+struct GHash *BLI_pbvh_bmesh_node_other_verts(PBVHNode *node); 
+void BLI_pbvh_bmesh_node_save_orig(PBVHNode *node);
+void BLI_pbvh_bmesh_after_stroke(PBVH *bvh);
+
 /* Update Normals/Bounding Box/Draw Buffers/Redraw and clear flags */
 
 void BLI_pbvh_update(PBVH *bvh, int flags, float (*face_nors)[3]);
@@ -169,7 +197,6 @@ float (*BLI_pbvh_get_vertCos(struct PBVH *pbvh))[3];
 void BLI_pbvh_apply_vertCos(struct PBVH *pbvh, float (*vertCos)[3]);
 int BLI_pbvh_isDeformed(struct PBVH *pbvh);
 
-
 /* Vertex Iterator */
 
 /* this iterator has quite a lot of code, but it's designed to:
@@ -205,9 +232,15 @@ typedef struct PBVHVertexIter {
 	int *vert_indices;
 	float *vmask;
 
+	/* bmesh */
+	struct GHashIterator bm_unique_verts;
+	struct GHashIterator bm_other_verts;
+	struct CustomData *bm_vdata;
+
 	/* result: these are all computed in the macro, but we assume
 	 * that compiler optimization's will skip the ones we don't use */
 	struct MVert *mvert;
+	struct BMVert *bm_vert;
 	float *co;
 	short *no;
 	float *fno;
@@ -249,7 +282,7 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node,
 							continue; \
 					} \
 				} \
-				else { \
+				else if (vi.mverts) { \
 					vi.mvert = &vi.mverts[vi.vert_indices[vi.gx]]; \
 					if (mode == PBVH_ITER_UNIQUE && vi.mvert->flag & ME_HIDE) \
 						continue; \
@@ -258,6 +291,24 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node,
 					if (vi.vmask) \
 						vi.mask = &vi.vmask[vi.vert_indices[vi.gx]]; \
 				} \
+				else { \
+					if (!BLI_ghashIterator_isDone(&vi.bm_unique_verts)) {\
+						vi.bm_vert = BLI_ghashIterator_getKey(&vi.bm_unique_verts); \
+						BLI_ghashIterator_step(&vi.bm_unique_verts); \
+					} \
+					else { \
+						vi.bm_vert = BLI_ghashIterator_getKey(&vi.bm_other_verts); \
+						BLI_ghashIterator_step(&vi.bm_other_verts); \
+					} \
+					if (mode == PBVH_ITER_UNIQUE && \
+						BM_elem_flag_test(vi.bm_vert, BM_ELEM_HIDDEN)) \
+						continue; \
+					vi.co = vi.bm_vert->co; \
+					vi.fno = vi.bm_vert->no; \
+					vi.mask = CustomData_bmesh_get(vi.bm_vdata, \
+												   vi.bm_vert->head.data, \
+												   CD_PAINT_MASK); \
+				}
 
 #define BLI_pbvh_vertex_iter_end \
 			} \
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 6d53f9e7dd5..99008309498 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -124,6 +124,7 @@ set(SRC
 	intern/particle.c
 	intern/particle_system.c
 	intern/pbvh.c
+	intern/pbvh_bmesh.c
 	intern/pointcache.c
 	intern/property.c
 	intern/report.c
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index e9009050d4b..6e0209e7683 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -66,14 +66,14 @@ typedef struct PBVHIter {
 	int stackspace;
 } PBVHIter;
 
-static void BB_reset(BB *bb)
+void BB_reset(BB *bb)
 {
 	bb->bmin[0] = bb->bmin[1] = bb->bmin[2] = FLT_MAX;
 	bb->bmax[0] = bb->bmax[1] = bb->bmax[2] = -FLT_MAX;
 }
 
 /* Expand the bounding box to include a new coordinate */
-static void BB_expand(BB *bb, float co[3])
+void BB_expand(BB *bb, const float co[3])
 {
 	int i;
 	for (i = 0; i < 3; ++i) {
@@ -83,7 +83,7 @@ static void BB_expand(BB *bb, float co[3])
 }
 
 /* Expand the bounding box to include another bounding box */
-static void BB_expand_with_bb(BB *bb, BB *bb2)
+void BB_expand_with_bb(BB *bb, BB *bb2)
 {
 	int i;
 	for (i = 0; i < 3; ++i) {
@@ -93,7 +93,7 @@ static void BB_expand_with_bb(BB *bb, BB *bb2)
 }
 
 /* Return 0, 1, or 2 to indicate the widest axis of the bounding box */
-static int BB_widest_axis(BB *bb)
+int BB_widest_axis(const BB *bb)
 {
 	float dim[3];
 	int i;
@@ -115,7 +115,7 @@ static int BB_widest_axis(BB *bb)
 	}
 }
 
-static void BBC_update_centroid(BBC *bbc)
+void BBC_update_centroid(BBC *bbc)
 {
 	int i;
 	for (i = 0; i < 3; ++i)
@@ -220,7 +220,7 @@ static int partition_indices_material(PBVH *bvh, int lo, int hi)
 	}
 }
 
-static void grow_nodes(PBVH *bvh, int totnode)
+void pbvh_grow_nodes(PBVH *bvh, int totnode)
 {
 	if (totnode > bvh->node_mem_count) {
 		PBVHNode *prev = bvh->nodes;
@@ -433,7 +433,7 @@ static void build_sub(PBVH *bvh, int node_index, BB *cb, BBC *prim_bbc,
 
 	/* Add two child nodes */
 	bvh->nodes[node_index].children_offset = bvh->totnode;
-	grow_nodes(bvh, bvh->totnode + 2);
+	pbvh_grow_nodes(bvh, bvh->totnode + 2);
 
 	/* Update parent node bounding box */
 	update_vb(bvh, &bvh->nodes[node_index], prim_bbc, offset, count);
@@ -601,6 +601,13 @@ void BLI_pbvh_free(PBVH *bvh)
 			if (node->face_vert_indices)
 				MEM_freeN(node->face_vert_indices);
 			BLI_pbvh_node_layer_disp_free(node);
+
+			if (node->bm_faces)
+				BLI_ghash_free(node->bm_faces, NULL, NULL);
+			if (node->bm_unique_verts)
+				BLI_ghash_free(node->bm_unique_verts, NULL, NULL);
+			if (node->bm_other_verts)
+				BLI_ghash_free(node->bm_other_verts, NULL, NULL);
 		}
 	}
 
@@ -620,6 +627,11 @@ void BLI_pbvh_free(PBVH *bvh)
 	if (bvh->prim_indices)
 		MEM_freeN(bvh->prim_indices);
 
+	if (bvh->bm_vert_to_node)
+		BLI_ghash_free(bvh->bm_vert_to_node, NULL, NULL);
+	if (bvh->bm_face_to_node)
+		BLI_ghash_free(bvh->bm_face_to_node, NULL, NULL);
+
 	MEM_freeN(bvh);
 }
 
@@ -900,6 +912,11 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
 	float (*vnor)[3];
 	int n;
 
+	if (bvh->type == PBVH_BMESH) {
+		pbvh_bmesh_normals_update(nodes, totnode);
+		return;
+	}
+
 	if (bvh->type != PBVH_FACES)
 		return;
 
@@ -993,8 +1010,7 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
 	MEM_freeN(vnor);
 }
 
-static void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes,
-                                  int totnode, int flag)
+void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag)
 {
 	int n;
 
@@ -1041,6 +1057,11 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
 					                           node->prim_indices,
 					                           node->totprim);
 					break;
+ 				case PBVH_BMESH:
+					node->draw_buffers =
+						GPU_build_bmesh_buffers(bvh->flags &
+							                    PBVH_DYNTOPO_SMOOTH_SHADING);
+					break;
 			}
  
 			node->flag &= ~PBVH_RebuildDrawBuffers;
@@ -1068,6 +1089,13 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
 					                        node->face_vert_indices,
 					                        bvh->show_diffuse_color);
 					break;
+ 				case PBVH_BMESH:
+					GPU_update_bmesh_buffers(node->draw_buffers,
+		                                     bvh->bm,
+											 node->bm_faces,
+											 node->bm_unique_verts,
+											 node->bm_other_verts);
+					break;
 			}
 
 			node->flag &= ~PBVH_UpdateDrawBuffers;
@@ -1222,6 +1250,12 @@ void BLI_pbvh_get_grid_key(const PBVH *bvh, CCGKey *key)
 	*key = bvh->gridkey;
 }
 
+BMesh *BLI_pbvh_get_bmesh(PBVH *bvh)
+{
+	BLI_assert(bvh->type == PBVH_BMESH);
+	return bvh->bm;
+}
+
 /***************************** Node Access ***********************************/
 
 void BLI_pbvh_node_mark_update(PBVHNode *node)
@@ -1264,6 +1298,11 @@ void BLI_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node, int *uniquevert, int *to
 			if (totvert) *totvert = node->uniq_verts + node->face_verts;
 			if (uniquevert) *uniquevert = node->uniq_verts;
 			break;
+		case PBVH_BMESH:
+			tot = BLI_ghash_size(node->bm_unique_verts);
+			if (totvert) *totvert = tot + BLI_ghash_size(node->bm_other_verts);
+			if (uniquevert) *uniquevert = tot;
+			break;
 	}
 }
 
@@ -1279,6 +1318,7 @@ void BLI_pbvh_node_get_grids(PBVH *bvh, PBVHNode *node, int **grid_indices, int
 			if (gridadj) *gridadj = bvh->gridadj;
 			break;
 		case PBVH_FACES:
+		case PBVH_BMESH:
 			if (grid_indices) *grid_indices = NULL;
 			if (totgrid) *totgrid = 0;
 			if (maxgrid) *maxgrid = 0;
@@ -1345,11 +1385,11 @@ void BLI_pbvh_raycast(PBVH *bvh, BLI_pbvh_HitOccludedCallback cb, void *data,
 	BLI_pbvh_search_callback_occluded(bvh, ray_aabb_intersect, &rcd, cb, data);
 }
 
-static int 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)
+int 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)
 {
 	float dist;
 
@@ -1455,7 +1495,7 @@ static int pbvh_grids_node_raycast(PBVH *bvh, PBVHNode *node,
 	return hit;
 }
 
-int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3],
+int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3], int use_origco,
                           const float ray_start[3], const float ray_normal[3],
                           float *dist)
 {
@@ -1473,6 +1513,9 @@ int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3],
 			hit |= pbvh_grids_node_raycast(bvh, node, origco,
 			                               ray_start, ray_normal, dist);
 			break;
+		case PBVH_BMESH:
+			hit = pbvh_bmesh_node_raycast(node, ray_start, ray_normal, dist, use_origco);
+			break;
 	}
 
 	return hit;
@@ -1803,12 +1846,18 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node,
 	vi->vert_indices = vert_indices;
 	vi->mverts = verts;
 
+	if (bvh->type == PBVH_BMESH) {
+		BLI_ghashIterator_init(&vi->bm_unique_verts, node->bm_unique_verts);
+		BLI_ghashIterator_init(&vi->bm_other_verts, node->bm_other_verts);
+		vi->bm_vdata = &bvh->bm->vdata;
+	}
+
 	vi->gh = NULL;
 	if (vi->grids && mode == PBVH_ITER_UNIQUE)
 		vi->grid_hidden = bvh->grid_hidden;
 
 	vi->mask = NULL;
-	if (!vi->grids)
+	if (bvh->type == PBVH_FACES)
 		vi->vmask = CustomData_get_layer(bvh->vdata, CD_PAINT_MASK);
 }
 
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
new file mode 100644
index 00000000000..9cc8fd09c73
--- /dev/null
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -0,0 +1,1414 @@
+/*
+ * ***** 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 *****
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_object_types.h"
+
+#include "BLI_array.h"
+#include "BLI_buffer.h"
+#include "BLI_ghash.h"
+#include "BLI_heap.h"
+#include "BLI_math.h"
+
+#include "BKE_ccg.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_global.h"
+#include "BKE_pbvh.h"
+
+#include "GPU_buffers.h"
+
+#include "bmesh.h"
+#include "pbvh_intern.h"
+
+#include 
+
+/****************************** Building ******************************/
+
+/* Update node data after splitting */
+static void pbvh_bmesh_node_finalize(PBVH *bvh, int node_index)
+{
+	GHashIterator gh_iter;
+	PBVHNode *n = &bvh->nodes[node_index];
+
+	/* Create vert hash sets */
+	n->bm_unique_verts = BLI_ghash_ptr_new("bm_unique_verts");
+	n->bm_other_verts = BLI_ghash_ptr_new("bm_other_verts");
+
+	BB_reset(&n->vb);
+
+	GHASH_ITER (gh_iter, n->bm_faces) {
+		BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+		BMIter bm_iter;
+		BMVert *v;
+		void *node_val = SET_INT_IN_POINTER(node_index);
+
+		/* Update ownership of faces */
+		BLI_ghash_insert(bvh->bm_face_to_node, f, node_val);
+
+		/* Update vertices */
+		BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) {
+			if (!BLI_ghash_haskey(n->bm_unique_verts, v)) {
+				if (BLI_ghash_haskey(bvh->bm_vert_to_node, v)) {
+					if (!BLI_ghash_haskey(n->bm_other_verts, v))
+						BLI_ghash_insert(n->bm_other_verts, v, NULL);
+				}
+				else {
+					BLI_ghash_insert(n->bm_unique_verts, v, NULL);
+					BLI_ghash_insert(bvh->bm_vert_to_node, v, node_val);
+				}
+			}
+			/* Update node bounding box */
+			BB_expand(&n->vb, v->co);
+		}
+	}
+
+	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 */
+	if (!G.background) {
+		int smooth = bvh->flags & PBVH_DYNTOPO_SMOOTH_SHADING;
+		n->draw_buffers = GPU_build_bmesh_buffers(smooth);
+		n->flag |= PBVH_UpdateDrawBuffers;
+	}
+}
+
+/* Recursively split the node if it exceeds the leaf_limit */
+static void pbvh_bmesh_node_split(PBVH *bvh, GHash *prim_bbc, int node_index)
+{
+	GHash *empty, *other;
+	GHashIterator gh_iter;
+	PBVHNode *n, *c1, *c2;
+	BB cb;
+	float mid;
+	int axis, children;
+
+	n = &bvh->nodes[node_index];
+
+	if (BLI_ghash_size(n->bm_faces) <= bvh->leaf_limit) {
+		/* Node limit not exceeded */
+		pbvh_bmesh_node_finalize(bvh, node_index);
+		return;
+	}
+
+	/* Calculate bounding box around primitive centroids */
+	BB_reset(&cb);
+	GHASH_ITER (gh_iter, n->bm_faces) {
+		const BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+		const BBC *bbc = BLI_ghash_lookup(prim_bbc, f);
+
+		BB_expand(&cb, bbc->bcentroid);
+	}
+
+	/* Find widest axis and its midpoint */
+	axis = BB_widest_axis(&cb);
+	mid = (cb.bmax[axis] + cb.bmin[axis]) * 0.5f;
+
+	/* Add two new child nodes */
+	children = bvh->totnode;
+	n->children_offset = children;
+	pbvh_grow_nodes(bvh, bvh->totnode + 2);
+
+	/* Array reallocated, update current node pointer */
+	n = &bvh->nodes[node_index];
+
+	/* Initialize children */
+	c1 = &bvh->nodes[children];
+	c2 = &bvh->nodes[children + 1];
+	c1->flag |= PBVH_Leaf;
+	c2->flag |= PBVH_Leaf;
+	c1->bm_faces = BLI_ghash_ptr_new("bm_faces");
+	c2->bm_faces = BLI_ghash_ptr_new("bm_faces");
+
+	/* Partition the parent node's faces between the two children */
+	GHASH_ITER (gh_iter, n->bm_faces) {
+		BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+		const BBC *bbc = BLI_ghash_lookup(prim_bbc, f);
+
+		if (bbc->bcentroid[axis] < mid)
+			BLI_ghash_insert(c1->bm_faces, f, NULL);
+		else
+			BLI_ghash_insert(c2->bm_faces, f, NULL);
+	}
+
+	/* Enforce at least one primitive in each node */
+	empty = NULL;
+	if (BLI_ghash_size(c1->bm_faces) == 0) {
+		empty = c1->bm_faces;
+		other = c2->bm_faces;
+	}
+	else if (BLI_ghash_size(c2->bm_faces) == 0) {
+		empty = c2->bm_faces;
+		other = c1->bm_faces;
+	}
+	if (empty) {
+		GHASH_ITER (gh_iter, other) {
+			void *key = BLI_ghashIterator_getKey(&gh_iter);
+			BLI_ghash_insert(empty, key, NULL);
+			BLI_ghash_remove(other, key, NULL, NULL);
+			break;
+		}
+	}
+	
+	/* Clear this node */
+
+	/* Mark this node's unique verts as unclaimed */
+	if (n->bm_unique_verts) {
+		GHASH_ITER (gh_iter, n->bm_unique_verts) {
+			BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+			BLI_ghash_remove(bvh->bm_vert_to_node, v, NULL, NULL);
+		}
+		BLI_ghash_free(n->bm_unique_verts, NULL, NULL);
+	}
+
+	/* Unclaim faces */
+	GHASH_ITER (gh_iter, n->bm_faces) {
+		BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+		BLI_ghash_remove(bvh->bm_face_to_node, f, NULL, NULL);
+	}
+	BLI_ghash_free(n->bm_faces, NULL, NULL);
+
+	if (n->bm_other_verts)
+		BLI_ghash_free(n->bm_other_verts, NULL, NULL);
+
+	if (n->layer_disp)
+		MEM_freeN(n->layer_disp);
+	
+	n->bm_faces = NULL;
+	n->bm_unique_verts = NULL;
+	n->bm_other_verts = NULL;
+	n->layer_disp = NULL;
+	
+	if (n->draw_buffers) {
+		GPU_free_buffers(n->draw_buffers);
+		n->draw_buffers = NULL;
+	}
+	n->flag &= ~PBVH_Leaf;
+	
+	/* Recurse */
+	c1 = c2 = NULL;
+	pbvh_bmesh_node_split(bvh, prim_bbc, children);
+	pbvh_bmesh_node_split(bvh, prim_bbc, children + 1);
+
+	/* Array maybe reallocated, update current node pointer */
+	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;
+}
+
+/* Recursively split the node if it exceeds the leaf_limit */
+static int pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index)
+{
+	GHash *prim_bbc;
+	GHashIterator gh_iter;
+
+	if (BLI_ghash_size(bvh->nodes[node_index].bm_faces) <= bvh->leaf_limit) {
+		/* Node limit not exceeded */
+		return FALSE;
+	}
+
+	/* For each BMFace, store the AABB and AABB centroid */
+	prim_bbc = BLI_ghash_ptr_new("prim_bbc");
+
+	GHASH_ITER (gh_iter, bvh->nodes[node_index].bm_faces) {
+		BMIter bm_iter;
+		BMVert *v;
+		BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+		BBC *bbc = MEM_callocN(sizeof(BBC), "BBC");
+
+		BB_reset((BB *)bbc);
+		BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) {
+			BB_expand((BB *)bbc, v->co);
+		}
+		BBC_update_centroid(bbc);
+
+		BLI_ghash_insert(prim_bbc, f, bbc);
+	}
+
+	pbvh_bmesh_node_split(bvh, prim_bbc, node_index);
+
+	BLI_ghash_free(prim_bbc, NULL, (void*)MEM_freeN);
+
+	return TRUE;
+}
+
+/**********************************************************************/
+
+static PBVHNode *pbvh_bmesh_node_lookup(PBVH *bvh, GHash *map, void *key)
+{
+	int node_index;
+
+	BLI_assert(BLI_ghash_haskey(map, key));
+
+	node_index = GET_INT_FROM_POINTER(BLI_ghash_lookup(map, key));
+	BLI_assert(node_index < bvh->totnode);
+
+	return &bvh->nodes[node_index];
+}
+
+static BMVert *pbvh_bmesh_vert_create(PBVH *bvh, int node_index,
+									  const float co[3],
+									  const BMVert *example)
+{
+	BMVert *v = BM_vert_create(bvh->bm, co, example, 0);
+	void *val = SET_INT_IN_POINTER(node_index);
+
+	BLI_assert((bvh->totnode == 1 || node_index) && node_index <= bvh->totnode);
+
+	BLI_ghash_insert(bvh->nodes[node_index].bm_unique_verts, v, NULL);
+	BLI_ghash_insert(bvh->bm_vert_to_node, v, val);
+
+	/* Log the new vertex */
+	BM_log_vert_added(bvh->bm, bvh->bm_log, v);
+
+	return v;
+}
+
+static BMFace *pbvh_bmesh_face_create(PBVH *bvh, int node_index, BMVert *v1,
+									  BMVert *v2, BMVert *v3,
+									  const BMFace *UNUSED(example))
+{
+	BMFace *f;
+	void *val = SET_INT_IN_POINTER(node_index);
+
+	/* Note: passing NULL for the 'example' parameter, profiling shows
+	 * a small performance bump */
+	f = BM_face_create_quad_tri(bvh->bm, v1, v2, v3, NULL, NULL, TRUE);
+	if (!BLI_ghash_haskey(bvh->bm_face_to_node, f)) {
+
+		BLI_ghash_insert(bvh->nodes[node_index].bm_faces, f, NULL);
+		BLI_ghash_insert(bvh->bm_face_to_node, f, val);
+
+		/* Log the new face */
+		BM_log_face_added(bvh->bm_log, f);
+	}
+
+	return f;
+}
+
+/* Return the number of faces in 'node' that use vertex 'v' */
+static int pbvh_bmesh_node_vert_use_count(PBVH *bvh, PBVHNode *node, BMVert *v)
+{
+	BMIter bm_iter;
+	BMFace *f;
+	int count = 0;
+
+	BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) {
+		PBVHNode *f_node;
+
+		f_node = pbvh_bmesh_node_lookup(bvh, bvh->bm_face_to_node, f);
+
+		if (f_node == node)
+			count++;
+	}
+
+	return count;
+}
+
+/* Return a node that uses vertex 'v' other than its current owner */
+static PBVHNode *pbvh_bmesh_vert_other_node_find(PBVH *bvh, BMVert *v)
+{
+	BMIter bm_iter;
+	BMFace *f;
+	PBVHNode *current_node;
+
+	current_node = pbvh_bmesh_node_lookup(bvh, bvh->bm_vert_to_node, v);
+
+	BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) {
+		PBVHNode *f_node;
+
+		f_node = pbvh_bmesh_node_lookup(bvh, bvh->bm_face_to_node, f);
+
+		if (f_node != current_node)
+			return f_node;
+	}
+
+	return NULL;
+}
+
+static void pbvh_bmesh_vert_ownership_transfer(PBVH *bvh, PBVHNode *new_owner,
+											   BMVert *v)
+{
+	PBVHNode *current_owner;
+
+	current_owner = pbvh_bmesh_node_lookup(bvh, bvh->bm_vert_to_node, v);
+	BLI_assert(current_owner != new_owner);
+
+	/* Remove current ownership */
+	BLI_ghash_remove(bvh->bm_vert_to_node, v, NULL, NULL);
+	BLI_ghash_remove(current_owner->bm_unique_verts, v, NULL, NULL);
+
+	/* Set new ownership */
+	BLI_ghash_insert(bvh->bm_vert_to_node, v,
+					 SET_INT_IN_POINTER(new_owner - bvh->nodes));
+	BLI_ghash_insert(new_owner->bm_unique_verts, v, NULL);
+	BLI_ghash_remove(new_owner->bm_other_verts, v, NULL, NULL);
+	BLI_assert(!BLI_ghash_haskey(new_owner->bm_other_verts, v));
+}
+
+static void pbvh_bmesh_vert_remove(PBVH *bvh, BMVert *v)
+{
+	PBVHNode *v_node;
+	BMIter bm_iter;
+	BMFace *f;
+
+	BLI_assert(BLI_ghash_haskey(bvh->bm_vert_to_node, v));
+	v_node = pbvh_bmesh_node_lookup(bvh, bvh->bm_vert_to_node, v);
+	BLI_ghash_remove(v_node->bm_unique_verts, v, NULL, NULL);
+	BLI_ghash_remove(bvh->bm_vert_to_node, v, NULL, NULL);
+
+	/* Have to check each neighboring face's node */
+	BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) {
+		PBVHNode *f_node = pbvh_bmesh_node_lookup(bvh, bvh->bm_face_to_node, f);
+
+		BLI_ghash_remove(f_node->bm_unique_verts, v, NULL, NULL);
+		BLI_ghash_remove(f_node->bm_other_verts, v, NULL, NULL);
+
+		BLI_assert(!BLI_ghash_haskey(f_node->bm_unique_verts, v));
+		BLI_assert(!BLI_ghash_haskey(f_node->bm_other_verts, v));
+	}
+}
+
+static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f)
+{
+	PBVHNode *f_node;
+	BMIter bm_iter;
+	BMVert *v;
+
+	f_node = pbvh_bmesh_node_lookup(bvh, bvh->bm_face_to_node, f);
+
+	/* Check if any of this face's vertices need to be removed
+	 * from the node */
+	BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) {
+		if (pbvh_bmesh_node_vert_use_count(bvh, f_node, v) == 1) {
+			if (BLI_ghash_lookup(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);
+
+				if (new_node) {
+					pbvh_bmesh_vert_ownership_transfer(bvh, new_node, v);
+				}
+			}
+			else {
+				/* Remove from other verts */
+				BLI_ghash_remove(f_node->bm_other_verts, v, NULL, NULL);
+			}
+		}
+	}
+
+	/* Remove face from node and top level */
+	BLI_ghash_remove(f_node->bm_faces, f, NULL, NULL);
+	BLI_ghash_remove(bvh->bm_face_to_node, f, NULL, NULL);
+
+	/* Log removed face */
+	BM_log_face_removed(bvh->bm_log, f);
+}
+
+static BMVert *bm_triangle_other_vert_find(BMFace *triangle, const BMVert *v1,
+										   const BMVert *v2)
+{
+	BLI_assert(triangle->len == 3);
+	BLI_assert(v1 != v2);
+
+	if (triangle->len == 3) {
+		BMIter iter;
+		BMVert *v, *other = NULL;
+		int found_v1 = FALSE, found_v2 = FALSE;
+
+		BM_ITER_ELEM (v, &iter, triangle, BM_VERTS_OF_FACE) {
+			if (v == v1)
+				found_v1 = TRUE;
+			else if (v == v2)
+				found_v2 = TRUE;
+			else
+				other = v;
+		}
+
+		if (found_v1 && found_v2)
+			return other;
+	}
+
+	BLI_assert(0);
+	return NULL;
+}
+
+static void pbvh_bmesh_edge_faces(BLI_Buffer *buf, BMEdge *e)
+{
+	BLI_buffer_resize(buf, BM_edge_face_count(e));
+	BM_iter_as_array(NULL, BM_FACES_OF_EDGE, e, buf->data, buf->count);
+}
+
+/* TODO: maybe a better way to do this, if not then this should go to
+ * bmesh_queries */
+static int bm_face_edge_backwards(BMFace *f, BMEdge *e)
+{
+	BMIter bm_iter;
+	BMLoop *l, *l1 = NULL, *l2 = NULL;
+
+	BM_ITER_ELEM (l, &bm_iter, f, BM_LOOPS_OF_FACE) {
+		if (l->v == e->v1)
+			l1 = l;
+		else if (l->v == e->v2)
+			l2 = l;
+	}
+
+	BLI_assert(l1 && l2);
+	BLI_assert(l1->next == l2 || l2->next == l1);
+	return l2->next == l1;
+}
+
+static void pbvh_bmesh_node_drop_orig(PBVHNode *node)
+{
+	if (node->bm_orco)
+		MEM_freeN(node->bm_orco);
+	if (node->bm_ortri)
+		MEM_freeN(node->bm_ortri);
+	node->bm_orco = NULL;
+	node->bm_ortri = NULL;
+	node->bm_tot_ortri = 0;
+}
+
+/****************************** EdgeQueue *****************************/
+
+typedef struct {
+	Heap *heap;
+	const float *center;
+	float radius_squared;
+	float limit_len_squared;
+} EdgeQueue;
+
+static int edge_queue_tri_in_sphere(const EdgeQueue *q, BMFace *f)
+{
+	BMVert *v[3];
+	float c[3];
+
+	/* Get closest point in triangle to sphere center */
+	BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3);
+	closest_on_tri_to_point_v3(c, q->center, v[0]->co, v[1]->co, v[2]->co);
+
+	/* Check if triangle intersects the sphere */
+	return ((len_squared_v3v3(q->center, c) <= q->radius_squared));
+}
+
+static void edge_queue_insert(EdgeQueue *q, BLI_mempool *pool, BMEdge *e,
+							  float priority)
+{
+	BMVert **pair;
+
+	pair = BLI_mempool_alloc(pool);
+	pair[0] = e->v1;
+	pair[1] = e->v2;
+	BLI_heap_insert(q->heap, priority, pair);
+}
+
+static void long_edge_queue_edge_add(EdgeQueue *q, BLI_mempool *pool,
+									 BMEdge *e)
+{
+	const float len_sq = BM_edge_calc_squared_length(e);
+	if (len_sq > q->limit_len_squared)
+		edge_queue_insert(q, pool, e, 1.0f / len_sq);
+}
+
+static void short_edge_queue_edge_add(EdgeQueue *q, BLI_mempool *pool,
+									  BMEdge *e)
+{
+	const float len_sq = BM_edge_calc_squared_length(e);
+	if (len_sq < q->limit_len_squared)
+		edge_queue_insert(q, pool, e, len_sq);
+}
+
+static int long_edge_queue_face_add(EdgeQueue *q, BLI_mempool *pool,
+									BMFace *f)
+{
+	BMIter bm_iter;
+	BMEdge *e;
+
+	if (edge_queue_tri_in_sphere(q, f)) {
+		/* Check each edge of the face */
+		BM_ITER_ELEM (e, &bm_iter, f, BM_EDGES_OF_FACE) {
+			long_edge_queue_edge_add(q, pool, e);
+		}
+	}
+
+	return TRUE;
+}
+
+static int short_edge_queue_face_add(EdgeQueue *q, BLI_mempool *pool,
+									 BMFace *f)
+{
+	BMIter bm_iter;
+	BMEdge *e;
+
+	if (edge_queue_tri_in_sphere(q, f)) {
+		/* Check each edge of the face */
+		BM_ITER_ELEM (e, &bm_iter, f, BM_EDGES_OF_FACE) {
+			short_edge_queue_edge_add(q, pool, e);
+		}
+	}
+
+	return TRUE;
+}
+
+/* Create a priority queue containing vertex pairs connected by a long
+ * edge as defined by PBVH.bm_max_edge_len.
+ *
+ * Only nodes marked for topology update are checked, and in those
+ * nodes only edges used by a face intersecting the (center, radius)
+ * sphere are checked.
+ *
+ * The highest priority (lowest number) is given to the longest edge.
+ */
+static void long_edge_queue_create(EdgeQueue *q, BLI_mempool *pool,
+								   PBVH *bvh, const float center[3],
+								   float radius)
+{
+	int n;
+
+	q->heap = BLI_heap_new();
+	q->center = center;
+	q->radius_squared = radius * radius;
+	q->limit_len_squared = bvh->bm_max_edge_len * bvh->bm_max_edge_len;
+
+	for (n = 0; n < bvh->totnode; n++) {
+		PBVHNode *node = &bvh->nodes[n];
+
+		/* Check leaf nodes marked for topology update */
+		if ((node->flag & PBVH_Leaf) &&
+			(node->flag & PBVH_UpdateTopology))
+		{
+			GHashIterator gh_iter;
+
+			/* Check each face */
+			GHASH_ITER (gh_iter, node->bm_faces) {
+				BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+
+				long_edge_queue_face_add(q, pool, f);
+			}
+		}
+	}
+}
+
+/* Create a priority queue containing vertex pairs connected by a
+ * short edge as defined by PBVH.bm_min_edge_len.
+ *
+ * Only nodes marked for topology update are checked, and in those
+ * nodes only edges used by a face intersecting the (center, radius)
+ * sphere are checked.
+ *
+ * The highest priority (lowest number) is given to the shortest edge.
+ */
+static void short_edge_queue_create(EdgeQueue *q, BLI_mempool *pool,
+									PBVH *bvh, const float center[3],
+									float radius)
+{
+	int n;
+
+	q->heap = BLI_heap_new();
+	q->center = center;
+	q->radius_squared = radius * radius;
+	q->limit_len_squared = bvh->bm_min_edge_len * bvh->bm_min_edge_len;
+
+	for (n = 0; n < bvh->totnode; n++) {
+		PBVHNode *node = &bvh->nodes[n];
+
+		/* Check leaf nodes marked for topology update */
+		if ((node->flag & PBVH_Leaf) &&
+			(node->flag & PBVH_UpdateTopology))
+		{
+			GHashIterator gh_iter;
+
+			/* Check each face */
+			GHASH_ITER (gh_iter, node->bm_faces) {
+				BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+
+				short_edge_queue_face_add(q, pool, f);
+			}
+		}
+	}
+}
+
+/*************************** Topology update **************************/
+
+static void pbvh_bmesh_split_edge(PBVH *bvh, EdgeQueue *q, BLI_mempool *pool,
+								  BMEdge *e, BLI_Buffer *edge_faces)
+{
+	BMVert *v_new;
+	float mid[3];
+	int i, node_index;
+
+	/* Get all faces adjacent to the edge */
+	pbvh_bmesh_edge_faces(edge_faces, e);
+
+	/* Create a new vertex in current node at the edge's midpoint */
+	mid_v3_v3v3(mid, e->v1->co, e->v2->co);
+
+	node_index = GET_INT_FROM_POINTER(BLI_ghash_lookup(bvh->bm_vert_to_node,
+													   e->v1));
+	v_new = pbvh_bmesh_vert_create(bvh, node_index, mid, e->v1);
+
+	/* For each face, add two new triangles and delete the original */
+	for (i = 0; i < edge_faces->count; i++) {
+		BMFace *f_adj = BLI_buffer_at(edge_faces, BMFace *, i);
+		BMFace *f_new;
+		BMVert *opp, *v1, *v2;
+		void *nip;
+		int ni;
+
+		BLI_assert(f_adj->len == 3);
+		nip = BLI_ghash_lookup(bvh->bm_face_to_node, f_adj);
+		ni = GET_INT_FROM_POINTER(nip);
+
+		/* Ensure node gets redrawn */
+		bvh->nodes[ni].flag |= PBVH_UpdateDrawBuffers;
+
+		/* Find the vertex not in the edge */
+		opp = bm_triangle_other_vert_find(f_adj, e->v1, e->v2);
+
+		/* Get e->v1 and e->v2 in the order they appear in the
+		 * existing face so that the new faces' winding orders
+		 * match */
+		v1 = e->v1;
+		v2 = e->v2;
+		if (bm_face_edge_backwards(f_adj, e))
+			SWAP(BMVert *, v1, v2);
+
+		if (ni != node_index && i == 0)
+			pbvh_bmesh_vert_ownership_transfer(bvh, &bvh->nodes[ni], v_new);
+
+		/* Create two new faces */
+		f_new = pbvh_bmesh_face_create(bvh, ni, v1, v_new, opp, f_adj);
+		long_edge_queue_face_add(q, pool, f_new);
+		f_new = pbvh_bmesh_face_create(bvh, ni, v_new, v2, opp, f_adj);
+		long_edge_queue_face_add(q, pool, f_new);
+
+		/* Delete original */
+		pbvh_bmesh_face_remove(bvh, f_adj);
+		BM_face_kill(bvh->bm, f_adj);
+
+		/* Ensure new vertex is in the node */
+		if (!BLI_ghash_haskey(bvh->nodes[ni].bm_unique_verts, v_new) &&
+			!BLI_ghash_haskey(bvh->nodes[ni].bm_other_verts, v_new))
+		{
+			BLI_ghash_insert(bvh->nodes[ni].bm_other_verts, v_new, NULL);
+		}
+
+		if (BM_vert_edge_count(opp) >= 9) {
+			BMIter bm_iter;
+			BMEdge *e2;
+
+			BM_ITER_ELEM (e2, &bm_iter, opp, BM_EDGES_OF_VERT) {
+				long_edge_queue_edge_add(q, pool, e2);
+			}
+		}
+	}
+
+	BM_edge_kill(bvh->bm, e);
+}
+
+static int pbvh_bmesh_subdivide_long_edges(PBVH *bvh, EdgeQueue *q,
+										   BLI_mempool *pool,
+										   BLI_Buffer *edge_faces)
+{
+	int any_subdivided = FALSE;
+
+	while (!BLI_heap_is_empty(q->heap)) {
+		BMVert **pair = BLI_heap_popmin(q->heap);
+		BMEdge *e;
+
+		/* Check that the edge still exists */
+		if (!(e = BM_edge_exists(pair[0], pair[1]))) {
+			BLI_mempool_free(pool, pair);
+			continue;
+		}
+
+		BLI_mempool_free(pool, pair);
+		pair = NULL;
+
+		/* 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
+		 * associated vertices. */
+		if (!BLI_ghash_haskey(bvh->bm_vert_to_node, e->v1) ||
+			!BLI_ghash_haskey(bvh->bm_vert_to_node, e->v2))
+		{
+			continue;
+		}
+
+		if (BM_edge_calc_squared_length(e) <= q->limit_len_squared)
+			continue;
+
+		any_subdivided = TRUE;
+
+		pbvh_bmesh_split_edge(bvh, q, pool, e, edge_faces);
+	}
+
+	return any_subdivided;
+}
+
+static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, BMVert *v1,
+									 BMVert *v2, GHash *deleted_verts,
+									 BLI_Buffer *edge_faces,
+									 BLI_Buffer *deleted_faces)
+{
+	BMIter bm_iter;
+	BMFace *f;
+	int i;
+
+	/* Get all faces adjacent to the edge */
+	pbvh_bmesh_edge_faces(edge_faces, e);
+
+	/* Remove the merge vertex from the PBVH */
+	pbvh_bmesh_vert_remove(bvh, v2);
+
+	/* Remove all faces adjacent to the edge */
+	for (i = 0; i < edge_faces->count; i++) {
+		BMFace *f_adj = BLI_buffer_at(edge_faces, BMFace *, i);
+
+		pbvh_bmesh_face_remove(bvh, f_adj);
+		BM_face_kill(bvh->bm, f_adj);
+	}
+
+	/* Kill the edge */
+	BLI_assert(BM_edge_face_count(e) == 0);
+	BM_edge_kill(bvh->bm, e);
+
+	/* For all remaining faces of v2, create a new face that is the
+	   same except it uses v1 instead of v2 */
+	/* Note: this could be done with BM_vert_splice(), but that
+	 * requires handling other issues like duplicate edges, so doesn't
+	 * really buy anything. */
+	deleted_faces->count = 0;
+	BM_ITER_ELEM (f, &bm_iter, v2, BM_FACES_OF_VERT) {
+		BMVert *v[3];
+		BMFace *existing_face;
+		PBVHNode *n;
+		int ni;
+
+		/* Get vertices, replace use of v2 with v1 */
+		BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3);
+		for (i = 0; i < 3; i++) {
+			if (v[i] == v2)
+				v[i] = v1;
+		}
+
+		/* Check if a face using these vertices already exists. If so,
+		 * skip adding this face and mark the existing one for
+		 * deletion as well. Prevents extraneous "flaps" from being
+		 * created. */
+		if (BM_face_exists(v, 3, &existing_face)) {
+			BLI_assert(existing_face);
+			BLI_buffer_append(deleted_faces, BMFace *, existing_face);
+		}
+		else {
+			n = pbvh_bmesh_node_lookup(bvh, bvh->bm_face_to_node, f);
+			ni = n - bvh->nodes;
+			pbvh_bmesh_face_create(bvh, ni, v[0], v[1], v[2], f);
+
+			/* Ensure that v1 is in the new face's node */
+			if (!BLI_ghash_haskey(n->bm_unique_verts, v1) &&
+				!BLI_ghash_haskey(n->bm_other_verts, v1)) {
+				BLI_ghash_insert(n->bm_other_verts, v1, NULL);
+			}
+		}
+
+		BLI_buffer_append(deleted_faces, BMFace *, f);
+	}
+
+	/* Delete the tagged faces */
+	for (i = 0; i < deleted_faces->count; i++) {
+		BMFace *f_del = BLI_buffer_at(deleted_faces, BMFace *, i);
+		BMVert *v[3];
+		int j;
+
+		BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f_del, (void **)v, 3);
+
+		/* 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[j] != v2 && BM_vert_face_count(v[j]) == 0) {
+				BLI_ghash_insert(deleted_verts, v[j], NULL);
+				pbvh_bmesh_vert_remove(bvh, v[j]);
+			}
+			else {
+				v[j] = NULL;
+			}
+		}
+
+		/* Remove the face */
+		pbvh_bmesh_face_remove(bvh, f_del);
+		BM_face_kill(bvh->bm, f_del);
+
+		/* Delete unused vertices */
+		for (j = 0; j < 3; j++) {
+			if (v[j]) {
+				BM_log_vert_removed(bvh->bm, bvh->bm_log, v[j]);
+				BM_vert_kill(bvh->bm, v[j]);
+			}
+		}
+	}
+
+	/* Move v1 to the midpoint of v1 and v2 */
+	BM_log_vert_before_modified(bvh->bm, bvh->bm_log, v1);
+	mid_v3_v3v3(v1->co, v1->co, v2->co);
+
+	/* Delete v2 */
+	BLI_assert(BM_vert_face_count(v2) == 0);
+	BLI_ghash_insert(deleted_verts, v2, NULL);
+	BM_log_vert_removed(bvh->bm, bvh->bm_log, v2);
+	BM_vert_kill(bvh->bm, v2);
+}
+
+static int pbvh_bmesh_collapse_short_edges(PBVH *bvh, EdgeQueue *q,
+										   BLI_mempool *pool,
+										   BLI_Buffer *edge_faces,
+										   BLI_Buffer *deleted_faces)
+{
+	float min_len_squared = bvh->bm_min_edge_len * bvh->bm_min_edge_len;
+	GHash *deleted_verts;
+	int any_collapsed = FALSE;
+
+	deleted_verts = BLI_ghash_ptr_new("deleted_verts");
+
+	while (!BLI_heap_is_empty(q->heap)) {
+		BMVert **pair = BLI_heap_popmin(q->heap);
+		BMEdge *e;
+		BMVert *v1, *v2;
+
+		v1 = pair[0];
+		v2 = pair[1];
+		BLI_mempool_free(pool, pair);
+		pair = NULL;
+
+		/* Check that the vertices/edge still exist */
+		if (BLI_ghash_haskey(deleted_verts, v1) ||
+			BLI_ghash_haskey(deleted_verts, v2) ||
+			!(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
+		 * associated vertices. */
+		if (!BLI_ghash_haskey(bvh->bm_vert_to_node, e->v1) ||
+			!BLI_ghash_haskey(bvh->bm_vert_to_node, e->v2))
+		{
+			continue;
+		}
+
+		if (BM_edge_calc_squared_length(e) >= min_len_squared)
+			continue;
+
+		any_collapsed = TRUE;
+
+		pbvh_bmesh_collapse_edge(bvh, e, v1, v2,
+								 deleted_verts, edge_faces,
+								 deleted_faces);
+	}
+
+	BLI_ghash_free(deleted_verts, NULL, NULL);
+
+	return any_collapsed;
+}
+
+/************************* Called from pbvh.c *************************/
+
+int pbvh_bmesh_node_raycast(PBVHNode *node, const float ray_start[3],
+							const float ray_normal[3], float *dist,
+							int use_original)
+{
+	GHashIterator gh_iter;
+	int hit = 0;
+
+	if (use_original && node->bm_tot_ortri) {
+		int i;
+		for (i = 0; i < node->bm_tot_ortri; i++) {
+			const int *t = node->bm_ortri[i];
+			hit |= ray_face_intersection(ray_start, ray_normal,
+										 node->bm_orco[t[0]],
+										 node->bm_orco[t[1]],
+										 node->bm_orco[t[2]],
+										 NULL, dist);
+		}
+	}
+	else {
+		GHASH_ITER (gh_iter, node->bm_faces) {
+			BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+
+			BLI_assert(f->len == 3);
+			if (f->len == 3) {
+				BMVert *v[3];
+
+				BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3);
+				hit |= ray_face_intersection(ray_start, ray_normal,
+											 v[0]->co,
+											 v[1]->co,
+											 v[2]->co,
+											 NULL, dist);
+			}
+		}
+	}
+
+	return hit;
+}
+
+void pbvh_bmesh_normals_update(PBVHNode **nodes, int totnode)
+{
+	int n;
+
+	for (n = 0; n < totnode; n++) {
+		PBVHNode *node = nodes[n];
+		GHashIterator gh_iter;
+
+		GHASH_ITER (gh_iter, node->bm_faces) {
+			BM_face_normal_update(BLI_ghashIterator_getKey(&gh_iter));
+		}
+		GHASH_ITER (gh_iter, node->bm_unique_verts) {
+			BM_vert_normal_update(BLI_ghashIterator_getKey(&gh_iter));
+		}
+	}
+}
+
+/***************************** Public API *****************************/
+
+/* Build a PBVH from a BMesh */
+void BLI_pbvh_build_bmesh(PBVH *bvh, BMesh *bm, int smooth_shading,
+						  BMLog *log)
+{
+	BMIter iter;
+	BMFace *f;
+	PBVHNode *n;
+	int node_index = 0;
+
+	bvh->bm = bm;
+
+	BLI_pbvh_bmesh_detail_size_set(bvh, 0.75);
+
+	bvh->type = PBVH_BMESH;
+	bvh->bm_face_to_node = BLI_ghash_ptr_new("bm_face_to_node");
+	bvh->bm_vert_to_node = BLI_ghash_ptr_new("bm_vert_to_node");
+	bvh->bm_log = log;
+
+	/* TODO: choose leaf limit better */
+	bvh->leaf_limit = 100;
+
+	if (smooth_shading)
+		bvh->flags |= PBVH_DYNTOPO_SMOOTH_SHADING;
+
+	/* Start with all faces in the root node */
+	n = bvh->nodes = MEM_callocN(sizeof(PBVHNode), "PBVHNode");
+	bvh->totnode = 1;
+	n->flag = PBVH_Leaf;
+	n->bm_faces = BLI_ghash_ptr_new("bm_faces");
+	BM_ITER_MESH (f, &iter, bvh->bm, BM_FACES_OF_MESH) {
+		BLI_ghash_insert(n->bm_faces, f, NULL);
+	}
+
+	/* 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);
+}
+
+/* Collapse short edges, subdivide long edges */
+int BLI_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode,
+								   const float center[3], float radius)
+{
+	BLI_buffer_declare(BMFace*, edge_faces, 8);
+	BLI_buffer_declare(BMFace*, deleted_faces, 32);
+	int modified = FALSE;
+	int n;
+
+	if (mode & PBVH_Collapse) {
+		EdgeQueue q;
+		BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert) * 2,
+													 128, 128, 0);
+		short_edge_queue_create(&q, queue_pool, bvh, center, radius);
+		pbvh_bmesh_collapse_short_edges(bvh, &q, queue_pool, &edge_faces,
+										&deleted_faces);
+		BLI_heap_free(q.heap, NULL);
+		BLI_mempool_destroy(queue_pool);
+	}
+
+	if (mode & PBVH_Subdivide) {
+		EdgeQueue q;
+		BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert) * 2,
+													 128, 128, 0);
+		long_edge_queue_create(&q, queue_pool, bvh, center, radius);
+		pbvh_bmesh_subdivide_long_edges(bvh, &q, queue_pool, &edge_faces);
+		BLI_heap_free(q.heap, NULL);
+		BLI_mempool_destroy(queue_pool);
+	}
+	
+	/* Unmark nodes */
+	for (n = 0; n < bvh->totnode; n++) {
+		PBVHNode *node = &bvh->nodes[n];
+
+		if (node->flag & PBVH_Leaf &&
+			node->flag & PBVH_UpdateTopology)
+		{
+			node->flag &= ~PBVH_UpdateTopology;
+		}
+	}
+	BLI_buffer_free(&edge_faces);
+	BLI_buffer_free(&deleted_faces);
+
+	return modified;
+}
+
+/* In order to perform operations on the original node coordinates
+ * (such as raycast), store the node's triangles and vertices.*/
+void BLI_pbvh_bmesh_node_save_orig(PBVHNode *node)
+{
+	GHashIterator gh_iter;
+	int i, totvert, tottri;
+
+	/* Skip if original coords/triangles are already saved */
+	if (node->bm_orco)
+		return;
+
+	totvert = (BLI_ghash_size(node->bm_unique_verts) +
+			   BLI_ghash_size(node->bm_other_verts));
+
+	tottri = BLI_ghash_size(node->bm_faces);
+
+	node->bm_orco = MEM_mallocN(sizeof(*node->bm_orco) * totvert, AT);
+	node->bm_ortri = MEM_mallocN(sizeof(*node->bm_ortri) * tottri, AT);
+
+	/* Copy out the vertices and assign a temporary index */
+	i = 0;
+	GHASH_ITER (gh_iter, node->bm_unique_verts) {
+		BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+		copy_v3_v3(node->bm_orco[i], v->co);
+		BM_elem_index_set(v, i); /* set_dirty! */
+		i++;
+	}
+	GHASH_ITER (gh_iter, node->bm_other_verts) {
+		BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+		copy_v3_v3(node->bm_orco[i], v->co);
+		BM_elem_index_set(v, i); /* set_dirty! */
+		i++;
+	}
+
+	/* Copy the triangles */
+	i = 0;
+	GHASH_ITER (gh_iter, node->bm_faces) {
+		BMIter bm_iter;
+		BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+		BMVert *v;
+		int j = 0;
+
+		BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) {
+			node->bm_ortri[i][j] = BM_elem_index_get(v);
+			j++;
+		}
+		i++;
+	}
+	node->bm_tot_ortri = i;
+}
+
+void BLI_pbvh_bmesh_after_stroke(PBVH *bvh)
+{
+	int i;
+	for (i = 0; i < bvh->totnode; i++) {
+		PBVHNode *n = &bvh->nodes[i];
+		if (n->flag & PBVH_Leaf) {
+			/* Free orco/ortri data */
+			pbvh_bmesh_node_drop_orig(n);
+
+			/* Recursively split nodes that have gotten too many
+			 * elements */
+			pbvh_bmesh_node_limit_ensure(bvh, i);
+		}
+	}
+}
+
+void BLI_pbvh_bmesh_detail_size_set(PBVH *bvh, float detail_size)
+{
+	bvh->bm_max_edge_len = detail_size;
+	bvh->bm_min_edge_len = bvh->bm_max_edge_len * 0.4;
+}
+
+void BLI_pbvh_node_mark_topology_update(PBVHNode *node)
+{
+	node->flag |= PBVH_UpdateTopology;
+}
+
+GHash *BLI_pbvh_bmesh_node_unique_verts(PBVHNode *node)
+{
+	return node->bm_unique_verts;
+}
+
+GHash *BLI_pbvh_bmesh_node_other_verts(PBVHNode *node)
+{
+	return node->bm_other_verts;
+}
+
+/****************************** Debugging *****************************/
+
+#if 0
+void bli_ghash_duplicate_key_check(GHash *gh)
+{
+	GHashIterator gh_iter1, gh_iter2;
+
+	GHASH_ITER (gh_iter1, gh) {
+		void *key1 = BLI_ghashIterator_getKey(&gh_iter1);
+		int dup = -1;
+
+		GHASH_ITER (gh_iter2, gh) {
+			void *key2 = BLI_ghashIterator_getKey(&gh_iter2);
+
+			if (key1 == key2) {
+				dup++;
+				if (dup > 0) {
+					BLI_assert(!"duplicate in hash");
+				}
+			}
+		}
+	}
+}
+
+void bmesh_print(BMesh *bm)
+{
+	BMIter iter, siter;
+	BMVert *v;
+	BMEdge *e;
+	BMFace *f;
+	BMLoop *l;
+
+	fprintf(stderr, "\nbm=%p, totvert=%d, totedge=%d, "
+			"totloop=%d, totface=%d\n",
+			bm, bm->totvert, bm->totedge,
+			bm->totloop, bm->totface);
+
+	fprintf(stderr, "vertices:\n");
+	BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) {
+		fprintf(stderr, "  %d co=(%.3f %.3f %.3f) oflag=%x\n",
+				BM_elem_index_get(v), v->co[0], v->co[1], v->co[2],
+				v->oflags[bm->stackdepth - 1].f);
+	}
+
+	fprintf(stderr, "edges:\n");
+	BM_ITER_MESH(e, &iter, bm, BM_EDGES_OF_MESH) {
+		fprintf(stderr, "  %d v1=%d, v2=%d, oflag=%x\n",
+				BM_elem_index_get(e),
+				BM_elem_index_get(e->v1),
+				BM_elem_index_get(e->v2),
+				e->oflags[bm->stackdepth - 1].f);
+	}
+
+	fprintf(stderr, "faces:\n");
+	BM_ITER_MESH(f, &iter, bm, BM_FACES_OF_MESH) {
+		fprintf(stderr, "  %d len=%d, oflag=%x\n",
+				BM_elem_index_get(f), f->len,
+				f->oflags[bm->stackdepth - 1].f);
+
+		fprintf(stderr, "    v: ");
+		BM_ITER_ELEM(v, &siter, f, BM_VERTS_OF_FACE) {
+			fprintf(stderr, "%d ", BM_elem_index_get(v));
+		}
+		fprintf(stderr, "\n");
+
+		fprintf(stderr, "    e: ");
+		BM_ITER_ELEM(e, &siter, f, BM_EDGES_OF_FACE) {
+			fprintf(stderr, "%d ", BM_elem_index_get(e));
+		}
+		fprintf(stderr, "\n");
+
+		fprintf(stderr, "    l: ");
+		BM_ITER_ELEM(l, &siter, f, BM_LOOPS_OF_FACE) {
+			fprintf(stderr, "%d(v=%d, e=%d) ",
+					BM_elem_index_get(l),
+					BM_elem_index_get(l->v),
+					BM_elem_index_get(l->e));
+		}
+		fprintf(stderr, "\n");
+	}	
+}
+
+void pbvh_bmesh_print(PBVH *bvh)
+{
+	GHashIterator gh_iter;
+	int n;
+
+	fprintf(stderr, "\npbvh=%p\n", bvh);
+	fprintf(stderr, "bm_face_to_node:\n");
+	GHASH_ITER (gh_iter, bvh->bm_face_to_node) {
+		fprintf(stderr, "  %d -> %d\n",
+				BM_elem_index_get((BMFace*)BLI_ghashIterator_getKey(&gh_iter)),
+				GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter)));
+	}
+
+	fprintf(stderr, "bm_vert_to_node:\n");
+	GHASH_ITER (gh_iter, bvh->bm_vert_to_node) {
+		fprintf(stderr, "  %d -> %d\n",
+				BM_elem_index_get((BMVert*)BLI_ghashIterator_getKey(&gh_iter)),
+				GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter)));
+	}
+
+	for (n = 0; n < bvh->totnode; n++) {
+		PBVHNode *node = &bvh->nodes[n];
+		if (!(node->flag & PBVH_Leaf))
+			continue;
+
+		fprintf(stderr, "node %d\n  faces:\n", n);
+		GHASH_ITER (gh_iter, node->bm_faces)
+			fprintf(stderr, "    %d\n",
+					BM_elem_index_get((BMFace*)BLI_ghashIterator_getKey(&gh_iter)));
+		fprintf(stderr, "  unique verts:\n");
+		GHASH_ITER (gh_iter, node->bm_unique_verts)
+			fprintf(stderr, "    %d\n",
+					BM_elem_index_get((BMVert*)BLI_ghashIterator_getKey(&gh_iter)));
+		fprintf(stderr, "  other verts:\n");
+		GHASH_ITER (gh_iter, node->bm_other_verts)
+			fprintf(stderr, "    %d\n",
+					BM_elem_index_get((BMVert*)BLI_ghashIterator_getKey(&gh_iter)));
+	}
+}
+
+void print_flag_factors(int flag)
+{
+	int i;
+	printf("flag=0x%x:\n", flag);
+	for (i = 0; i < 32; i++) {
+		if (flag & (1 << i)) {
+			printf("  %d (1 << %d)\n", 1 << i, i);
+		}
+	}
+}
+
+void pbvh_bmesh_verify(PBVH *bvh)
+{
+	GHashIterator gh_iter;
+	int i;
+
+	/* Check faces */
+	BLI_assert(bvh->bm->totface == BLI_ghash_size(bvh->bm_face_to_node));
+	GHASH_ITER (gh_iter, bvh->bm_face_to_node) {
+		BMIter bm_iter;
+		BMVert *v;
+		BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+		void *nip = BLI_ghashIterator_getValue(&gh_iter);
+		int ni = GET_INT_FROM_POINTER(nip);
+		PBVHNode *n = &bvh->nodes[ni];
+
+		/* Check that the face's node is a leaf */
+		BLI_assert(n->flag & PBVH_Leaf);
+
+		/* Check that the face's node knows it owns the face */
+		BLI_assert(BLI_ghash_haskey(n->bm_faces, f));
+
+		/* Check the face's vertices... */
+		BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) {
+			PBVHNode *nv;
+
+			/* Check that the vertex is in the node */
+			BLI_assert(BLI_ghash_haskey(n->bm_unique_verts, v) ^
+					   BLI_ghash_haskey(n->bm_other_verts, v));
+
+			/* Check that the vertex has a node owner */
+			nv = pbvh_bmesh_node_lookup(bvh, bvh->bm_vert_to_node, v);
+
+			/* Check that the vertex's node knows it owns the vert */
+			BLI_assert(BLI_ghash_haskey(nv->bm_unique_verts, v));
+
+			/* Check that the vertex isn't duplicated as an 'other' vert */
+			BLI_assert(!BLI_ghash_haskey(nv->bm_other_verts, v));
+		}
+	}
+
+	/* Check verts */
+	BLI_assert(bvh->bm->totvert == BLI_ghash_size(bvh->bm_vert_to_node));
+	GHASH_ITER (gh_iter, bvh->bm_vert_to_node) {
+		BMIter bm_iter;
+		BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+		BMFace *f;
+		void *nip = BLI_ghashIterator_getValue(&gh_iter);
+		int ni = GET_INT_FROM_POINTER(nip);
+		PBVHNode *n = &bvh->nodes[ni];
+		int found;
+
+		/* Check that the vert's node is a leaf */
+		BLI_assert(n->flag & PBVH_Leaf);
+
+		/* Check that the vert's node knows it owns the vert */
+		BLI_assert(BLI_ghash_haskey(n->bm_unique_verts, v));
+
+		/* Check that the vertex isn't duplicated as an 'other' vert */
+		BLI_assert(!BLI_ghash_haskey(n->bm_other_verts, v));
+
+		/* Check that the vert's node also contains one of the vert's
+		 * adjacent faces */
+		BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) {
+			if (BLI_ghash_lookup(bvh->bm_face_to_node, f) == nip) {
+				found = TRUE;
+				break;
+			}
+		}
+		BLI_assert(found);
+	}
+
+	/* Check that node elements are recorded in the top level */
+	for (i = 0; i < bvh->totnode; i++) {
+		PBVHNode *n = &bvh->nodes[i];
+		if (n->flag & PBVH_Leaf) {
+			/* Check for duplicate entries */
+			/* Slow */
+			#if 0
+			bli_ghash_duplicate_key_check(n->bm_faces);
+			bli_ghash_duplicate_key_check(n->bm_unique_verts);
+			bli_ghash_duplicate_key_check(n->bm_other_verts);
+			#endif
+
+			GHASH_ITER (gh_iter, n->bm_faces) {
+				BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+				void *nip = BLI_ghash_lookup(bvh->bm_face_to_node, f);
+				BLI_assert(BLI_ghash_haskey(bvh->bm_face_to_node, f));
+				BLI_assert(GET_INT_FROM_POINTER(nip) == (n - bvh->nodes));
+			}
+
+			GHASH_ITER (gh_iter, n->bm_unique_verts) {
+				BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+				void *nip = BLI_ghash_lookup(bvh->bm_vert_to_node, v);
+				BLI_assert(BLI_ghash_haskey(bvh->bm_vert_to_node, v));
+				BLI_assert(!BLI_ghash_haskey(n->bm_other_verts, v));
+				BLI_assert(GET_INT_FROM_POINTER(nip) == (n - bvh->nodes));
+			}
+
+			GHASH_ITER (gh_iter, n->bm_other_verts) {
+				BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+				BLI_assert(BLI_ghash_haskey(bvh->bm_vert_to_node, v));
+				BLI_assert(BM_vert_face_count(v) > 0);
+			}
+		}
+	}
+}
+
+#endif
diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h
index d3539245d11..d8365ce8006 100644
--- a/source/blender/blenkernel/intern/pbvh_intern.h
+++ b/source/blender/blenkernel/intern/pbvh_intern.h
@@ -31,6 +31,8 @@ typedef struct {
 	float bmin[3], bmax[3], bcentroid[3];
 } BBC;
 
+/* Note: this structure is getting large, might want to split it into
+ * union'd structs */
 struct PBVHNode {
 	/* Opaque handle for drawing code */
 	GPU_Buffers *draw_buffers;
@@ -86,7 +88,7 @@ struct PBVHNode {
 
 	/* Indicates whether this node is a leaf or not; also used for
 	 * marking various updates that need to be applied. */
-	PBVHNodeFlags flag : 8;
+	PBVHNodeFlags flag : 16;
 
 	/* Used for raycasting: how close bb is to the ray point. */
 	float tmin;
@@ -96,10 +98,25 @@ struct PBVHNode {
 
 	int proxy_count;
 	PBVHProxyNode *proxies;
+
+	/* Dyntopo */
+	GHash *bm_faces;
+	GHash *bm_unique_verts;
+	GHash *bm_other_verts;
+	float (*bm_orco)[3];
+	int (*bm_ortri)[3];
+	int bm_tot_ortri;
 };
 
+typedef enum {
+	PBVH_DYNTOPO_SMOOTH_SHADING = 1
+} PBVHFlags;
+
+typedef struct PBVHBMeshLog PBVHBMeshLog;
+
 struct PBVH {
 	PBVHType type;
+	PBVHFlags flags;
 
 	PBVHNode *nodes;
 	int node_mem_count, totnode;
@@ -136,6 +153,34 @@ struct PBVH {
 	int deformed;
 
 	int show_diffuse_color;
+
+	/* Dynamic topology */
+	BMesh *bm;
+	GHash *bm_face_to_node;
+	GHash *bm_vert_to_node;
+	float bm_max_edge_len;
+	float bm_min_edge_len;
+
+	struct BMLog *bm_log;
 };
 
+/* pbvh.c */
+void BB_reset(BB *bb);
+void BB_expand(BB *bb, const float co[3]);
+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);
+int 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 */
+int pbvh_bmesh_node_raycast(PBVHNode *node, const float ray_start[3],
+							const float ray_normal[3], float *dist,
+							int use_original);
+
+void pbvh_bmesh_normals_update(PBVHNode **nodes, int totnode);
+
 #endif
-- 
cgit v1.2.3


From 67d27db4a1ce276c394fd3fdfab221018d4240ce Mon Sep 17 00:00:00 2001
From: Nicholas Bishop 
Date: Sun, 30 Dec 2012 18:29:07 +0000
Subject: Add dynamic topology support to sculpt mode

* User documentation:
  wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.66/Dynamic_Topology_Sculpting

* Code review for this and the other dynamic-topology commits:
  https://codereview.appspot.com/6947064/
  Thanks to Sergey for doing code review!

* Add SCULPT_OT_dynamic_topology_toggle operator to enable or disable
  dynamic topology mode

* Most brushes need little modification for dynamic topology, but for
  some it won't work well and is disabled. This decision is made in
  sculpt_stroke_dynamic_topology().

* For brushes that need original data (e.g. grab brush) the topology
  is not updated during the stroke, but some changes to original
  vertex data is accessed were made since BMesh works a little
  differently from mesh/multires. This is abstracted with
  SculptOrigVertData and associated functions.

* Smooth brush gets yet another set of functions, for mesh and
  multires and dynamic topology and, separetely, masking

* For most brushes, the topology is updated during the stroke right
  before the regular brush action takes place. This is handled in
  sculpt_topology_update().

* Exiting sculpt mode also disables dynamic topology

* Sculpt undo works differently with BMesh. Since the contents of
  nodes in the PBVH do not remain static during a sculpt session, the
  SculptUndoNodes do not correspond with PBVHNodes if dynamic topology
  is enabled. Rather, each SculptUndoNode is associated with a
  BMLogEntry.

* Sculpt undo gets a few new cases: entering and exiting dynamic
  topology does an undo push of all mesh data. Symmetrize will
  similarly push a full copy of BMesh data, although it does so
  through the BMLog API.

* Undo and redo in dynamic-topology mode will do a full recalculation
  of the PBVH.

* Add some documentation to doc/sculpt.org. This could stand to be
  expanded a lot more, for now it mostly contains test cases for the
  undo system.

* Add SCULPT_OT_optimize operator to recalculate the BVH. The BVH gets
  less optimal more quickly with dynamic topology than regular
  sculpting. There is no doubt more clever stuff we can do to optimize
  it on the fly, but for now this gives the user a nicer way to
  recalculate it than toggling modes.
---
 source/blender/editors/sculpt_paint/sculpt.c       | 752 ++++++++++++++++++---
 .../blender/editors/sculpt_paint/sculpt_intern.h   |  25 +-
 source/blender/editors/sculpt_paint/sculpt_undo.c  | 236 ++++++-
 3 files changed, 920 insertions(+), 93 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 2f0d69bfd98..12843fde852 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -65,6 +65,7 @@
 #include "BKE_report.h"
 #include "BKE_lattice.h" /* for armature_deform_verts */
 #include "BKE_node.h"
+#include "BKE_object.h"
 #include "BKE_subsurf.h"
 
 #include "BIF_glutil.h"
@@ -86,6 +87,8 @@
 
 #include "GPU_buffers.h"
 
+#include "bmesh.h"
+
 #include 
 #include 
 #include 
@@ -98,8 +101,13 @@ void ED_sculpt_force_update(bContext *C)
 {
 	Object *ob = CTX_data_active_object(C);
 
-	if (ob && (ob->mode & OB_MODE_SCULPT))
+	if (ob && (ob->mode & OB_MODE_SCULPT)) {
 		multires_force_update(ob);
+
+		/* Set reorder=false so that saving the file doesn't reorder
+		 * the BMesh's elements */
+		sculptsession_bm_to_me(ob, FALSE);
+	}
 }
 
 float *ED_sculpt_get_last_stroke(struct Object *ob)
@@ -172,7 +180,8 @@ static int sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob)
 	Mesh *me = (Mesh *)ob->data;
 	MultiresModifierData *mmd = sculpt_multires_active(scene, ob);
 
-	if (mmd) return 0;
+	if (mmd || ob->sculpt->bm)
+		return 0;
 
 	/* non-locked shape keys could be handled in the same way as deformed mesh */
 	if ((ob->shapeflag & OB_SHAPE_LOCK) == 0 && me->key && ob->shapenr)
@@ -281,12 +290,130 @@ typedef struct StrokeCache {
 	rcti previous_r; /* previous redraw rectangle */
 } StrokeCache;
 
+/************** Access to original unmodified vertex data *************/
+
+typedef struct {
+	BMLog *bm_log;
+
+	SculptUndoNode *unode;
+	float (*coords)[3];
+	short (*normals)[3];
+	float *vmasks;
+
+	/* Original coordinate, normal, and mask */
+	const float *co;
+	float mask;
+	short no[3];
+} SculptOrigVertData;
+
+
+/* Initialize a SculptOrigVertData for accessing original vertex data;
+ * handles BMesh, mesh, and multires */
+static void sculpt_orig_vert_data_unode_init(SculptOrigVertData *data,
+											 Object *ob,
+											 SculptUndoNode *unode)
+{
+	SculptSession *ss = ob->sculpt;
+	BMesh *bm = ss->bm;
+
+	memset(data, 0, sizeof(*data));
+	data->unode = unode;
+
+	if (bm) {
+		data->bm_log = ss->bm_log;
+	}
+	else {
+		data->coords = data->unode->co;
+		data->normals = data->unode->no;
+		data->vmasks = data->unode->mask;
+	}
+}
+
+/* Initialize a SculptOrigVertData for accessing original vertex data;
+ * handles BMesh, mesh, and multires */
+static void sculpt_orig_vert_data_init(SculptOrigVertData *data,
+									   Object *ob,
+									   PBVHNode *node)
+{
+	SculptUndoNode *unode;
+	unode = sculpt_undo_push_node(ob, node, SCULPT_UNDO_COORDS);
+	sculpt_orig_vert_data_unode_init(data, ob, unode);
+									 
+}
+
+/* Update a SculptOrigVertData for a particular vertex from the PBVH
+ * iterator */
+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];
+		}
+		else {
+			orig_data->co = BM_log_original_vert_co(orig_data->bm_log, iter->bm_vert);
+		}
+
+		if (orig_data->normals) {
+			copy_v3_v3_short(orig_data->no, orig_data->normals[iter->i]);
+		}
+		else {
+			/* TODO: log doesn't store normals yet */
+			normal_float_to_short_v3(orig_data->no, iter->bm_vert->no);
+		}
+	}
+	else if (orig_data->unode->type == SCULPT_UNDO_MASK) {
+		if (orig_data->vmasks) {
+			orig_data->mask = orig_data->vmasks[iter->i];
+		}
+		else {
+			orig_data->mask = BM_log_original_mask(orig_data->bm_log, iter->bm_vert);
+		}
+	}
+}
+
+/**********************************************************************/
+
+/* Returns true if the stroke will use dynamic topology, false
+   otherwise.
+
+   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)
+{
+	return ((BLI_pbvh_type(ss->pbvh) == PBVH_BMESH) &&
+
+			(!ss->cache || (!ss->cache->alt_smooth)) &&
+
+			/* Requires mesh restore, which doesn't work with
+			 * dynamic-topology */
+			!(brush->flag & BRUSH_ANCHORED) &&
+			!(brush->flag & BRUSH_RESTORE_MESH) &&
+
+			(!ELEM6(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)));
+}
 
 /*** paint mesh ***/
 
-static void paint_mesh_restore_co(Sculpt *sd, SculptSession *ss)
+static void paint_mesh_restore_co(Sculpt *sd, Object *ob)
 {
+	SculptSession *ss = ob->sculpt;
 	StrokeCache *cache = ss->cache;
+	const Brush *brush = paint_brush(&sd->paint);
 	int i;
 
 	PBVHNode **nodes;
@@ -301,20 +428,27 @@ static void paint_mesh_restore_co(Sculpt *sd, SculptSession *ss)
 	#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
 	for (n = 0; n < totnode; n++) {
 		SculptUndoNode *unode;
-		
-		unode = sculpt_undo_get_node(nodes[n]);
+		SculptUndoType type = (brush->sculpt_tool == SCULPT_TOOL_MASK ?
+							   SCULPT_UNDO_MASK : SCULPT_UNDO_COORDS);
+
+		unode = sculpt_undo_push_node(ob, nodes[n], type);
 		if (unode) {
 			PBVHVertexIter vd;
+			SculptOrigVertData orig_data;
 
+			sculpt_orig_vert_data_unode_init(&orig_data, ob, unode);
+		
 			BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
 			{
-				if (unode->type == SCULPT_UNDO_COORDS) {
-					copy_v3_v3(vd.co, unode->co[vd.i]);
-					if (vd.no) copy_v3_v3_short(vd.no, unode->no[vd.i]);
-					else normal_short_to_float_v3(vd.fno, unode->no[vd.i]);
+				sculpt_orig_vert_data_update(&orig_data, &vd);
+
+				if (orig_data.unode->type == SCULPT_UNDO_COORDS) {
+					copy_v3_v3(vd.co, orig_data.co);
+					if (vd.no) copy_v3_v3_short(vd.no, orig_data.no);
+					else normal_short_to_float_v3(vd.fno, orig_data.no);
 				}
-				else if (unode->type == SCULPT_UNDO_MASK) {
-					*vd.mask = unode->mask[vd.i];
+				else if (orig_data.unode->type == SCULPT_UNDO_MASK) {
+					*vd.mask = orig_data.mask;
 				}
 				if (vd.mvert) vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 			}
@@ -405,7 +539,7 @@ static void sculpt_brush_test_init(SculptSession *ss, SculptBrushTest *test)
 	test->dist = 0.0f;   /* just for initialize */
 }
 
-static int sculpt_brush_test(SculptBrushTest *test, float co[3])
+static int sculpt_brush_test(SculptBrushTest *test, const float co[3])
 {
 	float distsq = len_squared_v3v3(co, test->location);
 
@@ -418,7 +552,7 @@ static int sculpt_brush_test(SculptBrushTest *test, float co[3])
 	}
 }
 
-static int sculpt_brush_test_sq(SculptBrushTest *test, float co[3])
+static int sculpt_brush_test_sq(SculptBrushTest *test, const float co[3])
 {
 	float distsq = len_squared_v3v3(co, test->location);
 
@@ -734,7 +868,8 @@ static float brush_strength(Sculpt *sd, StrokeCache *cache, float feather)
 }
 
 /* Return a multiplier for brush strength on a particular vertex. */
-static float tex_strength(SculptSession *ss, Brush *br, float point[3],
+static float tex_strength(SculptSession *ss, Brush *br,
+						  const float point[3],
                           const float len,
                           const float sculpt_normal[3],
                           const short vno[3],
@@ -926,6 +1061,11 @@ static void calc_area_normal(Sculpt *sd, Object *ob, float an[3], PBVHNode **nod
 	original = (paint_brush(&sd->paint)->sculpt_tool == SCULPT_TOOL_GRAB ?
 	            TRUE : ss->cache->original);
 
+	/* In general the original coords are not available with dynamic
+	 * topology */
+	if (ss->bm)
+		original = FALSE;
+
 	(void)sd; /* unused w/o openmp */
 	
 	zero_v3(an);
@@ -1210,6 +1350,81 @@ static float neighbor_average_mask(SculptSession *ss, unsigned vert)
 		return vmask[vert];
 }
 
+/* Same logic as neighbor_average(), but for bmesh rather than mesh */
+static void bmesh_neighbor_average(float avg[3], BMVert *v)
+{
+	int vfcount = BM_vert_face_count(v);
+
+	zero_v3(avg);
+		
+	/* Don't modify corner vertices */
+	if (vfcount > 1) {
+		BMIter iter;
+		BMFace *f;
+		int i, total = 0;
+
+		BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
+			BMLoop *l1 = BM_face_vert_share_loop(f, v);
+			BMLoop *l2 = BM_loop_other_vert_loop(l1, v);
+			BMVert *adj_v[3] = {
+				BM_edge_other_vert(l1->e, v),
+				v,
+				BM_edge_other_vert(l2->e, v)};
+			
+			for (i = 0; i < 3; i++) {
+				if (vfcount != 2 || BM_vert_face_count(adj_v[i]) <= 2) {
+					add_v3_v3(avg, adj_v[i]->co);
+					total++;
+				}
+			}
+		}
+
+		if (total > 0) {
+			mul_v3_fl(avg, 1.0f / total);
+			return;
+		}
+	}
+
+	copy_v3_v3(avg, v->co);
+}
+
+/* Same logic as neighbor_average_mask(), but for bmesh rather than mesh */
+static float bmesh_neighbor_average_mask(BMesh *bm, BMVert *v)
+{
+	BMIter iter;
+	BMFace *f;
+	float avg = 0;
+	int i, total = 0;
+
+	BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
+		BMLoop *l1 = BM_face_vert_share_loop(f, v);
+		BMLoop *l2 = BM_loop_other_vert_loop(l1, v);
+		BMVert *adj_v[3] = {
+			BM_edge_other_vert(l1->e, v),
+			v,
+			BM_edge_other_vert(l2->e, v)};
+			
+		for (i = 0; i < 3; i++) {
+			BMVert *v2 = adj_v[i];
+			float *vmask = CustomData_bmesh_get(&bm->vdata,
+												v2->head.data,
+												CD_PAINT_MASK);
+			avg += (*vmask);
+			total++;
+		}
+	}
+
+	if (total > 0) {
+		return avg / (float)total;
+	}
+	else {
+		float *vmask = CustomData_bmesh_get(&bm->vdata,
+											v->head.data,
+											CD_PAINT_MASK);
+		return (*vmask);
+	}
+}
+
 static void do_mesh_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node, float bstrength, int smooth_mask)
 {
 	Brush *brush = paint_brush(&sd->paint);
@@ -1251,6 +1466,47 @@ static void do_mesh_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node,
 	BLI_pbvh_vertex_iter_end;
 }
 
+static void do_bmesh_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node, float bstrength, int smooth_mask)
+{
+	Brush *brush = paint_brush(&sd->paint);
+	PBVHVertexIter vd;
+	SculptBrushTest test;
+	
+	CLAMP(bstrength, 0.0f, 1.0f);
+
+	sculpt_brush_test_init(ss, &test);
+
+	BLI_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
+	{
+		if (sculpt_brush_test(&test, vd.co)) {
+			const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist,
+			                                            ss->cache->view_normal, 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;
+				val *= fade * bstrength;
+				*vd.mask += val;
+				CLAMP(*vd.mask, 0, 1);
+			}
+			else {
+				float avg[3], val[3];
+
+				bmesh_neighbor_average(avg, vd.bm_vert);
+				sub_v3_v3v3(val, avg, vd.co);
+				mul_v3_fl(val, fade);
+
+				add_v3_v3(val, vd.co);
+
+				sculpt_clip(sd, ss, vd.co, val);
+			}
+
+			if (vd.mvert)
+				vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+		}
+	}
+	BLI_pbvh_vertex_iter_end;
+}
+
 static void do_multires_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node,
                                      float bstrength, int smooth_mask)
 {
@@ -1433,6 +1689,9 @@ static void smooth(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode,
 					do_mesh_smooth_brush(sd, ss, nodes[n], strength,
 					                     smooth_mask);
 					break;
+				case PBVH_BMESH:
+					do_bmesh_smooth_brush(sd, ss, nodes[n], strength, smooth_mask);
+					break;
 			}
 		}
 
@@ -1659,15 +1918,11 @@ static void do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
 	#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
 	for (n = 0; n < totnode; n++) {
 		PBVHVertexIter vd;
-		SculptUndoNode *unode;
 		SculptBrushTest test;
-		float (*origco)[3];
-		short (*origno)[3];
+		SculptOrigVertData orig_data;
 		float (*proxy)[3];
 
-		unode =  sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS);
-		origco = unode->co;
-		origno = unode->no;
+		sculpt_orig_vert_data_init(&orig_data, ob, nodes[n]);
 
 		proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
 
@@ -1675,10 +1930,15 @@ static void do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
 
 		BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
 		{
-			if (sculpt_brush_test(&test, origco[vd.i])) {
-				const float fade = bstrength * tex_strength(ss, brush, origco[vd.i], test.dist,
-				                                            ss->cache->sculpt_normal_symm, origno[vd.i],
-				                                            NULL, vd.mask ? *vd.mask : 0.0f);
+			sculpt_orig_vert_data_update(&orig_data, &vd);
+
+			if (sculpt_brush_test(&test, orig_data.co)) {
+				const float fade = bstrength * tex_strength(ss, brush,
+															orig_data.co,
+															test.dist,
+				                                            ss->cache->sculpt_normal_symm,
+															orig_data.no,
+															NULL, vd.mask ? *vd.mask : 0.0f);
 
 				mul_v3_v3fl(proxy[vd.i], grab_delta, fade);
 
@@ -1797,15 +2057,11 @@ static void do_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
 	#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
 	for (n = 0; n < totnode; n++) {
 		PBVHVertexIter vd;
-		SculptUndoNode *unode;
 		SculptBrushTest test;
-		float (*origco)[3];
-		short (*origno)[3];
+		SculptOrigVertData orig_data;
 		float (*proxy)[3];
 
-		unode =  sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS);
-		origco = unode->co;
-		origno = unode->no;
+		sculpt_orig_vert_data_init(&orig_data, ob, nodes[n]);
 
 		proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
 
@@ -1813,10 +2069,15 @@ static void do_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
 
 		BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
 		{
-			if (sculpt_brush_test(&test, origco[vd.i])) {
-				const float fade = bstrength * tex_strength(ss, brush, origco[vd.i], test.dist,
+			sculpt_orig_vert_data_update(&orig_data, &vd);
+
+			if (sculpt_brush_test(&test, orig_data.co)) {
+				const float fade = bstrength * tex_strength(ss, brush,
+															orig_data.co,
+															test.dist,
 				                                            ss->cache->sculpt_normal_symm,
-				                                            origno[vd.i], NULL, vd.mask ? *vd.mask : 0.0f);
+				                                            orig_data.no,
+															NULL, vd.mask ? *vd.mask : 0.0f);
 
 				mul_v3_v3fl(proxy[vd.i], cono, fade);
 
@@ -1850,15 +2111,11 @@ static void do_rotate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
 	#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
 	for (n = 0; n < totnode; n++) {
 		PBVHVertexIter vd;
-		SculptUndoNode *unode;
 		SculptBrushTest test;
-		float (*origco)[3];
-		short (*origno)[3];
+		SculptOrigVertData orig_data;
 		float (*proxy)[3];
 
-		unode =  sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS);
-		origco = unode->co;
-		origno = unode->no;
+		sculpt_orig_vert_data_init(&orig_data, ob, nodes[n]);
 
 		proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
 
@@ -1866,13 +2123,18 @@ static void do_rotate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
 
 		BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
 		{
-			if (sculpt_brush_test(&test, origco[vd.i])) {
-				const float fade = bstrength * tex_strength(ss, brush, origco[vd.i], test.dist,
+			sculpt_orig_vert_data_update(&orig_data, &vd);
+
+			if (sculpt_brush_test(&test, orig_data.co)) {
+				const float fade = bstrength * tex_strength(ss, brush,
+				                                            orig_data.co,
+				                                            test.dist,
 				                                            ss->cache->sculpt_normal_symm,
-				                                            origno[vd.i], NULL, vd.mask ? *vd.mask : 0.0f);
+				                                            orig_data.no,
+		                                                    NULL, vd.mask ? *vd.mask : 0.0f);
 
-				mul_v3_m4v3(proxy[vd.i], m, origco[vd.i]);
-				sub_v3_v3(proxy[vd.i], origco[vd.i]);
+				mul_v3_m4v3(proxy[vd.i], m, orig_data.co);
+				sub_v3_v3(proxy[vd.i], orig_data.co);
 				mul_v3_fl(proxy[vd.i], fade);
 
 				if (vd.mvert)
@@ -1901,13 +2163,12 @@ static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
 	for (n = 0; n < totnode; n++) {
 		PBVHVertexIter vd;
 		SculptBrushTest test;
-		SculptUndoNode *unode;
-		float (*origco)[3], *layer_disp;
+		SculptOrigVertData orig_data;
+		float *layer_disp;
 		/* XXX: layer brush needs conversion to proxy but its more complicated */
 		/* proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; */
 		
-		unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS);
-		origco = unode->co;
+		sculpt_orig_vert_data_init(&orig_data, ob, nodes[n]);
 
 		#pragma omp critical
 		{
@@ -1918,7 +2179,9 @@ static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
 
 		BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
 		{
-			if (sculpt_brush_test(&test, origco[vd.i])) {
+			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,
 				                                            ss->cache->sculpt_normal_symm,
 				                                            vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f);
@@ -1940,7 +2203,7 @@ static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
 					add_v3_v3(val, ss->layer_co[index]);
 				}
 				else {
-					add_v3_v3(val, origco[vd.i]);
+					add_v3_v3(val, orig_data.co);
 				}
 
 				sculpt_clip(sd, ss, vd.co, val);
@@ -2081,7 +2344,7 @@ 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);
 
-		if (ss->cache->original) {
+		if (ss->cache->original && unode->co) {
 			BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
 			{
 				if (sculpt_brush_test_fast(&test, unode->co[vd.i])) {
@@ -2687,6 +2950,63 @@ void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3])
 	BKE_key_convert_from_vertcos(ob, kb, vertCos);
 }
 
+/* Note: we do the topology update before any brush actions to avoid
+ * issues with the proxies. The size of the proxy can't change, so
+ * topology must be updated first. */
+static void sculpt_topology_update(Sculpt *sd, Object *ob, Brush *brush)
+{
+	SculptSession *ss = ob->sculpt;
+	SculptSearchSphereData data;
+	PBVHNode **nodes = NULL;
+	float radius;
+	int n, totnode;
+
+	/* Build a list of all nodes that are potentially within the
+	 * brush's area of influence */
+	data.ss = ss;
+	data.sd = sd;
+
+	radius = ss->cache->radius * 1.25;
+
+	data.radius_squared = radius * radius;
+	data.original = ELEM4(brush->sculpt_tool,
+	                      SCULPT_TOOL_GRAB,
+	                      SCULPT_TOOL_ROTATE,
+	                      SCULPT_TOOL_THUMB,
+	                      SCULPT_TOOL_LAYER);
+
+	BLI_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, &totnode);
+
+	/* Only act if some verts are inside the brush area */
+	if (totnode) {
+		PBVHTopologyUpdateMode mode = PBVH_Subdivide;
+
+		if (sd->flags & SCULPT_DYNTOPO_COLLAPSE) {
+			mode |= PBVH_Collapse;
+		}
+
+		for (n = 0; n < totnode; n++) {
+			sculpt_undo_push_node(ob, nodes[n],
+			                      brush->sculpt_tool == SCULPT_TOOL_MASK ?
+			                      SCULPT_UNDO_MASK : SCULPT_UNDO_COORDS);
+			BLI_pbvh_node_mark_update(nodes[n]);
+
+			if (BLI_pbvh_type(ss->pbvh) == PBVH_BMESH) {
+				BLI_pbvh_node_mark_topology_update(nodes[n]);
+				BLI_pbvh_bmesh_node_save_orig(nodes[n]);
+			}
+		}
+
+		if (BLI_pbvh_type(ss->pbvh) == PBVH_BMESH) {
+			BLI_pbvh_bmesh_update_topology(ss->pbvh, mode,
+										   ss->cache->location,
+			                               ss->cache->radius);
+		}
+
+		MEM_freeN(nodes);
+	}
+}
+
 static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush)
 {
 	SculptSession *ss = ob->sculpt;
@@ -2834,7 +3154,7 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob)
 			int proxy_count;
 			float (*orco)[3];
 
-			if (use_orco)
+			if (use_orco && !ss->bm)
 				orco = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS)->co;
 
 			BLI_pbvh_node_get_proxies(nodes[n], &proxies, &proxy_count);
@@ -2844,8 +3164,15 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob)
 				float val[3];
 				int p;
 
-				if (use_orco)
-					copy_v3_v3(val, orco[vd.i]);
+				if (use_orco) {
+					if (ss->bm) {
+						copy_v3_v3(val,
+								   BM_log_original_vert_co(ss->bm_log,
+								   vd.bm_vert));
+					}
+					else
+						copy_v3_v3(val, orco[vd.i]);
+				}
 				else
 					copy_v3_v3(val, vd.co);
 
@@ -2977,7 +3304,10 @@ static void calc_brushdata_symm(Sculpt *sd, StrokeCache *cache, const char symm,
 	mul_m4_v3(cache->symm_rot_mat, cache->grab_delta_symmetry);
 }
 
+typedef void (*BrushActionFunc)(Sculpt *sd, Object *ob, Brush *brush);
+
 static void do_radial_symmetry(Sculpt *sd, Object *ob, Brush *brush,
+							   BrushActionFunc action,
                                const char symm, const int axis,
                                const float feather)
 {
@@ -2988,7 +3318,7 @@ static void do_radial_symmetry(Sculpt *sd, Object *ob, Brush *brush,
 		const float angle = 2 * M_PI * i / sd->radial_symm[axis - 'X'];
 		ss->cache->radial_symmetry_pass = i;
 		calc_brushdata_symm(sd, ss->cache, symm, axis, angle, feather);
-		do_brush_action(sd, ob, brush);
+		action(sd, ob, brush);
 	}
 }
 
@@ -3005,7 +3335,8 @@ static void sculpt_fix_noise_tear(Sculpt *sd, Object *ob)
 		multires_stitch_grids(ob);
 }
 
-static void do_symmetrical_brush_actions(Sculpt *sd, Object *ob)
+static void do_symmetrical_brush_actions(Sculpt *sd, Object *ob,
+										 BrushActionFunc action)
 {
 	Brush *brush = paint_brush(&sd->paint);
 	SculptSession *ss = ob->sculpt;
@@ -3016,7 +3347,6 @@ static void do_symmetrical_brush_actions(Sculpt *sd, Object *ob)
 	float feather = calc_symmetry_feather(sd, ss->cache);
 
 	cache->bstrength = brush_strength(sd, cache, feather);
-
 	cache->symmetry = symm;
 
 	/* symm is a bit combination of XYZ - 1 is mirror X; 2 is Y; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */ 
@@ -3026,23 +3356,13 @@ static void do_symmetrical_brush_actions(Sculpt *sd, Object *ob)
 			cache->radial_symmetry_pass = 0;
 
 			calc_brushdata_symm(sd, cache, i, 0, 0, feather);
-			do_brush_action(sd, ob, brush);
+			action(sd, ob, brush);
 
-			do_radial_symmetry(sd, ob, brush, i, 'X', feather);
-			do_radial_symmetry(sd, ob, brush, i, 'Y', feather);
-			do_radial_symmetry(sd, ob, brush, i, 'Z', feather);
+			do_radial_symmetry(sd, ob, brush, action, i, 'X', feather);
+			do_radial_symmetry(sd, ob, brush, action, i, 'Y', feather);
+			do_radial_symmetry(sd, ob, brush, action, i, 'Z', feather);
 		}
 	}
-
-	sculpt_combine_proxies(sd, ob);
-
-	/* hack to fix noise texture tearing mesh */
-	sculpt_fix_noise_tear(sd, ob);
-
-	if (ss->modifiers_active)
-		sculpt_flush_stroke_deform(sd, ob);
-
-	cache->first_time = 0;
 }
 
 static void sculpt_update_tex(const Scene *scene, Sculpt *sd, SculptSession *ss)
@@ -3405,8 +3725,9 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio
 	ED_view3d_global_to_vector(cache->vc->rv3d, cache->vc->rv3d->twmat[3], cache->true_view_normal);
 	/* Initialize layer brush displacements and persistent coords */
 	if (brush->sculpt_tool == SCULPT_TOOL_LAYER) {
-		/* not supported yet for multires */
-		if (!ss->multires && !ss->layer_co && (brush->flag & BRUSH_PERSISTENT)) {
+		/* not supported yet for multires or dynamic topology */
+		if (!ss->multires && !ss->bm && !ss->layer_co &&
+			(brush->flag & BRUSH_PERSISTENT)) {
 			if (!ss->layer_co)
 				ss->layer_co = MEM_mallocN(sizeof(float) * 3 * ss->totvert,
 				                           "sculpt mesh vertices copy");
@@ -3723,14 +4044,23 @@ static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin)
 	if (BLI_pbvh_node_get_tmin(node) < *tmin) {
 		SculptRaycastData *srd = data_v;
 		float (*origco)[3] = NULL;
+		int use_origco = FALSE;
 
 		if (srd->original && srd->ss->cache) {
-			/* intersect with coordinates from before we started stroke */
-			SculptUndoNode *unode = sculpt_undo_get_node(node);
-			origco = (unode) ? unode->co : NULL;
+			if (BLI_pbvh_type(srd->ss->pbvh) == PBVH_BMESH) {
+				use_origco = TRUE;
+			}
+			else {
+				/* intersect with coordinates from before we started stroke */
+				SculptUndoNode *unode = sculpt_undo_get_node(node);
+				origco = (unode) ? unode->co : NULL;
+				use_origco = origco ? TRUE : FALSE;
+			}
 		}
 
-		if (BLI_pbvh_node_raycast(srd->ss->pbvh, node, origco, srd->ray_start, srd->ray_normal, &srd->dist)) {
+		if (BLI_pbvh_node_raycast(srd->ss->pbvh, node, origco, use_origco,
+								  srd->ray_start, srd->ray_normal, &srd->dist))
+		{
 			srd->hit = 1;
 			*tmin = srd->dist;
 		}
@@ -3828,8 +4158,9 @@ static int sculpt_brush_stroke_init(bContext *C, wmOperator *op)
 	return 1;
 }
 
-static void sculpt_restore_mesh(Sculpt *sd, SculptSession *ss)
+static void sculpt_restore_mesh(Sculpt *sd, Object *ob)
 {
+	SculptSession *ss = ob->sculpt;
 	Brush *brush = paint_brush(&sd->paint);
 
 	/* Restore the mesh before continuing with anchored stroke */
@@ -3838,7 +4169,7 @@ static void sculpt_restore_mesh(Sculpt *sd, SculptSession *ss)
 	     BKE_brush_use_size_pressure(ss->cache->vc->scene, brush)) ||
 	    (brush->flag & BRUSH_RESTORE_MESH))
 	{
-		paint_mesh_restore_co(sd, ss);
+		paint_mesh_restore_co(sd, ob);
 	}
 }
 
@@ -3916,11 +4247,32 @@ static void sculpt_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
 	Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
 	Object *ob = CTX_data_active_object(C);
 	SculptSession *ss = ob->sculpt;
+	const Brush *brush = paint_brush(&sd->paint);
 	
 	sculpt_stroke_modifiers_check(C, ob);
 	sculpt_update_cache_variants(C, sd, ob, stroke, itemptr);
-	sculpt_restore_mesh(sd, ss);
-	do_symmetrical_brush_actions(sd, ob);
+	sculpt_restore_mesh(sd, ob);
+
+	BLI_pbvh_bmesh_detail_size_set(ss->pbvh,
+								   (ss->cache->radius /
+									(float)ss->cache->pixel_radius) *
+								   (float)sd->detail_size);
+
+	if (sculpt_stroke_dynamic_topology(ss, brush)) {
+		do_symmetrical_brush_actions(sd, ob, sculpt_topology_update);
+	}
+
+	do_symmetrical_brush_actions(sd, ob, do_brush_action);
+
+	sculpt_combine_proxies(sd, ob);
+
+	/* hack to fix noise texture tearing mesh */
+	sculpt_fix_noise_tear(sd, ob);
+
+	if (ss->modifiers_active)
+		sculpt_flush_stroke_deform(sd, ob);
+
+	ss->cache->first_time = FALSE;
 
 	/* Cleanup */
 	sculpt_flush_update(C);
@@ -3980,6 +4332,9 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
 		sculpt_undo_push_end();
 
 		BLI_pbvh_update(ss->pbvh, PBVH_UpdateOriginalBB, NULL);
+		
+		if (BLI_pbvh_type(ss->pbvh) == PBVH_BMESH)
+			BLI_pbvh_bmesh_after_stroke(ss->pbvh);
 
 		/* optimization: if there is locked key and active modifiers present in */
 		/* the stack, keyblock is updating at each step. otherwise we could update */
@@ -4054,7 +4409,7 @@ static int sculpt_brush_stroke_cancel(bContext *C, wmOperator *op)
 	Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
 
 	if (ss->cache) {
-		paint_mesh_restore_co(sd, ss);
+		paint_mesh_restore_co(sd, ob);
 	}
 
 	paint_stroke_cancel(C, op);
@@ -4136,6 +4491,222 @@ static void SCULPT_OT_set_persistent_base(wmOperatorType *ot)
 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
+/************************** Dynamic Topology **************************/
+
+static void sculpt_dynamic_topology_triangulate(BMesh *bm)
+{
+	BMO_op_callf(bm, BMO_FLAG_DEFAULTS, "triangulate faces=%af");
+}
+
+void sculpt_pbvh_clear(Object *ob)
+{
+	SculptSession *ss = ob->sculpt;
+	DerivedMesh *dm = ob->derivedFinal;
+
+	/* Clear out any existing DM and PBVH */
+	if (ss->pbvh)
+		BLI_pbvh_free(ss->pbvh);
+	ss->pbvh = NULL;
+	if (dm)
+		dm->getPBVH(NULL, dm);
+	BKE_object_free_display(ob);
+}
+
+void sculpt_update_after_dynamic_topology_toggle(bContext *C)
+{
+	Scene *scene = CTX_data_scene(C);
+	Object *ob = CTX_data_active_object(C);
+	Sculpt *sd = scene->toolsettings->sculpt;
+
+	/* Create the PBVH */
+	sculpt_update_mesh_elements(scene, sd, ob, FALSE, FALSE);
+	WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+}
+
+void sculpt_dynamic_topology_enable(bContext *C)
+{
+	Scene *scene = CTX_data_scene(C);
+	Object *ob = CTX_data_active_object(C);
+	SculptSession *ss = ob->sculpt;
+	Mesh *me = ob->data;
+
+	sculpt_pbvh_clear(ob);
+
+	ss->bm_smooth_shading = (scene->toolsettings->sculpt->flags &
+							 SCULPT_DYNTOPO_SMOOTH_SHADING);
+
+	/* Create triangles-only BMesh */
+	ss->bm = BM_mesh_create(&bm_mesh_allocsize_default);
+
+	BM_mesh_bm_from_me(ss->bm, me, TRUE, ob->shapenr);
+	sculpt_dynamic_topology_triangulate(ss->bm);
+	BM_data_layer_add(ss->bm, &ss->bm->vdata, CD_PAINT_MASK);
+	BM_mesh_normals_update(ss->bm, TRUE);
+
+	/* Enable dynamic topology */
+	me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
+	
+	/* Enable logging for undo/redo */
+	ss->bm_log = BM_log_create(ss->bm);
+
+	/* Refresh */
+	sculpt_update_after_dynamic_topology_toggle(C);
+}
+
+/* Free the sculpt BMesh and BMLog
+ *
+ * If 'unode' is given, the BMesh's data is copied out to the unode
+ * before the BMesh is deleted so that it can be restored from */
+void sculpt_dynamic_topology_disable(bContext *C,
+									 SculptUndoNode *unode)
+{
+	Object *ob = CTX_data_active_object(C);
+	SculptSession *ss = ob->sculpt;
+	Mesh *me = ob->data;
+
+	sculpt_pbvh_clear(ob);
+
+	if (unode) {
+		/* Free all existing custom data */
+		CustomData_free(&me->vdata, me->totvert);
+		CustomData_free(&me->edata, me->totedge);
+		CustomData_free(&me->fdata, me->totface);
+		CustomData_free(&me->ldata, me->totloop);
+		CustomData_free(&me->pdata, me->totpoly);
+
+		/* Copy over stored custom data */
+		me->totvert = unode->bm_enter_totvert;
+		me->totloop = unode->bm_enter_totloop;
+		me->totpoly = unode->bm_enter_totpoly;
+		me->totedge = unode->bm_enter_totedge;
+		me->totface = 0;
+		CustomData_copy(&unode->bm_enter_vdata, &me->vdata, CD_MASK_MESH,
+						CD_DUPLICATE, unode->bm_enter_totvert);
+		CustomData_copy(&unode->bm_enter_edata, &me->edata, CD_MASK_MESH,
+						CD_DUPLICATE, unode->bm_enter_totedge);
+		CustomData_copy(&unode->bm_enter_ldata, &me->ldata, CD_MASK_MESH,
+						CD_DUPLICATE, unode->bm_enter_totloop);
+		CustomData_copy(&unode->bm_enter_pdata, &me->pdata, CD_MASK_MESH,
+						CD_DUPLICATE, unode->bm_enter_totpoly);
+
+		mesh_update_customdata_pointers(me, FALSE);
+	} else {
+		sculptsession_bm_to_me(ob, TRUE);
+	}
+
+	BM_mesh_free(ss->bm);
+
+	/* Clear data */
+	me->flag &= ~ME_SCULPT_DYNAMIC_TOPOLOGY;
+	ss->bm = NULL;
+	BM_log_free(ss->bm_log);
+	ss->bm_log = NULL;
+
+	/* Refresh */
+	sculpt_update_after_dynamic_topology_toggle(C);
+}
+
+static int sculpt_dynamic_topology_toggle_exec(bContext *C, wmOperator *UNUSED(op))
+{
+	Object *ob = CTX_data_active_object(C);
+	SculptSession *ss = ob->sculpt;
+
+	if (ss->bm) {
+		sculpt_undo_push_begin("Dynamic topology disable");
+		sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_END);
+		sculpt_dynamic_topology_disable(C, NULL);
+	}
+	else {
+		sculpt_undo_push_begin("Dynamic topology enable");
+		sculpt_dynamic_topology_enable(C);
+		sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN);
+	}
+	sculpt_undo_push_end();
+
+	return OPERATOR_FINISHED;
+}
+
+static int sculpt_dynamic_topology_toggle_invoke(bContext *C, wmOperator *op,
+												 wmEvent *UNUSED(event))
+{
+	Object *ob = CTX_data_active_object(C);
+	Mesh *me = ob->data;
+	SculptSession *ss = ob->sculpt;
+	const char *msg = "Dynamic-topology sculpting will not preserve"
+		              "vertex colors, UVs, or other customdata";
+
+	if (!ss->bm) {
+		int i;
+
+		for (i = 0; i < CD_NUMTYPES; i++) {
+			if (!ELEM7(i, CD_MVERT, CD_MEDGE, CD_MFACE,
+					   CD_MLOOP, CD_MPOLY, CD_PAINT_MASK,
+					   CD_ORIGINDEX) &&
+				(CustomData_has_layer(&me->vdata, i) ||
+				 CustomData_has_layer(&me->edata, i) ||
+				 CustomData_has_layer(&me->fdata, i))) {
+				/* The mesh has customdata that will be lost, let the
+				 * user confirm this is OK */
+				return WM_operator_confirm_message(C, op, msg);
+			}
+		}
+	}
+
+	return sculpt_dynamic_topology_toggle_exec(C, op);
+}
+
+static void SCULPT_OT_dynamic_topology_toggle(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name = "Dynamic Topology Toggle";
+	ot->idname = "SCULPT_OT_dynamic_topology_toggle";
+	ot->description = "Dynamic topology alters the mesh topology while sculpting";
+	
+	/* api callbacks */
+	ot->invoke = sculpt_dynamic_topology_toggle_invoke;
+	ot->exec = sculpt_dynamic_topology_toggle_exec;
+	ot->poll = sculpt_mode_poll;
+	
+	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/************************* SCULPT_OT_optimize *************************/
+
+static int sculpt_optimize_exec(bContext *C, wmOperator *UNUSED(op))
+{
+	Object *ob = CTX_data_active_object(C);
+
+	sculpt_pbvh_clear(ob);
+	WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+	return OPERATOR_FINISHED;
+}
+
+static int sculpt_and_dynamic_topology_poll(bContext *C)
+{
+	Object *ob = CTX_data_active_object(C);
+
+	return sculpt_mode_poll(C) && ob->sculpt->bm;
+}
+
+/* The BVH gets less optimal more quickly with dynamic topology than
+ * regular sculpting. There is no doubt more clever stuff we can do to
+ * optimize it on the fly, but for now this gives the user a nicer way
+ * to recalculate it than toggling modes. */
+static void SCULPT_OT_optimize(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name = "Optimize";
+	ot->idname = "SCULPT_OT_optimize";
+	ot->description = "Recalculate the sculpt BVH to improve performance";
+	
+	/* api callbacks */
+	ot->exec = sculpt_optimize_exec;
+	ot->poll = sculpt_and_dynamic_topology_poll;
+	
+	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
 /**** Toggle operator for turning sculpt mode on or off ****/
 
 static void sculpt_init_session(Scene *scene, Object *ob)
@@ -4221,6 +4792,7 @@ static int sculpt_toggle_mode(bContext *C, wmOperator *UNUSED(op))
 	Scene *scene = CTX_data_scene(C);
 	ToolSettings *ts = CTX_data_tool_settings(C);
 	Object *ob = CTX_data_active_object(C);
+	Mesh *me = ob->data;
 	MultiresModifierData *mmd = sculpt_multires_active(scene, ob);
 	int flush_recalc = 0;
 
@@ -4233,9 +4805,16 @@ static int sculpt_toggle_mode(bContext *C, wmOperator *UNUSED(op))
 		if (mmd)
 			multires_force_update(ob);
 
-		if (flush_recalc)
+		if (flush_recalc || (ob->sculpt && ob->sculpt->bm))
 			DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 
+		if (me->flag & ME_SCULPT_DYNAMIC_TOPOLOGY) {
+			/* Dynamic topology must be disabled before exiting sculpt
+			 * mode to ensure the undo stack stays in a consistent
+			 * state */
+			sculpt_dynamic_topology_toggle_exec(C, NULL);
+		}
+
 		/* Leave sculptmode */
 		ob->mode &= ~OB_MODE_SCULPT;
 
@@ -4256,6 +4835,9 @@ static int sculpt_toggle_mode(bContext *C, wmOperator *UNUSED(op))
 			ts->sculpt->flags |= SCULPT_SYMM_X;
 		}
 
+		if (!ts->sculpt->detail_size)
+			ts->sculpt->detail_size = 30;
+
 		/* Create sculpt mode session data */
 		if (ob->sculpt)
 			free_sculptsession(ob);
@@ -4270,7 +4852,7 @@ static int sculpt_toggle_mode(bContext *C, wmOperator *UNUSED(op))
 		}
 
 		BKE_paint_init(&ts->sculpt->paint, PAINT_CURSOR_SCULPT);
-		
+
 		paint_cursor_start(C, sculpt_poll);
 	}
 
@@ -4298,4 +4880,6 @@ void ED_operatortypes_sculpt(void)
 	WM_operatortype_append(SCULPT_OT_brush_stroke);
 	WM_operatortype_append(SCULPT_OT_sculptmode_toggle);
 	WM_operatortype_append(SCULPT_OT_set_persistent_base);
+	WM_operatortype_append(SCULPT_OT_dynamic_topology_toggle);
+	WM_operatortype_append(SCULPT_OT_optimize);
 }
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index cfc908bf453..e56962a3964 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -49,6 +49,7 @@ struct Object;
 struct Scene;
 struct Sculpt;
 struct SculptStroke;
+struct SculptUndoNode;
 
 /* Interface */
 struct MultiresModifierData *sculpt_multires_active(struct Scene *scene, struct Object *ob);
@@ -67,12 +68,22 @@ void free_sculptsession_deformMats(struct SculptSession *ss);
 /* Stroke */
 int sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2]);
 
+/* Dynamic topology */
+void sculpt_pbvh_clear(Object *ob);
+void sculpt_update_after_dynamic_topology_toggle(bContext *C);
+void sculpt_dynamic_topology_enable(struct bContext *C);
+void sculpt_dynamic_topology_disable(struct bContext *C,
+									 struct SculptUndoNode *unode);
+
 /* Undo */
 
 typedef enum {
 	SCULPT_UNDO_COORDS,
 	SCULPT_UNDO_HIDDEN,
-	SCULPT_UNDO_MASK
+	SCULPT_UNDO_MASK,
+	SCULPT_UNDO_DYNTOPO_BEGIN,
+	SCULPT_UNDO_DYNTOPO_END,
+	SCULPT_UNDO_DYNTOPO_SYMMETRIZE,
 } SculptUndoType;
 
 typedef struct SculptUndoNode {
@@ -101,6 +112,18 @@ typedef struct SculptUndoNode {
 	int *grids;                 /* to restore into right location */
 	BLI_bitmap *grid_hidden;
 
+	/* bmesh */
+	struct BMLogEntry *bm_entry;
+	int applied;
+	CustomData bm_enter_vdata;
+	CustomData bm_enter_edata;
+	CustomData bm_enter_ldata;
+	CustomData bm_enter_pdata;
+	int bm_enter_totvert;
+	int bm_enter_totedge;
+	int bm_enter_totloop;
+	int bm_enter_totpoly;
+
 	/* shape keys */
 	char shapeName[sizeof(((KeyBlock *)0))->name];
 } SculptUndoNode;
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index 053e17cde07..08e61a6d05d 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -65,6 +65,7 @@
 #include "GPU_buffers.h"
 
 #include "ED_sculpt.h"
+#include "bmesh.h"
 #include "paint_intern.h"
 #include "sculpt_intern.h"
 
@@ -261,6 +262,111 @@ static int sculpt_undo_restore_mask(bContext *C, DerivedMesh *dm, SculptUndoNode
 	return 1;
 }
 
+static void sculpt_undo_bmesh_restore_generic(SculptUndoNode *unode,
+											  Object *ob,
+											  SculptSession *ss)
+{
+	if (unode->applied) {
+		BM_log_undo(ss->bm, ss->bm_log);
+		unode->applied = FALSE;
+	}
+	else {
+		BM_log_redo(ss->bm, ss->bm_log);
+		unode->applied = TRUE;
+	}
+
+	/* A bit lame, but for now just recreate the PBVH. The alternative
+	 * is to store changes to the PBVH in the undo stack. */
+	sculpt_pbvh_clear(ob);
+}
+
+/* Create empty sculpt BMesh and enable logging */
+static void sculpt_undo_bmesh_enable(Object *ob,
+									 SculptUndoNode *unode)
+{
+	SculptSession *ss = ob->sculpt;
+	Mesh *me = ob->data;
+
+	sculpt_pbvh_clear(ob);
+
+	/* Create empty BMesh and enable logging */
+	ss->bm = BM_mesh_create(&bm_mesh_allocsize_default);
+	BM_data_layer_add(ss->bm, &ss->bm->vdata, CD_PAINT_MASK);
+	me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
+
+	/* Restore the BMLog using saved entries */
+	ss->bm_log = BM_log_from_existing_entries_create(ss->bm,
+													 unode->bm_entry);
+}
+
+static void sculpt_undo_bmesh_restore_begin(bContext *C,
+											SculptUndoNode *unode,
+											Object *ob,
+											SculptSession *ss)
+{
+	if (unode->applied) {
+		sculpt_dynamic_topology_disable(C, unode);
+		unode->applied = FALSE;
+	}
+	else {
+		sculpt_undo_bmesh_enable(ob, unode);
+
+		/* Restore the mesh from the first log entry */
+		BM_log_redo(ss->bm, ss->bm_log);
+
+		unode->applied = TRUE;
+	}
+}
+
+static void sculpt_undo_bmesh_restore_end(bContext *C,
+										  SculptUndoNode *unode,
+										  Object *ob,
+										  SculptSession *ss)
+{
+	if (unode->applied) {
+		sculpt_undo_bmesh_enable(ob, unode);
+
+		/* Restore the mesh from the last log entry */
+		BM_log_undo(ss->bm, ss->bm_log);
+
+		unode->applied = FALSE;
+	}
+	else {
+		/* Disable dynamic topology sculpting */
+		sculpt_dynamic_topology_disable(C, NULL);
+		unode->applied = TRUE;
+	}
+}
+
+/* Handle all dynamic-topology updates
+ *
+ * Returns TRUE if this was a dynamic-topology undo step, otherwise
+ * returns FALSE to indicate the non-dyntopo code should run. */
+static int sculpt_undo_bmesh_restore(bContext *C,
+									 SculptUndoNode *unode,
+									 Object *ob,
+									 SculptSession *ss)
+{
+	switch (unode->type) {
+		case SCULPT_UNDO_DYNTOPO_BEGIN:
+			sculpt_undo_bmesh_restore_begin(C, unode, ob, ss);
+			return TRUE;
+
+		case SCULPT_UNDO_DYNTOPO_END:
+			sculpt_undo_bmesh_restore_end(C, unode, ob, ss);
+			return TRUE;
+
+		default:
+			if (ss->bm_log) {
+				sculpt_undo_bmesh_restore_generic(unode, ob, ss);
+				return TRUE;
+			}
+			break;
+	}
+
+	return FALSE;
+}
+
 static void sculpt_undo_restore(bContext *C, ListBase *lb)
 {
 	Scene *scene = CTX_data_scene(C);
@@ -289,6 +395,9 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
 	/* call _after_ sculpt_update_mesh_elements() which may update 'ob->derivedFinal' */
 	dm = mesh_get_derived_final(scene, ob, 0);
 
+	if (lb->first && sculpt_undo_bmesh_restore(C, lb->first, ob, ss))
+		return;
+
 	for (unode = lb->first; unode; unode = unode->next) {
 		if (!(strcmp(unode->idname, ob->id.name) == 0))
 			continue;
@@ -306,9 +415,6 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
 				continue;
 			}
 		}
-		else {
-			continue;
-		}
 
 		switch (unode->type) {
 			case SCULPT_UNDO_COORDS:
@@ -323,6 +429,12 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
 				if (sculpt_undo_restore_mask(C, dm, unode))
 					update = TRUE;
 				break;
+
+			case SCULPT_UNDO_DYNTOPO_BEGIN:
+			case SCULPT_UNDO_DYNTOPO_END:
+			case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
+				BLI_assert(!"Dynamic topology should've already been handled");
+				break;
 		}
 	}
 
@@ -387,6 +499,17 @@ static void sculpt_undo_free(ListBase *lb)
 		}
 		if (unode->mask)
 			MEM_freeN(unode->mask);
+		if (unode->bm_entry) {
+			BM_log_entry_drop(unode->bm_entry);
+		}
+		if (unode->bm_enter_totvert)
+			CustomData_free(&unode->bm_enter_vdata, unode->bm_enter_totvert);
+		if (unode->bm_enter_totedge)
+			CustomData_free(&unode->bm_enter_edata, unode->bm_enter_totedge);
+		if (unode->bm_enter_totloop)
+			CustomData_free(&unode->bm_enter_ldata, unode->bm_enter_totloop);
+		if (unode->bm_enter_totpoly)
+			CustomData_free(&unode->bm_enter_pdata, unode->bm_enter_totpoly);
 	}
 }
 
@@ -437,11 +560,13 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node,
 	unode->type = type;
 	unode->node = node;
 
-	BLI_pbvh_node_num_verts(ss->pbvh, node, &totvert, &allvert);
-	BLI_pbvh_node_get_grids(ss->pbvh, node, &grids, &totgrid,
-	                        &maxgrid, &gridsize, NULL, NULL);
+	if (node) {
+		BLI_pbvh_node_num_verts(ss->pbvh, node, &totvert, &allvert);
+		BLI_pbvh_node_get_grids(ss->pbvh, node, &grids, &totgrid,
+								&maxgrid, &gridsize, NULL, NULL);
 
-	unode->totvert = totvert;
+		unode->totvert = totvert;
+	}
 	
 	/* we will use this while sculpting, is mapalloc slow to access then? */
 
@@ -466,6 +591,11 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node,
 			unode->mask = MEM_mapallocN(sizeof(float) * allvert, "SculptUndoNode.mask");
 			undo_paint_push_count_alloc(UNDO_PAINT_MESH, (sizeof(float) * sizeof(int)) * allvert);
 			break;
+		case SCULPT_UNDO_DYNTOPO_BEGIN:
+		case SCULPT_UNDO_DYNTOPO_END:
+		case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
+			BLI_assert(!"Dynamic topology should've already been handled");
+			break;
 	}
 	
 	BLI_addtail(lb, unode);
@@ -540,6 +670,80 @@ static void sculpt_undo_store_mask(Object *ob, SculptUndoNode *unode)
 	BLI_pbvh_vertex_iter_end;
 }
 
+static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob,
+											  PBVHNode *node,
+											  SculptUndoType type)
+{
+	ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_MESH);
+	SculptUndoNode *unode = lb->first;
+	SculptSession *ss = ob->sculpt;
+	PBVHVertexIter vd;
+
+	if (!lb->first) {
+		unode = MEM_callocN(sizeof(*unode), AT);
+
+		BLI_strncpy(unode->idname, ob->id.name, sizeof(unode->idname));
+		unode->type = type;
+		unode->applied = TRUE;
+
+		if (type == SCULPT_UNDO_DYNTOPO_END) {
+			unode->bm_entry = BM_log_entry_add(ss->bm_log);
+			BM_log_before_all_removed(ss->bm, ss->bm_log);
+		}
+		else if (type == SCULPT_UNDO_DYNTOPO_BEGIN) {
+			Mesh *me = ob->data;
+
+			/* Store a copy of the mesh's current vertices, loops, and
+			 * polys. A full copy like this is needed because entering
+			 * dynamic-topology immediately does topological edits
+			 * (converting polys to triangles) that the BMLog can't
+			 * fully restore from */
+			CustomData_copy(&me->vdata, &unode->bm_enter_vdata, CD_MASK_MESH,
+							CD_DUPLICATE, me->totvert);
+			CustomData_copy(&me->edata, &unode->bm_enter_edata, CD_MASK_MESH,
+							CD_DUPLICATE, me->totedge);
+			CustomData_copy(&me->ldata, &unode->bm_enter_ldata, CD_MASK_MESH,
+							CD_DUPLICATE, me->totloop);
+			CustomData_copy(&me->pdata, &unode->bm_enter_pdata, CD_MASK_MESH,
+							CD_DUPLICATE, me->totpoly);
+			unode->bm_enter_totvert = me->totvert;
+			unode->bm_enter_totedge = me->totedge;
+			unode->bm_enter_totloop = me->totloop;
+			unode->bm_enter_totpoly = me->totpoly;
+
+			unode->bm_entry = BM_log_entry_add(ss->bm_log);
+			BM_log_all_added(ss->bm, ss->bm_log);
+		}
+		else {
+			unode->bm_entry = BM_log_entry_add(ss->bm_log);
+		}
+
+		BLI_addtail(lb, unode);
+	}
+
+	if (node) {
+		switch (type) {
+			case SCULPT_UNDO_COORDS:
+			case SCULPT_UNDO_HIDDEN:
+			case SCULPT_UNDO_MASK:
+				/* Before any vertex values get modified, ensure their
+				 * original positions are logged */
+				BLI_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_ALL) {
+					BM_log_vert_before_modified(ss->bm, ss->bm_log, vd.bm_vert);
+				}
+				BLI_pbvh_vertex_iter_end;
+				break;
+
+			case SCULPT_UNDO_DYNTOPO_BEGIN:
+			case SCULPT_UNDO_DYNTOPO_END:
+			case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
+				break;
+		}
+	}
+
+	return unode;
+}
+
 SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
                                       SculptUndoType type)
 {
@@ -549,7 +753,18 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
 	/* list is manipulated by multiple threads, so we lock */
 	BLI_lock_thread(LOCK_CUSTOM1);
 
-	if ((unode = sculpt_undo_get_node(node))) {
+	if (ss->bm ||
+		ELEM(type,
+			 SCULPT_UNDO_DYNTOPO_BEGIN,
+			 SCULPT_UNDO_DYNTOPO_END))
+	{
+		/* Dynamic topology stores only one undo node per stroke,
+		 * regardless of the number of PBVH nodes modified */
+		unode = sculpt_undo_bmesh_push(ob, node, type);
+		BLI_unlock_thread(LOCK_CUSTOM1);
+		return unode;
+	}
+	else if ((unode = sculpt_undo_get_node(node))) {
 		BLI_unlock_thread(LOCK_CUSTOM1);
 		return unode;
 	}
@@ -583,6 +798,11 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
 		case SCULPT_UNDO_MASK:
 			sculpt_undo_store_mask(ob, unode);
 			break;
+		case SCULPT_UNDO_DYNTOPO_BEGIN:
+		case SCULPT_UNDO_DYNTOPO_END:
+		case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
+			BLI_assert(!"Dynamic topology should've already been handled");
+			break;
 	}
 
 	/* store active shape key */
-- 
cgit v1.2.3


From ae9d6e08130e56157cf3979bff81e6d2bf778946 Mon Sep 17 00:00:00 2001
From: Nicholas Bishop 
Date: Sun, 30 Dec 2012 18:29:25 +0000
Subject: Modify info stats for dynamic-topology sculpt mode

Format is like this: "Verts:8 | Tris:12 | Cube"
---
 source/blender/editors/space_info/info_stats.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

(limited to 'source')

diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index 73a43ee35ed..490d08284d2 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -48,6 +48,7 @@
 #include "BKE_DerivedMesh.h"
 #include "BKE_key.h"
 #include "BKE_mesh.h"
+#include "BKE_paint.h"
 #include "BKE_particle.h"
 #include "BKE_tessmesh.h"
 
@@ -246,6 +247,12 @@ static void stats_object_pose(Object *ob, SceneStats *stats)
 	}
 }
 
+static void stats_object_sculpt_dynamic_topology(Object *ob, SceneStats *stats)
+{
+	stats->totvert = ob->sculpt->bm->totvert;
+	stats->tottri = ob->sculpt->bm->totface;
+}
+
 static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats)
 {
 	if (base->flag & SELECT) stats->totobjsel++;
@@ -305,6 +312,12 @@ static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats)
 	}
 }
 
+static int stats_is_object_dynamic_topology_sculpt(Object *ob)
+{
+	return (ob && (ob->mode & OB_MODE_SCULPT) &&
+			ob->sculpt && ob->sculpt->bm);
+}
+
 /* Statistics displayed in info header. Called regularly on scene changes. */
 static void stats_update(Scene *scene)
 {
@@ -320,6 +333,10 @@ static void stats_update(Scene *scene)
 		/* Pose Mode */
 		stats_object_pose(ob, &stats);
 	}
+	else if (stats_is_object_dynamic_topology_sculpt(ob)) {
+		/* Dynamic-topology sculpt mode */
+		stats_object_sculpt_dynamic_topology(ob, &stats);
+	}
 	else {
 		/* Objects */
 		for (base = scene->base.first; base; base = base->next)
@@ -374,6 +391,9 @@ static void stats_string(Scene *scene)
 		s += sprintf(s, "Bones:%d/%d %s",
 		             stats->totbonesel, stats->totbone, memstr);
 	}
+	else if (stats_is_object_dynamic_topology_sculpt(ob)) {
+		s += sprintf(s, "Verts:%d | Tris:%d", stats->totvert, stats->tottri);
+	}
 	else {
 		s += sprintf(s, "Verts:%d | Faces:%d| Tris:%d | Objects:%d/%d | Lamps:%d/%d%s",
 		             stats->totvert, stats->totface, stats->tottri, stats->totobjsel, stats->totobj, stats->totlampsel, stats->totlamp, memstr);
-- 
cgit v1.2.3


From bbaeac3bf83bb622743e2b7e551db9aa5feb7ff9 Mon Sep 17 00:00:00 2001
From: Nicholas Bishop 
Date: Sun, 30 Dec 2012 18:29:41 +0000
Subject: Update DerivedMesh for dynamic-topology sculpt mode

* Build bmesh PBVH in CDDM when dyntopo is enabled

* Disable all modifiers when dyntopo is enabled
---
 source/blender/blenkernel/intern/DerivedMesh.c   | 10 ++++++++--
 source/blender/blenkernel/intern/cdderivedmesh.c | 11 +++++++++++
 2 files changed, 19 insertions(+), 2 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 4ccec3893e8..ec8d37e1ae3 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -1340,6 +1340,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
 	MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0);
 	int has_multires = mmd != NULL, multires_applied = 0;
 	int sculpt_mode = ob->mode & OB_MODE_SCULPT && ob->sculpt;
+	int sculpt_dyntopo = (sculpt_mode && ob->sculpt->bm);
 
 	const int draw_flag = ((scene->toolsettings->multipaint ? CALC_WP_MULTIPAINT : 0) |
 	                       (scene->toolsettings->auto_normalize ? CALC_WP_AUTO_NORMALIZE : 0));
@@ -1407,7 +1408,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
 			if (!modifier_isEnabled(scene, md, required_mode)) continue;
 			if (useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) continue;
 
-			if (mti->type == eModifierTypeType_OnlyDeform) {
+			if (mti->type == eModifierTypeType_OnlyDeform && !sculpt_dyntopo) {
 				if (!deformedVerts)
 					deformedVerts = mesh_getVertexCos(me, &numVerts);
 
@@ -1465,9 +1466,14 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
 			modifier_setError(md, "Modifier requires original data, bad stack position");
 			continue;
 		}
-		if (sculpt_mode && (!has_multires || multires_applied)) {
+		if (sculpt_mode &&
+			(!has_multires || multires_applied || ob->sculpt->bm))
+		{
 			int unsupported = 0;
 
+			if (sculpt_dyntopo)
+				unsupported = TRUE;
+
 			if (scene->toolsettings->sculpt->flags & SCULPT_ONLY_DEFORM)
 				unsupported |= mti->type != eModifierTypeType_OnlyDeform;
 
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 61d0936d41d..080e5fd857c 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -262,6 +262,17 @@ static PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
 		cddm->pbvh_draw = can_pbvh_draw(ob, dm);
 	}
 
+	/* Sculpting on a BMesh (dynamic-topology) gets a special PBVH */
+	if (!cddm->pbvh && ob->sculpt->bm) {
+		cddm->pbvh = BLI_pbvh_new();
+		cddm->pbvh_draw = TRUE;
+
+		BLI_pbvh_build_bmesh(cddm->pbvh, ob->sculpt->bm,
+							 ob->sculpt->bm_smooth_shading,
+							 ob->sculpt->bm_log);
+	}
+		
+
 	/* always build pbvh from original mesh, and only use it for drawing if
 	 * this derivedmesh is just original mesh. it's the multires subsurf dm
 	 * that this is actually for, to support a pbvh on a modified mesh */
-- 
cgit v1.2.3


From 6ded71fb62e7f8e6791bd5a6d721b1bd9efe0b85 Mon Sep 17 00:00:00 2001
From: Nicholas Bishop 
Date: Sun, 30 Dec 2012 18:29:56 +0000
Subject: Hiding support for dynamic topology

---
 source/blender/editors/sculpt_paint/paint_hide.c | 72 ++++++++++++++++++++++++
 1 file changed, 72 insertions(+)

(limited to 'source')

diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c
index 36fe4715fc0..9cc908746e8 100644
--- a/source/blender/editors/sculpt_paint/paint_hide.c
+++ b/source/blender/editors/sculpt_paint/paint_hide.c
@@ -232,6 +232,75 @@ static void partialvis_update_grids(Object *ob,
 	}
 }
 
+static void partialvis_update_bmesh_verts(BMesh *bm,
+										  GHash *verts,
+										  PartialVisAction action,
+										  PartialVisArea area,
+										  float planes[4][4],
+										  int *any_changed,
+										  int *any_visible)
+{
+	GHashIterator gh_iter;
+
+	GHASH_ITER (gh_iter, verts) {
+		BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+		float *vmask = CustomData_bmesh_get(&bm->vdata,
+											v->head.data,
+											CD_PAINT_MASK);
+
+		/* hide vertex if in the hide volume */
+		if (is_effected(area, planes, v->co, *vmask)) {
+			if (action == PARTIALVIS_HIDE)
+				BM_elem_flag_enable(v, BM_ELEM_HIDDEN);
+			else
+				BM_elem_flag_disable(v, BM_ELEM_HIDDEN);
+			(*any_changed) = TRUE;
+		}
+
+		if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN))
+			(*any_visible) = TRUE;
+	}
+}
+
+static void partialvis_update_bmesh(Object *ob,
+									PBVH *pbvh,
+									PBVHNode *node,
+									PartialVisAction action,
+									PartialVisArea area,
+									float planes[4][4])
+{
+	BMesh *bm;
+	GHash *unique, *other;
+	int any_changed = 0, any_visible = 0;
+
+	bm = BLI_pbvh_get_bmesh(pbvh);
+	unique = BLI_pbvh_bmesh_node_unique_verts(node);
+	other = BLI_pbvh_bmesh_node_other_verts(node);
+
+	sculpt_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN);
+
+	partialvis_update_bmesh_verts(bm,
+								  unique,
+								  action,
+								  area,
+								  planes,
+								  &any_changed,
+								  &any_visible);
+
+	partialvis_update_bmesh_verts(bm,
+								  other,
+								  action,
+								  area,
+								  planes,
+								  &any_changed,
+								  &any_visible);
+
+	if (any_changed) {
+		BLI_pbvh_node_mark_rebuild_draw(node);
+		BLI_pbvh_node_fully_hidden_set(node, !any_visible);
+	}
+}
+
 static void rect_from_props(rcti *rect, PointerRNA *ptr)
 {
 	rect->xmin = RNA_int_get(ptr, "xmin");
@@ -330,6 +399,9 @@ static int hide_show_exec(bContext *C, wmOperator *op)
 			case PBVH_GRIDS:
 				partialvis_update_grids(ob, pbvh, nodes[i], action, area, clip_planes);
 				break;
+			case PBVH_BMESH:
+				partialvis_update_bmesh(ob, pbvh, nodes[i], action, area, clip_planes);
+				break;
 		}
 	}
 
-- 
cgit v1.2.3


From d342e3ef0f0d864133ae1d40481c309b366bbec0 Mon Sep 17 00:00:00 2001
From: Nicholas Bishop 
Date: Sun, 30 Dec 2012 18:30:13 +0000
Subject: Use GPU_Buffers to draw wireframe when in dynamic-topology sculpt
 mode

This adds an override to the CDDM edge drawing function that switches
to GPU_Buffers drawing for PBVHes of type PBVH_BMESH.

Within the GPU_Buffers code, glPolygonMode() is used to draw lines
instead of faces.
---
 source/blender/blenkernel/BKE_pbvh.h             |  2 +-
 source/blender/blenkernel/intern/cdderivedmesh.c | 11 ++++++++++-
 source/blender/blenkernel/intern/pbvh.c          | 20 +++++++++++++++-----
 source/blender/blenkernel/intern/subsurf_ccg.c   |  3 ++-
 source/blender/gpu/GPU_buffers.h                 |  3 ++-
 source/blender/gpu/intern/gpu_buffers.c          | 21 ++++++++++++++++-----
 6 files changed, 46 insertions(+), 14 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 4abeed513df..7e5ebc9d022 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -102,7 +102,7 @@ int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3], int use
 
 void BLI_pbvh_node_draw(PBVHNode *node, void *data);
 void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
-                   int (*setMaterial)(int, void *attribs));
+                   int (*setMaterial)(int, void *attribs), int wireframe);
 
 /* PBVH Access */
 typedef enum {
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 080e5fd857c..3d4cb7b4745 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -425,6 +425,14 @@ static void cdDM_drawEdges(DerivedMesh *dm, int drawLooseEdges, int drawAllEdges
 	MVert *mvert = cddm->mvert;
 	MEdge *medge = cddm->medge;
 	int i;
+
+	if (cddm->pbvh && cddm->pbvh_draw &&
+		BLI_pbvh_type(cddm->pbvh) == PBVH_BMESH)
+	{
+		BLI_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, TRUE);
+
+		return;
+	}
 	
 	if (GPU_buffer_legacy(dm)) {
 		DEBUG_VBO("Using legacy code. cdDM_drawEdges\n");
@@ -541,7 +549,8 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm,
 		if (dm->numTessFaceData) {
 			float (*face_nors)[3] = CustomData_get_layer(&dm->faceData, CD_NORMAL);
 
-			BLI_pbvh_draw(cddm->pbvh, partial_redraw_planes, face_nors, setMaterial);
+			BLI_pbvh_draw(cddm->pbvh, partial_redraw_planes, face_nors,
+						  setMaterial, FALSE);
 			glShadeModel(GL_FLAT);
 		}
 
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 6e0209e7683..1b6a544339d 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -1523,8 +1523,15 @@ int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3], int use
 
 //#include 
 
-void BLI_pbvh_node_draw(PBVHNode *node, void *setMaterial)
+typedef struct {
+	DMSetMaterial setMaterial;
+	int wireframe;
+} PBVHNodeDrawData;
+
+void BLI_pbvh_node_draw(PBVHNode *node, void *data_v)
 {
+	PBVHNodeDrawData *data = data_v;
+
 #if 0
 	/* XXX: Just some quick code to show leaf nodes in different colors */
 	float col[3]; int i;
@@ -1543,7 +1550,9 @@ void BLI_pbvh_node_draw(PBVHNode *node, void *setMaterial)
 #endif
 
 	if (!(node->flag & PBVH_FullyHidden))
-		GPU_draw_buffers(node->draw_buffers, setMaterial);
+		GPU_draw_buffers(node->draw_buffers,
+						 data->setMaterial,
+						 data->wireframe);
 }
 
 typedef enum {
@@ -1612,8 +1621,9 @@ static void pbvh_node_check_diffuse_changed(PBVH *bvh, PBVHNode *node)
 }
 
 void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
-                   DMSetMaterial setMaterial)
+                   DMSetMaterial setMaterial, int wireframe)
 {
+	PBVHNodeDrawData draw_data = {setMaterial, wireframe};
 	PBVHNode **nodes;
 	int a, totnode;
 
@@ -1630,10 +1640,10 @@ void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
 
 	if (planes) {
 		BLI_pbvh_search_callback(bvh, BLI_pbvh_node_planes_contain_AABB,
-		                         planes, BLI_pbvh_node_draw, setMaterial);
+		                         planes, BLI_pbvh_node_draw, &draw_data);
 	}
 	else {
-		BLI_pbvh_search_callback(bvh, NULL, NULL, BLI_pbvh_node_draw, setMaterial);
+		BLI_pbvh_search_callback(bvh, NULL, NULL, BLI_pbvh_node_draw, &draw_data);
 	}
 }
 
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index fdd115617de..b72499b3b14 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -1707,7 +1707,8 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)
 
 	if (ccgdm->pbvh && ccgdm->multires.mmd && !fast) {
 		if (dm->numTessFaceData) {
-			BLI_pbvh_draw(ccgdm->pbvh, partial_redraw_planes, NULL, setMaterial);
+			BLI_pbvh_draw(ccgdm->pbvh, partial_redraw_planes, NULL,
+						  setMaterial, FALSE);
 			glShadeModel(GL_FLAT);
 		}
 
diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h
index 70ca44c2a3a..9f6f80585ab 100644
--- a/source/blender/gpu/GPU_buffers.h
+++ b/source/blender/gpu/GPU_buffers.h
@@ -184,7 +184,8 @@ void GPU_update_grid_buffers(GPU_Buffers *buffers, struct CCGElem **grids,
                              int *grid_indices, int totgrid, const struct CCGKey *key,
                              int show_diffuse_color);
 
-void GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial);
+void GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial,
+					  int wireframe);
 
 int GPU_buffers_diffuse_changed(GPU_Buffers *buffers, int show_diffuse_color);
 
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index ba090137118..5f9f68e9c99 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -2312,7 +2312,8 @@ static void gpu_draw_buffers_legacy_grids(GPU_Buffers *buffers)
 	}
 }
 
-void GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial)
+void GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial,
+					  int wireframe)
 {
 	if (buffers->totface) {
 		const MFace *f = &buffers->mface[buffers->face_indices[0]];
@@ -2329,14 +2330,19 @@ void GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial)
 
 	if (buffers->vert_buf) {
 		glEnableClientState(GL_VERTEX_ARRAY);
-		glEnableClientState(GL_NORMAL_ARRAY);
-		gpu_colors_enable(VBO_ENABLED);
+		if (!wireframe) {
+			glEnableClientState(GL_NORMAL_ARRAY);
+			gpu_colors_enable(VBO_ENABLED);
+		}
 
 		glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf);
 
 		if (buffers->index_buf)
 			glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
 
+		if (wireframe)
+			glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+
 		if (buffers->tot_quad) {
 			char *offset = 0;
 			int i, last = buffers->has_hidden ? 1 : buffers->totgrid;
@@ -2369,13 +2375,18 @@ void GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial)
 				glDrawArrays(GL_TRIANGLES, 0, totelem);
 		}
 
+		if (wireframe)
+			glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
 		glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
 		if (buffers->index_buf)
 			glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
 
 		glDisableClientState(GL_VERTEX_ARRAY);
-		glDisableClientState(GL_NORMAL_ARRAY);
-		gpu_colors_disable(VBO_ENABLED);
+		if (!wireframe) {
+			glDisableClientState(GL_NORMAL_ARRAY);
+			gpu_colors_disable(VBO_ENABLED);
+		}
 	}
 	/* fallbacks if we are out of memory or VBO is disabled */
 	else if (buffers->totface) {
-- 
cgit v1.2.3


From 37ed697d5c400ed342fda3ae4a277def6a3bcea9 Mon Sep 17 00:00:00 2001
From: Nicholas Bishop 
Date: Sun, 30 Dec 2012 18:30:40 +0000
Subject: Add simplify brush for sculpt mode

---
 source/blender/editors/sculpt_paint/sculpt.c | 9 +++++++--
 source/blender/makesdna/DNA_brush_types.h    | 5 +----
 source/blender/makesrna/intern/rna_brush.c   | 1 +
 3 files changed, 9 insertions(+), 6 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 12843fde852..af304d04d5d 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -2981,7 +2981,9 @@ static void sculpt_topology_update(Sculpt *sd, Object *ob, Brush *brush)
 	if (totnode) {
 		PBVHTopologyUpdateMode mode = PBVH_Subdivide;
 
-		if (sd->flags & SCULPT_DYNTOPO_COLLAPSE) {
+		if ((sd->flags & SCULPT_DYNTOPO_COLLAPSE) ||
+			(brush->sculpt_tool == SCULPT_TOOL_SIMPLIFY))
+		{
 			mode |= PBVH_Collapse;
 		}
 
@@ -3539,6 +3541,8 @@ static const char *sculpt_tool_name(Sculpt *sd)
 			return "Rotate Brush";
 		case SCULPT_TOOL_MASK:
 			return "Mask Brush";
+		case SCULPT_TOOL_SIMPLIFY:
+			return "Simplify Brush";
 	}
 
 	return "Sculpting";
@@ -4262,7 +4266,8 @@ static void sculpt_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
 		do_symmetrical_brush_actions(sd, ob, sculpt_topology_update);
 	}
 
-	do_symmetrical_brush_actions(sd, ob, do_brush_action);
+	if (paint_brush(&sd->paint)->sculpt_tool != SCULPT_TOOL_SIMPLIFY)
+		do_symmetrical_brush_actions(sd, ob, do_brush_action);
 
 	sculpt_combine_proxies(sd, ob);
 
diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h
index cc26ee479d7..e3571c767bd 100644
--- a/source/blender/makesdna/DNA_brush_types.h
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -156,10 +156,7 @@ typedef enum BrushSculptTool {
 	SCULPT_TOOL_THUMB = 12,
 	SCULPT_TOOL_SNAKE_HOOK = 13,
 	SCULPT_TOOL_ROTATE = 14,
-	
-	/* slot 15 is free for use */
-	/* SCULPT_TOOL_ = 15, */
-	
+	SCULPT_TOOL_SIMPLIFY = 15,
 	SCULPT_TOOL_CREASE = 16,
 	SCULPT_TOOL_BLOB = 17,
 	SCULPT_TOOL_CLAY_STRIPS = 18,
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index 7bdebd620ee..3d5106b0cef 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -65,6 +65,7 @@ EnumPropertyItem brush_sculpt_tool_items[] = {
 	{SCULPT_TOOL_PINCH, "PINCH", ICON_BRUSH_PINCH, "Pinch", ""},
 	{SCULPT_TOOL_ROTATE, "ROTATE", ICON_BRUSH_ROTATE, "Rotate", ""},
 	{SCULPT_TOOL_SCRAPE, "SCRAPE", ICON_BRUSH_SCRAPE, "Scrape", ""},
+	{SCULPT_TOOL_SIMPLIFY, "SIMPLIFY", ICON_BRUSH_SUBTRACT /* icon TODO */, "Simplify", ""},
 	{SCULPT_TOOL_SMOOTH, "SMOOTH", ICON_BRUSH_SMOOTH, "Smooth", ""},
 	{SCULPT_TOOL_SNAKE_HOOK, "SNAKE_HOOK", ICON_BRUSH_SNAKE_HOOK, "Snake Hook", ""},
 	{SCULPT_TOOL_THUMB, "THUMB", ICON_BRUSH_THUMB, "Thumb", ""},
-- 
cgit v1.2.3


From ab960eea889b8481358b0db789b6c7cddf311248 Mon Sep 17 00:00:00 2001
From: Nicholas Bishop 
Date: Sun, 30 Dec 2012 18:31:01 +0000
Subject: Add symmetrize operator for dynamic-topology sculpt mode

---
 source/blender/bmesh/operators/bmo_symmetrize.c   |  7 ++++
 source/blender/editors/mesh/editmesh_tools.c      | 18 ++-------
 source/blender/editors/sculpt_paint/sculpt.c      | 45 +++++++++++++++++++++++
 source/blender/makesdna/DNA_scene_types.h         |  5 +++
 source/blender/makesrna/RNA_enum_types.h          |  2 +
 source/blender/makesrna/intern/rna_sculpt_paint.c | 19 ++++++++++
 6 files changed, 81 insertions(+), 15 deletions(-)

(limited to 'source')

diff --git a/source/blender/bmesh/operators/bmo_symmetrize.c b/source/blender/bmesh/operators/bmo_symmetrize.c
index 248c7268ac6..172f0d40b27 100644
--- a/source/blender/bmesh/operators/bmo_symmetrize.c
+++ b/source/blender/bmesh/operators/bmo_symmetrize.c
@@ -361,6 +361,12 @@ static BMFace *symm_face_create_v(BMesh *bm, BMFace *example,
 	BMFace *f_new;
 	int i;
 
+	/* TODO: calling symmetrize in dynamic-topology sculpt mode
+	 * frequently tries to create faces of length less than two,
+	 * should investigate further */
+	if (len < 3)
+		return NULL;
+
 	for (i = 0; i < len; i++) {
 		int j = (i + 1) % len;
 		fe[i] = BM_edge_exists(fv[i], fv[j]);
@@ -374,6 +380,7 @@ static BMFace *symm_face_create_v(BMesh *bm, BMFace *example,
 		BM_elem_attrs_copy(bm, bm, example, f_new);
 	BM_face_select_set(bm, f_new, TRUE);
 	BMO_elem_flag_enable(bm, f_new, SYMM_OUTPUT_GEOM);
+
 	return f_new;
 }
 
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 12475c61bca..81f18b6a551 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -5734,18 +5734,6 @@ static int mesh_symmetrize_exec(bContext *C, wmOperator *op)
 
 void MESH_OT_symmetrize(struct wmOperatorType *ot)
 {
-	static EnumPropertyItem axis_direction_items[] = {
-		{BMO_SYMMETRIZE_NEGATIVE_X, "NEGATIVE_X", 0, "-X to +X", ""},
-		{BMO_SYMMETRIZE_POSITIVE_X, "POSITIVE_X", 0, "+X to -X", ""},
-
-		{BMO_SYMMETRIZE_NEGATIVE_Y, "NEGATIVE_Y", 0, "-Y to +Y", ""},
-		{BMO_SYMMETRIZE_POSITIVE_Y, "POSITIVE_Y", 0, "+Y to -Y", ""},
-
-		{BMO_SYMMETRIZE_NEGATIVE_Z, "NEGATIVE_Z", 0, "-Z to +Z", ""},
-		{BMO_SYMMETRIZE_POSITIVE_Z, "POSITIVE_Z", 0, "+Z to -Z", ""},
-		{0, NULL, 0, NULL, NULL},
-	};
-
 	/* identifiers */
 	ot->name = "Symmetrize";
 	ot->description = "Enforce symmetry (both form and topological) across an axis";
@@ -5758,7 +5746,7 @@ void MESH_OT_symmetrize(struct wmOperatorType *ot)
 	/* flags */
 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
-	ot->prop = RNA_def_enum(ot->srna, "direction", axis_direction_items,
-	                        BMO_SYMMETRIZE_NEGATIVE_X,
-	                        "Direction", "Which sides to copy from and to");
+	ot->prop = RNA_def_enum(ot->srna, "direction", symmetrize_direction_items,
+							BMO_SYMMETRIZE_NEGATIVE_X,
+							"Direction", "Which sides to copy from and to");
 }
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index af304d04d5d..95f997d46b1 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -4712,6 +4712,50 @@ static void SCULPT_OT_optimize(wmOperatorType *ot)
 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
+/********************* Dynamic topology symmetrize ********************/
+
+static int sculpt_symmetrize_exec(bContext *C, wmOperator *UNUSED(op))
+{
+	Object *ob = CTX_data_active_object(C);
+	const Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+	SculptSession *ss = ob->sculpt;
+
+	/* To simplify undo for symmetrize, all BMesh elements are logged
+	 * as deleted, then after symmetrize operation all BMesh elements
+	 * are logged as added (as opposed to attempting to store just the
+	 * parts that symmetrize modifies) */
+	sculpt_undo_push_begin("Dynamic topology symmetrize");
+	sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_SYMMETRIZE);
+	BM_log_before_all_removed(ss->bm, ss->bm_log);
+
+	/* Symmetrize and re-triangulate */
+	BMO_op_callf(ss->bm, BMO_FLAG_DEFAULTS,
+				 "symmetrize input=%avef direction=%i",
+				 sd->symmetrize_direction);
+	sculpt_dynamic_topology_triangulate(ss->bm);
+
+	/* Finish undo */
+	BM_log_all_added(ss->bm, ss->bm_log);
+	sculpt_undo_push_end();
+
+	/* Redraw */
+	sculpt_pbvh_clear(ob);
+	WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+	return OPERATOR_FINISHED;
+}
+
+static void SCULPT_OT_symmetrize(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name = "Symmetrize";
+	ot->idname = "SCULPT_OT_symmetrize";
+	
+	/* api callbacks */
+	ot->exec = sculpt_symmetrize_exec;
+	ot->poll = sculpt_and_dynamic_topology_poll;
+}
+
 /**** Toggle operator for turning sculpt mode on or off ****/
 
 static void sculpt_init_session(Scene *scene, Object *ob)
@@ -4887,4 +4931,5 @@ void ED_operatortypes_sculpt(void)
 	WM_operatortype_append(SCULPT_OT_set_persistent_base);
 	WM_operatortype_append(SCULPT_OT_dynamic_topology_toggle);
 	WM_operatortype_append(SCULPT_OT_optimize);
+	WM_operatortype_append(SCULPT_OT_symmetrize);
 }
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 0d1ef7af591..6dcc74d74e7 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -832,6 +832,11 @@ typedef struct Sculpt {
 
 	/* Maximum edge length for dynamic topology sculpting (in pixels) */
 	int detail_size;
+
+	/* Direction used for SCULPT_OT_symmetrize operator */
+	int symmetrize_direction;
+
+	int pad;
 } Sculpt;
 
 typedef struct UvSculpt {
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index 49f881ce285..6733d8a5c05 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -90,6 +90,8 @@ extern EnumPropertyItem brush_sculpt_tool_items[];
 extern EnumPropertyItem brush_vertex_tool_items[];
 extern EnumPropertyItem brush_image_tool_items[];
 
+extern EnumPropertyItem symmetrize_direction_items[];
+
 extern EnumPropertyItem texture_type_items[];
 
 extern EnumPropertyItem lamp_type_items[];
diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c
index e3b41222a38..fb4295ddb53 100644
--- a/source/blender/makesrna/intern/rna_sculpt_paint.c
+++ b/source/blender/makesrna/intern/rna_sculpt_paint.c
@@ -40,6 +40,9 @@
 #include "WM_api.h"
 #include "WM_types.h"
 
+#include "BLI_utildefines.h"
+#include "bmesh.h"
+
 static EnumPropertyItem particle_edit_hair_brush_items[] = {
 	{PE_BRUSH_NONE, "NONE", 0, "None", "Don't use any brush"},
 	{PE_BRUSH_COMB, "COMB", 0, "Comb", "Comb hairs"},
@@ -52,6 +55,18 @@ static EnumPropertyItem particle_edit_hair_brush_items[] = {
 	{0, NULL, 0, NULL, NULL}
 };
 
+EnumPropertyItem symmetrize_direction_items[] = {
+	{BMO_SYMMETRIZE_NEGATIVE_X, "NEGATIVE_X", 0, "-X to +X", ""},
+	{BMO_SYMMETRIZE_POSITIVE_X, "POSITIVE_X", 0, "+X to -X", ""},
+
+	{BMO_SYMMETRIZE_NEGATIVE_Y, "NEGATIVE_Y", 0, "-Y to +Y", ""},
+	{BMO_SYMMETRIZE_POSITIVE_Y, "POSITIVE_Y", 0, "+Y to -Y", ""},
+
+	{BMO_SYMMETRIZE_NEGATIVE_Z, "NEGATIVE_Z", 0, "-Z to +Z", ""},
+	{BMO_SYMMETRIZE_POSITIVE_Z, "POSITIVE_Z", 0, "+Z to -Z", ""},
+	{0, NULL, 0, NULL, NULL},
+};
+
 #ifdef RNA_RUNTIME
 #include "MEM_guardedalloc.h"
 
@@ -341,6 +356,10 @@ static void rna_def_sculpt(BlenderRNA  *brna)
 	RNA_def_property_ui_text(prop, "Collapse Short Edges",
 							 "In dynamic-topology mode, collapse short edges "
 							 "in addition to subdividing long ones");
+
+	prop = RNA_def_property(srna, "symmetrize_direction", PROP_ENUM, PROP_NONE);
+	RNA_def_property_enum_items(prop, symmetrize_direction_items);
+	RNA_def_property_ui_text(prop, "Direction", "Source and destination for symmetrize operator");
 }
 
 
-- 
cgit v1.2.3


From 21d79cf7691b53265d15efd3f061740611415d45 Mon Sep 17 00:00:00 2001
From: Nicholas Bishop 
Date: Sun, 30 Dec 2012 18:31:17 +0000
Subject: Add UI and keybindings for dynamic-topology sculpt mode

* New topology panel in 3D view toolbar with the enable/disable button
  for dynamic topology and other controls

* Ctrl+DKEY to toggle dynamic topology

* Shift+DKEY to show a radial control for detail size
---
 source/blender/editors/sculpt_paint/paint_ops.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

(limited to 'source')

diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index 10b9f26dbcd..9e702c16e2f 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -648,6 +648,18 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
 	kmi = WM_keymap_add_item(keymap, "PAINT_OT_mask_flood_fill", IKEY, KM_PRESS, KM_CTRL, 0);
 	RNA_enum_set(kmi->ptr, "mode", PAINT_MASK_INVERT);
 
+	/* Toggle dynamic topology */
+	WM_keymap_add_item(keymap, "SCULPT_OT_dynamic_topology_toggle", DKEY, KM_PRESS, KM_CTRL, 0);
+
+	/* Dynamic-topology detail size
+	 * 
+	 * This should be improved further, perhaps by showing a triangle
+	 * grid rather than brush alpha */
+	kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", DKEY, KM_PRESS, KM_SHIFT, 0);
+	set_brush_rc_props(kmi->ptr, "sculpt", "detail_size", NULL, 0);
+	RNA_string_set(kmi->ptr, "data_path_primary",
+				   "tool_settings.sculpt.detail_size");
+
 	/* multires switch */
 	kmi = WM_keymap_add_item(keymap, "OBJECT_OT_subdivision_set", PAGEUPKEY, KM_PRESS, 0, 0);
 	RNA_int_set(kmi->ptr, "level", 1);
-- 
cgit v1.2.3


From 22c02c9d3aa589fcedf58e4d7ff4a5c20a18443c Mon Sep 17 00:00:00 2001
From: Nicholas Bishop 
Date: Sun, 30 Dec 2012 18:31:31 +0000
Subject: Code cleanup: rename BLI_pbvh to BKE_pbvh

---
 source/blender/blenkernel/BKE_pbvh.h              | 118 ++++++------
 source/blender/blenkernel/intern/cdderivedmesh.c  |  18 +-
 source/blender/blenkernel/intern/multires.c       |   4 +-
 source/blender/blenkernel/intern/object.c         |   8 +-
 source/blender/blenkernel/intern/pbvh.c           | 146 +++++++--------
 source/blender/blenkernel/intern/pbvh_bmesh.c     |  18 +-
 source/blender/blenkernel/intern/subsurf_ccg.c    |  14 +-
 source/blender/editors/sculpt_paint/paint_hide.c  |  38 ++--
 source/blender/editors/sculpt_paint/paint_mask.c  |  10 +-
 source/blender/editors/sculpt_paint/sculpt.c      | 216 +++++++++++-----------
 source/blender/editors/sculpt_paint/sculpt_undo.c |  44 ++---
 11 files changed, 317 insertions(+), 317 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 7e5ebc9d022..7e34d3a115d 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -18,8 +18,8 @@
  * ***** END GPL LICENSE BLOCK *****
  */
 
-#ifndef __BLI_PBVH_H__
-#define __BLI_PBVH_H__
+#ifndef __BKE_PBVH_H__
+#define __BKE_PBVH_H__
 
 /** \file BKE_pbvh.h
  *  \ingroup bke
@@ -54,35 +54,35 @@ typedef struct {
 /* Callbacks */
 
 /* returns 1 if the search should continue from this node, 0 otherwise */
-typedef int (*BLI_pbvh_SearchCallback)(PBVHNode *node, void *data);
+typedef int (*BKE_pbvh_SearchCallback)(PBVHNode *node, void *data);
 
-typedef void (*BLI_pbvh_HitCallback)(PBVHNode *node, void *data);
-typedef void (*BLI_pbvh_HitOccludedCallback)(PBVHNode *node, void *data, float *tmin);
+typedef void (*BKE_pbvh_HitCallback)(PBVHNode *node, void *data);
+typedef void (*BKE_pbvh_HitOccludedCallback)(PBVHNode *node, void *data, float *tmin);
 
 /* Building */
 
-PBVH *BLI_pbvh_new(void);
-void BLI_pbvh_build_mesh(PBVH *bvh, struct MFace *faces, struct MVert *verts,
+PBVH *BKE_pbvh_new(void);
+void BKE_pbvh_build_mesh(PBVH *bvh, struct MFace *faces, struct MVert *verts,
                          int totface, int totvert, struct CustomData *vdata);
-void BLI_pbvh_build_grids(PBVH *bvh, struct CCGElem **grid_elems,
+void BKE_pbvh_build_grids(PBVH *bvh, struct CCGElem **grid_elems,
                           struct DMGridAdjacency *gridadj, int totgrid,
                           struct CCGKey *key, void **gridfaces, struct DMFlagMat *flagmats,
                           unsigned int **grid_hidden);
-void BLI_pbvh_build_bmesh(PBVH *bvh, struct BMesh *bm, int smooth_shading,
+void BKE_pbvh_build_bmesh(PBVH *bvh, struct BMesh *bm, int smooth_shading,
 						  struct BMLog *log);
 
-void BLI_pbvh_free(PBVH *bvh);
+void BKE_pbvh_free(PBVH *bvh);
 
 /* Hierarchical Search in the BVH, two methods:
  * - for each hit calling a callback
  * - gather nodes in an array (easy to multithread) */
 
-void BLI_pbvh_search_callback(PBVH *bvh,
-                              BLI_pbvh_SearchCallback scb, void *search_data,
-                              BLI_pbvh_HitCallback hcb, void *hit_data);
+void BKE_pbvh_search_callback(PBVH *bvh,
+                              BKE_pbvh_SearchCallback scb, void *search_data,
+                              BKE_pbvh_HitCallback hcb, void *hit_data);
 
-void BLI_pbvh_search_gather(PBVH *bvh,
-                            BLI_pbvh_SearchCallback scb, void *search_data,
+void BKE_pbvh_search_gather(PBVH *bvh,
+                            BKE_pbvh_SearchCallback scb, void *search_data,
                             PBVHNode ***array, int *tot);
 
 /* Raycast
@@ -90,18 +90,18 @@ void BLI_pbvh_search_gather(PBVH *bvh,
  * it's up to the callback to find the primitive within the leaves that is
  * hit first */
 
-void BLI_pbvh_raycast(PBVH *bvh, BLI_pbvh_HitOccludedCallback cb, void *data,
+void BKE_pbvh_raycast(PBVH *bvh, BKE_pbvh_HitOccludedCallback cb, void *data,
                       const float ray_start[3], const float ray_normal[3],
                       int original);
 
-int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3], int use_origco,
+int BKE_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3], int use_origco,
                           const float ray_start[3], const float ray_normal[3],
                           float *dist);
 
 /* Drawing */
 
-void BLI_pbvh_node_draw(PBVHNode *node, void *data);
-void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
+void BKE_pbvh_node_draw(PBVHNode *node, void *data);
+void BKE_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
                    int (*setMaterial)(int, void *attribs), int wireframe);
 
 /* PBVH Access */
@@ -111,23 +111,23 @@ typedef enum {
 	PBVH_BMESH
 } PBVHType;
 
-PBVHType BLI_pbvh_type(const PBVH *bvh);
+PBVHType BKE_pbvh_type(const PBVH *bvh);
 
 /* multires hidden data, only valid for type == PBVH_GRIDS */
-unsigned int **BLI_pbvh_grid_hidden(const PBVH *bvh);
+unsigned int **BKE_pbvh_grid_hidden(const PBVH *bvh);
 
 /* multires level, only valid for type == PBVH_GRIDS */
-void BLI_pbvh_get_grid_key(const PBVH *pbvh, struct CCGKey *key);
+void BKE_pbvh_get_grid_key(const PBVH *pbvh, struct CCGKey *key);
 
 /* Only valid for type == PBVH_BMESH */
-BMesh *BLI_pbvh_get_bmesh(PBVH *pbvh);
-void BLI_pbvh_bmesh_detail_size_set(PBVH *pbvh, float detail_size);
+BMesh *BKE_pbvh_get_bmesh(PBVH *pbvh);
+void BKE_pbvh_bmesh_detail_size_set(PBVH *pbvh, float detail_size);
 
 typedef enum {
 	PBVH_Subdivide = 1,
 	PBVH_Collapse = 2,
 } PBVHTopologyUpdateMode;
-int BLI_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode,
+int BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode,
 								   const float center[3], float radius);
 
 /* Node Access */
@@ -147,55 +147,55 @@ typedef enum {
 	PBVH_UpdateTopology = 256,
 } PBVHNodeFlags;
 
-void BLI_pbvh_node_mark_update(PBVHNode *node);
-void BLI_pbvh_node_mark_rebuild_draw(PBVHNode *node);
-void BLI_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden);
-void BLI_pbvh_node_mark_topology_update(PBVHNode *node);
+void BKE_pbvh_node_mark_update(PBVHNode *node);
+void BKE_pbvh_node_mark_rebuild_draw(PBVHNode *node);
+void BKE_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden);
+void BKE_pbvh_node_mark_topology_update(PBVHNode *node);
 
-void BLI_pbvh_node_get_grids(PBVH *bvh, PBVHNode *node,
+void BKE_pbvh_node_get_grids(PBVH *bvh, PBVHNode *node,
                              int **grid_indices, int *totgrid, int *maxgrid, int *gridsize,
                              struct CCGElem ***grid_elems, struct DMGridAdjacency **gridadj);
-void BLI_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node,
+void BKE_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node,
                              int *uniquevert, int *totvert);
-void BLI_pbvh_node_get_verts(PBVH *bvh, PBVHNode *node,
+void BKE_pbvh_node_get_verts(PBVH *bvh, PBVHNode *node,
                              int **vert_indices, struct MVert **verts);
 
-void BLI_pbvh_node_get_BB(PBVHNode * node, float bb_min[3], float bb_max[3]);
-void BLI_pbvh_node_get_original_BB(PBVHNode * node, float bb_min[3], float bb_max[3]);
+void BKE_pbvh_node_get_BB(PBVHNode * node, float bb_min[3], float bb_max[3]);
+void BKE_pbvh_node_get_original_BB(PBVHNode * node, float bb_min[3], float bb_max[3]);
 
-float BLI_pbvh_node_get_tmin(PBVHNode *node);
+float BKE_pbvh_node_get_tmin(PBVHNode *node);
 
 /* test if AABB is at least partially inside the planes' volume */
-int BLI_pbvh_node_planes_contain_AABB(PBVHNode *node, void *data);
+int BKE_pbvh_node_planes_contain_AABB(PBVHNode *node, void *data);
 /* test if AABB is at least partially outside the planes' volume */
-int BLI_pbvh_node_planes_exclude_AABB(PBVHNode *node, void *data);
+int BKE_pbvh_node_planes_exclude_AABB(PBVHNode *node, void *data);
 
-struct GHash *BLI_pbvh_bmesh_node_unique_verts(PBVHNode *node);
-struct GHash *BLI_pbvh_bmesh_node_other_verts(PBVHNode *node); 
-void BLI_pbvh_bmesh_node_save_orig(PBVHNode *node);
-void BLI_pbvh_bmesh_after_stroke(PBVH *bvh);
+struct GHash *BKE_pbvh_bmesh_node_unique_verts(PBVHNode *node);
+struct GHash *BKE_pbvh_bmesh_node_other_verts(PBVHNode *node); 
+void BKE_pbvh_bmesh_node_save_orig(PBVHNode *node);
+void BKE_pbvh_bmesh_after_stroke(PBVH *bvh);
 
 /* Update Normals/Bounding Box/Draw Buffers/Redraw and clear flags */
 
-void BLI_pbvh_update(PBVH *bvh, int flags, float (*face_nors)[3]);
-void BLI_pbvh_redraw_BB(PBVH * bvh, float bb_min[3], float bb_max[3]);
-void BLI_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***gridfaces, int *totface);
-void BLI_pbvh_grids_update(PBVH *bvh, struct CCGElem **grid_elems,
+void BKE_pbvh_update(PBVH *bvh, int flags, float (*face_nors)[3]);
+void BKE_pbvh_redraw_BB(PBVH * bvh, float bb_min[3], float bb_max[3]);
+void BKE_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***gridfaces, int *totface);
+void BKE_pbvh_grids_update(PBVH *bvh, struct CCGElem **grid_elems,
                            struct DMGridAdjacency *gridadj, void **gridfaces,
                            struct DMFlagMat *flagmats, unsigned int **grid_hidden);
 
 /* Layer displacement */
 
 /* Get the node's displacement layer, creating it if necessary */
-float *BLI_pbvh_node_layer_disp_get(PBVH *pbvh, PBVHNode *node);
+float *BKE_pbvh_node_layer_disp_get(PBVH *pbvh, PBVHNode *node);
 
 /* If the node has a displacement layer, free it and set to null */
-void BLI_pbvh_node_layer_disp_free(PBVHNode *node);
+void BKE_pbvh_node_layer_disp_free(PBVHNode *node);
 
 /* vertex deformer */
-float (*BLI_pbvh_get_vertCos(struct PBVH *pbvh))[3];
-void BLI_pbvh_apply_vertCos(struct PBVH *pbvh, float (*vertCos)[3]);
-int BLI_pbvh_isDeformed(struct PBVH *pbvh);
+float (*BKE_pbvh_get_vertCos(struct PBVH *pbvh))[3];
+void BKE_pbvh_apply_vertCos(struct PBVH *pbvh, float (*vertCos)[3]);
+int BKE_pbvh_isDeformed(struct PBVH *pbvh);
 
 /* Vertex Iterator */
 
@@ -254,7 +254,7 @@ typedef struct PBVHVertexIter {
 void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node,
                            PBVHVertexIter *vi, int mode);
 
-#define BLI_pbvh_vertex_iter_begin(bvh, node, vi, mode) \
+#define BKE_pbvh_vertex_iter_begin(bvh, node, vi, mode) \
 	pbvh_vertex_iter_init(bvh, node, &vi, mode); \
 	 \
 	for (vi.i = 0, vi.g = 0; vi.g < vi.totgrid; vi.g++) { \
@@ -310,20 +310,20 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node,
 												   CD_PAINT_MASK); \
 				}
 
-#define BLI_pbvh_vertex_iter_end \
+#define BKE_pbvh_vertex_iter_end \
 			} \
 		} \
 	}
 
-void BLI_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *proxy_count);
-void BLI_pbvh_node_free_proxies(PBVHNode *node);
-PBVHProxyNode *BLI_pbvh_node_add_proxy(PBVH *bvh, PBVHNode *node);
-void BLI_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***nodes,  int *totnode);
+void BKE_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *proxy_count);
+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 BLI_pbvh_node_BB_reset(PBVHNode *node);
-//void BLI_pbvh_node_BB_expand(PBVHNode *node, float co[3]);
+//void BKE_pbvh_node_BB_reset(PBVHNode *node);
+//void BKE_pbvh_node_BB_expand(PBVHNode *node, float co[3]);
 
 void pbvh_show_diffuse_color_set(PBVH *bvh, int show_diffuse_color);
 
-#endif /* __BLI_PBVH_H__ */
+#endif /* __BKE_PBVH_H__ */
 
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 3d4cb7b4745..5f747827ba7 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -264,10 +264,10 @@ static PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
 
 	/* Sculpting on a BMesh (dynamic-topology) gets a special PBVH */
 	if (!cddm->pbvh && ob->sculpt->bm) {
-		cddm->pbvh = BLI_pbvh_new();
+		cddm->pbvh = BKE_pbvh_new();
 		cddm->pbvh_draw = TRUE;
 
-		BLI_pbvh_build_bmesh(cddm->pbvh, ob->sculpt->bm,
+		BKE_pbvh_build_bmesh(cddm->pbvh, ob->sculpt->bm,
 							 ob->sculpt->bm_smooth_shading,
 							 ob->sculpt->bm_log);
 	}
@@ -281,14 +281,14 @@ static PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
 		Mesh *me = ob->data;
 		int deformed = 0;
 
-		cddm->pbvh = BLI_pbvh_new();
+		cddm->pbvh = BKE_pbvh_new();
 		cddm->pbvh_draw = can_pbvh_draw(ob, dm);
 
 		pbvh_show_diffuse_color_set(cddm->pbvh, ob->sculpt->show_diffuse_color);
 
 		BKE_mesh_tessface_ensure(me);
 		
-		BLI_pbvh_build_mesh(cddm->pbvh, me->mface, me->mvert,
+		BKE_pbvh_build_mesh(cddm->pbvh, me->mface, me->mvert,
 		                    me->totface, me->totvert, &me->vdata);
 
 		deformed = ss->modifiers_active || me->key;
@@ -301,7 +301,7 @@ static PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
 			totvert = deformdm->getNumVerts(deformdm);
 			vertCos = MEM_callocN(3 * totvert * sizeof(float), "cdDM_getPBVH vertCos");
 			deformdm->getVertCos(deformdm, vertCos);
-			BLI_pbvh_apply_vertCos(cddm->pbvh, vertCos);
+			BKE_pbvh_apply_vertCos(cddm->pbvh, vertCos);
 			MEM_freeN(vertCos);
 		}
 	}
@@ -321,7 +321,7 @@ static void cdDM_update_normals_from_pbvh(DerivedMesh *dm)
 
 	face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
 
-	BLI_pbvh_update(cddm->pbvh, PBVH_UpdateNormals, face_nors);
+	BKE_pbvh_update(cddm->pbvh, PBVH_UpdateNormals, face_nors);
 }
 
 static void cdDM_drawVerts(DerivedMesh *dm)
@@ -427,9 +427,9 @@ static void cdDM_drawEdges(DerivedMesh *dm, int drawLooseEdges, int drawAllEdges
 	int i;
 
 	if (cddm->pbvh && cddm->pbvh_draw &&
-		BLI_pbvh_type(cddm->pbvh) == PBVH_BMESH)
+		BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH)
 	{
-		BLI_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, TRUE);
+		BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, TRUE);
 
 		return;
 	}
@@ -549,7 +549,7 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm,
 		if (dm->numTessFaceData) {
 			float (*face_nors)[3] = CustomData_get_layer(&dm->faceData, CD_NORMAL);
 
-			BLI_pbvh_draw(cddm->pbvh, partial_redraw_planes, face_nors,
+			BKE_pbvh_draw(cddm->pbvh, partial_redraw_planes, face_nors,
 						  setMaterial, FALSE);
 			glShadeModel(GL_FLAT);
 		}
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 06d7cf55d49..b12463daf72 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -379,7 +379,7 @@ void multires_force_update(Object *ob)
 			ob->derivedFinal = NULL;
 		}
 		if (ob->sculpt && ob->sculpt->pbvh) {
-			BLI_pbvh_free(ob->sculpt->pbvh);
+			BKE_pbvh_free(ob->sculpt->pbvh);
 			ob->sculpt->pbvh = NULL;
 		}
 	}
@@ -1407,7 +1407,7 @@ void multires_stitch_grids(Object *ob)
 		int totface;
 
 		if (ccgdm->pbvh) {
-			BLI_pbvh_get_grid_updates(ccgdm->pbvh, 0, (void ***)&faces, &totface);
+			BKE_pbvh_get_grid_updates(ccgdm->pbvh, 0, (void ***)&faces, &totface);
 
 			if (totface) {
 				ccgSubSurf_stitchFaces(ccgdm->ss, 0, faces, totface);
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 92b2c8231d3..5914cbfc522 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -298,7 +298,7 @@ void free_sculptsession(Object *ob)
 		}
 
 		if (ss->pbvh)
-			BLI_pbvh_free(ss->pbvh);
+			BKE_pbvh_free(ss->pbvh);
 		if (ss->bm_log)
  			BM_log_free(ss->bm_log);
 
@@ -2815,7 +2815,7 @@ void BKE_object_sculpt_modifiers_changed(Object *ob)
 		 * changing PVBH node organization, we hope topology does not change in
 		 * the meantime .. weak */
 		if (ss->pbvh) {
-			BLI_pbvh_free(ss->pbvh);
+			BKE_pbvh_free(ss->pbvh);
 			ss->pbvh = NULL;
 		}
 
@@ -2825,10 +2825,10 @@ void BKE_object_sculpt_modifiers_changed(Object *ob)
 		PBVHNode **nodes;
 		int n, totnode;
 
-		BLI_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
+		BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
 
 		for (n = 0; n < totnode; n++)
-			BLI_pbvh_node_mark_update(nodes[n]);
+			BKE_pbvh_node_mark_update(nodes[n]);
 
 		MEM_freeN(nodes);
 	}
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 1b6a544339d..2df2dd631d5 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -56,7 +56,7 @@ typedef struct PBVHStack {
 
 typedef struct PBVHIter {
 	PBVH *bvh;
-	BLI_pbvh_SearchCallback scb;
+	BKE_pbvh_SearchCallback scb;
 	void *search_data;
 
 	PBVHStack *stack;
@@ -132,11 +132,11 @@ static void update_node_vb(PBVH *bvh, PBVHNode *node)
 	if (node->flag & PBVH_Leaf) {
 		PBVHVertexIter vd;
 
-		BLI_pbvh_vertex_iter_begin(bvh, node, vd, PBVH_ITER_ALL)
+		BKE_pbvh_vertex_iter_begin(bvh, node, vd, PBVH_ITER_ALL)
 		{
 			BB_expand(&vb, vd.co);
 		}
-		BLI_pbvh_vertex_iter_end;
+		BKE_pbvh_vertex_iter_end;
 	}
 	else {
 		BB_expand_with_bb(&vb,
@@ -148,12 +148,12 @@ static void update_node_vb(PBVH *bvh, PBVHNode *node)
 	node->vb = vb;
 }
 
-//void BLI_pbvh_node_BB_reset(PBVHNode *node)
+//void BKE_pbvh_node_BB_reset(PBVHNode *node)
 //{
 //	BB_reset(&node->vb);
 //}
 //
-//void BLI_pbvh_node_BB_expand(PBVHNode *node, float co[3])
+//void BKE_pbvh_node_BB_expand(PBVHNode *node, float co[3])
 //{
 //	BB_expand(&node->vb, co);
 //}
@@ -493,7 +493,7 @@ static void pbvh_build(PBVH *bvh, BB *cb, BBC *prim_bbc, int totprim)
 }
 
 /* Do a full rebuild with on Mesh data structure */
-void BLI_pbvh_build_mesh(PBVH *bvh, MFace *faces, MVert *verts, int totface, int totvert, struct CustomData *vdata)
+void BKE_pbvh_build_mesh(PBVH *bvh, MFace *faces, MVert *verts, int totface, int totvert, struct CustomData *vdata)
 {
 	BBC *prim_bbc = NULL;
 	BB cb;
@@ -535,7 +535,7 @@ void BLI_pbvh_build_mesh(PBVH *bvh, MFace *faces, MVert *verts, int totface, int
 }
 
 /* Do a full rebuild with on Grids data structure */
-void BLI_pbvh_build_grids(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj,
+void BKE_pbvh_build_grids(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj,
                           int totgrid, CCGKey *key, void **gridfaces, DMFlagMat *flagmats, BLI_bitmap *grid_hidden)
 {
 	BBC *prim_bbc = NULL;
@@ -578,14 +578,14 @@ void BLI_pbvh_build_grids(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj,
 	MEM_freeN(prim_bbc);
 }
 
-PBVH *BLI_pbvh_new(void)
+PBVH *BKE_pbvh_new(void)
 {
 	PBVH *bvh = MEM_callocN(sizeof(PBVH), "pbvh");
 
 	return bvh;
 }
 
-void BLI_pbvh_free(PBVH *bvh)
+void BKE_pbvh_free(PBVH *bvh)
 {
 	PBVHNode *node;
 	int i;
@@ -600,7 +600,7 @@ void BLI_pbvh_free(PBVH *bvh)
 				MEM_freeN(node->vert_indices);
 			if (node->face_vert_indices)
 				MEM_freeN(node->face_vert_indices);
-			BLI_pbvh_node_layer_disp_free(node);
+			BKE_pbvh_node_layer_disp_free(node);
 
 			if (node->bm_faces)
 				BLI_ghash_free(node->bm_faces, NULL, NULL);
@@ -635,7 +635,7 @@ void BLI_pbvh_free(PBVH *bvh)
 	MEM_freeN(bvh);
 }
 
-static void pbvh_iter_begin(PBVHIter *iter, PBVH *bvh, BLI_pbvh_SearchCallback scb, void *search_data)
+static void pbvh_iter_begin(PBVHIter *iter, PBVH *bvh, BKE_pbvh_SearchCallback scb, void *search_data)
 {
 	iter->bvh = bvh;
 	iter->scb = scb;
@@ -746,8 +746,8 @@ static PBVHNode *pbvh_iter_next_occluded(PBVHIter *iter)
 	return NULL;
 }
 
-void BLI_pbvh_search_gather(PBVH *bvh,
-                            BLI_pbvh_SearchCallback scb, void *search_data,
+void BKE_pbvh_search_gather(PBVH *bvh,
+                            BKE_pbvh_SearchCallback scb, void *search_data,
                             PBVHNode ***r_array, int *r_tot)
 {
 	PBVHIter iter;
@@ -787,9 +787,9 @@ void BLI_pbvh_search_gather(PBVH *bvh,
 	*r_tot = tot;
 }
 
-void BLI_pbvh_search_callback(PBVH *bvh,
-                              BLI_pbvh_SearchCallback scb, void *search_data,
-                              BLI_pbvh_HitCallback hcb, void *hit_data)
+void BKE_pbvh_search_callback(PBVH *bvh,
+                              BKE_pbvh_SearchCallback scb, void *search_data,
+                              BKE_pbvh_HitCallback hcb, void *hit_data)
 {
 	PBVHIter iter;
 	PBVHNode *node;
@@ -830,7 +830,7 @@ static void node_tree_insert(node_tree *tree, node_tree *new_node)
 	}
 }
 
-static void traverse_tree(node_tree *tree, BLI_pbvh_HitOccludedCallback hcb, void *hit_data, float *tmin)
+static void traverse_tree(node_tree *tree, BKE_pbvh_HitOccludedCallback hcb, void *hit_data, float *tmin)
 {
 	if (tree->left) traverse_tree(tree->left, hcb, hit_data, tmin);
 
@@ -854,14 +854,14 @@ static void free_tree(node_tree *tree)
 	free(tree);
 }
 
-float BLI_pbvh_node_get_tmin(PBVHNode *node)
+float BKE_pbvh_node_get_tmin(PBVHNode *node)
 {
 	return node->tmin;
 }
 
-static void BLI_pbvh_search_callback_occluded(PBVH *bvh,
-                                              BLI_pbvh_SearchCallback scb, void *search_data,
-                                              BLI_pbvh_HitOccludedCallback hcb, void *hit_data)
+static void BKE_pbvh_search_callback_occluded(PBVH *bvh,
+                                              BKE_pbvh_SearchCallback scb, void *search_data,
+                                              BKE_pbvh_HitOccludedCallback hcb, void *hit_data)
 {
 	PBVHIter iter;
 	PBVHNode *node;
@@ -1134,7 +1134,7 @@ static int pbvh_flush_bb(PBVH *bvh, PBVHNode *node, int flag)
 	return update;
 }
 
-void BLI_pbvh_update(PBVH *bvh, int flag, float (*face_nors)[3])
+void BKE_pbvh_update(PBVH *bvh, int flag, float (*face_nors)[3])
 {
 	PBVHNode **nodes;
 	int totnode;
@@ -1142,7 +1142,7 @@ void BLI_pbvh_update(PBVH *bvh, int flag, float (*face_nors)[3])
 	if (!bvh->nodes)
 		return;
 
-	BLI_pbvh_search_gather(bvh, update_search_cb, SET_INT_IN_POINTER(flag),
+	BKE_pbvh_search_gather(bvh, update_search_cb, SET_INT_IN_POINTER(flag),
 	                       &nodes, &totnode);
 
 	if (flag & PBVH_UpdateNormals)
@@ -1157,7 +1157,7 @@ void BLI_pbvh_update(PBVH *bvh, int flag, float (*face_nors)[3])
 	if (nodes) MEM_freeN(nodes);
 }
 
-void BLI_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3])
+void BKE_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3])
 {
 	PBVHIter iter;
 	PBVHNode *node;
@@ -1177,7 +1177,7 @@ void BLI_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3])
 	copy_v3_v3(bb_max, bb.bmax);
 }
 
-void BLI_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***gridfaces, int *totface)
+void BKE_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***gridfaces, int *totface)
 {
 	PBVHIter iter;
 	PBVHNode *node;
@@ -1233,24 +1233,24 @@ void BLI_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***gridfaces, int *tot
 
 /***************************** PBVH Access ***********************************/
 
-PBVHType BLI_pbvh_type(const PBVH *bvh)
+PBVHType BKE_pbvh_type(const PBVH *bvh)
 {
 	return bvh->type;
 }
 
-BLI_bitmap *BLI_pbvh_grid_hidden(const PBVH *bvh)
+BLI_bitmap *BKE_pbvh_grid_hidden(const PBVH *bvh)
 {
 	BLI_assert(bvh->type == PBVH_GRIDS);
 	return bvh->grid_hidden;
 }
 
-void BLI_pbvh_get_grid_key(const PBVH *bvh, CCGKey *key)
+void BKE_pbvh_get_grid_key(const PBVH *bvh, CCGKey *key)
 {
 	BLI_assert(bvh->type == PBVH_GRIDS);
 	*key = bvh->gridkey;
 }
 
-BMesh *BLI_pbvh_get_bmesh(PBVH *bvh)
+BMesh *BKE_pbvh_get_bmesh(PBVH *bvh)
 {
 	BLI_assert(bvh->type == PBVH_BMESH);
 	return bvh->bm;
@@ -1258,17 +1258,17 @@ BMesh *BLI_pbvh_get_bmesh(PBVH *bvh)
 
 /***************************** Node Access ***********************************/
 
-void BLI_pbvh_node_mark_update(PBVHNode *node)
+void BKE_pbvh_node_mark_update(PBVHNode *node)
 {
 	node->flag |= PBVH_UpdateNormals | PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw;
 }
 
-void BLI_pbvh_node_mark_rebuild_draw(PBVHNode *node)
+void BKE_pbvh_node_mark_rebuild_draw(PBVHNode *node)
 {
 	node->flag |= PBVH_RebuildDrawBuffers | PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw;
 }
 
-void BLI_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden)
+void BKE_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden)
 {
 	BLI_assert(node->flag & PBVH_Leaf);
 	
@@ -1278,13 +1278,13 @@ void BLI_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden)
 		node->flag &= ~PBVH_FullyHidden;
 }
 
-void BLI_pbvh_node_get_verts(PBVH *bvh, PBVHNode *node, int **vert_indices, MVert **verts)
+void BKE_pbvh_node_get_verts(PBVH *bvh, PBVHNode *node, int **vert_indices, MVert **verts)
 {
 	if (vert_indices) *vert_indices = node->vert_indices;
 	if (verts) *verts = bvh->verts;
 }
 
-void BLI_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node, int *uniquevert, int *totvert)
+void BKE_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node, int *uniquevert, int *totvert)
 {
 	int tot;
 	
@@ -1306,7 +1306,7 @@ void BLI_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node, int *uniquevert, int *to
 	}
 }
 
-void BLI_pbvh_node_get_grids(PBVH *bvh, PBVHNode *node, int **grid_indices, int *totgrid, int *maxgrid, int *gridsize, CCGElem ***griddata, DMGridAdjacency **gridadj)
+void BKE_pbvh_node_get_grids(PBVH *bvh, PBVHNode *node, int **grid_indices, int *totgrid, int *maxgrid, int *gridsize, CCGElem ***griddata, DMGridAdjacency **gridadj)
 {
 	switch (bvh->type) {
 		case PBVH_GRIDS:
@@ -1329,19 +1329,19 @@ void BLI_pbvh_node_get_grids(PBVH *bvh, PBVHNode *node, int **grid_indices, int
 	}
 }
 
-void BLI_pbvh_node_get_BB(PBVHNode *node, float bb_min[3], float bb_max[3])
+void BKE_pbvh_node_get_BB(PBVHNode *node, float bb_min[3], float bb_max[3])
 {
 	copy_v3_v3(bb_min, node->vb.bmin);
 	copy_v3_v3(bb_max, node->vb.bmax);
 }
 
-void BLI_pbvh_node_get_original_BB(PBVHNode *node, float bb_min[3], float bb_max[3])
+void BKE_pbvh_node_get_original_BB(PBVHNode *node, float bb_min[3], float bb_max[3])
 {
 	copy_v3_v3(bb_min, node->orig_vb.bmin);
 	copy_v3_v3(bb_max, node->orig_vb.bmax);
 }
 
-void BLI_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *proxy_count)
+void BKE_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *proxy_count)
 {
 	if (node->proxy_count > 0) {
 		if (proxies) *proxies = node->proxies;
@@ -1366,14 +1366,14 @@ static int ray_aabb_intersect(PBVHNode *node, void *data_v)
 	float bb_min[3], bb_max[3];
 
 	if (rcd->original)
-		BLI_pbvh_node_get_original_BB(node, bb_min, bb_max);
+		BKE_pbvh_node_get_original_BB(node, bb_min, bb_max);
 	else
-		BLI_pbvh_node_get_BB(node, bb_min, bb_max);
+		BKE_pbvh_node_get_BB(node, bb_min, bb_max);
 
 	return isect_ray_aabb(&rcd->ray, bb_min, bb_max, &node->tmin);
 }
 
-void BLI_pbvh_raycast(PBVH *bvh, BLI_pbvh_HitOccludedCallback cb, void *data,
+void BKE_pbvh_raycast(PBVH *bvh, BKE_pbvh_HitOccludedCallback cb, void *data,
                       const float ray_start[3], const float ray_normal[3],
                       int original)
 {
@@ -1382,7 +1382,7 @@ void BLI_pbvh_raycast(PBVH *bvh, BLI_pbvh_HitOccludedCallback cb, void *data,
 	isect_ray_aabb_initialize(&rcd.ray, ray_start, ray_normal);
 	rcd.original = original;
 
-	BLI_pbvh_search_callback_occluded(bvh, ray_aabb_intersect, &rcd, cb, data);
+	BKE_pbvh_search_callback_occluded(bvh, ray_aabb_intersect, &rcd, cb, data);
 }
 
 int ray_face_intersection(const float ray_start[3],
@@ -1495,7 +1495,7 @@ static int pbvh_grids_node_raycast(PBVH *bvh, PBVHNode *node,
 	return hit;
 }
 
-int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3], int use_origco,
+int BKE_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3], int use_origco,
                           const float ray_start[3], const float ray_normal[3],
                           float *dist)
 {
@@ -1528,7 +1528,7 @@ typedef struct {
 	int wireframe;
 } PBVHNodeDrawData;
 
-void BLI_pbvh_node_draw(PBVHNode *node, void *data_v)
+void BKE_pbvh_node_draw(PBVHNode *node, void *data_v)
 {
 	PBVHNodeDrawData *data = data_v;
 
@@ -1595,19 +1595,19 @@ static PlaneAABBIsect test_planes_aabb(const float bb_min[3],
 	return ret;
 }
 
-int BLI_pbvh_node_planes_contain_AABB(PBVHNode *node, void *data)
+int BKE_pbvh_node_planes_contain_AABB(PBVHNode *node, void *data)
 {
 	float bb_min[3], bb_max[3];
 	
-	BLI_pbvh_node_get_BB(node, bb_min, bb_max);
+	BKE_pbvh_node_get_BB(node, bb_min, bb_max);
 	return test_planes_aabb(bb_min, bb_max, data) != ISECT_OUTSIDE;
 }
 
-int BLI_pbvh_node_planes_exclude_AABB(PBVHNode *node, void *data)
+int BKE_pbvh_node_planes_exclude_AABB(PBVHNode *node, void *data)
 {
 	float bb_min[3], bb_max[3];
 	
-	BLI_pbvh_node_get_BB(node, bb_min, bb_max);
+	BKE_pbvh_node_get_BB(node, bb_min, bb_max);
 	return test_planes_aabb(bb_min, bb_max, data) != ISECT_INSIDE;
 }
 
@@ -1620,7 +1620,7 @@ static void pbvh_node_check_diffuse_changed(PBVH *bvh, PBVHNode *node)
 		node->flag |= PBVH_UpdateDrawBuffers;
 }
 
-void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
+void BKE_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
                    DMSetMaterial setMaterial, int wireframe)
 {
 	PBVHNodeDrawData draw_data = {setMaterial, wireframe};
@@ -1630,7 +1630,7 @@ void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
 	for (a = 0; a < bvh->totnode; a++)
 		pbvh_node_check_diffuse_changed(bvh, &bvh->nodes[a]);
 
-	BLI_pbvh_search_gather(bvh, update_search_cb, SET_INT_IN_POINTER(PBVH_UpdateNormals | PBVH_UpdateDrawBuffers),
+	BKE_pbvh_search_gather(bvh, update_search_cb, SET_INT_IN_POINTER(PBVH_UpdateNormals | PBVH_UpdateDrawBuffers),
 	                       &nodes, &totnode);
 
 	pbvh_update_normals(bvh, nodes, totnode, face_nors);
@@ -1639,15 +1639,15 @@ void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
 	if (nodes) MEM_freeN(nodes);
 
 	if (planes) {
-		BLI_pbvh_search_callback(bvh, BLI_pbvh_node_planes_contain_AABB,
-		                         planes, BLI_pbvh_node_draw, &draw_data);
+		BKE_pbvh_search_callback(bvh, BKE_pbvh_node_planes_contain_AABB,
+		                         planes, BKE_pbvh_node_draw, &draw_data);
 	}
 	else {
-		BLI_pbvh_search_callback(bvh, NULL, NULL, BLI_pbvh_node_draw, &draw_data);
+		BKE_pbvh_search_callback(bvh, NULL, NULL, BKE_pbvh_node_draw, &draw_data);
 	}
 }
 
-void BLI_pbvh_grids_update(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj, void **gridfaces,
+void BKE_pbvh_grids_update(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj, void **gridfaces,
                            DMFlagMat *flagmats, BLI_bitmap *grid_hidden)
 {
 	int a;
@@ -1661,23 +1661,23 @@ void BLI_pbvh_grids_update(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj,
 		bvh->grid_hidden = grid_hidden;
 
 		for (a = 0; a < bvh->totnode; ++a)
-			BLI_pbvh_node_mark_rebuild_draw(&bvh->nodes[a]);
+			BKE_pbvh_node_mark_rebuild_draw(&bvh->nodes[a]);
 	}
 }
 
 /* Get the node's displacement layer, creating it if necessary */
-float *BLI_pbvh_node_layer_disp_get(PBVH *bvh, PBVHNode *node)
+float *BKE_pbvh_node_layer_disp_get(PBVH *bvh, PBVHNode *node)
 {
 	if (!node->layer_disp) {
 		int totvert = 0;
-		BLI_pbvh_node_num_verts(bvh, node, &totvert, NULL);
+		BKE_pbvh_node_num_verts(bvh, node, &totvert, NULL);
 		node->layer_disp = MEM_callocN(sizeof(float) * totvert, "layer disp");
 	}
 	return node->layer_disp;
 }
 
 /* If the node has a displacement layer, free it and set to null */
-void BLI_pbvh_node_layer_disp_free(PBVHNode *node)
+void BKE_pbvh_node_layer_disp_free(PBVHNode *node)
 {
 	if (node->layer_disp) {
 		MEM_freeN(node->layer_disp);
@@ -1685,7 +1685,7 @@ void BLI_pbvh_node_layer_disp_free(PBVHNode *node)
 	}
 }
 
-float (*BLI_pbvh_get_vertCos(PBVH * pbvh))[3]
+float (*BKE_pbvh_get_vertCos(PBVH * pbvh))[3]
 {
 	int a;
 	float (*vertCos)[3] = NULL;
@@ -1694,7 +1694,7 @@ float (*BLI_pbvh_get_vertCos(PBVH * pbvh))[3]
 		float *co;
 		MVert *mvert = pbvh->verts;
 
-		vertCos = MEM_callocN(3 * pbvh->totvert * sizeof(float), "BLI_pbvh_get_vertCoords");
+		vertCos = MEM_callocN(3 * pbvh->totvert * sizeof(float), "BKE_pbvh_get_vertCoords");
 		co = (float *)vertCos;
 
 		for (a = 0; a < pbvh->totvert; a++, mvert++, co += 3) {
@@ -1705,7 +1705,7 @@ float (*BLI_pbvh_get_vertCos(PBVH * pbvh))[3]
 	return vertCos;
 }
 
-void BLI_pbvh_apply_vertCos(PBVH *pbvh, float (*vertCos)[3])
+void BKE_pbvh_apply_vertCos(PBVH *pbvh, float (*vertCos)[3])
 {
 	int a;
 
@@ -1734,21 +1734,21 @@ void BLI_pbvh_apply_vertCos(PBVH *pbvh, float (*vertCos)[3])
 		BKE_mesh_calc_normals_tessface(pbvh->verts, pbvh->totvert, pbvh->faces, pbvh->totprim, NULL);
 
 		for (a = 0; a < pbvh->totnode; ++a)
-			BLI_pbvh_node_mark_update(&pbvh->nodes[a]);
+			BKE_pbvh_node_mark_update(&pbvh->nodes[a]);
 
-		BLI_pbvh_update(pbvh, PBVH_UpdateBB, NULL);
-		BLI_pbvh_update(pbvh, PBVH_UpdateOriginalBB, NULL);
+		BKE_pbvh_update(pbvh, PBVH_UpdateBB, NULL);
+		BKE_pbvh_update(pbvh, PBVH_UpdateOriginalBB, NULL);
 
 	}
 }
 
-int BLI_pbvh_isDeformed(PBVH *pbvh)
+int BKE_pbvh_isDeformed(PBVH *pbvh)
 {
 	return pbvh->deformed;
 }
 /* Proxies */
 
-PBVHProxyNode *BLI_pbvh_node_add_proxy(PBVH *bvh, PBVHNode *node)
+PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *bvh, PBVHNode *node)
 {
 	int index, totverts;
 
@@ -1764,14 +1764,14 @@ PBVHProxyNode *BLI_pbvh_node_add_proxy(PBVH *bvh, PBVHNode *node)
 		else
 			node->proxies = MEM_mallocN(sizeof(PBVHProxyNode), "PBVHNodeProxy");
 
-		BLI_pbvh_node_num_verts(bvh, node, &totverts, NULL);
+		BKE_pbvh_node_num_verts(bvh, node, &totverts, NULL);
 		node->proxies[index].co = MEM_callocN(sizeof(float[3]) * totverts, "PBVHNodeProxy.co");
 	}
 
 	return node->proxies + index;
 }
 
-void BLI_pbvh_node_free_proxies(PBVHNode *node)
+void BKE_pbvh_node_free_proxies(PBVHNode *node)
 {
 	#pragma omp critical
 	{
@@ -1789,7 +1789,7 @@ void BLI_pbvh_node_free_proxies(PBVHNode *node)
 	}
 }
 
-void BLI_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***r_array,  int *r_tot)
+void BKE_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***r_array,  int *r_tot)
 {
 	PBVHNode **array = NULL, **newarray, *node;
 	int tot = 0, space = 0;
@@ -1802,7 +1802,7 @@ void BLI_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***r_array,  int *r_tot)
 			if (tot == space) {
 				/* resize array if needed */
 				space = (tot == 0) ? 32 : space * 2;
-				newarray = MEM_callocN(sizeof(PBVHNode) * space, "BLI_pbvh_gather_proxies");
+				newarray = MEM_callocN(sizeof(PBVHNode) * space, "BKE_pbvh_gather_proxies");
 
 				if (array) {
 					memcpy(newarray, array, sizeof(PBVHNode) * tot);
@@ -1839,9 +1839,9 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node,
 	vi->fno = 0;
 	vi->mvert = 0;
 	
-	BLI_pbvh_node_get_grids(bvh, node, &grid_indices, &totgrid, NULL, &gridsize, &grids, NULL);
-	BLI_pbvh_node_num_verts(bvh, node, &uniq_verts, &totvert);
-	BLI_pbvh_node_get_verts(bvh, node, &vert_indices, &verts);
+	BKE_pbvh_node_get_grids(bvh, node, &grid_indices, &totgrid, NULL, &gridsize, &grids, NULL);
+	BKE_pbvh_node_num_verts(bvh, node, &uniq_verts, &totvert);
+	BKE_pbvh_node_get_verts(bvh, node, &vert_indices, &verts);
 	vi->key = &bvh->gridkey;
 	
 	vi->grids = grids;
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index 9cc8fd09c73..30a032229b7 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -999,7 +999,7 @@ void pbvh_bmesh_normals_update(PBVHNode **nodes, int totnode)
 /***************************** Public API *****************************/
 
 /* Build a PBVH from a BMesh */
-void BLI_pbvh_build_bmesh(PBVH *bvh, BMesh *bm, int smooth_shading,
+void BKE_pbvh_build_bmesh(PBVH *bvh, BMesh *bm, int smooth_shading,
 						  BMLog *log)
 {
 	BMIter iter;
@@ -1009,7 +1009,7 @@ void BLI_pbvh_build_bmesh(PBVH *bvh, BMesh *bm, int smooth_shading,
 
 	bvh->bm = bm;
 
-	BLI_pbvh_bmesh_detail_size_set(bvh, 0.75);
+	BKE_pbvh_bmesh_detail_size_set(bvh, 0.75);
 
 	bvh->type = PBVH_BMESH;
 	bvh->bm_face_to_node = BLI_ghash_ptr_new("bm_face_to_node");
@@ -1038,7 +1038,7 @@ void BLI_pbvh_build_bmesh(PBVH *bvh, BMesh *bm, int smooth_shading,
 }
 
 /* Collapse short edges, subdivide long edges */
-int BLI_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode,
+int BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode,
 								   const float center[3], float radius)
 {
 	BLI_buffer_declare(BMFace*, edge_faces, 8);
@@ -1085,7 +1085,7 @@ int BLI_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode,
 
 /* In order to perform operations on the original node coordinates
  * (such as raycast), store the node's triangles and vertices.*/
-void BLI_pbvh_bmesh_node_save_orig(PBVHNode *node)
+void BKE_pbvh_bmesh_node_save_orig(PBVHNode *node)
 {
 	GHashIterator gh_iter;
 	int i, totvert, tottri;
@@ -1134,7 +1134,7 @@ void BLI_pbvh_bmesh_node_save_orig(PBVHNode *node)
 	node->bm_tot_ortri = i;
 }
 
-void BLI_pbvh_bmesh_after_stroke(PBVH *bvh)
+void BKE_pbvh_bmesh_after_stroke(PBVH *bvh)
 {
 	int i;
 	for (i = 0; i < bvh->totnode; i++) {
@@ -1150,23 +1150,23 @@ void BLI_pbvh_bmesh_after_stroke(PBVH *bvh)
 	}
 }
 
-void BLI_pbvh_bmesh_detail_size_set(PBVH *bvh, float detail_size)
+void BKE_pbvh_bmesh_detail_size_set(PBVH *bvh, float detail_size)
 {
 	bvh->bm_max_edge_len = detail_size;
 	bvh->bm_min_edge_len = bvh->bm_max_edge_len * 0.4;
 }
 
-void BLI_pbvh_node_mark_topology_update(PBVHNode *node)
+void BKE_pbvh_node_mark_topology_update(PBVHNode *node)
 {
 	node->flag |= PBVH_UpdateTopology;
 }
 
-GHash *BLI_pbvh_bmesh_node_unique_verts(PBVHNode *node)
+GHash *BKE_pbvh_bmesh_node_unique_verts(PBVHNode *node)
 {
 	return node->bm_unique_verts;
 }
 
-GHash *BLI_pbvh_bmesh_node_other_verts(PBVHNode *node)
+GHash *BKE_pbvh_bmesh_node_other_verts(PBVHNode *node)
 {
 	return node->bm_other_verts;
 }
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index b72499b3b14..12a82ba38d7 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -1569,7 +1569,7 @@ static void ccgdm_pbvh_update(CCGDerivedMesh *ccgdm)
 		CCGFace **faces;
 		int totface;
 
-		BLI_pbvh_get_grid_updates(ccgdm->pbvh, 1, (void ***)&faces, &totface);
+		BKE_pbvh_get_grid_updates(ccgdm->pbvh, 1, (void ***)&faces, &totface);
 		if (totface) {
 			ccgSubSurf_updateFromFaces(ccgdm->ss, 0, faces, totface);
 			ccgSubSurf_updateNormals(ccgdm->ss, faces, totface);
@@ -1707,7 +1707,7 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)
 
 	if (ccgdm->pbvh && ccgdm->multires.mmd && !fast) {
 		if (dm->numTessFaceData) {
-			BLI_pbvh_draw(ccgdm->pbvh, partial_redraw_planes, NULL,
+			BKE_pbvh_draw(ccgdm->pbvh, partial_redraw_planes, NULL,
 						  setMaterial, FALSE);
 			glShadeModel(GL_FLAT);
 		}
@@ -3026,7 +3026,7 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
 			 * when the ccgdm gets remade, the assumption is that the topology
 			 * does not change. */
 			ccgdm_create_grids(dm);
-			BLI_pbvh_grids_update(ob->sculpt->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, (void **)ccgdm->gridFaces,
+			BKE_pbvh_grids_update(ob->sculpt->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, (void **)ccgdm->gridFaces,
 			                      ccgdm->gridFlagMats, ccgdm->gridHidden);
 		}
 
@@ -3044,15 +3044,15 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
 
 		numGrids = ccgDM_getNumGrids(dm);
 
-		ob->sculpt->pbvh = ccgdm->pbvh = BLI_pbvh_new();
-		BLI_pbvh_build_grids(ccgdm->pbvh, ccgdm->gridData, ccgdm->gridAdjacency,
+		ob->sculpt->pbvh = ccgdm->pbvh = BKE_pbvh_new();
+		BKE_pbvh_build_grids(ccgdm->pbvh, ccgdm->gridData, ccgdm->gridAdjacency,
 		                     numGrids, &key, (void **) ccgdm->gridFaces, ccgdm->gridFlagMats, ccgdm->gridHidden);
 	}
 	else if (ob->type == OB_MESH) {
 		Mesh *me = ob->data;
-		ob->sculpt->pbvh = ccgdm->pbvh = BLI_pbvh_new();
+		ob->sculpt->pbvh = ccgdm->pbvh = BKE_pbvh_new();
 		BLI_assert(!(me->mface == NULL && me->mpoly != NULL)); /* BMESH ONLY complain if mpoly is valid but not mface */
-		BLI_pbvh_build_mesh(ccgdm->pbvh, me->mface, me->mvert,
+		BKE_pbvh_build_mesh(ccgdm->pbvh, me->mface, me->mvert,
 		                    me->totface, me->totvert, &me->vdata);
 	}
 
diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c
index 9cc908746e8..d50261a3b98 100644
--- a/source/blender/editors/sculpt_paint/paint_hide.c
+++ b/source/blender/editors/sculpt_paint/paint_hide.c
@@ -112,8 +112,8 @@ static void partialvis_update_mesh(Object *ob,
 	int *vert_indices;
 	int any_changed = 0, any_visible = 0, totvert, i;
 			
-	BLI_pbvh_node_num_verts(pbvh, node, NULL, &totvert);
-	BLI_pbvh_node_get_verts(pbvh, node, &vert_indices, &mvert);
+	BKE_pbvh_node_num_verts(pbvh, node, NULL, &totvert);
+	BKE_pbvh_node_get_verts(pbvh, node, &vert_indices, &mvert);
 	paint_mask = CustomData_get_layer(&me->vdata, CD_PAINT_MASK);
 
 	sculpt_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN);
@@ -136,8 +136,8 @@ static void partialvis_update_mesh(Object *ob,
 	}
 
 	if (any_changed) {
-		BLI_pbvh_node_mark_rebuild_draw(node);
-		BLI_pbvh_node_fully_hidden_set(node, !any_visible);
+		BKE_pbvh_node_mark_rebuild_draw(node);
+		BKE_pbvh_node_fully_hidden_set(node, !any_visible);
 	}
 }
 
@@ -157,11 +157,11 @@ static void partialvis_update_grids(Object *ob,
 	int *grid_indices, totgrid, any_changed, i;
 
 	/* get PBVH data */
-	BLI_pbvh_node_get_grids(pbvh, node,
+	BKE_pbvh_node_get_grids(pbvh, node,
 	                        &grid_indices, &totgrid, NULL, NULL,
 	                        &grids, NULL);
-	grid_hidden = BLI_pbvh_grid_hidden(pbvh);
-	BLI_pbvh_get_grid_key(pbvh, &key);
+	grid_hidden = BKE_pbvh_grid_hidden(pbvh);
+	BKE_pbvh_get_grid_key(pbvh, &key);
 	
 	sculpt_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN);
 	
@@ -226,8 +226,8 @@ static void partialvis_update_grids(Object *ob,
 
 	/* mark updates if anything was hidden/shown */
 	if (any_changed) {
-		BLI_pbvh_node_mark_rebuild_draw(node);
-		BLI_pbvh_node_fully_hidden_set(node, !any_visible);
+		BKE_pbvh_node_mark_rebuild_draw(node);
+		BKE_pbvh_node_fully_hidden_set(node, !any_visible);
 		multires_mark_as_modified(ob, MULTIRES_HIDDEN_MODIFIED);
 	}
 }
@@ -273,9 +273,9 @@ static void partialvis_update_bmesh(Object *ob,
 	GHash *unique, *other;
 	int any_changed = 0, any_visible = 0;
 
-	bm = BLI_pbvh_get_bmesh(pbvh);
-	unique = BLI_pbvh_bmesh_node_unique_verts(node);
-	other = BLI_pbvh_bmesh_node_other_verts(node);
+	bm = BKE_pbvh_get_bmesh(pbvh);
+	unique = BKE_pbvh_bmesh_node_unique_verts(node);
+	other = BKE_pbvh_bmesh_node_other_verts(node);
 
 	sculpt_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN);
 
@@ -296,8 +296,8 @@ static void partialvis_update_bmesh(Object *ob,
 								  &any_visible);
 
 	if (any_changed) {
-		BLI_pbvh_node_mark_rebuild_draw(node);
-		BLI_pbvh_node_fully_hidden_set(node, !any_visible);
+		BKE_pbvh_node_mark_rebuild_draw(node);
+		BKE_pbvh_node_fully_hidden_set(node, !any_visible);
 	}
 }
 
@@ -334,22 +334,22 @@ static void get_pbvh_nodes(PBVH *pbvh,
                            float clip_planes[4][4],
                            PartialVisArea mode)
 {
-	BLI_pbvh_SearchCallback cb = NULL;
+	BKE_pbvh_SearchCallback cb = NULL;
 
 	/* select search callback */
 	switch (mode) {
 		case PARTIALVIS_INSIDE:
-			cb = BLI_pbvh_node_planes_contain_AABB;
+			cb = BKE_pbvh_node_planes_contain_AABB;
 			break;
 		case PARTIALVIS_OUTSIDE:
-			cb = BLI_pbvh_node_planes_exclude_AABB;
+			cb = BKE_pbvh_node_planes_exclude_AABB;
 			break;
 		case PARTIALVIS_ALL:
 		case PARTIALVIS_MASKED:
 			break;
 	}
 	
-	BLI_pbvh_search_gather(pbvh, cb, clip_planes, nodes, totnode);
+	BKE_pbvh_search_gather(pbvh, cb, clip_planes, nodes, totnode);
 }
 
 static int hide_show_exec(bContext *C, wmOperator *op)
@@ -379,7 +379,7 @@ static int hide_show_exec(bContext *C, wmOperator *op)
 	ob->sculpt->pbvh = pbvh;
 
 	get_pbvh_nodes(pbvh, &nodes, &totnode, clip_planes, area);
-	pbvh_type = BLI_pbvh_type(pbvh);
+	pbvh_type = BKE_pbvh_type(pbvh);
 
 	/* start undo */
 	switch (action) {
diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c
index 9fe7fc1d3ac..3cf67667f39 100644
--- a/source/blender/editors/sculpt_paint/paint_mask.c
+++ b/source/blender/editors/sculpt_paint/paint_mask.c
@@ -96,7 +96,7 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
 	pbvh = dm->getPBVH(ob, dm);
 	ob->sculpt->pbvh = pbvh;
 
-	BLI_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
+	BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
 
 	sculpt_undo_push_begin("Mask flood fill");
 
@@ -105,12 +105,12 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
 
 		sculpt_undo_push_node(ob, nodes[i], SCULPT_UNDO_MASK);
 
-		BLI_pbvh_vertex_iter_begin(pbvh, nodes[i], vi, PBVH_ITER_UNIQUE) {
+		BKE_pbvh_vertex_iter_begin(pbvh, nodes[i], vi, PBVH_ITER_UNIQUE) {
 			mask_flood_fill_set_elem(vi.mask, mode, value);
-		} BLI_pbvh_vertex_iter_end;
+		} BKE_pbvh_vertex_iter_end;
 		
-		BLI_pbvh_node_mark_update(nodes[i]);
-		if (BLI_pbvh_type(pbvh) == PBVH_GRIDS)
+		BKE_pbvh_node_mark_update(nodes[i]);
+		if (BKE_pbvh_type(pbvh) == PBVH_GRIDS)
 			multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED);
 	}
 	
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 95f997d46b1..e0c8b39ece9 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -383,7 +383,7 @@ static void sculpt_orig_vert_data_update(SculptOrigVertData *orig_data,
 static int sculpt_stroke_dynamic_topology(const SculptSession *ss,
 										  const Brush *brush)
 {
-	return ((BLI_pbvh_type(ss->pbvh) == PBVH_BMESH) &&
+	return ((BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) &&
 
 			(!ss->cache || (!ss->cache->alt_smooth)) &&
 
@@ -423,7 +423,7 @@ static void paint_mesh_restore_co(Sculpt *sd, Object *ob)
 	(void)sd; /* quied unused warning */
 #endif
 
-	BLI_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
+	BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
 
 	#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
 	for (n = 0; n < totnode; n++) {
@@ -438,7 +438,7 @@ static void paint_mesh_restore_co(Sculpt *sd, Object *ob)
 
 			sculpt_orig_vert_data_unode_init(&orig_data, ob, unode);
 		
-			BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+			BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
 			{
 				sculpt_orig_vert_data_update(&orig_data, &vd);
 
@@ -452,9 +452,9 @@ static void paint_mesh_restore_co(Sculpt *sd, Object *ob)
 				}
 				if (vd.mvert) vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 			}
-			BLI_pbvh_vertex_iter_end;
+			BKE_pbvh_vertex_iter_end;
 
-			BLI_pbvh_node_mark_update(nodes[n]);
+			BKE_pbvh_node_mark_update(nodes[n]);
 		}
 	}
 
@@ -481,7 +481,7 @@ static int sculpt_get_redraw_rect(ARegion *ar, RegionView3D *rv3d,
 	if (!pbvh)
 		return 0;
 
-	BLI_pbvh_redraw_BB(pbvh, bb_min, bb_max);
+	BKE_pbvh_redraw_BB(pbvh, bb_min, bb_max);
 
 	/* convert 3D bounding box to screen space */
 	if (!paint_convert_bb_to_rect(rect,
@@ -521,7 +521,7 @@ void sculpt_get_redraw_planes(float planes[4][4], ARegion *ar,
 
 	/* clear redraw flag from nodes */
 	if (pbvh)
-		BLI_pbvh_update(pbvh, PBVH_UpdateRedraw, NULL);
+		BKE_pbvh_update(pbvh, PBVH_UpdateRedraw, NULL);
 }
 
 /************************ Brush Testing *******************/
@@ -1006,9 +1006,9 @@ static int sculpt_search_sphere_cb(PBVHNode *node, void *data_v)
 	int i;
 
 	if (data->original)
-		BLI_pbvh_node_get_original_BB(node, bb_min, bb_max);
+		BKE_pbvh_node_get_original_BB(node, bb_min, bb_max);
 	else
-		BLI_pbvh_node_get_BB(node, bb_min, bb_max);
+		BKE_pbvh_node_get_BB(node, bb_min, bb_max);
 	
 	for (i = 0; i < 3; ++i) {
 		if (bb_min[i] > center[i])
@@ -1082,7 +1082,7 @@ static void calc_area_normal(Sculpt *sd, Object *ob, float an[3], PBVHNode **nod
 		sculpt_brush_test_init(ss, &test);
 
 		if (original) {
-			BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+			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];
@@ -1091,10 +1091,10 @@ static void calc_area_normal(Sculpt *sd, Object *ob, float an[3], PBVHNode **nod
 					add_norm_if(ss->cache->view_normal, private_an, private_out_flip, fno);
 				}
 			}
-			BLI_pbvh_vertex_iter_end;
+			BKE_pbvh_vertex_iter_end;
 		}
 		else {
-			BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+			BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
 			{
 				if (sculpt_brush_test_fast(&test, vd.co)) {
 					if (vd.no) {
@@ -1108,7 +1108,7 @@ static void calc_area_normal(Sculpt *sd, Object *ob, float an[3], PBVHNode **nod
 					}
 				}
 			}
-			BLI_pbvh_vertex_iter_end;
+			BKE_pbvh_vertex_iter_end;
 		}
 
 		#pragma omp critical
@@ -1435,7 +1435,7 @@ static void do_mesh_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node,
 
 	sculpt_brush_test_init(ss, &test);
 
-	BLI_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
+	BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
 	{
 		if (sculpt_brush_test(&test, vd.co)) {
 			const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist,
@@ -1463,7 +1463,7 @@ static void do_mesh_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node,
 				vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 		}
 	}
-	BLI_pbvh_vertex_iter_end;
+	BKE_pbvh_vertex_iter_end;
 }
 
 static void do_bmesh_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node, float bstrength, int smooth_mask)
@@ -1476,7 +1476,7 @@ static void do_bmesh_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node,
 
 	sculpt_brush_test_init(ss, &test);
 
-	BLI_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
+	BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
 	{
 		if (sculpt_brush_test(&test, vd.co)) {
 			const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist,
@@ -1504,7 +1504,7 @@ static void do_bmesh_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node,
 				vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 		}
 	}
-	BLI_pbvh_vertex_iter_end;
+	BKE_pbvh_vertex_iter_end;
 }
 
 static void do_multires_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node,
@@ -1525,9 +1525,9 @@ static void do_multires_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *no
 
 	CLAMP(bstrength, 0.0f, 1.0f);
 
-	BLI_pbvh_node_get_grids(ss->pbvh, node, &grid_indices, &totgrid,
+	BKE_pbvh_node_get_grids(ss->pbvh, node, &grid_indices, &totgrid,
 	                        NULL, &gridsize, &griddata, &gridadj);
-	BLI_pbvh_get_grid_key(ss->pbvh, &key);
+	BKE_pbvh_get_grid_key(ss->pbvh, &key);
 
 	thread_num = 0;
 #ifdef _OPENMP
@@ -1661,7 +1661,7 @@ static void smooth(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode,
 	SculptSession *ss = ob->sculpt;
 	const int max_iterations = 4;
 	const float fract = 1.0f / max_iterations;
-	PBVHType type = BLI_pbvh_type(ss->pbvh);
+	PBVHType type = BKE_pbvh_type(ss->pbvh);
 	int iteration, n, count;
 	float last;
 
@@ -1721,7 +1721,7 @@ static void do_mask_brush_draw(Sculpt *sd, Object *ob, PBVHNode **nodes, int tot
 
 		sculpt_brush_test_init(ss, &test);
 
-		BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+		BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
 		{
 			if (sculpt_brush_test(&test, vd.co)) {
 				float fade = tex_strength(ss, brush, vd.co, test.dist,
@@ -1733,7 +1733,7 @@ static void do_mask_brush_draw(Sculpt *sd, Object *ob, PBVHNode **nodes, int tot
 				if (vd.mvert)
 					vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 			}
-			BLI_pbvh_vertex_iter_end;
+			BKE_pbvh_vertex_iter_end;
 		}
 	}
 }
@@ -1773,11 +1773,11 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
 		SculptBrushTest test;
 		float (*proxy)[3];
 
-		proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+		proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
 
 		sculpt_brush_test_init(ss, &test);
 
-		BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+		BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
 		{
 			if (sculpt_brush_test(&test, vd.co)) {
 				/* offset vertex */
@@ -1791,7 +1791,7 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
 					vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 			}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BKE_pbvh_vertex_iter_end;
 	}
 }
 
@@ -1829,11 +1829,11 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
 		SculptBrushTest test;
 		float (*proxy)[3];
 
-		proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+		proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
 
 		sculpt_brush_test_init(ss, &test);
 
-		BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+		BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
 		{
 			if (sculpt_brush_test(&test, vd.co)) {
 				/* offset vertex */
@@ -1856,7 +1856,7 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
 					vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 			}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BKE_pbvh_vertex_iter_end;
 	}
 }
 
@@ -1873,11 +1873,11 @@ static void do_pinch_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
 		SculptBrushTest test;
 		float (*proxy)[3];
 
-		proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+		proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
 
 		sculpt_brush_test_init(ss, &test);
 
-		BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+		BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
 		{
 			if (sculpt_brush_test(&test, vd.co)) {
 				float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist,
@@ -1892,7 +1892,7 @@ static void do_pinch_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
 					vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 			}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BKE_pbvh_vertex_iter_end;
 	}
 }
 
@@ -1924,11 +1924,11 @@ static void do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
 
 		sculpt_orig_vert_data_init(&orig_data, ob, nodes[n]);
 
-		proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+		proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
 
 		sculpt_brush_test_init(ss, &test);
 
-		BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+		BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
 		{
 			sculpt_orig_vert_data_update(&orig_data, &vd);
 
@@ -1946,7 +1946,7 @@ static void do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
 					vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 			}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BKE_pbvh_vertex_iter_end;
 	}
 }
 
@@ -1970,11 +1970,11 @@ static void do_nudge_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
 		SculptBrushTest test;
 		float (*proxy)[3];
 
-		proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+		proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
 
 		sculpt_brush_test_init(ss, &test);
 
-		BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+		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,
@@ -1987,7 +1987,7 @@ static void do_nudge_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
 					vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 			}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BKE_pbvh_vertex_iter_end;
 	}
 }
 
@@ -2019,11 +2019,11 @@ static void do_snake_hook_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
 		SculptBrushTest test;
 		float (*proxy)[3];
 
-		proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+		proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
 
 		sculpt_brush_test_init(ss, &test);
 
-		BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+		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,
@@ -2036,7 +2036,7 @@ static void do_snake_hook_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
 					vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 			}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BKE_pbvh_vertex_iter_end;
 	}
 }
 
@@ -2063,11 +2063,11 @@ static void do_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
 
 		sculpt_orig_vert_data_init(&orig_data, ob, nodes[n]);
 
-		proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+		proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
 
 		sculpt_brush_test_init(ss, &test);
 
-		BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+		BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
 		{
 			sculpt_orig_vert_data_update(&orig_data, &vd);
 
@@ -2085,7 +2085,7 @@ static void do_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
 					vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 			}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BKE_pbvh_vertex_iter_end;
 	}
 }
 
@@ -2117,11 +2117,11 @@ static void do_rotate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
 
 		sculpt_orig_vert_data_init(&orig_data, ob, nodes[n]);
 
-		proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+		proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
 
 		sculpt_brush_test_init(ss, &test);
 
-		BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+		BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
 		{
 			sculpt_orig_vert_data_update(&orig_data, &vd);
 
@@ -2141,7 +2141,7 @@ static void do_rotate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
 					vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 			}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BKE_pbvh_vertex_iter_end;
 	}
 }
 
@@ -2166,18 +2166,18 @@ static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
 		SculptOrigVertData orig_data;
 		float *layer_disp;
 		/* XXX: layer brush needs conversion to proxy but its more complicated */
-		/* proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; */
+		/* 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 = BLI_pbvh_node_layer_disp_get(ss->pbvh, nodes[n]);
+			layer_disp = BKE_pbvh_node_layer_disp_get(ss->pbvh, nodes[n]);
 		}
 		
 		sculpt_brush_test_init(ss, &test);
 
-		BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+		BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
 		{
 			sculpt_orig_vert_data_update(&orig_data, &vd);
 
@@ -2212,7 +2212,7 @@ static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
 					vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 			}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BKE_pbvh_vertex_iter_end;
 	}
 }
 
@@ -2229,11 +2229,11 @@ static void do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
 		SculptBrushTest test;
 		float (*proxy)[3];
 
-		proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+		proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
 
 		sculpt_brush_test_init(ss, &test);
 
-		BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+		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,
@@ -2251,7 +2251,7 @@ static void do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
 					vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 			}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BKE_pbvh_vertex_iter_end;
 	}
 }
 
@@ -2278,24 +2278,24 @@ static void calc_flatten_center(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
 		sculpt_brush_test_init(ss, &test);
 
 		if (ss->cache->original) {
-			BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+			BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
 			{
 				if (sculpt_brush_test_fast(&test, unode->co[vd.i])) {
 					add_v3_v3(private_fc, unode->co[vd.i]);
 					private_count++;
 				}
 			}
-			BLI_pbvh_vertex_iter_end;
+			BKE_pbvh_vertex_iter_end;
 		}
 		else {
-			BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+			BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
 			{
 				if (sculpt_brush_test_fast(&test, vd.co)) {
 					add_v3_v3(private_fc, vd.co);
 					private_count++;
 				}
 			}
-			BLI_pbvh_vertex_iter_end;
+			BKE_pbvh_vertex_iter_end;
 		}
 
 		#pragma omp critical
@@ -2345,7 +2345,7 @@ static void calc_area_normal_and_flatten_center(Sculpt *sd, Object *ob,
 		sculpt_brush_test_init(ss, &test);
 
 		if (ss->cache->original && unode->co) {
-			BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+			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 */
@@ -2359,10 +2359,10 @@ static void calc_area_normal_and_flatten_center(Sculpt *sd, Object *ob,
 					private_count++;
 				}
 			}
-			BLI_pbvh_vertex_iter_end;
+			BKE_pbvh_vertex_iter_end;
 		}
 		else {
-			BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+			BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
 			{
 				if (sculpt_brush_test_fast(&test, vd.co)) {
 					/* for area normal */
@@ -2381,7 +2381,7 @@ static void calc_area_normal_and_flatten_center(Sculpt *sd, Object *ob,
 					private_count++;
 				}
 			}
-			BLI_pbvh_vertex_iter_end;
+			BKE_pbvh_vertex_iter_end;
 		}
 
 		#pragma omp critical
@@ -2563,11 +2563,11 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
 		SculptBrushTest test;
 		float (*proxy)[3];
 
-		proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+		proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
 
 		sculpt_brush_test_init(ss, &test);
 
-		BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+		BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
 		{
 			if (sculpt_brush_test_sq(&test, vd.co)) {
 				float intr[3];
@@ -2588,7 +2588,7 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
 				}
 			}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BKE_pbvh_vertex_iter_end;
 	}
 }
 
@@ -2635,11 +2635,11 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
 		SculptBrushTest test;
 		float (*proxy)[3];
 
-		proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+		proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
 
 		sculpt_brush_test_init(ss, &test);
 
-		BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+		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)) {
@@ -2663,7 +2663,7 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
 				}
 			}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BKE_pbvh_vertex_iter_end;
 	}
 }
 
@@ -2737,11 +2737,11 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t
 		SculptBrushTest test;
 		float (*proxy)[3];
 
-		proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+		proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
 
 		sculpt_brush_test_init(ss, &test);
 
-		BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+		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)) {
@@ -2765,7 +2765,7 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t
 				}
 			}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BKE_pbvh_vertex_iter_end;
 	}
 }
 
@@ -2801,11 +2801,11 @@ static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
 		SculptBrushTest test;
 		float (*proxy)[3];
 
-		proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+		proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
 
 		sculpt_brush_test_init(ss, &test);
 
-		BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+		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)) {
@@ -2829,7 +2829,7 @@ static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
 				}
 			}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BKE_pbvh_vertex_iter_end;
 	}
 }
 
@@ -2865,11 +2865,11 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
 		SculptBrushTest test;
 		float (*proxy)[3];
 
-		proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+		proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
 
 		sculpt_brush_test_init(ss, &test);
 
-		BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+		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)) {
@@ -2893,7 +2893,7 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
 				}
 			}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BKE_pbvh_vertex_iter_end;
 	}
 }
 
@@ -2975,7 +2975,7 @@ static void sculpt_topology_update(Sculpt *sd, Object *ob, Brush *brush)
 	                      SCULPT_TOOL_THUMB,
 	                      SCULPT_TOOL_LAYER);
 
-	BLI_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, &totnode);
+	BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, &totnode);
 
 	/* Only act if some verts are inside the brush area */
 	if (totnode) {
@@ -2991,16 +2991,16 @@ static void sculpt_topology_update(Sculpt *sd, Object *ob, Brush *brush)
 			sculpt_undo_push_node(ob, nodes[n],
 			                      brush->sculpt_tool == SCULPT_TOOL_MASK ?
 			                      SCULPT_UNDO_MASK : SCULPT_UNDO_COORDS);
-			BLI_pbvh_node_mark_update(nodes[n]);
+			BKE_pbvh_node_mark_update(nodes[n]);
 
-			if (BLI_pbvh_type(ss->pbvh) == PBVH_BMESH) {
-				BLI_pbvh_node_mark_topology_update(nodes[n]);
-				BLI_pbvh_bmesh_node_save_orig(nodes[n]);
+			if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
+				BKE_pbvh_node_mark_topology_update(nodes[n]);
+				BKE_pbvh_bmesh_node_save_orig(nodes[n]);
 			}
 		}
 
-		if (BLI_pbvh_type(ss->pbvh) == PBVH_BMESH) {
-			BLI_pbvh_bmesh_update_topology(ss->pbvh, mode,
+		if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
+			BKE_pbvh_bmesh_update_topology(ss->pbvh, mode,
 										   ss->cache->location,
 			                               ss->cache->radius);
 		}
@@ -3025,7 +3025,7 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush)
 	                      SCULPT_TOOL_ROTATE,
 	                      SCULPT_TOOL_THUMB,
 	                      SCULPT_TOOL_LAYER);
-	BLI_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, &totnode);
+	BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, &totnode);
 
 	/* Only act if some verts are inside the brush area */
 	if (totnode) {
@@ -3034,7 +3034,7 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush)
 			sculpt_undo_push_node(ob, nodes[n],
 			                      brush->sculpt_tool == SCULPT_TOOL_MASK ?
 			                      SCULPT_UNDO_MASK : SCULPT_UNDO_COORDS);
-			BLI_pbvh_node_mark_update(nodes[n]);
+			BKE_pbvh_node_mark_update(nodes[n]);
 		}
 
 		if (brush_needs_sculpt_normal(brush))
@@ -3142,7 +3142,7 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob)
 	PBVHNode **nodes;
 	int totnode, n;
 
-	BLI_pbvh_gather_proxies(ss->pbvh, &nodes, &totnode);
+	BKE_pbvh_gather_proxies(ss->pbvh, &nodes, &totnode);
 
 	if (!ELEM(brush->sculpt_tool, SCULPT_TOOL_SMOOTH, SCULPT_TOOL_LAYER)) {
 		/* these brushes start from original coordinates */
@@ -3159,9 +3159,9 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob)
 			if (use_orco && !ss->bm)
 				orco = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS)->co;
 
-			BLI_pbvh_node_get_proxies(nodes[n], &proxies, &proxy_count);
+			BKE_pbvh_node_get_proxies(nodes[n], &proxies, &proxy_count);
 
-			BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+			BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
 			{
 				float val[3];
 				int p;
@@ -3186,9 +3186,9 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob)
 				if (ss->modifiers_active)
 					sculpt_flush_pbvhvert_deform(ob, &vd);
 			}
-			BLI_pbvh_vertex_iter_end;
+			BKE_pbvh_vertex_iter_end;
 
-			BLI_pbvh_node_free_proxies(nodes[n]);
+			BKE_pbvh_node_free_proxies(nodes[n]);
 		}
 	}
 
@@ -3205,7 +3205,7 @@ static void sculpt_update_keyblock(Object *ob)
 	/* Keyblock update happens after handling deformation caused by modifiers,
 	 * so ss->orig_cos would be updated with new stroke */
 	if (ss->orig_cos) vertCos = ss->orig_cos;
-	else vertCos = BLI_pbvh_get_vertCos(ss->pbvh);
+	else vertCos = BKE_pbvh_get_vertCos(ss->pbvh);
 
 	if (vertCos) {
 		sculpt_vertcos_to_key(ob, ss->kb, vertCos);
@@ -3233,13 +3233,13 @@ static void sculpt_flush_stroke_deform(Sculpt *sd, Object *ob)
 		if (ss->kb)
 			vertCos = MEM_callocN(sizeof(*vertCos) * me->totvert, "flushStrokeDeofrm keyVerts");
 
-		BLI_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
+		BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
 
 		#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
 		for (n = 0; n < totnode; n++) {
 			PBVHVertexIter vd;
 
-			BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+			BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
 			{
 				sculpt_flush_pbvhvert_deform(ob, &vd);
 
@@ -3248,7 +3248,7 @@ static void sculpt_flush_stroke_deform(Sculpt *sd, Object *ob)
 					copy_v3_v3(vertCos[index], ss->orig_cos[index]);
 				}
 			}
-			BLI_pbvh_vertex_iter_end;
+			BKE_pbvh_vertex_iter_end;
 		}
 
 		if (vertCos) {
@@ -3463,7 +3463,7 @@ void sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob,
 			ss->orig_cos = (ss->kb) ? BKE_key_convert_to_vertcos(ob, ss->kb) : mesh_getVertexCos(me, NULL);
 
 			crazyspace_build_sculpt(scene, ob, &ss->deform_imats, &ss->deform_cos);
-			BLI_pbvh_apply_vertCos(ss->pbvh, ss->deform_cos);
+			BKE_pbvh_apply_vertCos(ss->pbvh, ss->deform_cos);
 
 			for (a = 0; a < me->totvert; ++a) {
 				invert_m3(ss->deform_imats[a]);
@@ -3473,12 +3473,12 @@ void sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob,
 	else free_sculptsession_deformMats(ss);
 
 	/* if pbvh is deformed, key block is already applied to it */
-	if (ss->kb && !BLI_pbvh_isDeformed(ss->pbvh)) {
+	if (ss->kb && !BKE_pbvh_isDeformed(ss->pbvh)) {
 		float (*vertCos)[3] = BKE_key_convert_to_vertcos(ob, ss->kb);
 
 		if (vertCos) {
 			/* apply shape keys coordinates to PBVH */
-			BLI_pbvh_apply_vertCos(ss->pbvh, vertCos);
+			BKE_pbvh_apply_vertCos(ss->pbvh, vertCos);
 			MEM_freeN(vertCos);
 		}
 	}
@@ -3614,7 +3614,7 @@ static void sculpt_omp_start(Sculpt *sd, SculptSession *ss)
 
 	if (ss->multires) {
 		int i, gridsize, array_mem_size;
-		BLI_pbvh_node_get_grids(ss->pbvh, NULL, NULL, NULL, NULL,
+		BKE_pbvh_node_get_grids(ss->pbvh, NULL, NULL, NULL, NULL,
 		                        &gridsize, NULL, NULL);
 
 		array_mem_size = cache->num_threads * sizeof(void *);
@@ -4045,13 +4045,13 @@ typedef struct {
 
 static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin)
 {
-	if (BLI_pbvh_node_get_tmin(node) < *tmin) {
+	if (BKE_pbvh_node_get_tmin(node) < *tmin) {
 		SculptRaycastData *srd = data_v;
 		float (*origco)[3] = NULL;
 		int use_origco = FALSE;
 
 		if (srd->original && srd->ss->cache) {
-			if (BLI_pbvh_type(srd->ss->pbvh) == PBVH_BMESH) {
+			if (BKE_pbvh_type(srd->ss->pbvh) == PBVH_BMESH) {
 				use_origco = TRUE;
 			}
 			else {
@@ -4062,7 +4062,7 @@ static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin)
 			}
 		}
 
-		if (BLI_pbvh_node_raycast(srd->ss->pbvh, node, origco, use_origco,
+		if (BKE_pbvh_node_raycast(srd->ss->pbvh, node, origco, use_origco,
 								  srd->ray_start, srd->ray_normal, &srd->dist))
 		{
 			srd->hit = 1;
@@ -4113,7 +4113,7 @@ int sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2])
 	srd.dist = dist;
 	srd.hit = 0;
 	srd.original = (cache) ? cache->original : 0;
-	BLI_pbvh_raycast(ss->pbvh, sculpt_raycast_cb, &srd,
+	BKE_pbvh_raycast(ss->pbvh, sculpt_raycast_cb, &srd,
 	                 ray_start, ray_normal, srd.original);
 	
 	copy_v3_v3(out, ray_normal);
@@ -4196,7 +4196,7 @@ static void sculpt_flush_update(bContext *C)
 	else {
 		rcti r;
 
-		BLI_pbvh_update(ss->pbvh, PBVH_UpdateBB, NULL);
+		BKE_pbvh_update(ss->pbvh, PBVH_UpdateBB, NULL);
 		if (sculpt_get_redraw_rect(ar, CTX_wm_region_view3d(C), ob, &r)) {
 			if (ss->cache)
 				ss->cache->previous_r = r;
@@ -4257,7 +4257,7 @@ static void sculpt_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
 	sculpt_update_cache_variants(C, sd, ob, stroke, itemptr);
 	sculpt_restore_mesh(sd, ob);
 
-	BLI_pbvh_bmesh_detail_size_set(ss->pbvh,
+	BKE_pbvh_bmesh_detail_size_set(ss->pbvh,
 								   (ss->cache->radius /
 									(float)ss->cache->pixel_radius) *
 								   (float)sd->detail_size);
@@ -4336,10 +4336,10 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
 
 		sculpt_undo_push_end();
 
-		BLI_pbvh_update(ss->pbvh, PBVH_UpdateOriginalBB, NULL);
+		BKE_pbvh_update(ss->pbvh, PBVH_UpdateOriginalBB, NULL);
 		
-		if (BLI_pbvh_type(ss->pbvh) == PBVH_BMESH)
-			BLI_pbvh_bmesh_after_stroke(ss->pbvh);
+		if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH)
+			BKE_pbvh_bmesh_after_stroke(ss->pbvh);
 
 		/* optimization: if there is locked key and active modifiers present in */
 		/* the stack, keyblock is updating at each step. otherwise we could update */
@@ -4510,7 +4510,7 @@ void sculpt_pbvh_clear(Object *ob)
 
 	/* Clear out any existing DM and PBVH */
 	if (ss->pbvh)
-		BLI_pbvh_free(ss->pbvh);
+		BKE_pbvh_free(ss->pbvh);
 	ss->pbvh = NULL;
 	if (dm)
 		dm->getPBVH(NULL, dm);
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index 08e61a6d05d..c828e8c8651 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -73,10 +73,10 @@
 
 static void update_cb(PBVHNode *node, void *rebuild)
 {
-	BLI_pbvh_node_mark_update(node);
+	BKE_pbvh_node_mark_update(node);
 	if (*((int *)rebuild))
-		BLI_pbvh_node_mark_rebuild_draw(node);
-	BLI_pbvh_node_fully_hidden_set(node, 0);
+		BKE_pbvh_node_mark_rebuild_draw(node);
+	BKE_pbvh_node_fully_hidden_set(node, 0);
 }
 
 static void sculpt_undo_restore_deformed(const SculptSession *ss,
@@ -143,7 +143,7 @@ static int sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoNo
 
 			/* pbvh uses it's own mvert array, so coords should be */
 			/* propagated to pbvh here */
-			BLI_pbvh_apply_vertCos(ss->pbvh, vertCos);
+			BKE_pbvh_apply_vertCos(ss->pbvh, vertCos);
 
 			MEM_freeN(vertCos);
 		}
@@ -443,8 +443,8 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
 		/* we update all nodes still, should be more clever, but also
 		 * needs to work correct when exiting/entering sculpt mode and
 		 * the nodes get recreated, though in that case it could do all */
-		BLI_pbvh_search_callback(ss->pbvh, NULL, NULL, update_cb, &rebuild);
-		BLI_pbvh_update(ss->pbvh, PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw, NULL);
+		BKE_pbvh_search_callback(ss->pbvh, NULL, NULL, update_cb, &rebuild);
+		BKE_pbvh_update(ss->pbvh, PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw, NULL);
 
 		if ((mmd = sculpt_multires_active(scene, ob))) {
 			if (rebuild)
@@ -531,9 +531,9 @@ static void sculpt_undo_alloc_and_store_hidden(PBVH *pbvh,
 	BLI_bitmap *grid_hidden;
 	int i, *grid_indices, totgrid;
 
-	grid_hidden = BLI_pbvh_grid_hidden(pbvh);
+	grid_hidden = BKE_pbvh_grid_hidden(pbvh);
 
-	BLI_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid,
+	BKE_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid,
 	                        NULL, NULL, NULL, NULL);
 			
 	unode->grid_hidden = MEM_mapallocN(sizeof(BLI_bitmap) * totgrid,
@@ -561,8 +561,8 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node,
 	unode->node = node;
 
 	if (node) {
-		BLI_pbvh_node_num_verts(ss->pbvh, node, &totvert, &allvert);
-		BLI_pbvh_node_get_grids(ss->pbvh, node, &grids, &totgrid,
+		BKE_pbvh_node_num_verts(ss->pbvh, node, &totvert, &allvert);
+		BKE_pbvh_node_get_grids(ss->pbvh, node, &grids, &totgrid,
 								&maxgrid, &gridsize, NULL, NULL);
 
 		unode->totvert = totvert;
@@ -624,7 +624,7 @@ static void sculpt_undo_store_coords(Object *ob, SculptUndoNode *unode)
 	SculptSession *ss = ob->sculpt;
 	PBVHVertexIter vd;
 
-	BLI_pbvh_vertex_iter_begin(ss->pbvh, unode->node, vd, PBVH_ITER_ALL)
+	BKE_pbvh_vertex_iter_begin(ss->pbvh, unode->node, vd, PBVH_ITER_ALL)
 	{
 		copy_v3_v3(unode->co[vd.i], vd.co);
 		if (vd.no) copy_v3_v3_short(unode->no[vd.i], vd.no);
@@ -633,7 +633,7 @@ static void sculpt_undo_store_coords(Object *ob, SculptUndoNode *unode)
 		if (ss->modifiers_active)
 			copy_v3_v3(unode->orig_co[vd.i], ss->orig_cos[unode->index[vd.i]]);
 	}
-	BLI_pbvh_vertex_iter_end;
+	BKE_pbvh_vertex_iter_end;
 }
 
 static void sculpt_undo_store_hidden(Object *ob, SculptUndoNode *unode)
@@ -649,8 +649,8 @@ static void sculpt_undo_store_hidden(Object *ob, SculptUndoNode *unode)
 		int *vert_indices, allvert;
 		int i;
 		
-		BLI_pbvh_node_num_verts(pbvh, node, NULL, &allvert);
-		BLI_pbvh_node_get_verts(pbvh, node, &vert_indices, &mvert);
+		BKE_pbvh_node_num_verts(pbvh, node, NULL, &allvert);
+		BKE_pbvh_node_get_verts(pbvh, node, &vert_indices, &mvert);
 		for (i = 0; i < allvert; i++) {
 			BLI_BITMAP_MODIFY(unode->vert_hidden, i,
 			                  mvert[vert_indices[i]].flag & ME_HIDE);
@@ -663,11 +663,11 @@ static void sculpt_undo_store_mask(Object *ob, SculptUndoNode *unode)
 	SculptSession *ss = ob->sculpt;
 	PBVHVertexIter vd;
 
-	BLI_pbvh_vertex_iter_begin(ss->pbvh, unode->node, vd, PBVH_ITER_ALL)
+	BKE_pbvh_vertex_iter_begin(ss->pbvh, unode->node, vd, PBVH_ITER_ALL)
 	{
 		unode->mask[vd.i] = *vd.mask;
 	}
-	BLI_pbvh_vertex_iter_end;
+	BKE_pbvh_vertex_iter_end;
 }
 
 static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob,
@@ -728,10 +728,10 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob,
 			case SCULPT_UNDO_MASK:
 				/* Before any vertex values get modified, ensure their
 				 * original positions are logged */
-				BLI_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_ALL) {
+				BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_ALL) {
 					BM_log_vert_before_modified(ss->bm, ss->bm_log, vd.bm_vert);
 				}
-				BLI_pbvh_vertex_iter_end;
+				BKE_pbvh_vertex_iter_end;
 				break;
 
 			case SCULPT_UNDO_DYNTOPO_BEGIN:
@@ -777,14 +777,14 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
 
 	if (unode->grids) {
 		int totgrid, *grids;
-		BLI_pbvh_node_get_grids(ss->pbvh, node, &grids, &totgrid,
+		BKE_pbvh_node_get_grids(ss->pbvh, node, &grids, &totgrid,
 		                        NULL, NULL, NULL, NULL);
 		memcpy(unode->grids, grids, sizeof(int) * totgrid);
 	}
 	else {
 		int *vert_indices, allvert;
-		BLI_pbvh_node_num_verts(ss->pbvh, node, NULL, &allvert);
-		BLI_pbvh_node_get_verts(ss->pbvh, node, &vert_indices, NULL);
+		BKE_pbvh_node_num_verts(ss->pbvh, node, NULL, &allvert);
+		BKE_pbvh_node_get_verts(ss->pbvh, node, &vert_indices, NULL);
 		memcpy(unode->index, vert_indices, sizeof(int) * unode->totvert);
 	}
 
@@ -831,7 +831,7 @@ void sculpt_undo_push_end(void)
 		}
 
 		if (unode->node)
-			BLI_pbvh_node_layer_disp_free(unode->node);
+			BKE_pbvh_node_layer_disp_free(unode->node);
 	}
 
 	undo_paint_push_end(UNDO_PAINT_MESH);
-- 
cgit v1.2.3


From b3aa368c8f43e6ea2bb1423e844645f583a54a94 Mon Sep 17 00:00:00 2001
From: Bastien Montagne 
Date: Sun, 30 Dec 2012 23:21:33 +0000
Subject: Usual UI messages-related fixes...

---
 source/blender/makesrna/intern/rna_dynamicpaint.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/makesrna/intern/rna_dynamicpaint.c b/source/blender/makesrna/intern/rna_dynamicpaint.c
index 030325494ff..99d2f6dbbda 100644
--- a/source/blender/makesrna/intern/rna_dynamicpaint.c
+++ b/source/blender/makesrna/intern/rna_dynamicpaint.c
@@ -724,7 +724,7 @@ static void rna_def_canvas_surface(BlenderRNA *brna)
 	RNA_define_verify_sdna(FALSE);
 	prop = RNA_def_property(srna, "use_color_preview", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_funcs(prop, "rna_DynamicPaint_use_color_preview_get", NULL);
-	RNA_def_property_ui_text(prop, "Use Corlor Preview", "Whether this surface has some color preview for 3D view");
+	RNA_def_property_ui_text(prop, "Use Color Preview", "Whether this surface has some color preview for 3D view");
 	RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
 	RNA_define_verify_sdna(TRUE);
 }
-- 
cgit v1.2.3


From 1aebc0e790c4abe4bdb749fbaad051d1e6c53586 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Mon, 31 Dec 2012 02:37:28 +0000
Subject: style cleanup

---
 source/blender/blenkernel/BKE_pbvh.h              |  2 +-
 source/blender/blenkernel/intern/pbvh_bmesh.c     | 10 ++++++----
 source/blender/bmesh/intern/bmesh_log.c           |  4 ++--
 source/blender/editors/sculpt_paint/sculpt.c      |  2 +-
 source/blender/editors/space_info/info_stats.c    |  2 +-
 source/blender/makesdna/DNA_scene_types.h         |  4 ++--
 source/blender/makesrna/intern/rna_object.c       |  2 +-
 source/blender/makesrna/intern/rna_sculpt_paint.c |  8 ++++----
 8 files changed, 18 insertions(+), 16 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 7e34d3a115d..63a61006606 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -69,7 +69,7 @@ void BKE_pbvh_build_grids(PBVH *bvh, struct CCGElem **grid_elems,
                           struct CCGKey *key, void **gridfaces, struct DMFlagMat *flagmats,
                           unsigned int **grid_hidden);
 void BKE_pbvh_build_bmesh(PBVH *bvh, struct BMesh *bm, int smooth_shading,
-						  struct BMLog *log);
+                          struct BMLog *log);
 
 void BKE_pbvh_free(PBVH *bvh);
 
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index 30a032229b7..5db79a61e39 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -252,7 +252,7 @@ static int pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index)
 
 	pbvh_bmesh_node_split(bvh, prim_bbc, node_index);
 
-	BLI_ghash_free(prim_bbc, NULL, (void*)MEM_freeN);
+	BLI_ghash_free(prim_bbc, NULL, (void *)MEM_freeN);
 
 	return TRUE;
 }
@@ -909,9 +909,11 @@ static int pbvh_bmesh_collapse_short_edges(PBVH *bvh, EdgeQueue *q,
 
 		/* Check that the vertices/edge still exist */
 		if (BLI_ghash_haskey(deleted_verts, v1) ||
-			BLI_ghash_haskey(deleted_verts, v2) ||
-			!(e = BM_edge_exists(v1, v2)))
+		    BLI_ghash_haskey(deleted_verts, v2) ||
+		    !(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
@@ -1153,7 +1155,7 @@ void BKE_pbvh_bmesh_after_stroke(PBVH *bvh)
 void BKE_pbvh_bmesh_detail_size_set(PBVH *bvh, float detail_size)
 {
 	bvh->bm_max_edge_len = detail_size;
-	bvh->bm_min_edge_len = bvh->bm_max_edge_len * 0.4;
+	bvh->bm_min_edge_len = bvh->bm_max_edge_len * 0.4f;
 }
 
 void BKE_pbvh_node_mark_topology_update(PBVHNode *node)
diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c
index 1e94e81e6d7..b821c9875db 100644
--- a/source/blender/bmesh/intern/bmesh_log.c
+++ b/source/blender/bmesh/intern/bmesh_log.c
@@ -540,7 +540,7 @@ void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log)
 		const unsigned id = bm_log_vert_id_get(log, v);
 		const void *key = SET_INT_IN_POINTER(id);
 		const void *val = BLI_ghash_lookup(id_to_idx, key);
-		((int*)varr)[i++] = GET_INT_FROM_POINTER(val);
+		((int *)varr)[i++] = GET_INT_FROM_POINTER(val);
 	}
 	BLI_ghash_free(id_to_idx, NULL, NULL);
 
@@ -551,7 +551,7 @@ void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log)
 		const unsigned id = bm_log_face_id_get(log, f);
 		const void *key = SET_INT_IN_POINTER(id);
 		const void *val = BLI_ghash_lookup(id_to_idx, key);
-		((int*)farr)[i++] = GET_INT_FROM_POINTER(val);
+		((int *)farr)[i++] = GET_INT_FROM_POINTER(val);
 	}
 	BLI_ghash_free(id_to_idx, NULL, NULL);
 
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index e0c8b39ece9..098d8e5006f 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -2966,7 +2966,7 @@ static void sculpt_topology_update(Sculpt *sd, Object *ob, Brush *brush)
 	data.ss = ss;
 	data.sd = sd;
 
-	radius = ss->cache->radius * 1.25;
+	radius = ss->cache->radius * 1.25f;
 
 	data.radius_squared = radius * radius;
 	data.original = ELEM4(brush->sculpt_tool,
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index 490d08284d2..3f73fc2605a 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -315,7 +315,7 @@ static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats)
 static int stats_is_object_dynamic_topology_sculpt(Object *ob)
 {
 	return (ob && (ob->mode & OB_MODE_SCULPT) &&
-			ob->sculpt && ob->sculpt->bm);
+	        ob->sculpt && ob->sculpt->bm);
 }
 
 /* Statistics displayed in info header. Called regularly on scene changes. */
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 6dcc74d74e7..fad539de284 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -1487,11 +1487,11 @@ typedef enum SculptFlags {
 	SCULPT_SHOW_DIFFUSE = (1<<9),
 
 	/* If set, the mesh will be drawn with smooth-shading in
-	   dynamic-topology mode */
+	 * dynamic-topology mode */
 	SCULPT_DYNTOPO_SMOOTH_SHADING = (1<<10),
 
 	/* If set, dynamic-topology brushes will collapse short edges in
-	   addition to subdividing long ones */
+	 * addition to subdividing long ones */
 	SCULPT_DYNTOPO_COLLAPSE = (1<<11)
 } SculptFlags;
 
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 6e81e866118..80d74c3a9fe 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -1439,7 +1439,7 @@ int rna_DupliObject_index_get(PointerRNA *ptr)
 
 int rna_Object_use_dynamic_topology_sculpting_get(PointerRNA *ptr)
 {
-	SculptSession *ss = ((Object*)ptr->id.data)->sculpt;
+	SculptSession *ss = ((Object *)ptr->id.data)->sculpt;
 	return (ss && ss->bm);
 }
 
diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c
index fb4295ddb53..17edf2944aa 100644
--- a/source/blender/makesrna/intern/rna_sculpt_paint.c
+++ b/source/blender/makesrna/intern/rna_sculpt_paint.c
@@ -347,15 +347,15 @@ static void rna_def_sculpt(BlenderRNA  *brna)
 	prop = RNA_def_property(srna, "use_smooth_shading", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "flags", SCULPT_DYNTOPO_SMOOTH_SHADING);
 	RNA_def_property_ui_text(prop, "Smooth Shading",
-							 "Show faces in dynamic-topology mode with smooth "
-							 "shading rather than flat shaded");
+	                         "Show faces in dynamic-topology mode with smooth "
+	                         "shading rather than flat shaded");
 	RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Sculpt_update");
 
 	prop = RNA_def_property(srna, "use_edge_collapse", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "flags", SCULPT_DYNTOPO_COLLAPSE);
 	RNA_def_property_ui_text(prop, "Collapse Short Edges",
-							 "In dynamic-topology mode, collapse short edges "
-							 "in addition to subdividing long ones");
+	                         "In dynamic-topology mode, collapse short edges "
+	                         "in addition to subdividing long ones");
 
 	prop = RNA_def_property(srna, "symmetrize_direction", PROP_ENUM, PROP_NONE);
 	RNA_def_property_enum_items(prop, symmetrize_direction_items);
-- 
cgit v1.2.3


From 827f9aa737e32cbb962864c25fa7ede88ccd99c5 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Mon, 31 Dec 2012 02:40:15 +0000
Subject: rename BM_edge_calc_squared_length -> BM_edge_calc_length_squared,
 matching len_v3, len_squared_v3

---
 source/blender/blenkernel/intern/pbvh_bmesh.c | 8 ++++----
 source/blender/bmesh/intern/bmesh_queries.c   | 2 +-
 source/blender/bmesh/intern/bmesh_queries.h   | 2 +-
 3 files changed, 6 insertions(+), 6 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index 5db79a61e39..d13ec78d604 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -532,7 +532,7 @@ static void edge_queue_insert(EdgeQueue *q, BLI_mempool *pool, BMEdge *e,
 static void long_edge_queue_edge_add(EdgeQueue *q, BLI_mempool *pool,
 									 BMEdge *e)
 {
-	const float len_sq = BM_edge_calc_squared_length(e);
+	const float len_sq = BM_edge_calc_length_squared(e);
 	if (len_sq > q->limit_len_squared)
 		edge_queue_insert(q, pool, e, 1.0f / len_sq);
 }
@@ -540,7 +540,7 @@ static void long_edge_queue_edge_add(EdgeQueue *q, BLI_mempool *pool,
 static void short_edge_queue_edge_add(EdgeQueue *q, BLI_mempool *pool,
 									  BMEdge *e)
 {
-	const float len_sq = BM_edge_calc_squared_length(e);
+	const float len_sq = BM_edge_calc_length_squared(e);
 	if (len_sq < q->limit_len_squared)
 		edge_queue_insert(q, pool, e, len_sq);
 }
@@ -762,7 +762,7 @@ static int pbvh_bmesh_subdivide_long_edges(PBVH *bvh, EdgeQueue *q,
 			continue;
 		}
 
-		if (BM_edge_calc_squared_length(e) <= q->limit_len_squared)
+		if (BM_edge_calc_length_squared(e) <= q->limit_len_squared)
 			continue;
 
 		any_subdivided = TRUE;
@@ -925,7 +925,7 @@ static int pbvh_bmesh_collapse_short_edges(PBVH *bvh, EdgeQueue *q,
 			continue;
 		}
 
-		if (BM_edge_calc_squared_length(e) >= min_len_squared)
+		if (BM_edge_calc_length_squared(e) >= min_len_squared)
 			continue;
 
 		any_collapsed = TRUE;
diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c
index d723e6464df..b5b6c69bd7e 100644
--- a/source/blender/bmesh/intern/bmesh_queries.c
+++ b/source/blender/bmesh/intern/bmesh_queries.c
@@ -478,7 +478,7 @@ float BM_edge_calc_length(BMEdge *e)
 /**
  * Returns edge length squared (for comparisons)
  */
-float BM_edge_calc_squared_length(BMEdge *e)
+float BM_edge_calc_length_squared(BMEdge *e)
 {
 	return len_squared_v3v3(e->v1->co, e->v2->co);
 }
diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h
index 59c3fae8c5d..a9d6719c491 100644
--- a/source/blender/bmesh/intern/bmesh_queries.h
+++ b/source/blender/bmesh/intern/bmesh_queries.h
@@ -37,7 +37,7 @@ int     BM_vert_in_edge(BMEdge *e, BMVert *v);
 int     BM_verts_in_edge(BMVert *v1, BMVert *v2, BMEdge *e);
 
 float   BM_edge_calc_length(BMEdge *e);
-float   BM_edge_calc_squared_length(BMEdge *e);
+float   BM_edge_calc_length_squared(BMEdge *e);
 int     BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb);
 int     BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb);
 BMVert *BM_edge_other_vert(BMEdge *e, BMVert *v);
-- 
cgit v1.2.3


From c9d16fd22cb55666225044604d2da3c4156de4ae Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Mon, 31 Dec 2012 07:06:51 +0000
Subject: add ".hh" as an extension for source scripts.

---
 source/blender/blenkernel/intern/pbvh_bmesh.c  | 3 ---
 source/blender/blenkernel/intern/pbvh_intern.h | 2 +-
 source/tests/check_deprecated.py               | 4 ++--
 3 files changed, 3 insertions(+), 6 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index d13ec78d604..5d60957abcb 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -20,9 +20,6 @@
 
 #include "MEM_guardedalloc.h"
 
-#include "DNA_object_types.h"
-
-#include "BLI_array.h"
 #include "BLI_buffer.h"
 #include "BLI_ghash.h"
 #include "BLI_heap.h"
diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h
index d8365ce8006..b3f7bf6e3d1 100644
--- a/source/blender/blenkernel/intern/pbvh_intern.h
+++ b/source/blender/blenkernel/intern/pbvh_intern.h
@@ -35,7 +35,7 @@ typedef struct {
  * union'd structs */
 struct PBVHNode {
 	/* Opaque handle for drawing code */
-	GPU_Buffers *draw_buffers;
+	struct GPU_Buffers *draw_buffers;
 
 	/* Voxel bounds */
 	BB vb;
diff --git a/source/tests/check_deprecated.py b/source/tests/check_deprecated.py
index c5c7bdcdcb0..bb9fcd818d2 100644
--- a/source/tests/check_deprecated.py
+++ b/source/tests/check_deprecated.py
@@ -31,12 +31,12 @@ SKIP_DIRS = ("extern",
 
 def is_c_header(filename):
     ext = splitext(filename)[1]
-    return (ext in (".h", ".hpp", ".hxx"))
+    return (ext in {".h", ".hpp", ".hxx", ".hh"})
 
 
 def is_c(filename):
     ext = splitext(filename)[1]
-    return (ext in (".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl"))
+    return (ext in {".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl"})
 
 
 def is_c_any(filename):
-- 
cgit v1.2.3


From bec3b34d257cdfbfb9e12c57dfa672e98d0f587a Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Mon, 31 Dec 2012 12:13:30 +0000
Subject: Bug fix - post 2.65a problem:

The keymap entries for NDOF device were moved up, so the hotkey searches for
menus didn't show the keyboard shortcuts. Special devices shouldn't list as a
shortcut.
---
 source/blender/editors/space_view3d/view3d_ops.c | 57 ++++++++++++------------
 1 file changed, 28 insertions(+), 29 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index 37ee778c576..615ae71cf9b 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -196,35 +196,6 @@ void view3d_keymap(wmKeyConfig *keyconf)
 	/* only for region 3D window */
 	keymap = WM_keymap_find(keyconf, "3D View", SPACE_VIEW3D, 0);
 
-
-	/* NDOF: begin */
-	/* note: positioned here so keymaps show keyboard keys if assigned */
-	/* 3D mouse */
-	WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_orbit_zoom", NDOF_MOTION, 0, 0, 0);
-	WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_orbit", NDOF_MOTION, 0, KM_CTRL, 0);
-	WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_pan", NDOF_MOTION, 0, KM_SHIFT, 0);
-	WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_all", NDOF_MOTION, 0, KM_CTRL | KM_SHIFT, 0);
-	WM_keymap_add_item(keymap, "VIEW3D_OT_view_selected", NDOF_BUTTON_FIT, KM_PRESS, 0, 0);
-	RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_FRONT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_FRONT);
-	RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_BACK, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_BACK);
-	RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_LEFT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_LEFT);
-	RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_RIGHT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_RIGHT);
-	RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_TOP, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_TOP);
-	RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_BOTTOM, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_BOTTOM);
-
-	/* 3D mouse align */
-	kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_FRONT, KM_PRESS, KM_SHIFT, 0);
-	RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_FRONT);
-	RNA_boolean_set(kmi->ptr, "align_active", TRUE);
-	kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_RIGHT, KM_PRESS, KM_SHIFT, 0);
-	RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_RIGHT);
-	RNA_boolean_set(kmi->ptr, "align_active", TRUE);
-	kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_TOP, KM_PRESS, KM_SHIFT, 0);
-	RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_TOP);
-	RNA_boolean_set(kmi->ptr, "align_active", TRUE);
-	/* NDOF: end */
-
-
 	kmi = WM_keymap_verify_item(keymap, "VIEW3D_OT_manipulator", LEFTMOUSE, KM_PRESS, KM_ANY, 0);
 	RNA_boolean_set(kmi->ptr, "release_confirm", TRUE);
 	/*
@@ -333,6 +304,34 @@ void view3d_keymap(wmKeyConfig *keyconf)
 
 	WM_keymap_add_item(keymap, "VIEW3D_OT_localview", PADSLASHKEY, KM_PRESS, 0, 0);
 	
+	/* NDOF: begin */
+	/* note: positioned here so keymaps show keyboard keys if assigned */
+	/* 3D mouse */
+	WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_orbit_zoom", NDOF_MOTION, 0, 0, 0);
+	WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_orbit", NDOF_MOTION, 0, KM_CTRL, 0);
+	WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_pan", NDOF_MOTION, 0, KM_SHIFT, 0);
+	WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_all", NDOF_MOTION, 0, KM_CTRL | KM_SHIFT, 0);
+	WM_keymap_add_item(keymap, "VIEW3D_OT_view_selected", NDOF_BUTTON_FIT, KM_PRESS, 0, 0);
+	RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_FRONT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_FRONT);
+	RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_BACK, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_BACK);
+	RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_LEFT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_LEFT);
+	RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_RIGHT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_RIGHT);
+	RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_TOP, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_TOP);
+	RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_BOTTOM, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_BOTTOM);
+	
+	/* 3D mouse align */
+	kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_FRONT, KM_PRESS, KM_SHIFT, 0);
+	RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_FRONT);
+	RNA_boolean_set(kmi->ptr, "align_active", TRUE);
+	kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_RIGHT, KM_PRESS, KM_SHIFT, 0);
+	RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_RIGHT);
+	RNA_boolean_set(kmi->ptr, "align_active", TRUE);
+	kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_TOP, KM_PRESS, KM_SHIFT, 0);
+	RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_TOP);
+	RNA_boolean_set(kmi->ptr, "align_active", TRUE);
+	/* NDOF: end */
+	
+
 	/* layers, shift + alt are properties set in invoke() */
 	RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", ACCENTGRAVEKEY, KM_PRESS, 0, 0)->ptr, "nr", 0);
 	RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", ONEKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 1);
-- 
cgit v1.2.3


From fc6784126bf06dad15a9a84fcb15773f9caa70c8 Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Mon, 31 Dec 2012 12:26:14 +0000
Subject: Usability todo:

Editmode "Shear" didn't communicate well.
- Added X and Y shortcut to set shear axis
- Added print in header to denote that.

It will still switch with MMB press too.
---
 source/blender/editors/transform/transform.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index f861d41c260..39bad76b3d7 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -2721,6 +2721,18 @@ int handleEventShear(TransInfo *t, wmEvent *event)
 
 		status = 1;
 	}
+	else if (event->type == XKEY && event->val == KM_PRESS) {
+		initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_ABSOLUTE);
+		t->customData = NULL;
+		
+		status = 1;
+	}
+	else if (event->type == YKEY && event->val == KM_PRESS) {
+		initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE);
+		t->customData = (void *)1;
+		
+		status = 1;
+	}
 	
 	return status;
 }
@@ -2754,7 +2766,7 @@ int Shear(TransInfo *t, const int UNUSED(mval[2]))
 	}
 	else {
 		/* default header print */
-		sprintf(str, "Shear: %.3f %s", value, t->proptext);
+		sprintf(str, "Shear: %.3f %s (Press X or Y to set shear axis)", value, t->proptext);
 	}
 	
 	t->values[0] = value;
-- 
cgit v1.2.3


From 97c6a55c39e1a1949e04cf491946f8b275e2efb5 Mon Sep 17 00:00:00 2001
From: Brecht Van Lommel 
Date: Mon, 31 Dec 2012 13:07:06 +0000
Subject: Fix #33706: issue in cycles motion blur rendering after hair commit,
 my fault for not finding it in review.

Also removed the hard limits on motion blur shutter time, soft limits are still
the same but it can be useful to set things lower/higher in some cases.
---
 source/blender/makesrna/intern/rna_scene.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

(limited to 'source')

diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 75164a38239..5696511b614 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -3694,10 +3694,9 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
 	RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
 	RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update");
 	
-	prop = RNA_def_property(srna, "motion_blur_shutter", PROP_FLOAT, PROP_NONE);
+	prop = RNA_def_property(srna, "motion_blur_shutter", PROP_FLOAT, PROP_UNSIGNED);
 	RNA_def_property_float_sdna(prop, NULL, "blurfac");
-	RNA_def_property_range(prop, 0.01f, 10.0f);
-	RNA_def_property_ui_range(prop, 0.01, 2.0f, 1, 0);
+	RNA_def_property_ui_range(prop, 0.01f, 2.0f, 1, 0);
 	RNA_def_property_ui_text(prop, "Shutter", "Time taken in frames between shutter open and close");
 	RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
 	RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update");
-- 
cgit v1.2.3


From 08cea96ab08026ae9a3351b3e5830eda93f3106f Mon Sep 17 00:00:00 2001
From: Sergey Sharybin 
Date: Mon, 31 Dec 2012 13:52:13 +0000
Subject: Alpha premul pipeline cleanup

This assumptions are now made:
- Internally float buffers are always linear alpha-premul colors
- Readers should worry about delivering float buffers with that
  assumptions.
- There's an input image setting to say whether it's stored with
  straight/premul alpha on the disk.
- Byte buffers are now assumed have straight alpha, readers should
  deliver straight alpha.

Some implementation details:

- Removed scene's color unpremultiply setting, which was very
  much confusing and was wrong for default settings.
  Now all renderers assumes to deliver premultiplied alpha.

- IMB_buffer_byte_from_float will now linearize alpha when
  converting from buffer.

- Sequencer's effects were changed to assume bytes have got
  straight alpha. Most of effects will work with bytes still,
  however for glow it was more tricky to avoid data loss, so
  there's a commented out glow implementation which converts
  byte buffer to floats first, operates on floats and returns
  bytes back. It's slower and not sure if it should actually
  be used -- who're using glow on alpha anyway?

- Sequencer modifiers should also be working nice with straight
  bytes now.

- GLSL preview will predivide float textures to make nice shading,
  shading with byte textures worked nice (GLSL was assuming straight
  alpha).

- Blender Internal will set alpha=1 to the whole sky. The same
  happens in Cycles and there's no way to avoid this -- sky is
  neither straight nor premul and doesn't fit color pipeline well.

- Straight alpha mode for render result was also eliminated.

- Conversion to correct alpha need to be done before linearizing
  float buffer.

- TIFF will now load and save files with proper alpha mode setting
  in file meta data header.

- Remove Use Alpha from texture mapping and replaced with image
  datablock setting.

  Behaves much more predictable and clear from code point of view
  and solves possible regressions when non-premultiplied images were
  used as textures with ignoring alpha channel.
---
 source/blender/blenkernel/BKE_blender.h            |   2 +-
 source/blender/blenkernel/intern/image.c           |  59 ++--
 source/blender/blenkernel/intern/seqeffects.c      | 370 ++++++++++++---------
 source/blender/blenkernel/intern/seqmodifier.c     |  20 +-
 source/blender/blenkernel/intern/sequencer.c       | 127 ++++---
 source/blender/blenkernel/intern/texture.c         |   2 +-
 source/blender/blenlib/BLI_math_color.h            |   7 +
 source/blender/blenlib/intern/math_color_inline.c  |  83 +++--
 source/blender/blenloader/intern/readfile.c        |  30 +-
 .../blender/blenloader/intern/versioning_legacy.c  |  10 +-
 source/blender/collada/DocumentImporter.cpp        |   2 -
 source/blender/editors/render/render_preview.c     |   2 +-
 source/blender/editors/space_image/image_buttons.c |  22 +-
 source/blender/gpu/intern/gpu_draw.c               |   6 +-
 source/blender/gpu/intern/gpu_material.c           |   3 +-
 source/blender/imbuf/IMB_colormanagement.h         |   1 +
 source/blender/imbuf/IMB_imbuf.h                   |   4 +-
 source/blender/imbuf/IMB_imbuf_types.h             |   5 +-
 source/blender/imbuf/intern/IMB_filter.h           |   3 +
 source/blender/imbuf/intern/cineon/cineon_dpx.c    |   3 +
 source/blender/imbuf/intern/colormanagement.c      |  63 ++--
 source/blender/imbuf/intern/divers.c               |  81 +++--
 source/blender/imbuf/intern/filter.c               |  64 ++++
 .../blender/imbuf/intern/openexr/openexr_api.cpp   |   3 +
 source/blender/imbuf/intern/png.c                  |  21 +-
 source/blender/imbuf/intern/radiance_hdr.c         |   3 +
 source/blender/imbuf/intern/readimage.c            |  24 +-
 source/blender/imbuf/intern/scaling.c              |  35 +-
 source/blender/imbuf/intern/tiff.c                 |  52 ++-
 source/blender/makesdna/DNA_image_types.h          |  14 +-
 source/blender/makesdna/DNA_scene_types.h          |   4 +-
 source/blender/makesdna/DNA_sequence_types.h       |  13 +-
 source/blender/makesdna/DNA_texture_types.h        |   2 +-
 source/blender/makesrna/intern/rna_image.c         |  35 +-
 source/blender/makesrna/intern/rna_scene.c         |  10 +-
 source/blender/makesrna/intern/rna_sequencer.c     |  12 +-
 source/blender/makesrna/intern/rna_texture.c       |   5 -
 .../blender/nodes/composite/node_composite_util.c  |   2 +-
 .../nodes/composite/nodes/node_composite_image.c   |   3 +-
 .../blender/render/intern/include/render_result.h  |   2 +-
 source/blender/render/intern/source/imagetexture.c |  30 +-
 source/blender/render/intern/source/pipeline.c     |   6 +-
 .../blender/render/intern/source/render_result.c   |  11 +-
 source/blender/render/intern/source/rendercore.c   |  33 +-
 44 files changed, 795 insertions(+), 494 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index ecd38403d72..10528f1b270 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         265
-#define BLENDER_SUBVERSION      4
+#define BLENDER_SUBVERSION      5
 
 /* 262 was the last editmesh release but it has compatibility code for bmesh data */
 #define BLENDER_MINVERSION      262
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 8630ace4edf..b93f917c9e2 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -312,10 +312,6 @@ static void image_assign_ibuf(Image *ima, ImBuf *ibuf, int index, int frame)
 				break;
 
 		ibuf->index = index;
-		if (ima->flag & IMA_CM_PREDIVIDE)
-			ibuf->flags |= IB_cm_predivide;
-		else
-			ibuf->flags &= ~IB_cm_predivide;
 
 		/* this function accepts (link == NULL) */
 		BLI_insertlinkbefore(&ima->ibufs, link, ibuf);
@@ -552,6 +548,26 @@ int BKE_image_scale(Image *image, int width, int height)
 	return (ibuf != NULL);
 }
 
+static void image_init_color_management(Image *ima)
+{
+	ImBuf *ibuf;
+	char name[FILE_MAX];
+
+	BKE_image_user_file_path(NULL, ima, name);
+
+	/* will set input color space to image format default's */
+	ibuf = IMB_loadiffname(name, IB_test | IB_alphamode_detect, ima->colorspace_settings.name);
+
+	if (ibuf) {
+		if (ibuf->flags & IB_alphamode_premul)
+			ima->alpha_mode = IMA_ALPHA_PREMUL;
+		else
+			ima->alpha_mode = IMA_ALPHA_STRAIGHT;
+
+		IMB_freeImBuf(ibuf);
+	}
+}
+
 Image *BKE_image_load(const char *filepath)
 {
 	Image *ima;
@@ -579,6 +595,8 @@ Image *BKE_image_load(const char *filepath)
 	if (BLI_testextensie_array(filepath, imb_ext_movie))
 		ima->source = IMA_SRC_MOVIE;
 
+	image_init_color_management(ima);
+
 	return ima;
 }
 
@@ -666,7 +684,7 @@ static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char
 		/* both byte and float buffers are filling in sRGB space, need to linearize float buffer after BKE_image_buf_fill* functions */
 
 		IMB_buffer_float_from_float(rect_float, rect_float, ibuf->channels, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB,
-		                            ibuf->flags & IB_cm_predivide, ibuf->x, ibuf->y, ibuf->x, ibuf->x);
+		                            TRUE, ibuf->x, ibuf->y, ibuf->x, ibuf->x);
 	}
 
 	return ibuf;
@@ -2343,7 +2361,7 @@ void BKE_image_backup_render(Scene *scene, Image *ima)
 static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr)
 {
 	const char *colorspace = ima->colorspace_settings.name;
-	int predivide = ima->flag & IMA_CM_PREDIVIDE;
+	int predivide = ima->alpha_mode == IMA_ALPHA_PREMUL;
 
 	ima->rr = RE_MultilayerConvert(ibuf->userdata, colorspace, predivide, ibuf->x, ibuf->y);
 
@@ -2375,6 +2393,18 @@ static void image_initialize_after_load(Image *ima, ImBuf *ibuf)
 
 }
 
+static int imbuf_alpha_flags_for_image(Image *ima)
+{
+	int flag = 0;
+
+	if (ima->flag & IMA_IGNORE_ALPHA)
+		flag |= IB_ignore_alpha;
+	else if (ima->alpha_mode == IMA_ALPHA_PREMUL)
+		flag |= IB_alphamode_premul;
+
+	return flag;
+}
+
 static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame)
 {
 	struct ImBuf *ibuf;
@@ -2389,8 +2419,7 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame)
 	BKE_image_user_file_path(iuser, ima, name);
 
 	flag = IB_rect | IB_multilayer;
-	if (ima->flag & IMA_DO_PREMUL)
-		flag |= IB_premul;
+	flag |= imbuf_alpha_flags_for_image(ima);
 
 	/* read ibuf */
 	ibuf = IMB_loadiffname(name, flag, ima->colorspace_settings.name);
@@ -2549,15 +2578,14 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
 	/* is there a PackedFile with this image ? */
 	if (ima->packedfile) {
 		flag = IB_rect | IB_multilayer;
-		if (ima->flag & IMA_DO_PREMUL) flag |= IB_premul;
+		flag |= imbuf_alpha_flags_for_image(ima);
 
 		ibuf = IMB_ibImageFromMemory((unsigned char *)ima->packedfile->data, ima->packedfile->size, flag,
 		                             ima->colorspace_settings.name, "");
 	}
 	else {
 		flag = IB_rect | IB_multilayer | IB_metadata;
-		if (ima->flag & IMA_DO_PREMUL)
-			flag |= IB_premul;
+		flag |= imbuf_alpha_flags_for_image(ima);
 
 		/* get the right string */
 		BKE_image_user_frame_calc(iuser, cfra, 0);
@@ -2777,15 +2805,6 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_
 
 	ibuf->dither = dither;
 
-	if (iuser->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE) {
-		ibuf->flags |= IB_cm_predivide;
-		ima->flag |= IMA_CM_PREDIVIDE;
-	}
-	else {
-		ibuf->flags &= ~IB_cm_predivide;
-		ima->flag &= ~IMA_CM_PREDIVIDE;
-	}
-
 	ima->ok = IMA_OK_LOADED;
 
 	return ibuf;
diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c
index 3bff209f53c..7dbbca6ddaa 100644
--- a/source/blender/blenkernel/intern/seqeffects.c
+++ b/source/blender/blenkernel/intern/seqeffects.c
@@ -156,42 +156,43 @@ static void init_alpha_over_or_under(Sequence *seq)
 	seq->seq1 = seq2;
 }
 
-static void do_alphaover_effect_byte(float facf0, float facf1, int x, int y,  char *rect1, char *rect2, char *out)
+static void do_alphaover_effect_byte(float facf0, float facf1, int x, int y,  unsigned char *rect1, unsigned char *rect2, unsigned char *out)
 {
-	int fac2, mfac, fac, fac4;
-	int xo, tempc;
-	char *rt1, *rt2, *rt;
+	float fac2, mfac, fac, fac4;
+	int xo;
+	unsigned char *cp1, *cp2, *rt;
+	float tempc[4], rt1[4], rt2[4];
 
 	xo = x;
-	rt1 = (char *) rect1;
-	rt2 = (char *) rect2;
-	rt = (char *) out;
+	cp1 = rect1;
+	cp2 = rect2;
+	rt = out;
 
-	fac2 = (int) (256.0f * facf0);
-	fac4 = (int) (256.0f * facf1);
+	fac2 = facf0;
+	fac4 = facf1;
 
 	while (y--) {
 		x = xo;
 		while (x--) {
-
 			/* rt = rt1 over rt2  (alpha from rt1) */
 
+			straight_uchar_to_premul_float(rt1, cp1);
+			straight_uchar_to_premul_float(rt2, cp2);
+
 			fac = fac2;
-			mfac = 256 - ( (fac2 * rt1[3]) >> 8);
+			mfac = 1.0f - fac2 * rt1[3];
 
-			if (fac == 0) *( (unsigned int *) rt) = *( (unsigned int *) rt2);
-			else if (mfac == 0) *( (unsigned int *) rt) = *( (unsigned int *) rt1);
+			if (fac <= 0.0f) *( (unsigned int *) rt) = *( (unsigned int *) cp2);
+			else if (mfac <= 0.0f) *( (unsigned int *) rt) = *( (unsigned int *) cp1);
 			else {
-				tempc = (fac * rt1[0] + mfac * rt2[0]) >> 8;
-				if (tempc > 255) rt[0] = 255; else rt[0] = tempc;
-				tempc = (fac * rt1[1] + mfac * rt2[1]) >> 8;
-				if (tempc > 255) rt[1] = 255; else rt[1] = tempc;
-				tempc = (fac * rt1[2] + mfac * rt2[2]) >> 8;
-				if (tempc > 255) rt[2] = 255; else rt[2] = tempc;
-				tempc = (fac * rt1[3] + mfac * rt2[3]) >> 8;
-				if (tempc > 255) rt[3] = 255; else rt[3] = tempc;
+				tempc[0] = fac * rt1[0] + mfac * rt2[0];
+				tempc[1] = fac * rt1[1] + mfac * rt2[1];
+				tempc[2] = fac * rt1[2] + mfac * rt2[2];
+				tempc[3] = fac * rt1[3] + mfac * rt2[3];
+
+				premul_float_to_straight_uchar(rt, tempc);
 			}
-			rt1 += 4; rt2 += 4; rt += 4;
+			cp1 += 4; cp2 += 4; rt += 4;
 		}
 
 		if (y == 0) break;
@@ -199,22 +200,23 @@ static void do_alphaover_effect_byte(float facf0, float facf1, int x, int y,  ch
 
 		x = xo;
 		while (x--) {
+			straight_uchar_to_premul_float(rt1, cp1);
+			straight_uchar_to_premul_float(rt2, cp2);
+
 			fac = fac4;
-			mfac = 256 - ( (fac4 * rt1[3]) >> 8);
+			mfac = 1.0f - (fac4 * rt1[3]);
 
-			if (fac == 0) *( (unsigned int *) rt) = *( (unsigned int *) rt2);
-			else if (mfac == 0) *( (unsigned int *) rt) = *( (unsigned int *) rt1);
+			if (fac <= 0.0f) *( (unsigned int *) rt) = *( (unsigned int *) cp2);
+			else if (mfac <= 0.0f) *( (unsigned int *) rt) = *( (unsigned int *) cp1);
 			else {
-				tempc = (fac * rt1[0] + mfac * rt2[0]) >> 8;
-				if (tempc > 255) rt[0] = 255; else rt[0] = tempc;
-				tempc = (fac * rt1[1] + mfac * rt2[1]) >> 8;
-				if (tempc > 255) rt[1] = 255; else rt[1] = tempc;
-				tempc = (fac * rt1[2] + mfac * rt2[2]) >> 8;
-				if (tempc > 255) rt[2] = 255; else rt[2] = tempc;
-				tempc = (fac * rt1[3] + mfac * rt2[3]) >> 8;
-				if (tempc > 255) rt[3] = 255; else rt[3] = tempc;
+				tempc[0] = fac * rt1[0] + mfac * rt2[0];
+				tempc[1] = fac * rt1[1] + mfac * rt2[1];
+				tempc[2] = fac * rt1[2] + mfac * rt2[2];
+				tempc[3] = fac * rt1[3] + mfac * rt2[3];
+
+				premul_float_to_straight_uchar(rt, tempc);
 			}
-			rt1 += 4; rt2 += 4; rt += 4;
+			cp1 += 4; cp2 += 4; rt += 4;
 		}
 	}
 }
@@ -298,17 +300,17 @@ static void do_alphaover_effect(SeqRenderData context, Sequence *UNUSED(seq), fl
 
 		slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
 
-		do_alphaover_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out);
+		do_alphaover_effect_byte(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
 	}
 }
 
 /*********************** Alpha Under *************************/
 
-static void do_alphaunder_effect_byte(float facf0, float facf1, int x, int y, char *rect1, char *rect2, char *out)
+static void do_alphaunder_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out)
 {
 	int fac2, mfac, fac, fac4;
 	int xo;
-	char *rt1, *rt2, *rt;
+	unsigned char *rt1, *rt2, *rt;
 
 	xo = x;
 	rt1 = rect1;
@@ -460,17 +462,17 @@ static void do_alphaunder_effect(SeqRenderData context, Sequence *UNUSED(seq), f
 
 		slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
 
-		do_alphaunder_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out);
+		do_alphaunder_effect_byte(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
 	}
 }
 
 /*********************** Cross *************************/
 
-static void do_cross_effect_byte(float facf0, float facf1, int x, int y, char *rect1, char *rect2, char *out)
+static void do_cross_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out)
 {
 	int fac1, fac2, fac3, fac4;
 	int xo;
-	char *rt1, *rt2, *rt;
+	unsigned char *rt1, *rt2, *rt;
 
 	xo = x;
 	rt1 = rect1;
@@ -570,7 +572,7 @@ static void do_cross_effect(SeqRenderData context, Sequence *UNUSED(seq), float
 
 		slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
 
-		do_cross_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out);
+		do_cross_effect_byte(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
 	}
 }
 
@@ -713,31 +715,32 @@ static void free_gammacross(Sequence *UNUSED(seq))
 static void do_gammacross_effect_byte(float facf0, float UNUSED(facf1),  int x, int y, unsigned char *rect1,
                                       unsigned char *rect2, unsigned char *out)
 {
-	int fac1, fac2, col;
+	float fac1, fac2;
 	int xo;
-	unsigned char *rt1, *rt2, *rt;
-	
+	unsigned char *cp1, *cp2, *rt;
+	float rt1[4], rt2[4], tempc[4];
+
 	xo = x;
-	rt1 = (unsigned char *) rect1;
-	rt2 = (unsigned char *) rect2;
-	rt = (unsigned char *) out;
+	cp1 = rect1;
+	cp2 = rect2;
+	rt = out;
 
-	fac2 = (int)(256.0f * facf0);
-	fac1 = 256 - fac2;
+	fac2 = facf0;
+	fac1 = 1.0f - fac2;
 
 	while (y--) {
 		x = xo;
 		while (x--) {
-			col = (fac1 * igamtab1[rt1[0]] + fac2 * igamtab1[rt2[0]]) >> 8;
-			if (col > 65535) rt[0] = 255; else rt[0] = ( (char *)(gamtab + col))[MOST_SIG_BYTE];
-			col = (fac1 * igamtab1[rt1[1]] + fac2 * igamtab1[rt2[1]]) >> 8;
-			if (col > 65535) rt[1] = 255; else rt[1] = ( (char *)(gamtab + col))[MOST_SIG_BYTE];
-			col = (fac1 * igamtab1[rt1[2]] + fac2 * igamtab1[rt2[2]]) >> 8;
-			if (col > 65535) rt[2] = 255; else rt[2] = ( (char *)(gamtab + col))[MOST_SIG_BYTE];
-			col = (fac1 * igamtab1[rt1[3]] + fac2 * igamtab1[rt2[3]]) >> 8;
-			if (col > 65535) rt[3] = 255; else rt[3] = ( (char *)(gamtab + col))[MOST_SIG_BYTE];
+			straight_uchar_to_premul_float(rt1, cp1);
+			straight_uchar_to_premul_float(rt2, cp2);
 
-			rt1 += 4; rt2 += 4; rt += 4;
+			tempc[0] = gammaCorrect(fac1 * invGammaCorrect(rt1[0]) + fac2 * invGammaCorrect(rt2[0]));
+			tempc[1] = gammaCorrect(fac1 * invGammaCorrect(rt1[1]) + fac2 * invGammaCorrect(rt2[1]));
+			tempc[2] = gammaCorrect(fac1 * invGammaCorrect(rt1[2]) + fac2 * invGammaCorrect(rt2[2]));
+			tempc[3] = gammaCorrect(fac1 * invGammaCorrect(rt1[3]) + fac2 * invGammaCorrect(rt2[3]));
+
+			premul_float_to_straight_uchar(rt, tempc);
+			cp1 += 4; cp2 += 4; rt += 4;
 		}
 
 		if (y == 0)
@@ -746,16 +749,16 @@ static void do_gammacross_effect_byte(float facf0, float UNUSED(facf1),  int x,
 
 		x = xo;
 		while (x--) {
-			col = (fac1 * igamtab1[rt1[0]] + fac2 * igamtab1[rt2[0]]) >> 8;
-			if (col > 65535) rt[0] = 255; else rt[0] = ( (char *)(gamtab + col))[MOST_SIG_BYTE];
-			col = (fac1 * igamtab1[rt1[1]] + fac2 * igamtab1[rt2[1]]) >> 8;
-			if (col > 65535) rt[1] = 255; else rt[1] = ( (char *)(gamtab + col))[MOST_SIG_BYTE];
-			col = (fac1 * igamtab1[rt1[2]] + fac2 * igamtab1[rt2[2]]) >> 8;
-			if (col > 65535) rt[2] = 255; else rt[2] = ( (char *)(gamtab + col))[MOST_SIG_BYTE];
-			col = (fac1 * igamtab1[rt1[3]] + fac2 * igamtab1[rt2[3]]) >> 8;
-			if (col > 65535) rt[3] = 255; else rt[3] = ( (char *)(gamtab + col))[MOST_SIG_BYTE];
+			straight_uchar_to_premul_float(rt1, cp1);
+			straight_uchar_to_premul_float(rt2, cp2);
 
-			rt1 += 4; rt2 += 4; rt += 4;
+			tempc[0] = gammaCorrect(fac1 * invGammaCorrect(rt1[0]) + fac2 * invGammaCorrect(rt2[0]));
+			tempc[1] = gammaCorrect(fac1 * invGammaCorrect(rt1[1]) + fac2 * invGammaCorrect(rt2[1]));
+			tempc[2] = gammaCorrect(fac1 * invGammaCorrect(rt1[2]) + fac2 * invGammaCorrect(rt2[2]));
+			tempc[3] = gammaCorrect(fac1 * invGammaCorrect(rt1[3]) + fac2 * invGammaCorrect(rt2[3]));
+
+			premul_float_to_straight_uchar(rt, tempc);
+			cp1 += 4; cp2 += 4; rt += 4;
 		}
 	}
 }
@@ -828,31 +831,34 @@ static void do_gammacross_effect(SeqRenderData context, Sequence *UNUSED(seq), f
 static void do_add_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect1, unsigned char *rect2,
                                unsigned char *out)
 {
-	int col, xo, fac1, fac3;
-	char *rt1, *rt2, *rt;
+	int xo;
+	unsigned char *cp1, *cp2, *rt;
+	float fac1, fac3;
+	float tempc[4], rt1[4], rt2[4];
 
 	xo = x;
-	rt1 = (char *)rect1;
-	rt2 = (char *)rect2;
-	rt = (char *)out;
+	cp1 = rect1;
+	cp2 = rect2;
+	rt = out;
 
-	fac1 = (int)(256.0f * facf0);
-	fac3 = (int)(256.0f * facf1);
+	fac1 = facf0;
+	fac3 = facf1;
 
 	while (y--) {
 		x = xo;
 
 		while (x--) {
-			col = rt1[0] + ((fac1 * rt2[0]) >> 8);
-			if (col > 255) rt[0] = 255; else rt[0] = col;
-			col = rt1[1] + ((fac1 * rt2[1]) >> 8);
-			if (col > 255) rt[1] = 255; else rt[1] = col;
-			col = rt1[2] + ((fac1 * rt2[2]) >> 8);
-			if (col > 255) rt[2] = 255; else rt[2] = col;
-			col = rt1[3] + ((fac1 * rt2[3]) >> 8);
-			if (col > 255) rt[3] = 255; else rt[3] = col;
+			straight_uchar_to_premul_float(rt1, cp1);
+			straight_uchar_to_premul_float(rt2, cp2);
 
-			rt1 += 4; rt2 += 4; rt += 4;
+			tempc[0] = rt1[0] + fac1 * rt2[0];
+			tempc[1] = rt1[1] + fac1 * rt2[1];
+			tempc[2] = rt1[2] + fac1 * rt2[2];
+			tempc[3] = min_ff(1.0f, rt1[3] + fac1 * rt2[3]);
+
+			premul_float_to_straight_uchar(rt, tempc);
+
+			cp1 += 4; cp2 += 4; rt += 4;
 		}
 
 		if (y == 0)
@@ -861,16 +867,17 @@ static void do_add_effect_byte(float facf0, float facf1, int x, int y, unsigned
 
 		x = xo;
 		while (x--) {
-			col = rt1[0] + ((fac3 * rt2[0]) >> 8);
-			if (col > 255) rt[0] = 255; else rt[0] = col;
-			col = rt1[1] + ((fac3 * rt2[1]) >> 8);
-			if (col > 255) rt[1] = 255; else rt[1] = col;
-			col = rt1[2] + ((fac3 * rt2[2]) >> 8);
-			if (col > 255) rt[2] = 255; else rt[2] = col;
-			col = rt1[3] + ((fac3 * rt2[3]) >> 8);
-			if (col > 255) rt[3] = 255; else rt[3] = col;
+			straight_uchar_to_premul_float(rt1, cp1);
+			straight_uchar_to_premul_float(rt2, cp2);
 
-			rt1 += 4; rt2 += 4; rt += 4;
+			tempc[0] = rt1[0] + fac3 * rt2[0];
+			tempc[1] = rt1[1] + fac3 * rt2[1];
+			tempc[2] = rt1[2] + fac3 * rt2[2];
+			tempc[3] = min_ff(1.0f, rt1[3] + fac3 * rt2[3]);
+
+			premul_float_to_straight_uchar(rt, tempc);
+
+			cp1 += 4; cp2 += 4; rt += 4;
 		}
 	}
 }
@@ -890,22 +897,28 @@ static void do_add_effect_float(float facf0, float facf1, int x, int y, float *r
 	fac3 = facf1;
 
 	while (y--) {
-		x = xo * 4;
+		x = xo;
 		while (x--) {
-			*rt = *rt1 + fac1 * (*rt2);
+			rt[0] = rt1[0] + fac1 * rt2[0];
+			rt[1] = rt1[1] + fac1 * rt2[1];
+			rt[2] = rt1[2] + fac1 * rt2[2];
+			rt[3] = min_ff(1.0f, rt1[3] + fac1 * rt2[3]);
 
-			rt1++; rt2++; rt++;
+			rt1 += 4; rt2 += 4; rt += 4;
 		}
 
 		if (y == 0)
 			break;
 		y--;
 
-		x = xo * 4;
+		x = xo;
 		while (x--) {
-			*rt = *rt1 + fac3 * (*rt2);
+			rt[0] = rt1[0] + fac1 * rt2[0];
+			rt[1] = rt1[1] + fac1 * rt2[1];
+			rt[2] = rt1[2] + fac1 * rt2[2];
+			rt[3] = min_ff(1.0f, rt1[3] + fac3 * rt2[3]);
 
-			rt1++; rt2++; rt++;
+			rt1 += 4; rt2 += 4; rt += 4;
 		}
 	}
 }
@@ -931,32 +944,35 @@ static void do_add_effect(SeqRenderData context, Sequence *UNUSED(seq), float UN
 
 /*********************** Sub *************************/
 
-static void do_sub_effect_byte(float facf0, float facf1, int x, int y, char *rect1, char *rect2, char *out)
+static void do_sub_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out)
 {
-	int col, xo, fac1, fac3;
-	char *rt1, *rt2, *rt;
+	int xo;
+	unsigned char *cp1, *cp2, *rt;
+	float fac1, fac3;
+	float tempc[4], rt1[4], rt2[4];
 
 	xo = x;
-	rt1 = (char *) rect1;
-	rt2 = (char *) rect2;
-	rt = (char *) out;
+	cp1 = rect1;
+	cp2 = rect2;
+	rt = out;
 
-	fac1 = (int) (256.0f * facf0);
-	fac3 = (int) (256.0f * facf1);
+	fac1 = facf0;
+	fac3 = facf1;
 
 	while (y--) {
 		x = xo;
 		while (x--) {
-			col = rt1[0] - ((fac1 * rt2[0]) >> 8);
-			if (col < 0) rt[0] = 0; else rt[0] = col;
-			col = rt1[1] - ((fac1 * rt2[1]) >> 8);
-			if (col < 0) rt[1] = 0; else rt[1] = col;
-			col = rt1[2] - ((fac1 * rt2[2]) >> 8);
-			if (col < 0) rt[2] = 0; else rt[2] = col;
-			col = rt1[3] - ((fac1 * rt2[3]) >> 8);
-			if (col < 0) rt[3] = 0; else rt[3] = col;
+			straight_uchar_to_premul_float(rt1, cp1);
+			straight_uchar_to_premul_float(rt2, cp2);
 
-			rt1 += 4; rt2 += 4; rt += 4;
+			tempc[0] = rt1[0] - fac1 * rt2[0];
+			tempc[1] = rt1[1] - fac1 * rt2[1];
+			tempc[2] = rt1[2] - fac1 * rt2[2];
+			tempc[3] = rt1[3] - fac1 * rt2[3];
+
+			premul_float_to_straight_uchar(rt, tempc);
+
+			cp1 += 4; cp2 += 4; rt += 4;
 		}
 
 		if (y == 0)
@@ -965,16 +981,17 @@ static void do_sub_effect_byte(float facf0, float facf1, int x, int y, char *rec
 
 		x = xo;
 		while (x--) {
-			col = rt1[0] - ((fac3 * rt2[0]) >> 8);
-			if (col < 0) rt[0] = 0; else rt[0] = col;
-			col = rt1[1] - ((fac3 * rt2[1]) >> 8);
-			if (col < 0) rt[1] = 0; else rt[1] = col;
-			col = rt1[2] - ((fac3 * rt2[2]) >> 8);
-			if (col < 0) rt[2] = 0; else rt[2] = col;
-			col = rt1[3] - ((fac3 * rt2[3]) >> 8);
-			if (col < 0) rt[3] = 0; else rt[3] = col;
+			straight_uchar_to_premul_float(rt1, cp1);
+			straight_uchar_to_premul_float(rt2, cp2);
 
-			rt1 += 4; rt2 += 4; rt += 4;
+			tempc[0] = rt1[0] - fac3 * rt2[0];
+			tempc[1] = rt1[1] - fac3 * rt2[1];
+			tempc[2] = rt1[2] - fac3 * rt2[2];
+			tempc[3] = rt1[3] - fac3 * rt2[3];
+
+			premul_float_to_straight_uchar(rt, tempc);
+
+			cp1 += 4; cp2 += 4; rt += 4;
 		}
 	}
 }
@@ -1029,7 +1046,7 @@ static void do_sub_effect(SeqRenderData context, Sequence *UNUSED(seq), float UN
 
 		slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
 
-		do_sub_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out);
+		do_sub_effect_byte(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
 	}
 }
 
@@ -1039,10 +1056,10 @@ static void do_sub_effect(SeqRenderData context, Sequence *UNUSED(seq), float UN
 #define XOFF    8
 #define YOFF    8
 
-static void do_drop_effect_byte(float facf0, float facf1, int x, int y, char *rect2i, char *rect1i, char *outi)
+static void do_drop_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect2i, unsigned char *rect1i, unsigned char *outi)
 {
 	int height, width, temp, fac, fac1, fac2;
-	char *rt1, *rt2, *out;
+	unsigned char *rt1, *rt2, *out;
 	int field = 1;
 
 	width = x;
@@ -1051,9 +1068,9 @@ static void do_drop_effect_byte(float facf0, float facf1, int x, int y, char *re
 	fac1 = (int) (70.0f * facf0);
 	fac2 = (int) (70.0f * facf1);
 
-	rt2 = (char *) (rect2i + YOFF * width);
-	rt1 = (char *) rect1i;
-	out = (char *) outi;
+	rt2 = (unsigned char *) (rect2i + YOFF * width);
+	rt1 = (unsigned char *) rect1i;
+	out = (unsigned char *) outi;
 	for (y = 0; y < height - YOFF; y++) {
 		if (field) fac = fac1;
 		else fac = fac2;
@@ -1122,12 +1139,12 @@ static void do_mul_effect_byte(float facf0, float facf1, int x, int y, unsigned
                                unsigned char *out)
 {
 	int xo, fac1, fac3;
-	char *rt1, *rt2, *rt;
+	unsigned char *rt1, *rt2, *rt;
 
 	xo = x;
-	rt1 = (char *)rect1;
-	rt2 = (char *)rect2;
-	rt = (char *)out;
+	rt1 = rect1;
+	rt2 = rect2;
+	rt = out;
 
 	fac1 = (int)(256.0f * facf0);
 	fac3 = (int)(256.0f * facf1);
@@ -1539,13 +1556,13 @@ static void do_wipe_effect_byte(Sequence *seq, float facf0, float UNUSED(facf1),
 	WipeZone wipezone;
 	WipeVars *wipe = (WipeVars *)seq->effectdata;
 	int xo, yo;
-	char *rt1, *rt2, *rt;
+	unsigned char *cp1, *cp2, *rt;
 
 	precalc_wipe_zone(&wipezone, wipe, x, y);
 
-	rt1 = (char *)rect1;
-	rt2 = (char *)rect2;
-	rt = (char *)out;
+	cp1 = rect1;
+	cp2 = rect2;
+	rt = out;
 
 	xo = x;
 	yo = y;
@@ -1553,11 +1570,18 @@ static void do_wipe_effect_byte(Sequence *seq, float facf0, float UNUSED(facf1),
 		for (x = 0; x < xo; x++) {
 			float check = check_zone(&wipezone, x, y, seq, facf0);
 			if (check) {
-				if (rt1) {
-					rt[0] = (int)(rt1[0] * check) + (int)(rt2[0] * (1 - check));
-					rt[1] = (int)(rt1[1] * check) + (int)(rt2[1] * (1 - check));
-					rt[2] = (int)(rt1[2] * check) + (int)(rt2[2] * (1 - check));
-					rt[3] = (int)(rt1[3] * check) + (int)(rt2[3] * (1 - check));
+				if (cp1) {
+					float rt1[4], rt2[4], tempc[4];
+
+					straight_uchar_to_premul_float(rt1, cp1);
+					straight_uchar_to_premul_float(rt2, cp2);
+
+					tempc[0] = rt1[0] * check + rt2[0] * (1 - check);
+					tempc[1] = rt1[1] * check + rt2[1] * (1 - check);
+					tempc[2] = rt1[2] * check + rt2[2] * (1 - check);
+					tempc[3] = rt1[3] * check + rt2[3] * (1 - check);
+
+					premul_float_to_straight_uchar(rt, tempc);
 				}
 				else {
 					rt[0] = 0;
@@ -1567,11 +1591,11 @@ static void do_wipe_effect_byte(Sequence *seq, float facf0, float UNUSED(facf1),
 				}
 			}
 			else {
-				if (rt2) {
-					rt[0] = rt2[0];
-					rt[1] = rt2[1];
-					rt[2] = rt2[2];
-					rt[3] = rt2[3];
+				if (cp2) {
+					rt[0] = cp2[0];
+					rt[1] = cp2[1];
+					rt[2] = cp2[2];
+					rt[3] = cp2[3];
 				}
 				else {
 					rt[0] = 0;
@@ -1582,11 +1606,11 @@ static void do_wipe_effect_byte(Sequence *seq, float facf0, float UNUSED(facf1),
 			}
 
 			rt += 4;
-			if (rt1 != NULL) {
-				rt1 += 4;
+			if (cp1 != NULL) {
+				cp1 += 4;
 			}
-			if (rt2 != NULL) {
-				rt2 += 4;
+			if (cp2 != NULL) {
+				cp2 += 4;
 			}
 		}
 	}
@@ -2254,16 +2278,42 @@ static void copy_glow_effect(Sequence *dst, Sequence *src)
 }
 
 static void do_glow_effect_byte(Sequence *seq, int render_size, float facf0, float UNUSED(facf1),  int x, int y,
-                                char *rect1, char *UNUSED(rect2), char *out)
+                                unsigned char *rect1, unsigned char *UNUSED(rect2), unsigned char *out)
 {
-	unsigned char *outbuf = (unsigned char *)out;
-	unsigned char *inbuf = (unsigned char *)rect1;
+#if 0
+	/* XXX: not sure what's better here, on the one hand conversion to floats
+	 *      here is not so much trouble, but on the other hand who're using
+	 *      glow on buffers with alpha?
+	 */
+	unsigned char *outbuf = out;
+	unsigned char *inbuf = rect1;
 	GlowVars *glow = (GlowVars *)seq->effectdata;
-	
+
 	RVIsolateHighlights_byte(inbuf, outbuf, x, y, glow->fMini * 765, glow->fBoost * facf0, glow->fClamp);
 	RVBlurBitmap2_byte(outbuf, x, y, glow->dDist * (render_size / 100.0f), glow->dQuality);
 	if (!glow->bNoComp)
 		RVAddBitmaps_byte(inbuf, outbuf, outbuf, x, y);
+#else
+	float *outbuf, *inbuf;
+	GlowVars *glow = (GlowVars *)seq->effectdata;
+
+	inbuf = MEM_mallocN(4 * sizeof(float) * x * y, "glow effect input");
+	outbuf = MEM_mallocN(4 * sizeof(float) * x * y, "glow effect output");
+
+	IMB_buffer_float_from_byte(inbuf, rect1, IB_PROFILE_SRGB, IB_PROFILE_SRGB, FALSE, x, y, x, x);
+	IMB_buffer_float_premultiply(inbuf, x, y);
+
+	RVIsolateHighlights_float(inbuf, outbuf, x, y, glow->fMini * 3.0f, glow->fBoost * facf0, glow->fClamp);
+	RVBlurBitmap2_float(outbuf, x, y, glow->dDist * (render_size / 100.0f), glow->dQuality);
+	if (!glow->bNoComp)
+		RVAddBitmaps_float(inbuf, outbuf, outbuf, x, y);
+
+	IMB_buffer_float_unpremultiply(outbuf, x, y);
+	IMB_buffer_byte_from_float(out, outbuf, 4, 0.0f, IB_PROFILE_SRGB, IB_PROFILE_SRGB, FALSE, x, y, x, x);
+
+	MEM_freeN(inbuf);
+	MEM_freeN(outbuf);
+#endif
 }
 
 static void do_glow_effect_float(Sequence *seq, int render_size, float facf0, float UNUSED(facf1),  int x, int y,
@@ -2292,7 +2342,7 @@ static ImBuf *do_glow_effect(SeqRenderData context, Sequence *seq, float UNUSED(
 	}
 	else {
 		do_glow_effect_byte(seq, render_size, facf0, facf1, context.rectx, context.recty,
-		                    (char *) ibuf1->rect, (char *) ibuf2->rect, (char *) out->rect);
+		                    (unsigned char *) ibuf1->rect, (unsigned char *) ibuf2->rect, (unsigned char *) out->rect);
 	}
 
 	return out;
@@ -2735,7 +2785,7 @@ static ImBuf *do_speed_effect(SeqRenderData context, Sequence *UNUSED(seq), floa
 	}
 	else {
 		do_cross_effect_byte(facf0, facf1, context.rectx, context.recty,
-		                     (char *) ibuf1->rect, (char *) ibuf2->rect, (char *) out->rect);
+		                     (unsigned char *) ibuf1->rect, (unsigned char *) ibuf2->rect, (unsigned char *) out->rect);
 	}
 	return out;
 }
@@ -2761,8 +2811,8 @@ static void do_overdrop_effect(SeqRenderData context, Sequence *UNUSED(seq), flo
 
 		slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
 
-		do_drop_effect_byte(facf0, facf1, x, y, (char *) rect1, (char *) rect2, (char *) rect_out);
-		do_alphaover_effect_byte(facf0, facf1, x, y, (char *) rect1, (char *) rect2, (char *) rect_out);
+		do_drop_effect_byte(facf0, facf1, x, y, rect1, rect2, rect_out);
+		do_alphaover_effect_byte(facf0, facf1, x, y, rect1, rect2, rect_out);
 	}
 }
 
diff --git a/source/blender/blenkernel/intern/seqmodifier.c b/source/blender/blenkernel/intern/seqmodifier.c
index 5b2e9f2bf23..3d8a2f7cddf 100644
--- a/source/blender/blenkernel/intern/seqmodifier.c
+++ b/source/blender/blenkernel/intern/seqmodifier.c
@@ -226,24 +226,28 @@ static void curves_apply_threaded(int width, int height, unsigned char *rect, fl
 			}
 			if (rect) {
 				unsigned char *pixel = rect + pixel_index;
-				unsigned char result[3];
+				float result[3], tempc[4];
 
-				curvemapping_evaluate_premulRGB(curve_mapping, result, pixel);
+				straight_uchar_to_premul_float(tempc, pixel);
+
+				curvemapping_evaluate_premulRGBF(curve_mapping, result, tempc);
 
 				if (mask_rect) {
 					float t[3];
 
 					rgb_uchar_to_float(t, mask_rect + pixel_index);
 
-					pixel[0] = pixel[0] * (1.0f - t[0]) + result[0] * t[0];
-					pixel[1] = pixel[1] * (1.0f - t[1]) + result[1] * t[1];
-					pixel[2] = pixel[2] * (1.0f - t[2]) + result[2] * t[2];
+					tempc[0] = pixel[0] * (1.0f - t[0]) + result[0] * t[0];
+					tempc[1] = pixel[1] * (1.0f - t[1]) + result[1] * t[1];
+					tempc[2] = pixel[2] * (1.0f - t[2]) + result[2] * t[2];
 				}
 				else {
-					pixel[0] = result[0];
-					pixel[1] = result[1];
-					pixel[2] = result[2];
+					tempc[0] = result[0];
+					tempc[1] = result[1];
+					tempc[2] = result[2];
 				}
+
+				premul_float_to_straight_uchar(pixel, tempc);
 			}
 		}
 	}
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index a82704d9e38..69c125b0ece 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -324,7 +324,6 @@ void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, int make_
 {
 	const char *from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
 	const char *to_colorspace = scene->sequencer_colorspace_settings.name;
-	int predivide = ibuf->flags & IB_cm_predivide;
 
 	if (!ibuf->rect_float) {
 		if (make_float && ibuf->rect) {
@@ -354,7 +353,7 @@ void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, int make_
 			imb_freerectImBuf(ibuf);
 
 		IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels,
-		                                       from_colorspace, to_colorspace, predivide);
+		                                       from_colorspace, to_colorspace, TRUE);
 	}
 }
 
@@ -367,10 +366,8 @@ void BKE_sequencer_imbuf_from_sequencer_space(Scene *scene, ImBuf *ibuf)
 		return;
 
 	if (to_colorspace && to_colorspace[0] != '\0') {
-		int predivide = ibuf->flags & IB_cm_predivide;
-
 		IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels,
-		                                       from_colorspace, to_colorspace, predivide);
+		                                       from_colorspace, to_colorspace, TRUE);
 	}
 }
 
@@ -1517,18 +1514,6 @@ MINLINE float color_balance_fl(float in, const float lift, const float gain, con
 	return powf(x, gamma) * mul;
 }
 
-static void make_cb_table_byte(float lift, float gain, float gamma,
-                               unsigned char *table, float mul)
-{
-	int y;
-
-	for (y = 0; y < 256; y++) {
-		float v = color_balance_fl((float)y * (1.0f / 255.0f), lift, gain, gamma, mul);
-
-		table[y] = FTOCHAR(v);
-	}
-}
-
 static void make_cb_table_float(float lift, float gain, float gamma,
                                 float *table, float mul)
 {
@@ -1543,35 +1528,33 @@ static void make_cb_table_float(float lift, float gain, float gamma,
 
 static void color_balance_byte_byte(StripColorBalance *cb_, unsigned char *rect, unsigned char *mask_rect, int width, int height, float mul)
 {
-	unsigned char cb_tab[3][256];
-	int c;
-	unsigned char *p = rect;
-	unsigned char *e = p + width * 4 * height;
+	//unsigned char cb_tab[3][256];
+	unsigned char *cp = rect;
+	unsigned char *e = cp + width * 4 * height;
 	unsigned char *m = mask_rect;
 
 	StripColorBalance cb = calc_cb(cb_);
 
-	for (c = 0; c < 3; c++) {
-		make_cb_table_byte(cb.lift[c], cb.gain[c], cb.gamma[c], cb_tab[c], mul);
-	}
+	while (cp < e) {
+		float p[4];
+		int c;
 
-	while (p < e) {
-		if (m) {
-			float t[3] = {m[0] / 255.0f, m[1] / 255.0f, m[2] / 255.0f};
+		straight_uchar_to_premul_float(p, cp);
 
-			p[0] = p[0] * (1.0f - t[0]) + t[0] * cb_tab[0][p[0]];
-			p[1] = p[1] * (1.0f - t[1]) + t[1] * cb_tab[1][p[1]];
-			p[2] = p[2] * (1.0f - t[2]) + t[2] * cb_tab[2][p[2]];
+		for (c = 0; c < 3; c++) {
+			float t = color_balance_fl(p[c], cb.lift[c], cb.gain[c], cb.gamma[c], mul);
 
-			m += 4;
-		}
-		else {
-			p[0] = cb_tab[0][p[0]];
-			p[1] = cb_tab[1][p[1]];
-			p[2] = cb_tab[2][p[2]];
+			if (m)
+				p[c] = p[c] * (1.0f - (float)m[c] / 255.0f) + t * m[c];
+			else
+				p[c] = t;
 		}
 		
-		p += 4;
+		premul_float_to_straight_uchar(cp, p);
+
+		cp += 4;
+		if (m)
+			m += 4;
 	}
 }
 
@@ -1795,7 +1778,7 @@ int BKE_sequencer_input_have_to_preprocess(SeqRenderData UNUSED(context), Sequen
 {
 	float mul;
 
-	if (seq->flag & (SEQ_FILTERY | SEQ_USE_CROP | SEQ_USE_TRANSFORM | SEQ_FLIPX | SEQ_FLIPY | SEQ_MAKE_PREMUL | SEQ_MAKE_FLOAT)) {
+	if (seq->flag & (SEQ_FILTERY | SEQ_USE_CROP | SEQ_USE_TRANSFORM | SEQ_FLIPX | SEQ_FLIPY | SEQ_MAKE_FLOAT)) {
 		return TRUE;
 	}
 
@@ -1892,7 +1875,8 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra,
 			ImBuf *i = IMB_allocImBuf(dx, dy, 32, ibuf->rect_float ? IB_rectfloat : IB_rect);
 
 			IMB_rectcpy(i, ibuf, t.xofs, t.yofs, c.left, c.bottom, sx, sy);
-			
+			sequencer_imbuf_assign_spaces(context.scene, i);
+
 			IMB_freeImBuf(ibuf);
 
 			ibuf = i;
@@ -1931,12 +1915,6 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra,
 		multibuf(ibuf, mul);
 	}
 
-	if (seq->flag & SEQ_MAKE_PREMUL) {
-		if (ibuf->planes == 32 && ibuf->zbuf == NULL) {
-			IMB_premultiply_alpha(ibuf);
-		}
-	}
-
 	if (ibuf->x != context.rectx || ibuf->y != context.recty) {
 		if (context.scene->r.mode & R_OSA) {
 			IMB_scaleImBuf(ibuf, (short)context.rectx, (short)context.recty);
@@ -2546,13 +2524,18 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo
 		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);
 			}
 
-			if (s_elem && (ibuf = IMB_loadiffname(name, IB_rect, seq->strip->colorspace_settings.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);
@@ -2641,7 +2624,7 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo
 static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra)
 {
 	ImBuf *ibuf = NULL;
-	int use_preprocess = BKE_sequencer_input_have_to_preprocess(context, seq, cfra);
+	int use_preprocess = FALSE;
 	int is_proxy_image = FALSE;
 	float nr = give_stripelem_index(seq, cfra);
 	/* all effects are handled similarly with the exception of speed effect */
@@ -2650,30 +2633,36 @@ static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra)
 
 	ibuf = BKE_sequencer_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF);
 
-	/* currently, we cache preprocessed images in SEQ_STRIPELEM_IBUF,
-	 * but not(!) on SEQ_STRIPELEM_IBUF_ENDSTILL and ..._STARTSTILL */
-	if (ibuf)
-		use_preprocess = FALSE;
-
-	if (ibuf == NULL)
-		ibuf = copy_from_ibuf_still(context, seq, nr);
-
 	if (ibuf == NULL) {
-		ibuf = BKE_sequencer_preprocessed_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF);
+		if (ibuf == NULL)
+			ibuf = copy_from_ibuf_still(context, seq, nr);
 
 		if (ibuf == NULL) {
-			/* MOVIECLIPs have their own proxy management */
-			if (ibuf == NULL && seq->type != SEQ_TYPE_MOVIECLIP) {
-				ibuf = seq_proxy_fetch(context, seq, cfra);
-				is_proxy_image = (ibuf != NULL);
-			}
+			ibuf = BKE_sequencer_preprocessed_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF);
 
-			if (ibuf == NULL)
-				ibuf = do_render_strip_uncached(context, seq, cfra);
+			if (ibuf == NULL) {
+				/* MOVIECLIPs have their own proxy management */
+				if (ibuf == NULL && seq->type != SEQ_TYPE_MOVIECLIP) {
+					ibuf = seq_proxy_fetch(context, seq, cfra);
+					is_proxy_image = (ibuf != NULL);
+				}
 
-			if (ibuf)
-				BKE_sequencer_preprocessed_cache_put(context, seq, cfra, SEQ_STRIPELEM_IBUF, ibuf);
+				if (ibuf == NULL)
+					ibuf = do_render_strip_uncached(context, seq, cfra);
+
+				if (ibuf)
+					BKE_sequencer_preprocessed_cache_put(context, seq, cfra, SEQ_STRIPELEM_IBUF, ibuf);
+			}
 		}
+
+		if (ibuf)
+			use_preprocess = BKE_sequencer_input_have_to_preprocess(context, seq, cfra);
+	}
+	else {
+		/* currently, we cache preprocessed images in SEQ_STRIPELEM_IBUF,
+		 * but not(!) on SEQ_STRIPELEM_IBUF_ENDSTILL and ..._STARTSTILL
+		 * so, no need in check for preprocess here
+		 */
 	}
 
 	if (ibuf == NULL) {
@@ -3975,6 +3964,14 @@ void BKE_sequence_init_colorspace(Sequence *seq)
 		if (seq->type == SEQ_TYPE_IMAGE) {
 			ibuf = IMB_loadiffname(name, IB_rect, seq->strip->colorspace_settings.name);
 
+			/* byte images are default to straight alpha, however sequencer
+			 * works in premul space, so mark strip to be premultiplied first
+			 */
+			if (!ibuf->rect_float)
+				seq->alpha_mode = SEQ_ALPHA_STRAIGHT;
+			else
+				seq->alpha_mode = SEQ_ALPHA_PREMUL;
+
 			if (ibuf)
 				IMB_freeImBuf(ibuf);
 		}
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index 149842bc038..fbaf6f70fbc 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -440,7 +440,7 @@ void default_tex(Tex *tex)
 	tex->type = TEX_CLOUDS;
 	tex->stype = 0;
 	tex->flag = TEX_CHECKER_ODD;
-	tex->imaflag = TEX_INTERPOL | TEX_MIPMAP | TEX_USEALPHA;
+	tex->imaflag = TEX_INTERPOL | TEX_MIPMAP;
 	tex->extend = TEX_REPEAT;
 	tex->cropxmin = tex->cropymin = 0.0;
 	tex->cropxmax = tex->cropymax = 1.0;
diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h
index c71463da61d..3831ec3cbb4 100644
--- a/source/blender/blenlib/BLI_math_color.h
+++ b/source/blender/blenlib/BLI_math_color.h
@@ -100,6 +100,13 @@ MINLINE void linearrgb_to_srgb_uchar4(unsigned char srgb[4], const float linear[
 
 void BLI_init_srgb_conversion(void);
 
+/**************** Alpha Transformations *****************/
+
+MINLINE void premul_to_straight_v4(float straight[4], const float premul[4]);
+MINLINE void straight_to_premul_v4(float straight[4], const float premul[4]);
+MINLINE void straight_uchar_to_premul_float(float result[4], const unsigned char color[4]);
+MINLINE void premul_float_to_straight_uchar(unsigned char *result, const float color[4]);
+
 /************************** Other *************************/
 
 int constrain_rgb(float *r, float *g, float *b);
diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c
index 4c8bd43ef73..b8eeca50db6 100644
--- a/source/blender/blenlib/intern/math_color_inline.c
+++ b/source/blender/blenlib/intern/math_color_inline.c
@@ -149,31 +149,6 @@ MINLINE void linearrgb_to_srgb_ushort4(unsigned short srgb[4], const float linea
 	srgb[3] = FTOUSHORT(linear[3]);
 }
 
-MINLINE void linearrgb_to_srgb_ushort4_predivide(unsigned short srgb[4], const float linear[4])
-{
-	float alpha, inv_alpha, t;
-	int i;
-
-	if (linear[3] == 1.0f || linear[3] == 0.0f) {
-		linearrgb_to_srgb_ushort4(srgb, linear);
-		return;
-	}
-
-	alpha = linear[3];
-	inv_alpha = 1.0f / alpha;
-
-	for (i = 0; i < 3; ++i) {
-		t = linear[i] * inv_alpha;
-		srgb[i] = (t <= 1.0f) ?
-		          /* warning - converts: float -> short -> float -> short */
-		          (unsigned short) (to_srgb_table_lookup(t) * alpha) :
-		          /* if FTOUSHORT was an inline function this could be done less confusingly */
-		          ((t = linearrgb_to_srgb(t) * alpha), FTOUSHORT(t));
-	}
-
-	srgb[3] = FTOUSHORT(linear[3]);
-}
-
 MINLINE void srgb_to_linearrgb_uchar4(float linear[4], const unsigned char srgb[4])
 {
 	linear[0] = BLI_color_from_srgb_table[srgb[0]];
@@ -293,4 +268,62 @@ MINLINE int compare_rgb_uchar(const unsigned char col_a[3], const unsigned char
 	return 0;
 }
 
+/**************** Alpha Transformations *****************/
+
+MINLINE void premul_to_straight_v4(float straight[4], const float premul[4])
+{
+	if (premul[3] == 0.0f || premul[3] == 1.0f) {
+		straight[0] = premul[0];
+		straight[1] = premul[1];
+		straight[2] = premul[2];
+		straight[3] = premul[3];
+	}
+	else {
+		float alpha_inv = 1.0f / premul[3];
+		straight[0] = premul[0] * alpha_inv;
+		straight[1] = premul[1] * alpha_inv;
+		straight[2] = premul[2] * alpha_inv;
+		straight[3] = premul[3];
+	}
+}
+
+MINLINE void straight_to_premul_v4(float premul[4], const float straight[4])
+{
+	float alpha = straight[3];
+	premul[0] = straight[0] * alpha;
+	premul[1] = straight[1] * alpha;
+	premul[2] = straight[2] * alpha;
+	premul[3] = straight[3];
+}
+
+MINLINE void straight_uchar_to_premul_float(float result[4], const unsigned char color[4])
+{
+	float alpha = color[3] / 255.0f;
+	float fac = alpha / 255.0f;
+
+	result[0] = color[0] * fac;
+	result[1] = color[1] * fac;
+	result[2] = color[2] * fac;
+	result[3] = alpha;
+}
+
+MINLINE void premul_float_to_straight_uchar(unsigned char *result, const float color[4])
+{
+	if (color[3] == 0.0f || color[3] == 1.0f) {
+		result[0] = FTOCHAR(color[0]);
+		result[1] = FTOCHAR(color[1]);
+		result[2] = FTOCHAR(color[2]);
+		result[3] = FTOCHAR(color[3]);
+	}
+	else {
+		float alpha_inv = 1.0f / color[3];
+
+		/* hopefully this would be optimized */
+		result[0] = FTOCHAR(color[0] * alpha_inv);
+		result[1] = FTOCHAR(color[1] * alpha_inv);
+		result[2] = FTOCHAR(color[2] * alpha_inv);
+		result[3] = FTOCHAR(color[3]);
+	}
+}
+
 #endif /* __MATH_COLOR_INLINE_C__ */
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 8ddd69f2f03..7827a3a9bf1 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -8568,14 +8568,40 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
 		}
 	}
 
-	{
+	if (main->versionfile < 265 || (main->versionfile == 265 && main->subversionfile < 5)) {
 		Scene *scene;
+		Image *image;
+		Tex *tex;
 
 		for (scene = main->scene.first; scene; scene = scene->id.next) {
+			Sequence *seq;
+
+			SEQ_BEGIN (scene->ed, seq)
+			{
+				if (seq->flag & SEQ_MAKE_PREMUL)
+					seq->alpha_mode = SEQ_ALPHA_STRAIGHT;
+			}
+			SEQ_END
+
 			if (scene->r.bake_samples == 0)
-				scene->r.bake_samples = 256;
+			scene->r.bake_samples = 256;
+		}
+
+		for (image = main->image.first; image; image = image->id.next) {
+			if (image->flag & IMA_DO_PREMUL)
+				image->alpha_mode = IMA_ALPHA_STRAIGHT;
+		}
+
+		for (tex = main->tex.first; tex; tex = tex->id.next) {
+			if (tex->type == TEX_IMAGE && (tex->imaflag & TEX_USEALPHA) == 0) {
+				if (tex->ima) {
+					image = blo_do_versions_newlibadr(fd, lib, tex->ima);
+					image->flag |= IMA_IGNORE_ALPHA;
+				}
+			}
 		}
 	}
+
 	/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
 	/* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */
 
diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c
index 2e783ac956e..65a60e11ab3 100644
--- a/source/blender/blenloader/intern/versioning_legacy.c
+++ b/source/blender/blenloader/intern/versioning_legacy.c
@@ -289,11 +289,10 @@ static void ntree_version_245(FileData *fd, Library *lib, bNodeTree *ntree)
 				iuser = node->storage;
 				if (iuser->flag & IMA_OLD_PREMUL) {
 					iuser->flag &= ~IMA_OLD_PREMUL;
-					iuser->flag |= IMA_DO_PREMUL;
 				}
 				if (iuser->flag & IMA_DO_PREMUL) {
 					image->flag &= ~IMA_OLD_PREMUL;
-					image->flag |= IMA_DO_PREMUL;
+					image->alpha_mode = IMA_ALPHA_STRAIGHT;
 				}
 			}
 		}
@@ -1840,7 +1839,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
 				SEQ_BEGIN (sce->ed, seq)
 				{
 					if (seq->type == SEQ_TYPE_IMAGE || seq->type == SEQ_TYPE_MOVIE)
-						seq->flag |= SEQ_MAKE_PREMUL;
+						seq->alpha_mode = SEQ_ALPHA_STRAIGHT;
 				}
 				SEQ_END
 			}
@@ -2901,20 +2900,19 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
 		for (ima = main->image.first; ima; ima = ima->id.next) {
 			if (ima->flag & IMA_OLD_PREMUL) {
 				ima->flag &= ~IMA_OLD_PREMUL;
-				ima->flag |= IMA_DO_PREMUL;
+				ima->alpha_mode = IMA_ALPHA_STRAIGHT;
 			}
 		}
 
 		for (tex = main->tex.first; tex; tex = tex->id.next) {
 			if (tex->iuser.flag & IMA_OLD_PREMUL) {
 				tex->iuser.flag &= ~IMA_OLD_PREMUL;
-				tex->iuser.flag |= IMA_DO_PREMUL;
 			}
 
 			ima = blo_do_versions_newlibadr(fd, lib, tex->ima);
 			if (ima && (tex->iuser.flag & IMA_DO_PREMUL)) {
 				ima->flag &= ~IMA_OLD_PREMUL;
-				ima->flag |= IMA_DO_PREMUL;
+				ima->alpha_mode = IMA_ALPHA_STRAIGHT;
 			}
 		}
 	}
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp
index 084f71e0afc..b7797b51252 100644
--- a/source/blender/collada/DocumentImporter.cpp
+++ b/source/blender/collada/DocumentImporter.cpp
@@ -614,7 +614,6 @@ MTex *DocumentImporter::create_texture(COLLADAFW::EffectCommon *ef, COLLADAFW::T
 	ma->mtex[i]->texco = TEXCO_UV;
 	ma->mtex[i]->tex = add_texture("Texture");
 	ma->mtex[i]->tex->type = TEX_IMAGE;
-	ma->mtex[i]->tex->imaflag &= ~TEX_USEALPHA;
 	ma->mtex[i]->tex->ima = uid_image_map[ima_uid];
 	
 	texindex_texarray_map[ctex.getTextureMapId()].push_back(ma->mtex[i]);
@@ -745,7 +744,6 @@ void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Materia
 		mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
 		if (mtex != NULL) {
 			mtex->mapto = MAP_ALPHA;
-			mtex->tex->imaflag |= TEX_USEALPHA;
 			i++;
 			ma->spectra = ma->alpha = 0;
 			ma->mode |= MA_ZTRANSP | MA_TRANSP;
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index a864fe306b3..6ca8478b489 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -502,7 +502,7 @@ static int ed_preview_draw_rect(ScrArea *sa, Scene *sce, ID *id, int split, int
 		/* exception: don't color manage texture previews - show the raw values */
 		if (sce) {
 			do_gamma_correct = TRUE;
-			do_predivide = sce->r.color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE;
+			do_predivide = TRUE;
 		}
 	}
 
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index 09d203784e4..060a181612b 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -674,6 +674,24 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
 
 			if (ima->source != IMA_SRC_GENERATED) {
 				if (compact == 0) { /* background image view doesnt need these */
+					ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
+					int has_alpha = TRUE;
+
+					if (ibuf) {
+						int imtype = BKE_ftype_to_imtype(ibuf->ftype);
+						char valid_channels = BKE_imtype_valid_channels(imtype);
+
+						has_alpha = valid_channels & IMA_CHAN_FLAG_ALPHA;
+
+						BKE_image_release_ibuf(ima, ibuf, NULL);
+					}
+
+					if (has_alpha) {
+						col = uiLayoutColumn(layout, FALSE);
+						uiItemR(col, &imaptr, "use_alpha", 0, NULL, ICON_NONE);
+						uiItemR(col, &imaptr, "alpha_mode", 0, "Alpha", ICON_NONE);
+					}
+
 					uiItemS(layout);
 
 					split = uiLayoutSplit(layout, 0.0f, FALSE);
@@ -694,10 +712,6 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
 					row = uiLayoutRow(col, FALSE);
 					uiLayoutSetActive(row, RNA_boolean_get(&imaptr, "use_fields"));
 					uiItemR(row, &imaptr, "field_order", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
-					
-					row = uiLayoutRow(layout, FALSE);
-					uiItemR(row, &imaptr, "use_premultiply", 0, NULL, ICON_NONE);
-					uiItemR(row, &imaptr, "use_color_unpremultiply", 0, NULL, ICON_NONE);
 				}
 			}
 
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index a633b39cb32..254899e6e07 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -556,8 +556,9 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
 				if (do_color_management) {
 					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, 0,
+						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;
@@ -581,8 +582,9 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
 				if (do_color_management) {
 					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, 0,
+							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);
 				}
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 2039f01a740..a2fc1eb05ec 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -1035,8 +1035,7 @@ static void do_material_tex(GPUShadeInput *shi)
 				GPU_link(mat, "mtex_image", texco, GPU_image(tex->ima, &tex->iuser, FALSE), &tin, &trgb);
 				rgbnor= TEX_RGB;
 
-				if (tex->imaflag & TEX_USEALPHA)
-					talpha= 1;
+				talpha= 1;
 			}
 			else {
 				continue;
diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h
index 0653956e113..1e33f8da363 100644
--- a/source/blender/imbuf/IMB_colormanagement.h
+++ b/source/blender/imbuf/IMB_colormanagement.h
@@ -138,6 +138,7 @@ struct ColormanageProcessor *IMB_colormanagement_display_processor_new(const str
                                                                        const struct ColorManagedDisplaySettings *display_settings);
 struct ColormanageProcessor *IMB_colormanagement_colorspace_processor_new(const char *from_colorspace, const char *to_colorspace);
 void IMB_colormanagement_processor_apply_v4(struct ColormanageProcessor *cm_processor, float pixel[4]);
+void IMB_colormanagement_processor_apply_v4_predivide(struct ColormanageProcessor *cm_processor, float pixel[4]);
 void IMB_colormanagement_processor_apply_v3(struct ColormanageProcessor *cm_processor, float pixel[3]);
 void IMB_colormanagement_processor_apply(struct ColormanageProcessor *cm_processor, float *buffer, int width, int height,
                                          int channels, int predivide);
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index db1404813b1..850060ef4d5 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -373,7 +373,6 @@ void IMB_rect_from_float(struct ImBuf *ibuf);
  * Changed part will be stored in buffer. This is expected to be used for texture painting updates */
 void IMB_partial_rect_from_float(struct ImBuf *ibuf, float *buffer, int x, int y, int w, int h, int is_data);
 void IMB_float_from_rect(struct ImBuf *ibuf);
-void IMB_float_from_rect_simple(struct ImBuf *ibuf); /* no profile conversion */
 /* note, check that the conversion exists, only some are supported */
 float *IMB_float_profile_ensure(struct ImBuf *ibuf, int profile, int *alloc);
 void IMB_color_to_bw(struct ImBuf *ibuf);
@@ -393,6 +392,8 @@ void IMB_buffer_byte_from_byte(unsigned char *rect_to, const unsigned char *rect
 	int profile_to, int profile_from, int predivide,
 	int width, int height, int stride_to, int stride_from);
 void IMB_buffer_float_clamp(float *buf, int width, int height);
+void IMB_buffer_float_unpremultiply(float *buf, int width, int height);
+void IMB_buffer_float_premultiply(float *buf, int width, int height);
 
 /**
  * Change the ordering of the color bytes pointed to by rect from
@@ -467,6 +468,7 @@ void IMB_flipy(struct ImBuf *ibuf);
 /* Premultiply alpha */
 
 void IMB_premultiply_alpha(struct ImBuf *ibuf);
+void IMB_unpremultiply_alpha(struct ImBuf *ibuf);
 
 /**
  *
diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h
index 9fe66b562d1..49e2e7fc80d 100644
--- a/source/blender/imbuf/IMB_imbuf_types.h
+++ b/source/blender/imbuf/IMB_imbuf_types.h
@@ -167,8 +167,9 @@ typedef struct ImBuf {
 #define IB_animdeinterlace	(1 << 9)
 #define IB_tiles			(1 << 10)
 #define IB_tilecache		(1 << 11)
-#define IB_premul			(1 << 12)
-#define IB_cm_predivide		(1 << 13)
+#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 */
 
 /*
  * The bit flag is stored in the ImBuf.ftype variable.
diff --git a/source/blender/imbuf/intern/IMB_filter.h b/source/blender/imbuf/intern/IMB_filter.h
index eaedb160c94..6bd5f44307f 100644
--- a/source/blender/imbuf/intern/IMB_filter.h
+++ b/source/blender/imbuf/intern/IMB_filter.h
@@ -41,6 +41,9 @@ void imb_filterx(struct ImBuf *ibuf);
 void IMB_premultiply_rect(unsigned int *rect, char planes, int w, int h);
 void IMB_premultiply_rect_float(float *rect_float, char planes, int w, int h);
 
+void IMB_unpremultiply_rect(unsigned int *rect, char planes, int w, int h);
+void IMB_unpremultiply_rect_float(float *rect_float, char planes, int w, int h);
+
 void imb_onehalf_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1);
 
 #endif
diff --git a/source/blender/imbuf/intern/cineon/cineon_dpx.c b/source/blender/imbuf/intern/cineon/cineon_dpx.c
index c8bc3f8ebb8..ba84063f317 100644
--- a/source/blender/imbuf/intern/cineon/cineon_dpx.c
+++ b/source/blender/imbuf/intern/cineon/cineon_dpx.c
@@ -95,6 +95,9 @@ static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, size_t size, int us
 	if (flags & IB_rect)
 		IMB_rect_from_float(ibuf);
 
+	if (flags & IB_alphamode_detect)
+		ibuf->flags |= IB_alphamode_premul;
+
 	return ibuf;
 }
 
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c
index 1c68a466ade..bcfddfe425a 100644
--- a/source/blender/imbuf/intern/colormanagement.c
+++ b/source/blender/imbuf/intern/colormanagement.c
@@ -189,7 +189,6 @@ typedef struct ColormnaageCacheData {
 	int flag;        /* view flags of cached buffer */
 	float exposure;  /* exposure value cached buffer is calculated with */
 	float gamma;     /* gamma value cached buffer is calculated with */
-	int predivide;   /* predivide flag of cached buffer */
 	CurveMapping *curve_mapping;  /* curve mapping used for cached buffer */
 	int curve_mapping_timestamp;  /* time stamp of curve mapping used for cached buffer */
 } ColormnaageCacheData;
@@ -323,7 +322,6 @@ static unsigned char *colormanage_cache_get(ImBuf *ibuf, const ColormanageCacheV
 	ColormanageCacheKey key;
 	ImBuf *cache_ibuf;
 	int view_flag = 1 << (view_settings->view - 1);
-	int predivide = ibuf->flags & IB_cm_predivide;
 	CurveMapping *curve_mapping = view_settings->curve_mapping;
 	int curve_mapping_timestamp = curve_mapping ? curve_mapping->changed_timestamp : 0;
 
@@ -353,7 +351,6 @@ static unsigned char *colormanage_cache_get(ImBuf *ibuf, const ColormanageCacheV
 
 		if (cache_data->exposure != view_settings->exposure ||
 		    cache_data->gamma != view_settings->gamma ||
-			cache_data->predivide != predivide ||
 			cache_data->flag != view_settings->flag ||
 			cache_data->curve_mapping != curve_mapping ||
 			cache_data->curve_mapping_timestamp != curve_mapping_timestamp)
@@ -379,7 +376,6 @@ static void colormanage_cache_put(ImBuf *ibuf, const ColormanageCacheViewSetting
 	ImBuf *cache_ibuf;
 	ColormnaageCacheData *cache_data;
 	int view_flag = 1 << (view_settings->view - 1);
-	int predivide = ibuf->flags & IB_cm_predivide;
 	struct MovieCache *moviecache = colormanage_moviecache_ensure(ibuf);
 	CurveMapping *curve_mapping = view_settings->curve_mapping;
 	int curve_mapping_timestamp = curve_mapping ? curve_mapping->changed_timestamp : 0;
@@ -400,7 +396,6 @@ static void colormanage_cache_put(ImBuf *ibuf, const ColormanageCacheViewSetting
 	cache_data = MEM_callocN(sizeof(ColormnaageCacheData), "color manage cache imbuf data");
 	cache_data->exposure = view_settings->exposure;
 	cache_data->gamma = view_settings->gamma;
-	cache_data->predivide = predivide;
 	cache_data->flag = view_settings->flag;
 	cache_data->curve_mapping = curve_mapping;
 	cache_data->curve_mapping_timestamp = curve_mapping_timestamp;
@@ -897,13 +892,12 @@ void colormanage_imbuf_make_linear(ImBuf *ibuf, const char *from_colorspace)
 
 	if (ibuf->rect_float) {
 		const char *to_colorspace = global_role_scene_linear;
-		int predivide = ibuf->flags & IB_cm_predivide;
 
 		if (ibuf->rect)
 			imb_freerectImBuf(ibuf);
 
 		IMB_colormanagement_transform(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels,
-		                              from_colorspace, to_colorspace, predivide);
+		                              from_colorspace, to_colorspace, TRUE);
 	}
 }
 
@@ -1130,7 +1124,6 @@ typedef struct DisplayBufferThread {
 
 	int channels;
 	float dither;
-	int predivide;
 	int is_data;
 
 	const char *byte_colorspace;
@@ -1158,7 +1151,6 @@ static void display_buffer_init_handle(void *handle_v, int start_line, int tot_l
 	DisplayBufferInitData *init_data = (DisplayBufferInitData *) init_data_v;
 	ImBuf *ibuf = init_data->ibuf;
 
-	int predivide = ibuf->flags & IB_cm_predivide;
 	int channels = ibuf->channels;
 	float dither = ibuf->dither;
 	int is_data = ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA;
@@ -1189,7 +1181,6 @@ static void display_buffer_init_handle(void *handle_v, int start_line, int tot_l
 
 	handle->channels = channels;
 	handle->dither = dither;
-	handle->predivide = predivide;
 	handle->is_data = is_data;
 
 	handle->byte_colorspace = init_data->byte_colorspace;
@@ -1206,7 +1197,6 @@ static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle)
 
 	int buffer_size = channels * width * height;
 
-	int predivide = handle->predivide;
 	int is_data = handle->is_data;
 	int is_data_display = handle->cm_processor->is_data_result;
 
@@ -1224,16 +1214,25 @@ static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle)
 
 		/* first convert byte buffer to float, keep in image space */
 		for (i = 0, fp = linear_buffer, cp = byte_buffer;
-		     i < channels * width * height;
-		     i++, fp++, cp++)
+		     i < width * height;
+		     i++, fp += channels, cp += channels)
 		{
-			*fp = (float)(*cp) / 255.0f;
+			if (channels == 3) {
+				rgb_uchar_to_float(fp, cp);
+			}
+			else if (channels == 4) {
+				rgba_uchar_to_float(fp, cp);
+				straight_to_premul_v4(fp, fp);
+			}
+			else {
+				BLI_assert(!"Buffers of 3 or 4 channels are only supported here");
+			}
 		}
 
 		if (!is_data && !is_data_display) {
 			/* convert float buffer to scene linear space */
 			IMB_colormanagement_transform(linear_buffer, width, height, channels,
-			                              from_colorspace, to_colorspace, predivide);
+			                              from_colorspace, to_colorspace, TRUE);
 		}
 	}
 	else if (handle->float_colorspace) {
@@ -1249,7 +1248,7 @@ static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle)
 		memcpy(linear_buffer, handle->buffer, buffer_size * sizeof(float));
 
 		IMB_colormanagement_transform(linear_buffer, width, height, channels,
-		                              from_colorspace, to_colorspace, predivide);
+		                              from_colorspace, to_colorspace, TRUE);
 	}
 	else {
 		/* some processors would want to modify float original buffer
@@ -1277,13 +1276,12 @@ static void *do_display_buffer_apply_thread(void *handle_v)
 	int width = handle->width;
 	int height = handle->tot_line;
 	float dither = handle->dither;
-	int predivide = handle->predivide;
 	int is_data = handle->is_data;
 
 	if (cm_processor == NULL) {
 		if (display_buffer_byte) {
 			IMB_buffer_byte_from_byte(display_buffer_byte, handle->byte_buffer, IB_PROFILE_SRGB, IB_PROFILE_SRGB,
-			                         FALSE, width, height, width, width);
+			                          FALSE, width, height, width, width);
 		}
 
 		if (display_buffer) {
@@ -1301,7 +1299,7 @@ static void *do_display_buffer_apply_thread(void *handle_v)
 		}
 		else {
 			/* apply processor */
-			IMB_colormanagement_processor_apply(cm_processor, linear_buffer, width, height, channels, predivide);
+			IMB_colormanagement_processor_apply(cm_processor, linear_buffer, width, height, channels, TRUE);
 		}
 
 		/* copy result to output buffers */
@@ -1309,7 +1307,7 @@ static void *do_display_buffer_apply_thread(void *handle_v)
 			/* do conversion */
 			IMB_buffer_byte_from_float(display_buffer_byte, linear_buffer,
 			                           channels, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB,
-			                           predivide, width, height, width, width);
+			                           TRUE, width, height, width, width);
 		}
 
 		if (display_buffer)
@@ -1663,7 +1661,7 @@ static void colormanagement_imbuf_make_display_space(ImBuf *ibuf, const ColorMan
 
 	if (global_tot_display == 0 || global_tot_view == 0) {
 		IMB_buffer_float_from_float(ibuf->rect_float, ibuf->rect_float, ibuf->channels, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB,
-		                            ibuf->flags & IB_cm_predivide, ibuf->x, ibuf->y, ibuf->x, ibuf->x);
+		                            TRUE, ibuf->x, ibuf->y, ibuf->x, ibuf->x);
 	}
 	else {
 		colormanage_display_buffer_process_ex(ibuf, ibuf->rect_float, (unsigned char *)ibuf->rect,
@@ -2326,7 +2324,6 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe
 {
 	int x, y;
 	int channels = ibuf->channels;
-	int predivide = ibuf->flags & IB_cm_predivide;
 	float dither = ibuf->dither;
 	ColorSpace *rect_colorspace = ibuf->rect_colorspace;
 	float *display_buffer_float = NULL;
@@ -2350,13 +2347,11 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe
 			else if (byte_buffer) {
 				rgba_uchar_to_float(pixel, byte_buffer + linear_index);
 				IMB_colormanagement_colorspace_to_scene_linear_v3(pixel, rect_colorspace);
+				straight_to_premul_v4(pixel, pixel);
 			}
 
 			if (!is_data) {
-				if (predivide)
-					IMB_colormanagement_processor_apply_v4(cm_processor, pixel);
-				else
-					IMB_colormanagement_processor_apply_v4(cm_processor, pixel);
+				IMB_colormanagement_processor_apply_v4_predivide(cm_processor, pixel);
 			}
 
 			if (display_buffer_float) {
@@ -2365,7 +2360,9 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe
 				copy_v4_v4(display_buffer_float + index, pixel);
 			}
 			else {
-				rgba_float_to_uchar(display_buffer + display_index, pixel);
+				float pixel_straight[4];
+				premul_to_straight_v4(pixel_straight, pixel);
+				rgba_float_to_uchar(display_buffer + display_index, pixel_straight);
 			}
 		}
 	}
@@ -2389,7 +2386,6 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer,
 		/* update byte buffer created by legacy color management */
 
 		unsigned char *rect = (unsigned char *) ibuf->rect;
-		int predivide = ibuf->flags & IB_cm_predivide;
 		int channels = ibuf->channels;
 		int width = xmax - xmin;
 		int height = ymax - ymin;
@@ -2397,7 +2393,7 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer,
 		int linear_index = ((ymin - offset_y) * stride + (xmin - offset_x)) * channels;
 
 		IMB_buffer_byte_from_float(rect + rect_index, linear_buffer + linear_index, channels, ibuf->dither,
-		                           IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, predivide, width, height, ibuf->x, stride);
+		                           IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, TRUE, width, height, ibuf->x, stride);
 	}
 
 	if (ibuf->display_buffer_flags) {
@@ -2503,6 +2499,15 @@ void IMB_colormanagement_processor_apply_v4(ColormanageProcessor *cm_processor,
 		OCIO_processorApplyRGBA(cm_processor->processor, pixel);
 }
 
+void IMB_colormanagement_processor_apply_v4_predivide(ColormanageProcessor *cm_processor, float pixel[4])
+{
+	if (cm_processor->curve_mapping)
+		curvemapping_evaluate_premulRGBF(cm_processor->curve_mapping, pixel, pixel);
+
+	if (cm_processor->processor)
+		OCIO_processorApplyRGBA_predivide(cm_processor->processor, pixel);
+}
+
 void IMB_colormanagement_processor_apply_v3(ColormanageProcessor *cm_processor, float pixel[3])
 {
 	if (cm_processor->curve_mapping)
diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c
index f049c404e2d..f0d8b7cac72 100644
--- a/source/blender/imbuf/intern/divers.c
+++ b/source/blender/imbuf/intern/divers.c
@@ -39,6 +39,7 @@
 #include "IMB_imbuf_types.h"
 #include "IMB_imbuf.h"
 #include "IMB_allocimbuf.h"
+#include "IMB_filter.h"
 
 #include "IMB_colormanagement.h"
 #include "IMB_colormanagement_intern.h"
@@ -249,11 +250,25 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from,
 			uchar *to = rect_to + stride_to * y * 4;
 
 			if (profile_to == profile_from) {
+				float straight[4];
+
 				/* no color space conversion */
-				if (dither) {
+				if (dither && predivide) {
+					for (x = 0; x < width; x++, from += 4, to += 4) {
+						premul_to_straight_v4(straight, from);
+						float_to_byte_dither_v4(to, straight, di);
+					}
+				}
+				else if (dither) {
 					for (x = 0; x < width; x++, from += 4, to += 4)
 						float_to_byte_dither_v4(to, from, di);
 				}
+				else if (predivide) {
+					for (x = 0; x < width; x++, from += 4, to += 4) {
+						premul_to_straight_v4(straight, from);
+						rgba_float_to_uchar(to, straight);
+					}
+				}
 				else {
 					for (x = 0; x < width; x++, from += 4, to += 4)
 						rgba_float_to_uchar(to, from);
@@ -262,10 +277,12 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from,
 			else if (profile_to == IB_PROFILE_SRGB) {
 				/* convert from linear to sRGB */
 				unsigned short us[4];
+				float straight[4];
 
 				if (dither && predivide) {
 					for (x = 0; x < width; x++, from += 4, to += 4) {
-						linearrgb_to_srgb_ushort4_predivide(us, from);
+						premul_to_straight_v4(straight, from);
+						linearrgb_to_srgb_ushort4(us, from);
 						ushort_to_byte_dither_v4(to, us, di);
 					}
 				}
@@ -277,7 +294,8 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from,
 				}
 				else if (predivide) {
 					for (x = 0; x < width; x++, from += 4, to += 4) {
-						linearrgb_to_srgb_ushort4_predivide(us, from);
+						premul_to_straight_v4(straight, from);
+						linearrgb_to_srgb_ushort4(us, from);
 						ushort_to_byte_v4(to, us);
 					}
 				}
@@ -526,7 +544,6 @@ void IMB_buffer_byte_from_byte(uchar *rect_to, const uchar *rect_from,
 
 void IMB_rect_from_float(ImBuf *ibuf)
 {
-	int predivide = (ibuf->flags & IB_cm_predivide);
 	float *buffer;
 	const char *from_colorspace;
 
@@ -548,7 +565,10 @@ void IMB_rect_from_float(ImBuf *ibuf)
 	buffer = MEM_dupallocN(ibuf->rect_float);
 
 	/* first make float buffer in byte space */
-	IMB_colormanagement_transform(buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, ibuf->rect_colorspace->name, predivide);
+	IMB_colormanagement_transform(buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, ibuf->rect_colorspace->name, TRUE);
+
+	/* convert from float's premul alpha to byte's straight alpha */
+	IMB_unpremultiply_rect_float(buffer, ibuf->planes, ibuf->x, ibuf->y);
 
 	/* convert float to byte */
 	IMB_buffer_byte_from_float((unsigned char *) ibuf->rect, buffer, ibuf->channels, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB,
@@ -565,7 +585,6 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w
 {
 	float *rect_float;
 	uchar *rect_byte;
-	int predivide = (ibuf->flags & IB_cm_predivide);
 	int profile_from = IB_PROFILE_LINEAR_RGB;
 
 	/* verify we have a float buffer */
@@ -588,12 +607,12 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w
 
 		/* and do color space conversion to byte */
 		IMB_buffer_byte_from_float(rect_byte, rect_float,
-		                           4, ibuf->dither, IB_PROFILE_SRGB, profile_from, predivide,
+		                           4, ibuf->dither, IB_PROFILE_SRGB, profile_from, TRUE,
 		                           w, h, ibuf->x, w);
 	}
 	else {
 		IMB_buffer_float_from_float(buffer, rect_float,
-		                            ibuf->channels, IB_PROFILE_SRGB, profile_from, predivide,
+		                            ibuf->channels, IB_PROFILE_SRGB, profile_from, TRUE,
 		                            w, h, w, ibuf->x);
 
 		/* XXX: need to convert to image buffer's rect space */
@@ -608,8 +627,6 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w
 
 void IMB_float_from_rect(ImBuf *ibuf)
 {
-	int predivide = (ibuf->flags & IB_cm_predivide);
-
 	/* verify if we byte and float buffers */
 	if (ibuf->rect == NULL)
 		return;
@@ -634,22 +651,12 @@ void IMB_float_from_rect(ImBuf *ibuf)
 
 	/* then make float be in linear space */
 	IMB_colormanagement_colorspace_to_scene_linear(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels,
-	                                               ibuf->rect_colorspace, predivide);
-
-	BLI_unlock_thread(LOCK_COLORMANAGE);
-}
-
-/* no profile conversion */
-void IMB_float_from_rect_simple(ImBuf *ibuf)
-{
-	int predivide = (ibuf->flags & IB_cm_predivide);
+	                                               ibuf->rect_colorspace, FALSE);
 
-	if (ibuf->rect_float == NULL)
-		imb_addrectfloatImBuf(ibuf);
+	/* byte buffer is straight alpha, float should always be premul */
+	IMB_premultiply_rect_float(ibuf->rect_float, ibuf->planes, ibuf->x, ibuf->y);
 
-	IMB_buffer_float_from_byte(ibuf->rect_float, (uchar *)ibuf->rect,
-	                           IB_PROFILE_SRGB, IB_PROFILE_SRGB, predivide,
-	                           ibuf->x, ibuf->y, ibuf->x, ibuf->x);
+	BLI_unlock_thread(LOCK_COLORMANAGE);
 }
 
 /* use when you need to get a buffer with a certain profile
@@ -660,7 +667,6 @@ void IMB_float_from_rect_simple(ImBuf *ibuf)
  */
 float *IMB_float_profile_ensure(ImBuf *ibuf, int profile, int *alloc)
 {
-	int predivide = (ibuf->flags & IB_cm_predivide);
 	int profile_from = IB_PROFILE_LINEAR_RGB;
 	int profile_to;
 
@@ -686,12 +692,13 @@ float *IMB_float_profile_ensure(ImBuf *ibuf, int profile, int *alloc)
 
 		if (ibuf->rect_float == NULL) {
 			IMB_buffer_float_from_byte(fbuf, (uchar *)ibuf->rect,
-			                           profile_to, profile_from, predivide,
+			                           profile_to, profile_from, FALSE,
 			                           ibuf->x, ibuf->y, ibuf->x, ibuf->x);
+			IMB_premultiply_rect_float(ibuf->rect_float, ibuf->planes, ibuf->x, ibuf->y);
 		}
 		else {
 			IMB_buffer_float_from_float(fbuf, ibuf->rect_float,
-			                            4, profile_to, profile_from, predivide,
+			                            4, profile_to, profile_from, TRUE,
 			                            ibuf->x, ibuf->y, ibuf->x, ibuf->x);
 		}
 
@@ -727,6 +734,26 @@ 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;
+	float *cp = buf;
+	while (total--) {
+		premul_to_straight_v4(cp, cp);
+		cp += 4;
+	}
+}
+
+void IMB_buffer_float_premultiply(float *buf, int width, int height)
+{
+	int total = width * height;
+	float *cp = buf;
+	while (total--) {
+		straight_to_premul_v4(cp, cp);
+		cp += 4;
+	}
+}
+
 /**************************** alter saturation *****************************/
 
 void IMB_saturation(ImBuf *ibuf, float sat)
diff --git a/source/blender/imbuf/intern/filter.c b/source/blender/imbuf/intern/filter.c
index 678b2908b96..51fee232034 100644
--- a/source/blender/imbuf/intern/filter.c
+++ b/source/blender/imbuf/intern/filter.c
@@ -599,3 +599,67 @@ void IMB_premultiply_alpha(ImBuf *ibuf)
 		IMB_premultiply_rect_float(ibuf->rect_float, ibuf->planes, ibuf->x, ibuf->y);
 }
 
+void IMB_unpremultiply_rect(unsigned int *rect, char planes, int w, int h)
+{
+	char *cp;
+	int x, y;
+	float val;
+
+	if (planes == 24) { /* put alpha at 255 */
+		cp = (char *)(rect);
+
+		for (y = 0; y < h; y++)
+			for (x = 0; x < w; x++, cp += 4)
+				cp[3] = 255;
+	}
+	else {
+		cp = (char *)(rect);
+
+		for (y = 0; y < h; y++) {
+			for (x = 0; x < w; x++, cp += 4) {
+				val = cp[3] != 0 ? 1.0f / (float)cp[3] : 1.0f;
+				cp[0] = FTOCHAR(cp[0] * val);
+				cp[1] = FTOCHAR(cp[1] * val);
+				cp[2] = FTOCHAR(cp[2] * val);
+			}
+		}
+	}
+}
+
+void IMB_unpremultiply_rect_float(float *rect_float, char planes, int w, int h)
+{
+	float val, *fp;
+	int x, y;
+
+	if (planes == 24) {   /* put alpha at 1.0 */
+		fp = rect_float;
+
+		for (y = 0; y < h; y++)
+			for (x = 0; x < w; x++, fp += 4)
+				fp[3] = 1.0;
+	}
+	else {
+		fp = rect_float;
+		for (y = 0; y < h; y++) {
+			for (x = 0; x < w; x++, fp += 4) {
+				val = fp[3] != 0.0f ? 1.0f / fp[3] : 1.0f;
+				fp[0] = fp[0] * val;
+				fp[1] = fp[1] * val;
+				fp[2] = fp[2] * val;
+			}
+		}
+	}
+
+}
+
+void IMB_unpremultiply_alpha(ImBuf *ibuf)
+{
+	if (ibuf == NULL)
+		return;
+
+	if (ibuf->rect)
+		IMB_unpremultiply_rect(ibuf->rect, ibuf->planes, ibuf->x, ibuf->y);
+
+	if (ibuf->rect_float)
+		IMB_unpremultiply_rect_float(ibuf->rect_float, ibuf->planes, ibuf->x, ibuf->y);
+}
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp
index da7b31cc2ba..18b08c9b59b 100644
--- a/source/blender/imbuf/intern/openexr/openexr_api.cpp
+++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp
@@ -1197,6 +1197,9 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char
 					delete file;
 				}
 			}
+
+			if (flags & IB_alphamode_detect)
+				ibuf->flags |= IB_alphamode_premul;
 		}
 		return(ibuf);
 	}
diff --git a/source/blender/imbuf/intern/png.c b/source/blender/imbuf/intern/png.c
index c0737fadffa..bbe43132051 100644
--- a/source/blender/imbuf/intern/png.c
+++ b/source/blender/imbuf/intern/png.c
@@ -110,7 +110,7 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
 	unsigned char *pixels = NULL;
 	unsigned char *from, *to;
 	unsigned short *pixels16 = NULL, *to16;
-	float *from_float;
+	float *from_float, from_straight[4];
 	png_bytepp row_pointers = NULL;
 	int i, bytesperpixel, color_type = PNG_COLOR_TYPE_GRAY;
 	FILE *fp = NULL;
@@ -175,10 +175,11 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
 			color_type = PNG_COLOR_TYPE_RGBA;
 			if (is_16bit) {
 				for (i = ibuf->x * ibuf->y; i > 0; i--) {
-					to16[0] = FTOUSHORT(from_float[0]);
-					to16[1] = FTOUSHORT(from_float[1]);
-					to16[2] = FTOUSHORT(from_float[2]);
-					to16[3] = FTOUSHORT(from_float[3]);
+					premul_to_straight_v4(from_straight, from_float);
+					to16[0] = FTOUSHORT(from_straight[0]);
+					to16[1] = FTOUSHORT(from_straight[1]);
+					to16[2] = FTOUSHORT(from_straight[2]);
+					to16[3] = FTOUSHORT(from_straight[3]);
 					to16 += 4; from_float += 4;
 				}
 			}
@@ -196,9 +197,10 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
 			color_type = PNG_COLOR_TYPE_RGB;
 			if (is_16bit) {
 				for (i = ibuf->x * ibuf->y; i > 0; i--) {
-					to16[0] = FTOUSHORT(from_float[0]);
-					to16[1] = FTOUSHORT(from_float[1]);
-					to16[2] = FTOUSHORT(from_float[2]);
+					premul_to_straight_v4(from_straight, from_float);
+					to16[0] = FTOUSHORT(from_straight[0]);
+					to16[1] = FTOUSHORT(from_straight[1]);
+					to16[2] = FTOUSHORT(from_straight[2]);
 					to16 += 3; from_float += 4;
 				}
 			}
@@ -215,7 +217,8 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
 			color_type = PNG_COLOR_TYPE_GRAY;
 			if (is_16bit) {
 				for (i = ibuf->x * ibuf->y; i > 0; i--) {
-					to16[0] = FTOUSHORT(from_float[0]);
+					premul_to_straight_v4(from_straight, from_float);
+					to16[0] = FTOUSHORT(from_straight[0]);
 					to16++; from_float += 4;
 				}
 			}
diff --git a/source/blender/imbuf/intern/radiance_hdr.c b/source/blender/imbuf/intern/radiance_hdr.c
index 03ed1bb8008..d09adeb09b5 100644
--- a/source/blender/imbuf/intern/radiance_hdr.c
+++ b/source/blender/imbuf/intern/radiance_hdr.c
@@ -212,6 +212,9 @@ struct ImBuf *imb_loadhdr(unsigned char *mem, size_t size, int flags, char color
 			if (ibuf == NULL) return NULL;
 			ibuf->ftype = RADHDR;
 
+			if (flags & IB_alphamode_detect)
+				ibuf->flags |= IB_alphamode_premul;
+
 			if (flags & IB_test) return ibuf;
 
 			/* read in and decode the actual data */
diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c
index be20c80bdec..8e0709e3670 100644
--- a/source/blender/imbuf/intern/readimage.c
+++ b/source/blender/imbuf/intern/readimage.c
@@ -86,15 +86,28 @@ ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, char co
 					BLI_strncpy(colorspace, effective_colorspace, IM_MAX_SPACE);
 				}
 
+				if (flags & IB_ignore_alpha) {
+					IMB_rectfill_alpha(ibuf, 1.0f);
+				}
+				else {
+					if (flags & IB_alphamode_premul) {
+						if (ibuf->rect)
+							IMB_unpremultiply_alpha(ibuf);
+						else
+							/* pass, floats are expected to be premul */ ;
+					}
+					else {
+						if (ibuf->rect_float)
+							IMB_premultiply_alpha(ibuf);
+						else
+							/* pass, bytes are expected to be straight */ ;
+					}
+				}
+
 				/* OCIO_TODO: in some cases it's faster to do threaded conversion,
 				 *            but how to distinguish such cases */
 				colormanage_imbuf_make_linear(ibuf, effective_colorspace);
 
-				if (flags & IB_premul) {
-					IMB_premultiply_alpha(ibuf);
-					ibuf->flags |= IB_premul;
-				}
-
 				return ibuf;
 			}
 		}
@@ -230,4 +243,3 @@ void imb_loadtile(ImBuf *ibuf, int tx, int ty, unsigned int *rect)
 
 	close(file);
 }
-
diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c
index 1e701b8d615..75d1f4c412d 100644
--- a/source/blender/imbuf/intern/scaling.c
+++ b/source/blender/imbuf/intern/scaling.c
@@ -33,6 +33,7 @@
 
 
 #include "BLI_utildefines.h"
+#include "BLI_math_color.h"
 #include "MEM_guardedalloc.h"
 
 #include "imbuf.h"
@@ -303,23 +304,33 @@ void imb_onehalf_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1)
 	}
 
 	if (do_rect) {
-		char *p1, *p2, *dest;
+		unsigned char *cp1, *cp2, *dest;
 		
-		p1 = (char *) ibuf1->rect;
-		dest = (char *) ibuf2->rect;
+		cp1 = (unsigned char *) ibuf1->rect;
+		dest = (unsigned char *) ibuf2->rect;
 		for (y = ibuf2->y; y > 0; y--) {
-			p2 = p1 + (ibuf1->x << 2);
+			cp2 = cp1 + (ibuf1->x << 2);
 			for (x = ibuf2->x; x > 0; x--) {
-				dest[0] = (p1[0] + p2[0] + p1[4] + p2[4]) >> 2;
-				dest[1] = (p1[1] + p2[1] + p1[5] + p2[5]) >> 2;
-				dest[2] = (p1[2] + p2[2] + p1[6] + p2[6]) >> 2;
-				dest[3] = (p1[3] + p2[3] + p1[7] + p2[7]) >> 2;
-				p1 += 8; 
-				p2 += 8; 
+				float p1f[8], p2f[8], destf[4];
+
+				straight_uchar_to_premul_float(p1f, cp1);
+				straight_uchar_to_premul_float(p2f, cp2);
+				straight_uchar_to_premul_float(p1f + 4, cp1 + 4);
+				straight_uchar_to_premul_float(p2f + 4, cp2 + 4);
+
+				destf[0] = 0.25f * (p1f[0] + p2f[0] + p1f[4] + p2f[4]);
+				destf[1] = 0.25f * (p1f[1] + p2f[1] + p1f[5] + p2f[5]);
+				destf[2] = 0.25f * (p1f[2] + p2f[2] + p1f[6] + p2f[6]);
+				destf[3] = 0.25f * (p1f[3] + p2f[3] + p1f[7] + p2f[7]);
+
+				premul_float_to_straight_uchar(dest, destf);
+
+				cp1 += 8;
+				cp2 += 8;
 				dest += 4;
 			}
-			p1 = p2;
-			if (ibuf1->x & 1) p1 += 4;
+			cp1 = cp2;
+			if (ibuf1->x & 1) cp1 += 4;
 		}
 	}
 	
diff --git a/source/blender/imbuf/intern/tiff.c b/source/blender/imbuf/intern/tiff.c
index 83830f260e1..2630aebef3b 100644
--- a/source/blender/imbuf/intern/tiff.c
+++ b/source/blender/imbuf/intern/tiff.c
@@ -376,7 +376,7 @@ static void imb_read_tiff_resolution(ImBuf *ibuf, TIFF *image)
  * This method is most flexible and can handle multiple different bit depths 
  * and RGB channel orderings.
  */
-static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image, int premul)
+static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image)
 {
 	ImBuf *tmpibuf;
 	int success = 0;
@@ -390,6 +390,23 @@ static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image, int premul)
 	TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &spp);     /* number of 'channels' */
 	TIFFGetField(image, TIFFTAG_PLANARCONFIG, &config);
 
+	if (spp == 4) {
+		/* HACK: this is really tricky hack, which is only needed to force libtiff
+		 *       do not touch RGB channels when there's alpha channel present
+		 *       The thing is: libtiff will premul RGB if alpha mode is set to
+		 *       unassociated, which really conflicts with blender's assumptions
+		 *
+		 *       Alternative would be to unpremul after load, but it'll be really
+		 *       lossy and unwanted behavior
+		 *
+		 *       So let's keep this thing here for until proper solution is found (sergey)
+		 */
+
+		unsigned short extraSampleTypes[1];
+		extraSampleTypes[0] = EXTRASAMPLE_ASSOCALPHA;
+		TIFFSetField(image, TIFFTAG_EXTRASAMPLES, 1, extraSampleTypes);
+	}
+
 	imb_read_tiff_resolution(ibuf, image);
 
 	scanline = TIFFScanlineSize(image);
@@ -471,10 +488,6 @@ static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image, int premul)
 		if (bitspersample < 16)
 			if (ENDIAN_ORDER == B_ENDIAN)
 				IMB_convert_rgba_to_abgr(tmpibuf);
-		if (premul) {
-			IMB_premultiply_alpha(tmpibuf);
-			ibuf->flags |= IB_premul;
-		}
 		
 		/* assign rect last */
 		if (tmpibuf->rect_float)
@@ -557,6 +570,18 @@ ImBuf *imb_loadtiff(unsigned char *mem, size_t size, int flags, char colorspace[
 		return NULL;
 	}
 
+	/* get alpha mode from file header */
+	if (flags & IB_alphamode_detect) {
+		if (spp == 4) {
+			unsigned short extra, *extraSampleTypes;
+
+			TIFFGetField(image, TIFFTAG_EXTRASAMPLES, &extra, &extraSampleTypes);
+
+			if (extraSampleTypes[0] == EXTRASAMPLE_ASSOCALPHA)
+				ibuf->flags |= IB_alphamode_premul;
+		}
+	}
+
 	/* if testing, we're done */
 	if (flags & IB_test) {
 		TIFFClose(image);
@@ -585,9 +610,6 @@ ImBuf *imb_loadtiff(unsigned char *mem, size_t size, int flags, char colorspace[
 					hbuf->miplevel = level;
 					hbuf->ftype = ibuf->ftype;
 					ibuf->mipmap[level - 1] = hbuf;
-
-					if (flags & IB_premul)
-						hbuf->flags |= IB_premul;
 				}
 				else
 					hbuf = ibuf;
@@ -608,7 +630,7 @@ ImBuf *imb_loadtiff(unsigned char *mem, size_t size, int flags, char colorspace[
 	}
 
 	/* read pixels */
-	if (!(ibuf->flags & IB_tilecache) && !imb_read_tiff_pixels(ibuf, image, 0)) {
+	if (!(ibuf->flags & IB_tilecache) && !imb_read_tiff_pixels(ibuf, image)) {
 		fprintf(stderr, "imb_loadtiff: Failed to read tiff image.\n");
 		TIFFClose(image);
 		return NULL;
@@ -644,9 +666,6 @@ void imb_loadtiletiff(ImBuf *ibuf, unsigned char *mem, size_t size, int tx, int
 				if (TIFFReadRGBATile(image, tx * ibuf->tilex, (ibuf->ytiles - 1 - ty) * ibuf->tiley, rect) == 1) {
 					if (ibuf->tiley > ibuf->y)
 						memmove(rect, rect + ibuf->tilex * (ibuf->tiley - ibuf->y), sizeof(int) * ibuf->tilex * ibuf->y);
-
-					if (ibuf->flags & IB_premul)
-						IMB_premultiply_rect(rect, 32, ibuf->tilex, ibuf->tiley);
 				}
 				else
 					printf("imb_loadtiff: failed to read tiff tile at mipmap level %d\n", ibuf->miplevel);
@@ -689,8 +708,6 @@ int imb_savetiff(ImBuf *ibuf, const char *name, int flags)
 	float *fromf = NULL;
 	float xres, yres;
 	int x, y, from_i, to_i, i;
-	int extraSampleTypes[1] = { EXTRASAMPLE_ASSOCALPHA };
-	
 
 	/* check for a valid number of bytes per pixel.  Like the PNG writer,
 	 * the TIFF writer supports 1, 3 or 4 bytes per pixel, corresponding
@@ -763,6 +780,13 @@ int imb_savetiff(ImBuf *ibuf, const char *name, int flags)
 	TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
 
 	if (samplesperpixel == 4) {
+		unsigned short extraSampleTypes[1];
+
+		if (bitspersample == 16)
+			extraSampleTypes[0] = EXTRASAMPLE_ASSOCALPHA;
+		else
+			extraSampleTypes[0] = EXTRASAMPLE_UNASSALPHA;
+
 		/* RGBA images */
 		TIFFSetField(image, TIFFTAG_EXTRASAMPLES, 1,
 		             extraSampleTypes);
diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h
index fe3550327f7..0f47ee224ae 100644
--- a/source/blender/makesdna/DNA_image_types.h
+++ b/source/blender/makesdna/DNA_image_types.h
@@ -111,6 +111,9 @@ typedef struct Image {
 
 	/* color management */
 	ColorManagedColorspaceSettings colorspace_settings;
+	char alpha_mode;
+
+	char pad[7];
 } Image;
 
 
@@ -119,15 +122,16 @@ typedef struct Image {
 /* Image.flag */
 #define IMA_FIELDS			1
 #define IMA_STD_FIELD		2
-#define IMA_DO_PREMUL		4
+#define IMA_DO_PREMUL		4    /* deprecated, should not be used */
 #define IMA_REFLECT			16
 #define IMA_NOCOLLECT   	32
 #define IMA_DEPRECATED		64
 #define IMA_OLD_PREMUL		128
-#define IMA_CM_PREDIVIDE	256
+/*#define IMA_CM_PREDIVIDE	256*/  /* deprecated, should not be used */
 #define IMA_USED_FOR_RENDER	512
 #define IMA_USER_FRAME_IN_RANGE	1024 /* for image user, but these flags are mixed */
 #define IMA_VIEW_AS_RENDER	2048
+#define IMA_IGNORE_ALPHA	4096
 
 /* Image.tpageflag */
 #define IMA_TILES			1
@@ -148,4 +152,10 @@ typedef struct Image {
 /* gen_flag */
 #define IMA_GEN_FLOAT		1
 
+/* alpha_mode */
+enum {
+	IMA_ALPHA_STRAIGHT = 0,
+	IMA_ALPHA_PREMUL = 1,
+};
+
 #endif
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index fad539de284..1e83b3dadf9 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -1292,11 +1292,11 @@ typedef struct Scene {
 /* alphamode */
 #define R_ADDSKY		0
 #define R_ALPHAPREMUL	1
-#define R_ALPHAKEY		2
+/*#define R_ALPHAKEY		2*/ /* deprecated, shouldn't be used */
 
 /* color_mgt_flag */
 #define R_COLOR_MANAGEMENT              (1 << 0)  /* deprecated, should only be used in versioning code only */
-#define R_COLOR_MANAGEMENT_PREDIVIDE    (1 << 1)
+/*#define R_COLOR_MANAGEMENT_PREDIVIDE    (1 << 1)*/  /* deprecated, shouldn't be used */
 
 /* subimtype, flag options for imtype */
 #define R_OPENEXR_HALF    1                                      /*deprecated*/
diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h
index f106c8f918a..0aa466f7245 100644
--- a/source/blender/makesdna/DNA_sequence_types.h
+++ b/source/blender/makesdna/DNA_sequence_types.h
@@ -172,7 +172,10 @@ typedef struct Sequence {
 	float blend_opacity;
 
 	/* is sfra needed anymore? - it looks like its only used in one place */
-	int sfra, pad;  /* starting frame according to the timeline of the scene. */
+	int sfra;  /* starting frame according to the timeline of the scene. */
+
+	char alpha_mode;
+	char pad[3];
 
 	/* modifiers */
 	ListBase modifiers;
@@ -315,7 +318,7 @@ typedef struct SequencerScopes {
 #define SEQ_OVERLAP                 (1 << 3)
 #define SEQ_FILTERY                 (1 << 4)
 #define SEQ_MUTE                    (1 << 5)
-#define SEQ_MAKE_PREMUL             (1 << 6)
+#define SEQ_MAKE_PREMUL             (1 << 6) /* deprecated, used for compatibility code only */
 #define SEQ_REVERSE_FRAMES          (1 << 7)
 #define SEQ_IPO_FRAME_LOCKED        (1 << 8)
 #define SEQ_EFFECT_NOT_LOADED       (1 << 9)
@@ -366,6 +369,12 @@ typedef struct SequencerScopes {
 #define SEQ_PROXY_TC_RECORD_RUN_NO_GAPS         8
 #define SEQ_PROXY_TC_ALL                        15
 
+/* seq->alpha_mode */
+enum {
+	SEQ_ALPHA_STRAIGHT = 0,
+	SEQ_ALPHA_PREMUL   = 1
+};
+
 /* seq->type WATCH IT: SEQ_TYPE_EFFECT BIT is used to determine if this is an effect strip!!! */
 enum {
 	SEQ_TYPE_IMAGE       = 0,
diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h
index dd63e6aad59..ea4f281efd6 100644
--- a/source/blender/makesdna/DNA_texture_types.h
+++ b/source/blender/makesdna/DNA_texture_types.h
@@ -340,7 +340,7 @@ typedef struct ColorMapping {
 
 /* imaflag */
 #define TEX_INTERPOL	1
-#define TEX_USEALPHA	2
+#define TEX_USEALPHA	2 /* deprecated, used for versioning only */
 #define TEX_MIPMAP		4
 #define TEX_IMAROT		16
 #define TEX_CALCALPHA	32
diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c
index ad7682b3af5..11e33152375 100644
--- a/source/blender/makesrna/intern/rna_image.c
+++ b/source/blender/makesrna/intern/rna_image.c
@@ -134,6 +134,15 @@ static void rna_Image_reload_update(Main *UNUSED(bmain), Scene *UNUSED(scene), P
 }
 
 static void rna_Image_generated_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+	Image *ima = ptr->id.data;
+	BKE_image_signal(ima, NULL, IMA_SIGNAL_COLORMANAGE);
+	DAG_id_tag_update(&ima->id, 0);
+	WM_main_add_notifier(NC_IMAGE | ND_DISPLAY, &ima->id);
+	WM_main_add_notifier(NC_IMAGE | NA_EDITED, &ima->id);
+}
+
+static void rna_Image_colormanage_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
 {
 	Image *ima = ptr->id.data;
 	BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
@@ -463,6 +472,11 @@ static void rna_def_image(BlenderRNA *brna)
 		{IMA_STD_FIELD, "ODD", 0, "Lower First", "Lower field first"},
 		{0, NULL, 0, NULL, NULL}
 	};
+	static const EnumPropertyItem alpha_mode_items[] = {
+		{IMA_ALPHA_STRAIGHT, "STRAIGHT", 0, "Straight", "Transparent RGB and alpha pixels are unmodified"},
+		{IMA_ALPHA_PREMUL, "PREMUL", 0, "Premultiplied", "Transparent RGB pixels are multiplied by the alpha channel"},
+		{0, NULL, 0, NULL, NULL}
+	};
 
 	srna = RNA_def_struct(brna, "Image", "ID");
 	RNA_def_struct_ui_text(srna, "Image", "Image datablock referencing an external or packed image");
@@ -512,23 +526,17 @@ static void rna_def_image(BlenderRNA *brna)
 	RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_fields_update");
 	RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
 	
-	prop = RNA_def_property(srna, "use_premultiply", PROP_BOOLEAN, PROP_NONE);
-	RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_DO_PREMUL);
-	RNA_def_property_ui_text(prop, "Premultiply", "Convert RGB from key alpha to premultiplied alpha");
-	RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_free_update");
-	
-	prop = RNA_def_property(srna, "use_color_unpremultiply", PROP_BOOLEAN, PROP_NONE);
-	RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_CM_PREDIVIDE);
-	RNA_def_property_ui_text(prop, "Color Unpremultiply",
-	                         "For premultiplied alpha images, do color space conversion on colors without alpha, "
-	                         "to avoid fringing for images with light backgrounds");
-	RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_free_update");
 
 	prop = RNA_def_property(srna, "view_as_render", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_VIEW_AS_RENDER);
 	RNA_def_property_ui_text(prop, "View as Render", "Apply render part of display transformation when displaying this image on the screen");
 	RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL);
 
+	prop = RNA_def_property(srna, "use_alpha", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", IMA_IGNORE_ALPHA);
+	RNA_def_property_ui_text(prop, "Use Alpha", "Use the alpha channel information from the image or make image fully opaque");
+	RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_generated_update");
+
 	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);
@@ -677,6 +685,11 @@ static void rna_def_image(BlenderRNA *brna)
 	RNA_def_property_struct_type(prop, "ColorManagedInputColorspaceSettings");
 	RNA_def_property_ui_text(prop, "Color Space Settings", "Input color space settings");
 
+	prop = RNA_def_property(srna, "alpha_mode", PROP_ENUM, PROP_NONE);
+	RNA_def_property_enum_items(prop, alpha_mode_items);
+	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_generated_update");
+
 	RNA_api_image(srna);
 }
 
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 5696511b614..b08e4731789 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -3332,8 +3332,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
 		
 	static EnumPropertyItem alpha_mode_items[] = {
 		{R_ADDSKY, "SKY", 0, "Sky", "Transparent pixels are filled with sky color"},
-		{R_ALPHAPREMUL, "PREMUL", 0, "Premultiplied", "Transparent RGB pixels are multiplied by the alpha channel"},
-		{R_ALPHAKEY, "STRAIGHT", 0, "Straight Alpha", "Transparent RGB and alpha pixels are unmodified"},
+		{R_ALPHAPREMUL, "TRANSPARENT", 0, "Transparent", "World background is transparent with premultiplied alpha"},
 		{0, NULL, 0, NULL, NULL}
 	};
 
@@ -3767,13 +3766,6 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
 	                         "editor pipeline, if sequencer strips exist");
 	RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
 	
-	prop = RNA_def_property(srna, "use_color_unpremultiply", PROP_BOOLEAN, PROP_NONE);
-	RNA_def_property_boolean_sdna(prop, NULL, "color_mgt_flag", R_COLOR_MANAGEMENT_PREDIVIDE);
-	RNA_def_property_ui_text(prop, "Color Unpremultiply",
-	                         "For premultiplied alpha render output, do color space conversion on "
-	                         "colors without alpha, to avoid fringing on light backgrounds");
-	RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
-	
 	prop = RNA_def_property(srna, "use_file_extension", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "scemode", R_EXTENSION);
 	RNA_def_property_ui_text(prop, "File Extensions",
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index 5c51f871ac8..e849e84ff38 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -1541,14 +1541,20 @@ static void rna_def_filter_video(StructRNA *srna)
 {
 	PropertyRNA *prop;
 
+	static const EnumPropertyItem alpha_mode_items[] = {
+		{SEQ_ALPHA_STRAIGHT, "STRAIGHT", 0, "Straight", "RGB channels in transparent pixels are unaffected by the alpha channel"},
+		{SEQ_ALPHA_PREMUL, "PREMUL", 0, "Premultiplied", "RGB channels in transparent pixels are multiplied by the alpha channel"},
+		{0, NULL, 0, NULL, NULL}
+	};
+
 	prop = RNA_def_property(srna, "use_deinterlace", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_FILTERY);
 	RNA_def_property_ui_text(prop, "De-Interlace", "For video movies to remove fields");
 	RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update_reopen_files");
 
-	prop = RNA_def_property(srna, "use_premultiply", PROP_BOOLEAN, PROP_NONE);
-	RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_MAKE_PREMUL);
-	RNA_def_property_ui_text(prop, "Premultiply", "Convert RGB from key alpha to premultiplied alpha");
+	prop = RNA_def_property(srna, "alpha_mode", PROP_ENUM, PROP_NONE);
+	RNA_def_property_enum_items(prop, alpha_mode_items);
+	RNA_def_property_ui_text(prop, "Alpha Mode", "Representation of alpha information in the RGBA pixels");
 	RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
 
 	prop = RNA_def_property(srna, "use_flip_x", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c
index e116e5df0de..2ab448c9188 100644
--- a/source/blender/makesrna/intern/rna_texture.c
+++ b/source/blender/makesrna/intern/rna_texture.c
@@ -1194,11 +1194,6 @@ static void rna_def_texture_image(BlenderRNA *brna)
 	RNA_def_property_ui_text(prop, "Flip Axis", "Flip the texture's X and Y axis");
 	RNA_def_property_update(prop, 0, "rna_Texture_update");
 
-	prop = RNA_def_property(srna, "use_alpha", PROP_BOOLEAN, PROP_NONE);
-	RNA_def_property_boolean_sdna(prop, NULL, "imaflag", TEX_USEALPHA);
-	RNA_def_property_ui_text(prop, "Use Alpha", "Use the alpha channel information in the image");
-	RNA_def_property_update(prop, 0, "rna_Texture_update");
-
 	prop = RNA_def_property(srna, "use_calculate_alpha", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "imaflag", TEX_CALCALPHA);
 	RNA_def_property_ui_text(prop, "Calculate Alpha", "Calculate an alpha channel based on RGB values in the image");
diff --git a/source/blender/nodes/composite/node_composite_util.c b/source/blender/nodes/composite/node_composite_util.c
index 57eb99021f6..c4b48b83b16 100644
--- a/source/blender/nodes/composite/node_composite_util.c
+++ b/source/blender/nodes/composite/node_composite_util.c
@@ -615,7 +615,7 @@ void generate_preview(void *data, bNode *node, CompBuf *stackbuf)
 	bNodePreview *preview= node->preview;
 	int xsize, ysize;
 	int profile_from= (rd->color_mgt_flag & R_COLOR_MANAGEMENT)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB;
-	int predivide= (rd->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE);
+	int predivide= TRUE;
 	int dither= 0;
 	unsigned char *rect;
 	
diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c
index 88d78df190f..7e44210928c 100644
--- a/source/blender/nodes/composite/nodes/node_composite_image.c
+++ b/source/blender/nodes/composite/nodes/node_composite_image.c
@@ -291,7 +291,6 @@ static void cmp_node_image_update(bNodeTree *ntree, bNode *node)
 float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc)
 {
 	float *rect;
-	int predivide= (ibuf->flags & IB_cm_predivide);
 
 	*alloc= FALSE;
 
@@ -305,7 +304,7 @@ float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc)
 		rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image");
 
 		IMB_buffer_float_from_float(rect, ibuf->rect_float,
-			4, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, predivide,
+			4, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, TRUE,
 			ibuf->x, ibuf->y, ibuf->x, ibuf->x);
 
 			*alloc= TRUE;
diff --git a/source/blender/render/intern/include/render_result.h b/source/blender/render/intern/include/render_result.h
index 5d61417cbaf..61b39a59b0b 100644
--- a/source/blender/render/intern/include/render_result.h
+++ b/source/blender/render/intern/include/render_result.h
@@ -91,7 +91,7 @@ void render_result_rect_from_ibuf(struct RenderResult *rr, struct RenderData *rd
 	struct ImBuf *ibuf);
 
 void render_result_rect_fill_zero(struct RenderResult *rr);
-void render_result_rect_get_pixels(struct RenderResult *rr, struct RenderData *rd,
+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);
diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c
index 7c14e0e5465..4aaa6247478 100644
--- a/source/blender/render/intern/source/imagetexture.c
+++ b/source/blender/render/intern/source/imagetexture.c
@@ -102,6 +102,11 @@ static void ibuf_get_color(float col[4], struct ImBuf *ibuf, int x, int y)
 		col[1] = ((float)rect[1])*(1.0f/255.0f);
 		col[2] = ((float)rect[2])*(1.0f/255.0f);
 		col[3] = ((float)rect[3])*(1.0f/255.0f);
+
+		/* bytes are internally straight, however render pipeline seems to expect premul */
+		col[0] *= col[3];
+		col[1] *= col[3];
+		col[2] *= col[3];
 	}
 }
 
@@ -219,10 +224,8 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul
 	}
 
 	/* keep this before interpolation [#29761] */
-	if (tex->imaflag & TEX_USEALPHA) {
-		if ((tex->imaflag & TEX_CALCALPHA) == 0) {
-			texres->talpha = TRUE;
-		}
+	if ((tex->imaflag & TEX_CALCALPHA) == 0) {
+		texres->talpha = TRUE;
 	}
 
 	/* interpolate */
@@ -710,9 +713,10 @@ static int ibuf_get_color_clip(float col[4], ImBuf *ibuf, int x, int y, int extf
 	}
 	else {
 		char *rect = (char *)(ibuf->rect + x + y*ibuf->x);
-		col[0] = rect[0]*(1.f/255.f);
-		col[1] = rect[1]*(1.f/255.f);
-		col[2] = rect[2]*(1.f/255.f);
+		float inv_alpha_fac = (1.0f / 255.0f) * rect[3] * (1.0f / 255.0f);
+		col[0] = rect[0] * inv_alpha_fac;
+		col[1] = rect[1] * inv_alpha_fac;
+		col[2] = rect[2] * inv_alpha_fac;
 		col[3] = clip ? 0.f : rect[3]*(1.f/255.f);
 	}
 	return clip;
@@ -1088,7 +1092,8 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
 	/* mipmap test */
 	image_mipmap_test(tex, ibuf);
 	
-	if ((tex->imaflag & TEX_USEALPHA) && ((tex->imaflag & TEX_CALCALPHA) == 0)) texres->talpha = 1;
+	if ((tex->imaflag & TEX_CALCALPHA) == 0)
+		texres->talpha = 1;
 	texr.talpha = texres->talpha;
 
 	if (tex->imaflag & TEX_IMAROT) {
@@ -1501,13 +1506,8 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const
 	/* mipmap test */
 	image_mipmap_test(tex, ibuf);
 
-	if (tex->imaflag & TEX_USEALPHA) {
-		if (tex->imaflag & TEX_CALCALPHA) {
-			/* pass */
-		}
-		else {
-			texres->talpha = TRUE;
-		}
+	if ((tex->imaflag & TEX_CALCALPHA) == 0) {
+		texres->talpha = TRUE;
 	}
 	
 	texr.talpha= texres->talpha;
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 0545d2940ab..f2db84c47a9 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -336,7 +336,7 @@ void RE_ResultGet32(Render *re, unsigned int *rect)
 	RenderResult rres;
 	
 	RE_AcquireResultImage(re, &rres);
-	render_result_rect_get_pixels(&rres, &re->r, rect, re->rectx, re->recty, &re->scene->view_settings, &re->scene->display_settings);
+	render_result_rect_get_pixels(&rres, rect, re->rectx, re->recty, &re->scene->view_settings, &re->scene->display_settings);
 	RE_ReleaseResultImage(re);
 }
 
@@ -833,7 +833,7 @@ static void threaded_tile_processor(Render *re)
 	
 	if (re->result == NULL)
 		return;
-	
+
 	/* warning; no return here without closing exr file */
 	
 	RE_parts_init(re, TRUE);
@@ -1092,7 +1092,7 @@ static void do_render_blur_3d(Render *re)
 		
 		blurfac = 1.0f / (float)(re->r.mblur_samples - blur);
 		
-		merge_renderresult_blur(rres, re->result, blurfac, re->r.alphamode & R_ALPHAKEY);
+		merge_renderresult_blur(rres, re->result, blurfac, FALSE);
 		if (re->test_break(re->tbh)) break;
 	}
 	
diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c
index f8281586038..78750cfd1ca 100644
--- a/source/blender/render/intern/source/render_result.c
+++ b/source/blender/render/intern/source/render_result.c
@@ -434,7 +434,7 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
 	rr->renrect.xmin = 0; rr->renrect.xmax = rectx - 2 * crop;
 	/* crop is one or two extra pixels rendered for filtering, is used for merging and display too */
 	rr->crop = crop;
-	
+
 	/* tilerect is relative coordinates within render disprect. do not subtract crop yet */
 	rr->tilerect.xmin = partrct->xmin - re->disprect.xmin;
 	rr->tilerect.xmax = partrct->xmax - re->disprect.xmin;
@@ -1077,8 +1077,7 @@ int render_result_exr_file_read_path(RenderResult *rr, RenderLayer *rl_single, c
 
 ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd)
 {
-	int flags = (rd->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE) ? IB_cm_predivide : 0;
-	ImBuf *ibuf = IMB_allocImBuf(rr->rectx, rr->recty, rd->im_format.planes, flags);
+	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;
@@ -1148,17 +1147,15 @@ void render_result_rect_fill_zero(RenderResult *rr)
 		rr->rect32 = MEM_callocN(sizeof(int) * rr->rectx * rr->recty, "render_seq rect");
 }
 
-void render_result_rect_get_pixels(RenderResult *rr, RenderData *rd, unsigned int *rect, int rectx, int recty,
+void render_result_rect_get_pixels(RenderResult *rr, unsigned int *rect, int rectx, int recty,
                                    const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings)
 {
 	if (rr->rect32) {
 		memcpy(rect, rr->rect32, sizeof(int) * rr->rectx * rr->recty);
 	}
 	else if (rr->rectf) {
-		int predivide = (rd->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE);
-
 		IMB_display_buffer_transform_apply((unsigned char *) rect, rr->rectf, rr->rectx, rr->recty, 4,
-		                                   view_settings, display_settings, predivide);
+		                                   view_settings, display_settings, TRUE);
 	}
 	else
 		/* else fill with black */
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index 9f171ba71db..9b08d6c07e9 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -710,9 +710,11 @@ static void sky_tile(RenderPart *pa, RenderLayer *rl)
 					
 					if (pass[3]==0.0f) {
 						copy_v4_v4(pass, col);
+						pass[3] = 1.0f;
 					}
 					else {
 						addAlphaUnderFloat(pass, col);
+						pass[3] = 1.0f;
 					}
 				}
 			}
@@ -981,29 +983,6 @@ static void edge_enhance_add(RenderPart *pa, float *rectf, float *arect)
 	}
 }
 
-static void convert_to_key_alpha(RenderPart *pa, RenderLayer *rl)
-{
-	RenderLayer *rlpp[RE_MAX_OSA];
-	int y, sample, totsample;
-	
-	totsample= get_sample_layers(pa, rl, rlpp);
-	
-	for (sample= 0; samplerectf;
-		
-		for (y= pa->rectx*pa->recty; y>0; y--, rectf+=4) {
-			if (rectf[3] >= 1.0f) {
-				/* pass */
-			}
-			else if (rectf[3] > 0.0f) {
-				rectf[0] /= rectf[3];
-				rectf[1] /= rectf[3];
-				rectf[2] /= rectf[3];
-			}
-		}
-	}
-}
-
 /* clamp alpha and RGB to 0..1 and 0..inf, can go outside due to filter */
 static void clamp_alpha_rgb_range(RenderPart *pa, RenderLayer *rl)
 {
@@ -1312,10 +1291,6 @@ void zbufshadeDA_tile(RenderPart *pa)
 		/* clamp alpha to 0..1 range, can go outside due to filter */
 		clamp_alpha_rgb_range(pa, rl);
 		
-		/* de-premul alpha */
-		if (R.r.alphamode & R_ALPHAKEY)
-			convert_to_key_alpha(pa, rl);
-		
 		/* free stuff within loop! */
 		MEM_freeN(pa->rectdaps); pa->rectdaps= NULL;
 		freeps(&psmlist);
@@ -1476,10 +1451,6 @@ void zbufshade_tile(RenderPart *pa)
 		if (rl->passflag & SCE_PASS_VECTOR)
 			reset_sky_speed(pa, rl);
 		
-		/* de-premul alpha */
-		if (R.r.alphamode & R_ALPHAKEY)
-			convert_to_key_alpha(pa, rl);
-		
 		if (edgerect) MEM_freeN(edgerect);
 		edgerect= NULL;
 
-- 
cgit v1.2.3


From 93f78ac1e1313544c633dd88d2ad05565f37ae82 Mon Sep 17 00:00:00 2001
From: Sergey Sharybin 
Date: Mon, 31 Dec 2012 13:52:26 +0000
Subject: Removed byte glow effect from sequencer in favor of float one.

Byte glow was disabled in previous commit and code is removed now
in separate commit for easier revert if that'd be needed.
---
 source/blender/blenkernel/intern/seqeffects.c | 226 --------------------------
 1 file changed, 226 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c
index 7dbbca6ddaa..3ca04f235b8 100644
--- a/source/blender/blenkernel/intern/seqeffects.c
+++ b/source/blender/blenkernel/intern/seqeffects.c
@@ -1827,166 +1827,6 @@ static ImBuf *do_transform_effect(SeqRenderData context, Sequence *seq, float UN
 
 /*********************** Glow *************************/
 
-static void RVBlurBitmap2_byte(unsigned char *map, int width, int height, float blur, int quality)
-/*	MUUUCCH better than the previous blur. */
-/*	We do the blurring in two passes which is a whole lot faster. */
-/*	I changed the math arount to implement an actual Gaussian */
-/*	distribution. */
-/* */
-/*	Watch out though, it tends to misbehaven with large blur values on */
-/*	a small bitmap.  Avoid avoid avoid. */
-/*=============================== */
-{
-	unsigned char *temp = NULL, *swap;
-	float   *filter = NULL;
-	int x, y, i, fx, fy;
-	int index, ix, halfWidth;
-	float fval, k, curColor[3], curColor2[3], weight = 0;
-
-	/* If we're not really blurring, bail out */
-	if (blur <= 0)
-		return;
-
-	/*Allocate memory for the tempmap and the blur filter matrix */
-	temp = MEM_mallocN((width * height * 4), "blurbitmaptemp");
-	if (!temp)
-		return;
-
-	/*Allocate memory for the filter elements */
-	halfWidth = ((quality + 1) * blur);
-	filter = (float *)MEM_mallocN(sizeof(float) * halfWidth * 2, "blurbitmapfilter");
-	if (!filter) {
-		MEM_freeN(temp);
-		return;
-	}
-
-	/* Apparently we're calculating a bell curve based on the standard deviation (or radius)
-	 * This code is based on an example posted to comp.graphics.algorithms by
-	 * Blancmange (bmange@airdmhor.gen.nz)
-	 */
-
-	k = -1.0f / (2.0f * (float)M_PI * blur * blur);
-	for (ix = 0; ix < halfWidth; ix++) {
-		weight = (float)exp(k * (ix * ix));
-		filter[halfWidth - ix] = weight;
-		filter[halfWidth + ix] = weight;
-	}
-	filter[0] = weight;
-
-	/* Normalize the array */
-	fval = 0;
-	for (ix = 0; ix < halfWidth * 2; ix++)
-		fval += filter[ix];
-
-	for (ix = 0; ix < halfWidth * 2; ix++)
-		filter[ix] /= fval;
-
-	/* Blur the rows */
-	for (y = 0; y < height; y++) {
-		/* Do the left & right strips */
-		for (x = 0; x < halfWidth; x++) {
-			index = (x + y * width) * 4;
-			fx = 0;
-			zero_v3(curColor);
-			zero_v3(curColor2);
-
-			for (i = x - halfWidth; i < x + halfWidth; i++) {
-				if ((i >= 0) && (i < width)) {
-					curColor[0] += map[(i + y * width) * 4 + GlowR] * filter[fx];
-					curColor[1] += map[(i + y * width) * 4 + GlowG] * filter[fx];
-					curColor[2] += map[(i + y * width) * 4 + GlowB] * filter[fx];
-
-					curColor2[0] += map[(width - 1 - i + y * width) * 4 + GlowR] * filter[fx];
-					curColor2[1] += map[(width - 1 - i + y * width) * 4 + GlowG] * filter[fx];
-					curColor2[2] += map[(width - 1 - i + y * width) * 4 + GlowB] * filter[fx];
-				}
-				fx++;
-			}
-			temp[index + GlowR] = curColor[0];
-			temp[index + GlowG] = curColor[1];
-			temp[index + GlowB] = curColor[2];
-
-			temp[((width - 1 - x + y * width) * 4) + GlowR] = curColor2[0];
-			temp[((width - 1 - x + y * width) * 4) + GlowG] = curColor2[1];
-			temp[((width - 1 - x + y * width) * 4) + GlowB] = curColor2[2];
-
-		}
-
-		/* Do the main body */
-		for (x = halfWidth; x < width - halfWidth; x++) {
-			index = (x + y * width) * 4;
-			fx = 0;
-			zero_v3(curColor);
-			for (i = x - halfWidth; i < x + halfWidth; i++) {
-				curColor[0] += map[(i + y * width) * 4 + GlowR] * filter[fx];
-				curColor[1] += map[(i + y * width) * 4 + GlowG] * filter[fx];
-				curColor[2] += map[(i + y * width) * 4 + GlowB] * filter[fx];
-				fx++;
-			}
-			temp[index + GlowR] = curColor[0];
-			temp[index + GlowG] = curColor[1];
-			temp[index + GlowB] = curColor[2];
-		}
-	}
-
-	/* Swap buffers */
-	swap = temp; temp = map; map = swap;
-
-	/* Blur the columns */
-	for (x = 0; x < width; x++) {
-		/* Do the top & bottom strips */
-		for (y = 0; y < halfWidth; y++) {
-			index = (x + y * width) * 4;
-			fy = 0;
-			zero_v3(curColor);
-			zero_v3(curColor2);
-			for (i = y - halfWidth; i < y + halfWidth; i++) {
-				if ((i >= 0) && (i < height)) {
-					/* Bottom */
-					curColor[0] += map[(x + i * width) * 4 + GlowR] * filter[fy];
-					curColor[1] += map[(x + i * width) * 4 + GlowG] * filter[fy];
-					curColor[2] += map[(x + i * width) * 4 + GlowB] * filter[fy];
-
-					/* Top */
-					curColor2[0] += map[(x + (height - 1 - i) * width) * 4 + GlowR] * filter[fy];
-					curColor2[1] += map[(x + (height - 1 - i) * width) * 4 + GlowG] * filter[fy];
-					curColor2[2] += map[(x + (height - 1 - i) * width) * 4 + GlowB] * filter[fy];
-				}
-				fy++;
-			}
-			temp[index + GlowR] = curColor[0];
-			temp[index + GlowG] = curColor[1];
-			temp[index + GlowB] = curColor[2];
-			temp[((x + (height - 1 - y) * width) * 4) + GlowR] = curColor2[0];
-			temp[((x + (height - 1 - y) * width) * 4) + GlowG] = curColor2[1];
-			temp[((x + (height - 1 - y) * width) * 4) + GlowB] = curColor2[2];
-		}
-
-		/* Do the main body */
-		for (y = halfWidth; y < height - halfWidth; y++) {
-			index = (x + y * width) * 4;
-			fy = 0;
-			zero_v3(curColor);
-			for (i = y - halfWidth; i < y + halfWidth; i++) {
-				curColor[0] += map[(x + i * width) * 4 + GlowR] * filter[fy];
-				curColor[1] += map[(x + i * width) * 4 + GlowG] * filter[fy];
-				curColor[2] += map[(x + i * width) * 4 + GlowB] * filter[fy];
-				fy++;
-			}
-			temp[index + GlowR] = curColor[0];
-			temp[index + GlowG] = curColor[1];
-			temp[index + GlowB] = curColor[2];
-		}
-	}
-
-	/* Swap buffers */
-	swap = temp; temp = map; /* map = swap; */ /* UNUSED */
-
-	/* Tidy up */
-	MEM_freeN(filter);
-	MEM_freeN(temp);
-}
-
 static void RVBlurBitmap2_float(float *map, int width, int height, float blur, int quality)
 /*	MUUUCCH better than the previous blur. */
 /*	We do the blurring in two passes which is a whole lot faster. */
@@ -2148,26 +1988,6 @@ static void RVBlurBitmap2_float(float *map, int width, int height, float blur, i
 	MEM_freeN(temp);
 }
 
-
-/*	Adds two bitmaps and puts the results into a third map. */
-/*	C must have been previously allocated but it may be A or B. */
-/*	We clamp values to 255 to prevent weirdness */
-/*=============================== */
-static void RVAddBitmaps_byte(unsigned char *a, unsigned char *b, unsigned char *c, int width, int height)
-{
-	int x, y, index;
-
-	for (y = 0; y < height; y++) {
-		for (x = 0; x < width; x++) {
-			index = (x + y * width) * 4;
-			c[index + GlowR] = MIN2(255, a[index + GlowR] + b[index + GlowR]);
-			c[index + GlowG] = MIN2(255, a[index + GlowG] + b[index + GlowG]);
-			c[index + GlowB] = MIN2(255, a[index + GlowB] + b[index + GlowB]);
-			c[index + GlowA] = MIN2(255, a[index + GlowA] + b[index + GlowA]);
-		}
-	}
-}
-
 static void RVAddBitmaps_float(float *a, float *b, float *c, int width, int height)
 {
 	int x, y, index;
@@ -2183,37 +2003,6 @@ static void RVAddBitmaps_float(float *a, float *b, float *c, int width, int heig
 	}
 }
 
-/* For each pixel whose total luminance exceeds the threshold,
- * Multiply it's value by BOOST and add it to the output map
- */
-static void RVIsolateHighlights_byte(unsigned char *in, unsigned char *out, int width, int height, int threshold,
-                                     float boost, float clamp)
-{
-	int x, y, index;
-	int intensity;
-
-	for (y = 0; y < height; y++) {
-		for (x = 0; x < width; x++) {
-			index = (x + y * width) * 4;
-
-			/* Isolate the intensity */
-			intensity = (in[index + GlowR] + in[index + GlowG] + in[index + GlowB] - threshold);
-			if (intensity > 0) {
-				out[index + GlowR] = MIN2(255 * clamp, (in[index + GlowR] * boost * intensity) / 255);
-				out[index + GlowG] = MIN2(255 * clamp, (in[index + GlowG] * boost * intensity) / 255);
-				out[index + GlowB] = MIN2(255 * clamp, (in[index + GlowB] * boost * intensity) / 255);
-				out[index + GlowA] = MIN2(255 * clamp, (in[index + GlowA] * boost * intensity) / 255);
-			}
-			else {
-				out[index + GlowR] = 0;
-				out[index + GlowG] = 0;
-				out[index + GlowB] = 0;
-				out[index + GlowA] = 0;
-			}
-		}
-	}
-}
-
 static void RVIsolateHighlights_float(float *in, float *out, int width, int height, float threshold, float boost, float clamp)
 {
 	int x, y, index;
@@ -2280,20 +2069,6 @@ static void copy_glow_effect(Sequence *dst, Sequence *src)
 static void do_glow_effect_byte(Sequence *seq, int render_size, float facf0, float UNUSED(facf1),  int x, int y,
                                 unsigned char *rect1, unsigned char *UNUSED(rect2), unsigned char *out)
 {
-#if 0
-	/* XXX: not sure what's better here, on the one hand conversion to floats
-	 *      here is not so much trouble, but on the other hand who're using
-	 *      glow on buffers with alpha?
-	 */
-	unsigned char *outbuf = out;
-	unsigned char *inbuf = rect1;
-	GlowVars *glow = (GlowVars *)seq->effectdata;
-
-	RVIsolateHighlights_byte(inbuf, outbuf, x, y, glow->fMini * 765, glow->fBoost * facf0, glow->fClamp);
-	RVBlurBitmap2_byte(outbuf, x, y, glow->dDist * (render_size / 100.0f), glow->dQuality);
-	if (!glow->bNoComp)
-		RVAddBitmaps_byte(inbuf, outbuf, outbuf, x, y);
-#else
 	float *outbuf, *inbuf;
 	GlowVars *glow = (GlowVars *)seq->effectdata;
 
@@ -2313,7 +2088,6 @@ static void do_glow_effect_byte(Sequence *seq, int render_size, float facf0, flo
 
 	MEM_freeN(inbuf);
 	MEM_freeN(outbuf);
-#endif
 }
 
 static void do_glow_effect_float(Sequence *seq, int render_size, float facf0, float UNUSED(facf1),  int x, int y,
-- 
cgit v1.2.3


From 334ca1d344123f4d8f54c16cf93dab9f2fdae88f Mon Sep 17 00:00:00 2001
From: Sergey Sharybin 
Date: Mon, 31 Dec 2012 14:02:33 +0000
Subject: Correction to recent PNG commit

Need to set default depth to 8bit.
---
 source/blender/blenkernel/intern/image.c | 1 +
 source/blender/blenkernel/intern/scene.c | 1 +
 2 files changed, 2 insertions(+)

(limited to 'source')

diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index b93f917c9e2..dbc423f98b3 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -1309,6 +1309,7 @@ void BKE_imformat_defaults(ImageFormatData *im_format)
 	memset(im_format, 0, sizeof(*im_format));
 	im_format->planes = R_IMF_PLANES_RGB;
 	im_format->imtype = R_IMF_IMTYPE_PNG;
+	im_format->depth = R_IMF_CHAN_DEPTH_8;
 	im_format->quality = 90;
 	im_format->compress = 90;
 
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index baf2e7e47e3..bccbdc44584 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -400,6 +400,7 @@ static Scene *scene_add(Main *bmain, const char *name)
 
 	sce->r.im_format.planes = R_IMF_PLANES_RGB;
 	sce->r.im_format.imtype = R_IMF_IMTYPE_PNG;
+	sce->r.im_format.depth = R_IMF_CHAN_DEPTH_8;
 	sce->r.im_format.quality = 90;
 	sce->r.im_format.compress = 90;
 
-- 
cgit v1.2.3


From acc05db50faa7323e32bab988b2f28e1bb05bc51 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Mon, 31 Dec 2012 14:49:27 +0000
Subject: minor updates to text autocomplete api - draw function wasn't lining
 up correctly since DPI edits - rename text_python.c to text_autocomplete.c

---
 source/blender/blenkernel/BKE_suggestions.h        |   2 +-
 source/blender/blenkernel/intern/suggestions.c     |   8 +-
 source/blender/editors/space_text/CMakeLists.txt   |   2 +-
 .../blender/editors/space_text/text_autocomplete.c | 352 ++++++++++++++++++++
 source/blender/editors/space_text/text_draw.c      |   4 +-
 source/blender/editors/space_text/text_python.c    | 358 ---------------------
 6 files changed, 360 insertions(+), 366 deletions(-)
 create mode 100644 source/blender/editors/space_text/text_autocomplete.c
 delete mode 100644 source/blender/editors/space_text/text_python.c

(limited to 'source')

diff --git a/source/blender/blenkernel/BKE_suggestions.h b/source/blender/blenkernel/BKE_suggestions.h
index 9b61d9141fb..c36a2d61968 100644
--- a/source/blender/blenkernel/BKE_suggestions.h
+++ b/source/blender/blenkernel/BKE_suggestions.h
@@ -75,7 +75,7 @@ short texttool_text_is_active(Text *text);
 
 /* Suggestions */
 void texttool_suggest_add(const char *name, char type);
-void texttool_suggest_prefix(const char *prefix);
+void texttool_suggest_prefix(const char *prefix, const int prefix_len);
 void texttool_suggest_clear(void);
 SuggItem *texttool_suggest_first(void);
 SuggItem *texttool_suggest_last(void);
diff --git a/source/blender/blenkernel/intern/suggestions.c b/source/blender/blenkernel/intern/suggestions.c
index ff9774f85af..6f9736df683 100644
--- a/source/blender/blenkernel/intern/suggestions.c
+++ b/source/blender/blenkernel/intern/suggestions.c
@@ -163,13 +163,13 @@ void texttool_suggest_add(const char *name, char type)
 	suggestions.top = 0;
 }
 
-void texttool_suggest_prefix(const char *prefix)
+void texttool_suggest_prefix(const char *prefix, const int prefix_len)
 {
 	SuggItem *match, *first, *last;
-	int cmp, len = strlen(prefix), top = 0;
+	int cmp, top = 0;
 
 	if (!suggestions.first) return;
-	if (len == 0) {
+	if (prefix_len == 0) {
 		suggestions.selected = suggestions.firstmatch = suggestions.first;
 		suggestions.lastmatch = suggestions.last;
 		return;
@@ -177,7 +177,7 @@ void texttool_suggest_prefix(const char *prefix)
 	
 	first = last = NULL;
 	for (match = suggestions.first; match; match = match->next) {
-		cmp = txttl_cmp(prefix, match->name, len);
+		cmp = txttl_cmp(prefix, match->name, prefix_len);
 		if (cmp == 0) {
 			if (!first) {
 				first = match;
diff --git a/source/blender/editors/space_text/CMakeLists.txt b/source/blender/editors/space_text/CMakeLists.txt
index b9e4e2f0afa..a33a9abada1 100644
--- a/source/blender/editors/space_text/CMakeLists.txt
+++ b/source/blender/editors/space_text/CMakeLists.txt
@@ -36,13 +36,13 @@ set(INC_SYS
 
 set(SRC
 	space_text.c
+	text_autocomplete.c
 	text_draw.c
 	text_format.c
 	text_format_osl.c
 	text_format_py.c
 	text_header.c
 	text_ops.c
-	text_python.c
 
 	text_format.h
 	text_intern.h
diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c
new file mode 100644
index 00000000000..044c5322f23
--- /dev/null
+++ b/source/blender/editors/space_text/text_autocomplete.c
@@ -0,0 +1,352 @@
+/*
+ * ***** 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.
+ * All rights reserved.
+ *
+ * 
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_text/text_python.c
+ *  \ingroup sptext
+ */
+
+#include 
+
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_text_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_suggestions.h"
+#include "BKE_text.h"
+
+#include "BLI_blenlib.h"
+
+#include "WM_types.h"
+
+#include "text_intern.h"
+
+int text_do_suggest_select(SpaceText *st, ARegion *ar)
+{
+	SuggItem *item, *first, *last /* , *sel */ /* UNUSED */;
+	TextLine *tmp;
+	int l, x, y, w, h, i;
+	int tgti, *top;
+	int mval[2] = {0, 0};
+	
+	if (!st || !st->text) return 0;
+	if (!texttool_text_is_active(st->text)) return 0;
+
+	first = texttool_suggest_first();
+	last = texttool_suggest_last();
+	/* sel = texttool_suggest_selected(); */ /* UNUSED */
+	top = texttool_suggest_top();
+
+	if (!last || !first)
+		return 0;
+
+	/* Count the visible lines to the cursor */
+	for (tmp = st->text->curl, l = -st->top; tmp; tmp = tmp->prev, l++) ;
+	if (l < 0) return 0;
+
+	text_update_character_width(st);
+	
+	if (st->showlinenrs) {
+		x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET + TEXTXLOC - 4;
+	}
+	else {
+		x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET - 4;
+	}
+	y = ar->winy - st->lheight_dpi * l - 2;
+
+	w = SUGG_LIST_WIDTH * st->cwidth + U.widget_unit;
+	h = SUGG_LIST_SIZE * st->lheight_dpi + 0.4f * U.widget_unit;
+
+	// XXX getmouseco_areawin(mval);
+
+	if (mval[0] < x || x + w < mval[0] || mval[1] < y - h || y < mval[1])
+		return 0;
+
+	/* Work out which of the items is at the top of the visible list */
+	for (i = 0, item = first; i < *top && item->next; i++, item = item->next) ;
+
+	/* Work out the target item index in the visible list */
+	tgti = (y - mval[1] - 4) / st->lheight_dpi;
+	if (tgti < 0 || tgti > SUGG_LIST_SIZE)
+		return 1;
+
+	for (i = tgti; i > 0 && item->next; i--, item = item->next) ;
+	if (item)
+		texttool_suggest_select(item);
+	return 1;
+}
+
+void text_pop_suggest_list(void)
+{
+	SuggItem *item, *sel;
+	int *top, i;
+
+	item = texttool_suggest_first();
+	sel = texttool_suggest_selected();
+	top = texttool_suggest_top();
+
+	i = 0;
+	while (item && item != sel) {
+		item = item->next;
+		i++;
+	}
+	if (i > *top + SUGG_LIST_SIZE - 1)
+		*top = i - SUGG_LIST_SIZE + 1;
+	else if (i < *top)
+		*top = i;
+}
+
+static void get_suggest_prefix(Text *text, int offset)
+{
+	int i, len;
+	char *line;
+
+	if (!text) return;
+	if (!texttool_text_is_active(text)) return;
+
+	line = text->curl->line;
+	for (i = text->curc - 1 + offset; i >= 0; i--)
+		if (!text_check_identifier(line[i]))
+			break;
+	i++;
+	len = text->curc - i + offset;
+	texttool_suggest_prefix(line + i, len);
+}
+
+static void confirm_suggestion(Text *text, int skipleft)
+{
+	SuggItem *sel;
+	int i, over = 0;
+	char *line;
+
+	if (!text) return;
+	if (!texttool_text_is_active(text)) return;
+
+	sel = texttool_suggest_selected();
+	if (!sel) return;
+
+	line = text->curl->line;
+	i = text->curc - skipleft - 1;
+	while (i >= 0) {
+		if (!text_check_identifier(line[i]))
+			break;
+		over++;
+		i--;
+	}
+
+	for (i = 0; i < skipleft; i++)
+		txt_move_left(text, 0);
+	for (i = 0; i < over; i++)
+		txt_move_left(text, 1);
+
+	txt_insert_buf(text, sel->name);
+	
+	for (i = 0; i < skipleft; i++)
+		txt_move_right(text, 0);
+
+	texttool_text_clear();
+}
+
+// XXX
+#define LR_SHIFTKEY 0
+#define LR_ALTKEY 0
+#define LR_CTRLKEY 0
+
+// XXX
+static int doc_scroll = 0;
+
+static short UNUSED_FUNCTION(do_texttools) (SpaceText * st, char ascii, unsigned short evnt, short val)
+{
+	ARegion *ar = NULL; // XXX
+	int qual = 0; // XXX
+	int draw = 0, tools = 0, swallow = 0, scroll = 1;
+	if (!texttool_text_is_active(st->text)) return 0;
+	if (!st->text || st->text->id.lib) return 0;
+
+	if (st->doplugins && texttool_text_is_active(st->text)) {
+		if (texttool_suggest_first()) tools |= TOOL_SUGG_LIST;
+		if (texttool_docs_get()) tools |= TOOL_DOCUMENT;
+	}
+
+	if (ascii) {
+		if (tools & TOOL_SUGG_LIST) {
+			if ((ascii != '_' && ascii != '*' && ispunct(ascii)) || text_check_whitespace(ascii)) {
+				confirm_suggestion(st->text, 0);
+				text_update_line_edited(st->text->curl);
+			}
+			else if ((st->overwrite && txt_replace_char(st->text, ascii)) || txt_add_char(st->text, ascii)) {
+				get_suggest_prefix(st->text, 0);
+				text_pop_suggest_list();
+				swallow = 1;
+				draw = 1;
+			}
+		}
+		if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0, draw = 1;
+
+	}
+	else if (val == 1 && evnt) {
+		switch (evnt) {
+			case LEFTMOUSE:
+				if (text_do_suggest_select(st, ar))
+					swallow = 1;
+				else {
+					if (tools & TOOL_SUGG_LIST) texttool_suggest_clear();
+					if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
+				}
+				draw = 1;
+				break;
+			case MIDDLEMOUSE:
+				if (text_do_suggest_select(st, ar)) {
+					confirm_suggestion(st->text, 0);
+					text_update_line_edited(st->text->curl);
+					swallow = 1;
+				}
+				else {
+					if (tools & TOOL_SUGG_LIST) texttool_suggest_clear();
+					if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
+				}
+				draw = 1;
+				break;
+			case ESCKEY:
+				draw = swallow = 1;
+				if (tools & TOOL_SUGG_LIST) texttool_suggest_clear();
+				else if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
+				else draw = swallow = 0;
+				break;
+			case RETKEY:
+				if (tools & TOOL_SUGG_LIST) {
+					confirm_suggestion(st->text, 0);
+					text_update_line_edited(st->text->curl);
+					swallow = 1;
+					draw = 1;
+				}
+				if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0, draw = 1;
+				break;
+			case LEFTARROWKEY:
+			case BACKSPACEKEY:
+				if (tools & TOOL_SUGG_LIST) {
+					if (qual)
+						texttool_suggest_clear();
+					else {
+						/* Work out which char we are about to delete/pass */
+						if (st->text->curl && st->text->curc > 0) {
+							char ch = st->text->curl->line[st->text->curc - 1];
+							if ((ch == '_' || !ispunct(ch)) && !text_check_whitespace(ch)) {
+								get_suggest_prefix(st->text, -1);
+								text_pop_suggest_list();
+							}
+							else
+								texttool_suggest_clear();
+						}
+						else
+							texttool_suggest_clear();
+					}
+				}
+				if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
+				break;
+			case RIGHTARROWKEY:
+				if (tools & TOOL_SUGG_LIST) {
+					if (qual)
+						texttool_suggest_clear();
+					else {
+						/* Work out which char we are about to pass */
+						if (st->text->curl && st->text->curc < st->text->curl->len) {
+							char ch = st->text->curl->line[st->text->curc + 1];
+							if ((ch == '_' || !ispunct(ch)) && !text_check_whitespace(ch)) {
+								get_suggest_prefix(st->text, 1);
+								text_pop_suggest_list();
+							}
+							else
+								texttool_suggest_clear();
+						}
+						else
+							texttool_suggest_clear();
+					}
+				}
+				if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
+				break;
+			case PAGEDOWNKEY:
+				scroll = SUGG_LIST_SIZE - 1;
+			case WHEELDOWNMOUSE:
+			case DOWNARROWKEY:
+				if (tools & TOOL_DOCUMENT) {
+					doc_scroll++;
+					swallow = 1;
+					draw = 1;
+					break;
+				}
+				else if (tools & TOOL_SUGG_LIST) {
+					SuggItem *sel = texttool_suggest_selected();
+					if (!sel) {
+						texttool_suggest_select(texttool_suggest_first());
+					}
+					else {
+						while (sel && sel != texttool_suggest_last() && sel->next && scroll--) {
+							texttool_suggest_select(sel->next);
+							sel = sel->next;
+						}
+					}
+					text_pop_suggest_list();
+					swallow = 1;
+					draw = 1;
+					break;
+				}
+			case PAGEUPKEY:
+				scroll = SUGG_LIST_SIZE - 1;
+			case WHEELUPMOUSE:
+			case UPARROWKEY:
+				if (tools & TOOL_DOCUMENT) {
+					if (doc_scroll > 0) doc_scroll--;
+					swallow = 1;
+					draw = 1;
+					break;
+				}
+				else if (tools & TOOL_SUGG_LIST) {
+					SuggItem *sel = texttool_suggest_selected();
+					while (sel && sel != texttool_suggest_first() && sel->prev && scroll--) {
+						texttool_suggest_select(sel->prev);
+						sel = sel->prev;
+					}
+					text_pop_suggest_list();
+					swallow = 1;
+					draw = 1;
+					break;
+				}
+			case RIGHTSHIFTKEY:
+			case LEFTSHIFTKEY:
+				break;
+			default:
+				if (tools & TOOL_SUGG_LIST) texttool_suggest_clear(), draw = 1;
+				if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0, draw = 1;
+		}
+	}
+
+	if (draw) {
+		// XXX redraw_alltext();
+	}
+
+	return swallow;
+}
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index 11a5687915b..6e33fc122b5 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -894,7 +894,7 @@ static void draw_documentation(SpaceText *st, ARegion *ar)
 
 	/* top = */ /* UNUSED */ y = ar->winy - st->lheight_dpi * l - 2;
 	boxw = DOC_WIDTH * st->cwidth + 20;
-	boxh = (DOC_HEIGHT + 1) * st->lheight_dpi;
+	boxh = (DOC_HEIGHT + 1) * (st->lheight_dpi + TXT_LINE_SPACING);
 
 	/* Draw panel */
 	UI_ThemeColor(TH_BACK);
@@ -981,7 +981,7 @@ static void draw_suggestion_list(SpaceText *st, ARegion *ar)
 	else {
 		x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET - 4;
 	}
-	y = ar->winy - st->lheight_dpi * l - 2;
+	y = ar->winy - (st->lheight_dpi + TXT_LINE_SPACING) * l - 2;
 
 	boxw = SUGG_LIST_WIDTH * st->cwidth + 20;
 	boxh = SUGG_LIST_SIZE * st->lheight_dpi + 8;
diff --git a/source/blender/editors/space_text/text_python.c b/source/blender/editors/space_text/text_python.c
deleted file mode 100644
index 1201302dad0..00000000000
--- a/source/blender/editors/space_text/text_python.c
+++ /dev/null
@@ -1,358 +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) 2008 Blender Foundation.
- * All rights reserved.
- *
- * 
- * Contributor(s): Blender Foundation
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/editors/space_text/text_python.c
- *  \ingroup sptext
- */
-
-#include 
-
-#include "DNA_screen_types.h"
-#include "DNA_space_types.h"
-#include "DNA_text_types.h"
-#include "DNA_userdef_types.h"
-
-#include "BKE_suggestions.h"
-#include "BKE_text.h"
-
-#include "BLI_blenlib.h"
-
-#include "WM_types.h"
-
-#include "text_intern.h"
-
-int text_do_suggest_select(SpaceText *st, ARegion *ar)
-{
-	SuggItem *item, *first, *last /* , *sel */ /* UNUSED */;
-	TextLine *tmp;
-	int l, x, y, w, h, i;
-	int tgti, *top;
-	int mval[2] = {0, 0};
-	
-	if (!st || !st->text) return 0;
-	if (!texttool_text_is_active(st->text)) return 0;
-
-	first = texttool_suggest_first();
-	last = texttool_suggest_last();
-	/* sel = texttool_suggest_selected(); */ /* UNUSED */
-	top = texttool_suggest_top();
-
-	if (!last || !first)
-		return 0;
-
-	/* Count the visible lines to the cursor */
-	for (tmp = st->text->curl, l = -st->top; tmp; tmp = tmp->prev, l++) ;
-	if (l < 0) return 0;
-
-	text_update_character_width(st);
-	
-	if (st->showlinenrs) {
-		x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET + TEXTXLOC - 4;
-	}
-	else {
-		x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET - 4;
-	}
-	y = ar->winy - st->lheight_dpi * l - 2;
-
-	w = SUGG_LIST_WIDTH * st->cwidth + U.widget_unit;
-	h = SUGG_LIST_SIZE * st->lheight_dpi + 0.4f * U.widget_unit;
-
-	// XXX getmouseco_areawin(mval);
-
-	if (mval[0] < x || x + w < mval[0] || mval[1] < y - h || y < mval[1])
-		return 0;
-
-	/* Work out which of the items is at the top of the visible list */
-	for (i = 0, item = first; i < *top && item->next; i++, item = item->next) ;
-
-	/* Work out the target item index in the visible list */
-	tgti = (y - mval[1] - 4) / st->lheight_dpi;
-	if (tgti < 0 || tgti > SUGG_LIST_SIZE)
-		return 1;
-
-	for (i = tgti; i > 0 && item->next; i--, item = item->next) ;
-	if (item)
-		texttool_suggest_select(item);
-	return 1;
-}
-
-void text_pop_suggest_list(void)
-{
-	SuggItem *item, *sel;
-	int *top, i;
-
-	item = texttool_suggest_first();
-	sel = texttool_suggest_selected();
-	top = texttool_suggest_top();
-
-	i = 0;
-	while (item && item != sel) {
-		item = item->next;
-		i++;
-	}
-	if (i > *top + SUGG_LIST_SIZE - 1)
-		*top = i - SUGG_LIST_SIZE + 1;
-	else if (i < *top)
-		*top = i;
-}
-
-static void get_suggest_prefix(Text *text, int offset)
-{
-	int i, len;
-	char *line, tmp[256];
-
-	if (!text) return;
-	if (!texttool_text_is_active(text)) return;
-
-	line = text->curl->line;
-	for (i = text->curc - 1 + offset; i >= 0; i--)
-		if (!text_check_identifier(line[i]))
-			break;
-	i++;
-	len = text->curc - i + offset;
-	if (len > 255) {
-		printf("Suggestion prefix too long\n");
-		len = 255;
-	}
-	BLI_strncpy(tmp, line + i, len);
-	tmp[len] = '\0';
-	texttool_suggest_prefix(tmp);
-}
-
-static void confirm_suggestion(Text *text, int skipleft)
-{
-	SuggItem *sel;
-	int i, over = 0;
-	char *line;
-
-	if (!text) return;
-	if (!texttool_text_is_active(text)) return;
-
-	sel = texttool_suggest_selected();
-	if (!sel) return;
-
-	line = text->curl->line;
-	i = text->curc - skipleft - 1;
-	while (i >= 0) {
-		if (!text_check_identifier(line[i]))
-			break;
-		over++;
-		i--;
-	}
-
-	for (i = 0; i < skipleft; i++)
-		txt_move_left(text, 0);
-	for (i = 0; i < over; i++)
-		txt_move_left(text, 1);
-
-	txt_insert_buf(text, sel->name);
-	
-	for (i = 0; i < skipleft; i++)
-		txt_move_right(text, 0);
-
-	texttool_text_clear();
-}
-
-// XXX
-#define LR_SHIFTKEY 0
-#define LR_ALTKEY 0
-#define LR_CTRLKEY 0
-
-// XXX
-static int doc_scroll = 0;
-
-static short UNUSED_FUNCTION(do_texttools) (SpaceText * st, char ascii, unsigned short evnt, short val)
-{
-	ARegion *ar = NULL; // XXX
-	int qual = 0; // XXX
-	int draw = 0, tools = 0, swallow = 0, scroll = 1;
-	if (!texttool_text_is_active(st->text)) return 0;
-	if (!st->text || st->text->id.lib) return 0;
-
-	if (st->doplugins && texttool_text_is_active(st->text)) {
-		if (texttool_suggest_first()) tools |= TOOL_SUGG_LIST;
-		if (texttool_docs_get()) tools |= TOOL_DOCUMENT;
-	}
-
-	if (ascii) {
-		if (tools & TOOL_SUGG_LIST) {
-			if ((ascii != '_' && ascii != '*' && ispunct(ascii)) || text_check_whitespace(ascii)) {
-				confirm_suggestion(st->text, 0);
-				text_update_line_edited(st->text->curl);
-			}
-			else if ((st->overwrite && txt_replace_char(st->text, ascii)) || txt_add_char(st->text, ascii)) {
-				get_suggest_prefix(st->text, 0);
-				text_pop_suggest_list();
-				swallow = 1;
-				draw = 1;
-			}
-		}
-		if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0, draw = 1;
-
-	}
-	else if (val == 1 && evnt) {
-		switch (evnt) {
-			case LEFTMOUSE:
-				if (text_do_suggest_select(st, ar))
-					swallow = 1;
-				else {
-					if (tools & TOOL_SUGG_LIST) texttool_suggest_clear();
-					if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
-				}
-				draw = 1;
-				break;
-			case MIDDLEMOUSE:
-				if (text_do_suggest_select(st, ar)) {
-					confirm_suggestion(st->text, 0);
-					text_update_line_edited(st->text->curl);
-					swallow = 1;
-				}
-				else {
-					if (tools & TOOL_SUGG_LIST) texttool_suggest_clear();
-					if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
-				}
-				draw = 1;
-				break;
-			case ESCKEY:
-				draw = swallow = 1;
-				if (tools & TOOL_SUGG_LIST) texttool_suggest_clear();
-				else if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
-				else draw = swallow = 0;
-				break;
-			case RETKEY:
-				if (tools & TOOL_SUGG_LIST) {
-					confirm_suggestion(st->text, 0);
-					text_update_line_edited(st->text->curl);
-					swallow = 1;
-					draw = 1;
-				}
-				if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0, draw = 1;
-				break;
-			case LEFTARROWKEY:
-			case BACKSPACEKEY:
-				if (tools & TOOL_SUGG_LIST) {
-					if (qual)
-						texttool_suggest_clear();
-					else {
-						/* Work out which char we are about to delete/pass */
-						if (st->text->curl && st->text->curc > 0) {
-							char ch = st->text->curl->line[st->text->curc - 1];
-							if ((ch == '_' || !ispunct(ch)) && !text_check_whitespace(ch)) {
-								get_suggest_prefix(st->text, -1);
-								text_pop_suggest_list();
-							}
-							else
-								texttool_suggest_clear();
-						}
-						else
-							texttool_suggest_clear();
-					}
-				}
-				if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
-				break;
-			case RIGHTARROWKEY:
-				if (tools & TOOL_SUGG_LIST) {
-					if (qual)
-						texttool_suggest_clear();
-					else {
-						/* Work out which char we are about to pass */
-						if (st->text->curl && st->text->curc < st->text->curl->len) {
-							char ch = st->text->curl->line[st->text->curc + 1];
-							if ((ch == '_' || !ispunct(ch)) && !text_check_whitespace(ch)) {
-								get_suggest_prefix(st->text, 1);
-								text_pop_suggest_list();
-							}
-							else
-								texttool_suggest_clear();
-						}
-						else
-							texttool_suggest_clear();
-					}
-				}
-				if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
-				break;
-			case PAGEDOWNKEY:
-				scroll = SUGG_LIST_SIZE - 1;
-			case WHEELDOWNMOUSE:
-			case DOWNARROWKEY:
-				if (tools & TOOL_DOCUMENT) {
-					doc_scroll++;
-					swallow = 1;
-					draw = 1;
-					break;
-				}
-				else if (tools & TOOL_SUGG_LIST) {
-					SuggItem *sel = texttool_suggest_selected();
-					if (!sel) {
-						texttool_suggest_select(texttool_suggest_first());
-					}
-					else {
-						while (sel && sel != texttool_suggest_last() && sel->next && scroll--) {
-							texttool_suggest_select(sel->next);
-							sel = sel->next;
-						}
-					}
-					text_pop_suggest_list();
-					swallow = 1;
-					draw = 1;
-					break;
-				}
-			case PAGEUPKEY:
-				scroll = SUGG_LIST_SIZE - 1;
-			case WHEELUPMOUSE:
-			case UPARROWKEY:
-				if (tools & TOOL_DOCUMENT) {
-					if (doc_scroll > 0) doc_scroll--;
-					swallow = 1;
-					draw = 1;
-					break;
-				}
-				else if (tools & TOOL_SUGG_LIST) {
-					SuggItem *sel = texttool_suggest_selected();
-					while (sel && sel != texttool_suggest_first() && sel->prev && scroll--) {
-						texttool_suggest_select(sel->prev);
-						sel = sel->prev;
-					}
-					text_pop_suggest_list();
-					swallow = 1;
-					draw = 1;
-					break;
-				}
-			case RIGHTSHIFTKEY:
-			case LEFTSHIFTKEY:
-				break;
-			default:
-				if (tools & TOOL_SUGG_LIST) texttool_suggest_clear(), draw = 1;
-				if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0, draw = 1;
-		}
-	}
-
-	if (draw) {
-		// XXX redraw_alltext();
-	}
-
-	return swallow;
-}
-- 
cgit v1.2.3


From 44632295b323de590fcc7068c836c3d2445049bc Mon Sep 17 00:00:00 2001
From: Bastien Montagne 
Date: Mon, 31 Dec 2012 14:52:55 +0000
Subject: Some minor cleanup in camera's FOV angle props (mostly use DEG2RAD
 macro, and remove reference to degrees in tips - user is free to use radians
 if he prefers!).

---
 source/blender/makesrna/intern/rna_camera.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

(limited to 'source')

diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c
index b72bba0422a..0b1e1c215c4 100644
--- a/source/blender/makesrna/intern/rna_camera.c
+++ b/source/blender/makesrna/intern/rna_camera.c
@@ -112,8 +112,8 @@ void RNA_def_camera(BlenderRNA *brna)
 		{0, NULL, 0, NULL, NULL}
 	};
 	static EnumPropertyItem prop_lens_unit_items[] = {
-		{0, "MILLIMETERS", 0, "Millimeters", ""},
-		{CAM_ANGLETOGGLE, "DEGREES", 0, "Degrees", ""},
+		{0, "MILLIMETERS", 0, "Millimeters", "Specify the lens in millimeters"},
+		{CAM_ANGLETOGGLE, "FOV", 0, "Field of View", "Specify the lens as the field of view's angle"},
 		{0, NULL, 0, NULL, NULL}
 	};
 	static EnumPropertyItem sensor_fit_items[] = {
@@ -154,23 +154,23 @@ void RNA_def_camera(BlenderRNA *brna)
 	RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
 
 	prop = RNA_def_property(srna, "angle_x", PROP_FLOAT, PROP_ANGLE);
-	RNA_def_property_range(prop, M_PI * (0.367 / 180.0), M_PI * (172.847 / 180.0));
+	RNA_def_property_range(prop, DEG2RAD(0.367), DEG2RAD(172.847));
 	RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
-	RNA_def_property_ui_text(prop, "Horizontal FOV", "Camera lens horizontal field of view in degrees");
+	RNA_def_property_ui_text(prop, "Horizontal FOV", "Camera lens horizontal field of view");
 	RNA_def_property_float_funcs(prop, "rna_Camera_angle_x_get", "rna_Camera_angle_x_set", NULL);
 	RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_update");
 
 	prop = RNA_def_property(srna, "angle_y", PROP_FLOAT, PROP_ANGLE);
-	RNA_def_property_range(prop, M_PI * (0.367 / 180.0), M_PI * (172.847 / 180.0));
+	RNA_def_property_range(prop, DEG2RAD(0.367), DEG2RAD(172.847));
 	RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
-	RNA_def_property_ui_text(prop, "Vertical FOV", "Camera lens vertical field of view in degrees");
+	RNA_def_property_ui_text(prop, "Vertical FOV", "Camera lens vertical field of view");
 	RNA_def_property_float_funcs(prop, "rna_Camera_angle_y_get", "rna_Camera_angle_y_set", NULL);
 	RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_update");
 
 	prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE);
-	RNA_def_property_range(prop, M_PI * (0.367 / 180.0), M_PI * (172.847 / 180.0));
+	RNA_def_property_range(prop, DEG2RAD(0.367), DEG2RAD(172.847));
 	RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
-	RNA_def_property_ui_text(prop, "Field of View", "Camera lens field of view in degrees");
+	RNA_def_property_ui_text(prop, "Field of View", "Camera lens field of view");
 	RNA_def_property_float_funcs(prop, "rna_Camera_angle_get", "rna_Camera_angle_set", NULL);
 	RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_update");
 
-- 
cgit v1.2.3


From b754fcd6f93ff610d533803a1acb2fd4c3aac0ae Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Mon, 31 Dec 2012 14:55:16 +0000
Subject: code cleanup: warning

---
 source/blender/imbuf/intern/readimage.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

(limited to 'source')

diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c
index 8e0709e3670..00bc78ee488 100644
--- a/source/blender/imbuf/intern/readimage.c
+++ b/source/blender/imbuf/intern/readimage.c
@@ -91,16 +91,20 @@ ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, char co
 				}
 				else {
 					if (flags & IB_alphamode_premul) {
-						if (ibuf->rect)
+						if (ibuf->rect) {
 							IMB_unpremultiply_alpha(ibuf);
-						else
-							/* pass, floats are expected to be premul */ ;
+						}
+						else {
+							/* pass, floats are expected to be premul */
+						}
 					}
 					else {
-						if (ibuf->rect_float)
+						if (ibuf->rect_float) {
 							IMB_premultiply_alpha(ibuf);
-						else
-							/* pass, bytes are expected to be straight */ ;
+						}
+						else {
+							/* pass, bytes are expected to be straight */
+						}
 					}
 				}
 
-- 
cgit v1.2.3


From d4eac8189ead0db6b01f3b393f563158cff0ca92 Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Mon, 31 Dec 2012 14:56:07 +0000
Subject: Removed on old patch from the code, which attempted to keep the
 scrollers in user preferences in place.

New scroller code made user pref scroller jump back on activating add-ons,
because that causes a full blender system refresh.
---
 source/blender/editors/screen/area.c                   | 4 ----
 source/blender/editors/space_userpref/space_userpref.c | 4 +++-
 2 files changed, 3 insertions(+), 5 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 827f19307b8..5af60726f14 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -1783,10 +1783,6 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *
 void ED_region_panels_init(wmWindowManager *wm, ARegion *ar)
 {
 	wmKeyMap *keymap;
-	
-	/* used for correctly initialized User-Prefs only?  */
-//	if (!(ar->v2d.align & V2D_ALIGN_NO_POS_Y))
-//		ar->v2d.flag &= ~V2D_IS_INITIALISED;
 
 	UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_PANELS_UI, ar->winx, ar->winy);
 
diff --git a/source/blender/editors/space_userpref/space_userpref.c b/source/blender/editors/space_userpref/space_userpref.c
index 6560f218002..5ebbebec35b 100644
--- a/source/blender/editors/space_userpref/space_userpref.c
+++ b/source/blender/editors/space_userpref/space_userpref.c
@@ -105,7 +105,9 @@ static SpaceLink *userpref_duplicate(SpaceLink *sl)
 /* add handlers, stuff you only do once or on area/region changes */
 static void userpref_main_area_init(wmWindowManager *wm, ARegion *ar)
 {
-	ar->v2d.flag &= ~V2D_IS_INITIALISED;
+	/* do not use here, the properties changed in userprefs do a system-wide refresh, then scroller jumps back */
+	/*	ar->v2d.flag &= ~V2D_IS_INITIALISED; */
+	
 	ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
 
 	ED_region_panels_init(wm, ar);
-- 
cgit v1.2.3


From 4e1da54b5e35d7069850d186988447b279fd49b3 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Mon, 31 Dec 2012 15:11:36 +0000
Subject: add back initial autocomplete support.

- This doesnt use python as 2.4x did, instead it just autocompletes based on the text files unique identifiers so its useful for any language.
- key is same as console (Ctrl+Space)
---
 source/blender/editors/space_text/space_text.c     |   6 +-
 .../blender/editors/space_text/text_autocomplete.c | 375 ++++++++++++++++-----
 source/blender/editors/space_text/text_intern.h    |   2 +
 3 files changed, 297 insertions(+), 86 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c
index 6ebadb3b921..fa3eefcc0f7 100644
--- a/source/blender/editors/space_text/space_text.c
+++ b/source/blender/editors/space_text/space_text.c
@@ -223,6 +223,8 @@ static void text_operatortypes(void)
 	WM_operatortype_append(TEXT_OT_to_3d_object);
 
 	WM_operatortype_append(TEXT_OT_resolve_conflict);
+
+	WM_operatortype_append(TEXT_OT_autocomplete);
 }
 
 static void text_keymap(struct wmKeyConfig *keyconf)
@@ -276,7 +278,7 @@ static void text_keymap(struct wmKeyConfig *keyconf)
 	kmi = WM_keymap_add_item(keymap, "WM_OT_context_cycle_int", PADMINUS, KM_PRESS, KM_CTRL, 0);
 	RNA_string_set(kmi->ptr, "data_path", "space_data.font_size");
 	RNA_boolean_set(kmi->ptr, "reverse", TRUE);
-	
+
 	WM_keymap_add_item(keymap, "TEXT_OT_new", NKEY, KM_PRESS, KM_CTRL, 0);
 	WM_keymap_add_item(keymap, "TEXT_OT_open", OKEY, KM_PRESS, KM_ALT, 0);
 	WM_keymap_add_item(keymap, "TEXT_OT_reload", RKEY, KM_PRESS, KM_ALT, 0);
@@ -375,6 +377,8 @@ static void text_keymap(struct wmKeyConfig *keyconf)
 	WM_keymap_add_item(keymap, "TEXT_OT_line_break", PADENTER, KM_PRESS, 0, 0);
 
 	WM_keymap_add_menu(keymap, "TEXT_MT_toolbox", RIGHTMOUSE, KM_PRESS, KM_ANY, 0);
+
+	WM_keymap_add_item(keymap, "TEXT_OT_autocomplete", SPACEKEY, KM_PRESS, KM_CTRL, 0);
 	
 	WM_keymap_add_item(keymap, "TEXT_OT_line_number", KM_TEXTINPUT, KM_ANY, KM_ANY, 0);
 	WM_keymap_add_item(keymap, "TEXT_OT_insert", KM_TEXTINPUT, KM_ANY, KM_ANY, 0); // last!
diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c
index 044c5322f23..097174f2645 100644
--- a/source/blender/editors/space_text/text_autocomplete.c
+++ b/source/blender/editors/space_text/text_autocomplete.c
@@ -4,7 +4,7 @@
  * 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. 
+ * 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
@@ -15,34 +15,46 @@
  * 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.
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
  *
- * 
- * Contributor(s): Blender Foundation
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
  *
  * ***** END GPL LICENSE BLOCK *****
  */
 
-/** \file blender/editors/space_text/text_python.c
+/** \file blender/editors/space_text/text_autocomplete.c
  *  \ingroup sptext
  */
 
 #include 
+#include 
 
-#include "DNA_screen_types.h"
-#include "DNA_space_types.h"
-#include "DNA_text_types.h"
-#include "DNA_userdef_types.h"
+#include "MEM_guardedalloc.h"
 
-#include "BKE_suggestions.h"
-#include "BKE_text.h"
+#include "DNA_text_types.h"
 
 #include "BLI_blenlib.h"
+#include "BLI_ghash.h"
+
+#include "BKE_context.h"
+#include "BKE_text.h"
+#include "BKE_screen.h"
+#include "BKE_suggestions.h"
 
+#include "WM_api.h"
 #include "WM_types.h"
 
-#include "text_intern.h"
+#include "ED_screen.h"
+#include "UI_interface.h"
+
+#include "text_intern.h"  /* own include */
+
+
+/* -------------------------------------------------------------------- */
+/* Public API */
 
 int text_do_suggest_select(SpaceText *st, ARegion *ar)
 {
@@ -51,7 +63,7 @@ int text_do_suggest_select(SpaceText *st, ARegion *ar)
 	int l, x, y, w, h, i;
 	int tgti, *top;
 	int mval[2] = {0, 0};
-	
+
 	if (!st || !st->text) return 0;
 	if (!texttool_text_is_active(st->text)) return 0;
 
@@ -68,7 +80,7 @@ int text_do_suggest_select(SpaceText *st, ARegion *ar)
 	if (l < 0) return 0;
 
 	text_update_character_width(st);
-	
+
 	if (st->showlinenrs) {
 		x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET + TEXTXLOC - 4;
 	}
@@ -119,10 +131,100 @@ void text_pop_suggest_list(void)
 		*top = i;
 }
 
+/* -------------------------------------------------------------------- */
+/* Private API */
+
+static void text_autocomplete_free(bContext *C, wmOperator *op);
+
+static GHash *text_autocomplete_build(Text *text)
+{
+	GHash *gh;
+	int seek_len = 0;
+	const char *seek;
+	texttool_text_clear();
+
+	texttool_text_set_active(text);
+
+	/* first get the word we're at */
+	{
+		int i = text->curc;
+		while (i--) {
+			if (!text_check_identifier(text->curl->line[i])) {
+				break;
+			}
+		}
+		i++;
+		seek_len = text->curc - i;
+		seek = text->curl->line + i;
+
+		// BLI_strncpy(seek, seek_ptr, seek_len);
+	}
+
+	/* now walk over entire doc and suggest words */
+	{
+		TextLine *linep;
+
+		gh = BLI_ghash_str_new(__func__);
+
+		for (linep = text->lines.first; linep; linep = linep->next) {
+			int i_start = 0;
+			int i_end = 0;
+
+			while (i_start < linep->len) {
+				/* seek identifier beginning */
+				while (i_start < linep->len && !text_check_identifier(linep->line[i_start])) {
+					i_start++;
+				}
+				i_end = i_start;
+				while (i_end < linep->len && text_check_identifier(linep->line[i_end])) {
+					i_end++;
+				}
+
+				if (i_start != i_end) {
+					char *str_sub = &linep->line[i_start];
+					const int choice_len = i_end - i_start;
+
+					if ((choice_len > seek_len) &&
+					    (seek_len == 0 || strncmp(seek, str_sub, seek_len) == 0) &&
+					    (seek != str_sub))
+					{
+						// printf("Adding: %s\n", s);
+						char str_sub_last = str_sub[choice_len];
+						str_sub[choice_len] = '\0';
+						if (!BLI_ghash_lookup(gh, str_sub)) {
+							char *str_dup = BLI_strdupn(str_sub, choice_len);
+							BLI_ghash_insert(gh, str_dup, str_dup);  /* A 'set' would make more sense here */
+						}
+						str_sub[choice_len] = str_sub_last;
+					}
+				}
+				i_start = i_end;
+			}
+		}
+
+		{
+			GHashIterator *iter = BLI_ghashIterator_new(gh);
+
+			for (; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) {
+				const char *s = BLI_ghashIterator_getValue(iter);
+				texttool_suggest_add(s, 'k');
+			}
+			BLI_ghashIterator_free(iter);
+
+		}
+	}
+
+	texttool_suggest_prefix(seek, seek_len);
+
+	return gh;
+}
+
+/* -- */
+
 static void get_suggest_prefix(Text *text, int offset)
 {
 	int i, len;
-	char *line;
+	char *line, tmp[256];
 
 	if (!text) return;
 	if (!texttool_text_is_active(text)) return;
@@ -133,7 +235,14 @@ static void get_suggest_prefix(Text *text, int offset)
 			break;
 	i++;
 	len = text->curc - i + offset;
-	texttool_suggest_prefix(line + i, len);
+	if (len > 255) {
+		printf("Suggestion prefix too long\n");
+		len = 255;
+	}
+	if (len != 0)
+		BLI_strncpy(tmp, line + i, len);
+	tmp[len] = '\0';
+	texttool_suggest_prefix(tmp, len);
 }
 
 static void confirm_suggestion(Text *text, int skipleft)
@@ -163,62 +272,79 @@ static void confirm_suggestion(Text *text, int skipleft)
 		txt_move_left(text, 1);
 
 	txt_insert_buf(text, sel->name);
-	
+
 	for (i = 0; i < skipleft; i++)
 		txt_move_right(text, 0);
 
 	texttool_text_clear();
 }
 
-// XXX
-#define LR_SHIFTKEY 0
-#define LR_ALTKEY 0
-#define LR_CTRLKEY 0
+/* -- */
+
+
+static int text_autocomplete_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+{
+	SpaceText *st = CTX_wm_space_text(C);
+	Text *text = CTX_data_edit_text(C);
+
+	st->doplugins = TRUE;
+	op->customdata = text_autocomplete_build(text);
+
+	if (texttool_suggest_first()) {
+
+		ED_area_tag_redraw(CTX_wm_area(C));
+
+		if (texttool_suggest_first() == texttool_suggest_last()) {
+			confirm_suggestion(st->text, 0);
+			text_update_line_edited(st->text->curl);
+			text_autocomplete_free(C, op);
+			return OPERATOR_FINISHED;
+		}
+		else {
+			WM_event_add_modal_handler(C, op);
+			return OPERATOR_RUNNING_MODAL;
+		}
+	}
+	else {
+		text_autocomplete_free(C, op);
+		return OPERATOR_CANCELLED;
+	}
+}
 
-// XXX
 static int doc_scroll = 0;
 
-static short UNUSED_FUNCTION(do_texttools) (SpaceText * st, char ascii, unsigned short evnt, short val)
+static int text_autocomplete_modal(bContext *C, wmOperator *op, wmEvent *event)
 {
-	ARegion *ar = NULL; // XXX
-	int qual = 0; // XXX
+	SpaceText *st = CTX_wm_space_text(C);
+	ScrArea *sa = CTX_wm_area(C);
+	ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+
 	int draw = 0, tools = 0, swallow = 0, scroll = 1;
-	if (!texttool_text_is_active(st->text)) return 0;
-	if (!st->text || st->text->id.lib) return 0;
+	Text *text = CTX_data_edit_text(C);
+	int retval = OPERATOR_RUNNING_MODAL;
+
+	(void)text;
 
 	if (st->doplugins && texttool_text_is_active(st->text)) {
 		if (texttool_suggest_first()) tools |= TOOL_SUGG_LIST;
 		if (texttool_docs_get()) tools |= TOOL_DOCUMENT;
 	}
 
-	if (ascii) {
-		if (tools & TOOL_SUGG_LIST) {
-			if ((ascii != '_' && ascii != '*' && ispunct(ascii)) || text_check_whitespace(ascii)) {
-				confirm_suggestion(st->text, 0);
-				text_update_line_edited(st->text->curl);
-			}
-			else if ((st->overwrite && txt_replace_char(st->text, ascii)) || txt_add_char(st->text, ascii)) {
-				get_suggest_prefix(st->text, 0);
-				text_pop_suggest_list();
-				swallow = 1;
-				draw = 1;
-			}
-		}
-		if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0, draw = 1;
-
-	}
-	else if (val == 1 && evnt) {
-		switch (evnt) {
-			case LEFTMOUSE:
+	switch (event->type) {
+		case LEFTMOUSE:
+			if (event->val == KM_PRESS) {
 				if (text_do_suggest_select(st, ar))
 					swallow = 1;
 				else {
 					if (tools & TOOL_SUGG_LIST) texttool_suggest_clear();
 					if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
+					retval = OPERATOR_FINISHED;
 				}
 				draw = 1;
-				break;
-			case MIDDLEMOUSE:
+			}
+			break;
+		case MIDDLEMOUSE:
+			if (event->val == KM_PRESS) {
 				if (text_do_suggest_select(st, ar)) {
 					confirm_suggestion(st->text, 0);
 					text_update_line_edited(st->text->curl);
@@ -227,16 +353,22 @@ static short UNUSED_FUNCTION(do_texttools) (SpaceText * st, char ascii, unsigned
 				else {
 					if (tools & TOOL_SUGG_LIST) texttool_suggest_clear();
 					if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
+					retval = OPERATOR_FINISHED;
 				}
 				draw = 1;
-				break;
-			case ESCKEY:
+			}
+			break;
+		case ESCKEY:
+			if (event->val == KM_PRESS) {
 				draw = swallow = 1;
 				if (tools & TOOL_SUGG_LIST) texttool_suggest_clear();
 				else if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
 				else draw = swallow = 0;
-				break;
-			case RETKEY:
+				retval = OPERATOR_CANCELLED;
+			}
+			break;
+		case RETKEY:
+			if (event->val == KM_PRESS) {
 				if (tools & TOOL_SUGG_LIST) {
 					confirm_suggestion(st->text, 0);
 					text_update_line_edited(st->text->curl);
@@ -244,12 +376,17 @@ static short UNUSED_FUNCTION(do_texttools) (SpaceText * st, char ascii, unsigned
 					draw = 1;
 				}
 				if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0, draw = 1;
-				break;
-			case LEFTARROWKEY:
-			case BACKSPACEKEY:
+				retval = OPERATOR_FINISHED;
+			}
+			break;
+		case LEFTARROWKEY:
+		case BACKSPACEKEY:
+			if (event->val == KM_PRESS) {
 				if (tools & TOOL_SUGG_LIST) {
-					if (qual)
+					if (event->ctrl) {
 						texttool_suggest_clear();
+						retval = OPERATOR_CANCELLED;
+					}
 					else {
 						/* Work out which char we are about to delete/pass */
 						if (st->text->curl && st->text->curc > 0) {
@@ -258,19 +395,27 @@ static short UNUSED_FUNCTION(do_texttools) (SpaceText * st, char ascii, unsigned
 								get_suggest_prefix(st->text, -1);
 								text_pop_suggest_list();
 							}
-							else
+							else {
 								texttool_suggest_clear();
+								retval = OPERATOR_CANCELLED;
+							}
 						}
-						else
+						else {
 							texttool_suggest_clear();
+							retval = OPERATOR_CANCELLED;
+						}
 					}
 				}
 				if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
-				break;
-			case RIGHTARROWKEY:
+			}
+			break;
+		case RIGHTARROWKEY:
+			if (event->val == KM_PRESS) {
 				if (tools & TOOL_SUGG_LIST) {
-					if (qual)
+					if (event->ctrl) {
 						texttool_suggest_clear();
+						retval = OPERATOR_CANCELLED;
+					}
 					else {
 						/* Work out which char we are about to pass */
 						if (st->text->curl && st->text->curc < st->text->curl->len) {
@@ -279,24 +424,29 @@ static short UNUSED_FUNCTION(do_texttools) (SpaceText * st, char ascii, unsigned
 								get_suggest_prefix(st->text, 1);
 								text_pop_suggest_list();
 							}
-							else
+							else {
 								texttool_suggest_clear();
+								retval = OPERATOR_CANCELLED;
+							}
 						}
-						else
+						else {
 							texttool_suggest_clear();
+							retval = OPERATOR_CANCELLED;
+						}
 					}
 				}
 				if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
-				break;
-			case PAGEDOWNKEY:
-				scroll = SUGG_LIST_SIZE - 1;
-			case WHEELDOWNMOUSE:
-			case DOWNARROWKEY:
+			}
+			break;
+		case PAGEDOWNKEY:
+			scroll = SUGG_LIST_SIZE - 1;
+		case WHEELDOWNMOUSE:
+		case DOWNARROWKEY:
+			if (event->val == KM_PRESS) {
 				if (tools & TOOL_DOCUMENT) {
 					doc_scroll++;
 					swallow = 1;
 					draw = 1;
-					break;
 				}
 				else if (tools & TOOL_SUGG_LIST) {
 					SuggItem *sel = texttool_suggest_selected();
@@ -312,17 +462,18 @@ static short UNUSED_FUNCTION(do_texttools) (SpaceText * st, char ascii, unsigned
 					text_pop_suggest_list();
 					swallow = 1;
 					draw = 1;
-					break;
 				}
-			case PAGEUPKEY:
-				scroll = SUGG_LIST_SIZE - 1;
-			case WHEELUPMOUSE:
-			case UPARROWKEY:
+			}
+			break;
+		case PAGEUPKEY:
+			scroll = SUGG_LIST_SIZE - 1;
+		case WHEELUPMOUSE:
+		case UPARROWKEY:
+			if (event->val == KM_PRESS) {
 				if (tools & TOOL_DOCUMENT) {
 					if (doc_scroll > 0) doc_scroll--;
 					swallow = 1;
 					draw = 1;
-					break;
 				}
 				else if (tools & TOOL_SUGG_LIST) {
 					SuggItem *sel = texttool_suggest_selected();
@@ -333,20 +484,74 @@ static short UNUSED_FUNCTION(do_texttools) (SpaceText * st, char ascii, unsigned
 					text_pop_suggest_list();
 					swallow = 1;
 					draw = 1;
-					break;
 				}
-			case RIGHTSHIFTKEY:
-			case LEFTSHIFTKEY:
-				break;
-			default:
-				if (tools & TOOL_SUGG_LIST) texttool_suggest_clear(), draw = 1;
-				if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0, draw = 1;
-		}
+			}
+			break;
+		case RIGHTSHIFTKEY:
+		case LEFTSHIFTKEY:
+			break;
+#if 0
+		default:
+			if (tools & TOOL_SUGG_LIST) texttool_suggest_clear(), draw = 1;
+			if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0, draw = 1;
+#endif
 	}
 
 	if (draw) {
-		// XXX redraw_alltext();
+		ED_area_tag_redraw(CTX_wm_area(C));
+	}
+
+//	if (swallow) {
+//		retval = OPERATOR_RUNNING_MODAL;
+//	}
+
+	if (texttool_suggest_first()) {
+		if (retval != OPERATOR_RUNNING_MODAL) {
+			text_autocomplete_free(C, op);
+		}
+		return retval;
+	}
+	else {
+		text_autocomplete_free(C, op);
+		return OPERATOR_FINISHED;
+	}
+}
+
+static void text_autocomplete_free(bContext *C, wmOperator *op)
+{
+	GHash *gh = op->customdata;
+	if (gh) {
+		BLI_ghash_free(gh, NULL, (GHashValFreeFP)MEM_freeN);
+		op->customdata = NULL;
 	}
 
-	return swallow;
+	/* other stuff */
+	{
+		SpaceText *st = CTX_wm_space_text(C);
+		st->doplugins = FALSE;
+		texttool_text_clear();
+	}
+}
+
+static int text_autocomplete_cancel(bContext *C, wmOperator *op)
+{
+	text_autocomplete_free(C, op);
+	return OPERATOR_CANCELLED;
+}
+
+void TEXT_OT_autocomplete(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name = "Text Auto Complete";
+	ot->description = "Show a list of used text in the open document";
+	ot->idname = "TEXT_OT_autocomplete";
+
+	/* api callbacks */
+	ot->invoke = text_autocomplete_invoke;
+	ot->cancel = text_autocomplete_cancel;
+	ot->modal = text_autocomplete_modal;
+	//ot->poll = ED_operator_view3d_active;
+
+	/* flags */
+	ot->flag = OPTYPE_BLOCKING;
 }
diff --git a/source/blender/editors/space_text/text_intern.h b/source/blender/editors/space_text/text_intern.h
index c7f9512737f..8fa74a5c866 100644
--- a/source/blender/editors/space_text/text_intern.h
+++ b/source/blender/editors/space_text/text_intern.h
@@ -143,6 +143,8 @@ void TEXT_OT_to_3d_object(struct wmOperatorType *ot);
 
 void TEXT_OT_resolve_conflict(struct wmOperatorType *ot);
 
+void TEXT_OT_autocomplete(struct wmOperatorType *ot);
+
 /* space_text.c */
 extern const char *text_context_dir[]; /* doc access */
 
-- 
cgit v1.2.3


From f1da6fe4dd0ecade4c06832ed2f7c6ef9dcae8d3 Mon Sep 17 00:00:00 2001
From: Sergey Sharybin 
Date: Mon, 31 Dec 2012 15:30:03 +0000
Subject: Fix for saving 8bit PNG images when there's no byte buffer in ImBuf

Misunderstand flag of file filter, should work fine now.
---
 source/blender/imbuf/intern/filetype.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/imbuf/intern/filetype.c b/source/blender/imbuf/intern/filetype.c
index 6d1f2abab0b..5c2dc0c7df9 100644
--- a/source/blender/imbuf/intern/filetype.c
+++ b/source/blender/imbuf/intern/filetype.c
@@ -69,7 +69,7 @@ void quicktime_exit(void);
 
 ImFileType IMB_FILE_TYPES[] = {
 	{NULL, NULL, imb_is_a_jpeg, imb_ftype_default, imb_load_jpeg, imb_savejpeg, NULL, 0, JPG, COLOR_ROLE_DEFAULT_BYTE},
-	{NULL, NULL, imb_is_a_png, imb_ftype_default, imb_loadpng, imb_savepng, NULL, IM_FTYPE_FLOAT, PNG, COLOR_ROLE_DEFAULT_BYTE},
+	{NULL, NULL, imb_is_a_png, imb_ftype_default, imb_loadpng, imb_savepng, NULL, 0, PNG, COLOR_ROLE_DEFAULT_BYTE},
 	{NULL, NULL, imb_is_a_bmp, imb_ftype_default, imb_bmp_decode, imb_savebmp, NULL, 0, BMP, COLOR_ROLE_DEFAULT_BYTE},
 	{NULL, NULL, imb_is_a_targa, imb_ftype_default, imb_loadtarga, imb_savetarga, NULL, 0, TGA, COLOR_ROLE_DEFAULT_BYTE},
 	{NULL, NULL, imb_is_a_iris, imb_ftype_iris, imb_loadiris, imb_saveiris, NULL, 0, IMAGIC, COLOR_ROLE_DEFAULT_BYTE},
-- 
cgit v1.2.3


From 281465a3118124ce77088c81d18015caade6171f Mon Sep 17 00:00:00 2001
From: Sergey Sharybin 
Date: Mon, 31 Dec 2012 15:45:31 +0000
Subject: Correction to RNA update functions

Either forgot to merge some local changes into trunk or merge happened wrong..
---
 source/blender/makesrna/intern/rna_image.c | 23 +++++++----------------
 1 file changed, 7 insertions(+), 16 deletions(-)

(limited to 'source')

diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c
index 11e33152375..5d37f67fa93 100644
--- a/source/blender/makesrna/intern/rna_image.c
+++ b/source/blender/makesrna/intern/rna_image.c
@@ -116,15 +116,6 @@ static void rna_Image_fields_update(Main *UNUSED(bmain), Scene *UNUSED(scene), P
 	BKE_image_release_ibuf(ima, ibuf, lock);
 }
 
-static void rna_Image_free_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
-{
-	Image *ima = ptr->id.data;
-	BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
-	WM_main_add_notifier(NC_IMAGE | NA_EDITED, &ima->id);
-	DAG_id_tag_update(&ima->id, 0);
-}
-
-
 static void rna_Image_reload_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
 {
 	Image *ima = ptr->id.data;
@@ -136,16 +127,16 @@ static void rna_Image_reload_update(Main *UNUSED(bmain), Scene *UNUSED(scene), P
 static void rna_Image_generated_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
 {
 	Image *ima = ptr->id.data;
-	BKE_image_signal(ima, NULL, IMA_SIGNAL_COLORMANAGE);
-	DAG_id_tag_update(&ima->id, 0);
-	WM_main_add_notifier(NC_IMAGE | ND_DISPLAY, &ima->id);
-	WM_main_add_notifier(NC_IMAGE | NA_EDITED, &ima->id);
+	BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
 }
 
 static void rna_Image_colormanage_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
 {
 	Image *ima = ptr->id.data;
-	BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
+	BKE_image_signal(ima, NULL, IMA_SIGNAL_COLORMANAGE);
+	DAG_id_tag_update(&ima->id, 0);
+	WM_main_add_notifier(NC_IMAGE | ND_DISPLAY, &ima->id);
+	WM_main_add_notifier(NC_IMAGE | NA_EDITED, &ima->id);
 }
 
 static void rna_ImageUser_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
@@ -535,7 +526,7 @@ static void rna_def_image(BlenderRNA *brna)
 	prop = RNA_def_property(srna, "use_alpha", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", IMA_IGNORE_ALPHA);
 	RNA_def_property_ui_text(prop, "Use Alpha", "Use the alpha channel information from the image or make image fully opaque");
-	RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_generated_update");
+	RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_colormanage_update");
 
 	prop = RNA_def_property(srna, "is_dirty", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_funcs(prop, "rna_Image_dirty_get", NULL);
@@ -688,7 +679,7 @@ static void rna_def_image(BlenderRNA *brna)
 	prop = RNA_def_property(srna, "alpha_mode", PROP_ENUM, PROP_NONE);
 	RNA_def_property_enum_items(prop, alpha_mode_items);
 	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_generated_update");
+	RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_colormanage_update");
 
 	RNA_api_image(srna);
 }
-- 
cgit v1.2.3


From f54b6eee45cf24450076d39c3fa3bd0d4e21f564 Mon Sep 17 00:00:00 2001
From: Bastien Montagne 
Date: Mon, 31 Dec 2012 15:54:44 +0000
Subject: More wrong "in degrees" busted out of tips!

---
 source/blender/makesrna/intern/rna_constraint.c | 6 +++---
 source/blender/makesrna/intern/rna_mesh.c       | 2 +-
 source/blender/makesrna/intern/rna_scene.c      | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

(limited to 'source')

diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index 84b7080ba9b..5a110802acd 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -1392,19 +1392,19 @@ static void rna_def_constraint_rigid_body_joint(BlenderRNA *brna)
 	prop = RNA_def_property(srna, "axis_x", PROP_FLOAT, PROP_ANGLE);
 	RNA_def_property_float_sdna(prop, NULL, "axX");
 	RNA_def_property_range(prop, -M_PI * 2, M_PI * 2);
-	RNA_def_property_ui_text(prop, "Axis X", "Rotate pivot on X axis in degrees");
+	RNA_def_property_ui_text(prop, "Axis X", "Rotate pivot on X axis");
 	RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
 
 	prop = RNA_def_property(srna, "axis_y", PROP_FLOAT, PROP_ANGLE);
 	RNA_def_property_float_sdna(prop, NULL, "axY");
 	RNA_def_property_range(prop, -M_PI * 2, M_PI * 2);
-	RNA_def_property_ui_text(prop, "Axis Y", "Rotate pivot on Y axis in degrees");
+	RNA_def_property_ui_text(prop, "Axis Y", "Rotate pivot on Y axis");
 	RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
 
 	prop = RNA_def_property(srna, "axis_z", PROP_FLOAT, PROP_ANGLE);
 	RNA_def_property_float_sdna(prop, NULL, "axZ");
 	RNA_def_property_range(prop, -M_PI * 2, M_PI * 2);
-	RNA_def_property_ui_text(prop, "Axis Z", "Rotate pivot on Z axis in degrees");
+	RNA_def_property_ui_text(prop, "Axis Z", "Rotate pivot on Z axis");
 	RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
 
 	prop = RNA_def_property(srna, "use_linked_collision", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index ae142708072..6f33f8c1db4 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -2930,7 +2930,7 @@ static void rna_def_mesh(BlenderRNA *brna)
 	prop = RNA_def_property(srna, "show_extra_face_angle", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAWEXTRA_FACEANG);
 	RNA_def_property_ui_text(prop, "Face Angles",
-	                         "Display the angles in the selected edges in degrees, "
+	                         "Display the angles in the selected edges, "
 	                         "using global values when set in the transform panel");
 	RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
 
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index b08e4731789..29d2d949fa2 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -2326,7 +2326,7 @@ static void rna_def_scene_game_recast_data(BlenderRNA *brna)
 	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_ui_text(prop, "Max Slope", "Maximum walkable slope angle in degrees");
+	RNA_def_property_ui_text(prop, "Max Slope", "Maximum walkable slope angle");
 	RNA_def_property_update(prop, NC_SCENE, NULL);
 
 
-- 
cgit v1.2.3


From dd62a2c3756d4335479a561a52468a548f2f1d65 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Mon, 31 Dec 2012 16:24:49 +0000
Subject: text autocomplete - make the popup box line up the X axis with the
 current word. - add poll function for the operator

---
 source/blender/blenkernel/BKE_text.h               |  1 +
 source/blender/blenkernel/intern/text.c            | 11 ++++++++++
 .../blender/editors/space_text/text_autocomplete.c | 10 ++-------
 source/blender/editors/space_text/text_draw.c      | 24 ++++++++++++++--------
 source/blender/editors/space_text/text_intern.h    |  3 +++
 source/blender/editors/space_text/text_ops.c       |  2 +-
 6 files changed, 34 insertions(+), 17 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h
index accac8694a9..1e3dd426efa 100644
--- a/source/blender/blenkernel/BKE_text.h
+++ b/source/blender/blenkernel/BKE_text.h
@@ -106,6 +106,7 @@ int text_check_delim(const char ch);
 int text_check_digit(const char ch);
 int text_check_identifier(const char ch);
 int text_check_whitespace(const char ch);
+int text_find_identifier_start(const char *str, int i);
 
 enum {
 	TXT_MOVE_LINE_UP   = -1,
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 322b77e0462..a9a9f6538d3 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -2936,3 +2936,14 @@ int text_check_whitespace(const char ch)
 		return 1;
 	return 0;
 }
+
+int text_find_identifier_start(const char *str, int i)
+{
+	while (i--) {
+		if (!text_check_identifier(str[i])) {
+			break;
+		}
+	}
+	i++;
+	return i;
+}
diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c
index 097174f2645..46e2f99d3fa 100644
--- a/source/blender/editors/space_text/text_autocomplete.c
+++ b/source/blender/editors/space_text/text_autocomplete.c
@@ -147,13 +147,7 @@ static GHash *text_autocomplete_build(Text *text)
 
 	/* first get the word we're at */
 	{
-		int i = text->curc;
-		while (i--) {
-			if (!text_check_identifier(text->curl->line[i])) {
-				break;
-			}
-		}
-		i++;
+		const int i = text_find_identifier_start(text->curl->line, text->curc);
 		seek_len = text->curc - i;
 		seek = text->curl->line + i;
 
@@ -550,7 +544,7 @@ void TEXT_OT_autocomplete(wmOperatorType *ot)
 	ot->invoke = text_autocomplete_invoke;
 	ot->cancel = text_autocomplete_cancel;
 	ot->modal = text_autocomplete_modal;
-	//ot->poll = ED_operator_view3d_active;
+	ot->poll = text_space_edit_poll;
 
 	/* flags */
 	ot->flag = OPTYPE_BLOCKING;
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index 6e33fc122b5..a26b4f56e02 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -958,8 +958,10 @@ static void draw_suggestion_list(SpaceText *st, ARegion *ar)
 	TextLine *tmp;
 	char str[SUGG_LIST_WIDTH + 1];
 	int w, boxw = 0, boxh, i, l, x, y, b, *top;
+	const int lheight = st->lheight_dpi + TXT_LINE_SPACING;
+	const int margin_x = 2;
 	
-	if (!st || !st->text) return;
+	if (!st->text) return;
 	if (!texttool_text_is_active(st->text)) return;
 
 	first = texttool_suggest_first();
@@ -981,14 +983,20 @@ static void draw_suggestion_list(SpaceText *st, ARegion *ar)
 	else {
 		x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET - 4;
 	}
-	y = ar->winy - (st->lheight_dpi + TXT_LINE_SPACING) * l - 2;
+	/* offset back so the start of the text lines up with the suggestions,
+	 * not essential but makes suggestions easier to follow */
+	x -= st->cwidth * (st->text->curc - text_find_identifier_start(st->text->curl->line, st->text->curc));
+	y = ar->winy - lheight * l - 2;
 
 	boxw = SUGG_LIST_WIDTH * st->cwidth + 20;
-	boxh = SUGG_LIST_SIZE * st->lheight_dpi + 8;
+	boxh = SUGG_LIST_SIZE * lheight + 8;
 	
+	/* not needed but stands out nicer */
+	uiDrawBoxShadow(220, x, y - boxh, x + boxw, y);
+
 	UI_ThemeColor(TH_SHADE1);
 	glRecti(x - 1, y + 1, x + boxw + 1, y - boxh - 1);
-	UI_ThemeColor(TH_BACK);
+	UI_ThemeColorShade(TH_BACK, 16);
 	glRecti(x, y, x + boxw, y - boxh);
 
 	/* Set the top 'item' of the visible list */
@@ -996,7 +1004,7 @@ static void draw_suggestion_list(SpaceText *st, ARegion *ar)
 
 	for (i = 0; i < SUGG_LIST_SIZE && item; i++, item = item->next) {
 
-		y -= st->lheight_dpi;
+		y -= lheight;
 
 		BLI_strncpy(str, item->name, SUGG_LIST_WIDTH);
 
@@ -1004,7 +1012,7 @@ static void draw_suggestion_list(SpaceText *st, ARegion *ar)
 		
 		if (item == sel) {
 			UI_ThemeColor(TH_SHADE2);
-			glRecti(x + 16, y - 3, x + 16 + w, y + st->lheight_dpi - 3);
+			glRecti(x + margin_x, y - 3, x + margin_x + w, y + lheight - 3);
 		}
 		b = 1; /* b=1 color block, text is default. b=0 no block, color text */
 		switch (item->type) {
@@ -1018,7 +1026,7 @@ static void draw_suggestion_list(SpaceText *st, ARegion *ar)
 			glRecti(x + 8, y + 2, x + 11, y + 5);
 			UI_ThemeColor(TH_TEXT);
 		}
-		text_draw(st, str, 0, 0, 1, x + 16, y - 1, NULL);
+		text_draw(st, str, 0, 0, 1, x + margin_x, y - 1, NULL);
 
 		if (item == last) break;
 	}
@@ -1031,7 +1039,7 @@ static void draw_cursor(SpaceText *st, ARegion *ar)
 	Text *text = st->text;
 	int vcurl, vcurc, vsell, vselc, hidden = 0;
 	int x, y, w, i;
-	int lheight = st->lheight_dpi + TXT_LINE_SPACING;
+	const int lheight = st->lheight_dpi + TXT_LINE_SPACING;
 
 	/* Draw the selection */
 	if (text->curl != text->sell || text->curc != text->selc) {
diff --git a/source/blender/editors/space_text/text_intern.h b/source/blender/editors/space_text/text_intern.h
index 8fa74a5c866..799bc49b624 100644
--- a/source/blender/editors/space_text/text_intern.h
+++ b/source/blender/editors/space_text/text_intern.h
@@ -143,6 +143,9 @@ void TEXT_OT_to_3d_object(struct wmOperatorType *ot);
 
 void TEXT_OT_resolve_conflict(struct wmOperatorType *ot);
 
+int text_space_edit_poll(struct bContext *C);
+
+/* text_autocomplete.c */
 void TEXT_OT_autocomplete(struct wmOperatorType *ot);
 
 /* space_text.c */
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index 01041c0e385..89cc396efbb 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -98,7 +98,7 @@ static int text_edit_poll(bContext *C)
 	return 1;
 }
 
-static int text_space_edit_poll(bContext *C)
+int text_space_edit_poll(bContext *C)
 {
 	SpaceText *st = CTX_wm_space_text(C);
 	Text *text = CTX_data_edit_text(C);
-- 
cgit v1.2.3


From d191dec1d5a938c0d7d2950f5140a4811627602e Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Mon, 31 Dec 2012 16:40:14 +0000
Subject: syntax highlight autocomplete listing.

---
 source/blender/editors/space_text/text_autocomplete.c |  7 ++++++-
 source/blender/editors/space_text/text_draw.c         | 16 +++-------------
 source/blender/editors/space_text/text_format.h       |  2 ++
 source/blender/editors/space_text/text_format_osl.c   | 15 ++++++++++++++-
 source/blender/editors/space_text/text_format_py.c    | 14 +++++++++++++-
 5 files changed, 38 insertions(+), 16 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c
index 46e2f99d3fa..31f6d92988c 100644
--- a/source/blender/editors/space_text/text_autocomplete.c
+++ b/source/blender/editors/space_text/text_autocomplete.c
@@ -50,6 +50,7 @@
 #include "ED_screen.h"
 #include "UI_interface.h"
 
+#include "text_format.h"
 #include "text_intern.h"  /* own include */
 
 
@@ -199,9 +200,13 @@ static GHash *text_autocomplete_build(Text *text)
 		{
 			GHashIterator *iter = BLI_ghashIterator_new(gh);
 
+			/* get the formatter for highlighting */
+			TextFormatType *tft;
+			tft = ED_text_format_get(text);
+
 			for (; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) {
 				const char *s = BLI_ghashIterator_getValue(iter);
-				texttool_suggest_add(s, 'k');
+				texttool_suggest_add(s, tft->format_identifier(s));
 			}
 			BLI_ghashIterator_free(iter);
 
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index a26b4f56e02..c264368e714 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -957,7 +957,7 @@ static void draw_suggestion_list(SpaceText *st, ARegion *ar)
 	SuggItem *item, *first, *last, *sel;
 	TextLine *tmp;
 	char str[SUGG_LIST_WIDTH + 1];
-	int w, boxw = 0, boxh, i, l, x, y, b, *top;
+	int w, boxw = 0, boxh, i, l, x, y, *top;
 	const int lheight = st->lheight_dpi + TXT_LINE_SPACING;
 	const int margin_x = 2;
 	
@@ -1014,18 +1014,8 @@ static void draw_suggestion_list(SpaceText *st, ARegion *ar)
 			UI_ThemeColor(TH_SHADE2);
 			glRecti(x + margin_x, y - 3, x + margin_x + w, y + lheight - 3);
 		}
-		b = 1; /* b=1 color block, text is default. b=0 no block, color text */
-		switch (item->type) {
-			case 'k': UI_ThemeColor(TH_SYNTAX_B); b = 0; break;
-			case 'm': UI_ThemeColor(TH_TEXT); break;
-			case 'f': UI_ThemeColor(TH_SYNTAX_L); break;
-			case 'v': UI_ThemeColor(TH_SYNTAX_N); break;
-			case '?': UI_ThemeColor(TH_TEXT); b = 0; break;
-		}
-		if (b) {
-			glRecti(x + 8, y + 2, x + 11, y + 5);
-			UI_ThemeColor(TH_TEXT);
-		}
+
+		format_draw_color(item->type);
 		text_draw(st, str, 0, 0, 1, x + margin_x, y - 1, NULL);
 
 		if (item == last) break;
diff --git a/source/blender/editors/space_text/text_format.h b/source/blender/editors/space_text/text_format.h
index 99cd20149cf..e593e41d42c 100644
--- a/source/blender/editors/space_text/text_format.h
+++ b/source/blender/editors/space_text/text_format.h
@@ -66,6 +66,8 @@ int  text_check_format_len(TextLine *line, unsigned int len);
 typedef struct TextFormatType {
 	struct TextFormatType *next, *prev;
 
+	char (*format_identifier)(const char *string);
+
 	/* Formats the specified line. If do_next is set, the process will move on to
 	 * the succeeding line if it is affected (eg. multiline strings). Format strings
 	 * may contain any of the following characters:
diff --git a/source/blender/editors/space_text/text_format_osl.c b/source/blender/editors/space_text/text_format_osl.c
index f313e9a5f2a..3120e88163e 100644
--- a/source/blender/editors/space_text/text_format_osl.c
+++ b/source/blender/editors/space_text/text_format_osl.c
@@ -170,6 +170,17 @@ static int txtfmt_osl_find_preprocessor(const char *string)
 	return -1;
 }
 
+static char txtfmt_osl_format_identifier(const char *str)
+{
+	char fmt;
+	if      ((txtfmt_osl_find_specialvar(str))   != -1) fmt = FMT_TYPE_SPECIAL;
+	else if ((txtfmt_osl_find_builtinfunc(str))  != -1) fmt = FMT_TYPE_KEYWORD;
+	else if ((txtfmt_osl_find_reserved(str))     != -1) fmt = FMT_TYPE_RESERVED;
+	else if ((txtfmt_osl_find_preprocessor(str)) != -1) fmt = FMT_TYPE_DIRECTIVE;
+	else                                                fmt = FMT_TYPE_DEFAULT;
+	return fmt;
+}
+
 static void txtfmt_osl_format_line(SpaceText *st, TextLine *line, const int do_next)
 {
 	FlattenString fs;
@@ -280,6 +291,7 @@ static void txtfmt_osl_format_line(SpaceText *st, TextLine *line, const int do_n
 			/* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
 			else {
 				/* Special vars(v) or built-in keywords(b) */
+				/* keep in sync with 'txtfmt_osl_format_identifier()' */
 				if      ((i = txtfmt_osl_find_specialvar(str))   != -1) prev = FMT_TYPE_SPECIAL;
 				else if ((i = txtfmt_osl_find_builtinfunc(str))  != -1) prev = FMT_TYPE_KEYWORD;
 				else if ((i = txtfmt_osl_find_reserved(str))     != -1) prev = FMT_TYPE_RESERVED;
@@ -315,7 +327,8 @@ void ED_text_format_register_osl(void)
 	static TextFormatType tft = {0};
 	static const char *ext[] = {"osl", NULL};
 
-	tft.format_line = txtfmt_osl_format_line;
+	tft.format_identifier = txtfmt_osl_format_identifier;
+	tft.format_line       = txtfmt_osl_format_line;
 	tft.ext = ext;
 
 	ED_text_format_register(&tft);
diff --git a/source/blender/editors/space_text/text_format_py.c b/source/blender/editors/space_text/text_format_py.c
index d68d6ae0e78..cbccc6a770f 100644
--- a/source/blender/editors/space_text/text_format_py.c
+++ b/source/blender/editors/space_text/text_format_py.c
@@ -154,6 +154,16 @@ static int txtfmt_py_find_bool(const char *string)
 	return i;
 }
 
+static char txtfmt_py_format_identifier(const char *str)
+{
+	char fmt;
+	if      ((txtfmt_py_find_specialvar(str))   != -1) fmt = FMT_TYPE_SPECIAL;
+	else if ((txtfmt_py_find_builtinfunc(str))  != -1) fmt = FMT_TYPE_KEYWORD;
+	else if ((txtfmt_py_find_decorator(str))    != -1) fmt = FMT_TYPE_RESERVED;
+	else                                               fmt = FMT_TYPE_DEFAULT;
+	return fmt;
+}
+
 static void txtfmt_py_format_line(SpaceText *st, TextLine *line, const int do_next)
 {
 	FlattenString fs;
@@ -269,6 +279,7 @@ static void txtfmt_py_format_line(SpaceText *st, TextLine *line, const int do_ne
 			/* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
 			else {
 				/* Special vars(v) or built-in keywords(b) */
+				/* keep in sync with 'txtfmt_py_format_identifier()' */
 				if      ((i = txtfmt_py_find_specialvar(str))   != -1) prev = FMT_TYPE_SPECIAL;
 				else if ((i = txtfmt_py_find_builtinfunc(str))  != -1) prev = FMT_TYPE_KEYWORD;
 				else if ((i = txtfmt_py_find_decorator(str))    != -1) prev = FMT_TYPE_DIRECTIVE;
@@ -303,7 +314,8 @@ void ED_text_format_register_py(void)
 	static TextFormatType tft = {0};
 	static const char *ext[] = {"py", NULL};
 
-	tft.format_line = txtfmt_py_format_line;
+	tft.format_identifier = txtfmt_py_format_identifier;
+	tft.format_line       = txtfmt_py_format_line;
 	tft.ext = ext;
 
 	ED_text_format_register(&tft);
-- 
cgit v1.2.3


From 9d9542561c5565c8bfdb89814136001416c8a522 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Mon, 31 Dec 2012 17:19:55 +0000
Subject: code cleanup: autocomplete functions

---
 source/blender/blenkernel/intern/text.c            |  4 ++
 .../blender/editors/space_text/text_autocomplete.c | 43 +++++++---------------
 2 files changed, 18 insertions(+), 29 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index a9a9f6538d3..c337e339ebf 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -2939,6 +2939,10 @@ int text_check_whitespace(const char ch)
 
 int text_find_identifier_start(const char *str, int i)
 {
+	if (UNLIKELY(i <= 0)) {
+		return 0;
+	}
+
 	while (i--) {
 		if (!text_check_identifier(str[i])) {
 			break;
diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c
index 31f6d92988c..e406a1b7166 100644
--- a/source/blender/editors/space_text/text_autocomplete.c
+++ b/source/blender/editors/space_text/text_autocomplete.c
@@ -223,32 +223,22 @@ static GHash *text_autocomplete_build(Text *text)
 static void get_suggest_prefix(Text *text, int offset)
 {
 	int i, len;
-	char *line, tmp[256];
+	char *line;
 
 	if (!text) return;
 	if (!texttool_text_is_active(text)) return;
 
 	line = text->curl->line;
-	for (i = text->curc - 1 + offset; i >= 0; i--)
-		if (!text_check_identifier(line[i]))
-			break;
-	i++;
+	i = text_find_identifier_start(line, text->curc + offset);
 	len = text->curc - i + offset;
-	if (len > 255) {
-		printf("Suggestion prefix too long\n");
-		len = 255;
-	}
-	if (len != 0)
-		BLI_strncpy(tmp, line + i, len);
-	tmp[len] = '\0';
-	texttool_suggest_prefix(tmp, len);
+	texttool_suggest_prefix(line + i, len);
 }
 
-static void confirm_suggestion(Text *text, int skipleft)
+static void confirm_suggestion(Text *text)
 {
 	SuggItem *sel;
 	int i, over = 0;
-	char *line;
+	const char *line;
 
 	if (!text) return;
 	if (!texttool_text_is_active(text)) return;
@@ -257,23 +247,18 @@ static void confirm_suggestion(Text *text, int skipleft)
 	if (!sel) return;
 
 	line = text->curl->line;
-	i = text->curc - skipleft - 1;
-	while (i >= 0) {
-		if (!text_check_identifier(line[i]))
-			break;
-		over++;
-		i--;
-	}
+	i = text_find_identifier_start(line, text->curc /* - skipleft */);
+	over = text->curc - i;
 
-	for (i = 0; i < skipleft; i++)
-		txt_move_left(text, 0);
+//	for (i = 0; i < skipleft; i++)
+//		txt_move_left(text, 0);
 	for (i = 0; i < over; i++)
 		txt_move_left(text, 1);
 
 	txt_insert_buf(text, sel->name);
 
-	for (i = 0; i < skipleft; i++)
-		txt_move_right(text, 0);
+//	for (i = 0; i < skipleft; i++)
+//		txt_move_right(text, 0);
 
 	texttool_text_clear();
 }
@@ -294,7 +279,7 @@ static int text_autocomplete_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED
 		ED_area_tag_redraw(CTX_wm_area(C));
 
 		if (texttool_suggest_first() == texttool_suggest_last()) {
-			confirm_suggestion(st->text, 0);
+			confirm_suggestion(st->text);
 			text_update_line_edited(st->text->curl);
 			text_autocomplete_free(C, op);
 			return OPERATOR_FINISHED;
@@ -345,7 +330,7 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, wmEvent *event)
 		case MIDDLEMOUSE:
 			if (event->val == KM_PRESS) {
 				if (text_do_suggest_select(st, ar)) {
-					confirm_suggestion(st->text, 0);
+					confirm_suggestion(st->text);
 					text_update_line_edited(st->text->curl);
 					swallow = 1;
 				}
@@ -369,7 +354,7 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, wmEvent *event)
 		case RETKEY:
 			if (event->val == KM_PRESS) {
 				if (tools & TOOL_SUGG_LIST) {
-					confirm_suggestion(st->text, 0);
+					confirm_suggestion(st->text);
 					text_update_line_edited(st->text->curl);
 					swallow = 1;
 					draw = 1;
-- 
cgit v1.2.3


From 5ce8409be6fbebc61086969602af00cf26321ab7 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Mon, 31 Dec 2012 17:39:01 +0000
Subject: code cleanup: name event -> event_type in macros, since this is from
 event->type

---
 source/blender/windowmanager/wm_event_types.h | 29 +++++++++++++++------------
 1 file changed, 16 insertions(+), 13 deletions(-)

(limited to 'source')

diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h
index c90bbaf8d6c..78a67a31e0f 100644
--- a/source/blender/windowmanager/wm_event_types.h
+++ b/source/blender/windowmanager/wm_event_types.h
@@ -53,6 +53,9 @@
 #define MOUSEX		4
 #define MOUSEY		5
 
+
+/* *** wmEvent.type *** */
+
 /* non-event, for example disabled timer */
 #define EVENT_NONE		0
 /* MOUSE : 0x00x */
@@ -154,8 +157,7 @@ enum {
 #define TIMERF			0x011F	/* last timer */
 
 /* test whether the event is timer event */
-#define ISTIMER(event)	(event >= TIMER && event <= TIMERF)
-
+#define ISTIMER(event_type)	(event_type >= TIMER && event_type <= TIMERF)
 
 /* standard keyboard */
 #define AKEY		'a'
@@ -289,29 +291,30 @@ enum {
 /* for event checks */
 	/* only used for KM_TEXTINPUT, so assume that we want all user-inputtable ascii codes included */
 	/* UNUSED - see wm_eventmatch - BUG [#30479] */
-// #define ISTEXTINPUT(event)  (event >= ' ' && event <= 255)
+// #define ISTEXTINPUT(event_type)  (event_type >= ' ' && event_type <= 255)
+/* note, an alternative could be to check 'event->utf8_buf' */
 
 	/* test whether the event is a key on the keyboard */
-#define ISKEYBOARD(event)  (event >= ' ' && event <= 320)
+#define ISKEYBOARD(event_type)  (event_type >= ' ' && event_type <= 320)
 
 	/* test whether the event is a modifier key */
-#define ISKEYMODIFIER(event)  ((event >= LEFTCTRLKEY && event <= LEFTSHIFTKEY) || event == OSKEY)
+#define ISKEYMODIFIER(event_type)  ((event_type >= LEFTCTRLKEY && event_type <= LEFTSHIFTKEY) || event_type == OSKEY)
 
 	/* test whether the event is a mouse button */
-#define ISMOUSE(event)  (event >= LEFTMOUSE && event <= MOUSEROTATE)
+#define ISMOUSE(event_type)  (event_type >= LEFTMOUSE && event_type <= MOUSEROTATE)
 
 	/* test whether the event is tweak event */
-#define ISTWEAK(event)  (event >= EVT_TWEAK_L && event <= EVT_GESTURE)
+#define ISTWEAK(event_type)  (event_type >= EVT_TWEAK_L && event_type <= EVT_GESTURE)
 
 	/* test whether the event is a NDOF event */
-#define ISNDOF(event)  (event >= NDOF_MOTION && event < NDOF_LAST)
+#define ISNDOF(event_type)  (event_type >= NDOF_MOTION && event_type < NDOF_LAST)
 
 /* test whether event type is acceptable as hotkey, excluding modifiers */
-#define ISHOTKEY(event)                                           \
-	((ISKEYBOARD(event) || ISMOUSE(event) || ISNDOF(event)) &&    \
-	 (event != ESCKEY) &&                                         \
-	 (event >= LEFTCTRLKEY && event <= LEFTSHIFTKEY) == FALSE &&  \
-	 (event >= UNKNOWNKEY  && event <= GRLESSKEY) == FALSE)
+#define ISHOTKEY(event_type)                                                  \
+	((ISKEYBOARD(event_type) || ISMOUSE(event_type) || ISNDOF(event_type)) && \
+	 (event_type != ESCKEY) &&                                                \
+	 (event_type >= LEFTCTRLKEY && event_type <= LEFTSHIFTKEY) == FALSE &&    \
+	 (event_type >= UNKNOWNKEY  && event_type <= GRLESSKEY) == FALSE)
 
 /* **************** BLENDER GESTURE EVENTS (0x5000) **************** */
 
-- 
cgit v1.2.3


From 2787c78175eb7f12e48afe65098779444ff83720 Mon Sep 17 00:00:00 2001
From: Antony Riakiotakis 
Date: Mon, 31 Dec 2012 19:38:40 +0000
Subject: smart stitching: * Some code cleanup * Bugfix: rotation of uv islands
 during stitch on images with aspect ratio was different for different island
 rotations. I needed to correct normal and tangent calculation to take image
 aspect into account.

---
 .../blender/editors/uvedit/uvedit_smart_stitch.c   | 58 ++++++++++++----------
 1 file changed, 32 insertions(+), 26 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c
index 96e43dafa2f..dc9f5fbf97c 100644
--- a/source/blender/editors/uvedit/uvedit_smart_stitch.c
+++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c
@@ -468,15 +468,12 @@ static void stitch_island_calculate_edge_rotation(UvEdge *edge, StitchState *sta
 	int index1, index2;
 	float rotation;
 	MLoopUV *luv1, *luv2;
-	BMLoop *l1, *l2;
 
 	element1 = state->uvs[edge->uv1];
 	element2 = state->uvs[edge->uv2];
 
-	l1 = element1->l;
-	luv1 = CustomData_bmesh_get(&state->em->bm->ldata, l1->head.data, CD_MLOOPUV);
-	l2 = element2->l;
-	luv2 = CustomData_bmesh_get(&state->em->bm->ldata, l2->head.data, CD_MLOOPUV);
+	luv1 = CustomData_bmesh_get(&state->em->bm->ldata, element1->l->head.data, CD_MLOOPUV);
+	luv2 = CustomData_bmesh_get(&state->em->bm->ldata, element2->l->head.data, CD_MLOOPUV);
 
 	if (state->mode == STITCH_VERT) {
 		index1 = uvfinal_map[element1 - state->element_map->buf];
@@ -491,14 +488,18 @@ static void stitch_island_calculate_edge_rotation(UvEdge *edge, StitchState *sta
 	uv1[0] = luv2->uv[0] - luv1->uv[0];
 	uv1[1] = luv2->uv[1] - luv1->uv[1];
 
+	uv1[1] /= state->aspect;
+
 	uv2[0] = uv_average[index2].uv[0] - uv_average[index1].uv[0];
 	uv2[1] = uv_average[index2].uv[1] - uv_average[index1].uv[1];
 
+	uv2[1] /= state->aspect;
+
 	normalize_v2(uv1);
 	normalize_v2(uv2);
 
-	edgecos = uv1[0] * uv2[0] + uv1[1] * uv2[1];
-	edgesin = uv1[0] * uv2[1] - uv2[0] * uv1[1];
+	edgecos = dot_v2v2(uv1, uv2);
+	edgesin = cross_v2v2(uv1, uv2);
 
 	rotation = (edgesin > 0.0f) ?
 	            +acosf(max_ff(-1.0f, min_ff(1.0f, edgecos))) :
@@ -543,7 +544,9 @@ static void stitch_island_calculate_vert_rotation(UvElement *element, StitchStat
 			negate_v2_v2(normal, state->normals + index_tmp2 * 2);
 			edgecos = dot_v2v2(normal, state->normals + index_tmp1 * 2);
 			edgesin = cross_v2v2(normal, state->normals + index_tmp1 * 2);
-			rotation += (edgesin > 0.0f) ? acosf(edgecos) : -acosf(edgecos);
+			rotation += (edgesin > 0.0f) ?
+				+acosf(max_ff(-1.0f, min_ff(1.0f, edgecos))) :
+	            -acosf(max_ff(-1.0f, min_ff(1.0f, edgecos)));
 		}
 	}
 
@@ -844,13 +847,13 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
 	int previous_island = state->static_island;
 	BMFace *efa;
 	BMIter iter;
-	UVVertAverage *final_position;
+	UVVertAverage *final_position = NULL;
 
 	char stitch_midpoints = state->midpoints;
 	/* used to map uv indices to uvaverage indices for selection */
-	unsigned int *uvfinal_map;
+	unsigned int *uvfinal_map = NULL;
 	/* per face preview position in preview buffer */
-	PreviewPosition *preview_position;
+	PreviewPosition *preview_position = NULL;
 
 	/* cleanup previous preview */
 	stitch_preview_delete(state->stitch_preview);
@@ -1429,18 +1432,19 @@ static void stitch_switch_selection_mode(StitchState *state)
 	MEM_freeN(old_selection_stack);
 }
 
-static void stitch_calculate_edge_normal(BMEditMesh *em, UvEdge *edge, float *normal)
+static void stitch_calculate_edge_normal(BMEditMesh *em, UvEdge *edge, float *normal, float aspect)
 {
 	BMLoop *l1 = edge->element->l;
-	BMLoop *l2 = l1->next;
 	MLoopUV *luv1, *luv2;
 	float tangent[2];
 
 	luv1 = CustomData_bmesh_get(&em->bm->ldata, l1->head.data, CD_MLOOPUV);
-	luv2 = CustomData_bmesh_get(&em->bm->ldata, l2->head.data, CD_MLOOPUV);
+	luv2 = CustomData_bmesh_get(&em->bm->ldata, l1->next->head.data, CD_MLOOPUV);
 
 	sub_v2_v2v2(tangent, luv2->uv,  luv1->uv);
 
+	tangent[1] /= aspect;
+
 	normal[0] = tangent[1];
 	normal[1] = -tangent[0];
 
@@ -1457,6 +1461,8 @@ static void stitch_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void *ar
 	glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
 	glEnableClientState(GL_VERTEX_ARRAY);
 
+	glPointSize(pointsize * 2.0f);
+
 	glEnable(GL_BLEND);
 
 	UI_ThemeColor4(TH_STITCH_PREVIEW_ACTIVE);
@@ -1472,19 +1478,18 @@ static void stitch_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void *ar
 		glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
 		UI_ThemeColor4(TH_STITCH_PREVIEW_EDGE);
 		glDrawArrays(GL_POLYGON, index, stitch_preview->uvs_per_polygon[i]);
+		#if 0
+		glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
+		UI_ThemeColor4(TH_STITCH_PREVIEW_VERT);
+		glDrawArrays(GL_POLYGON, index, stitch_preview->uvs_per_polygon[i]);
+		#endif
 
 		index += stitch_preview->uvs_per_polygon[i];
 	}
-	glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
-#if 0
-	UI_ThemeColor4(TH_STITCH_PREVIEW_VERT);
-	glDrawArrays(GL_TRIANGLES, 0, stitch_preview->num_tris * 3);
-#endif
 	glDisable(GL_BLEND);
 
 	/* draw vert preview */
 	if (state->mode == STITCH_VERT) {
-		glPointSize(pointsize * 2.0f);
 		UI_ThemeColor4(TH_STITCH_PREVIEW_STITCHABLE);
 		glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_stitchable);
 		glDrawArrays(GL_POINTS, 0, stitch_preview->num_stitchable);
@@ -1733,15 +1738,16 @@ static int stitch_init(bContext *C, wmOperator *op)
 	 * the winding of the polygon (assuming counter-clockwise flow). */
 
 	for (i = 0; i < total_edges; i++) {
+		UvEdge *edge = edges + i;
 		float normal[2];
-		if (edges[i].flag & STITCH_BOUNDARY) {
-			stitch_calculate_edge_normal(em, edges + i, normal);
+		if (edge->flag & STITCH_BOUNDARY) {
+			stitch_calculate_edge_normal(em, edge, normal, state->aspect);
 
-			add_v2_v2(state->normals + edges[i].uv1 * 2, normal);
-			add_v2_v2(state->normals + edges[i].uv2 * 2, normal);
+			add_v2_v2(state->normals + edge->uv1 * 2, normal);
+			add_v2_v2(state->normals + edge->uv2 * 2, normal);
 
-			normalize_v2(state->normals + edges[i].uv1 * 2);
-			normalize_v2(state->normals + edges[i].uv2 * 2);
+			normalize_v2(state->normals + edge->uv1 * 2);
+			normalize_v2(state->normals + edge->uv2 * 2);
 		}
 	}
 
-- 
cgit v1.2.3


From d0981c279b9705e076045c7af7faf6e90937cd96 Mon Sep 17 00:00:00 2001
From: Mitchell Stokes 
Date: Mon, 31 Dec 2012 21:32:46 +0000
Subject: BGE: Fixing a crash that occurred when LibLoading a scene with a 2D
 Filter Actuator. The actuator was still referencing the old scene.

---
 source/gameengine/GameLogic/SCA_2DFilterActuator.cpp | 5 +++++
 source/gameengine/GameLogic/SCA_2DFilterActuator.h   | 2 ++
 source/gameengine/Ketsji/KX_Scene.cpp                | 6 ++++++
 3 files changed, 13 insertions(+)

(limited to 'source')

diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp
index 5ad5aedbd39..6a87d3ccb98 100644
--- a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp
+++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp
@@ -97,6 +97,11 @@ bool SCA_2DFilterActuator::Update()
 }
 
 
+void SCA_2DFilterActuator::SetScene(SCA_IScene *scene)
+{
+	m_scene = scene;
+}
+
 void SCA_2DFilterActuator::SetShaderText(const char *text)
 {
 	m_shaderText = text;
diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.h b/source/gameengine/GameLogic/SCA_2DFilterActuator.h
index a754d950859..4635a8ad9f8 100644
--- a/source/gameengine/GameLogic/SCA_2DFilterActuator.h
+++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.h
@@ -64,6 +64,8 @@ public:
 	virtual ~SCA_2DFilterActuator();
 	virtual bool Update();
 
+	void	SetScene(SCA_IScene *scene);
+
 	virtual CValue* GetReplica();
 };
 #endif
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index 9483b864d52..55c9ff5307f 100644
--- a/source/gameengine/Ketsji/KX_Scene.cpp
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -47,6 +47,7 @@
 //#include "SCA_AlwaysEventManager.h"
 //#include "SCA_RandomEventManager.h"
 //#include "KX_RayEventManager.h"
+#include "SCA_2DFilterActuator.h"
 #include "KX_TouchEventManager.h"
 #include "SCA_KeyboardManager.h"
 #include "SCA_MouseManager.h"
@@ -1781,6 +1782,11 @@ static void MergeScene_LogicBrick(SCA_ILogicBrick* brick, KX_Scene *to)
 	if (sensor) {
 		sensor->Replace_EventManager(logicmgr);
 	}
+
+	SCA_2DFilterActuator *filter_actuator = dynamic_cast(brick);
+	if (filter_actuator) {
+		filter_actuator->SetScene(to);
+	}
 }
 
 #ifdef USE_BULLET
-- 
cgit v1.2.3


From ccf27a3c346335cc0146a034239df9208a6859e0 Mon Sep 17 00:00:00 2001
From: Antony Riakiotakis 
Date: Tue, 1 Jan 2013 11:08:05 +0000
Subject: Fix: weight painting operated only for selected vertices in edit
 mode. We only need this in case vertex selection is enabled.

---
 source/blender/editors/sculpt_paint/paint_vertex.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 6a61a6c45dc..819305f9508 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -2342,7 +2342,7 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
 		unsigned int       i;
 
 		for (i = 0; i < totvert; i++) {
-			me->dvert[i].flag = (me->mvert[i].flag & SELECT);
+			me->dvert[i].flag = use_vert_sel ? (me->mvert[i].flag & SELECT) : SELECT;
 		}
 
 		if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
-- 
cgit v1.2.3


From e4f65749f9c522476f646004c06556b0fc5c4b4d Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Tue, 1 Jan 2013 11:47:47 +0000
Subject: remove vertex selection check for weight paint mode so you can paint
 `through` the mesh.

also made the wire draw without depth masking when the depth check is off, similar to mesh editmode drawing, nice hint about whats going on.
---
 source/blender/editors/sculpt_paint/paint_vertex.c | 10 +++++-----
 source/blender/editors/space_view3d/drawmesh.c     | 20 ++++++++++++++++----
 2 files changed, 21 insertions(+), 9 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 819305f9508..15d5257af60 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -2194,7 +2194,7 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
 	float alpha;
 	float mval[2];
 	int use_vert_sel;
-	int use_zbuf;
+	int use_depth;
 
 	MDeformWeight *(*dw_func)(MDeformVert *, const int) =
 	        (brush->vertexpaint_tool == PAINT_BLEND_BLUR) ?
@@ -2258,10 +2258,10 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
 	swap_m4m4(wpd->vc.rv3d->persmat, mat);
 
 	use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
-	use_zbuf = use_vert_sel && (vc->v3d->flag & V3D_ZBUF_SELECT);
+	use_depth = (vc->v3d->flag & V3D_ZBUF_SELECT);
 
 	/* which faces are involved */
-	if (use_zbuf) {
+	if (use_depth) {
 		if (wp->flag & VP_AREA) {
 			/* Ugly hack, to avoid drawing vertex index when getting the face index buffer - campbell */
 			me->editflag &= ~ME_EDIT_PAINT_VERT_SEL;
@@ -2310,7 +2310,7 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
 	} (void)0
 
 
-	if (use_zbuf) {
+	if (use_depth) {
 		for (index = 0; index < totindex; index++) {
 			if (indexar[index] && indexar[index] <= me->totpoly) {
 				MPoly *mpoly = me->mpoly + (indexar[index] - 1);
@@ -2372,7 +2372,7 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
 		} \
 	} (void)0
 
-	if (use_zbuf) {
+	if (use_depth) {
 		for (index = 0; index < totindex; index++) {
 
 			if (indexar[index] && indexar[index] <= me->totpoly) {
diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c
index ad7d3b1bddd..0e86438997c 100644
--- a/source/blender/editors/space_view3d/drawmesh.c
+++ b/source/blender/editors/space_view3d/drawmesh.c
@@ -1066,12 +1066,18 @@ void draw_mesh_paint(View3D *v3d, RegionView3D *rv3d,
 		draw_mesh_face_select(rv3d, me, dm);
 	}
 	else if ((do_light == FALSE) || (ob->dtx & OB_DRAWWIRE)) {
+		const int use_depth = (v3d->flag & V3D_ZBUF_SELECT);
 
 		/* weight paint in solid mode, special case. focus on making the weights clear
 		 * rather than the shading, this is also forced in wire view */
 
-		bglPolygonOffset(rv3d->dist, 1.0);
-		glDepthMask(0);  /* disable write in zbuffer, selected edge wires show better */
+		if (use_depth) {
+			bglPolygonOffset(rv3d->dist, 1.0);
+			glDepthMask(0);  /* disable write in zbuffer, selected edge wires show better */
+		}
+		else {
+			glDisable(GL_DEPTH_TEST);
+		}
 
 		glEnable(GL_BLEND);
 		glColor4ub(255, 255, 255, 96);
@@ -1080,8 +1086,14 @@ void draw_mesh_paint(View3D *v3d, RegionView3D *rv3d,
 
 		dm->drawEdges(dm, 1, 1);
 
-		bglPolygonOffset(rv3d->dist, 0.0);
-		glDepthMask(1);
+		if (use_depth) {
+			bglPolygonOffset(rv3d->dist, 0.0);
+			glDepthMask(1);
+		}
+		else {
+			glEnable(GL_DEPTH_TEST);
+		}
+
 		glDisable(GL_LINE_STIPPLE);
 		glDisable(GL_BLEND);
 	}
-- 
cgit v1.2.3


From 80ff313495ed739851dbd15d3e31506904503d5e Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Tue, 1 Jan 2013 12:47:58 +0000
Subject: patch [#33331] Time To Start Moving To Stdbool by Lawrence D'Oliveiro
 (ldo)

so BKE_utildefines.h allows use of C99's bool type and true/false.

currently scons wont try to use stdbool.h, and works as if its never found.
---
 source/blender/blenlib/BLI_utildefines.h | 30 ++++++++++++++++++++++++++----
 1 file changed, 26 insertions(+), 4 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h
index 7c3b70545d6..1774ef3d2b7 100644
--- a/source/blender/blenlib/BLI_utildefines.h
+++ b/source/blender/blenlib/BLI_utildefines.h
@@ -32,12 +32,34 @@
  *  \ingroup bli
  */
 
-#ifndef FALSE
-#  define FALSE 0
+/* note: use of (int, TRUE / FALSE) is deprecated,
+ * use (bool, true / false) instead */
+#ifdef HAVE_STDBOOL_H
+# include 
+#else
+# ifndef HAVE__BOOL
+#  ifdef __cplusplus
+typedef bool _Bool;
+#  else
+#   define _Bool signed char
+#  endif
+# endif
+# define bool _Bool
+# define false 0
+# define true 1
+# define __bool_true_false_are_defined 1
 #endif
 
-#ifndef TRUE
-#  define TRUE 1
+/* remove this when we're ready to remove TRUE/FALSE completely */
+#ifdef WITH_BOOL_COMPAT
+/* interim until all occurrences of these can be updated to stdbool */
+# ifndef FALSE
+#   define FALSE 0
+# endif
+
+# ifndef TRUE
+#   define TRUE 1
+# endif
 #endif
 
 /* useful for finding bad use of min/max */
-- 
cgit v1.2.3


From 1db74622cecfc7fa4172b961961309ae6c793c67 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Tue, 1 Jan 2013 12:51:08 +0000
Subject: make wight-paint-through feature work in face select mode. (still
 WIP, relies on selection flushing which currently ensured).

---
 source/blender/editors/sculpt_paint/paint_vertex.c | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 15d5257af60..fce58f776e8 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -2193,8 +2193,9 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
 	unsigned int index, totindex;
 	float alpha;
 	float mval[2];
-	int use_vert_sel;
-	int use_depth;
+	bool use_vert_sel;
+	bool use_face_sel;
+	bool use_depth;
 
 	MDeformWeight *(*dw_func)(MDeformVert *, const int) =
 	        (brush->vertexpaint_tool == PAINT_BLEND_BLUR) ?
@@ -2258,6 +2259,7 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
 	swap_m4m4(wpd->vc.rv3d->persmat, mat);
 
 	use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
+	use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
 	use_depth = (vc->v3d->flag & V3D_ZBUF_SELECT);
 
 	/* which faces are involved */
@@ -2274,7 +2276,7 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
 			else totindex = 0;
 		}
 
-		if ((me->editflag & ME_EDIT_PAINT_FACE_SEL) && me->mpoly) {
+		if (use_face_sel && me->mpoly) {
 			for (index = 0; index < totindex; index++) {
 				if (indexar[index] && indexar[index] <= me->totpoly) {
 					MPoly *mpoly = ((MPoly *)me->mpoly) + (indexar[index] - 1);
@@ -2341,8 +2343,16 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
 		const unsigned int totvert = me->totvert;
 		unsigned int       i;
 
-		for (i = 0; i < totvert; i++) {
-			me->dvert[i].flag = use_vert_sel ? (me->mvert[i].flag & SELECT) : SELECT;
+		/* in the case of face selection we need to flush */
+		if (use_vert_sel || use_face_sel) {
+			for (i = 0; i < totvert; i++) {
+				me->dvert[i].flag = me->mvert[i].flag & SELECT;
+			}
+		}
+		else {
+			for (i = 0; i < totvert; i++) {
+				me->dvert[i].flag = SELECT;
+			}
 		}
 
 		if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
-- 
cgit v1.2.3


From 1692f17c9b3d28e176e95443e491bb508de18932 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Tue, 1 Jan 2013 13:08:07 +0000
Subject: fix for long standing annoyance with weight-paint mode selection.

There was no selection flushing when faces or verts were selected, this allowed incorrect selection states like selected face with unselected vertices.

add flush commands to paintface_flush_flags() and paintvert_flush_flags()
---
 source/blender/editors/mesh/editface.c    | 18 ++++++++++++++++--
 source/blender/makesrna/intern/rna_mesh.c |  2 --
 2 files changed, 16 insertions(+), 4 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
index 11226b38cbb..3fbfaabbc0d 100644
--- a/source/blender/editors/mesh/editface.c
+++ b/source/blender/editors/mesh/editface.c
@@ -69,7 +69,14 @@ void paintface_flush_flags(Object *ob)
 	int totface, totpoly;
 	int i;
 	
-	if (me == NULL || dm == NULL)
+	if (me == NULL)
+		return;
+
+	/* we could call this directly in all areas that change selection,
+	 * since this could become slow for realtime updates (circle-select for eg) */
+	BKE_mesh_flush_select_from_polys(me);
+
+	if (dm == NULL)
 		return;
 
 	/*
@@ -603,7 +610,14 @@ void paintvert_flush_flags(Object *ob)
 	int totvert;
 	int i;
 
-	if (me == NULL || dm == NULL)
+	if (me == NULL)
+		return;
+
+	/* we could call this directly in all areas that change selection,
+	 * since this could become slow for realtime updates (circle-select for eg) */
+	BKE_mesh_flush_select_from_verts(me);
+
+	if (dm == NULL)
 		return;
 
 	index_array = dm->getVertDataArray(dm, CD_ORIGINDEX);
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index 6f33f8c1db4..e471bf3dd3c 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -154,7 +154,6 @@ static void rna_Mesh_update_vertmask(Main *bmain, Scene *scene, PointerRNA *ptr)
 	Mesh *me = ptr->data;
 	if ((me->editflag & ME_EDIT_PAINT_VERT_SEL) && (me->editflag & ME_EDIT_PAINT_FACE_SEL)) {
 		me->editflag &= ~ME_EDIT_PAINT_FACE_SEL;
-		BKE_mesh_flush_select_from_polys(me);
 	}
 	rna_Mesh_update_draw(bmain, scene, ptr);
 }
@@ -164,7 +163,6 @@ static void rna_Mesh_update_facemask(Main *bmain, Scene *scene, PointerRNA *ptr)
 	Mesh *me = ptr->data;
 	if ((me->editflag & ME_EDIT_PAINT_VERT_SEL) && (me->editflag & ME_EDIT_PAINT_FACE_SEL)) {
 		me->editflag &= ~ME_EDIT_PAINT_VERT_SEL;
-		BKE_mesh_flush_select_from_verts(me);
 	}
 	rna_Mesh_update_draw(bmain, scene, ptr);
 }
-- 
cgit v1.2.3


From 2754ee1f628303ecf43b4d0126914a94839f6659 Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Tue, 1 Jan 2013 14:06:02 +0000
Subject: Added MOUSEPAN (the trackpad event) to control propertional size
 while transform.

There's many hardcoded scrollwheel events in Blender for this, and with new proper
analog trackpad handling I'll try to find good remapping for most cases.
---
 source/blender/editors/transform/transform.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

(limited to 'source')

diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 39bad76b3d7..cbd8521cc33 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -686,6 +686,9 @@ static void view_editmove(unsigned short UNUSED(event))
 #define TFM_MODAL_EDGESLIDE_UP 24
 #define TFM_MODAL_EDGESLIDE_DOWN 25
 
+/* for analog input, like trackpad */
+#define TFM_MODAL_PROPSIZE		26
+
 /* called in transform_ops.c, on each regeneration of keymaps */
 wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf)
 {
@@ -715,6 +718,7 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf)
 		{TFM_MODAL_AUTOIK_LEN_DEC, "AUTOIK_CHAIN_LEN_DOWN", 0, "Decrease Max AutoIK Chain Length", ""},
 		{TFM_MODAL_EDGESLIDE_UP, "EDGESLIDE_EDGE_NEXT", 0, "Select next Edge Slide Edge", ""},
 		{TFM_MODAL_EDGESLIDE_DOWN, "EDGESLIDE_PREV_NEXT", 0, "Select previous Edge Slide Edge", ""},
+		{TFM_MODAL_PROPSIZE, "PROPORTIONAL_SIZE", 0, "Adjust Proportional Influence", ""},
 		{0, NULL, 0, NULL, NULL}
 	};
 	
@@ -750,6 +754,7 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf)
 	WM_modalkeymap_add_item(keymap, PAGEDOWNKEY, KM_PRESS, 0, 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, MOUSEPAN, 0, 0, 0, TFM_MODAL_PROPSIZE);
 
 	WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, KM_ALT, 0, TFM_MODAL_EDGESLIDE_UP);
 	WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, KM_ALT, 0, TFM_MODAL_EDGESLIDE_DOWN);
@@ -1024,6 +1029,19 @@ int transformEvent(TransInfo *t, wmEvent *event)
 				removeSnapPoint(t);
 				t->redraw |= TREDRAW_HARD;
 				break;
+				
+			case TFM_MODAL_PROPSIZE:
+				/* MOUSEPAN usage... */
+				if (t->flag & T_PROP_EDIT) {
+					float fac = 1.0f + 0.005f *(event->y - event->prevy);
+					t->prop_size *= fac;
+					if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO)
+						t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->far);
+					calculatePropRatio(t);
+				}
+				t->redraw |= TREDRAW_HARD;
+				break;
+				
 			case TFM_MODAL_PROPSIZE_UP:
 				if (t->flag & T_PROP_EDIT) {
 					t->prop_size *= 1.1f;
-- 
cgit v1.2.3


From 16afa704cccd5822f1d03f826ec45c7da9612b1b Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Tue, 1 Jan 2013 14:20:59 +0000
Subject: fix for own error in recent weight paint code, bound-box clip wasnt
 working.

---
 source/blender/editors/sculpt_paint/paint_vertex.c   | 8 ++++----
 source/blender/editors/space_view3d/view3d_project.c | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index fce58f776e8..ead6320c7d2 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -859,7 +859,7 @@ static float calc_vp_strength_dl(VPaint *vp, ViewContext *vc, const float co[3],
 {
 	float vertco[2];
 
-	if (ED_view3d_project_float_global(vc->ar,
+	if (ED_view3d_project_float_object(vc->ar,
 	                                   co, vertco,
 	                                   V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
 	{
@@ -2218,7 +2218,7 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
 		ED_region_tag_redraw(CTX_wm_region(C));
 		return;
 	}
-		
+
 	vc = &wpd->vc;
 	ob = vc->obact;
 	me = ob->data;
@@ -3061,9 +3061,9 @@ static void gradientVert__mapFunc(void *userData, int index, const float co[3],
 		 * the screen coords of the verts need to be cached because
 		 * updating the mesh may move them about (entering feedback loop) */
 		if (grad_data->is_init) {
-			if (ED_view3d_project_float_global(grad_data->ar,
+			if (ED_view3d_project_float_object(grad_data->ar,
 			                                   co, vs->sco,
-			                                   V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
+			                                   V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
 			{
 				/* ok */
 				MDeformVert *dv = &me->dvert[index];
diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c
index d4bdf6c3177..c428cb02236 100644
--- a/source/blender/editors/space_view3d/view3d_project.c
+++ b/source/blender/editors/space_view3d/view3d_project.c
@@ -110,7 +110,7 @@ eV3DProjStatus ED_view3d_project_base(struct ARegion *ar, struct Base *base)
 
 /* perspmat is typically...
  * - 'rv3d->perspmat',   is_local == FALSE
- * - 'rv3d->perspmatob', is_local == TRUE
+ * - 'rv3d->persmatob', is_local == TRUE
  */
 static eV3DProjStatus ed_view3d_project__internal(ARegion *ar,
                                                   float perspmat[4][4], const int is_local,  /* normally hidden */
-- 
cgit v1.2.3


From b88836a45ba03d97c23bda95ca4ead6b5f8f2637 Mon Sep 17 00:00:00 2001
From: Bastien Montagne 
Date: Tue, 1 Jan 2013 15:55:21 +0000
Subject: Add a warning to enum props' items parameter, to *never* use a
 generator as value for this param! It works in most cases, but in some it
 leads to an empty set of values for the enum (see [#33716]), and it's not an
 easy bug to track down!

---
 source/blender/python/intern/bpy_props.c | 2 ++
 1 file changed, 2 insertions(+)

(limited to 'source')

diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c
index bd033736865..57ddee0c8c0 100644
--- a/source/blender/python/intern/bpy_props.c
+++ b/source/blender/python/intern/bpy_props.c
@@ -1233,6 +1233,8 @@ BPY_PROPDEF_DESC_DOC
 "      For dynamic values a callback can be passed which returns a list in\n"
 "      the same format as the static list.\n"
 "      This function must take 2 arguments (self, context)\n"
+"      WARNING: Do not use generators here (they will work the first time, but will lead to empty values\n"
+"               in some unload/reload scenarii)!\n"
 "   :type items: sequence of string triplets or a function\n"
 BPY_PROPDEF_UPDATE_DOC
 );
-- 
cgit v1.2.3


From 2e0e2cb17056892cefeefeef9e0fd693084ef71f Mon Sep 17 00:00:00 2001
From: Sergey Sharybin 
Date: Tue, 1 Jan 2013 16:15:13 +0000
Subject: Highlight currently rendering tiles

This commit implements highlight of tiles which are being currently
rendered for both Blender Internal and Cycles (and should be possible
to use it for other external engines as well).

Couple of implementation details:

- Added one extra boolean flag to render engine which should be set
  to truth if render engine wants to highlight tiles. If so, property
  use_highlight_tiles should be set to True.

- Render Part's ready boolena was changed by status enum, which could
  be NONE, IN_PROGRESS and READY. All render part with IN_PROGRESS
  status will be highlighted in image editor.

- For external engines render part's status is filling in automatically.
  Initially all render parts has got NONE status, then one external
  engine acquire render result, corresponding part will change status
  to IN_PROGRESS. As soon as render result is finished, corresponding
  render part will change status to FINISHED

  This should make it easy to highlight tiles for other engines as well.
---
 source/blender/editors/space_image/image_draw.c    | 76 ++++++++++++++++++--
 source/blender/makesrna/intern/rna_render.c        |  3 +
 source/blender/render/extern/include/RE_engine.h   |  3 +
 .../blender/render/intern/include/render_types.h   |  8 ++-
 .../blender/render/intern/source/external_engine.c | 83 ++++++++++++++++++----
 source/blender/render/intern/source/pipeline.c     | 14 ++--
 .../blender/render/intern/source/render_result.c   |  2 +-
 7 files changed, 164 insertions(+), 25 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index e85ff016745..79130ccca2f 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -75,13 +75,15 @@
 #include "WM_types.h"
 
 #include "RE_pipeline.h"
+#include "RE_engine.h"
 
 #include "image_intern.h"
 
-static void draw_render_info(Scene *scene, Image *ima, ARegion *ar)
+static void draw_render_info(Scene *scene, Image *ima, ARegion *ar, float zoomx, float zoomy)
 {
 	RenderResult *rr;
-	
+	Render *re = RE_GetRender(scene->id.name);
+
 	rr = BKE_image_acquire_renderresult(scene, ima);
 
 	if (rr && rr->text) {
@@ -89,6 +91,73 @@ static void draw_render_info(Scene *scene, Image *ima, ARegion *ar)
 	}
 
 	BKE_image_release_renderresult(scene, ima);
+
+	if (re) {
+		int total_tiles;
+		rcti *tiles;
+
+		RE_engine_get_current_tiles(re, &total_tiles, &tiles);
+
+		if (total_tiles) {
+			int i, x, y;
+			rcti *tile;
+
+			/* find window pixel coordinates of origin */
+			UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x, &y);
+
+			glPushMatrix();
+			glTranslatef(x, y, 0.0f);
+			glScalef(zoomx, zoomy, 1.0f);
+
+			if (scene->r.mode & R_BORDER) {
+				glTranslatef(-scene->r.border.xmin * scene->r.xsch * scene->r.size / 100.0f,
+				             -scene->r.border.ymin * scene->r.ysch * scene->r.size / 100.0f,
+				             0.0f);
+			}
+
+			UI_ThemeColor(TH_FACE_SELECT);
+
+			for (i = 0, tile = tiles; i < total_tiles; i++, tile++) {
+				float delta_x = 4.0f * UI_DPI_FAC / zoomx;
+				float delta_y = 4.0f * UI_DPI_FAC / zoomy;
+
+				delta_x = min_ff(delta_x, tile->xmax - tile->xmin);
+				delta_y = min_ff(delta_y, tile->ymax - tile->ymin);
+
+				/* left bottom corner */
+				glBegin(GL_LINE_STRIP);
+				glVertex2f(tile->xmin, tile->ymin + delta_y);
+				glVertex2f(tile->xmin, tile->ymin);
+				glVertex2f(tile->xmin + delta_x, tile->ymin);
+				glEnd();
+
+				/* left top corner */
+				glBegin(GL_LINE_STRIP);
+				glVertex2f(tile->xmin, tile->ymax - delta_y);
+				glVertex2f(tile->xmin, tile->ymax);
+				glVertex2f(tile->xmin + delta_x, tile->ymax);
+				glEnd();
+
+				/* right bottom corner */
+				glBegin(GL_LINE_STRIP);
+				glVertex2f(tile->xmax - delta_x, tile->ymin);
+				glVertex2f(tile->xmax, tile->ymin);
+				glVertex2f(tile->xmax, tile->ymin + delta_y);
+				glEnd();
+
+				/* right top corner */
+				glBegin(GL_LINE_STRIP);
+				glVertex2f(tile->xmax - delta_x, tile->ymax);
+				glVertex2f(tile->xmax, tile->ymax);
+				glVertex2f(tile->xmax, tile->ymax - delta_y);
+				glEnd();
+			}
+
+			MEM_freeN(tiles);
+
+			glPopMatrix();
+		}
+	}
 }
 
 /* used by node view too */
@@ -786,7 +855,6 @@ void draw_image_main(const bContext *C, ARegion *ar)
 	if (sima->mode == SI_MODE_PAINT)
 		draw_image_paint_helpers(C, ar, scene, zoomx, zoomy);
 
-
 	/* XXX integrate this code */
 #if 0
 	if (ibuf) {
@@ -812,5 +880,5 @@ void draw_image_main(const bContext *C, ARegion *ar)
 
 	/* render info */
 	if (ima && show_render)
-		draw_render_info(scene, ima, ar);
+		draw_render_info(scene, ima, ar, zoomx, zoomy);
 }
diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c
index 03dc58233d5..93c5b45e642 100644
--- a/source/blender/makesrna/intern/rna_render.c
+++ b/source/blender/makesrna/intern/rna_render.c
@@ -406,6 +406,9 @@ static void rna_def_render_engine(BlenderRNA *brna)
 	RNA_def_property_int_sdna(prop, NULL, "resolution_y");
 	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
 
+	prop = RNA_def_property(srna, "use_highlight_tiles", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "flag", RE_ENGINE_HIGHLIGHT_TILES);
+
 	/* registration */
 
 	prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h
index d2ffc3a0e26..64135a16f5d 100644
--- a/source/blender/render/extern/include/RE_engine.h
+++ b/source/blender/render/extern/include/RE_engine.h
@@ -61,6 +61,7 @@ struct Scene;
 #define RE_ENGINE_DO_DRAW		4
 #define RE_ENGINE_DO_UPDATE		8
 #define RE_ENGINE_RENDERING		16
+#define RE_ENGINE_HIGHLIGHT_TILES	32
 
 extern ListBase R_engines;
 
@@ -130,5 +131,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);
+
 #endif /* __RE_ENGINE_H__ */
 
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index 742241676dc..905b4b4f4a8 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -104,13 +104,19 @@ typedef struct RenderPart {
 
 	rcti disprect;					/* part coordinates within total picture */
 	int rectx, recty;				/* the size */
-	short crop, ready;				/* crop is amount of pixels we crop, for filter */
+	short crop, status;				/* crop is amount of pixels we crop, for filter */
 	short sample, nr;				/* sample can be used by zbuffers, nr is partnr */
 	short thread;					/* thread id */
 	
 	char *clipflag;					/* clipflags for part zbuffering */
 } RenderPart;
 
+enum {
+	PART_STATUS_NONE        = 0,
+	PART_STATUS_IN_PROGRESS = 1,
+	PART_STATUS_READY       = 2
+};
+
 /* controls state of render, everything that's read-only during render stage */
 struct Render
 {
diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c
index 6fdf11ba48c..296c8b6eba8 100644
--- a/source/blender/render/intern/source/external_engine.c
+++ b/source/blender/render/intern/source/external_engine.c
@@ -150,6 +150,23 @@ void RE_engine_free(RenderEngine *engine)
 
 /* Render Results */
 
+static RenderPart *get_part_from_result(Render *re, RenderResult *result)
+{
+	RenderPart *pa;
+
+	for (pa = re->parts.first; pa; pa = pa->next) {
+		if (result->tilerect.xmin == pa->disprect.xmin - re->disprect.xmin &&
+		    result->tilerect.ymin == pa->disprect.ymin - re->disprect.ymin &&
+		    result->tilerect.xmax == pa->disprect.xmax - re->disprect.xmin &&
+		    result->tilerect.ymax == pa->disprect.ymax - re->disprect.ymin)
+		{
+			return pa;
+		}
+	}
+
+	return NULL;
+}
+
 RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername)
 {
 	Render *re = engine->re;
@@ -179,12 +196,19 @@ RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w,
 
 	/* can be NULL if we CLAMP the width or height to 0 */
 	if (result) {
+		RenderPart *pa;
+
 		BLI_addtail(&engine->fullresult, result);
 
 		result->tilerect.xmin += re->disprect.xmin;
 		result->tilerect.xmax += re->disprect.xmin;
 		result->tilerect.ymin += re->disprect.ymin;
 		result->tilerect.ymax += re->disprect.ymin;
+
+		pa = get_part_from_result(re, result);
+
+		if (pa)
+			pa->status = PART_STATUS_IN_PROGRESS;
 	}
 
 	return result;
@@ -203,7 +227,6 @@ void RE_engine_update_result(RenderEngine *engine, RenderResult *result)
 void RE_engine_end_result(RenderEngine *engine, RenderResult *result, int cancel)
 {
 	Render *re = engine->re;
-	RenderPart *pa;
 
 	if (!result) {
 		return;
@@ -212,15 +235,10 @@ void RE_engine_end_result(RenderEngine *engine, RenderResult *result, int cancel
 	/* merge. on break, don't merge in result for preview renders, looks nicer */
 	if (!cancel) {
 		/* for exr tile render, detect tiles that are done */
-		for (pa = re->parts.first; pa; pa = pa->next) {
-			if (result->tilerect.xmin == pa->disprect.xmin &&
-			    result->tilerect.ymin == pa->disprect.ymin &&
-			    result->tilerect.xmax == pa->disprect.xmax &&
-			    result->tilerect.ymax == pa->disprect.ymax)
-			{
-				pa->ready = 1;
-			}
-		}
+		RenderPart *pa = get_part_from_result(re, result);
+
+		if (pa)
+			pa->status = PART_STATUS_READY;
 
 		if (re->result->do_exr_tile)
 			render_result_exr_file_merge(re->result, result);
@@ -310,6 +328,47 @@ void RE_engine_report(RenderEngine *engine, int type, const char *msg)
 		BKE_report(engine->reports, type, msg);
 }
 
+void RE_engine_get_current_tiles(Render *re, int *total_tiles_r, rcti **tiles_r)
+{
+	RenderPart *pa;
+	int total_tiles = 0;
+	rcti *tiles = NULL;
+	int allocation_size = 0, allocation_step = BLENDER_MAX_THREADS;
+
+	if (re->engine && (re->engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0) {
+		*total_tiles_r = 0;
+		*tiles_r = NULL;
+		return;
+	}
+
+	for (pa = re->parts.first; pa; pa = pa->next) {
+		if (pa->status == PART_STATUS_IN_PROGRESS) {
+			if (total_tiles >= allocation_size) {
+				if (tiles == NULL)
+					tiles = MEM_mallocN(allocation_step * sizeof(rcti), "current engine tiles");
+				else
+					tiles = MEM_reallocN(tiles, (total_tiles + allocation_step) * sizeof(rcti));
+
+				allocation_size += allocation_step;
+			}
+
+			tiles[total_tiles] = pa->disprect;
+
+			if (pa->crop) {
+				tiles[total_tiles].xmin += pa->crop;
+				tiles[total_tiles].ymin += pa->crop;
+				tiles[total_tiles].xmax -= pa->crop;
+				tiles[total_tiles].ymax -= pa->crop;
+			}
+
+			total_tiles++;
+		}
+	}
+
+	*total_tiles_r = total_tiles;
+	*tiles_r = tiles;
+}
+
 /* Render */
 
 int RE_engine_render(Render *re, int do_all)
@@ -354,9 +413,7 @@ int RE_engine_render(Render *re, int do_all)
 
 	if (!engine) {
 		engine = RE_engine_create(type);
-
-		if (persistent_data)
-			re->engine = engine;
+		re->engine = engine;
 	}
 
 	engine->flag |= RE_ENGINE_RENDERING;
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index f2db84c47a9..755c8f40ba1 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -655,7 +655,9 @@ static int render_display_draw_enabled(Render *re)
 static void *do_part_thread(void *pa_v)
 {
 	RenderPart *pa = pa_v;
-	
+
+	pa->status = PART_STATUS_IN_PROGRESS;
+
 	/* need to return nicely all parts on esc */
 	if (R.test_break(R.tbh) == 0) {
 		
@@ -686,7 +688,7 @@ static void *do_part_thread(void *pa_v)
 		}
 	}
 	
-	pa->ready = 1;
+	pa->status = PART_STATUS_READY;
 	
 	return NULL;
 }
@@ -727,7 +729,7 @@ static RenderPart *find_next_pano_slice(Render *re, int *minx, rctf *viewplane)
 	
 	/* most left part of the non-rendering parts */
 	for (pa = re->parts.first; pa; pa = pa->next) {
-		if (pa->ready == 0 && pa->nr == 0) {
+		if (pa->status == PART_STATUS_NONE && pa->nr == 0) {
 			if (pa->disprect.xmin < *minx) {
 				best = pa;
 				*minx = pa->disprect.xmin;
@@ -765,7 +767,7 @@ static RenderPart *find_next_part(Render *re, int minx)
 	
 	/* find center of rendered parts, image center counts for 1 too */
 	for (pa = re->parts.first; pa; pa = pa->next) {
-		if (pa->ready) {
+		if (pa->status == PART_STATUS_READY) {
 			centx += BLI_rcti_cent_x(&pa->disprect);
 			centy += BLI_rcti_cent_y(&pa->disprect);
 			tot++;
@@ -776,7 +778,7 @@ static RenderPart *find_next_part(Render *re, int minx)
 	
 	/* closest of the non-rendering parts */
 	for (pa = re->parts.first; pa; pa = pa->next) {
-		if (pa->ready == 0 && pa->nr == 0) {
+		if (pa->status == PART_STATUS_NONE && pa->nr == 0) {
 			long long int distx = centx - BLI_rcti_cent_x(&pa->disprect);
 			long long int disty = centy - BLI_rcti_cent_y(&pa->disprect);
 			distx = (long long int)sqrt(distx * distx + disty * disty);
@@ -884,7 +886,7 @@ static void threaded_tile_processor(Render *re)
 		rendering = 0;
 		hasdrawn = 0;
 		for (pa = re->parts.first; pa; pa = pa->next) {
-			if (pa->ready) {
+			if (pa->status == PART_STATUS_READY) {
 				
 				BLI_remove_thread(&threads, pa);
 				
diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c
index 78750cfd1ca..6de5830df27 100644
--- a/source/blender/render/intern/source/render_result.c
+++ b/source/blender/render/intern/source/render_result.c
@@ -924,7 +924,7 @@ static void save_empty_result_tiles(Render *re)
 			IMB_exrtile_clear_channels(rl->exrhandle);
 		
 			for (pa = re->parts.first; pa; pa = pa->next) {
-				if (pa->ready == 0) {
+				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);
-- 
cgit v1.2.3


From be519ad7ff6bbf2301cfb95a78f344fd8aa0448e Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Tue, 1 Jan 2013 16:42:35 +0000
Subject: Further trackpad work:

When trackpad swipes don't convert to ScrollWheel steps anymore, several hardcoded
wheel events need to support swipe too.

This adds swipe support to:
- Menu item scroll
- Search item scroll
- ALT + number/slider/swatch values

The amount of old style scroll "clicks" is calculated based on how trackad is
being mapped to move a mouse pointer. Move it one widget unit = 1 click.

The swatch option applies trackpad swipe motion in analog way.
---
 .../blender/editors/interface/interface_handlers.c | 92 +++++++++++++++++-----
 .../blender/editors/interface/interface_intern.h   |  1 +
 .../blender/editors/interface/interface_regions.c  |  6 +-
 3 files changed, 77 insertions(+), 22 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 8df47f033c4..83f1cc4851d 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -220,6 +220,29 @@ static void button_timers_tooltip_remove(bContext *C, uiBut *but);
 
 /* ******************** menu navigation helpers ************** */
 
+/* assumes event type is MOUSEPAN */
+void ui_pan_to_scroll(wmEvent *event, int *type, int *val)
+{
+	static int lastdy = 0;
+	int dy = event->prevy - event->y;
+	
+	/* sign differs, reset */
+	if ((dy > 0 && lastdy < 0) || (dy < 0 && lastdy > 0))
+		lastdy = dy;
+	else {
+		lastdy += dy;
+		
+		if (ABS(lastdy) > (int)UI_UNIT_Y) {
+			*val = KM_PRESS;
+			if (event->prevy - event->y > 0)
+				*type = WHEELUPMOUSE;
+			else
+				*type = WHEELDOWNMOUSE;
+			lastdy = 0;
+		}
+	}
+}
+
 static int ui_but_editable(uiBut *but)
 {
 	return ELEM5(but->type, LABEL, SEPR, ROUNDBOX, LISTBOX, PROGRESSBAR);
@@ -1894,6 +1917,7 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
 		case WHEELUPMOUSE:
 		case WHEELDOWNMOUSE:
 		case MOUSEMOVE:
+		case MOUSEPAN:
 			if (data->searchbox)
 				ui_searchbox_event(C, data->searchbox, but, event);
 			
@@ -2688,12 +2712,16 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
 	ui_window_to_block(data->region, block, &mx, &my);
 
 	if (data->state == BUTTON_STATE_HIGHLIGHT) {
+		int type = event->type, val = event->val;
+		
+		ui_pan_to_scroll(event, &type, &val);
+		
 		/* XXX hardcoded keymap check.... */
-		if (event->type == WHEELDOWNMOUSE && event->alt) {
+		if (type == WHEELDOWNMOUSE && event->alt) {
 			mx = but->rect.xmin;
 			click = 1;
 		}
-		else if (event->type == WHEELUPMOUSE && event->alt) {
+		else if (type == WHEELUPMOUSE && event->alt) {
 			mx = but->rect.xmax;
 			click = 1;
 		}
@@ -2912,12 +2940,16 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
 	ui_window_to_block(data->region, block, &mx, &my);
 
 	if (data->state == BUTTON_STATE_HIGHLIGHT) {
+		int type = event->type, val = event->val;
+		
+		ui_pan_to_scroll(event, &type, &val);
+
 		/* XXX hardcoded keymap check.... */
-		if (event->type == WHEELDOWNMOUSE && event->alt) {
+		if (type == WHEELDOWNMOUSE && event->alt) {
 			mx = but->rect.xmin;
 			click = 2;
 		}
-		else if (event->type == WHEELUPMOUSE && event->alt) {
+		else if (type == WHEELUPMOUSE && event->alt) {
 			mx = but->rect.xmax;
 			click = 2;
 		}
@@ -3143,7 +3175,7 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, wm
 			}
 		}
 		else if (but->type == COLOR) {
-			if (ELEM(event->type, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->alt) {
+			if (ELEM3(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->alt) {
 				float *hsv = ui_block_hsv_get(but->block);
 				float col[3];
 				
@@ -3152,8 +3184,12 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, wm
 
 				if (event->type == WHEELDOWNMOUSE)
 					hsv[2] = CLAMPIS(hsv[2] - 0.05f, 0.0f, 1.0f);
-				else
+				else if (event->type == WHEELUPMOUSE)
 					hsv[2] = CLAMPIS(hsv[2] + 0.05f, 0.0f, 1.0f);
+				else {
+					float fac = 0.005 * (event->y - event->prevy);
+					hsv[2] = CLAMPIS(hsv[2] + fac, 0.0f, 1.0f);
+				}
 				
 				hsv_to_rgb_v(hsv, data->vec);
 				ui_set_but_vectorf(but, data->vec);
@@ -6093,18 +6129,24 @@ static int ui_handle_list_event(bContext *C, wmEvent *event, ARegion *ar)
 	uiBut *but = ui_list_find_mouse_over(ar, event->x, event->y);
 	int retval = WM_UI_HANDLER_CONTINUE;
 	int value, min, max;
+	int type = event->type, val = event->val;
 
-	if (but && (event->val == KM_PRESS)) {
+	/* convert pan to scrollwheel */
+	if (type == MOUSEPAN)
+		ui_pan_to_scroll(event, &type, &val);
+	
+	if (but && (val == KM_PRESS)) {
 		uiList *ui_list = but->custom_data;
 
 		if (ui_list) {
-			if (ELEM(event->type, UPARROWKEY, DOWNARROWKEY) ||
-				((ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->alt)))
+
+			if (ELEM(type, UPARROWKEY, DOWNARROWKEY) ||
+				((ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->alt)))
 			{
 				/* activate up/down the list */
 				value = RNA_property_int_get(&but->rnapoin, but->rnaprop);
 
-				if (ELEM(event->type, UPARROWKEY, WHEELUPMOUSE))
+				if (ELEM(type, UPARROWKEY, WHEELUPMOUSE))
 					value--;
 				else
 					value++;
@@ -6125,12 +6167,12 @@ static int ui_handle_list_event(bContext *C, wmEvent *event, ARegion *ar)
 
 				retval = WM_UI_HANDLER_BREAK;
 			}
-			else if (ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->shift) {
+			else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->shift) {
 				/* silly replacement for proper grip */
 				if (ui_list->list_grip_size == 0)
 					ui_list->list_grip_size = ui_list->list_size;
 
-				if (event->type == WHEELUPMOUSE)
+				if (type == WHEELUPMOUSE)
 					ui_list->list_grip_size--;
 				else
 					ui_list->list_grip_size++;
@@ -6141,10 +6183,10 @@ static int ui_handle_list_event(bContext *C, wmEvent *event, ARegion *ar)
 
 				retval = WM_UI_HANDLER_BREAK;
 			}
-			else if (ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
+			else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
 				if (ui_list->list_last_len > ui_list->list_size) {
 					/* list template will clamp */
-					if (event->type == WHEELUPMOUSE)
+					if (type == WHEELUPMOUSE)
 						ui_list->list_scroll--;
 					else
 						ui_list->list_scroll++;
@@ -6458,21 +6500,29 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
 				case DOWNARROWKEY:
 				case WHEELUPMOUSE:
 				case WHEELDOWNMOUSE:
+				case MOUSEPAN:
 					/* arrowkeys: only handle for block_loop blocks */
 					if (event->alt || event->shift || event->ctrl || event->oskey) {
 						/* pass */
 					}
 					else if (inside || (block->flag & UI_BLOCK_LOOP)) {
-						if (event->val == KM_PRESS) {
+						int type = event->type;
+						int val = event->val;
+						
+						/* convert pan to scrollwheel */
+						if (type == MOUSEPAN)
+							ui_pan_to_scroll(event, &type, &val);
+						
+						if (val == KM_PRESS) {
 
 							PASS_EVENT_TO_PARENT_IF_NONACTIVE;
 
 							but = ui_but_find_activated(ar);
 							if (but) {
 								/* is there a situation where UI_LEFT or UI_RIGHT would also change navigation direction? */
-								if (((ELEM(event->type, DOWNARROWKEY, WHEELDOWNMOUSE)) && (block->direction & UI_DOWN)) ||
-								    ((ELEM(event->type, DOWNARROWKEY, WHEELDOWNMOUSE)) && (block->direction & UI_RIGHT)) ||
-								    ((ELEM(event->type, UPARROWKEY, WHEELUPMOUSE)) && (block->direction & UI_TOP)))
+								if (((ELEM(type, DOWNARROWKEY, WHEELDOWNMOUSE)) && (block->direction & UI_DOWN)) ||
+								    ((ELEM(type, DOWNARROWKEY, WHEELDOWNMOUSE)) && (block->direction & UI_RIGHT)) ||
+								    ((ELEM(type, UPARROWKEY, WHEELUPMOUSE)) && (block->direction & UI_TOP)))
 								{
 									/* the following is just a hack - uiBut->type set to BUT and BUTM have there menus built 
 									 * opposite ways - this should be changed so that all popup-menus use the same uiBlock->direction */
@@ -6495,9 +6545,9 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
 							}
 
 							if (!but) {
-								if (((ELEM(event->type, UPARROWKEY, WHEELUPMOUSE)) && (block->direction & UI_DOWN)) ||
-								    ((ELEM(event->type, UPARROWKEY, WHEELUPMOUSE)) && (block->direction & UI_RIGHT)) ||
-								    ((ELEM(event->type, DOWNARROWKEY, WHEELDOWNMOUSE)) && (block->direction & UI_TOP)))
+								if (((ELEM(type, UPARROWKEY, WHEELUPMOUSE)) && (block->direction & UI_DOWN)) ||
+								    ((ELEM(type, UPARROWKEY, WHEELUPMOUSE)) && (block->direction & UI_RIGHT)) ||
+								    ((ELEM(type, DOWNARROWKEY, WHEELDOWNMOUSE)) && (block->direction & UI_TOP)))
 								{
 									if ((bt = ui_but_first(block)) && (bt->type & BUT)) {
 										bt = ui_but_last(block);
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 8341307481d..706301dc060 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -507,6 +507,7 @@ void ui_draw_but_IMAGE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rct
 void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
 
 /* interface_handlers.c */
+extern void ui_pan_to_scroll(struct wmEvent *event, int *type, int *val);
 extern void ui_button_activate_do(struct bContext *C, struct ARegion *ar, uiBut *but);
 extern void ui_button_active_free(const struct bContext *C, uiBut *but);
 extern int ui_button_is_active(struct ARegion *ar);
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 329e1aabe67..4a8ad5d24a6 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -896,8 +896,12 @@ void ui_searchbox_apply(uiBut *but, ARegion *ar)
 void ui_searchbox_event(bContext *C, ARegion *ar, uiBut *but, wmEvent *event)
 {
 	uiSearchboxData *data = ar->regiondata;
+	int type = event->type, val = event->val;
 	
-	switch (event->type) {
+	if (type == MOUSEPAN)
+		ui_pan_to_scroll(event, &type, &val);
+	
+	switch (type) {
 		case WHEELUPMOUSE:
 		case UPARROWKEY:
 			ui_searchbox_select(C, ar, but, -1);
-- 
cgit v1.2.3


From 6ea766be0ea0e929c768d004c9f63976838f44b5 Mon Sep 17 00:00:00 2001
From: Bastien Montagne 
Date: Tue, 1 Jan 2013 18:18:45 +0000
Subject: Intent to fix windows not compiling after r53480.

Looks like _Bool is also a type in std (at least with msvc), so the 'typdef bool _Bool;' generates a name collision... Now using _BLI_Bool as placeholder instead.
---
 source/blender/blenlib/BLI_utildefines.h | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h
index 1774ef3d2b7..cb30138c4f9 100644
--- a/source/blender/blenlib/BLI_utildefines.h
+++ b/source/blender/blenlib/BLI_utildefines.h
@@ -39,12 +39,14 @@
 #else
 # ifndef HAVE__BOOL
 #  ifdef __cplusplus
-typedef bool _Bool;
+typedef bool _BLI_Bool;
 #  else
-#   define _Bool signed char
+#   define _BLI_Bool signed char
 #  endif
+# else
+#  define _BLI_Bool _Bool
 # endif
-# define bool _Bool
+# define bool _BLI_Bool
 # define false 0
 # define true 1
 # define __bool_true_false_are_defined 1
@@ -53,6 +55,7 @@ typedef bool _Bool;
 /* remove this when we're ready to remove TRUE/FALSE completely */
 #ifdef WITH_BOOL_COMPAT
 /* interim until all occurrences of these can be updated to stdbool */
+/* XXX Why not use the true/false velues here? */
 # ifndef FALSE
 #   define FALSE 0
 # endif
-- 
cgit v1.2.3


From 247c7078bc1ae60a21748f16f331390d4f46d212 Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Tue, 1 Jan 2013 19:02:08 +0000
Subject: Bug fixes, own collection.

While examining icons, I noticed material icons were too dark.
It appeared a lot of bad hacks were added for colormanagement in preview render.

Removed them all, and things look smooth (yes, color management is OK!).

However! It is now very clear that Procedural Textures miss getting inverse
color managed in render - a reason why they show so bright washed out, already
since introduction of Color Management in Blender.

Try render a plane with linear black-white blend, shadeless!
http://www.blender.org/bf/Untitled.png

Todo: add colormanaged procedurals (optional).
---
 source/blender/editors/render/render_preview.c | 57 ++++++--------------------
 1 file changed, 12 insertions(+), 45 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index 6ca8478b489..8d748d3ea20 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -280,11 +280,6 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
 			sce->r.tiley = sce->r.ysch / 4;
 		}
 		
-		/* exception: don't apply render part of display transform for texture previews or icons */
-		if ((id && sp->pr_method == PR_ICON_RENDER) || id_type == ID_TE) {
-			BKE_scene_disable_color_management(sce);
-		}
-		
 		if ((id && sp->pr_method == PR_ICON_RENDER) && id_type != ID_WO)
 			sce->r.alphamode = R_ALPHAPREMUL;
 		else
@@ -488,24 +483,15 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
 
 /* new UI convention: draw is in pixel space already. */
 /* uses ROUNDBOX button in block to get the rect */
-static int ed_preview_draw_rect(ScrArea *sa, Scene *sce, ID *id, int split, int first, rcti *rect, rcti *newrect)
+static int ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect, rcti *newrect)
 {
 	Render *re;
 	RenderResult rres;
 	char name[32];
-	int do_gamma_correct = FALSE, do_predivide = FALSE;
 	int offx = 0;
 	int newx = BLI_rcti_size_x(rect);
 	int newy = BLI_rcti_size_y(rect);
 
-	if (id && GS(id->name) != ID_TE) {
-		/* exception: don't color manage texture previews - show the raw values */
-		if (sce) {
-			do_gamma_correct = TRUE;
-			do_predivide = TRUE;
-		}
-	}
-
 	if (!split || first) sprintf(name, "Preview %p", (void *)sa);
 	else sprintf(name, "SecondPreview %p", (void *)sa);
 
@@ -520,8 +506,10 @@ static int ed_preview_draw_rect(ScrArea *sa, Scene *sce, ID *id, int split, int
 		}
 	}
 
+	/* test if something rendered ok */
 	re = RE_GetRender(name);
 	RE_AcquireResultImage(re, &rres);
+	RE_ReleaseResultImage(re);
 
 	if (rres.rectf) {
 		
@@ -531,40 +519,20 @@ static int ed_preview_draw_rect(ScrArea *sa, Scene *sce, ID *id, int split, int
 			newrect->ymax = max_ii(newrect->ymax, rect->ymin + rres.recty);
 
 			if (rres.rectx && rres.recty) {
-				/* temporary conversion to byte for drawing */
+				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;
-				int dither = 0;
-				unsigned char *rect_byte;
-
-				rect_byte = MEM_mallocN(rres.rectx * rres.recty * sizeof(int), "ed_preview_draw_rect");
-
-				if (do_gamma_correct) {
-					IMB_display_buffer_transform_apply(rect_byte, rres.rectf, rres.rectx, rres.recty, 4,
-					                                   &sce->view_settings, &sce->display_settings, do_predivide);
-
-				}
-				else {
-					/* OCIO_TODO: currently seems an exception for textures (came fro mlegacish time),
-					 *            but is it indeed expected behavior, or textures should be
-					 *            color managed as well?
-					 */
-					IMB_buffer_byte_from_float(rect_byte, rres.rectf,
-					                           4, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, do_predivide,
-					                           rres.rectx, rres.recty, rres.rectx, rres.rectx);
-				}
-
+				
+				RE_ResultGet32(re, (unsigned int *)rect_byte);
 				glaDrawPixelsSafe(fx, fy, rres.rectx, rres.recty, rres.rectx, GL_RGBA, GL_UNSIGNED_BYTE, rect_byte);
-
+				
 				MEM_freeN(rect_byte);
+				
+				return 1;
 			}
-
-			RE_ReleaseResultImage(re);
-			return 1;
 		}
 	}
 
-	RE_ReleaseResultImage(re);
 	return 0;
 }
 
@@ -572,7 +540,6 @@ void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, r
 {
 	if (idp) {
 		ScrArea *sa = CTX_wm_area(C);
-		Scene *sce = CTX_data_scene(C);
 		ID *id = (ID *)idp;
 		ID *parent = (ID *)parentp;
 		MTex *slot = (MTex *)slotp;
@@ -588,11 +555,11 @@ void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, r
 		newrect.ymax = rect->ymin;
 
 		if (parent) {
-			ok = ed_preview_draw_rect(sa, sce, id, 1, 1, rect, &newrect);
-			ok &= ed_preview_draw_rect(sa, sce, parent, 1, 0, rect, &newrect);
+			ok = ed_preview_draw_rect(sa, 1, 1, rect, &newrect);
+			ok &= ed_preview_draw_rect(sa, 1, 0, rect, &newrect);
 		}
 		else
-			ok = ed_preview_draw_rect(sa, sce, id, 0, 0, rect, &newrect);
+			ok = ed_preview_draw_rect(sa, 0, 0, rect, &newrect);
 
 		if (ok)
 			*rect = newrect;
-- 
cgit v1.2.3


From 0f3931dee4fb38e2447d05cebb41cc26041be82a Mon Sep 17 00:00:00 2001
From: Stuart Broadfoot 
Date: Tue, 1 Jan 2013 19:50:29 +0000
Subject: Fix for normal scaling when using triangle primitives for hair.

and some code clean ups in blender_curves and node_shader_hair_info.c
---
 source/blender/nodes/shader/nodes/node_shader_hair_info.c | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

(limited to 'source')

diff --git a/source/blender/nodes/shader/nodes/node_shader_hair_info.c b/source/blender/nodes/shader/nodes/node_shader_hair_info.c
index 8e6f40faf24..5cd4c8bd1d3 100644
--- a/source/blender/nodes/shader/nodes/node_shader_hair_info.c
+++ b/source/blender/nodes/shader/nodes/node_shader_hair_info.c
@@ -35,11 +35,6 @@ static bNodeSocketTemplate outputs[] = {
 	{	-1, 0, ""	}
 };
 
-static int node_shader_gpu_curve_attrib(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
-{
-	return GPU_stack_link(mat, "NODE_HAIR_INFO", in, out);
-}
-
 /* node type definition */
 void register_node_type_sh_hair_info(bNodeTreeType *ttype)
 {
@@ -52,7 +47,7 @@ void register_node_type_sh_hair_info(bNodeTreeType *ttype)
 	node_type_init(&ntype, NULL);
 	node_type_storage(&ntype, "", NULL, NULL);
 	node_type_exec(&ntype, NULL);
-	node_type_gpu(&ntype, node_shader_gpu_curve_attrib);
+	node_type_gpu(&ntype, NULL);
 
 	nodeRegisterType(ttype, &ntype);
 }
-- 
cgit v1.2.3


From 59893d9d5b0e1c0d39b629e7d25e94c467eb5997 Mon Sep 17 00:00:00 2001
From: Antony Riakiotakis 
Date: Tue, 1 Jan 2013 21:23:12 +0000
Subject: Code cleanup: Separate 2D painting functions away from brush.c, which
 should implement the brush API and into its own file, paint_2D.c. Ideally
 projective texturing and 2D painting should be totally separate, however
 functionality is still interleaved mostly in the BKE_brush_painter_paint
 function. The functionality of this function can possibly be done using the
 brush stroke functions instead.

---
 source/blender/blenkernel/BKE_brush.h              |   1 +
 source/blender/blenkernel/intern/brush.c           | 526 +------------------
 source/blender/editors/sculpt_paint/CMakeLists.txt |   1 +
 source/blender/editors/sculpt_paint/paint_2D.c     | 562 +++++++++++++++++++++
 4 files changed, 565 insertions(+), 525 deletions(-)
 create mode 100644 source/blender/editors/sculpt_paint/paint_2D.c

(limited to 'source')

diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h
index cbffb6c0cea..248fe9c8968 100644
--- a/source/blender/blenkernel/BKE_brush.h
+++ b/source/blender/blenkernel/BKE_brush.h
@@ -99,6 +99,7 @@ float BKE_brush_unprojected_radius_get(const struct Scene *scene, struct 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);
+void BKE_brush_alpha_set(Scene *scene, struct Brush *brush, float alpha);
 float BKE_brush_weight_get(const Scene *scene, struct Brush *brush);
 void BKE_brush_weight_set(const Scene *scene, struct Brush *brush, float value);
 
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 405b1efb25d..aeb0407b37f 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -29,29 +29,16 @@
  *  \ingroup bke
  */
 
-
-#include 
-#include 
-
 #include "MEM_guardedalloc.h"
 
 #include "DNA_brush_types.h"
-#include "DNA_color_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_object_types.h"
-#include "DNA_userdef_types.h"
-#include "DNA_windowmanager_types.h"
-
-#include "WM_types.h"
-
-#include "RNA_access.h"
 
 #include "BLI_math.h"
 #include "BLI_blenlib.h"
 #include "BLI_rand.h"
-#include "BLI_utildefines.h"
 
-#include "BKE_blender.h"
 #include "BKE_brush.h"
 #include "BKE_colortools.h"
 #include "BKE_global.h"
@@ -66,7 +53,6 @@
 #include "IMB_imbuf_types.h"
 
 #include "RE_render_ext.h" /* externtex */
-#include "RE_shader_ext.h"
 
 static void brush_defaults(Brush *brush)
 {
@@ -696,7 +682,7 @@ float BKE_brush_unprojected_radius_get(const Scene *scene, Brush *brush)
 	       brush->unprojected_radius;
 }
 
-static void brush_alpha_set(Scene *scene, Brush *brush, float alpha)
+void BKE_brush_alpha_set(Scene *scene, Brush *brush, float alpha)
 {
 	UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
 
@@ -754,315 +740,6 @@ void BKE_brush_scale_size(int *r_brush_size,
 	(*r_brush_size) = (int)((float)(*r_brush_size) * scale);
 }
 
-/* Brush Painting */
-
-typedef struct BrushPainterCache {
-	short enabled;
-
-	int size;           /* size override, if 0 uses 2*BKE_brush_size_get(brush) */
-	short flt;          /* need float imbuf? */
-	short texonly;      /* no alpha, color or fallof, only texture in imbuf */
-
-	int lastsize;
-	float lastalpha;
-	float lastjitter;
-
-	ImBuf *ibuf;
-	ImBuf *texibuf;
-	ImBuf *maskibuf;
-} BrushPainterCache;
-
-struct BrushPainter {
-	Scene *scene;
-	Brush *brush;
-
-	float lastmousepos[2];  /* mouse position of last paint call */
-
-	float accumdistance;    /* accumulated distance of brush since last paint op */
-	float lastpaintpos[2];  /* position of last paint op */
-	float startpaintpos[2]; /* position of first paint */
-
-	double accumtime;       /* accumulated time since last paint op (airbrush) */
-	double lasttime;        /* time of last update */
-
-	float lastpressure;
-
-	short firsttouch;       /* first paint op */
-
-	float startsize;
-	float startalpha;
-	float startjitter;
-	float startspacing;
-
-	BrushPainterCache cache;
-};
-
-BrushPainter *BKE_brush_painter_new(Scene *scene, Brush *brush)
-{
-	BrushPainter *painter = MEM_callocN(sizeof(BrushPainter), "BrushPainter");
-
-	painter->brush = brush;
-	painter->scene = scene;
-	painter->firsttouch = 1;
-	painter->cache.lastsize = -1; /* force ibuf create in refresh */
-
-	painter->startsize = BKE_brush_size_get(scene, brush);
-	painter->startalpha = BKE_brush_alpha_get(scene, brush);
-	painter->startjitter = brush->jitter;
-	painter->startspacing = brush->spacing;
-
-	return painter;
-}
-
-void BKE_brush_painter_require_imbuf(BrushPainter *painter, short flt, short texonly, int size)
-{
-	if ((painter->cache.flt != flt) || (painter->cache.size != size) ||
-	    ((painter->cache.texonly != texonly) && texonly))
-	{
-		if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
-		if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf);
-		painter->cache.ibuf = painter->cache.maskibuf = NULL;
-		painter->cache.lastsize = -1; /* force ibuf create in refresh */
-	}
-
-	if (painter->cache.flt != flt) {
-		if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
-		painter->cache.texibuf = NULL;
-		painter->cache.lastsize = -1; /* force ibuf create in refresh */
-	}
-
-	painter->cache.size = size;
-	painter->cache.flt = flt;
-	painter->cache.texonly = texonly;
-	painter->cache.enabled = 1;
-}
-
-void BKE_brush_painter_free(BrushPainter *painter)
-{
-	Brush *brush = painter->brush;
-
-	BKE_brush_size_set(painter->scene, brush, painter->startsize);
-	brush_alpha_set(painter->scene, brush, painter->startalpha);
-	brush->jitter = painter->startjitter;
-	brush->spacing = painter->startspacing;
-
-	if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
-	if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
-	if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf);
-	MEM_freeN(painter);
-}
-
-static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf,
-                                     int x, int y, int w, int h, int xt, int yt,
-                                     const float pos[2])
-{
-	Scene *scene = painter->scene;
-	Brush *brush = painter->brush;
-	ImBuf *ibuf, *maskibuf, *texibuf;
-	float *bf, *mf, *tf, *otf = NULL, xoff, yoff, xy[2], rgba[4];
-	unsigned char *b, *m, *t, *ot = NULL;
-	int dotexold, origx = x, origy = y;
-	const int radius = BKE_brush_size_get(painter->scene, brush);
-
-	xoff = -radius + 0.5f;
-	yoff = -radius + 0.5f;
-	xoff += (int)pos[0] - (int)painter->startpaintpos[0];
-	yoff += (int)pos[1] - (int)painter->startpaintpos[1];
-
-	ibuf = painter->cache.ibuf;
-	texibuf = painter->cache.texibuf;
-	maskibuf = painter->cache.maskibuf;
-
-	dotexold = (oldtexibuf != NULL);
-
-	/* not sure if it's actually needed or it's a mistake in coords/sizes
-	 * calculation in brush_painter_fixed_tex_partial_update(), but without this
-	 * limitation memory gets corrupted at fast strokes with quite big spacing (sergey) */
-	w = min_ii(w, ibuf->x);
-	h = min_ii(h, ibuf->y);
-
-	if (painter->cache.flt) {
-		for (; y < h; y++) {
-			bf = ibuf->rect_float + (y * ibuf->x + origx) * 4;
-			tf = texibuf->rect_float + (y * texibuf->x + origx) * 4;
-			mf = maskibuf->rect_float + (y * maskibuf->x + origx) * 4;
-
-			if (dotexold)
-				otf = oldtexibuf->rect_float + ((y - origy + yt) * oldtexibuf->x + xt) * 4;
-
-			for (x = origx; x < w; x++, bf += 4, mf += 4, tf += 4) {
-				if (dotexold) {
-					copy_v3_v3(tf, otf);
-					tf[3] = otf[3];
-					otf += 4;
-				}
-				else {
-					xy[0] = x + xoff;
-					xy[1] = y + yoff;
-
-					BKE_brush_sample_tex(scene, brush, xy, tf, 0);
-				}
-
-				bf[0] = tf[0] * mf[0];
-				bf[1] = tf[1] * mf[1];
-				bf[2] = tf[2] * mf[2];
-				bf[3] = tf[3] * mf[3];
-			}
-		}
-	}
-	else {
-		for (; y < h; y++) {
-			b = (unsigned char *)ibuf->rect + (y * ibuf->x + origx) * 4;
-			t = (unsigned char *)texibuf->rect + (y * texibuf->x + origx) * 4;
-			m = (unsigned char *)maskibuf->rect + (y * maskibuf->x + origx) * 4;
-
-			if (dotexold)
-				ot = (unsigned char *)oldtexibuf->rect + ((y - origy + yt) * oldtexibuf->x + xt) * 4;
-
-			for (x = origx; x < w; x++, b += 4, m += 4, t += 4) {
-				if (dotexold) {
-					t[0] = ot[0];
-					t[1] = ot[1];
-					t[2] = ot[2];
-					t[3] = ot[3];
-					ot += 4;
-				}
-				else {
-					xy[0] = x + xoff;
-					xy[1] = y + yoff;
-
-					BKE_brush_sample_tex(scene, brush, xy, rgba, 0);
-					rgba_float_to_uchar(t, rgba);
-				}
-
-				b[0] = t[0] * m[0] / 255;
-				b[1] = t[1] * m[1] / 255;
-				b[2] = t[2] * m[2] / 255;
-				b[3] = t[3] * m[3] / 255;
-			}
-		}
-	}
-}
-
-static void brush_painter_fixed_tex_partial_update(BrushPainter *painter, const float pos[2])
-{
-	const Scene *scene = painter->scene;
-	Brush *brush = painter->brush;
-	BrushPainterCache *cache = &painter->cache;
-	ImBuf *oldtexibuf, *ibuf;
-	int imbflag, destx, desty, srcx, srcy, w, h, x1, y1, x2, y2;
-	const int diameter = 2 * BKE_brush_size_get(scene, brush);
-
-	imbflag = (cache->flt) ? IB_rectfloat : IB_rect;
-	if (!cache->ibuf)
-		cache->ibuf = IMB_allocImBuf(diameter, diameter, 32, imbflag);
-	ibuf = cache->ibuf;
-
-	oldtexibuf = cache->texibuf;
-	cache->texibuf = IMB_allocImBuf(diameter, diameter, 32, imbflag);
-
-	if (oldtexibuf) {
-		srcx = srcy = 0;
-		destx = (int)painter->lastpaintpos[0] - (int)pos[0];
-		desty = (int)painter->lastpaintpos[1] - (int)pos[1];
-		w = oldtexibuf->x;
-		h = oldtexibuf->y;
-
-		IMB_rectclip(cache->texibuf, oldtexibuf, &destx, &desty, &srcx, &srcy, &w, &h);
-	}
-	else {
-		srcx = srcy = 0;
-		destx = desty = 0;
-		w = h = 0;
-	}
-	
-	x1 = destx;
-	y1 = desty;
-	x2 = destx + w;
-	y2 = desty + h;
-
-	/* blend existing texture in new position */
-	if ((x1 < x2) && (y1 < y2))
-		brush_painter_do_partial(painter, oldtexibuf, x1, y1, x2, y2, srcx, srcy, pos);
-
-	if (oldtexibuf)
-		IMB_freeImBuf(oldtexibuf);
-
-	/* sample texture in new areas */
-	if ((0 < x1) && (0 < ibuf->y))
-		brush_painter_do_partial(painter, NULL, 0, 0, x1, ibuf->y, 0, 0, pos);
-	if ((x2 < ibuf->x) && (0 < ibuf->y))
-		brush_painter_do_partial(painter, NULL, x2, 0, ibuf->x, ibuf->y, 0, 0, pos);
-	if ((x1 < x2) && (0 < y1))
-		brush_painter_do_partial(painter, NULL, x1, 0, x2, y1, 0, 0, pos);
-	if ((x1 < x2) && (y2 < ibuf->y))
-		brush_painter_do_partial(painter, NULL, x1, y2, x2, ibuf->y, 0, 0, pos);
-}
-
-static void brush_painter_refresh_cache(BrushPainter *painter, const float pos[2], int use_color_correction)
-{
-	const Scene *scene = painter->scene;
-	Brush *brush = painter->brush;
-	BrushPainterCache *cache = &painter->cache;
-	MTex *mtex = &brush->mtex;
-	int size;
-	short flt;
-	const int diameter = 2 * BKE_brush_size_get(scene, brush);
-	const float alpha = BKE_brush_alpha_get(scene, brush);
-
-	if (diameter != cache->lastsize ||
-	    alpha != cache->lastalpha ||
-	    brush->jitter != cache->lastjitter)
-	{
-		if (cache->ibuf) {
-			IMB_freeImBuf(cache->ibuf);
-			cache->ibuf = NULL;
-		}
-		if (cache->maskibuf) {
-			IMB_freeImBuf(cache->maskibuf);
-			cache->maskibuf = NULL;
-		}
-
-		flt = cache->flt;
-		size = (cache->size) ? cache->size : diameter;
-
-		if (brush->flag & BRUSH_FIXED_TEX) {
-			BKE_brush_imbuf_new(scene, brush, flt, 3, size, &cache->maskibuf, use_color_correction);
-			brush_painter_fixed_tex_partial_update(painter, pos);
-		}
-		else
-			BKE_brush_imbuf_new(scene, brush, flt, 2, size, &cache->ibuf, use_color_correction);
-
-		cache->lastsize = diameter;
-		cache->lastalpha = alpha;
-		cache->lastjitter = brush->jitter;
-	}
-	else if ((brush->flag & BRUSH_FIXED_TEX) && mtex && mtex->tex) {
-		int dx = (int)painter->lastpaintpos[0] - (int)pos[0];
-		int dy = (int)painter->lastpaintpos[1] - (int)pos[1];
-
-		if ((dx != 0) || (dy != 0))
-			brush_painter_fixed_tex_partial_update(painter, pos);
-	}
-}
-
-void BKE_brush_painter_break_stroke(BrushPainter *painter)
-{
-	painter->firsttouch = 1;
-}
-
-static void brush_pressure_apply(BrushPainter *painter, Brush *brush, float pressure)
-{
-	if (BKE_brush_use_alpha_pressure(painter->scene, brush))
-		brush_alpha_set(painter->scene, brush, max_ff(0.0f, painter->startalpha * pressure));
-	if (BKE_brush_use_size_pressure(painter->scene, brush))
-		BKE_brush_size_set(painter->scene, brush, max_ff(1.0f, painter->startsize * pressure));
-	if (brush->flag & BRUSH_JITTER_PRESSURE)
-		brush->jitter = max_ff(0.0f, painter->startjitter * pressure);
-	if (brush->flag & BRUSH_SPACING_PRESSURE)
-		brush->spacing = max_ff(1.0f, painter->startspacing * (1.5f - pressure));
-}
-
 void BKE_brush_jitter_pos(const Scene *scene, Brush *brush, const float pos[2], float jitterpos[2])
 {
 	int use_jitter = brush->jitter != 0;
@@ -1090,165 +767,6 @@ void BKE_brush_jitter_pos(const Scene *scene, Brush *brush, const float pos[2],
 	}
 }
 
-int BKE_brush_painter_paint(BrushPainter *painter, BrushFunc func, const float pos[2], double time, float pressure,
-                            void *user, int use_color_correction)
-{
-	Scene *scene = painter->scene;
-	Brush *brush = painter->brush;
-	int totpaintops = 0;
-
-	if (pressure == 0.0f) {
-		if (painter->lastpressure) // XXX - hack, operator misses
-			pressure = painter->lastpressure;
-		else
-			pressure = 1.0f;    /* zero pressure == not using tablet */
-	}
-	if (painter->firsttouch) {
-		/* paint exactly once on first touch */
-		painter->startpaintpos[0] = pos[0];
-		painter->startpaintpos[1] = pos[1];
-
-		brush_pressure_apply(painter, brush, pressure);
-		if (painter->cache.enabled)
-			brush_painter_refresh_cache(painter, pos, use_color_correction);
-		totpaintops += func(user, painter->cache.ibuf, pos, pos);
-		
-		painter->lasttime = time;
-		painter->firsttouch = 0;
-		painter->lastpaintpos[0] = pos[0];
-		painter->lastpaintpos[1] = pos[1];
-	}
-#if 0
-	else if (painter->brush->flag & BRUSH_AIRBRUSH) {
-		float spacing, step, paintpos[2], dmousepos[2], len;
-		double starttime, curtime = time;
-
-		/* compute brush spacing adapted to brush size */
-		spacing = brush->rate; //radius*brush->spacing*0.01f;
-
-		/* setup starting time, direction vector and accumulated time */
-		starttime = painter->accumtime;
-		sub_v2_v2v2(dmousepos, pos, painter->lastmousepos);
-		len = normalize_v2(dmousepos);
-		painter->accumtime += curtime - painter->lasttime;
-
-		/* do paint op over unpainted time distance */
-		while (painter->accumtime >= spacing) {
-			step = (spacing - starttime) * len;
-			paintpos[0] = painter->lastmousepos[0] + dmousepos[0] * step;
-			paintpos[1] = painter->lastmousepos[1] + dmousepos[1] * step;
-
-			if (painter->cache.enabled)
-				brush_painter_refresh_cache(painter);
-			totpaintops += func(user, painter->cache.ibuf,
-			                    painter->lastpaintpos, paintpos);
-
-			painter->lastpaintpos[0] = paintpos[0];
-			painter->lastpaintpos[1] = paintpos[1];
-			painter->accumtime -= spacing;
-			starttime -= spacing;
-		}
-		
-		painter->lasttime = curtime;
-	}
-#endif
-	else {
-		float startdistance, spacing, step, paintpos[2], dmousepos[2], finalpos[2];
-		float t, len, press;
-		const int radius = BKE_brush_size_get(scene, brush);
-
-		/* compute brush spacing adapted to brush radius, spacing may depend
-		 * on pressure, so update it */
-		brush_pressure_apply(painter, brush, painter->lastpressure);
-		spacing = max_ff(1.0f, radius) * brush->spacing * 0.01f;
-
-		/* setup starting distance, direction vector and accumulated distance */
-		startdistance = painter->accumdistance;
-		sub_v2_v2v2(dmousepos, pos, painter->lastmousepos);
-		len = normalize_v2(dmousepos);
-		painter->accumdistance += len;
-
-		if (brush->flag & BRUSH_SPACE) {
-			/* do paint op over unpainted distance */
-			while ((len > 0.0f) && (painter->accumdistance >= spacing)) {
-				step = spacing - startdistance;
-				paintpos[0] = painter->lastmousepos[0] + dmousepos[0] * step;
-				paintpos[1] = painter->lastmousepos[1] + dmousepos[1] * step;
-
-				t = step / len;
-				press = (1.0f - t) * painter->lastpressure + t * pressure;
-				brush_pressure_apply(painter, brush, press);
-				spacing = max_ff(1.0f, radius) * brush->spacing * 0.01f;
-
-				BKE_brush_jitter_pos(scene, brush, paintpos, finalpos);
-
-				if (painter->cache.enabled)
-					brush_painter_refresh_cache(painter, finalpos, use_color_correction);
-
-				totpaintops +=
-				    func(user, painter->cache.ibuf, painter->lastpaintpos, finalpos);
-
-				painter->lastpaintpos[0] = paintpos[0];
-				painter->lastpaintpos[1] = paintpos[1];
-				painter->accumdistance -= spacing;
-				startdistance -= spacing;
-			}
-		}
-		else {
-			BKE_brush_jitter_pos(scene, brush, pos, finalpos);
-
-			if (painter->cache.enabled)
-				brush_painter_refresh_cache(painter, finalpos, use_color_correction);
-
-			totpaintops += func(user, painter->cache.ibuf, pos, finalpos);
-
-			painter->lastpaintpos[0] = pos[0];
-			painter->lastpaintpos[1] = pos[1];
-			painter->accumdistance = 0;
-		}
-
-		/* do airbrush paint ops, based on the number of paint ops left over
-		 * from regular painting. this is a temporary solution until we have
-		 * accurate time stamps for mouse move events */
-		if (brush->flag & BRUSH_AIRBRUSH) {
-			double curtime = time;
-			double painttime = brush->rate * totpaintops;
-
-			painter->accumtime += curtime - painter->lasttime;
-			if (painter->accumtime <= painttime)
-				painter->accumtime = 0.0;
-			else
-				painter->accumtime -= painttime;
-
-			while (painter->accumtime >= (double)brush->rate) {
-				brush_pressure_apply(painter, brush, pressure);
-
-				BKE_brush_jitter_pos(scene, brush, pos, finalpos);
-
-				if (painter->cache.enabled)
-					brush_painter_refresh_cache(painter, finalpos, use_color_correction);
-
-				totpaintops +=
-				    func(user, painter->cache.ibuf, painter->lastmousepos, finalpos);
-				painter->accumtime -= (double)brush->rate;
-			}
-
-			painter->lasttime = curtime;
-		}
-	}
-
-	painter->lastmousepos[0] = pos[0];
-	painter->lastmousepos[1] = pos[1];
-	painter->lastpressure = pressure;
-
-	brush_alpha_set(scene, brush, painter->startalpha);
-	BKE_brush_size_set(scene, brush, painter->startsize);
-	brush->jitter = painter->startjitter;
-	brush->spacing = painter->startspacing;
-
-	return totpaintops;
-}
-
 /* Uses the brush curve control to find a strength value between 0 and 1 */
 float BKE_brush_curve_strength_clamp(Brush *br, float p, const float len)
 {
@@ -1275,48 +793,6 @@ float BKE_brush_curve_strength(Brush *br, float p, const float len)
 	return curvemapping_evaluateF(br->curve, 0, p);
 }
 
-/* TODO: should probably be unified with BrushPainter stuff? */
-unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side)
-{
-	unsigned int *texcache = NULL;
-	MTex *mtex = &br->mtex;
-	TexResult texres = {0};
-	int hasrgb, ix, iy;
-	int side = half_side * 2;
-	
-	if (mtex->tex) {
-		float x, y, step = 2.0 / side, co[3];
-
-		texcache = MEM_callocN(sizeof(int) * side * side, "Brush texture cache");
-
-		/*do normalized cannonical view coords for texture*/
-		for (y = -1.0, iy = 0; iy < side; iy++, y += step) {
-			for (x = -1.0, ix = 0; ix < side; ix++, x += step) {
-				co[0] = x;
-				co[1] = y;
-				co[2] = 0.0f;
-				
-				/* This is copied from displace modifier code */
-				hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 0, &texres);
-			
-				/* if the texture gave an RGB value, we assume it didn't give a valid
-				 * intensity, so calculate one (formula from do_material_tex).
-				 * if the texture didn't give an RGB value, copy the intensity across
-				 */
-				if (hasrgb & TEX_RGB)
-					texres.tin = rgb_to_grayscale(&texres.tr);
-
-				((char *)texcache)[(iy * side + ix) * 4] =
-				((char *)texcache)[(iy * side + ix) * 4 + 1] =
-				((char *)texcache)[(iy * side + ix) * 4 + 2] =
-				((char *)texcache)[(iy * side + ix) * 4 + 3] = (char)(texres.tin * 255.0f);
-			}
-		}
-	}
-
-	return texcache;
-}
-
 /**** Radial Control ****/
 struct ImBuf *BKE_brush_gen_radial_control_imbuf(Brush *br)
 {
diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index ae72dce1415..7f4ee4fdd55 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -42,6 +42,7 @@ set(SRC
 	paint_cursor.c
 	paint_hide.c
 	paint_image.c
+	paint_2D.c
 	paint_mask.c
 	paint_ops.c
 	paint_stroke.c
diff --git a/source/blender/editors/sculpt_paint/paint_2D.c b/source/blender/editors/sculpt_paint/paint_2D.c
new file mode 100644
index 00000000000..80e189a08e1
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/paint_2D.c
@@ -0,0 +1,562 @@
+/*
+ * ***** 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 blender/editors/sculpt_paint/paint_2D.c
+ *  \ingroup bke
+ */
+//#include 
+#include 
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_brush_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_brush.h"
+#include "BKE_texture.h"
+
+#include "BLI_math.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "RE_shader_ext.h"
+
+ /* Brush Painting for 2D image editor */
+
+typedef struct BrushPainterCache {
+	short enabled;
+
+	int size;           /* size override, if 0 uses 2*BKE_brush_size_get(brush) */
+	short flt;          /* need float imbuf? */
+	short texonly;      /* no alpha, color or fallof, only texture in imbuf */
+
+	int lastsize;
+	float lastalpha;
+	float lastjitter;
+
+	ImBuf *ibuf;
+	ImBuf *texibuf;
+	ImBuf *maskibuf;
+} BrushPainterCache;
+
+struct BrushPainter {
+	Scene *scene;
+	Brush *brush;
+
+	float lastmousepos[2];  /* mouse position of last paint call */
+
+	float accumdistance;    /* accumulated distance of brush since last paint op */
+	float lastpaintpos[2];  /* position of last paint op */
+	float startpaintpos[2]; /* position of first paint */
+
+	double accumtime;       /* accumulated time since last paint op (airbrush) */
+	double lasttime;        /* time of last update */
+
+	float lastpressure;
+
+	short firsttouch;       /* first paint op */
+
+	float startsize;
+	float startalpha;
+	float startjitter;
+	float startspacing;
+
+	BrushPainterCache cache;
+};
+
+BrushPainter *BKE_brush_painter_new(Scene *scene, Brush *brush)
+{
+	BrushPainter *painter = MEM_callocN(sizeof(BrushPainter), "BrushPainter");
+
+	painter->brush = brush;
+	painter->scene = scene;
+	painter->firsttouch = 1;
+	painter->cache.lastsize = -1; /* force ibuf create in refresh */
+
+	painter->startsize = BKE_brush_size_get(scene, brush);
+	painter->startalpha = BKE_brush_alpha_get(scene, brush);
+	painter->startjitter = brush->jitter;
+	painter->startspacing = brush->spacing;
+
+	return painter;
+}
+
+
+static void brush_pressure_apply(BrushPainter *painter, Brush *brush, float pressure)
+{
+	if (BKE_brush_use_alpha_pressure(painter->scene, brush))
+		BKE_brush_alpha_set(painter->scene, brush, max_ff(0.0f, painter->startalpha * pressure));
+	if (BKE_brush_use_size_pressure(painter->scene, brush))
+		BKE_brush_size_set(painter->scene, brush, max_ff(1.0f, painter->startsize * pressure));
+	if (brush->flag & BRUSH_JITTER_PRESSURE)
+		brush->jitter = max_ff(0.0f, painter->startjitter * pressure);
+	if (brush->flag & BRUSH_SPACING_PRESSURE)
+		brush->spacing = max_ff(1.0f, painter->startspacing * (1.5f - pressure));
+}
+
+
+void BKE_brush_painter_require_imbuf(BrushPainter *painter, short flt, short texonly, int size)
+{
+	if ((painter->cache.flt != flt) || (painter->cache.size != size) ||
+	    ((painter->cache.texonly != texonly) && texonly))
+	{
+		if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
+		if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf);
+		painter->cache.ibuf = painter->cache.maskibuf = NULL;
+		painter->cache.lastsize = -1; /* force ibuf create in refresh */
+	}
+
+	if (painter->cache.flt != flt) {
+		if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
+		painter->cache.texibuf = NULL;
+		painter->cache.lastsize = -1; /* force ibuf create in refresh */
+	}
+
+	painter->cache.size = size;
+	painter->cache.flt = flt;
+	painter->cache.texonly = texonly;
+	painter->cache.enabled = 1;
+}
+
+void BKE_brush_painter_free(BrushPainter *painter)
+{
+	Brush *brush = painter->brush;
+
+	BKE_brush_size_set(painter->scene, brush, painter->startsize);
+	BKE_brush_alpha_set(painter->scene, brush, painter->startalpha);
+	brush->jitter = painter->startjitter;
+	brush->spacing = painter->startspacing;
+
+	if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
+	if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
+	if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf);
+	MEM_freeN(painter);
+}
+
+static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf,
+                                     int x, int y, int w, int h, int xt, int yt,
+                                     const float pos[2])
+{
+	Scene *scene = painter->scene;
+	Brush *brush = painter->brush;
+	ImBuf *ibuf, *maskibuf, *texibuf;
+	float *bf, *mf, *tf, *otf = NULL, xoff, yoff, xy[2], rgba[4];
+	unsigned char *b, *m, *t, *ot = NULL;
+	int dotexold, origx = x, origy = y;
+	const int radius = BKE_brush_size_get(painter->scene, brush);
+
+	xoff = -radius + 0.5f;
+	yoff = -radius + 0.5f;
+	xoff += (int)pos[0] - (int)painter->startpaintpos[0];
+	yoff += (int)pos[1] - (int)painter->startpaintpos[1];
+
+	ibuf = painter->cache.ibuf;
+	texibuf = painter->cache.texibuf;
+	maskibuf = painter->cache.maskibuf;
+
+	dotexold = (oldtexibuf != NULL);
+
+	/* not sure if it's actually needed or it's a mistake in coords/sizes
+	 * calculation in brush_painter_fixed_tex_partial_update(), but without this
+	 * limitation memory gets corrupted at fast strokes with quite big spacing (sergey) */
+	w = min_ii(w, ibuf->x);
+	h = min_ii(h, ibuf->y);
+
+	if (painter->cache.flt) {
+		for (; y < h; y++) {
+			bf = ibuf->rect_float + (y * ibuf->x + origx) * 4;
+			tf = texibuf->rect_float + (y * texibuf->x + origx) * 4;
+			mf = maskibuf->rect_float + (y * maskibuf->x + origx) * 4;
+
+			if (dotexold)
+				otf = oldtexibuf->rect_float + ((y - origy + yt) * oldtexibuf->x + xt) * 4;
+
+			for (x = origx; x < w; x++, bf += 4, mf += 4, tf += 4) {
+				if (dotexold) {
+					copy_v3_v3(tf, otf);
+					tf[3] = otf[3];
+					otf += 4;
+				}
+				else {
+					xy[0] = x + xoff;
+					xy[1] = y + yoff;
+
+					BKE_brush_sample_tex(scene, brush, xy, tf, 0);
+				}
+
+				bf[0] = tf[0] * mf[0];
+				bf[1] = tf[1] * mf[1];
+				bf[2] = tf[2] * mf[2];
+				bf[3] = tf[3] * mf[3];
+			}
+		}
+	}
+	else {
+		for (; y < h; y++) {
+			b = (unsigned char *)ibuf->rect + (y * ibuf->x + origx) * 4;
+			t = (unsigned char *)texibuf->rect + (y * texibuf->x + origx) * 4;
+			m = (unsigned char *)maskibuf->rect + (y * maskibuf->x + origx) * 4;
+
+			if (dotexold)
+				ot = (unsigned char *)oldtexibuf->rect + ((y - origy + yt) * oldtexibuf->x + xt) * 4;
+
+			for (x = origx; x < w; x++, b += 4, m += 4, t += 4) {
+				if (dotexold) {
+					t[0] = ot[0];
+					t[1] = ot[1];
+					t[2] = ot[2];
+					t[3] = ot[3];
+					ot += 4;
+				}
+				else {
+					xy[0] = x + xoff;
+					xy[1] = y + yoff;
+
+					BKE_brush_sample_tex(scene, brush, xy, rgba, 0);
+					rgba_float_to_uchar(t, rgba);
+				}
+
+				b[0] = t[0] * m[0] / 255;
+				b[1] = t[1] * m[1] / 255;
+				b[2] = t[2] * m[2] / 255;
+				b[3] = t[3] * m[3] / 255;
+			}
+		}
+	}
+}
+
+static void brush_painter_fixed_tex_partial_update(BrushPainter *painter, const float pos[2])
+{
+	const Scene *scene = painter->scene;
+	Brush *brush = painter->brush;
+	BrushPainterCache *cache = &painter->cache;
+	ImBuf *oldtexibuf, *ibuf;
+	int imbflag, destx, desty, srcx, srcy, w, h, x1, y1, x2, y2;
+	const int diameter = 2 * BKE_brush_size_get(scene, brush);
+
+	imbflag = (cache->flt) ? IB_rectfloat : IB_rect;
+	if (!cache->ibuf)
+		cache->ibuf = IMB_allocImBuf(diameter, diameter, 32, imbflag);
+	ibuf = cache->ibuf;
+
+	oldtexibuf = cache->texibuf;
+	cache->texibuf = IMB_allocImBuf(diameter, diameter, 32, imbflag);
+
+	if (oldtexibuf) {
+		srcx = srcy = 0;
+		destx = (int)painter->lastpaintpos[0] - (int)pos[0];
+		desty = (int)painter->lastpaintpos[1] - (int)pos[1];
+		w = oldtexibuf->x;
+		h = oldtexibuf->y;
+
+		IMB_rectclip(cache->texibuf, oldtexibuf, &destx, &desty, &srcx, &srcy, &w, &h);
+	}
+	else {
+		srcx = srcy = 0;
+		destx = desty = 0;
+		w = h = 0;
+	}
+	
+	x1 = destx;
+	y1 = desty;
+	x2 = destx + w;
+	y2 = desty + h;
+
+	/* blend existing texture in new position */
+	if ((x1 < x2) && (y1 < y2))
+		brush_painter_do_partial(painter, oldtexibuf, x1, y1, x2, y2, srcx, srcy, pos);
+
+	if (oldtexibuf)
+		IMB_freeImBuf(oldtexibuf);
+
+	/* sample texture in new areas */
+	if ((0 < x1) && (0 < ibuf->y))
+		brush_painter_do_partial(painter, NULL, 0, 0, x1, ibuf->y, 0, 0, pos);
+	if ((x2 < ibuf->x) && (0 < ibuf->y))
+		brush_painter_do_partial(painter, NULL, x2, 0, ibuf->x, ibuf->y, 0, 0, pos);
+	if ((x1 < x2) && (0 < y1))
+		brush_painter_do_partial(painter, NULL, x1, 0, x2, y1, 0, 0, pos);
+	if ((x1 < x2) && (y2 < ibuf->y))
+		brush_painter_do_partial(painter, NULL, x1, y2, x2, ibuf->y, 0, 0, pos);
+}
+
+static void brush_painter_refresh_cache(BrushPainter *painter, const float pos[2], int use_color_correction)
+{
+	const Scene *scene = painter->scene;
+	Brush *brush = painter->brush;
+	BrushPainterCache *cache = &painter->cache;
+	MTex *mtex = &brush->mtex;
+	int size;
+	short flt;
+	const int diameter = 2 * BKE_brush_size_get(scene, brush);
+	const float alpha = BKE_brush_alpha_get(scene, brush);
+
+	if (diameter != cache->lastsize ||
+	    alpha != cache->lastalpha ||
+	    brush->jitter != cache->lastjitter)
+	{
+		if (cache->ibuf) {
+			IMB_freeImBuf(cache->ibuf);
+			cache->ibuf = NULL;
+		}
+		if (cache->maskibuf) {
+			IMB_freeImBuf(cache->maskibuf);
+			cache->maskibuf = NULL;
+		}
+
+		flt = cache->flt;
+		size = (cache->size) ? cache->size : diameter;
+
+		if (brush->flag & BRUSH_FIXED_TEX) {
+			BKE_brush_imbuf_new(scene, brush, flt, 3, size, &cache->maskibuf, use_color_correction);
+			brush_painter_fixed_tex_partial_update(painter, pos);
+		}
+		else
+			BKE_brush_imbuf_new(scene, brush, flt, 2, size, &cache->ibuf, use_color_correction);
+
+		cache->lastsize = diameter;
+		cache->lastalpha = alpha;
+		cache->lastjitter = brush->jitter;
+	}
+	else if ((brush->flag & BRUSH_FIXED_TEX) && mtex && mtex->tex) {
+		int dx = (int)painter->lastpaintpos[0] - (int)pos[0];
+		int dy = (int)painter->lastpaintpos[1] - (int)pos[1];
+
+		if ((dx != 0) || (dy != 0))
+			brush_painter_fixed_tex_partial_update(painter, pos);
+	}
+}
+
+void BKE_brush_painter_break_stroke(BrushPainter *painter)
+{
+	painter->firsttouch = 1;
+}
+
+
+int BKE_brush_painter_paint(BrushPainter *painter, BrushFunc func, const float pos[2], double time, float pressure,
+                            void *user, int use_color_correction)
+{
+	Scene *scene = painter->scene;
+	Brush *brush = painter->brush;
+	int totpaintops = 0;
+
+	if (pressure == 0.0f) {
+		if (painter->lastpressure) // XXX - hack, operator misses
+			pressure = painter->lastpressure;
+		else
+			pressure = 1.0f;    /* zero pressure == not using tablet */
+	}
+	if (painter->firsttouch) {
+		/* paint exactly once on first touch */
+		painter->startpaintpos[0] = pos[0];
+		painter->startpaintpos[1] = pos[1];
+
+		brush_pressure_apply(painter, brush, pressure);
+		if (painter->cache.enabled)
+			brush_painter_refresh_cache(painter, pos, use_color_correction);
+		totpaintops += func(user, painter->cache.ibuf, pos, pos);
+		
+		painter->lasttime = time;
+		painter->firsttouch = 0;
+		painter->lastpaintpos[0] = pos[0];
+		painter->lastpaintpos[1] = pos[1];
+	}
+#if 0
+	else if (painter->brush->flag & BRUSH_AIRBRUSH) {
+		float spacing, step, paintpos[2], dmousepos[2], len;
+		double starttime, curtime = time;
+
+		/* compute brush spacing adapted to brush size */
+		spacing = brush->rate; //radius*brush->spacing*0.01f;
+
+		/* setup starting time, direction vector and accumulated time */
+		starttime = painter->accumtime;
+		sub_v2_v2v2(dmousepos, pos, painter->lastmousepos);
+		len = normalize_v2(dmousepos);
+		painter->accumtime += curtime - painter->lasttime;
+
+		/* do paint op over unpainted time distance */
+		while (painter->accumtime >= spacing) {
+			step = (spacing - starttime) * len;
+			paintpos[0] = painter->lastmousepos[0] + dmousepos[0] * step;
+			paintpos[1] = painter->lastmousepos[1] + dmousepos[1] * step;
+
+			if (painter->cache.enabled)
+				brush_painter_refresh_cache(painter);
+			totpaintops += func(user, painter->cache.ibuf,
+			                    painter->lastpaintpos, paintpos);
+
+			painter->lastpaintpos[0] = paintpos[0];
+			painter->lastpaintpos[1] = paintpos[1];
+			painter->accumtime -= spacing;
+			starttime -= spacing;
+		}
+		
+		painter->lasttime = curtime;
+	}
+#endif
+	else {
+		float startdistance, spacing, step, paintpos[2], dmousepos[2], finalpos[2];
+		float t, len, press;
+		const int radius = BKE_brush_size_get(scene, brush);
+
+		/* compute brush spacing adapted to brush radius, spacing may depend
+		 * on pressure, so update it */
+		brush_pressure_apply(painter, brush, painter->lastpressure);
+		spacing = max_ff(1.0f, radius) * brush->spacing * 0.01f;
+
+		/* setup starting distance, direction vector and accumulated distance */
+		startdistance = painter->accumdistance;
+		sub_v2_v2v2(dmousepos, pos, painter->lastmousepos);
+		len = normalize_v2(dmousepos);
+		painter->accumdistance += len;
+
+		if (brush->flag & BRUSH_SPACE) {
+			/* do paint op over unpainted distance */
+			while ((len > 0.0f) && (painter->accumdistance >= spacing)) {
+				step = spacing - startdistance;
+				paintpos[0] = painter->lastmousepos[0] + dmousepos[0] * step;
+				paintpos[1] = painter->lastmousepos[1] + dmousepos[1] * step;
+
+				t = step / len;
+				press = (1.0f - t) * painter->lastpressure + t * pressure;
+				brush_pressure_apply(painter, brush, press);
+				spacing = max_ff(1.0f, radius) * brush->spacing * 0.01f;
+
+				BKE_brush_jitter_pos(scene, brush, paintpos, finalpos);
+
+				if (painter->cache.enabled)
+					brush_painter_refresh_cache(painter, finalpos, use_color_correction);
+
+				totpaintops +=
+				    func(user, painter->cache.ibuf, painter->lastpaintpos, finalpos);
+
+				painter->lastpaintpos[0] = paintpos[0];
+				painter->lastpaintpos[1] = paintpos[1];
+				painter->accumdistance -= spacing;
+				startdistance -= spacing;
+			}
+		}
+		else {
+			BKE_brush_jitter_pos(scene, brush, pos, finalpos);
+
+			if (painter->cache.enabled)
+				brush_painter_refresh_cache(painter, finalpos, use_color_correction);
+
+			totpaintops += func(user, painter->cache.ibuf, pos, finalpos);
+
+			painter->lastpaintpos[0] = pos[0];
+			painter->lastpaintpos[1] = pos[1];
+			painter->accumdistance = 0;
+		}
+
+		/* do airbrush paint ops, based on the number of paint ops left over
+		 * from regular painting. this is a temporary solution until we have
+		 * accurate time stamps for mouse move events */
+		if (brush->flag & BRUSH_AIRBRUSH) {
+			double curtime = time;
+			double painttime = brush->rate * totpaintops;
+
+			painter->accumtime += curtime - painter->lasttime;
+			if (painter->accumtime <= painttime)
+				painter->accumtime = 0.0;
+			else
+				painter->accumtime -= painttime;
+
+			while (painter->accumtime >= (double)brush->rate) {
+				brush_pressure_apply(painter, brush, pressure);
+
+				BKE_brush_jitter_pos(scene, brush, pos, finalpos);
+
+				if (painter->cache.enabled)
+					brush_painter_refresh_cache(painter, finalpos, use_color_correction);
+
+				totpaintops +=
+				    func(user, painter->cache.ibuf, painter->lastmousepos, finalpos);
+				painter->accumtime -= (double)brush->rate;
+			}
+
+			painter->lasttime = curtime;
+		}
+	}
+
+	painter->lastmousepos[0] = pos[0];
+	painter->lastmousepos[1] = pos[1];
+	painter->lastpressure = pressure;
+
+	BKE_brush_alpha_set(scene, brush, painter->startalpha);
+	BKE_brush_size_set(scene, brush, painter->startsize);
+	brush->jitter = painter->startjitter;
+	brush->spacing = painter->startspacing;
+
+	return totpaintops;
+}
+
+
+/* TODO: should probably be unified with BrushPainter stuff? */
+unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side)
+{
+	unsigned int *texcache = NULL;
+	MTex *mtex = &br->mtex;
+	TexResult texres = {0};
+	int hasrgb, ix, iy;
+	int side = half_side * 2;
+	
+	if (mtex->tex) {
+		float x, y, step = 2.0 / side, co[3];
+
+		texcache = MEM_callocN(sizeof(int) * side * side, "Brush texture cache");
+
+		/*do normalized cannonical view coords for texture*/
+		for (y = -1.0, iy = 0; iy < side; iy++, y += step) {
+			for (x = -1.0, ix = 0; ix < side; ix++, x += step) {
+				co[0] = x;
+				co[1] = y;
+				co[2] = 0.0f;
+				
+				/* This is copied from displace modifier code */
+				hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 0, &texres);
+			
+				/* if the texture gave an RGB value, we assume it didn't give a valid
+				 * intensity, so calculate one (formula from do_material_tex).
+				 * if the texture didn't give an RGB value, copy the intensity across
+				 */
+				if (hasrgb & TEX_RGB)
+					texres.tin = rgb_to_grayscale(&texres.tr);
+
+				((char *)texcache)[(iy * side + ix) * 4] =
+				((char *)texcache)[(iy * side + ix) * 4 + 1] =
+				((char *)texcache)[(iy * side + ix) * 4 + 2] =
+				((char *)texcache)[(iy * side + ix) * 4 + 3] = (char)(texres.tin * 255.0f);
+			}
+		}
+	}
+
+	return texcache;
+}
+
-- 
cgit v1.2.3


From 7085387defb2e9ae90bdf3ed625f056d616fac6b Mon Sep 17 00:00:00 2001
From: Antony Riakiotakis 
Date: Tue, 1 Jan 2013 21:32:17 +0000
Subject: rename paint_2D to paint_image_2D. Catering for possible name
 conflicts with other 2D paint systems.

---
 source/blender/editors/sculpt_paint/CMakeLists.txt |   2 +-
 source/blender/editors/sculpt_paint/paint_2D.c     | 562 ---------------------
 .../blender/editors/sculpt_paint/paint_image_2D.c  | 562 +++++++++++++++++++++
 3 files changed, 563 insertions(+), 563 deletions(-)
 delete mode 100644 source/blender/editors/sculpt_paint/paint_2D.c
 create mode 100644 source/blender/editors/sculpt_paint/paint_image_2D.c

(limited to 'source')

diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index 7f4ee4fdd55..7a74385ea77 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -42,7 +42,7 @@ set(SRC
 	paint_cursor.c
 	paint_hide.c
 	paint_image.c
-	paint_2D.c
+	paint_image_2D.c
 	paint_mask.c
 	paint_ops.c
 	paint_stroke.c
diff --git a/source/blender/editors/sculpt_paint/paint_2D.c b/source/blender/editors/sculpt_paint/paint_2D.c
deleted file mode 100644
index 80e189a08e1..00000000000
--- a/source/blender/editors/sculpt_paint/paint_2D.c
+++ /dev/null
@@ -1,562 +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 blender/editors/sculpt_paint/paint_2D.c
- *  \ingroup bke
- */
-//#include 
-#include 
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_brush_types.h"
-#include "DNA_scene_types.h"
-
-#include "BKE_brush.h"
-#include "BKE_texture.h"
-
-#include "BLI_math.h"
-
-#include "IMB_imbuf.h"
-#include "IMB_imbuf_types.h"
-
-#include "RE_shader_ext.h"
-
- /* Brush Painting for 2D image editor */
-
-typedef struct BrushPainterCache {
-	short enabled;
-
-	int size;           /* size override, if 0 uses 2*BKE_brush_size_get(brush) */
-	short flt;          /* need float imbuf? */
-	short texonly;      /* no alpha, color or fallof, only texture in imbuf */
-
-	int lastsize;
-	float lastalpha;
-	float lastjitter;
-
-	ImBuf *ibuf;
-	ImBuf *texibuf;
-	ImBuf *maskibuf;
-} BrushPainterCache;
-
-struct BrushPainter {
-	Scene *scene;
-	Brush *brush;
-
-	float lastmousepos[2];  /* mouse position of last paint call */
-
-	float accumdistance;    /* accumulated distance of brush since last paint op */
-	float lastpaintpos[2];  /* position of last paint op */
-	float startpaintpos[2]; /* position of first paint */
-
-	double accumtime;       /* accumulated time since last paint op (airbrush) */
-	double lasttime;        /* time of last update */
-
-	float lastpressure;
-
-	short firsttouch;       /* first paint op */
-
-	float startsize;
-	float startalpha;
-	float startjitter;
-	float startspacing;
-
-	BrushPainterCache cache;
-};
-
-BrushPainter *BKE_brush_painter_new(Scene *scene, Brush *brush)
-{
-	BrushPainter *painter = MEM_callocN(sizeof(BrushPainter), "BrushPainter");
-
-	painter->brush = brush;
-	painter->scene = scene;
-	painter->firsttouch = 1;
-	painter->cache.lastsize = -1; /* force ibuf create in refresh */
-
-	painter->startsize = BKE_brush_size_get(scene, brush);
-	painter->startalpha = BKE_brush_alpha_get(scene, brush);
-	painter->startjitter = brush->jitter;
-	painter->startspacing = brush->spacing;
-
-	return painter;
-}
-
-
-static void brush_pressure_apply(BrushPainter *painter, Brush *brush, float pressure)
-{
-	if (BKE_brush_use_alpha_pressure(painter->scene, brush))
-		BKE_brush_alpha_set(painter->scene, brush, max_ff(0.0f, painter->startalpha * pressure));
-	if (BKE_brush_use_size_pressure(painter->scene, brush))
-		BKE_brush_size_set(painter->scene, brush, max_ff(1.0f, painter->startsize * pressure));
-	if (brush->flag & BRUSH_JITTER_PRESSURE)
-		brush->jitter = max_ff(0.0f, painter->startjitter * pressure);
-	if (brush->flag & BRUSH_SPACING_PRESSURE)
-		brush->spacing = max_ff(1.0f, painter->startspacing * (1.5f - pressure));
-}
-
-
-void BKE_brush_painter_require_imbuf(BrushPainter *painter, short flt, short texonly, int size)
-{
-	if ((painter->cache.flt != flt) || (painter->cache.size != size) ||
-	    ((painter->cache.texonly != texonly) && texonly))
-	{
-		if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
-		if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf);
-		painter->cache.ibuf = painter->cache.maskibuf = NULL;
-		painter->cache.lastsize = -1; /* force ibuf create in refresh */
-	}
-
-	if (painter->cache.flt != flt) {
-		if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
-		painter->cache.texibuf = NULL;
-		painter->cache.lastsize = -1; /* force ibuf create in refresh */
-	}
-
-	painter->cache.size = size;
-	painter->cache.flt = flt;
-	painter->cache.texonly = texonly;
-	painter->cache.enabled = 1;
-}
-
-void BKE_brush_painter_free(BrushPainter *painter)
-{
-	Brush *brush = painter->brush;
-
-	BKE_brush_size_set(painter->scene, brush, painter->startsize);
-	BKE_brush_alpha_set(painter->scene, brush, painter->startalpha);
-	brush->jitter = painter->startjitter;
-	brush->spacing = painter->startspacing;
-
-	if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
-	if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
-	if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf);
-	MEM_freeN(painter);
-}
-
-static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf,
-                                     int x, int y, int w, int h, int xt, int yt,
-                                     const float pos[2])
-{
-	Scene *scene = painter->scene;
-	Brush *brush = painter->brush;
-	ImBuf *ibuf, *maskibuf, *texibuf;
-	float *bf, *mf, *tf, *otf = NULL, xoff, yoff, xy[2], rgba[4];
-	unsigned char *b, *m, *t, *ot = NULL;
-	int dotexold, origx = x, origy = y;
-	const int radius = BKE_brush_size_get(painter->scene, brush);
-
-	xoff = -radius + 0.5f;
-	yoff = -radius + 0.5f;
-	xoff += (int)pos[0] - (int)painter->startpaintpos[0];
-	yoff += (int)pos[1] - (int)painter->startpaintpos[1];
-
-	ibuf = painter->cache.ibuf;
-	texibuf = painter->cache.texibuf;
-	maskibuf = painter->cache.maskibuf;
-
-	dotexold = (oldtexibuf != NULL);
-
-	/* not sure if it's actually needed or it's a mistake in coords/sizes
-	 * calculation in brush_painter_fixed_tex_partial_update(), but without this
-	 * limitation memory gets corrupted at fast strokes with quite big spacing (sergey) */
-	w = min_ii(w, ibuf->x);
-	h = min_ii(h, ibuf->y);
-
-	if (painter->cache.flt) {
-		for (; y < h; y++) {
-			bf = ibuf->rect_float + (y * ibuf->x + origx) * 4;
-			tf = texibuf->rect_float + (y * texibuf->x + origx) * 4;
-			mf = maskibuf->rect_float + (y * maskibuf->x + origx) * 4;
-
-			if (dotexold)
-				otf = oldtexibuf->rect_float + ((y - origy + yt) * oldtexibuf->x + xt) * 4;
-
-			for (x = origx; x < w; x++, bf += 4, mf += 4, tf += 4) {
-				if (dotexold) {
-					copy_v3_v3(tf, otf);
-					tf[3] = otf[3];
-					otf += 4;
-				}
-				else {
-					xy[0] = x + xoff;
-					xy[1] = y + yoff;
-
-					BKE_brush_sample_tex(scene, brush, xy, tf, 0);
-				}
-
-				bf[0] = tf[0] * mf[0];
-				bf[1] = tf[1] * mf[1];
-				bf[2] = tf[2] * mf[2];
-				bf[3] = tf[3] * mf[3];
-			}
-		}
-	}
-	else {
-		for (; y < h; y++) {
-			b = (unsigned char *)ibuf->rect + (y * ibuf->x + origx) * 4;
-			t = (unsigned char *)texibuf->rect + (y * texibuf->x + origx) * 4;
-			m = (unsigned char *)maskibuf->rect + (y * maskibuf->x + origx) * 4;
-
-			if (dotexold)
-				ot = (unsigned char *)oldtexibuf->rect + ((y - origy + yt) * oldtexibuf->x + xt) * 4;
-
-			for (x = origx; x < w; x++, b += 4, m += 4, t += 4) {
-				if (dotexold) {
-					t[0] = ot[0];
-					t[1] = ot[1];
-					t[2] = ot[2];
-					t[3] = ot[3];
-					ot += 4;
-				}
-				else {
-					xy[0] = x + xoff;
-					xy[1] = y + yoff;
-
-					BKE_brush_sample_tex(scene, brush, xy, rgba, 0);
-					rgba_float_to_uchar(t, rgba);
-				}
-
-				b[0] = t[0] * m[0] / 255;
-				b[1] = t[1] * m[1] / 255;
-				b[2] = t[2] * m[2] / 255;
-				b[3] = t[3] * m[3] / 255;
-			}
-		}
-	}
-}
-
-static void brush_painter_fixed_tex_partial_update(BrushPainter *painter, const float pos[2])
-{
-	const Scene *scene = painter->scene;
-	Brush *brush = painter->brush;
-	BrushPainterCache *cache = &painter->cache;
-	ImBuf *oldtexibuf, *ibuf;
-	int imbflag, destx, desty, srcx, srcy, w, h, x1, y1, x2, y2;
-	const int diameter = 2 * BKE_brush_size_get(scene, brush);
-
-	imbflag = (cache->flt) ? IB_rectfloat : IB_rect;
-	if (!cache->ibuf)
-		cache->ibuf = IMB_allocImBuf(diameter, diameter, 32, imbflag);
-	ibuf = cache->ibuf;
-
-	oldtexibuf = cache->texibuf;
-	cache->texibuf = IMB_allocImBuf(diameter, diameter, 32, imbflag);
-
-	if (oldtexibuf) {
-		srcx = srcy = 0;
-		destx = (int)painter->lastpaintpos[0] - (int)pos[0];
-		desty = (int)painter->lastpaintpos[1] - (int)pos[1];
-		w = oldtexibuf->x;
-		h = oldtexibuf->y;
-
-		IMB_rectclip(cache->texibuf, oldtexibuf, &destx, &desty, &srcx, &srcy, &w, &h);
-	}
-	else {
-		srcx = srcy = 0;
-		destx = desty = 0;
-		w = h = 0;
-	}
-	
-	x1 = destx;
-	y1 = desty;
-	x2 = destx + w;
-	y2 = desty + h;
-
-	/* blend existing texture in new position */
-	if ((x1 < x2) && (y1 < y2))
-		brush_painter_do_partial(painter, oldtexibuf, x1, y1, x2, y2, srcx, srcy, pos);
-
-	if (oldtexibuf)
-		IMB_freeImBuf(oldtexibuf);
-
-	/* sample texture in new areas */
-	if ((0 < x1) && (0 < ibuf->y))
-		brush_painter_do_partial(painter, NULL, 0, 0, x1, ibuf->y, 0, 0, pos);
-	if ((x2 < ibuf->x) && (0 < ibuf->y))
-		brush_painter_do_partial(painter, NULL, x2, 0, ibuf->x, ibuf->y, 0, 0, pos);
-	if ((x1 < x2) && (0 < y1))
-		brush_painter_do_partial(painter, NULL, x1, 0, x2, y1, 0, 0, pos);
-	if ((x1 < x2) && (y2 < ibuf->y))
-		brush_painter_do_partial(painter, NULL, x1, y2, x2, ibuf->y, 0, 0, pos);
-}
-
-static void brush_painter_refresh_cache(BrushPainter *painter, const float pos[2], int use_color_correction)
-{
-	const Scene *scene = painter->scene;
-	Brush *brush = painter->brush;
-	BrushPainterCache *cache = &painter->cache;
-	MTex *mtex = &brush->mtex;
-	int size;
-	short flt;
-	const int diameter = 2 * BKE_brush_size_get(scene, brush);
-	const float alpha = BKE_brush_alpha_get(scene, brush);
-
-	if (diameter != cache->lastsize ||
-	    alpha != cache->lastalpha ||
-	    brush->jitter != cache->lastjitter)
-	{
-		if (cache->ibuf) {
-			IMB_freeImBuf(cache->ibuf);
-			cache->ibuf = NULL;
-		}
-		if (cache->maskibuf) {
-			IMB_freeImBuf(cache->maskibuf);
-			cache->maskibuf = NULL;
-		}
-
-		flt = cache->flt;
-		size = (cache->size) ? cache->size : diameter;
-
-		if (brush->flag & BRUSH_FIXED_TEX) {
-			BKE_brush_imbuf_new(scene, brush, flt, 3, size, &cache->maskibuf, use_color_correction);
-			brush_painter_fixed_tex_partial_update(painter, pos);
-		}
-		else
-			BKE_brush_imbuf_new(scene, brush, flt, 2, size, &cache->ibuf, use_color_correction);
-
-		cache->lastsize = diameter;
-		cache->lastalpha = alpha;
-		cache->lastjitter = brush->jitter;
-	}
-	else if ((brush->flag & BRUSH_FIXED_TEX) && mtex && mtex->tex) {
-		int dx = (int)painter->lastpaintpos[0] - (int)pos[0];
-		int dy = (int)painter->lastpaintpos[1] - (int)pos[1];
-
-		if ((dx != 0) || (dy != 0))
-			brush_painter_fixed_tex_partial_update(painter, pos);
-	}
-}
-
-void BKE_brush_painter_break_stroke(BrushPainter *painter)
-{
-	painter->firsttouch = 1;
-}
-
-
-int BKE_brush_painter_paint(BrushPainter *painter, BrushFunc func, const float pos[2], double time, float pressure,
-                            void *user, int use_color_correction)
-{
-	Scene *scene = painter->scene;
-	Brush *brush = painter->brush;
-	int totpaintops = 0;
-
-	if (pressure == 0.0f) {
-		if (painter->lastpressure) // XXX - hack, operator misses
-			pressure = painter->lastpressure;
-		else
-			pressure = 1.0f;    /* zero pressure == not using tablet */
-	}
-	if (painter->firsttouch) {
-		/* paint exactly once on first touch */
-		painter->startpaintpos[0] = pos[0];
-		painter->startpaintpos[1] = pos[1];
-
-		brush_pressure_apply(painter, brush, pressure);
-		if (painter->cache.enabled)
-			brush_painter_refresh_cache(painter, pos, use_color_correction);
-		totpaintops += func(user, painter->cache.ibuf, pos, pos);
-		
-		painter->lasttime = time;
-		painter->firsttouch = 0;
-		painter->lastpaintpos[0] = pos[0];
-		painter->lastpaintpos[1] = pos[1];
-	}
-#if 0
-	else if (painter->brush->flag & BRUSH_AIRBRUSH) {
-		float spacing, step, paintpos[2], dmousepos[2], len;
-		double starttime, curtime = time;
-
-		/* compute brush spacing adapted to brush size */
-		spacing = brush->rate; //radius*brush->spacing*0.01f;
-
-		/* setup starting time, direction vector and accumulated time */
-		starttime = painter->accumtime;
-		sub_v2_v2v2(dmousepos, pos, painter->lastmousepos);
-		len = normalize_v2(dmousepos);
-		painter->accumtime += curtime - painter->lasttime;
-
-		/* do paint op over unpainted time distance */
-		while (painter->accumtime >= spacing) {
-			step = (spacing - starttime) * len;
-			paintpos[0] = painter->lastmousepos[0] + dmousepos[0] * step;
-			paintpos[1] = painter->lastmousepos[1] + dmousepos[1] * step;
-
-			if (painter->cache.enabled)
-				brush_painter_refresh_cache(painter);
-			totpaintops += func(user, painter->cache.ibuf,
-			                    painter->lastpaintpos, paintpos);
-
-			painter->lastpaintpos[0] = paintpos[0];
-			painter->lastpaintpos[1] = paintpos[1];
-			painter->accumtime -= spacing;
-			starttime -= spacing;
-		}
-		
-		painter->lasttime = curtime;
-	}
-#endif
-	else {
-		float startdistance, spacing, step, paintpos[2], dmousepos[2], finalpos[2];
-		float t, len, press;
-		const int radius = BKE_brush_size_get(scene, brush);
-
-		/* compute brush spacing adapted to brush radius, spacing may depend
-		 * on pressure, so update it */
-		brush_pressure_apply(painter, brush, painter->lastpressure);
-		spacing = max_ff(1.0f, radius) * brush->spacing * 0.01f;
-
-		/* setup starting distance, direction vector and accumulated distance */
-		startdistance = painter->accumdistance;
-		sub_v2_v2v2(dmousepos, pos, painter->lastmousepos);
-		len = normalize_v2(dmousepos);
-		painter->accumdistance += len;
-
-		if (brush->flag & BRUSH_SPACE) {
-			/* do paint op over unpainted distance */
-			while ((len > 0.0f) && (painter->accumdistance >= spacing)) {
-				step = spacing - startdistance;
-				paintpos[0] = painter->lastmousepos[0] + dmousepos[0] * step;
-				paintpos[1] = painter->lastmousepos[1] + dmousepos[1] * step;
-
-				t = step / len;
-				press = (1.0f - t) * painter->lastpressure + t * pressure;
-				brush_pressure_apply(painter, brush, press);
-				spacing = max_ff(1.0f, radius) * brush->spacing * 0.01f;
-
-				BKE_brush_jitter_pos(scene, brush, paintpos, finalpos);
-
-				if (painter->cache.enabled)
-					brush_painter_refresh_cache(painter, finalpos, use_color_correction);
-
-				totpaintops +=
-				    func(user, painter->cache.ibuf, painter->lastpaintpos, finalpos);
-
-				painter->lastpaintpos[0] = paintpos[0];
-				painter->lastpaintpos[1] = paintpos[1];
-				painter->accumdistance -= spacing;
-				startdistance -= spacing;
-			}
-		}
-		else {
-			BKE_brush_jitter_pos(scene, brush, pos, finalpos);
-
-			if (painter->cache.enabled)
-				brush_painter_refresh_cache(painter, finalpos, use_color_correction);
-
-			totpaintops += func(user, painter->cache.ibuf, pos, finalpos);
-
-			painter->lastpaintpos[0] = pos[0];
-			painter->lastpaintpos[1] = pos[1];
-			painter->accumdistance = 0;
-		}
-
-		/* do airbrush paint ops, based on the number of paint ops left over
-		 * from regular painting. this is a temporary solution until we have
-		 * accurate time stamps for mouse move events */
-		if (brush->flag & BRUSH_AIRBRUSH) {
-			double curtime = time;
-			double painttime = brush->rate * totpaintops;
-
-			painter->accumtime += curtime - painter->lasttime;
-			if (painter->accumtime <= painttime)
-				painter->accumtime = 0.0;
-			else
-				painter->accumtime -= painttime;
-
-			while (painter->accumtime >= (double)brush->rate) {
-				brush_pressure_apply(painter, brush, pressure);
-
-				BKE_brush_jitter_pos(scene, brush, pos, finalpos);
-
-				if (painter->cache.enabled)
-					brush_painter_refresh_cache(painter, finalpos, use_color_correction);
-
-				totpaintops +=
-				    func(user, painter->cache.ibuf, painter->lastmousepos, finalpos);
-				painter->accumtime -= (double)brush->rate;
-			}
-
-			painter->lasttime = curtime;
-		}
-	}
-
-	painter->lastmousepos[0] = pos[0];
-	painter->lastmousepos[1] = pos[1];
-	painter->lastpressure = pressure;
-
-	BKE_brush_alpha_set(scene, brush, painter->startalpha);
-	BKE_brush_size_set(scene, brush, painter->startsize);
-	brush->jitter = painter->startjitter;
-	brush->spacing = painter->startspacing;
-
-	return totpaintops;
-}
-
-
-/* TODO: should probably be unified with BrushPainter stuff? */
-unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side)
-{
-	unsigned int *texcache = NULL;
-	MTex *mtex = &br->mtex;
-	TexResult texres = {0};
-	int hasrgb, ix, iy;
-	int side = half_side * 2;
-	
-	if (mtex->tex) {
-		float x, y, step = 2.0 / side, co[3];
-
-		texcache = MEM_callocN(sizeof(int) * side * side, "Brush texture cache");
-
-		/*do normalized cannonical view coords for texture*/
-		for (y = -1.0, iy = 0; iy < side; iy++, y += step) {
-			for (x = -1.0, ix = 0; ix < side; ix++, x += step) {
-				co[0] = x;
-				co[1] = y;
-				co[2] = 0.0f;
-				
-				/* This is copied from displace modifier code */
-				hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 0, &texres);
-			
-				/* if the texture gave an RGB value, we assume it didn't give a valid
-				 * intensity, so calculate one (formula from do_material_tex).
-				 * if the texture didn't give an RGB value, copy the intensity across
-				 */
-				if (hasrgb & TEX_RGB)
-					texres.tin = rgb_to_grayscale(&texres.tr);
-
-				((char *)texcache)[(iy * side + ix) * 4] =
-				((char *)texcache)[(iy * side + ix) * 4 + 1] =
-				((char *)texcache)[(iy * side + ix) * 4 + 2] =
-				((char *)texcache)[(iy * side + ix) * 4 + 3] = (char)(texres.tin * 255.0f);
-			}
-		}
-	}
-
-	return texcache;
-}
-
diff --git a/source/blender/editors/sculpt_paint/paint_image_2D.c b/source/blender/editors/sculpt_paint/paint_image_2D.c
new file mode 100644
index 00000000000..80e189a08e1
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/paint_image_2D.c
@@ -0,0 +1,562 @@
+/*
+ * ***** 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 blender/editors/sculpt_paint/paint_2D.c
+ *  \ingroup bke
+ */
+//#include 
+#include 
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_brush_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_brush.h"
+#include "BKE_texture.h"
+
+#include "BLI_math.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "RE_shader_ext.h"
+
+ /* Brush Painting for 2D image editor */
+
+typedef struct BrushPainterCache {
+	short enabled;
+
+	int size;           /* size override, if 0 uses 2*BKE_brush_size_get(brush) */
+	short flt;          /* need float imbuf? */
+	short texonly;      /* no alpha, color or fallof, only texture in imbuf */
+
+	int lastsize;
+	float lastalpha;
+	float lastjitter;
+
+	ImBuf *ibuf;
+	ImBuf *texibuf;
+	ImBuf *maskibuf;
+} BrushPainterCache;
+
+struct BrushPainter {
+	Scene *scene;
+	Brush *brush;
+
+	float lastmousepos[2];  /* mouse position of last paint call */
+
+	float accumdistance;    /* accumulated distance of brush since last paint op */
+	float lastpaintpos[2];  /* position of last paint op */
+	float startpaintpos[2]; /* position of first paint */
+
+	double accumtime;       /* accumulated time since last paint op (airbrush) */
+	double lasttime;        /* time of last update */
+
+	float lastpressure;
+
+	short firsttouch;       /* first paint op */
+
+	float startsize;
+	float startalpha;
+	float startjitter;
+	float startspacing;
+
+	BrushPainterCache cache;
+};
+
+BrushPainter *BKE_brush_painter_new(Scene *scene, Brush *brush)
+{
+	BrushPainter *painter = MEM_callocN(sizeof(BrushPainter), "BrushPainter");
+
+	painter->brush = brush;
+	painter->scene = scene;
+	painter->firsttouch = 1;
+	painter->cache.lastsize = -1; /* force ibuf create in refresh */
+
+	painter->startsize = BKE_brush_size_get(scene, brush);
+	painter->startalpha = BKE_brush_alpha_get(scene, brush);
+	painter->startjitter = brush->jitter;
+	painter->startspacing = brush->spacing;
+
+	return painter;
+}
+
+
+static void brush_pressure_apply(BrushPainter *painter, Brush *brush, float pressure)
+{
+	if (BKE_brush_use_alpha_pressure(painter->scene, brush))
+		BKE_brush_alpha_set(painter->scene, brush, max_ff(0.0f, painter->startalpha * pressure));
+	if (BKE_brush_use_size_pressure(painter->scene, brush))
+		BKE_brush_size_set(painter->scene, brush, max_ff(1.0f, painter->startsize * pressure));
+	if (brush->flag & BRUSH_JITTER_PRESSURE)
+		brush->jitter = max_ff(0.0f, painter->startjitter * pressure);
+	if (brush->flag & BRUSH_SPACING_PRESSURE)
+		brush->spacing = max_ff(1.0f, painter->startspacing * (1.5f - pressure));
+}
+
+
+void BKE_brush_painter_require_imbuf(BrushPainter *painter, short flt, short texonly, int size)
+{
+	if ((painter->cache.flt != flt) || (painter->cache.size != size) ||
+	    ((painter->cache.texonly != texonly) && texonly))
+	{
+		if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
+		if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf);
+		painter->cache.ibuf = painter->cache.maskibuf = NULL;
+		painter->cache.lastsize = -1; /* force ibuf create in refresh */
+	}
+
+	if (painter->cache.flt != flt) {
+		if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
+		painter->cache.texibuf = NULL;
+		painter->cache.lastsize = -1; /* force ibuf create in refresh */
+	}
+
+	painter->cache.size = size;
+	painter->cache.flt = flt;
+	painter->cache.texonly = texonly;
+	painter->cache.enabled = 1;
+}
+
+void BKE_brush_painter_free(BrushPainter *painter)
+{
+	Brush *brush = painter->brush;
+
+	BKE_brush_size_set(painter->scene, brush, painter->startsize);
+	BKE_brush_alpha_set(painter->scene, brush, painter->startalpha);
+	brush->jitter = painter->startjitter;
+	brush->spacing = painter->startspacing;
+
+	if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
+	if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
+	if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf);
+	MEM_freeN(painter);
+}
+
+static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf,
+                                     int x, int y, int w, int h, int xt, int yt,
+                                     const float pos[2])
+{
+	Scene *scene = painter->scene;
+	Brush *brush = painter->brush;
+	ImBuf *ibuf, *maskibuf, *texibuf;
+	float *bf, *mf, *tf, *otf = NULL, xoff, yoff, xy[2], rgba[4];
+	unsigned char *b, *m, *t, *ot = NULL;
+	int dotexold, origx = x, origy = y;
+	const int radius = BKE_brush_size_get(painter->scene, brush);
+
+	xoff = -radius + 0.5f;
+	yoff = -radius + 0.5f;
+	xoff += (int)pos[0] - (int)painter->startpaintpos[0];
+	yoff += (int)pos[1] - (int)painter->startpaintpos[1];
+
+	ibuf = painter->cache.ibuf;
+	texibuf = painter->cache.texibuf;
+	maskibuf = painter->cache.maskibuf;
+
+	dotexold = (oldtexibuf != NULL);
+
+	/* not sure if it's actually needed or it's a mistake in coords/sizes
+	 * calculation in brush_painter_fixed_tex_partial_update(), but without this
+	 * limitation memory gets corrupted at fast strokes with quite big spacing (sergey) */
+	w = min_ii(w, ibuf->x);
+	h = min_ii(h, ibuf->y);
+
+	if (painter->cache.flt) {
+		for (; y < h; y++) {
+			bf = ibuf->rect_float + (y * ibuf->x + origx) * 4;
+			tf = texibuf->rect_float + (y * texibuf->x + origx) * 4;
+			mf = maskibuf->rect_float + (y * maskibuf->x + origx) * 4;
+
+			if (dotexold)
+				otf = oldtexibuf->rect_float + ((y - origy + yt) * oldtexibuf->x + xt) * 4;
+
+			for (x = origx; x < w; x++, bf += 4, mf += 4, tf += 4) {
+				if (dotexold) {
+					copy_v3_v3(tf, otf);
+					tf[3] = otf[3];
+					otf += 4;
+				}
+				else {
+					xy[0] = x + xoff;
+					xy[1] = y + yoff;
+
+					BKE_brush_sample_tex(scene, brush, xy, tf, 0);
+				}
+
+				bf[0] = tf[0] * mf[0];
+				bf[1] = tf[1] * mf[1];
+				bf[2] = tf[2] * mf[2];
+				bf[3] = tf[3] * mf[3];
+			}
+		}
+	}
+	else {
+		for (; y < h; y++) {
+			b = (unsigned char *)ibuf->rect + (y * ibuf->x + origx) * 4;
+			t = (unsigned char *)texibuf->rect + (y * texibuf->x + origx) * 4;
+			m = (unsigned char *)maskibuf->rect + (y * maskibuf->x + origx) * 4;
+
+			if (dotexold)
+				ot = (unsigned char *)oldtexibuf->rect + ((y - origy + yt) * oldtexibuf->x + xt) * 4;
+
+			for (x = origx; x < w; x++, b += 4, m += 4, t += 4) {
+				if (dotexold) {
+					t[0] = ot[0];
+					t[1] = ot[1];
+					t[2] = ot[2];
+					t[3] = ot[3];
+					ot += 4;
+				}
+				else {
+					xy[0] = x + xoff;
+					xy[1] = y + yoff;
+
+					BKE_brush_sample_tex(scene, brush, xy, rgba, 0);
+					rgba_float_to_uchar(t, rgba);
+				}
+
+				b[0] = t[0] * m[0] / 255;
+				b[1] = t[1] * m[1] / 255;
+				b[2] = t[2] * m[2] / 255;
+				b[3] = t[3] * m[3] / 255;
+			}
+		}
+	}
+}
+
+static void brush_painter_fixed_tex_partial_update(BrushPainter *painter, const float pos[2])
+{
+	const Scene *scene = painter->scene;
+	Brush *brush = painter->brush;
+	BrushPainterCache *cache = &painter->cache;
+	ImBuf *oldtexibuf, *ibuf;
+	int imbflag, destx, desty, srcx, srcy, w, h, x1, y1, x2, y2;
+	const int diameter = 2 * BKE_brush_size_get(scene, brush);
+
+	imbflag = (cache->flt) ? IB_rectfloat : IB_rect;
+	if (!cache->ibuf)
+		cache->ibuf = IMB_allocImBuf(diameter, diameter, 32, imbflag);
+	ibuf = cache->ibuf;
+
+	oldtexibuf = cache->texibuf;
+	cache->texibuf = IMB_allocImBuf(diameter, diameter, 32, imbflag);
+
+	if (oldtexibuf) {
+		srcx = srcy = 0;
+		destx = (int)painter->lastpaintpos[0] - (int)pos[0];
+		desty = (int)painter->lastpaintpos[1] - (int)pos[1];
+		w = oldtexibuf->x;
+		h = oldtexibuf->y;
+
+		IMB_rectclip(cache->texibuf, oldtexibuf, &destx, &desty, &srcx, &srcy, &w, &h);
+	}
+	else {
+		srcx = srcy = 0;
+		destx = desty = 0;
+		w = h = 0;
+	}
+	
+	x1 = destx;
+	y1 = desty;
+	x2 = destx + w;
+	y2 = desty + h;
+
+	/* blend existing texture in new position */
+	if ((x1 < x2) && (y1 < y2))
+		brush_painter_do_partial(painter, oldtexibuf, x1, y1, x2, y2, srcx, srcy, pos);
+
+	if (oldtexibuf)
+		IMB_freeImBuf(oldtexibuf);
+
+	/* sample texture in new areas */
+	if ((0 < x1) && (0 < ibuf->y))
+		brush_painter_do_partial(painter, NULL, 0, 0, x1, ibuf->y, 0, 0, pos);
+	if ((x2 < ibuf->x) && (0 < ibuf->y))
+		brush_painter_do_partial(painter, NULL, x2, 0, ibuf->x, ibuf->y, 0, 0, pos);
+	if ((x1 < x2) && (0 < y1))
+		brush_painter_do_partial(painter, NULL, x1, 0, x2, y1, 0, 0, pos);
+	if ((x1 < x2) && (y2 < ibuf->y))
+		brush_painter_do_partial(painter, NULL, x1, y2, x2, ibuf->y, 0, 0, pos);
+}
+
+static void brush_painter_refresh_cache(BrushPainter *painter, const float pos[2], int use_color_correction)
+{
+	const Scene *scene = painter->scene;
+	Brush *brush = painter->brush;
+	BrushPainterCache *cache = &painter->cache;
+	MTex *mtex = &brush->mtex;
+	int size;
+	short flt;
+	const int diameter = 2 * BKE_brush_size_get(scene, brush);
+	const float alpha = BKE_brush_alpha_get(scene, brush);
+
+	if (diameter != cache->lastsize ||
+	    alpha != cache->lastalpha ||
+	    brush->jitter != cache->lastjitter)
+	{
+		if (cache->ibuf) {
+			IMB_freeImBuf(cache->ibuf);
+			cache->ibuf = NULL;
+		}
+		if (cache->maskibuf) {
+			IMB_freeImBuf(cache->maskibuf);
+			cache->maskibuf = NULL;
+		}
+
+		flt = cache->flt;
+		size = (cache->size) ? cache->size : diameter;
+
+		if (brush->flag & BRUSH_FIXED_TEX) {
+			BKE_brush_imbuf_new(scene, brush, flt, 3, size, &cache->maskibuf, use_color_correction);
+			brush_painter_fixed_tex_partial_update(painter, pos);
+		}
+		else
+			BKE_brush_imbuf_new(scene, brush, flt, 2, size, &cache->ibuf, use_color_correction);
+
+		cache->lastsize = diameter;
+		cache->lastalpha = alpha;
+		cache->lastjitter = brush->jitter;
+	}
+	else if ((brush->flag & BRUSH_FIXED_TEX) && mtex && mtex->tex) {
+		int dx = (int)painter->lastpaintpos[0] - (int)pos[0];
+		int dy = (int)painter->lastpaintpos[1] - (int)pos[1];
+
+		if ((dx != 0) || (dy != 0))
+			brush_painter_fixed_tex_partial_update(painter, pos);
+	}
+}
+
+void BKE_brush_painter_break_stroke(BrushPainter *painter)
+{
+	painter->firsttouch = 1;
+}
+
+
+int BKE_brush_painter_paint(BrushPainter *painter, BrushFunc func, const float pos[2], double time, float pressure,
+                            void *user, int use_color_correction)
+{
+	Scene *scene = painter->scene;
+	Brush *brush = painter->brush;
+	int totpaintops = 0;
+
+	if (pressure == 0.0f) {
+		if (painter->lastpressure) // XXX - hack, operator misses
+			pressure = painter->lastpressure;
+		else
+			pressure = 1.0f;    /* zero pressure == not using tablet */
+	}
+	if (painter->firsttouch) {
+		/* paint exactly once on first touch */
+		painter->startpaintpos[0] = pos[0];
+		painter->startpaintpos[1] = pos[1];
+
+		brush_pressure_apply(painter, brush, pressure);
+		if (painter->cache.enabled)
+			brush_painter_refresh_cache(painter, pos, use_color_correction);
+		totpaintops += func(user, painter->cache.ibuf, pos, pos);
+		
+		painter->lasttime = time;
+		painter->firsttouch = 0;
+		painter->lastpaintpos[0] = pos[0];
+		painter->lastpaintpos[1] = pos[1];
+	}
+#if 0
+	else if (painter->brush->flag & BRUSH_AIRBRUSH) {
+		float spacing, step, paintpos[2], dmousepos[2], len;
+		double starttime, curtime = time;
+
+		/* compute brush spacing adapted to brush size */
+		spacing = brush->rate; //radius*brush->spacing*0.01f;
+
+		/* setup starting time, direction vector and accumulated time */
+		starttime = painter->accumtime;
+		sub_v2_v2v2(dmousepos, pos, painter->lastmousepos);
+		len = normalize_v2(dmousepos);
+		painter->accumtime += curtime - painter->lasttime;
+
+		/* do paint op over unpainted time distance */
+		while (painter->accumtime >= spacing) {
+			step = (spacing - starttime) * len;
+			paintpos[0] = painter->lastmousepos[0] + dmousepos[0] * step;
+			paintpos[1] = painter->lastmousepos[1] + dmousepos[1] * step;
+
+			if (painter->cache.enabled)
+				brush_painter_refresh_cache(painter);
+			totpaintops += func(user, painter->cache.ibuf,
+			                    painter->lastpaintpos, paintpos);
+
+			painter->lastpaintpos[0] = paintpos[0];
+			painter->lastpaintpos[1] = paintpos[1];
+			painter->accumtime -= spacing;
+			starttime -= spacing;
+		}
+		
+		painter->lasttime = curtime;
+	}
+#endif
+	else {
+		float startdistance, spacing, step, paintpos[2], dmousepos[2], finalpos[2];
+		float t, len, press;
+		const int radius = BKE_brush_size_get(scene, brush);
+
+		/* compute brush spacing adapted to brush radius, spacing may depend
+		 * on pressure, so update it */
+		brush_pressure_apply(painter, brush, painter->lastpressure);
+		spacing = max_ff(1.0f, radius) * brush->spacing * 0.01f;
+
+		/* setup starting distance, direction vector and accumulated distance */
+		startdistance = painter->accumdistance;
+		sub_v2_v2v2(dmousepos, pos, painter->lastmousepos);
+		len = normalize_v2(dmousepos);
+		painter->accumdistance += len;
+
+		if (brush->flag & BRUSH_SPACE) {
+			/* do paint op over unpainted distance */
+			while ((len > 0.0f) && (painter->accumdistance >= spacing)) {
+				step = spacing - startdistance;
+				paintpos[0] = painter->lastmousepos[0] + dmousepos[0] * step;
+				paintpos[1] = painter->lastmousepos[1] + dmousepos[1] * step;
+
+				t = step / len;
+				press = (1.0f - t) * painter->lastpressure + t * pressure;
+				brush_pressure_apply(painter, brush, press);
+				spacing = max_ff(1.0f, radius) * brush->spacing * 0.01f;
+
+				BKE_brush_jitter_pos(scene, brush, paintpos, finalpos);
+
+				if (painter->cache.enabled)
+					brush_painter_refresh_cache(painter, finalpos, use_color_correction);
+
+				totpaintops +=
+				    func(user, painter->cache.ibuf, painter->lastpaintpos, finalpos);
+
+				painter->lastpaintpos[0] = paintpos[0];
+				painter->lastpaintpos[1] = paintpos[1];
+				painter->accumdistance -= spacing;
+				startdistance -= spacing;
+			}
+		}
+		else {
+			BKE_brush_jitter_pos(scene, brush, pos, finalpos);
+
+			if (painter->cache.enabled)
+				brush_painter_refresh_cache(painter, finalpos, use_color_correction);
+
+			totpaintops += func(user, painter->cache.ibuf, pos, finalpos);
+
+			painter->lastpaintpos[0] = pos[0];
+			painter->lastpaintpos[1] = pos[1];
+			painter->accumdistance = 0;
+		}
+
+		/* do airbrush paint ops, based on the number of paint ops left over
+		 * from regular painting. this is a temporary solution until we have
+		 * accurate time stamps for mouse move events */
+		if (brush->flag & BRUSH_AIRBRUSH) {
+			double curtime = time;
+			double painttime = brush->rate * totpaintops;
+
+			painter->accumtime += curtime - painter->lasttime;
+			if (painter->accumtime <= painttime)
+				painter->accumtime = 0.0;
+			else
+				painter->accumtime -= painttime;
+
+			while (painter->accumtime >= (double)brush->rate) {
+				brush_pressure_apply(painter, brush, pressure);
+
+				BKE_brush_jitter_pos(scene, brush, pos, finalpos);
+
+				if (painter->cache.enabled)
+					brush_painter_refresh_cache(painter, finalpos, use_color_correction);
+
+				totpaintops +=
+				    func(user, painter->cache.ibuf, painter->lastmousepos, finalpos);
+				painter->accumtime -= (double)brush->rate;
+			}
+
+			painter->lasttime = curtime;
+		}
+	}
+
+	painter->lastmousepos[0] = pos[0];
+	painter->lastmousepos[1] = pos[1];
+	painter->lastpressure = pressure;
+
+	BKE_brush_alpha_set(scene, brush, painter->startalpha);
+	BKE_brush_size_set(scene, brush, painter->startsize);
+	brush->jitter = painter->startjitter;
+	brush->spacing = painter->startspacing;
+
+	return totpaintops;
+}
+
+
+/* TODO: should probably be unified with BrushPainter stuff? */
+unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side)
+{
+	unsigned int *texcache = NULL;
+	MTex *mtex = &br->mtex;
+	TexResult texres = {0};
+	int hasrgb, ix, iy;
+	int side = half_side * 2;
+	
+	if (mtex->tex) {
+		float x, y, step = 2.0 / side, co[3];
+
+		texcache = MEM_callocN(sizeof(int) * side * side, "Brush texture cache");
+
+		/*do normalized cannonical view coords for texture*/
+		for (y = -1.0, iy = 0; iy < side; iy++, y += step) {
+			for (x = -1.0, ix = 0; ix < side; ix++, x += step) {
+				co[0] = x;
+				co[1] = y;
+				co[2] = 0.0f;
+				
+				/* This is copied from displace modifier code */
+				hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 0, &texres);
+			
+				/* if the texture gave an RGB value, we assume it didn't give a valid
+				 * intensity, so calculate one (formula from do_material_tex).
+				 * if the texture didn't give an RGB value, copy the intensity across
+				 */
+				if (hasrgb & TEX_RGB)
+					texres.tin = rgb_to_grayscale(&texres.tr);
+
+				((char *)texcache)[(iy * side + ix) * 4] =
+				((char *)texcache)[(iy * side + ix) * 4 + 1] =
+				((char *)texcache)[(iy * side + ix) * 4 + 2] =
+				((char *)texcache)[(iy * side + ix) * 4 + 3] = (char)(texres.tin * 255.0f);
+			}
+		}
+	}
+
+	return texcache;
+}
+
-- 
cgit v1.2.3


From 5e0e62f0407e15c936bae92d8fec043adee6ab07 Mon Sep 17 00:00:00 2001
From: Alex Fraser 
Date: Wed, 2 Jan 2013 00:05:30 +0000
Subject: Patch [#29035] Vertex colour baking

There is a new option in the Bake panel to enable baking to vertex colors. Unlike regular baking, this mode does not require a UV map or image to bake to, however the object must have a vertex color layer.

Thanks to:
 - AutoCRC for funding
 - Brech van Lommel and Dalai Felinto for their initial advice on how to implement it
 - Campbell Barton for helping to make this feature work with modifiers and bmesh
---
 source/blender/makesdna/DNA_scene_types.h          |   1 +
 source/blender/makesrna/intern/rna_scene.c         |   6 +
 .../blender/render/intern/include/renderdatabase.h |   6 +
 .../blender/render/intern/source/convertblender.c  |  42 +++-
 source/blender/render/intern/source/rendercore.c   | 243 +++++++++++++++++----
 .../blender/render/intern/source/renderdatabase.c  |  50 +++++
 6 files changed, 302 insertions(+), 46 deletions(-)

(limited to 'source')

diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 1e83b3dadf9..c8175461c1d 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -1319,6 +1319,7 @@ typedef struct Scene {
 #define R_BAKE_NORMALIZE	8
 #define R_BAKE_MULTIRES		16
 #define R_BAKE_LORES_MESH	32
+#define R_BAKE_VCOL			64
 
 /* bake_normal_space */
 #define R_BAKE_SPACE_CAMERA	 0
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 29d2d949fa2..27aeccbde8a 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -3918,6 +3918,12 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
 	RNA_def_property_ui_text(prop, "Samples", "Number of samples used for ambient occlusion baking from multires");
 	RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
 
+	prop= RNA_def_property(srna, "use_bake_to_vertex_color", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "bake_flag", R_BAKE_VCOL);
+	RNA_def_property_ui_text(prop, "Bake to Vertex Colour",
+	                         "Bake to vertex colors instead of to a UV-mapped image.");
+	RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+
 	/* stamp */
 	
 	prop = RNA_def_property(srna, "use_stamp_time", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/render/intern/include/renderdatabase.h b/source/blender/render/intern/include/renderdatabase.h
index 24989b13c48..1e81ca20d03 100644
--- a/source/blender/render/intern/include/renderdatabase.h
+++ b/source/blender/render/intern/include/renderdatabase.h
@@ -59,12 +59,16 @@ typedef struct VertTableNode {
 	float *tangent;
 	float *stress;
 	float *winspeed;
+	/* Index of vertex in source mesh (before modifiers). */
+	int *origindex;
 } VertTableNode;
 
 typedef struct VlakTableNode {
 	struct VlakRen *vlak;
 	struct MTFace *mtface;
 	struct MCol *mcol;
+	/* Index of mpoly in source mesh (before tessellation). */
+	int *origindex;
 	int totmtface, totmcol;
 	float *surfnor;
 	float *tangent;
@@ -114,9 +118,11 @@ float *RE_vertren_get_rad(struct ObjectRen *obr, struct VertRen *ver, int verify
 float *RE_vertren_get_strand(struct ObjectRen *obr, struct VertRen *ver, int verify);
 float *RE_vertren_get_tangent(struct ObjectRen *obr, struct VertRen *ver, int verify);
 float *RE_vertren_get_winspeed(struct ObjectInstanceRen *obi, struct VertRen *ver, int verify);
+int *RE_vertren_get_origindex(struct ObjectRen *obr, VertRen *ver, int verify);
 
 struct MTFace *RE_vlakren_get_tface(struct ObjectRen *obr, VlakRen *ren, int n, char **name, int verify);
 struct MCol *RE_vlakren_get_mcol(struct ObjectRen *obr, VlakRen *ren, int n, char **name, int verify);
+int *RE_vlakren_get_origindex(struct ObjectRen *obr, VlakRen *vlak, int verify);
 float *RE_vlakren_get_surfnor(struct ObjectRen *obr, VlakRen *ren, int verify);
 float *RE_vlakren_get_nmap_tangent(struct ObjectRen *obr, VlakRen *ren, int verify);
 RadFace **RE_vlakren_get_radface(struct ObjectRen *obr, VlakRen *ren, int verify);
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 76d67765424..6c5e558e6c7 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -3231,7 +3231,7 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
 	CustomDataMask mask;
 	float xn, yn, zn,  imat[3][3], mat[4][4];  //nor[3],
 	float *orco=0;
-	int need_orco=0, need_stress=0, need_nmap_tangent=0, need_tangent=0;
+	int need_orco=0, need_stress=0, need_nmap_tangent=0, need_tangent=0, need_origindex=0;
 	int a, a1, ok, vertofs;
 	int end, do_autosmooth = FALSE, totvert = 0;
 	int use_original_normals = FALSE;
@@ -3281,6 +3281,10 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
 		need_nmap_tangent= 1;
 	}
 	
+	/* origindex currently only used when baking to vertex colors */
+	if(re->flag & R_BAKING && re->r.bake_flag & R_BAKE_VCOL)
+		need_origindex= 1;
+
 	/* check autosmooth and displacement, we then have to skip only-verts optimize */
 	do_autosmooth |= (me->flag & ME_AUTOSMOOTH);
 	if (do_autosmooth)
@@ -3318,6 +3322,15 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
 		make_render_halos(re, obr, me, totvert, mvert, ma, orco);
 	}
 	else {
+		const int *index_vert_orig = NULL;
+		const int *index_mf_to_mpoly = NULL;
+		const int *index_mp_to_orig = NULL;
+		if (need_origindex) {
+			index_vert_orig = dm->getVertDataArray(dm, CD_ORIGINDEX);
+			/* double lookup for faces -> polys */
+			index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
+			index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
+		}
 
 		for (a=0; atotvert++);
@@ -3334,6 +3347,18 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
 				ver->orco= orco;
 				orco+=3;
 			}
+
+			if (need_origindex) {
+				int *origindex;
+				origindex = RE_vertren_get_origindex(obr, ver, 1);
+
+				/* Use orig index array if it's available (e.g. in the presence
+				 * of modifiers). */
+				if (index_vert_orig)
+					*origindex = index_vert_orig[a];
+				else
+					*origindex = a;
+			}
 		}
 		
 		if (!timeoffset) {
@@ -3455,6 +3480,21 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
 										}
 									}
 								}
+
+								if (need_origindex) {
+									/* Find original index of mpoly for this tessface. Options:
+									   - Modified mesh; two-step look up from tessface -> modified mpoly -> original mpoly
+									   - OR Tesselated mesh; look up from tessface -> mpoly
+									   - OR Failsafe; tessface == mpoly. Could probably assert(false) in this case? */
+									int *origindex;
+									origindex = RE_vlakren_get_origindex(obr, vlr, 1);
+									if (index_mf_to_mpoly && index_mp_to_orig)
+										*origindex = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a);
+									else if (index_mf_to_mpoly)
+										*origindex = index_mf_to_mpoly[a];
+									else
+										*origindex = a;
+								}
 							}
 						}
 					}
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index 9b08d6c07e9..90ff96d7a64 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -20,6 +20,7 @@
  *
  * Contributors: Hos, Robert Wenzlaff.
  * Contributors: 2004/2005/2006 Blender Foundation, full recode
+ * Contributors: Vertex color baking, Copyright 2011 AutoCRC
  *
  * ***** END GPL LICENSE BLOCK *****
  */
@@ -51,9 +52,12 @@
 #include "DNA_image_types.h"
 #include "DNA_lamp_types.h"
 #include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h"
 #include "DNA_group_types.h"
 
+#include "BKE_customdata.h"
+#include "BKE_depsgraph.h"
 #include "BKE_global.h"
 #include "BKE_image.h"
 #include "BKE_main.h"
@@ -2003,6 +2007,12 @@ typedef struct BakeShade {
 
 	float dir[3];
 	Object *actob;
+
+	/* Output: vertex color or image data. If vcol is not NULL, rect and
+	 * rect_float should be NULL. */
+	MPoly *mpoly;
+	MLoop *mloop;
+	MLoopCol *vcol;
 	
 	unsigned int *rect;
 	float *rect_float;
@@ -2179,7 +2189,7 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(qua
 		}
 	}
 	
-	if (bs->rect_float) {
+	if (bs->rect_float && !bs->vcol) {
 		float *col= bs->rect_float + 4*(bs->rectx*y + x);
 		copy_v3_v3(col, shr.combined);
 		if (bs->type==RE_BAKE_ALL || bs->type==RE_BAKE_TEXTURE) {
@@ -2190,7 +2200,8 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(qua
 		}
 	}
 	else {
-		unsigned char *col= (unsigned char *)(bs->rect + bs->rectx*y + x);
+		/* Target is char (LDR). */
+		unsigned char col[4];
 
 		if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) {
 			float rgb[3];
@@ -2210,6 +2221,19 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(qua
 		else {
 			col[3]= 255;
 		}
+
+		if (bs->vcol) {
+			/* Vertex colour baking. Vcol has no useful alpha channel (it exists
+			 * but is used only for vertex painting). */
+			bs->vcol->r = col[0];
+			bs->vcol->g = col[1];
+			bs->vcol->b = col[2];
+		}
+		else {
+			unsigned char *imcol= (unsigned char *)(bs->rect + bs->rectx*y + x);
+			copy_v4_v4_char((char *)imcol, (char *)col);
+		}
+
 	}
 	
 	if (bs->rect_mask) {
@@ -2229,15 +2253,28 @@ static void bake_displacement(void *handle, ShadeInput *UNUSED(shi), float dist,
 		disp = 0.5f + dist; /* alter the range from [-0.5,0.5] to [0,1]*/
 	}
 	
-	if (bs->rect_float) {
+	if (bs->rect_float && !bs->vcol) {
 		float *col= bs->rect_float + 4*(bs->rectx*y + x);
 		col[0] = col[1] = col[2] = disp;
 		col[3]= 1.0f;
 	}
 	else {
-		char *col= (char *)(bs->rect + bs->rectx*y + x);
+		/* Target is char (LDR). */
+		unsigned char col[4];
 		col[0] = col[1] = col[2] = FTOCHAR(disp);
-		col[3]= 255;
+		col[3] = 255;
+
+		if(bs->vcol) {
+			/* Vertex colour baking. Vcol has no useful alpha channel (it exists
+			 * but is used only for vertex painting). */
+			bs->vcol->r = col[0];
+			bs->vcol->g = col[1];
+			bs->vcol->b = col[2];
+		}
+		else {
+			char *imcol= (char *)(bs->rect + bs->rectx*y + x);
+			copy_v4_v4_char((char *)imcol, (char *)col);
+		}
 	}
 	if (bs->rect_mask) {
 		bs->rect_mask[bs->rectx*y + x] = FILTER_MASK_USED;
@@ -2473,13 +2510,55 @@ static int get_next_bake_face(BakeShade *bs)
 			vlr= RE_findOrAddVlak(obr, v);
 
 			if ((bs->actob && bs->actob == obr->ob) || (!bs->actob && (obr->ob->flag & SELECT))) {
-				tface= RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0);
+				if(R.r.bake_flag & R_BAKE_VCOL) {
+					/* Gather face data for vertex colour bake */
+					Mesh *me;
+					int *origindex, vcollayer;
+					CustomDataLayer *cdl;
+
+					if(obr->ob->type != OB_MESH)
+						continue;
+					me = obr->ob->data;
+
+					origindex = RE_vlakren_get_origindex(obr, vlr, 0);
+					if(origindex == NULL)
+						continue;
+					if (*origindex >= me->totpoly) {
+						/* Small hack for Array modifier, which gives false
+						   original indices - z0r */
+						continue;
+					}
+#if 0
+					/* Only shade selected faces. */
+					if((me->mface[*origindex].flag & ME_FACE_SEL) == 0)
+						continue;
+#endif
+
+					vcollayer = CustomData_get_render_layer_index(&me->ldata, CD_MLOOPCOL);
+					if(vcollayer == -1)
+						continue;
+
+					cdl = &me->ldata.layers[vcollayer];
+					bs->mpoly = me->mpoly + *origindex;
+					bs->vcol = ((MLoopCol*)cdl->data) + bs->mpoly->loopstart;
+					bs->mloop = me->mloop + bs->mpoly->loopstart;
 
-				if (tface && tface->tpage) {
-					Image *ima= tface->tpage;
-					ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL);
+					/* Tag mesh for reevaluation. */
+					DAG_id_tag_update(&me->id, 0);
+				}
+				else {
+					Image *ima = NULL;
+					ImBuf *ibuf = NULL;
 					const float vec_alpha[4]= {0.0f, 0.0f, 0.0f, 0.0f};
 					const float vec_solid[4]= {0.0f, 0.0f, 0.0f, 1.0f};
+
+					tface= RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0);
+
+					if (!tface || !tface->tpage)
+						continue;
+
+					ima = tface->tpage;
+					ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
 					
 					if (ibuf==NULL)
 						continue;
@@ -2515,20 +2594,17 @@ static int get_next_bake_face(BakeShade *bs)
 						R.bakebuf= ima;
 					}
 
+					/* Tag image for redraw. */
 					ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
-
-					bs->obi= obi;
-					bs->vlr= vlr;
-					
-					bs->vdone++;	/* only for error message if nothing was rendered */
-					v++;
-					
-					BLI_unlock_thread(LOCK_CUSTOM1);
-
 					BKE_image_release_ibuf(ima, ibuf, NULL);
-
-					return 1;
 				}
+
+				bs->obi = obi;
+				bs->vlr = vlr;
+				bs->vdone++;	/* only for error message if nothing was rendered */
+				v++;
+				BLI_unlock_thread(LOCK_CUSTOM1);
+				return 1;
 			}
 		}
 	}
@@ -2537,6 +2613,72 @@ static int get_next_bake_face(BakeShade *bs)
 	return 0;
 }
 
+static void bake_single_vertex(BakeShade *bs, VertRen *vert, float u, float v) {
+	int *origindex, i;
+	MLoopCol *basevcol;
+	MLoop *mloop;
+
+	origindex = RE_vertren_get_origindex(bs->obi->obr, vert, 0);
+	if (!origindex || *origindex == ORIGINDEX_NONE)
+		return;
+
+	/* Search for matching vertex index and apply shading. */
+	for (i = 0; i < bs->mpoly->totloop; i++) {
+		mloop = bs->mloop + i;
+		if (mloop->v != *origindex)
+			continue;
+		basevcol = bs->vcol;
+		bs->vcol = basevcol + i;
+		do_bake_shade(bs, 0, 0, u, v);
+		bs->vcol = basevcol;
+		break;
+	}
+}
+
+/* Bake all vertices of a face. Actually, this still works on a face-by-face
+   basis, and each vertex on each face is shaded. Vertex colors are a property
+   of loops, not vertices. */
+static void shade_verts(BakeShade *bs)
+{
+	VlakRen *vlr = bs->vlr;
+
+	/* Disable baking to image; write to vcol instead. vcol pointer is set in
+	 * bake_single_vertex. */
+	bs->ima = NULL;
+	bs->rect = NULL;
+	bs->rect_float = NULL;
+
+	bs->quad = 0;
+
+	/* No anti-aliasing for vertices. */
+	zero_v3(bs->dxco);
+	zero_v3(bs->dyco);
+
+	/* Shade each vertex of the face. u and v are barycentric coordinates; since
+	   we're only interested in vertices, these will be 0 or 1. */
+	if ((vlr->flag & R_FACE_SPLIT) == 0) {
+		/* Processing triangle face, whole quad, or first half of split quad. */
+
+		bake_single_vertex(bs, bs->vlr->v1, 1.0f, 0.0f);
+		bake_single_vertex(bs, bs->vlr->v2, 0.0f, 1.0f);
+		bake_single_vertex(bs, bs->vlr->v3, 0.0f, 0.0f);
+
+		if (vlr->v4) {
+			bs->quad = 1;
+			bake_single_vertex(bs, bs->vlr->v4, 0.0f, 0.0f);
+		}
+	}
+	else {
+		/* Processing second half of split quad. Only one vertex to go. */
+		if (vlr->flag & R_DIVIDE_24) {
+			bake_single_vertex(bs, bs->vlr->v2, 0.0f, 1.0f);
+		}
+		else {
+			bake_single_vertex(bs, bs->vlr->v3, 0.0f, 0.0f);
+		}
+	}
+}
+
 /* already have tested for tface and ima and zspan */
 static void shade_tface(BakeShade *bs)
 {
@@ -2564,6 +2706,7 @@ static void shade_tface(BakeShade *bs)
 	bs->rect= bs->ibuf->rect;
 	bs->rect_colorspace= bs->ibuf->rect_colorspace;
 	bs->rect_float= bs->ibuf->rect_float;
+	bs->vcol = NULL;
 	bs->quad= 0;
 	
 	if (bs->use_mask) {
@@ -2607,7 +2750,10 @@ static void *do_bake_thread(void *bs_v)
 	BakeShade *bs= bs_v;
 	
 	while (get_next_bake_face(bs)) {
-		shade_tface(bs);
+		if (R.r.bake_flag & R_BAKE_VCOL)
+			shade_verts(bs);
+		else
+			shade_tface(bs);
 		
 		/* fast threadsafe break test */
 		if (R.test_break(R.tbh))
@@ -2671,14 +2817,16 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up
 		use_mask = TRUE;
 	
 	/* baker uses this flag to detect if image was initialized */
-	for (ima= G.main->image.first; ima; ima= ima->id.next) {
-		ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL);
-		ima->id.flag |= LIB_DOIT;
-		ima->flag&= ~IMA_USED_FOR_RENDER;
-		if (ibuf) {
-			ibuf->userdata = NULL; /* use for masking if needed */
+	if ((R.r.bake_flag & R_BAKE_VCOL) == 0) {
+		for (ima = G.main->image.first; ima; ima = ima->id.next) {
+			ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+			ima->id.flag |= LIB_DOIT;
+			ima->flag &= ~IMA_USED_FOR_RENDER;
+			if (ibuf) {
+				ibuf->userdata = NULL; /* use for masking if needed */
+			}
+			BKE_image_release_ibuf(ima, ibuf, NULL);
 		}
-		BKE_image_release_ibuf(ima, ibuf, NULL);
 	}
 	
 	BLI_init_threads(&threads, do_bake_thread, re->r.threads);
@@ -2702,7 +2850,10 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up
 		
 		handles[a].type= type;
 		handles[a].actob= actob;
-		handles[a].zspan= MEM_callocN(sizeof(ZSpan), "zspan for bake");
+		if (R.r.bake_flag & R_BAKE_VCOL)
+			handles[a].zspan = NULL;
+		else
+			handles[a].zspan = MEM_callocN(sizeof(ZSpan), "zspan for bake");
 		
 		handles[a].use_mask = use_mask;
 
@@ -2729,27 +2880,29 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up
 	}
 	
 	/* filter and refresh images */
-	for (ima= G.main->image.first; ima; ima= ima->id.next) {
-		if ((ima->id.flag & LIB_DOIT)==0) {
-			ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL);
+	if ((R.r.bake_flag & R_BAKE_VCOL) == 0) {
+		for (ima = G.main->image.first; ima; ima = ima->id.next) {
+			if ((ima->id.flag & LIB_DOIT)==0) {
+				ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
 
-			if (ima->flag & IMA_USED_FOR_RENDER)
-				result= BAKE_RESULT_FEEDBACK_LOOP;
+				if (ima->flag & IMA_USED_FOR_RENDER)
+					result = BAKE_RESULT_FEEDBACK_LOOP;
 
-			if (!ibuf)
-				continue;
+				if (!ibuf)
+					continue;
 
-			RE_bake_ibuf_filter(ibuf, (char *)ibuf->userdata, re->r.bake_filter);
+				RE_bake_ibuf_filter(ibuf, (char *)ibuf->userdata, re->r.bake_filter);
 
-			ibuf->userflags |= IB_BITMAPDIRTY;
-			BKE_image_release_ibuf(ima, ibuf, NULL);
+				ibuf->userflags |= IB_BITMAPDIRTY;
+				BKE_image_release_ibuf(ima, ibuf, NULL);
+			}
+		}
+
+		/* calculate return value */
+		for (a = 0; a < re->r.threads; a++) {
+			zbuf_free_span(handles[a].zspan);
+			MEM_freeN(handles[a].zspan);
 		}
-	}
-	
-	/* calculate return value */
-	for (a=0; ar.threads; a++) {
-		zbuf_free_span(handles[a].zspan);
-		MEM_freeN(handles[a].zspan);
 	}
 
 	MEM_freeN(handles);
diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c
index a4e5b9eb7a2..7ca4f01ae47 100644
--- a/source/blender/render/intern/source/renderdatabase.c
+++ b/source/blender/render/intern/source/renderdatabase.c
@@ -105,6 +105,8 @@
 #define RE_MTFACE_ELEMS		1
 #define RE_MCOL_ELEMS		4
 #define RE_UV_ELEMS			2
+#define RE_VLAK_ORIGINDEX_ELEMS	1
+#define RE_VERT_ORIGINDEX_ELEMS	1
 #define RE_SURFNOR_ELEMS	3
 #define RE_RADFACE_ELEMS	1
 #define RE_SIMPLIFY_ELEMS	2
@@ -192,10 +194,26 @@ float *RE_vertren_get_winspeed(ObjectInstanceRen *obi, VertRen *ver, int verify)
 	return winspeed + ver->index*RE_WINSPEED_ELEMS;
 }
 
+int *RE_vertren_get_origindex(ObjectRen *obr, VertRen *ver, int verify)
+{
+	int *origindex;
+	int nr= ver->index>>8;
+
+	origindex= obr->vertnodes[nr].origindex;
+	if (origindex==NULL) {
+		if (verify)
+			origindex= obr->vertnodes[nr].origindex= MEM_mallocN(256*RE_VERT_ORIGINDEX_ELEMS*sizeof(int), "origindex table");
+		else
+			return NULL;
+	}
+	return origindex + (ver->index & 255)*RE_VERT_ORIGINDEX_ELEMS;
+}
+
 VertRen *RE_vertren_copy(ObjectRen *obr, VertRen *ver)
 {
 	VertRen *v1= RE_findOrAddVert(obr, obr->totvert++);
 	float *fp1, *fp2;
+	int *int1, *int2;
 	int index= v1->index;
 	
 	*v1= *ver;
@@ -221,6 +239,11 @@ VertRen *RE_vertren_copy(ObjectRen *obr, VertRen *ver)
 		fp2= RE_vertren_get_tangent(obr, v1, 1);
 		memcpy(fp2, fp1, RE_TANGENT_ELEMS*sizeof(float));
 	}
+	int1= RE_vertren_get_origindex(obr, ver, 0);
+	if (int1) {
+		int2= RE_vertren_get_origindex(obr, v1, 1);
+		memcpy(int2, int1, RE_VERT_ORIGINDEX_ELEMS*sizeof(int));
+	}
 	return v1;
 }
 
@@ -332,6 +355,21 @@ MCol *RE_vlakren_get_mcol(ObjectRen *obr, VlakRen *vlr, int n, char **name, int
 	return node->mcol + index*RE_MCOL_ELEMS;
 }
 
+int *RE_vlakren_get_origindex(ObjectRen *obr, VlakRen *vlak, int verify)
+{
+	int *origindex;
+	int nr= vlak->index>>8;
+
+	origindex= obr->vlaknodes[nr].origindex;
+	if(origindex==NULL) {
+		if(verify)
+			origindex= obr->vlaknodes[nr].origindex= MEM_callocN(256*RE_VLAK_ORIGINDEX_ELEMS*sizeof(int), "origindex table");
+		else
+			return NULL;
+	}
+	return origindex + (vlak->index & 255)*RE_VLAK_ORIGINDEX_ELEMS;
+}
+
 float *RE_vlakren_get_surfnor(ObjectRen *obr, VlakRen *vlak, int verify)
 {
 	float *surfnor;
@@ -383,6 +421,7 @@ VlakRen *RE_vlakren_copy(ObjectRen *obr, VlakRen *vlr)
 	MTFace *mtface, *mtface1;
 	MCol *mcol, *mcol1;
 	float *surfnor, *surfnor1, *tangent, *tangent1;
+	int *origindex, *origindex1;
 	RadFace **radface, **radface1;
 	int i, index = vlr1->index;
 	char *name;
@@ -400,6 +439,13 @@ VlakRen *RE_vlakren_copy(ObjectRen *obr, VlakRen *vlr)
 		memcpy(mcol1, mcol, sizeof(MCol)*RE_MCOL_ELEMS);
 	}
 
+	origindex= RE_vlakren_get_origindex(obr, vlr, 0);
+	if(origindex) {
+		origindex1= RE_vlakren_get_origindex(obr, vlr1, 1);
+		/* Just an int, but memcpy for consistency. */
+		memcpy(origindex1, origindex, sizeof(int)*RE_VLAK_ORIGINDEX_ELEMS);
+	}
+
 	surfnor= RE_vlakren_get_surfnor(obr, vlr, 0);
 	if (surfnor) {
 		surfnor1= RE_vlakren_get_surfnor(obr, vlr1, 1);
@@ -725,6 +771,8 @@ void free_renderdata_vertnodes(VertTableNode *vertnodes)
 			MEM_freeN(vertnodes[a].stress);
 		if (vertnodes[a].winspeed)
 			MEM_freeN(vertnodes[a].winspeed);
+		if (vertnodes[a].origindex)
+			MEM_freeN(vertnodes[a].origindex);
 	}
 	
 	MEM_freeN(vertnodes);
@@ -743,6 +791,8 @@ void free_renderdata_vlaknodes(VlakTableNode *vlaknodes)
 			MEM_freeN(vlaknodes[a].mtface);
 		if (vlaknodes[a].mcol)
 			MEM_freeN(vlaknodes[a].mcol);
+		if(vlaknodes[a].origindex)
+			MEM_freeN(vlaknodes[a].origindex);
 		if (vlaknodes[a].surfnor)
 			MEM_freeN(vlaknodes[a].surfnor);
 		if (vlaknodes[a].tangent)
-- 
cgit v1.2.3


From 4ab2fed9bb22663c61dbf4f66a5937ce760df69e Mon Sep 17 00:00:00 2001
From: Joshua Leung 
Date: Wed, 2 Jan 2013 00:15:37 +0000
Subject: Fix for what appears to be a typo (seq_prev is always NULL) - found
 while reviewing the latest Clang reports

---
 source/blender/editors/transform/transform_conversions.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 8e27530f730..82ad236f7ae 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -4268,8 +4268,8 @@ static void freeSeqData(TransInfo *t)
 			{
 				int overlap = 0;
 
+				seq_prev = NULL;
 				for (a = 0; a < t->total; a++, td++) {
-					seq_prev = NULL;
 					seq = ((TransDataSeq *)td->extra)->seq;
 					if ((seq != seq_prev) && (seq->depth == 0) && (seq->flag & SEQ_OVERLAP)) {
 						overlap = 1;
-- 
cgit v1.2.3


From ab156fba3be0cf19a5f990fb6213ee5b94fa78ce Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Wed, 2 Jan 2013 01:36:36 +0000
Subject: rename image paint_image_2d to lowercase (as we have for view2d).

---
 source/blender/editors/sculpt_paint/CMakeLists.txt |   2 +-
 .../blender/editors/sculpt_paint/paint_image_2D.c  | 562 ---------------------
 .../blender/editors/sculpt_paint/paint_image_2d.c  | 562 +++++++++++++++++++++
 source/blender/makesrna/intern/rna_scene.c         |   2 +-
 4 files changed, 564 insertions(+), 564 deletions(-)
 delete mode 100644 source/blender/editors/sculpt_paint/paint_image_2D.c
 create mode 100644 source/blender/editors/sculpt_paint/paint_image_2d.c

(limited to 'source')

diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index 7a74385ea77..5bed31e2e52 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -42,7 +42,7 @@ set(SRC
 	paint_cursor.c
 	paint_hide.c
 	paint_image.c
-	paint_image_2D.c
+	paint_image_2d.c
 	paint_mask.c
 	paint_ops.c
 	paint_stroke.c
diff --git a/source/blender/editors/sculpt_paint/paint_image_2D.c b/source/blender/editors/sculpt_paint/paint_image_2D.c
deleted file mode 100644
index 80e189a08e1..00000000000
--- a/source/blender/editors/sculpt_paint/paint_image_2D.c
+++ /dev/null
@@ -1,562 +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 blender/editors/sculpt_paint/paint_2D.c
- *  \ingroup bke
- */
-//#include 
-#include 
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_brush_types.h"
-#include "DNA_scene_types.h"
-
-#include "BKE_brush.h"
-#include "BKE_texture.h"
-
-#include "BLI_math.h"
-
-#include "IMB_imbuf.h"
-#include "IMB_imbuf_types.h"
-
-#include "RE_shader_ext.h"
-
- /* Brush Painting for 2D image editor */
-
-typedef struct BrushPainterCache {
-	short enabled;
-
-	int size;           /* size override, if 0 uses 2*BKE_brush_size_get(brush) */
-	short flt;          /* need float imbuf? */
-	short texonly;      /* no alpha, color or fallof, only texture in imbuf */
-
-	int lastsize;
-	float lastalpha;
-	float lastjitter;
-
-	ImBuf *ibuf;
-	ImBuf *texibuf;
-	ImBuf *maskibuf;
-} BrushPainterCache;
-
-struct BrushPainter {
-	Scene *scene;
-	Brush *brush;
-
-	float lastmousepos[2];  /* mouse position of last paint call */
-
-	float accumdistance;    /* accumulated distance of brush since last paint op */
-	float lastpaintpos[2];  /* position of last paint op */
-	float startpaintpos[2]; /* position of first paint */
-
-	double accumtime;       /* accumulated time since last paint op (airbrush) */
-	double lasttime;        /* time of last update */
-
-	float lastpressure;
-
-	short firsttouch;       /* first paint op */
-
-	float startsize;
-	float startalpha;
-	float startjitter;
-	float startspacing;
-
-	BrushPainterCache cache;
-};
-
-BrushPainter *BKE_brush_painter_new(Scene *scene, Brush *brush)
-{
-	BrushPainter *painter = MEM_callocN(sizeof(BrushPainter), "BrushPainter");
-
-	painter->brush = brush;
-	painter->scene = scene;
-	painter->firsttouch = 1;
-	painter->cache.lastsize = -1; /* force ibuf create in refresh */
-
-	painter->startsize = BKE_brush_size_get(scene, brush);
-	painter->startalpha = BKE_brush_alpha_get(scene, brush);
-	painter->startjitter = brush->jitter;
-	painter->startspacing = brush->spacing;
-
-	return painter;
-}
-
-
-static void brush_pressure_apply(BrushPainter *painter, Brush *brush, float pressure)
-{
-	if (BKE_brush_use_alpha_pressure(painter->scene, brush))
-		BKE_brush_alpha_set(painter->scene, brush, max_ff(0.0f, painter->startalpha * pressure));
-	if (BKE_brush_use_size_pressure(painter->scene, brush))
-		BKE_brush_size_set(painter->scene, brush, max_ff(1.0f, painter->startsize * pressure));
-	if (brush->flag & BRUSH_JITTER_PRESSURE)
-		brush->jitter = max_ff(0.0f, painter->startjitter * pressure);
-	if (brush->flag & BRUSH_SPACING_PRESSURE)
-		brush->spacing = max_ff(1.0f, painter->startspacing * (1.5f - pressure));
-}
-
-
-void BKE_brush_painter_require_imbuf(BrushPainter *painter, short flt, short texonly, int size)
-{
-	if ((painter->cache.flt != flt) || (painter->cache.size != size) ||
-	    ((painter->cache.texonly != texonly) && texonly))
-	{
-		if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
-		if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf);
-		painter->cache.ibuf = painter->cache.maskibuf = NULL;
-		painter->cache.lastsize = -1; /* force ibuf create in refresh */
-	}
-
-	if (painter->cache.flt != flt) {
-		if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
-		painter->cache.texibuf = NULL;
-		painter->cache.lastsize = -1; /* force ibuf create in refresh */
-	}
-
-	painter->cache.size = size;
-	painter->cache.flt = flt;
-	painter->cache.texonly = texonly;
-	painter->cache.enabled = 1;
-}
-
-void BKE_brush_painter_free(BrushPainter *painter)
-{
-	Brush *brush = painter->brush;
-
-	BKE_brush_size_set(painter->scene, brush, painter->startsize);
-	BKE_brush_alpha_set(painter->scene, brush, painter->startalpha);
-	brush->jitter = painter->startjitter;
-	brush->spacing = painter->startspacing;
-
-	if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
-	if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
-	if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf);
-	MEM_freeN(painter);
-}
-
-static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf,
-                                     int x, int y, int w, int h, int xt, int yt,
-                                     const float pos[2])
-{
-	Scene *scene = painter->scene;
-	Brush *brush = painter->brush;
-	ImBuf *ibuf, *maskibuf, *texibuf;
-	float *bf, *mf, *tf, *otf = NULL, xoff, yoff, xy[2], rgba[4];
-	unsigned char *b, *m, *t, *ot = NULL;
-	int dotexold, origx = x, origy = y;
-	const int radius = BKE_brush_size_get(painter->scene, brush);
-
-	xoff = -radius + 0.5f;
-	yoff = -radius + 0.5f;
-	xoff += (int)pos[0] - (int)painter->startpaintpos[0];
-	yoff += (int)pos[1] - (int)painter->startpaintpos[1];
-
-	ibuf = painter->cache.ibuf;
-	texibuf = painter->cache.texibuf;
-	maskibuf = painter->cache.maskibuf;
-
-	dotexold = (oldtexibuf != NULL);
-
-	/* not sure if it's actually needed or it's a mistake in coords/sizes
-	 * calculation in brush_painter_fixed_tex_partial_update(), but without this
-	 * limitation memory gets corrupted at fast strokes with quite big spacing (sergey) */
-	w = min_ii(w, ibuf->x);
-	h = min_ii(h, ibuf->y);
-
-	if (painter->cache.flt) {
-		for (; y < h; y++) {
-			bf = ibuf->rect_float + (y * ibuf->x + origx) * 4;
-			tf = texibuf->rect_float + (y * texibuf->x + origx) * 4;
-			mf = maskibuf->rect_float + (y * maskibuf->x + origx) * 4;
-
-			if (dotexold)
-				otf = oldtexibuf->rect_float + ((y - origy + yt) * oldtexibuf->x + xt) * 4;
-
-			for (x = origx; x < w; x++, bf += 4, mf += 4, tf += 4) {
-				if (dotexold) {
-					copy_v3_v3(tf, otf);
-					tf[3] = otf[3];
-					otf += 4;
-				}
-				else {
-					xy[0] = x + xoff;
-					xy[1] = y + yoff;
-
-					BKE_brush_sample_tex(scene, brush, xy, tf, 0);
-				}
-
-				bf[0] = tf[0] * mf[0];
-				bf[1] = tf[1] * mf[1];
-				bf[2] = tf[2] * mf[2];
-				bf[3] = tf[3] * mf[3];
-			}
-		}
-	}
-	else {
-		for (; y < h; y++) {
-			b = (unsigned char *)ibuf->rect + (y * ibuf->x + origx) * 4;
-			t = (unsigned char *)texibuf->rect + (y * texibuf->x + origx) * 4;
-			m = (unsigned char *)maskibuf->rect + (y * maskibuf->x + origx) * 4;
-
-			if (dotexold)
-				ot = (unsigned char *)oldtexibuf->rect + ((y - origy + yt) * oldtexibuf->x + xt) * 4;
-
-			for (x = origx; x < w; x++, b += 4, m += 4, t += 4) {
-				if (dotexold) {
-					t[0] = ot[0];
-					t[1] = ot[1];
-					t[2] = ot[2];
-					t[3] = ot[3];
-					ot += 4;
-				}
-				else {
-					xy[0] = x + xoff;
-					xy[1] = y + yoff;
-
-					BKE_brush_sample_tex(scene, brush, xy, rgba, 0);
-					rgba_float_to_uchar(t, rgba);
-				}
-
-				b[0] = t[0] * m[0] / 255;
-				b[1] = t[1] * m[1] / 255;
-				b[2] = t[2] * m[2] / 255;
-				b[3] = t[3] * m[3] / 255;
-			}
-		}
-	}
-}
-
-static void brush_painter_fixed_tex_partial_update(BrushPainter *painter, const float pos[2])
-{
-	const Scene *scene = painter->scene;
-	Brush *brush = painter->brush;
-	BrushPainterCache *cache = &painter->cache;
-	ImBuf *oldtexibuf, *ibuf;
-	int imbflag, destx, desty, srcx, srcy, w, h, x1, y1, x2, y2;
-	const int diameter = 2 * BKE_brush_size_get(scene, brush);
-
-	imbflag = (cache->flt) ? IB_rectfloat : IB_rect;
-	if (!cache->ibuf)
-		cache->ibuf = IMB_allocImBuf(diameter, diameter, 32, imbflag);
-	ibuf = cache->ibuf;
-
-	oldtexibuf = cache->texibuf;
-	cache->texibuf = IMB_allocImBuf(diameter, diameter, 32, imbflag);
-
-	if (oldtexibuf) {
-		srcx = srcy = 0;
-		destx = (int)painter->lastpaintpos[0] - (int)pos[0];
-		desty = (int)painter->lastpaintpos[1] - (int)pos[1];
-		w = oldtexibuf->x;
-		h = oldtexibuf->y;
-
-		IMB_rectclip(cache->texibuf, oldtexibuf, &destx, &desty, &srcx, &srcy, &w, &h);
-	}
-	else {
-		srcx = srcy = 0;
-		destx = desty = 0;
-		w = h = 0;
-	}
-	
-	x1 = destx;
-	y1 = desty;
-	x2 = destx + w;
-	y2 = desty + h;
-
-	/* blend existing texture in new position */
-	if ((x1 < x2) && (y1 < y2))
-		brush_painter_do_partial(painter, oldtexibuf, x1, y1, x2, y2, srcx, srcy, pos);
-
-	if (oldtexibuf)
-		IMB_freeImBuf(oldtexibuf);
-
-	/* sample texture in new areas */
-	if ((0 < x1) && (0 < ibuf->y))
-		brush_painter_do_partial(painter, NULL, 0, 0, x1, ibuf->y, 0, 0, pos);
-	if ((x2 < ibuf->x) && (0 < ibuf->y))
-		brush_painter_do_partial(painter, NULL, x2, 0, ibuf->x, ibuf->y, 0, 0, pos);
-	if ((x1 < x2) && (0 < y1))
-		brush_painter_do_partial(painter, NULL, x1, 0, x2, y1, 0, 0, pos);
-	if ((x1 < x2) && (y2 < ibuf->y))
-		brush_painter_do_partial(painter, NULL, x1, y2, x2, ibuf->y, 0, 0, pos);
-}
-
-static void brush_painter_refresh_cache(BrushPainter *painter, const float pos[2], int use_color_correction)
-{
-	const Scene *scene = painter->scene;
-	Brush *brush = painter->brush;
-	BrushPainterCache *cache = &painter->cache;
-	MTex *mtex = &brush->mtex;
-	int size;
-	short flt;
-	const int diameter = 2 * BKE_brush_size_get(scene, brush);
-	const float alpha = BKE_brush_alpha_get(scene, brush);
-
-	if (diameter != cache->lastsize ||
-	    alpha != cache->lastalpha ||
-	    brush->jitter != cache->lastjitter)
-	{
-		if (cache->ibuf) {
-			IMB_freeImBuf(cache->ibuf);
-			cache->ibuf = NULL;
-		}
-		if (cache->maskibuf) {
-			IMB_freeImBuf(cache->maskibuf);
-			cache->maskibuf = NULL;
-		}
-
-		flt = cache->flt;
-		size = (cache->size) ? cache->size : diameter;
-
-		if (brush->flag & BRUSH_FIXED_TEX) {
-			BKE_brush_imbuf_new(scene, brush, flt, 3, size, &cache->maskibuf, use_color_correction);
-			brush_painter_fixed_tex_partial_update(painter, pos);
-		}
-		else
-			BKE_brush_imbuf_new(scene, brush, flt, 2, size, &cache->ibuf, use_color_correction);
-
-		cache->lastsize = diameter;
-		cache->lastalpha = alpha;
-		cache->lastjitter = brush->jitter;
-	}
-	else if ((brush->flag & BRUSH_FIXED_TEX) && mtex && mtex->tex) {
-		int dx = (int)painter->lastpaintpos[0] - (int)pos[0];
-		int dy = (int)painter->lastpaintpos[1] - (int)pos[1];
-
-		if ((dx != 0) || (dy != 0))
-			brush_painter_fixed_tex_partial_update(painter, pos);
-	}
-}
-
-void BKE_brush_painter_break_stroke(BrushPainter *painter)
-{
-	painter->firsttouch = 1;
-}
-
-
-int BKE_brush_painter_paint(BrushPainter *painter, BrushFunc func, const float pos[2], double time, float pressure,
-                            void *user, int use_color_correction)
-{
-	Scene *scene = painter->scene;
-	Brush *brush = painter->brush;
-	int totpaintops = 0;
-
-	if (pressure == 0.0f) {
-		if (painter->lastpressure) // XXX - hack, operator misses
-			pressure = painter->lastpressure;
-		else
-			pressure = 1.0f;    /* zero pressure == not using tablet */
-	}
-	if (painter->firsttouch) {
-		/* paint exactly once on first touch */
-		painter->startpaintpos[0] = pos[0];
-		painter->startpaintpos[1] = pos[1];
-
-		brush_pressure_apply(painter, brush, pressure);
-		if (painter->cache.enabled)
-			brush_painter_refresh_cache(painter, pos, use_color_correction);
-		totpaintops += func(user, painter->cache.ibuf, pos, pos);
-		
-		painter->lasttime = time;
-		painter->firsttouch = 0;
-		painter->lastpaintpos[0] = pos[0];
-		painter->lastpaintpos[1] = pos[1];
-	}
-#if 0
-	else if (painter->brush->flag & BRUSH_AIRBRUSH) {
-		float spacing, step, paintpos[2], dmousepos[2], len;
-		double starttime, curtime = time;
-
-		/* compute brush spacing adapted to brush size */
-		spacing = brush->rate; //radius*brush->spacing*0.01f;
-
-		/* setup starting time, direction vector and accumulated time */
-		starttime = painter->accumtime;
-		sub_v2_v2v2(dmousepos, pos, painter->lastmousepos);
-		len = normalize_v2(dmousepos);
-		painter->accumtime += curtime - painter->lasttime;
-
-		/* do paint op over unpainted time distance */
-		while (painter->accumtime >= spacing) {
-			step = (spacing - starttime) * len;
-			paintpos[0] = painter->lastmousepos[0] + dmousepos[0] * step;
-			paintpos[1] = painter->lastmousepos[1] + dmousepos[1] * step;
-
-			if (painter->cache.enabled)
-				brush_painter_refresh_cache(painter);
-			totpaintops += func(user, painter->cache.ibuf,
-			                    painter->lastpaintpos, paintpos);
-
-			painter->lastpaintpos[0] = paintpos[0];
-			painter->lastpaintpos[1] = paintpos[1];
-			painter->accumtime -= spacing;
-			starttime -= spacing;
-		}
-		
-		painter->lasttime = curtime;
-	}
-#endif
-	else {
-		float startdistance, spacing, step, paintpos[2], dmousepos[2], finalpos[2];
-		float t, len, press;
-		const int radius = BKE_brush_size_get(scene, brush);
-
-		/* compute brush spacing adapted to brush radius, spacing may depend
-		 * on pressure, so update it */
-		brush_pressure_apply(painter, brush, painter->lastpressure);
-		spacing = max_ff(1.0f, radius) * brush->spacing * 0.01f;
-
-		/* setup starting distance, direction vector and accumulated distance */
-		startdistance = painter->accumdistance;
-		sub_v2_v2v2(dmousepos, pos, painter->lastmousepos);
-		len = normalize_v2(dmousepos);
-		painter->accumdistance += len;
-
-		if (brush->flag & BRUSH_SPACE) {
-			/* do paint op over unpainted distance */
-			while ((len > 0.0f) && (painter->accumdistance >= spacing)) {
-				step = spacing - startdistance;
-				paintpos[0] = painter->lastmousepos[0] + dmousepos[0] * step;
-				paintpos[1] = painter->lastmousepos[1] + dmousepos[1] * step;
-
-				t = step / len;
-				press = (1.0f - t) * painter->lastpressure + t * pressure;
-				brush_pressure_apply(painter, brush, press);
-				spacing = max_ff(1.0f, radius) * brush->spacing * 0.01f;
-
-				BKE_brush_jitter_pos(scene, brush, paintpos, finalpos);
-
-				if (painter->cache.enabled)
-					brush_painter_refresh_cache(painter, finalpos, use_color_correction);
-
-				totpaintops +=
-				    func(user, painter->cache.ibuf, painter->lastpaintpos, finalpos);
-
-				painter->lastpaintpos[0] = paintpos[0];
-				painter->lastpaintpos[1] = paintpos[1];
-				painter->accumdistance -= spacing;
-				startdistance -= spacing;
-			}
-		}
-		else {
-			BKE_brush_jitter_pos(scene, brush, pos, finalpos);
-
-			if (painter->cache.enabled)
-				brush_painter_refresh_cache(painter, finalpos, use_color_correction);
-
-			totpaintops += func(user, painter->cache.ibuf, pos, finalpos);
-
-			painter->lastpaintpos[0] = pos[0];
-			painter->lastpaintpos[1] = pos[1];
-			painter->accumdistance = 0;
-		}
-
-		/* do airbrush paint ops, based on the number of paint ops left over
-		 * from regular painting. this is a temporary solution until we have
-		 * accurate time stamps for mouse move events */
-		if (brush->flag & BRUSH_AIRBRUSH) {
-			double curtime = time;
-			double painttime = brush->rate * totpaintops;
-
-			painter->accumtime += curtime - painter->lasttime;
-			if (painter->accumtime <= painttime)
-				painter->accumtime = 0.0;
-			else
-				painter->accumtime -= painttime;
-
-			while (painter->accumtime >= (double)brush->rate) {
-				brush_pressure_apply(painter, brush, pressure);
-
-				BKE_brush_jitter_pos(scene, brush, pos, finalpos);
-
-				if (painter->cache.enabled)
-					brush_painter_refresh_cache(painter, finalpos, use_color_correction);
-
-				totpaintops +=
-				    func(user, painter->cache.ibuf, painter->lastmousepos, finalpos);
-				painter->accumtime -= (double)brush->rate;
-			}
-
-			painter->lasttime = curtime;
-		}
-	}
-
-	painter->lastmousepos[0] = pos[0];
-	painter->lastmousepos[1] = pos[1];
-	painter->lastpressure = pressure;
-
-	BKE_brush_alpha_set(scene, brush, painter->startalpha);
-	BKE_brush_size_set(scene, brush, painter->startsize);
-	brush->jitter = painter->startjitter;
-	brush->spacing = painter->startspacing;
-
-	return totpaintops;
-}
-
-
-/* TODO: should probably be unified with BrushPainter stuff? */
-unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side)
-{
-	unsigned int *texcache = NULL;
-	MTex *mtex = &br->mtex;
-	TexResult texres = {0};
-	int hasrgb, ix, iy;
-	int side = half_side * 2;
-	
-	if (mtex->tex) {
-		float x, y, step = 2.0 / side, co[3];
-
-		texcache = MEM_callocN(sizeof(int) * side * side, "Brush texture cache");
-
-		/*do normalized cannonical view coords for texture*/
-		for (y = -1.0, iy = 0; iy < side; iy++, y += step) {
-			for (x = -1.0, ix = 0; ix < side; ix++, x += step) {
-				co[0] = x;
-				co[1] = y;
-				co[2] = 0.0f;
-				
-				/* This is copied from displace modifier code */
-				hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 0, &texres);
-			
-				/* if the texture gave an RGB value, we assume it didn't give a valid
-				 * intensity, so calculate one (formula from do_material_tex).
-				 * if the texture didn't give an RGB value, copy the intensity across
-				 */
-				if (hasrgb & TEX_RGB)
-					texres.tin = rgb_to_grayscale(&texres.tr);
-
-				((char *)texcache)[(iy * side + ix) * 4] =
-				((char *)texcache)[(iy * side + ix) * 4 + 1] =
-				((char *)texcache)[(iy * side + ix) * 4 + 2] =
-				((char *)texcache)[(iy * side + ix) * 4 + 3] = (char)(texres.tin * 255.0f);
-			}
-		}
-	}
-
-	return texcache;
-}
-
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
new file mode 100644
index 00000000000..80e189a08e1
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -0,0 +1,562 @@
+/*
+ * ***** 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 blender/editors/sculpt_paint/paint_2D.c
+ *  \ingroup bke
+ */
+//#include 
+#include 
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_brush_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_brush.h"
+#include "BKE_texture.h"
+
+#include "BLI_math.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "RE_shader_ext.h"
+
+ /* Brush Painting for 2D image editor */
+
+typedef struct BrushPainterCache {
+	short enabled;
+
+	int size;           /* size override, if 0 uses 2*BKE_brush_size_get(brush) */
+	short flt;          /* need float imbuf? */
+	short texonly;      /* no alpha, color or fallof, only texture in imbuf */
+
+	int lastsize;
+	float lastalpha;
+	float lastjitter;
+
+	ImBuf *ibuf;
+	ImBuf *texibuf;
+	ImBuf *maskibuf;
+} BrushPainterCache;
+
+struct BrushPainter {
+	Scene *scene;
+	Brush *brush;
+
+	float lastmousepos[2];  /* mouse position of last paint call */
+
+	float accumdistance;    /* accumulated distance of brush since last paint op */
+	float lastpaintpos[2];  /* position of last paint op */
+	float startpaintpos[2]; /* position of first paint */
+
+	double accumtime;       /* accumulated time since last paint op (airbrush) */
+	double lasttime;        /* time of last update */
+
+	float lastpressure;
+
+	short firsttouch;       /* first paint op */
+
+	float startsize;
+	float startalpha;
+	float startjitter;
+	float startspacing;
+
+	BrushPainterCache cache;
+};
+
+BrushPainter *BKE_brush_painter_new(Scene *scene, Brush *brush)
+{
+	BrushPainter *painter = MEM_callocN(sizeof(BrushPainter), "BrushPainter");
+
+	painter->brush = brush;
+	painter->scene = scene;
+	painter->firsttouch = 1;
+	painter->cache.lastsize = -1; /* force ibuf create in refresh */
+
+	painter->startsize = BKE_brush_size_get(scene, brush);
+	painter->startalpha = BKE_brush_alpha_get(scene, brush);
+	painter->startjitter = brush->jitter;
+	painter->startspacing = brush->spacing;
+
+	return painter;
+}
+
+
+static void brush_pressure_apply(BrushPainter *painter, Brush *brush, float pressure)
+{
+	if (BKE_brush_use_alpha_pressure(painter->scene, brush))
+		BKE_brush_alpha_set(painter->scene, brush, max_ff(0.0f, painter->startalpha * pressure));
+	if (BKE_brush_use_size_pressure(painter->scene, brush))
+		BKE_brush_size_set(painter->scene, brush, max_ff(1.0f, painter->startsize * pressure));
+	if (brush->flag & BRUSH_JITTER_PRESSURE)
+		brush->jitter = max_ff(0.0f, painter->startjitter * pressure);
+	if (brush->flag & BRUSH_SPACING_PRESSURE)
+		brush->spacing = max_ff(1.0f, painter->startspacing * (1.5f - pressure));
+}
+
+
+void BKE_brush_painter_require_imbuf(BrushPainter *painter, short flt, short texonly, int size)
+{
+	if ((painter->cache.flt != flt) || (painter->cache.size != size) ||
+	    ((painter->cache.texonly != texonly) && texonly))
+	{
+		if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
+		if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf);
+		painter->cache.ibuf = painter->cache.maskibuf = NULL;
+		painter->cache.lastsize = -1; /* force ibuf create in refresh */
+	}
+
+	if (painter->cache.flt != flt) {
+		if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
+		painter->cache.texibuf = NULL;
+		painter->cache.lastsize = -1; /* force ibuf create in refresh */
+	}
+
+	painter->cache.size = size;
+	painter->cache.flt = flt;
+	painter->cache.texonly = texonly;
+	painter->cache.enabled = 1;
+}
+
+void BKE_brush_painter_free(BrushPainter *painter)
+{
+	Brush *brush = painter->brush;
+
+	BKE_brush_size_set(painter->scene, brush, painter->startsize);
+	BKE_brush_alpha_set(painter->scene, brush, painter->startalpha);
+	brush->jitter = painter->startjitter;
+	brush->spacing = painter->startspacing;
+
+	if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
+	if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
+	if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf);
+	MEM_freeN(painter);
+}
+
+static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf,
+                                     int x, int y, int w, int h, int xt, int yt,
+                                     const float pos[2])
+{
+	Scene *scene = painter->scene;
+	Brush *brush = painter->brush;
+	ImBuf *ibuf, *maskibuf, *texibuf;
+	float *bf, *mf, *tf, *otf = NULL, xoff, yoff, xy[2], rgba[4];
+	unsigned char *b, *m, *t, *ot = NULL;
+	int dotexold, origx = x, origy = y;
+	const int radius = BKE_brush_size_get(painter->scene, brush);
+
+	xoff = -radius + 0.5f;
+	yoff = -radius + 0.5f;
+	xoff += (int)pos[0] - (int)painter->startpaintpos[0];
+	yoff += (int)pos[1] - (int)painter->startpaintpos[1];
+
+	ibuf = painter->cache.ibuf;
+	texibuf = painter->cache.texibuf;
+	maskibuf = painter->cache.maskibuf;
+
+	dotexold = (oldtexibuf != NULL);
+
+	/* not sure if it's actually needed or it's a mistake in coords/sizes
+	 * calculation in brush_painter_fixed_tex_partial_update(), but without this
+	 * limitation memory gets corrupted at fast strokes with quite big spacing (sergey) */
+	w = min_ii(w, ibuf->x);
+	h = min_ii(h, ibuf->y);
+
+	if (painter->cache.flt) {
+		for (; y < h; y++) {
+			bf = ibuf->rect_float + (y * ibuf->x + origx) * 4;
+			tf = texibuf->rect_float + (y * texibuf->x + origx) * 4;
+			mf = maskibuf->rect_float + (y * maskibuf->x + origx) * 4;
+
+			if (dotexold)
+				otf = oldtexibuf->rect_float + ((y - origy + yt) * oldtexibuf->x + xt) * 4;
+
+			for (x = origx; x < w; x++, bf += 4, mf += 4, tf += 4) {
+				if (dotexold) {
+					copy_v3_v3(tf, otf);
+					tf[3] = otf[3];
+					otf += 4;
+				}
+				else {
+					xy[0] = x + xoff;
+					xy[1] = y + yoff;
+
+					BKE_brush_sample_tex(scene, brush, xy, tf, 0);
+				}
+
+				bf[0] = tf[0] * mf[0];
+				bf[1] = tf[1] * mf[1];
+				bf[2] = tf[2] * mf[2];
+				bf[3] = tf[3] * mf[3];
+			}
+		}
+	}
+	else {
+		for (; y < h; y++) {
+			b = (unsigned char *)ibuf->rect + (y * ibuf->x + origx) * 4;
+			t = (unsigned char *)texibuf->rect + (y * texibuf->x + origx) * 4;
+			m = (unsigned char *)maskibuf->rect + (y * maskibuf->x + origx) * 4;
+
+			if (dotexold)
+				ot = (unsigned char *)oldtexibuf->rect + ((y - origy + yt) * oldtexibuf->x + xt) * 4;
+
+			for (x = origx; x < w; x++, b += 4, m += 4, t += 4) {
+				if (dotexold) {
+					t[0] = ot[0];
+					t[1] = ot[1];
+					t[2] = ot[2];
+					t[3] = ot[3];
+					ot += 4;
+				}
+				else {
+					xy[0] = x + xoff;
+					xy[1] = y + yoff;
+
+					BKE_brush_sample_tex(scene, brush, xy, rgba, 0);
+					rgba_float_to_uchar(t, rgba);
+				}
+
+				b[0] = t[0] * m[0] / 255;
+				b[1] = t[1] * m[1] / 255;
+				b[2] = t[2] * m[2] / 255;
+				b[3] = t[3] * m[3] / 255;
+			}
+		}
+	}
+}
+
+static void brush_painter_fixed_tex_partial_update(BrushPainter *painter, const float pos[2])
+{
+	const Scene *scene = painter->scene;
+	Brush *brush = painter->brush;
+	BrushPainterCache *cache = &painter->cache;
+	ImBuf *oldtexibuf, *ibuf;
+	int imbflag, destx, desty, srcx, srcy, w, h, x1, y1, x2, y2;
+	const int diameter = 2 * BKE_brush_size_get(scene, brush);
+
+	imbflag = (cache->flt) ? IB_rectfloat : IB_rect;
+	if (!cache->ibuf)
+		cache->ibuf = IMB_allocImBuf(diameter, diameter, 32, imbflag);
+	ibuf = cache->ibuf;
+
+	oldtexibuf = cache->texibuf;
+	cache->texibuf = IMB_allocImBuf(diameter, diameter, 32, imbflag);
+
+	if (oldtexibuf) {
+		srcx = srcy = 0;
+		destx = (int)painter->lastpaintpos[0] - (int)pos[0];
+		desty = (int)painter->lastpaintpos[1] - (int)pos[1];
+		w = oldtexibuf->x;
+		h = oldtexibuf->y;
+
+		IMB_rectclip(cache->texibuf, oldtexibuf, &destx, &desty, &srcx, &srcy, &w, &h);
+	}
+	else {
+		srcx = srcy = 0;
+		destx = desty = 0;
+		w = h = 0;
+	}
+	
+	x1 = destx;
+	y1 = desty;
+	x2 = destx + w;
+	y2 = desty + h;
+
+	/* blend existing texture in new position */
+	if ((x1 < x2) && (y1 < y2))
+		brush_painter_do_partial(painter, oldtexibuf, x1, y1, x2, y2, srcx, srcy, pos);
+
+	if (oldtexibuf)
+		IMB_freeImBuf(oldtexibuf);
+
+	/* sample texture in new areas */
+	if ((0 < x1) && (0 < ibuf->y))
+		brush_painter_do_partial(painter, NULL, 0, 0, x1, ibuf->y, 0, 0, pos);
+	if ((x2 < ibuf->x) && (0 < ibuf->y))
+		brush_painter_do_partial(painter, NULL, x2, 0, ibuf->x, ibuf->y, 0, 0, pos);
+	if ((x1 < x2) && (0 < y1))
+		brush_painter_do_partial(painter, NULL, x1, 0, x2, y1, 0, 0, pos);
+	if ((x1 < x2) && (y2 < ibuf->y))
+		brush_painter_do_partial(painter, NULL, x1, y2, x2, ibuf->y, 0, 0, pos);
+}
+
+static void brush_painter_refresh_cache(BrushPainter *painter, const float pos[2], int use_color_correction)
+{
+	const Scene *scene = painter->scene;
+	Brush *brush = painter->brush;
+	BrushPainterCache *cache = &painter->cache;
+	MTex *mtex = &brush->mtex;
+	int size;
+	short flt;
+	const int diameter = 2 * BKE_brush_size_get(scene, brush);
+	const float alpha = BKE_brush_alpha_get(scene, brush);
+
+	if (diameter != cache->lastsize ||
+	    alpha != cache->lastalpha ||
+	    brush->jitter != cache->lastjitter)
+	{
+		if (cache->ibuf) {
+			IMB_freeImBuf(cache->ibuf);
+			cache->ibuf = NULL;
+		}
+		if (cache->maskibuf) {
+			IMB_freeImBuf(cache->maskibuf);
+			cache->maskibuf = NULL;
+		}
+
+		flt = cache->flt;
+		size = (cache->size) ? cache->size : diameter;
+
+		if (brush->flag & BRUSH_FIXED_TEX) {
+			BKE_brush_imbuf_new(scene, brush, flt, 3, size, &cache->maskibuf, use_color_correction);
+			brush_painter_fixed_tex_partial_update(painter, pos);
+		}
+		else
+			BKE_brush_imbuf_new(scene, brush, flt, 2, size, &cache->ibuf, use_color_correction);
+
+		cache->lastsize = diameter;
+		cache->lastalpha = alpha;
+		cache->lastjitter = brush->jitter;
+	}
+	else if ((brush->flag & BRUSH_FIXED_TEX) && mtex && mtex->tex) {
+		int dx = (int)painter->lastpaintpos[0] - (int)pos[0];
+		int dy = (int)painter->lastpaintpos[1] - (int)pos[1];
+
+		if ((dx != 0) || (dy != 0))
+			brush_painter_fixed_tex_partial_update(painter, pos);
+	}
+}
+
+void BKE_brush_painter_break_stroke(BrushPainter *painter)
+{
+	painter->firsttouch = 1;
+}
+
+
+int BKE_brush_painter_paint(BrushPainter *painter, BrushFunc func, const float pos[2], double time, float pressure,
+                            void *user, int use_color_correction)
+{
+	Scene *scene = painter->scene;
+	Brush *brush = painter->brush;
+	int totpaintops = 0;
+
+	if (pressure == 0.0f) {
+		if (painter->lastpressure) // XXX - hack, operator misses
+			pressure = painter->lastpressure;
+		else
+			pressure = 1.0f;    /* zero pressure == not using tablet */
+	}
+	if (painter->firsttouch) {
+		/* paint exactly once on first touch */
+		painter->startpaintpos[0] = pos[0];
+		painter->startpaintpos[1] = pos[1];
+
+		brush_pressure_apply(painter, brush, pressure);
+		if (painter->cache.enabled)
+			brush_painter_refresh_cache(painter, pos, use_color_correction);
+		totpaintops += func(user, painter->cache.ibuf, pos, pos);
+		
+		painter->lasttime = time;
+		painter->firsttouch = 0;
+		painter->lastpaintpos[0] = pos[0];
+		painter->lastpaintpos[1] = pos[1];
+	}
+#if 0
+	else if (painter->brush->flag & BRUSH_AIRBRUSH) {
+		float spacing, step, paintpos[2], dmousepos[2], len;
+		double starttime, curtime = time;
+
+		/* compute brush spacing adapted to brush size */
+		spacing = brush->rate; //radius*brush->spacing*0.01f;
+
+		/* setup starting time, direction vector and accumulated time */
+		starttime = painter->accumtime;
+		sub_v2_v2v2(dmousepos, pos, painter->lastmousepos);
+		len = normalize_v2(dmousepos);
+		painter->accumtime += curtime - painter->lasttime;
+
+		/* do paint op over unpainted time distance */
+		while (painter->accumtime >= spacing) {
+			step = (spacing - starttime) * len;
+			paintpos[0] = painter->lastmousepos[0] + dmousepos[0] * step;
+			paintpos[1] = painter->lastmousepos[1] + dmousepos[1] * step;
+
+			if (painter->cache.enabled)
+				brush_painter_refresh_cache(painter);
+			totpaintops += func(user, painter->cache.ibuf,
+			                    painter->lastpaintpos, paintpos);
+
+			painter->lastpaintpos[0] = paintpos[0];
+			painter->lastpaintpos[1] = paintpos[1];
+			painter->accumtime -= spacing;
+			starttime -= spacing;
+		}
+		
+		painter->lasttime = curtime;
+	}
+#endif
+	else {
+		float startdistance, spacing, step, paintpos[2], dmousepos[2], finalpos[2];
+		float t, len, press;
+		const int radius = BKE_brush_size_get(scene, brush);
+
+		/* compute brush spacing adapted to brush radius, spacing may depend
+		 * on pressure, so update it */
+		brush_pressure_apply(painter, brush, painter->lastpressure);
+		spacing = max_ff(1.0f, radius) * brush->spacing * 0.01f;
+
+		/* setup starting distance, direction vector and accumulated distance */
+		startdistance = painter->accumdistance;
+		sub_v2_v2v2(dmousepos, pos, painter->lastmousepos);
+		len = normalize_v2(dmousepos);
+		painter->accumdistance += len;
+
+		if (brush->flag & BRUSH_SPACE) {
+			/* do paint op over unpainted distance */
+			while ((len > 0.0f) && (painter->accumdistance >= spacing)) {
+				step = spacing - startdistance;
+				paintpos[0] = painter->lastmousepos[0] + dmousepos[0] * step;
+				paintpos[1] = painter->lastmousepos[1] + dmousepos[1] * step;
+
+				t = step / len;
+				press = (1.0f - t) * painter->lastpressure + t * pressure;
+				brush_pressure_apply(painter, brush, press);
+				spacing = max_ff(1.0f, radius) * brush->spacing * 0.01f;
+
+				BKE_brush_jitter_pos(scene, brush, paintpos, finalpos);
+
+				if (painter->cache.enabled)
+					brush_painter_refresh_cache(painter, finalpos, use_color_correction);
+
+				totpaintops +=
+				    func(user, painter->cache.ibuf, painter->lastpaintpos, finalpos);
+
+				painter->lastpaintpos[0] = paintpos[0];
+				painter->lastpaintpos[1] = paintpos[1];
+				painter->accumdistance -= spacing;
+				startdistance -= spacing;
+			}
+		}
+		else {
+			BKE_brush_jitter_pos(scene, brush, pos, finalpos);
+
+			if (painter->cache.enabled)
+				brush_painter_refresh_cache(painter, finalpos, use_color_correction);
+
+			totpaintops += func(user, painter->cache.ibuf, pos, finalpos);
+
+			painter->lastpaintpos[0] = pos[0];
+			painter->lastpaintpos[1] = pos[1];
+			painter->accumdistance = 0;
+		}
+
+		/* do airbrush paint ops, based on the number of paint ops left over
+		 * from regular painting. this is a temporary solution until we have
+		 * accurate time stamps for mouse move events */
+		if (brush->flag & BRUSH_AIRBRUSH) {
+			double curtime = time;
+			double painttime = brush->rate * totpaintops;
+
+			painter->accumtime += curtime - painter->lasttime;
+			if (painter->accumtime <= painttime)
+				painter->accumtime = 0.0;
+			else
+				painter->accumtime -= painttime;
+
+			while (painter->accumtime >= (double)brush->rate) {
+				brush_pressure_apply(painter, brush, pressure);
+
+				BKE_brush_jitter_pos(scene, brush, pos, finalpos);
+
+				if (painter->cache.enabled)
+					brush_painter_refresh_cache(painter, finalpos, use_color_correction);
+
+				totpaintops +=
+				    func(user, painter->cache.ibuf, painter->lastmousepos, finalpos);
+				painter->accumtime -= (double)brush->rate;
+			}
+
+			painter->lasttime = curtime;
+		}
+	}
+
+	painter->lastmousepos[0] = pos[0];
+	painter->lastmousepos[1] = pos[1];
+	painter->lastpressure = pressure;
+
+	BKE_brush_alpha_set(scene, brush, painter->startalpha);
+	BKE_brush_size_set(scene, brush, painter->startsize);
+	brush->jitter = painter->startjitter;
+	brush->spacing = painter->startspacing;
+
+	return totpaintops;
+}
+
+
+/* TODO: should probably be unified with BrushPainter stuff? */
+unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side)
+{
+	unsigned int *texcache = NULL;
+	MTex *mtex = &br->mtex;
+	TexResult texres = {0};
+	int hasrgb, ix, iy;
+	int side = half_side * 2;
+	
+	if (mtex->tex) {
+		float x, y, step = 2.0 / side, co[3];
+
+		texcache = MEM_callocN(sizeof(int) * side * side, "Brush texture cache");
+
+		/*do normalized cannonical view coords for texture*/
+		for (y = -1.0, iy = 0; iy < side; iy++, y += step) {
+			for (x = -1.0, ix = 0; ix < side; ix++, x += step) {
+				co[0] = x;
+				co[1] = y;
+				co[2] = 0.0f;
+				
+				/* This is copied from displace modifier code */
+				hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 0, &texres);
+			
+				/* if the texture gave an RGB value, we assume it didn't give a valid
+				 * intensity, so calculate one (formula from do_material_tex).
+				 * if the texture didn't give an RGB value, copy the intensity across
+				 */
+				if (hasrgb & TEX_RGB)
+					texres.tin = rgb_to_grayscale(&texres.tr);
+
+				((char *)texcache)[(iy * side + ix) * 4] =
+				((char *)texcache)[(iy * side + ix) * 4 + 1] =
+				((char *)texcache)[(iy * side + ix) * 4 + 2] =
+				((char *)texcache)[(iy * side + ix) * 4 + 3] = (char)(texres.tin * 255.0f);
+			}
+		}
+	}
+
+	return texcache;
+}
+
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 27aeccbde8a..5731b6379c9 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -3921,7 +3921,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
 	prop= RNA_def_property(srna, "use_bake_to_vertex_color", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "bake_flag", R_BAKE_VCOL);
 	RNA_def_property_ui_text(prop, "Bake to Vertex Colour",
-	                         "Bake to vertex colors instead of to a UV-mapped image.");
+	                         "Bake to vertex colors instead of to a UV-mapped image");
 	RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
 
 	/* stamp */
-- 
cgit v1.2.3


From ec1681fae7439c55cc632647d45aaf60e1fb7907 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Wed, 2 Jan 2013 01:49:07 +0000
Subject: style cleanup

---
 source/blender/blenkernel/BKE_pbvh.h                 | 2 +-
 source/blender/blenkernel/intern/cdderivedmesh.c     | 6 +++---
 source/blender/blenkernel/intern/object.c            | 4 ++--
 source/blender/blenlib/intern/math_geom.c            | 2 +-
 source/blender/editors/mesh/editmesh_tools.c         | 4 ++--
 source/blender/editors/sculpt_paint/paint_image_2d.c | 2 +-
 source/blender/editors/uvedit/uvedit_smart_stitch.c  | 4 ++--
 source/blender/makesrna/intern/rna_scene.c           | 2 +-
 8 files changed, 13 insertions(+), 13 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 63a61006606..709db7e4570 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -128,7 +128,7 @@ typedef enum {
 	PBVH_Collapse = 2,
 } PBVHTopologyUpdateMode;
 int BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode,
-								   const float center[3], float radius);
+                                   const float center[3], float radius);
 
 /* Node Access */
 
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 5f747827ba7..164faba1b1d 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -268,8 +268,8 @@ static PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
 		cddm->pbvh_draw = TRUE;
 
 		BKE_pbvh_build_bmesh(cddm->pbvh, ob->sculpt->bm,
-							 ob->sculpt->bm_smooth_shading,
-							 ob->sculpt->bm_log);
+		                     ob->sculpt->bm_smooth_shading,
+		                     ob->sculpt->bm_log);
 	}
 		
 
@@ -550,7 +550,7 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm,
 			float (*face_nors)[3] = CustomData_get_layer(&dm->faceData, CD_NORMAL);
 
 			BKE_pbvh_draw(cddm->pbvh, partial_redraw_planes, face_nors,
-						  setMaterial, FALSE);
+			              setMaterial, FALSE);
 			glShadeModel(GL_FLAT);
 		}
 
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 5914cbfc522..976818fe2df 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -276,7 +276,7 @@ void sculptsession_bm_to_me(struct Object *ob, int reorder)
 				BMFace *efa;
 				BM_ITER_MESH (efa, &iter, ss->bm, BM_FACES_OF_MESH) {
 					BM_elem_flag_set(efa, BM_ELEM_SMOOTH,
-									 ss->bm_smooth_shading);
+					                 ss->bm_smooth_shading);
 				}
 				if (reorder)
 					BM_log_mesh_elems_reorder(ss->bm, ss->bm_log);
@@ -300,7 +300,7 @@ void free_sculptsession(Object *ob)
 		if (ss->pbvh)
 			BKE_pbvh_free(ss->pbvh);
 		if (ss->bm_log)
- 			BM_log_free(ss->bm_log);
+			BM_log_free(ss->bm_log);
 
 		if (dm && dm->getPBVH)
 			dm->getPBVH(NULL, dm);  /* signal to clear */
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index eec59e47ea6..3527af365ec 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -301,7 +301,7 @@ float dist_to_line_segment_v3(const float v1[3], const float v2[3], const float
  * 
  * Set 'r' to the point in triangle (a, b, c) closest to point 'p' */
 void closest_on_tri_to_point_v3(float r[3], const float p[3],
-					   const float a[3], const float b[3], const float c[3])
+                                const float a[3], const float b[3], const float c[3])
 {
 	float ab[3], ac[3], ap[3], d1, d2;
 	float bp[3], d3, d4, vc, cp[3], d5, d6, vb, va;
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 81f18b6a551..b25b3cc683c 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -5747,6 +5747,6 @@ void MESH_OT_symmetrize(struct wmOperatorType *ot)
 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
 	ot->prop = RNA_def_enum(ot->srna, "direction", symmetrize_direction_items,
-							BMO_SYMMETRIZE_NEGATIVE_X,
-							"Direction", "Which sides to copy from and to");
+	                        BMO_SYMMETRIZE_NEGATIVE_X,
+	                        "Direction", "Which sides to copy from and to");
 }
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
index 80e189a08e1..2e5ab757be3 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -25,7 +25,7 @@
  * ***** END GPL LICENSE BLOCK *****
  */
 
-/** \file blender/editors/sculpt_paint/paint_2D.c
+/** \file blender/editors/sculpt_paint/paint_image_2d.c
  *  \ingroup bke
  */
 //#include 
diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c
index dc9f5fbf97c..8c3eaa1192f 100644
--- a/source/blender/editors/uvedit/uvedit_smart_stitch.c
+++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c
@@ -545,8 +545,8 @@ static void stitch_island_calculate_vert_rotation(UvElement *element, StitchStat
 			edgecos = dot_v2v2(normal, state->normals + index_tmp1 * 2);
 			edgesin = cross_v2v2(normal, state->normals + index_tmp1 * 2);
 			rotation += (edgesin > 0.0f) ?
-				+acosf(max_ff(-1.0f, min_ff(1.0f, edgecos))) :
-	            -acosf(max_ff(-1.0f, min_ff(1.0f, edgecos)));
+			    +acosf(max_ff(-1.0f, min_ff(1.0f, edgecos))) :
+			    -acosf(max_ff(-1.0f, min_ff(1.0f, edgecos)));
 		}
 	}
 
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 5731b6379c9..7507e90525e 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -3918,7 +3918,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
 	RNA_def_property_ui_text(prop, "Samples", "Number of samples used for ambient occlusion baking from multires");
 	RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
 
-	prop= RNA_def_property(srna, "use_bake_to_vertex_color", PROP_BOOLEAN, PROP_NONE);
+	prop = RNA_def_property(srna, "use_bake_to_vertex_color", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "bake_flag", R_BAKE_VCOL);
 	RNA_def_property_ui_text(prop, "Bake to Vertex Colour",
 	                         "Bake to vertex colors instead of to a UV-mapped image");
-- 
cgit v1.2.3


From 8b8e5882aa7739af4ce280496b34050f67c193f1 Mon Sep 17 00:00:00 2001
From: Joshua Leung 
Date: Wed, 2 Jan 2013 02:08:43 +0000
Subject: Replacing/cleaning up some gibberish...

---
 source/blender/blenkernel/intern/constraint.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 4874a3a019d..1a25def3829 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -4610,7 +4610,7 @@ short BKE_proxylocked_constraints_owner(Object *ob, bPoseChannel *pchan)
  * None of the actual calculations of the matrices should be done here! Also, this function is
  * not to be used by any new constraints, particularly any that have multiple targets.
  */
-void BKE_get_constraint_target_matrix(struct Scene *scene, bConstraint *con, int n, short ownertype, void *ownerdata, float mat[4][4], float ctime)
+void BKE_get_constraint_target_matrix(Scene *scene, bConstraint *con, int index, short ownertype, void *ownerdata, float mat[4][4], float ctime)
 {
 	bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
 	ListBase targets = {NULL, NULL};
@@ -4657,10 +4657,8 @@ void BKE_get_constraint_target_matrix(struct Scene *scene, bConstraint *con, int
 		cti->get_constraint_targets(con, &targets);
 		
 		/* only calculate the target matrix on the first target */
-		ct = (bConstraintTarget *)targets.first;
-		while (ct && n-- > 0)
-			ct = ct->next;
-
+		ct = (bConstraintTarget *)BLI_findlink(&targets, index);
+		
 		if (ct) {
 			if (cti->get_target_matrix)
 				cti->get_target_matrix(con, cob, ct, ctime);
-- 
cgit v1.2.3


From a8a60c6566c1097355f55d64d9861ed850040a1c Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Wed, 2 Jan 2013 02:12:10 +0000
Subject: dyntopo speedup for smooth brush, no need to search for the shared
 vert-face loop, instead just iterate over the loops.

---
 source/blender/editors/sculpt_paint/sculpt.c | 32 ++++++++++------------------
 1 file changed, 11 insertions(+), 21 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 098d8e5006f..54ae2ebf588 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -1353,24 +1353,19 @@ 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)
 {
-	int vfcount = BM_vert_face_count(v);
+	const int vfcount = BM_vert_face_count(v);
 
 	zero_v3(avg);
 		
 	/* Don't modify corner vertices */
 	if (vfcount > 1) {
-		BMIter iter;
-		BMFace *f;
+		BMIter liter;
+		BMLoop *l;
 		int i, total = 0;
 
-		BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
-			BMLoop *l1 = BM_face_vert_share_loop(f, v);
-			BMLoop *l2 = BM_loop_other_vert_loop(l1, v);
-			BMVert *adj_v[3] = {
-				BM_edge_other_vert(l1->e, v),
-				v,
-				BM_edge_other_vert(l2->e, v)};
-			
+		BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
+			BMVert *adj_v[3] = {l->prev->v, v, l->next->v};
+
 			for (i = 0; i < 3; i++) {
 				if (vfcount != 2 || BM_vert_face_count(adj_v[i]) <= 2) {
 					add_v3_v3(avg, adj_v[i]->co);
@@ -1391,19 +1386,14 @@ 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)
 {
-	BMIter iter;
-	BMFace *f;
+	BMIter liter;
+	BMLoop *l;
 	float avg = 0;
 	int i, total = 0;
 
-	BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
-		BMLoop *l1 = BM_face_vert_share_loop(f, v);
-		BMLoop *l2 = BM_loop_other_vert_loop(l1, v);
-		BMVert *adj_v[3] = {
-			BM_edge_other_vert(l1->e, v),
-			v,
-			BM_edge_other_vert(l2->e, v)};
-			
+	BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
+		BMVert *adj_v[3] = {l->prev->v, v, l->next->v};
+
 		for (i = 0; i < 3; i++) {
 			BMVert *v2 = adj_v[i];
 			float *vmask = CustomData_bmesh_get(&bm->vdata,
-- 
cgit v1.2.3


From 9190c493c17b09dc52b96bb46439d03df086ad7c Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Wed, 2 Jan 2013 05:00:02 +0000
Subject: extend BLI_buffer - add option to calloc or not, existing code wasnt
 consistent here, would calloc on first alloc but not on realloc, also - the
 static memory was never zero'd.   use flag BLI_BUFFER_USE_CALLOC to ensure
 all new memory is zero'd (static/alloc/realloc's).

- add BLI_buffer_declare_static / BLI_buffer_declare so its possible to have a buffer that never uses static memory.
---
 source/blender/blenkernel/intern/pbvh_bmesh.c |  5 +--
 source/blender/blenlib/BLI_buffer.h           | 42 ++++++++++++++++++-------
 source/blender/blenlib/intern/buffer.c        | 45 ++++++++++++++++++++-------
 3 files changed, 68 insertions(+), 24 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index 5d60957abcb..791288a4dda 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -1040,8 +1040,9 @@ void BKE_pbvh_build_bmesh(PBVH *bvh, BMesh *bm, int smooth_shading,
 int BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode,
 								   const float center[3], float radius)
 {
-	BLI_buffer_declare(BMFace*, edge_faces, 8);
-	BLI_buffer_declare(BMFace*, deleted_faces, 32);
+	BLI_buffer_declare_static(BMFace *, edge_faces, BLI_BUFFER_NOP, 8);
+	BLI_buffer_declare_static(BMFace *, deleted_faces, BLI_BUFFER_NOP, 32);
+
 	int modified = FALSE;
 	int n;
 
diff --git a/source/blender/blenlib/BLI_buffer.h b/source/blender/blenlib/BLI_buffer.h
index 7c14736ec40..4f053179d84 100644
--- a/source/blender/blenlib/BLI_buffer.h
+++ b/source/blender/blenlib/BLI_buffer.h
@@ -28,7 +28,7 @@
 /* Usage examples:
  *
  * { 
- *     BLI_buffer_declare(int, my_int_array, 32);
+ *     BLI_buffer_declare_static(int, my_int_array, BLI_BUFFER_NOP, 32);
  *
  *     BLI_buffer_append(my_int_array, int, 42);
  *     assert(my_int_array.count == 1);
@@ -42,23 +42,43 @@ typedef struct {
 	void *data;
 	const int elem_size;
 	int count, alloc_count;
-	int using_static;
+	int flag;
 } BLI_Buffer;
 
-#define BLI_buffer_declare(type_, name_, static_count_) \
+enum {
+	BLI_BUFFER_NOP        = 0,
+	BLI_BUFFER_USE_STATIC = (1 << 0),
+	BLI_BUFFER_USE_CALLOC = (1 << 1),  /* ensure the array is always calloc'd */
+};
+
+#define BLI_buffer_declare_static(type_, name_, flag_, static_count_) \
 	type_ *name_ ## _static_[static_count_]; \
-	BLI_Buffer name_ = {name_ ## _static_, \
-						sizeof(type_), \
-						0, \
-						static_count_, \
-						TRUE}
+	BLI_Buffer name_ = { \
+	/* clear the static memory if this is a calloc'd array */ \
+	((void)((flag_ & BLI_BUFFER_USE_CALLOC) ? \
+	          memset(name_ ## _static_, 0, sizeof(name_ ## _static_)) : 0\
+	), /* memset-end */ \
+	                    name_ ## _static_), \
+	                    sizeof(type_), \
+	                    0, \
+	                    static_count_, \
+	                    BLI_BUFFER_USE_STATIC | flag_}
+
+/* never use static*/
+#define BLI_buffer_declare(type_, name_, flag_) \
+	BLI_Buffer name_ = {NULL, \
+	                    sizeof(type_), \
+	                    0, \
+	                    0, \
+	                    flag_}
 
 #define BLI_buffer_at(buffer_, type_, index_) \
 	(((type_*)(buffer_)->data)[index_])
 
-#define BLI_buffer_append(buffer_, type_, val_) \
+#define BLI_buffer_append(buffer_, type_, val_)  { \
 	BLI_buffer_resize(buffer_, (buffer_)->count + 1); \
-	BLI_buffer_at(buffer_, type_, (buffer_)->count - 1) = val_
+	BLI_buffer_at(buffer_, type_, (buffer_)->count - 1) = val_; \
+} (void)0
 
 /* Never decreases the amount of memory allocated */
 void BLI_buffer_resize(BLI_Buffer *buffer, int new_count);
@@ -66,4 +86,4 @@ void BLI_buffer_resize(BLI_Buffer *buffer, int new_count);
 /* Does not free the buffer structure itself */
 void BLI_buffer_free(BLI_Buffer *buffer);
 
-#endif
+#endif  /* __BLI_BUFFER_H__ */
diff --git a/source/blender/blenlib/intern/buffer.c b/source/blender/blenlib/intern/buffer.c
index 98151c8eebf..b2280b9a0d1 100644
--- a/source/blender/blenlib/intern/buffer.c
+++ b/source/blender/blenlib/intern/buffer.c
@@ -25,25 +25,45 @@
 
 #include 
 
+static void *buffer_alloc(BLI_Buffer *buffer, int len)
+{
+	return ((buffer->flag & BLI_BUFFER_USE_CALLOC) ?
+	        MEM_callocN : MEM_mallocN)
+	        (buffer->elem_size * len, "BLI_Buffer.data");
+}
+
+static void *buffer_realloc(BLI_Buffer *buffer, int len)
+{
+	return ((buffer->flag & BLI_BUFFER_USE_CALLOC) ?
+	        MEM_recallocN : MEM_reallocN)
+	        (buffer->data, (buffer->elem_size * len));
+}
+
 void BLI_buffer_resize(BLI_Buffer *buffer, int new_count)
 {
 	if (new_count > buffer->alloc_count) {
-		if (buffer->using_static) {
+		if (buffer->flag & BLI_BUFFER_USE_STATIC) {
 			void *orig = buffer->data;
-			buffer->data = MEM_callocN(buffer->elem_size * new_count,
-									   "BLI_Buffer.data");
+
+			buffer->data = buffer_alloc(buffer, new_count);
 			memcpy(buffer->data, orig, buffer->elem_size * buffer->count);
 			buffer->alloc_count = new_count;
-			buffer->using_static = FALSE;
+			buffer->flag &= ~BLI_BUFFER_USE_STATIC;
 		}
 		else {
-			if (new_count < buffer->alloc_count * 2)
+			if (buffer->alloc_count && (new_count < buffer->alloc_count * 2)) {
 				buffer->alloc_count *= 2;
-			else
+			}
+			else {
 				buffer->alloc_count = new_count;
-			buffer->data = MEM_reallocN(buffer->data,
-										(buffer->elem_size *
-										 buffer->alloc_count));
+			}
+
+			if (buffer->data) {
+				buffer->data = buffer_realloc(buffer, buffer->alloc_count);
+			}
+			else {
+				buffer->data = buffer_alloc(buffer, buffer->alloc_count);
+			}
 		}
 	}
 
@@ -52,7 +72,10 @@ void BLI_buffer_resize(BLI_Buffer *buffer, int new_count)
 
 void BLI_buffer_free(BLI_Buffer *buffer)
 {
-	if (!buffer->using_static)
-		MEM_freeN(buffer->data);
+	if ((buffer->flag & BLI_BUFFER_USE_STATIC) == 0) {
+		if (buffer->data) {
+			MEM_freeN(buffer->data);
+		}
+	}
 	memset(buffer, 0, sizeof(*buffer));
 }
-- 
cgit v1.2.3


From 0d95dde79b3ed6b0e6ea375c2536699aa1bec4c9 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Wed, 2 Jan 2013 05:19:55 +0000
Subject: add assert to BLI_buffer_at if a type is given different to
 'elem_size'

---
 source/blender/blenlib/BLI_buffer.h | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenlib/BLI_buffer.h b/source/blender/blenlib/BLI_buffer.h
index 4f053179d84..880a97acb80 100644
--- a/source/blender/blenlib/BLI_buffer.h
+++ b/source/blender/blenlib/BLI_buffer.h
@@ -72,13 +72,14 @@ enum {
 	                    0, \
 	                    flag_}
 
-#define BLI_buffer_at(buffer_, type_, index_) \
-	(((type_*)(buffer_)->data)[index_])
 
-#define BLI_buffer_append(buffer_, type_, val_)  { \
-	BLI_buffer_resize(buffer_, (buffer_)->count + 1); \
-	BLI_buffer_at(buffer_, type_, (buffer_)->count - 1) = val_; \
-} (void)0
+#define BLI_buffer_at(buffer_, type_, index_) ( \
+	(((type_ *)(buffer_)->data)[(BLI_assert(sizeof(type_) == (buffer_)->elem_size)), index_]))
+
+#define BLI_buffer_append(buffer_, type_, val_)  ( \
+	BLI_buffer_resize(buffer_, (buffer_)->count + 1), \
+	(BLI_buffer_at(buffer_, type_, (buffer_)->count - 1) = val_) \
+)
 
 /* Never decreases the amount of memory allocated */
 void BLI_buffer_resize(BLI_Buffer *buffer, int new_count);
-- 
cgit v1.2.3


From a94e4e0ef84ff53012c5f2708a63174feb6e726d Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Wed, 2 Jan 2013 06:09:53 +0000
Subject: fix [#33726] keyframe_insert() and keyframe_delete() with index=-1
 always fail

The bug was introduced in r53297, was calling pyrna_struct_anim_args_parse() twice for no reason, perhaps baddly applied patch?.
---
 source/blender/python/intern/bpy_rna_anim.c | 3 ---
 1 file changed, 3 deletions(-)

(limited to 'source')

diff --git a/source/blender/python/intern/bpy_rna_anim.c b/source/blender/python/intern/bpy_rna_anim.c
index cacae8fd184..0acfc36bb4e 100644
--- a/source/blender/python/intern/bpy_rna_anim.c
+++ b/source/blender/python/intern/bpy_rna_anim.c
@@ -167,9 +167,6 @@ static int pyrna_struct_keyframe_parse(
 		*cfra = CTX_data_scene(BPy_GetContext())->r.cfra;
 
 	/* flag may be null (no option currently for remove keyframes e.g.). */
-	if (pyrna_struct_anim_args_parse(ptr, error_prefix, path, path_full, index) < 0)
-		return -1;
-
 	if (pyoptions && options && (pyrna_set_to_enum_bitfield(keying_flag_items, pyoptions, options, error_prefix) < 0))
 		return -1;
 
-- 
cgit v1.2.3


From 55f33619246d60050cf94fcb4ed026d5e306e10e Mon Sep 17 00:00:00 2001
From: Jens Verwiebe 
Date: Wed, 2 Jan 2013 13:41:30 +0000
Subject: Fix playercompile with stub for BKE_brush_gen_texture_cache

---
 source/blenderplayer/bad_level_call_stubs/stubs.c | 1 +
 1 file changed, 1 insertion(+)

(limited to 'source')

diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index ce0576c68d1..e457b577c43 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -511,6 +511,7 @@ float sculpt_get_brush_alpha(struct Brush *brush) {return 0.0f;}
 void sculpt_set_brush_alpha(struct Brush *brush, float alpha) {}
 void ED_sculpt_modifiers_changed(struct Object *ob) {}
 void ED_mesh_calc_tessface(struct Mesh *mesh) {}
+void BKE_brush_gen_texture_cache(struct Brush *br, int half_side) {}
 
 /* bpy/python internal api */
 void operator_wrapper(struct wmOperatorType *ot, void *userdata) {}
-- 
cgit v1.2.3


From dadb1ccd9298688addf811dd62e6dcc6b4f49a45 Mon Sep 17 00:00:00 2001
From: Bastien Montagne 
Date: Wed, 2 Jan 2013 16:03:58 +0000
Subject: Fix [#33189] AFTER 2.65 - Units in doc strings in ocean modifier.

Also:
* Fixes a (op prop) bug which prevented, once you had baked and freed ocean once, to bake again.
* Fixed infinite values of acumulated foam when baking with foam_fade values above 1.0, now simply clipping accumulated foam value to 1.0, as already done for the "instantaneaous" foam value returned by BKE_ocean_jminus_to_foam().
* Added missing RNA descriptions.
* Made foam_fade unanimatable!
* Added in UI some missing properties that are imho useful: random seed, size (kindof 'surface scaling'), and foam_fade (baking only).
* Removed custom lerp() func from bke's ocean.c, BLI's interpf does exactly the same thing (the first two args are just in reversed order). Note: this could most certainly be done in other parts of the code, bpy's mathutils for e.g. has its own linear interpolation code for vectors and matrices :/).
* Did some general code cleanup (mostly line length and no C++ -> C comments)...
---
 source/blender/blenkernel/intern/ocean.c      | 352 +++++++++++++++-----------
 source/blender/makesrna/intern/rna_modifier.c |  39 +--
 source/blender/modifiers/intern/MOD_ocean.c   |  28 +-
 3 files changed, 233 insertions(+), 186 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c
index 57234a5feae..c4274aa1f93 100644
--- a/source/blender/blenkernel/intern/ocean.c
+++ b/source/blender/blenkernel/intern/ocean.c
@@ -35,16 +35,15 @@
 
 #include "DNA_scene_types.h"
 
+#include "BKE_global.h" /* XXX TESTING */
 #include "BKE_image.h"
 #include "BKE_ocean.h"
-#include "BKE_global.h" // XXX TESTING
 
-#include "BLI_math_base.h"
-#include "BLI_math_inline.h"
+#include "BLI_math.h"
+#include "BLI_path_util.h"
 #include "BLI_rand.h"
 #include "BLI_string.h"
 #include "BLI_threads.h"
-#include "BLI_path_util.h"
 #include "BLI_utildefines.h"
 
 #include "IMB_imbuf.h"
@@ -54,7 +53,7 @@
 
 #ifdef WITH_OCEANSIM
 
-// Ocean code
+/* Ocean code */
 #include "fftw3.h"
 
 #define GRAVITY  9.81f
@@ -82,7 +81,7 @@ typedef struct Ocean {
 	float _Lx;
 	float _Lz;
 
-	float normalize_factor;                 // init w
+	float normalize_factor;                 /* init w */
 	float time;
 
 	short _do_disp_y;
@@ -96,51 +95,52 @@ typedef struct Ocean {
 	/* ********* sim data arrays ********* */
 
 	/* two dimensional arrays of complex */
-	fftw_complex *_fft_in;          // init w	sim w
-	fftw_complex *_fft_in_x;        // init w	sim w
-	fftw_complex *_fft_in_z;        // init w	sim w
-	fftw_complex *_fft_in_jxx;      // init w	sim w
-	fftw_complex *_fft_in_jzz;      // init w	sim w
-	fftw_complex *_fft_in_jxz;      // init w	sim w
-	fftw_complex *_fft_in_nx;       // init w	sim w
-	fftw_complex *_fft_in_nz;       // init w	sim w
-	fftw_complex *_htilda;          // init w	sim w (only once)
+	fftw_complex *_fft_in;          /* init w	sim w */
+	fftw_complex *_fft_in_x;        /* init w	sim w */
+	fftw_complex *_fft_in_z;        /* init w	sim w */
+	fftw_complex *_fft_in_jxx;      /* init w	sim w */
+	fftw_complex *_fft_in_jzz;      /* init w	sim w */
+	fftw_complex *_fft_in_jxz;      /* init w	sim w */
+	fftw_complex *_fft_in_nx;       /* init w	sim w */
+	fftw_complex *_fft_in_nz;       /* init w	sim w */
+	fftw_complex *_htilda;          /* init w	sim w (only once) */
 
 	/* fftw "plans" */
-	fftw_plan _disp_y_plan;         // init w	sim r
-	fftw_plan _disp_x_plan;         // init w	sim r
-	fftw_plan _disp_z_plan;         // init w	sim r
-	fftw_plan _N_x_plan;            // init w	sim r
-	fftw_plan _N_z_plan;            // init w	sim r
-	fftw_plan _Jxx_plan;            // init w	sim r
-	fftw_plan _Jxz_plan;            // init w	sim r
-	fftw_plan _Jzz_plan;            // init w	sim r
+	fftw_plan _disp_y_plan;         /* init w	sim r */
+	fftw_plan _disp_x_plan;         /* init w	sim r */
+	fftw_plan _disp_z_plan;         /* init w	sim r */
+	fftw_plan _N_x_plan;            /* init w	sim r */
+	fftw_plan _N_z_plan;            /* init w	sim r */
+	fftw_plan _Jxx_plan;            /* init w	sim r */
+	fftw_plan _Jxz_plan;            /* init w	sim r */
+	fftw_plan _Jzz_plan;            /* init w	sim r */
 
 	/* two dimensional arrays of float */
-	double *_disp_y;                // init w	sim w via plan?
-	double *_N_x;                   // init w	sim w via plan?
-	/*float * _N_y; all member of this array has same values, so convert this array to a float to reduce memory usage (MEM01)*/
-	double _N_y;                    //			sim w ********* can be rearranged?
-	double *_N_z;                   // init w	sim w via plan?
-	double *_disp_x;                // init w	sim w via plan?
-	double *_disp_z;                // init w	sim w via plan?
+	double *_disp_y;                /* init w	sim w via plan? */
+	double *_N_x;                   /* init w	sim w via plan? */
+	/* all member of this array has same values, so convert this array to a float to reduce memory usage (MEM01)*/
+	/*float * _N_y; */
+	double _N_y;                    /*			sim w ********* can be rearranged? */
+	double *_N_z;                   /* init w	sim w via plan? */
+	double *_disp_x;                /* init w	sim w via plan? */
+	double *_disp_z;                /* init w	sim w via plan? */
 
 	/* two dimensional arrays of float */
 	/* Jacobian and minimum eigenvalue */
-	double *_Jxx;                   // init w	sim w
-	double *_Jzz;                   // init w	sim w
-	double *_Jxz;                   // init w	sim w
+	double *_Jxx;                   /* init w	sim w */
+	double *_Jzz;                   /* init w	sim w */
+	double *_Jxz;                   /* init w	sim w */
 
 	/* one dimensional float array */
-	float *_kx;                     // init w	sim r
-	float *_kz;                     // init w	sim r
+	float *_kx;                     /* init w	sim r */
+	float *_kz;                     /* init w	sim r */
 
 	/* two dimensional complex array */
-	fftw_complex *_h0;              // init w	sim r
-	fftw_complex *_h0_minus;        // init w	sim r
+	fftw_complex *_h0;              /* init w	sim r */
+	fftw_complex *_h0_minus;        /* init w	sim r */
 
 	/* two dimensional float array */
-	float *_k;                      // init w	sim r
+	float *_k;                      /* init w	sim r */
 } Ocean;
 
 
@@ -152,10 +152,13 @@ static float nextfr(float min, float max)
 
 static float gaussRand(void)
 {
-	float x;        // Note: to avoid numerical problems with very small
-	float y;        // numbers, we make these variables singe-precision
-	float length2;  // floats, but later we call the double-precision log()
-	// and sqrt() functions instead of logf() and sqrtf().
+	/* Note: to avoid numerical problems with very small numbers, we make these variables singe-precision floats,
+	 * but later we call the double-precision log() and sqrt() functions instead of logf() and sqrtf().
+	 */ 
+	float x;
+	float y;
+	float length2;
+
 	do {
 		x = (float) (nextfr(-1, 1));
 		y = (float)(nextfr(-1, 1));
@@ -167,12 +170,7 @@ static float gaussRand(void)
 
 /**
  * Some useful functions
- * */
-MINLINE float lerp(float a, float b, float f)
-{
-	return a + (b - a) * f;
-}
-
+ */
 MINLINE float catrom(float p0, float p1, float p2, float p3, float f)
 {
 	return 0.5f * ((2.0f * p1) +
@@ -186,23 +184,24 @@ MINLINE float omega(float k, float depth)
 	return sqrtf(GRAVITY * k * tanhf(k * depth));
 }
 
-// modified Phillips spectrum
+/* modified Phillips spectrum */
 static float Ph(struct Ocean *o, float kx, float kz)
 {
 	float tmp;
 	float k2 = kx * kx + kz * kz;
 
 	if (k2 == 0.0f) {
-		return 0.0f; // no DC component
+		return 0.0f; /* no DC component */
 	}
 
-	// damp out the waves going in the direction opposite the wind
+	/* damp out the waves going in the direction opposite the wind */
 	tmp = (o->_wx * kx + o->_wz * kz) / sqrtf(k2);
 	if (tmp < 0) {
 		tmp *= o->_damp_reflections;
 	}
 
-	return o->_A * expf(-1.0f / (k2 * (o->_L * o->_L))) * expf(-k2 * (o->_l * o->_l)) * powf(fabsf(tmp), o->_wind_alignment) / (k2 * k2);
+	return o->_A * expf(-1.0f / (k2 * (o->_L * o->_L))) * expf(-k2 * (o->_l * o->_l)) *
+	       powf(fabsf(tmp), o->_wind_alignment) / (k2 * k2);
 }
 
 static void compute_eigenstuff(struct OceanResult *ocr, float jxx, float jzz, float jxz)
@@ -240,7 +239,7 @@ static void init_complex(fftw_complex cmpl, float real, float image)
 	cmpl[1] = image;
 }
 
-#if 0   // unused
+#if 0   /* unused */
 static void add_complex_f(fftw_complex res, fftw_complex cmpl, float f)
 {
 	res[0] = cmpl[0] + f;
@@ -306,7 +305,7 @@ void BKE_ocean_eval_uv(struct Ocean *oc, struct OceanResult *ocr, float u, float
 	float frac_x, frac_z;
 	float uu, vv;
 
-	// first wrap the texture so 0 <= (u, v) < 1
+	/* first wrap the texture so 0 <= (u, v) < 1 */
 	u = fmodf(u, 1.0f);
 	v = fmodf(v, 1.0f);
 
@@ -334,7 +333,9 @@ void BKE_ocean_eval_uv(struct Ocean *oc, struct OceanResult *ocr, float u, float
 	j1 = j1 % oc->_N;
 
 
-#define BILERP(m) (lerp(lerp(m[i0 * oc->_N + j0], m[i1 * oc->_N + j0], frac_x), lerp(m[i0 * oc->_N + j1], m[i1 * oc->_N + j1], frac_x), frac_z))
+#define BILERP(m) (interpf(interpf(m[i1 * oc->_N + j1], m[i0 * oc->_N + j1], frac_x), \
+                           interpf(m[i1 * oc->_N + j0], m[i0 * oc->_N + j0], frac_x), \
+                           frac_z))
 	{
 		if (oc->_do_disp_y) {
 			ocr->disp[1] = BILERP(oc->_disp_y);
@@ -364,14 +365,14 @@ void BKE_ocean_eval_uv(struct Ocean *oc, struct OceanResult *ocr, float u, float
 	BLI_rw_mutex_unlock(&oc->oceanmutex);
 }
 
-// use catmullrom interpolation rather than linear
+/* use catmullrom interpolation rather than linear */
 void BKE_ocean_eval_uv_catrom(struct Ocean *oc, struct OceanResult *ocr, float u, float v)
 {
 	int i0, i1, i2, i3, j0, j1, j2, j3;
 	float frac_x, frac_z;
 	float uu, vv;
 
-	// first wrap the texture so 0 <= (u, v) < 1
+	/* first wrap the texture so 0 <= (u, v) < 1 */
 	u = fmod(u, 1.0f);
 	v = fmod(v, 1.0f);
 
@@ -408,11 +409,15 @@ void BKE_ocean_eval_uv_catrom(struct Ocean *oc, struct OceanResult *ocr, float u
 	j0 = j0 <   0 ? j0 + oc->_N : j0;
 	j3 = j3 >= oc->_N ? j3 - oc->_N : j3;
 
-#define INTERP(m) catrom(catrom(m[i0 * oc->_N + j0], m[i1 * oc->_N + j0], m[i2 * oc->_N + j0], m[i3 * oc->_N + j0], frac_x), \
-	                     catrom(m[i0 * oc->_N + j1], m[i1 * oc->_N + j1], m[i2 * oc->_N + j1], m[i3 * oc->_N + j1], frac_x), \
-	                     catrom(m[i0 * oc->_N + j2], m[i1 * oc->_N + j2], m[i2 * oc->_N + j2], m[i3 * oc->_N + j2], frac_x), \
-	                     catrom(m[i0 * oc->_N + j3], m[i1 * oc->_N + j3], m[i2 * oc->_N + j3], m[i3 * oc->_N + j3], frac_x), \
-	                     frac_z)
+#define INTERP(m) catrom(catrom(m[i0 * oc->_N + j0], m[i1 * oc->_N + j0], \
+                                m[i2 * oc->_N + j0], m[i3 * oc->_N + j0], frac_x), \
+                         catrom(m[i0 * oc->_N + j1], m[i1 * oc->_N + j1], \
+                                m[i2 * oc->_N + j1], m[i3 * oc->_N + j1], frac_x), \
+                         catrom(m[i0 * oc->_N + j2], m[i1 * oc->_N + j2], \
+                                m[i2 * oc->_N + j2], m[i3 * oc->_N + j2], frac_x), \
+                         catrom(m[i0 * oc->_N + j3], m[i1 * oc->_N + j3], \
+                                m[i2 * oc->_N + j3], m[i3 * oc->_N + j3], frac_x), \
+                         frac_z)
 
 	{
 		if (oc->_do_disp_y) {
@@ -452,9 +457,9 @@ void BKE_ocean_eval_xz_catrom(struct Ocean *oc, struct OceanResult *ocr, float x
 	BKE_ocean_eval_uv_catrom(oc, ocr, x / oc->_Lx, z / oc->_Lz);
 }
 
-// note that this doesn't wrap properly for i, j < 0, but its
-// not really meant for that being just a way to get the raw data out
-// to save in some image format.
+/* note that this doesn't wrap properly for i, j < 0, but its not really meant for that being just a way to get
+ * the raw data out to save in some image format.
+ */
 void BKE_ocean_eval_ij(struct Ocean *oc, struct OceanResult *ocr, int i, int j)
 {
 	BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_READ);
@@ -496,11 +501,10 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount
 
 	BLI_rw_mutex_lock(&o->oceanmutex, THREAD_LOCK_WRITE);
 
-	// compute a new htilda
+	/* compute a new htilda */
 #pragma omp parallel for private(i, j)
 	for (i = 0; i < o->_M; ++i) {
-		// note the <= _N/2 here, see the fftw doco about
-		// the mechanics of the complex->real fft storage
+		/* note the <= _N/2 here, see the fftw doco about the mechanics of the complex->real fft storage */
 		for (j = 0; j <= o->_N / 2; ++j) {
 			fftw_complex exp_param1;
 			fftw_complex exp_param2;
@@ -527,15 +531,15 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount
 #pragma omp section
 		{
 			if (o->_do_disp_y) {
-				// y displacement
+				/* y displacement */
 				fftw_execute(o->_disp_y_plan);
 			}
-		} // section 1
+		} /* section 1 */
 
 #pragma omp section
 		{
 			if (o->_do_chop) {
-				// x displacement
+				/* x displacement */
 				for (i = 0; i < o->_M; ++i) {
 					for (j = 0; j <= o->_N / 2; ++j) {
 						fftw_complex mul_param;
@@ -546,18 +550,21 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount
 						mul_complex_f(mul_param, mul_param, chop_amount);
 						mul_complex_c(mul_param, mul_param, minus_i);
 						mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
-						mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0f ? 0.0f : o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j]));
+						mul_complex_f(mul_param, mul_param,
+						              ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
+						               0.0f :
+						               o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j]));
 						init_complex(o->_fft_in_x[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
 					}
 				}
 				fftw_execute(o->_disp_x_plan);
 			}
-		} //section 2
+		} /* section 2 */
 
 #pragma omp section
 		{
 			if (o->_do_chop) {
-				// z displacement
+				/* z displacement */
 				for (i = 0; i < o->_M; ++i) {
 					for (j = 0; j <= o->_N / 2; ++j) {
 						fftw_complex mul_param;
@@ -568,28 +575,34 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount
 						mul_complex_f(mul_param, mul_param, chop_amount);
 						mul_complex_c(mul_param, mul_param, minus_i);
 						mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
-						mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0f ? 0.0f : o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j]));
+						mul_complex_f(mul_param, mul_param,
+						              ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
+						               0.0f :
+						               o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j]));
 						init_complex(o->_fft_in_z[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
 					}
 				}
 				fftw_execute(o->_disp_z_plan);
 			}
-		} // section 3
+		} /* section 3 */
 
 #pragma omp section
 		{
 			if (o->_do_jacobian) {
-				// Jxx
+				/* Jxx */
 				for (i = 0; i < o->_M; ++i) {
 					for (j = 0; j <= o->_N / 2; ++j) {
 						fftw_complex mul_param;
 
-						//init_complex(mul_param, -scale, 0);
+						/* init_complex(mul_param, -scale, 0); */
 						init_complex(mul_param, -1, 0);
 
 						mul_complex_f(mul_param, mul_param, chop_amount);
 						mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
-						mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0f ? 0.0f : o->_kx[i] * o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j]));
+						mul_complex_f(mul_param, mul_param,
+						              ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
+						               0.0f :
+						               o->_kx[i] * o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j]));
 						init_complex(o->_fft_in_jxx[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
 					}
 				}
@@ -601,22 +614,25 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount
 					}
 				}
 			}
-		} // section 4
+		} /* section 4 */
 
 #pragma omp section
 		{
 			if (o->_do_jacobian) {
-				// Jzz
+				/* Jzz */
 				for (i = 0; i < o->_M; ++i) {
 					for (j = 0; j <= o->_N / 2; ++j) {
 						fftw_complex mul_param;
 
-						//init_complex(mul_param, -scale, 0);
+						/* init_complex(mul_param, -scale, 0); */
 						init_complex(mul_param, -1, 0);
 
 						mul_complex_f(mul_param, mul_param, chop_amount);
 						mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
-						mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0f ? 0.0f : o->_kz[j] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j]));
+						mul_complex_f(mul_param, mul_param,
+						              ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
+						               0.0f :
+						               o->_kz[j] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j]));
 						init_complex(o->_fft_in_jzz[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
 					}
 				}
@@ -627,32 +643,35 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount
 					}
 				}
 			}
-		} // section 5
+		} /* section 5 */
 
 #pragma omp section
 		{
 			if (o->_do_jacobian) {
-				// Jxz
+				/* Jxz */
 				for (i = 0; i < o->_M; ++i) {
 					for (j = 0; j <= o->_N / 2; ++j) {
 						fftw_complex mul_param;
 
-						//init_complex(mul_param, -scale, 0);
+						/* init_complex(mul_param, -scale, 0); */
 						init_complex(mul_param, -1, 0);
 
 						mul_complex_f(mul_param, mul_param, chop_amount);
 						mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
-						mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0f ? 0.0f : o->_kx[i] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j]));
+						mul_complex_f(mul_param, mul_param,
+						              ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
+						               0.0f :
+						               o->_kx[i] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j]));
 						init_complex(o->_fft_in_jxz[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
 					}
 				}
 				fftw_execute(o->_Jxz_plan);
 			}
-		} // section 6
+		} /* section 6 */
 
 #pragma omp section
 		{
-			// fft normals
+			/* fft normals */
 			if (o->_do_normals) {
 				for (i = 0; i < o->_M; ++i) {
 					for (j = 0; j <= o->_N / 2; ++j) {
@@ -667,7 +686,7 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount
 				fftw_execute(o->_N_x_plan);
 
 			}
-		} // section 7
+		} /* section 7 */
 
 #pragma omp section
 		{
@@ -694,9 +713,9 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount
 #endif
 				o->_N_y = 1.0f / scale;
 			}
-		} // section 8
+		} /* section 8 */
 
-	} // omp sections
+	} /* omp sections */
 
 	BLI_rw_mutex_unlock(&o->oceanmutex);
 }
@@ -726,7 +745,8 @@ static void set_height_normalize_factor(struct Ocean *oc)
 
 	BLI_rw_mutex_unlock(&oc->oceanmutex);
 
-	if (max_h == 0.0f) max_h = 0.00001f;  // just in case ...
+	if (max_h == 0.0f)
+		max_h = 0.00001f;  /* just in case ... */
 
 	res = 1.0f / (max_h);
 
@@ -743,7 +763,8 @@ struct Ocean *BKE_add_ocean(void)
 }
 
 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)
+                    float alignment, float depth, float time, short do_height_field, short do_chop, short do_normals,
+                    short do_jacobian, int seed)
 {
 	int i, j, ii;
 
@@ -761,8 +782,8 @@ void BKE_init_ocean(struct Ocean *o, int M, int N, float Lx, float Lz, float V,
 	o->_Lx = Lx;
 	o->_Lz = Lz;
 	o->_wx = cos(w);
-	o->_wz = -sin(w); // wave direction
-	o->_L = V * V / GRAVITY;  // largest wave for a given velocity V
+	o->_wz = -sin(w); /* wave direction */
+	o->_L = V * V / GRAVITY;  /* largest wave for a given velocity V */
 	o->time = time;
 
 	o->_do_disp_y = do_height_field;
@@ -776,30 +797,30 @@ void BKE_init_ocean(struct Ocean *o, int M, int N, float Lx, float Lz, float V,
 	o->_kx = (float *) MEM_mallocN(o->_M * sizeof(float), "ocean_kx");
 	o->_kz = (float *) MEM_mallocN(o->_N * sizeof(float), "ocean_kz");
 
-	// make this robust in the face of erroneous usage
+	/* make this robust in the face of erroneous usage */
 	if (o->_Lx == 0.0f)
 		o->_Lx = 0.001f;
 
 	if (o->_Lz == 0.0f)
 		o->_Lz = 0.001f;
 
-	// the +ve components and DC
+	/* the +ve components and DC */
 	for (i = 0; i <= o->_M / 2; ++i)
 		o->_kx[i] = 2.0f * (float)M_PI * i / o->_Lx;
 
-	// the -ve components
+	/* the -ve components */
 	for (i = o->_M - 1, ii = 0; i > o->_M / 2; --i, ++ii)
 		o->_kx[i] = -2.0f * (float)M_PI * ii / o->_Lx;
 
-	// the +ve components and DC
+	/* the +ve components and DC */
 	for (i = 0; i <= o->_N / 2; ++i)
 		o->_kz[i] = 2.0f * (float)M_PI * i / o->_Lz;
 
-	// the -ve components
+	/* the -ve components */
 	for (i = o->_N - 1, ii = 0; i > o->_N / 2; --i, ++ii)
 		o->_kz[i] = -2.0f * (float)M_PI * ii / o->_Lz;
 
-	// pre-calculate the k matrix
+	/* pre-calculate the k matrix */
 	for (i = 0; i < o->_M; ++i)
 		for (j = 0; j <= o->_N / 2; ++j)
 			o->_k[i * (1 + o->_N / 2) + j] = sqrt(o->_kx[i] * o->_kx[i] + o->_kz[j] * o->_kz[j]);
@@ -819,11 +840,11 @@ void BKE_init_ocean(struct Ocean *o, int M, int N, float Lx, float Lz, float V,
 		}
 	}
 
-	o->_fft_in = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in");
-	o->_htilda = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_htilda");
+	o->_fft_in = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in");
+	o->_htilda = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_htilda");
 
 	if (o->_do_disp_y) {
-		o->_disp_y = (double *) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_y");
+		o->_disp_y = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_y");
 		o->_disp_y_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in, o->_disp_y, FFTW_ESTIMATE);
 	}
 
@@ -831,32 +852,35 @@ void BKE_init_ocean(struct Ocean *o, int M, int N, float Lx, float Lz, float V,
 		o->_fft_in_nx = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_nx");
 		o->_fft_in_nz = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_nz");
 
-		o->_N_x = (double *) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_N_x");
+		o->_N_x = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_N_x");
 		/* o->_N_y = (float *) fftwf_malloc(o->_M * o->_N * sizeof(float)); (MEM01) */
-		o->_N_z = (double *) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_N_z");
+		o->_N_z = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_N_z");
 
 		o->_N_x_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_nx, o->_N_x, FFTW_ESTIMATE);
 		o->_N_z_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_nz, o->_N_z, FFTW_ESTIMATE);
 	}
 
 	if (o->_do_chop) {
-		o->_fft_in_x = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_x");
-		o->_fft_in_z = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_z");
+		o->_fft_in_x = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_x");
+		o->_fft_in_z = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_z");
 
-		o->_disp_x = (double *) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_x");
-		o->_disp_z = (double *) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_z");
+		o->_disp_x = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_x");
+		o->_disp_z = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_z");
 
 		o->_disp_x_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_x, o->_disp_x, FFTW_ESTIMATE);
 		o->_disp_z_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_z, o->_disp_z, FFTW_ESTIMATE);
 	}
 	if (o->_do_jacobian) {
-		o->_fft_in_jxx = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_jxx");
-		o->_fft_in_jzz = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_jzz");
-		o->_fft_in_jxz = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_jxz");
+		o->_fft_in_jxx = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex),
+		                                             "ocean_fft_in_jxx");
+		o->_fft_in_jzz = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex),
+		                                             "ocean_fft_in_jzz");
+		o->_fft_in_jxz = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex),
+		                                             "ocean_fft_in_jxz");
 
-		o->_Jxx = (double *) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jxx");
-		o->_Jzz = (double *) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jzz");
-		o->_Jxz = (double *) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jxz");
+		o->_Jxx = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jxx");
+		o->_Jzz = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jzz");
+		o->_Jxz = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jxz");
 
 		o->_Jxx_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_jxx, o->_Jxx, FFTW_ESTIMATE);
 		o->_Jzz_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_jzz, o->_Jzz, FFTW_ESTIMATE);
@@ -1076,8 +1100,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_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)
 {
 	OceanCache *och = MEM_callocN(sizeof(OceanCache), "ocean cache data");
@@ -1112,7 +1135,7 @@ void BKE_simulate_ocean_cache(struct OceanCache *och, int frame)
 	/* ibufs array is zero based, but filenames are based on frame numbers */
 	/* still need to clamp frame numbers to valid range of images on disk though */
 	CLAMP(frame, och->start, och->end);
-	f = frame - och->start; // shift to 0 based
+	f = frame - och->start; /* shift to 0 based */
 
 	/* if image is already loaded in mem, return */
 	if (och->ibufs_disp[f] != NULL) return;
@@ -1121,22 +1144,35 @@ void BKE_simulate_ocean_cache(struct OceanCache *och, int frame)
 
 	cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_DISPLACE);
 	och->ibufs_disp[f] = IMB_loadiffname(string, 0, NULL);
-	//if (och->ibufs_disp[f] == NULL) printf("error loading %s\n", string);
-	//else printf("loaded cache %s\n", string);
+#if 0
+	if (och->ibufs_disp[f] == NULL)
+		printf("error loading %s\n", string);
+	else
+		printf("loaded cache %s\n", string);
+#endif
 
 	cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_FOAM);
 	och->ibufs_foam[f] = IMB_loadiffname(string, 0, NULL);
-	//if (och->ibufs_foam[f] == NULL) printf("error loading %s\n", string);
-	//else printf("loaded cache %s\n", string);
+#if 0
+	if (och->ibufs_foam[f] == NULL)
+		printf("error loading %s\n", string);
+	else
+		printf("loaded cache %s\n", string);
+#endif
 
 	cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_NORMAL);
 	och->ibufs_norm[f] = IMB_loadiffname(string, 0, NULL);
-	//if (och->ibufs_norm[f] == NULL) printf("error loading %s\n", string);
-	//else printf("loaded cache %s\n", string);
+#if 0
+	if (och->ibufs_norm[f] == NULL)
+		printf("error loading %s\n", string);
+	else
+		printf("loaded cache %s\n", string);
+#endif
 }
 
 
-void BKE_bake_ocean(struct Ocean *o, struct OceanCache *och, void (*update_cb)(void *, float progress, int *cancel), void *update_cb_data)
+void BKE_bake_ocean(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
 	 * are enabled, take care that BKE_ocean_eval_ij() initializes a member
@@ -1197,13 +1233,13 @@ void BKE_bake_ocean(struct Ocean *o, struct OceanCache *och, void (*update_cb)(v
 						pr = prev_foam[res_x * y + x];
 					}
 
-					/* r = BLI_frand(); */ /* UNUSED */ // randomly reduce foam
+					/* r = BLI_frand(); */ /* UNUSED */ /* randomly reduce foam */
 
-					//pr = pr * och->foam_fade;		// overall fade
+					/* pr = pr * och->foam_fade; */		/* overall fade */
 
-					// remember ocean coord sys is Y up!
-					// break up the foam where height (Y) is low (wave valley),
-					// and X and Z displacement is greatest
+					/* remember ocean coord sys is Y up!
+					 * break up the foam where height (Y) is low (wave valley), and X and Z displacement is greatest
+					 */
 
 #if 0
 					vec[0] = ocr.disp[0];
@@ -1219,22 +1255,27 @@ void BKE_bake_ocean(struct Ocean *o, struct OceanCache *och, void (*update_cb)(v
 					neg_eplus = ocr.Eplus[2] < 0.0f ? 1.0f + ocr.Eplus[2] : 1.0f;
 					neg_eplus = neg_eplus < 0.0f ? 0.0f : neg_eplus;
 
-					//if (ocr.disp[1] < 0.0 || r > och->foam_fade)
-					//	pr *= och->foam_fade;
+#if 0
+					if (ocr.disp[1] < 0.0 || r > och->foam_fade)
+						pr *= och->foam_fade;
 
 
-					//pr = pr * (1.0 - hor_stretch) * ocr.disp[1];
-					//pr = pr * neg_disp * neg_eplus;
+					pr = pr * (1.0 - hor_stretch) * ocr.disp[1];
+					pr = pr * neg_disp * neg_eplus;
+#endif
 
-					if (pr < 1.0f) pr *= pr;
+					if (pr < 1.0f)
+						pr *= pr;
 
 					pr *= och->foam_fade * (0.75f + neg_eplus * 0.25f);
 
-
-					foam_result = pr + ocr.foam;
+					/* A full clamping should not be needed! */
+					foam_result = min_ff(pr + ocr.foam, 1.0f);
 
 					prev_foam[res_x * y + x] = foam_result;
 
+					/*foam_result = min_ff(foam_result, 1.0f); */
+
 					value_to_rgba_unit_alpha(&ibuf_foam->rect_float[4 * (res_x * y + x)], foam_result);
 				}
 
@@ -1279,7 +1320,7 @@ void BKE_bake_ocean(struct Ocean *o, struct OceanCache *och, void (*update_cb)(v
 	och->baked = 1;
 }
 
-#else // WITH_OCEANSIM
+#else /* WITH_OCEANSIM */
 
 /* stub */
 typedef struct Ocean {
@@ -1297,8 +1338,9 @@ void BKE_ocean_eval_uv(struct Ocean *UNUSED(oc), struct OceanResult *UNUSED(ocr)
 {
 }
 
-// use catmullrom interpolation rather than linear
-void BKE_ocean_eval_uv_catrom(struct Ocean *UNUSED(oc), struct OceanResult *UNUSED(ocr), float UNUSED(u), float UNUSED(v))
+/* use catmullrom interpolation rather than linear */
+void BKE_ocean_eval_uv_catrom(struct Ocean *UNUSED(oc), struct OceanResult *UNUSED(ocr), float UNUSED(u),
+                              float UNUSED(v))
 {
 }
 
@@ -1306,7 +1348,8 @@ void BKE_ocean_eval_xz(struct Ocean *UNUSED(oc), struct OceanResult *UNUSED(ocr)
 {
 }
 
-void BKE_ocean_eval_xz_catrom(struct Ocean *UNUSED(oc), struct OceanResult *UNUSED(ocr), float UNUSED(x), float UNUSED(z))
+void BKE_ocean_eval_xz_catrom(struct Ocean *UNUSED(oc), struct OceanResult *UNUSED(ocr), float UNUSED(x),
+                              float UNUSED(z))
 {
 }
 
@@ -1325,8 +1368,10 @@ struct Ocean *BKE_add_ocean(void)
 	return oc;
 }
 
-void BKE_init_ocean(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_init_ocean(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))
 {
 }
 
@@ -1351,17 +1396,19 @@ void BKE_free_ocean_cache(struct OceanCache *och)
 	MEM_freeN(och);
 }
 
-void BKE_ocean_cache_eval_uv(struct OceanCache *UNUSED(och), struct OceanResult *UNUSED(ocr), int UNUSED(f), float UNUSED(u), float UNUSED(v))
+void BKE_ocean_cache_eval_uv(struct OceanCache *UNUSED(och), struct OceanResult *UNUSED(ocr), int UNUSED(f),
+                             float UNUSED(u), float UNUSED(v))
 {
 }
 
-void BKE_ocean_cache_eval_ij(struct OceanCache *UNUSED(och), struct OceanResult *UNUSED(ocr), int UNUSED(f), int UNUSED(i), int UNUSED(j))
+void BKE_ocean_cache_eval_ij(struct OceanCache *UNUSED(och), struct OceanResult *UNUSED(ocr), int UNUSED(f),
+                             int UNUSED(i), int UNUSED(j))
 {
 }
 
-OceanCache *BKE_init_ocean_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))
+OceanCache *BKE_init_ocean_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))
 {
 	OceanCache *och = MEM_callocN(sizeof(OceanCache), "ocean cache data");
 
@@ -1372,9 +1419,10 @@ void BKE_simulate_ocean_cache(struct OceanCache *UNUSED(och), int UNUSED(frame))
 {
 }
 
-void BKE_bake_ocean(struct Ocean *UNUSED(o), struct OceanCache *UNUSED(och), void (*update_cb)(void *, float progress, int *cancel), void *UNUSED(update_cb_data))
+void BKE_bake_ocean(struct Ocean *UNUSED(o), struct OceanCache *UNUSED(och),
+                    void (*update_cb)(void *, float progress, int *cancel), void *UNUSED(update_cb_data))
 {
 	/* unused */
 	(void)update_cb;
 }
-#endif // WITH_OCEANSIM
+#endif /* WITH_OCEANSIM */
\ No newline at end of file
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index dda9a2b0494..7a576c88677 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -3269,7 +3269,7 @@ static void rna_def_modifier_ocean(BlenderRNA *brna)
 	
 	prop = RNA_def_property(srna, "size", PROP_FLOAT, PROP_UNSIGNED);
 	RNA_def_property_float_sdna(prop, NULL, "size");
-	RNA_def_property_ui_text(prop, "Size", "");
+	RNA_def_property_ui_text(prop, "Size", "Surface scale factor (does not affect the height of the waves)");
 	RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, 0);
 	RNA_def_property_update(prop, 0, "rna_OceanModifier_topology_update");
 	
@@ -3310,16 +3310,17 @@ static void rna_def_modifier_ocean(BlenderRNA *brna)
 	RNA_def_property_ui_text(prop, "Resolution", "Resolution of the generated surface");
 	RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
 	
-	prop = RNA_def_property(srna, "spatial_size", PROP_INT, PROP_DISTANCE);
+	prop = RNA_def_property(srna, "spatial_size", PROP_INT, PROP_NONE);
 	RNA_def_property_int_sdna(prop, NULL, "spatial_size");
 	RNA_def_property_ui_range(prop, 1, 512, 2, 0);
 	RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
-	RNA_def_property_ui_text(prop, "Spatial Size", "Physical size of the simulation domain (m)");
+	RNA_def_property_ui_text(prop, "Spatial Size",
+	                         "Size of the simulation domain (in meters), and of the generated geometry (in BU)");
 	RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
 	
 	prop = RNA_def_property(srna, "wind_velocity", PROP_FLOAT, PROP_VELOCITY);
 	RNA_def_property_float_sdna(prop, NULL, "wind_velocity");
-	RNA_def_property_ui_text(prop, "Wind Velocity", "Wind speed (m/s)");
+	RNA_def_property_ui_text(prop, "Wind Velocity", "Wind speed");
 	RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
 	
 	prop = RNA_def_property(srna, "damping", PROP_FLOAT, PROP_FACTOR);
@@ -3332,42 +3333,43 @@ static void rna_def_modifier_ocean(BlenderRNA *brna)
 	RNA_def_property_float_sdna(prop, NULL, "smallest_wave");
 	RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
 	RNA_def_property_range(prop, 0.0, FLT_MAX);
-	RNA_def_property_ui_text(prop, "Smallest Wave", "Shortest allowed wavelength (m)");
+	RNA_def_property_ui_text(prop, "Smallest Wave", "Shortest allowed wavelength");
 	RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
 	
 	prop = RNA_def_property(srna, "wave_alignment", PROP_FLOAT, PROP_UNSIGNED);
 	RNA_def_property_float_sdna(prop, NULL, "wave_alignment");
 	RNA_def_property_range(prop, 0.0, 10.0);
-	RNA_def_property_ui_text(prop, "Wave Alignment", "");
+	RNA_def_property_ui_text(prop, "Wave Alignment", "How much the waves are aligned to each other");
 	RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
 	
 	prop = RNA_def_property(srna, "wave_direction", PROP_FLOAT, PROP_ANGLE);
 	RNA_def_property_float_sdna(prop, NULL, "wave_direction");
 	RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
-	RNA_def_property_ui_text(prop, "Wave Direction", "");
+	RNA_def_property_ui_text(prop, "Wave Direction", "Main direction of the waves when they are (partially) aligned");
 	RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
 	
 	prop = RNA_def_property(srna, "wave_scale", PROP_FLOAT, PROP_UNSIGNED);
 	RNA_def_property_float_sdna(prop, NULL, "wave_scale");
-	RNA_def_property_ui_text(prop, "Wave Scale", "");
+	RNA_def_property_ui_text(prop, "Wave Scale", "Scale of the displacement effect");
 	RNA_def_property_update(prop, 0, "rna_OceanModifier_sim_update");
 	
-	prop = RNA_def_property(srna, "depth", PROP_FLOAT, PROP_UNSIGNED);
+	prop = RNA_def_property(srna, "depth", PROP_FLOAT, PROP_DISTANCE);
 	RNA_def_property_float_sdna(prop, NULL, "depth");
 	RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
-	RNA_def_property_ui_text(prop, "Depth", "");
+	RNA_def_property_ui_text(prop, "Depth", "Depth of the solid ground below the water surface");
 	RNA_def_property_ui_range(prop, 0, 250, 1, 0);
 	RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
 	
 	prop = RNA_def_property(srna, "foam_coverage", PROP_FLOAT, PROP_NONE);
 	RNA_def_property_float_sdna(prop, NULL, "foam_coverage");
-	RNA_def_property_ui_text(prop, "Foam Coverage", "");
+	RNA_def_property_ui_text(prop, "Foam Coverage", "Amount of generated foam");
 	RNA_def_property_update(prop, 0, "rna_Modifier_update");
 	
 	prop = RNA_def_property(srna, "bake_foam_fade", PROP_FLOAT, PROP_UNSIGNED);
 	RNA_def_property_float_sdna(prop, NULL, "foam_fade");
-	RNA_def_property_ui_text(prop, "Foam Fade", "");
-	RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, 0);
+	RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+	RNA_def_property_ui_text(prop, "Foam Fade", "How much foam accumulates over time (baked ocean only)");
+	RNA_def_property_ui_range(prop, 0.0, 10.0, 1, 0);
 	RNA_def_property_update(prop, 0, NULL);
 	
 	prop = RNA_def_property(srna, "foam_layer_name", PROP_STRING, PROP_NONE);
@@ -3377,33 +3379,34 @@ static void rna_def_modifier_ocean(BlenderRNA *brna)
 	
 	prop = RNA_def_property(srna, "choppiness", PROP_FLOAT, PROP_UNSIGNED);
 	RNA_def_property_float_sdna(prop, NULL, "chop_amount");
-	RNA_def_property_ui_text(prop, "Choppiness", "");
+	RNA_def_property_ui_text(prop, "Choppiness",
+	                         "Choppiness of the wave's crest (adds some horizontal component to the displacement)");
 	RNA_def_property_ui_range(prop, 0.0, 4.0, 3, 0);
 	RNA_def_property_float_funcs(prop, NULL, "rna_OceanModifier_ocean_chop_set", NULL);
 	RNA_def_property_update(prop, 0, "rna_OceanModifier_sim_update");
 	
 	prop = RNA_def_property(srna, "time", PROP_FLOAT, PROP_UNSIGNED);
 	RNA_def_property_float_sdna(prop, NULL, "time");
-	RNA_def_property_ui_text(prop, "Time", "");
+	RNA_def_property_ui_text(prop, "Time", "Current time of the simulation");
 	RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, 0);
 	RNA_def_property_update(prop, 0, "rna_OceanModifier_sim_update");
 	
 	prop = RNA_def_property(srna, "random_seed", PROP_INT, PROP_UNSIGNED);
 	RNA_def_property_int_sdna(prop, NULL, "seed");
 	RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
-	RNA_def_property_ui_text(prop, "Random Seed", "");
+	RNA_def_property_ui_text(prop, "Random Seed", "Seed of the random generator");
 	RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
 	
 	prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_UNSIGNED);
 	RNA_def_property_int_sdna(prop, NULL, "bakestart");
 	RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
-	RNA_def_property_ui_text(prop, "Bake Start", "");
+	RNA_def_property_ui_text(prop, "Bake Start", "Start frame of the ocean baking");
 	RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
 	
 	prop = RNA_def_property(srna, "frame_end", PROP_INT, PROP_UNSIGNED);
 	RNA_def_property_int_sdna(prop, NULL, "bakeend");
 	RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
-	RNA_def_property_ui_text(prop, "Bake End", "");
+	RNA_def_property_ui_text(prop, "Bake End", "End frame of the ocean baking");
 	RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
 	
 	prop = RNA_def_property(srna, "is_cached", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c
index 564fa696c2a..c0e529f1eae 100644
--- a/source/blender/modifiers/intern/MOD_ocean.c
+++ b/source/blender/modifiers/intern/MOD_ocean.c
@@ -139,10 +139,10 @@ static void initData(ModifierData *md)
 	omd->ocean = BKE_add_ocean();
 	init_ocean_modifier(omd);
 	simulate_ocean_modifier(omd);
-#else  // WITH_OCEANSIM
+#else  /* WITH_OCEANSIM */
 	   /* unused */
 	(void)md;
-#endif // WITH_OCEANSIM
+#endif /* WITH_OCEANSIM */
 }
 
 static void freeData(ModifierData *md)
@@ -153,10 +153,10 @@ static void freeData(ModifierData *md)
 	BKE_free_ocean(omd->ocean);
 	if (omd->oceancache)
 		BKE_free_ocean_cache(omd->oceancache);
-#else // WITH_OCEANSIM
+#else /* WITH_OCEANSIM */
 	/* unused */
 	(void)md;
-#endif // WITH_OCEANSIM
+#endif /* WITH_OCEANSIM */
 }
 
 static void copyData(ModifierData *md, ModifierData *target)
@@ -201,11 +201,11 @@ static void copyData(ModifierData *md, ModifierData *target)
 	tomd->ocean = BKE_add_ocean();
 	init_ocean_modifier(tomd);
 	simulate_ocean_modifier(tomd);
-#else // WITH_OCEANSIM
+#else /* WITH_OCEANSIM */
 	/* unused */
 	(void)md;
 	(void)target;
-#endif // WITH_OCEANSIM
+#endif /* WITH_OCEANSIM */
 }
 
 #ifdef WITH_OCEANSIM
@@ -219,14 +219,14 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
 
 	return dataMask;
 }
-#else // WITH_OCEANSIM
+#else /* WITH_OCEANSIM */
 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
 {
 	/* unused */
 	(void)md;
 	return 0;
 }
-#endif // WITH_OCEANSIM
+#endif /* WITH_OCEANSIM */
 
 #if 0
 static void dm_get_bounds(DerivedMesh *dm, float *sx, float *sy, float *ox, float *oy)
@@ -302,11 +302,7 @@ static DerivedMesh *generate_ocean_geometry(OceanModifierData *omd)
 	mpolys = CDDM_get_polys(result);
 	mloops = CDDM_get_loops(result);
 
-#if 0 // trunk
-	origindex = result->getFaceDataArray(result, CD_ORIGINDEX);
-#else // bmesh
 	origindex = CustomData_get_layer(&result->polyData, CD_ORIGINDEX);
-#endif
 
 	/* create vertices */
 	#pragma omp parallel for private(x, y) if (rx > OMP_MIN_RES)
@@ -443,7 +439,7 @@ static DerivedMesh *doOcean(ModifierData *md, Object *ob,
 
 	cfra = md->scene->r.cfra;
 	CLAMP(cfra, omd->bakestart, omd->bakeend);
-	cfra -= omd->bakestart; // shift to 0 based
+	cfra -= omd->bakestart; /* shift to 0 based */
 
 	num_verts = dm->getNumVerts(dm);
 	num_faces = dm->getNumPolys(dm);
@@ -500,7 +496,7 @@ static DerivedMesh *doOcean(ModifierData *md, Object *ob,
 
 	/* displace the geometry */
 
-	//#pragma omp parallel for private(i, ocr) if (omd->resolution > OMP_MIN_RES)
+	/* #pragma omp parallel for private(i, ocr) if (omd->resolution > OMP_MIN_RES) */
 	for (i = 0, mv = mverts; i < num_verts; i++, mv++) {
 		const float u = OCEAN_CO(size_co_inv, mv->co[0]);
 		const float v = OCEAN_CO(size_co_inv, mv->co[1]);
@@ -522,7 +518,7 @@ static DerivedMesh *doOcean(ModifierData *md, Object *ob,
 
 	return dm;
 }
-#else  // WITH_OCEANSIM
+#else  /* WITH_OCEANSIM */
 static DerivedMesh *doOcean(ModifierData *md, Object *UNUSED(ob),
                             DerivedMesh *derivedData,
                             int UNUSED(useRenderParams))
@@ -531,7 +527,7 @@ static DerivedMesh *doOcean(ModifierData *md, Object *UNUSED(ob),
 	(void)md;
 	return derivedData;
 }
-#endif // WITH_OCEANSIM
+#endif /* WITH_OCEANSIM */
 
 static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
                                   DerivedMesh *derivedData,
-- 
cgit v1.2.3


From c0e1f23e5a6ade738aea75571f2fe374bfecd854 Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Wed, 2 Jan 2013 16:10:03 +0000
Subject: Bug fix - post 2.65a

New option "Keep Session" was not using "untitled.blend" as default save name,
in case a startup.blend was kept as session. Could give bad accidents.
---
 source/blender/windowmanager/intern/wm_operators.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

(limited to 'source')

diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 39164995cc5..751ccd4aacd 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -2129,8 +2129,11 @@ void wm_recover_last_session(bContext *C, ReportList *reports)
 		/* XXX bad global... fixme */
 		if (G.main->name[0])
 			G.file_loaded = 1;	/* prevents splash to show */
-		else
+		else {
 			G.relbase_valid = 0;
+			G.save_over = 0;    /* start with save preference untitled.blend */
+		}
+
 	}
 }
 
@@ -2168,7 +2171,7 @@ static int wm_recover_auto_save_exec(bContext *C, wmOperator *op)
 	WM_file_read(C, path, op->reports);
 
 	G.fileflags &= ~G_FILE_RECOVER;
-
+	
 	return OPERATOR_FINISHED;
 }
 
-- 
cgit v1.2.3


From ea2224e28d179d1bba3e278750a42c36fa3939c5 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Wed, 2 Jan 2013 16:15:45 +0000
Subject: changes needed for EDL import to work again. - add
 sequence.update(data=False) function. - made some sequence vars editable. -
 correct some comments.

also rename rna function sequence.getStripElem() --> strip_elem_from_frame()
---
 source/blender/blenkernel/intern/sequencer.c         |  2 +-
 .../blender/editors/space_sequencer/sequencer_add.c  |  2 +-
 .../editors/transform/transform_conversions.c        |  2 +-
 source/blender/makesrna/intern/rna_sequencer.c       |  8 ++++----
 source/blender/makesrna/intern/rna_sequencer_api.c   | 20 +++++++++++++++++++-
 source/blender/python/intern/bpy_interface.c         |  5 ++++-
 6 files changed, 30 insertions(+), 9 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 69c125b0ece..a5c1c990b9e 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -633,7 +633,7 @@ void BKE_sequence_calc(Scene *scene, Sequence *seq)
 	}
 }
 
-/* note: caller should run calc_sequence(scene, seq) after */
+/* note: caller should run BKE_sequence_calc(scene, seq) after */
 void BKE_sequence_reload_new_file(Scene *scene, Sequence *seq, int lock_range)
 {
 	char str[FILE_MAX];
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index 6219a9061f4..0ade57b7ca9 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -871,7 +871,7 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
 		if (BKE_sequence_test_overlap(ed->seqbasep, seq)) BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
 	}
 
-	BKE_sequencer_update_changed_seq_and_deps(scene, seq, 1, 1); /* runs calc_sequence */
+	BKE_sequencer_update_changed_seq_and_deps(scene, seq, 1, 1); /* runs BKE_sequence_calc */
 
 
 	/* not sure if this is needed with update_changed_seq_and_deps.
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 82ad236f7ae..12b0341d395 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -4090,7 +4090,7 @@ static void SeqTransInfo(TransInfo *t, Sequence *seq, int *recursive, int *count
 				/* Meta's can only directly be moved between channels since they
 				 * don't have their start and length set directly (children affect that)
 				 * since this Meta is nested we don't need any of its data in fact.
-				 * calc_sequence() will update its settings when run on the toplevel meta */
+				 * BKE_sequence_calc() will update its settings when run on the toplevel meta */
 				*flag = 0;
 				*count = 0;
 				*recursive = TRUE;
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index e849e84ff38..a41551fc8da 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -1401,26 +1401,26 @@ static void rna_def_sequence(BlenderRNA *brna)
 
 	prop = RNA_def_property(srna, "frame_offset_start", PROP_INT, PROP_TIME);
 	RNA_def_property_int_sdna(prop, NULL, "startofs");
-	RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* overlap tests */
+//	RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* overlap tests */
 	RNA_def_property_ui_text(prop, "Start Offset", "");
 	RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
 	
 	prop = RNA_def_property(srna, "frame_offset_end", PROP_INT, PROP_TIME);
 	RNA_def_property_int_sdna(prop, NULL, "endofs");
-	RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* overlap tests */
+//	RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* overlap tests */
 	RNA_def_property_ui_text(prop, "End Offset", "");
 	RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
 	
 	prop = RNA_def_property(srna, "frame_still_start", PROP_INT, PROP_TIME);
 	RNA_def_property_int_sdna(prop, NULL, "startstill");
-	RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* overlap tests */
+//	RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* overlap tests */
 	RNA_def_property_range(prop, 0, MAXFRAME);
 	RNA_def_property_ui_text(prop, "Start Still", "");
 	RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
 	
 	prop = RNA_def_property(srna, "frame_still_end", PROP_INT, PROP_TIME);
 	RNA_def_property_int_sdna(prop, NULL, "endstill");
-	RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* overlap tests */
+//	RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* overlap tests */
 	RNA_def_property_range(prop, 0, MAXFRAME);
 	RNA_def_property_ui_text(prop, "End Still", "");
 	RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c
index 7602ec99c2b..69d35a3c2f0 100644
--- a/source/blender/makesrna/intern/rna_sequencer_api.c
+++ b/source/blender/makesrna/intern/rna_sequencer_api.c
@@ -37,6 +37,8 @@
 #include "DNA_scene_types.h"
 #include "DNA_sequence_types.h"
 
+#include "BLI_utildefines.h"
+
 #ifdef RNA_RUNTIME
 
 //#include "DNA_anim_types.h"
@@ -62,6 +64,16 @@
 
 #include "WM_api.h"
 
+static void rna_Sequence_update_rnafunc(ID *id, Sequence *self, int do_data)
+{
+	if (do_data) {
+		BKE_sequencer_update_changed_seq_and_deps((Scene *)id, self, true, true);
+		// new_tstripdata(self); // need 2.6x version of this.
+	}
+	BKE_sequence_calc((Scene *)id, self);
+	BKE_sequence_calc_disp((Scene *)id, self);
+}
+
 static void rna_Sequence_swap_internal(Sequence *seq_self, ReportList *reports, Sequence *seq_other)
 {
 	const char *error_msg;
@@ -389,7 +401,13 @@ void RNA_api_sequence_strip(StructRNA *srna)
 	FunctionRNA *func;
 	PropertyRNA *parm;
 
-	func = RNA_def_function(srna, "getStripElem", "BKE_sequencer_give_stripelem");
+	func = RNA_def_function(srna, "update", "rna_Sequence_update_rnafunc");
+	RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+	RNA_def_function_ui_description(func, "Update the strip dimensions");
+	parm = RNA_def_boolean(func, "data", false, "Frame",
+	                       "Update strip data");
+
+	func = RNA_def_function(srna, "strip_elem_from_frame", "BKE_sequencer_give_stripelem");
 	RNA_def_function_ui_description(func, "Return the strip element from a given frame or None");
 	parm = RNA_def_int(func, "frame", 0, -MAXFRAME, MAXFRAME, "Frame",
 	                   "The frame to get the strip element from", -MAXFRAME, MAXFRAME);
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index 08eb29a2a3e..d71c85bc3a0 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -818,7 +818,7 @@ typedef struct {
 } dealloc_obj;
 
 /* call once __file__ is set */
-void bpy_module_delay_init(PyObject *bpy_proxy)
+static void bpy_module_delay_init(PyObject *bpy_proxy)
 {
 	const int argc = 1;
 	const char *argv[2];
@@ -856,6 +856,9 @@ static void dealloc_obj_dealloc(PyObject *self)
 	dealloc_obj_Type.tp_free(self);
 }
 
+PyMODINIT_FUNC
+PyInit_bpy(void);
+
 PyMODINIT_FUNC
 PyInit_bpy(void)
 {
-- 
cgit v1.2.3


From 7139a08566a0d33163daf630219688e0d2ef39f7 Mon Sep 17 00:00:00 2001
From: Bastien Montagne 
Date: Wed, 2 Jan 2013 16:56:36 +0000
Subject: Some UI message fixes...

---
 source/blender/makesrna/intern/rna_scene.c         | 2 +-
 source/blender/windowmanager/intern/wm_operators.c | 5 ++---
 2 files changed, 3 insertions(+), 4 deletions(-)

(limited to 'source')

diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 7507e90525e..ced72dbeb99 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -3920,7 +3920,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
 
 	prop = RNA_def_property(srna, "use_bake_to_vertex_color", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "bake_flag", R_BAKE_VCOL);
-	RNA_def_property_ui_text(prop, "Bake to Vertex Colour",
+	RNA_def_property_ui_text(prop, "Bake to Vertex Color",
 	                         "Bake to vertex colors instead of to a UV-mapped image");
 	RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
 
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 751ccd4aacd..bfcd4b1e955 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -2429,9 +2429,8 @@ static int wm_console_toggle_op(bContext *UNUSED(C), wmOperator *UNUSED(op))
 
 static void WM_OT_console_toggle(wmOperatorType *ot)
 {
-	/* XXX Have to mark these for xgettext, as under linux they do not exists...
-	 *     And even worth, have to give the context as text, as xgettext doesn't expand macros. :( */
-	ot->name = CTX_N_("Operator" /* BLF_I18NCONTEXT_OPERATOR_DEFAULT */, "Toggle System Console");
+	/* XXX Have to mark these for xgettext, as under linux they do not exists... */
+	ot->name = CTX_N_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Toggle System Console");
 	ot->idname = "WM_OT_console_toggle";
 	ot->description = N_("Toggle System Console");
 	
-- 
cgit v1.2.3


From a4a3ed00186e0e73e20d1c85e90ea639e36653d1 Mon Sep 17 00:00:00 2001
From: Mitchell Stokes 
Date: Wed, 2 Jan 2013 22:14:40 +0000
Subject: r53351 removed a NULL check for name in defgroup_name_index(). name
 can be NULL when deforming verts in the BGE, so I'm adding a NULL check back
 in.

---
 source/blender/blenkernel/intern/deform.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index b5280fdc039..cea92d53916 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -343,7 +343,7 @@ bDeformGroup *defgroup_find_name(Object *ob, const char *name)
 
 int defgroup_name_index(Object *ob, const char *name)
 {
-	return BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name));
+	return (name) ? BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name)) : -1;
 }
 
 /* note, must be freed */
-- 
cgit v1.2.3


From 1a7638fa94fbe9c6244d054d20efa3405153747f Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Wed, 2 Jan 2013 23:10:14 +0000
Subject: add id property clear function (matching the same python function for
 dicts/lists)

---
 source/blender/blenkernel/BKE_idprop.h                  | 2 ++
 source/blender/blenkernel/intern/idprop.c               | 7 +++++++
 source/blender/editors/space_sequencer/sequencer_edit.c | 2 +-
 source/blender/python/generic/idprop_py_api.c           | 7 +++++++
 4 files changed, 17 insertions(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h
index a9f6a61a655..ad3e4bb2251 100644
--- a/source/blender/blenkernel/BKE_idprop.h
+++ b/source/blender/blenkernel/BKE_idprop.h
@@ -315,6 +315,8 @@ __attribute__((nonnull))
  * the actual struct IDProperty struct either.*/
 void IDP_FreeProperty(struct IDProperty *prop);
 
+void IDP_ClearProperty(IDProperty *prop);
+
 /** Unlinks any struct IDProperty<->ID linkage that might be going on.*/
 void IDP_UnlinkProperty(struct IDProperty *prop);
 
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index 5dd0f08dc71..3be47668fb5 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -815,6 +815,13 @@ void IDP_FreeProperty(IDProperty *prop)
 	}
 }
 
+void IDP_ClearProperty(IDProperty *prop)
+{
+	IDP_FreeProperty(prop);
+	prop->data.pointer = NULL;
+	prop->len = prop->totallen = 0;
+}
+
 /* Unlinks any IDProperty<->ID linkage that might be going on.
  * note: currently unused.*/
 void IDP_UnlinkProperty(IDProperty *prop)
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 409f655bb79..892f0a3f489 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -925,7 +925,7 @@ static void set_filter_seq(Scene *scene)
 			if (seq->type == SEQ_TYPE_MOVIE) {
 				seq->flag |= SEQ_FILTERY;
 				reload_sequence_new_file(scene, seq, FALSE);
-				calc_sequence(scene, seq);
+				BKE_sequence_calc(scene, seq);
 			}
 
 		}
diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c
index 53112d46098..10ca7a943cb 100644
--- a/source/blender/python/generic/idprop_py_api.c
+++ b/source/blender/python/generic/idprop_py_api.c
@@ -836,6 +836,11 @@ static PyObject *BPy_IDGroup_to_dict(BPy_IDProperty *self)
 	return BPy_IDGroup_MapDataToPy(self->prop);
 }
 
+static PyObject *BPy_IDGroup_clear(BPy_IDProperty *self)
+{
+	IDP_ClearProperty(self->prop);
+	Py_RETURN_NONE;
+}
 
 /* Matches python dict.get(key, [default]) */
 static PyObject *BPy_IDGroup_Get(BPy_IDProperty *self, PyObject *args)
@@ -875,6 +880,8 @@ static struct PyMethodDef BPy_IDGroup_methods[] = {
 	 "idprop.get(k[,d]) -> idprop[k] if k in idprop, else d.  d defaults to None"},
 	{"to_dict", (PyCFunction)BPy_IDGroup_to_dict, METH_NOARGS,
 	 "return a purely python version of the group"},
+	{"clear", (PyCFunction)BPy_IDGroup_clear, METH_NOARGS,
+	 "clear all members from this group"},
 	{NULL, NULL, 0, NULL}
 };
 
-- 
cgit v1.2.3


From c2839bfe76139ed753e6b99118001bba5f2fa6ee Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Thu, 3 Jan 2013 00:23:52 +0000
Subject: add option WITH_SYSTEM_BULLET to link against the bullet installation
 found on the system.

Note: this doesn't work yet for everything with latest stable bullet (2.81), need to look into why and likely apply some patches upstream.
However I managed to link blender by disabling some features, likely it can be made to work without too much trouble.
---
 source/blender/blenkernel/CMakeLists.txt         | 2 +-
 source/blender/bmesh/CMakeLists.txt              | 4 +++-
 source/creator/CMakeLists.txt                    | 5 ++++-
 source/gameengine/BlenderRoutines/CMakeLists.txt | 9 ++++++++-
 source/gameengine/Converter/CMakeLists.txt       | 2 +-
 source/gameengine/Ketsji/CMakeLists.txt          | 2 +-
 source/gameengine/Physics/Bullet/CMakeLists.txt  | 4 +++-
 7 files changed, 21 insertions(+), 7 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 99008309498..aca06a1abcf 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -259,7 +259,7 @@ endif()
 
 if(WITH_BULLET)
 	list(APPEND INC_SYS
-		../../../extern/bullet2/src
+		${BULLET_INCLUDE_DIRS}
 	)
 	add_definitions(-DUSE_BULLET)
 endif()
diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt
index 955b18c3db7..d11d74888ca 100644
--- a/source/blender/bmesh/CMakeLists.txt
+++ b/source/blender/bmesh/CMakeLists.txt
@@ -30,7 +30,6 @@ set(INC
 	../blenlib
 	../makesdna
 	../../../intern/guardedalloc
-	../../../extern/bullet2/src
 	../../../extern/rangetree
 	../../../intern/opennl/extern
 )
@@ -127,6 +126,9 @@ endif()
 
 if(WITH_BULLET)
 	add_definitions(-DWITH_BULLET)
+	list(APPEND INC_SYS
+		${BULLET_INCLUDE_DIRS}
+	)
 endif()
 
 if(WITH_INTERNATIONAL)
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index c53f27c7326..3fa646ac884 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -893,7 +893,6 @@ endif()
 		ge_scenegraph
 		ge_logic_network
 		ge_logic_ngnetwork
-		extern_bullet
 		ge_logic_loopbacknetwork
 		bf_intern_moto
 		extern_openjpeg
@@ -972,6 +971,10 @@ endif()
 		list(APPEND BLENDER_SORTED_LIBS bf_intern_locale)
 	endif()
 
+	if(WITH_BULLET AND NOT WITH_BULLET_SYSTEM)
+		list_insert_after(BLENDER_SORTED_LIBS "ge_logic_ngnetwork" "extern_bullet")
+	endif()
+
 	foreach(SORTLIB ${BLENDER_SORTED_LIBS})
 		set(REMLIB ${SORTLIB})
 		foreach(SEARCHLIB ${BLENDER_LINK_LIBS})
diff --git a/source/gameengine/BlenderRoutines/CMakeLists.txt b/source/gameengine/BlenderRoutines/CMakeLists.txt
index 9a47d223f76..d833534605b 100644
--- a/source/gameengine/BlenderRoutines/CMakeLists.txt
+++ b/source/gameengine/BlenderRoutines/CMakeLists.txt
@@ -30,7 +30,6 @@ set(INC
 )
 
 set(INC_SYS
-	../../../extern/bullet2/src
 	${PTHREADS_INCLUDE_DIRS}
 	${GLEW_INCLUDE_PATH}
 	${BOOST_INCLUDE_DIR}
@@ -70,4 +69,12 @@ if(WITH_CODEC_FFMPEG)
 	add_definitions(-DWITH_FFMPEG)
 endif()
 
+if(WITH_BULLET)
+	list(APPEND INC_SYS
+		${BULLET_INCLUDE_DIRS}
+	)
+	add_definitions(-DUSE_BULLET)
+endif()
+
+
 blender_add_lib(ge_blen_routines "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/gameengine/Converter/CMakeLists.txt b/source/gameengine/Converter/CMakeLists.txt
index e01729e156f..8ac9e523d5d 100644
--- a/source/gameengine/Converter/CMakeLists.txt
+++ b/source/gameengine/Converter/CMakeLists.txt
@@ -112,7 +112,7 @@ set(SRC
 
 if(WITH_BULLET)
 	list(APPEND INC_SYS
-		../../../extern/bullet2/src
+		${BULLET_INCLUDE_DIRS}
 	)
 	add_definitions(-DUSE_BULLET)
 endif()
diff --git a/source/gameengine/Ketsji/CMakeLists.txt b/source/gameengine/Ketsji/CMakeLists.txt
index 524a38a4c26..e42c2a74a8e 100644
--- a/source/gameengine/Ketsji/CMakeLists.txt
+++ b/source/gameengine/Ketsji/CMakeLists.txt
@@ -252,7 +252,7 @@ if(WITH_BULLET)
 		../Physics/Bullet
 	)
 	list(APPEND INC
-		../../../extern/bullet2/src
+		${BULLET_INCLUDE_DIRS}
 	)
 	add_definitions(-DUSE_BULLET)
 endif()
diff --git a/source/gameengine/Physics/Bullet/CMakeLists.txt b/source/gameengine/Physics/Bullet/CMakeLists.txt
index 43b1bfe7468..afb166eee57 100644
--- a/source/gameengine/Physics/Bullet/CMakeLists.txt
+++ b/source/gameengine/Physics/Bullet/CMakeLists.txt
@@ -44,7 +44,6 @@ set(INC
 )
 
 set(INC_SYS
-	../../../../extern/bullet2/src
 	${GLEW_INCLUDE_PATH}
 	${PYTHON_INCLUDE_DIRS}
 )
@@ -60,6 +59,9 @@ set(SRC
 )
 
 if(WITH_BULLET)
+	list(APPEND INC
+		${BULLET_INCLUDE_DIRS}
+	)
 	add_definitions(-DUSE_BULLET)
 endif()
 
-- 
cgit v1.2.3


From d8d24bdebd4544825c57e86a47bf796fe8ead64b Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Thu, 3 Jan 2013 06:47:44 +0000
Subject: fix [#33682] Animation not updated when the active shape index isnt
 set

---
 source/blender/blenkernel/BKE_key.h            |  2 +-
 source/blender/blenkernel/intern/displist.c    |  4 ++--
 source/blender/blenkernel/intern/key.c         | 11 +++++++----
 source/blender/blenkernel/intern/object.c      | 15 +++++++++------
 source/blender/modifiers/intern/MOD_shapekey.c | 11 +++++++----
 source/creator/CMakeLists.txt                  |  3 +--
 6 files changed, 27 insertions(+), 19 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h
index d7d75b4c4c9..a159cbb13d4 100644
--- a/source/blender/blenkernel/BKE_key.h
+++ b/source/blender/blenkernel/BKE_key.h
@@ -59,7 +59,7 @@ void key_curve_position_weights(float t, float data[4], int type);
 void key_curve_tangent_weights(float t, float data[4], int type);
 void key_curve_normal_weights(float t, float data[4], int type);
 
-float *do_ob_key(struct Scene *scene, struct Object *ob);
+float *BKE_key_evaluate_object(struct Scene *scene, struct Object *ob, int *r_totelem);
 
 struct Key      *BKE_key_from_object(struct Object *ob);
 struct KeyBlock *BKE_keyblock_from_object(struct Object *ob);
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 5fff8a51214..71e9daaee6b 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -799,7 +799,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, fl
 		required_mode |= eModifierMode_Editmode;
 
 	if (cu->editnurb == NULL) {
-		keyVerts = do_ob_key(scene, ob);
+		keyVerts = BKE_key_evaluate_object(scene, ob, &numVerts);
 
 		if (keyVerts) {
 			/* split coords from key data, the latter also includes
@@ -808,7 +808,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, fl
 			 * shape key modifier yet. */
 			deformedVerts = BKE_curve_keyVertexCos_get(cu, nurb, keyVerts);
 			originalVerts = MEM_dupallocN(deformedVerts);
-			numVerts = BKE_nurbList_verts_count(nurb);
+			BLI_assert(BKE_nurbList_verts_count(nurb) == numVerts);
 		}
 	}
 
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index ad95f09826a..ccc57a24540 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -1300,13 +1300,13 @@ static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, const int
 }
 
 /* returns key coordinates (+ tilt) when key applied, NULL otherwise */
-float *do_ob_key(Scene *scene, Object *ob)
+float *BKE_key_evaluate_object(Scene *scene, Object *ob, int *r_totelem)
 {
 	Key *key = BKE_key_from_object(ob);
 	KeyBlock *actkb = BKE_keyblock_from_object(ob);
 	char *out;
 	int tot = 0, size = 0;
-	
+
 	if (key == NULL || key->block.first == NULL)
 		return NULL;
 
@@ -1344,7 +1344,7 @@ float *do_ob_key(Scene *scene, Object *ob)
 		return NULL;
 	
 	/* allocate array */
-	out = MEM_callocN(size, "do_ob_key out");
+	out = MEM_callocN(size, "BKE_key_evaluate_object out");
 
 	/* prevent python from screwing this up? anyhoo, the from pointer could be dropped */
 	key->from = (ID *)ob->data;
@@ -1383,6 +1383,9 @@ float *do_ob_key(Scene *scene, Object *ob)
 		else if (ob->type == OB_SURF) do_curve_key(scene, ob, key, out, tot);
 	}
 	
+	if (r_totelem) {
+		*r_totelem = tot;
+	}
 	return (float *)out;
 }
 
@@ -1732,7 +1735,7 @@ void BKE_key_convert_to_mesh(KeyBlock *kb, Mesh *me)
 }
 
 /************************* vert coords ************************/
-float (*BKE_key_convert_to_vertcos(Object * ob, KeyBlock * kb))[3]
+float (*BKE_key_convert_to_vertcos(Object *ob, KeyBlock *kb))[3]
 {
 	float (*vertCos)[3], *co;
 	float *fp = kb->data;
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 976818fe2df..b2371da0c3c 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -2981,12 +2981,13 @@ static KeyBlock *insert_meshkey(Scene *scene, Object *ob, const char *name, int
 	}
 	else {
 		/* copy from current values */
-		float *data = do_ob_key(scene, ob);
+		int totelem;
+		float *data = BKE_key_evaluate_object(scene, ob, &totelem);
 
 		/* create new block with prepared data */
 		kb = BKE_keyblock_add_ctime(key, name, FALSE);
 		kb->data = data;
-		kb->totelem = me->totvert;
+		kb->totelem = totelem;
 	}
 
 	return kb;
@@ -3018,11 +3019,12 @@ static KeyBlock *insert_lattkey(Scene *scene, Object *ob, const char *name, int
 	}
 	else {
 		/* copy from current values */
-		float *data = do_ob_key(scene, ob);
+		int totelem;
+		float *data = BKE_key_evaluate_object(scene, ob, &totelem);
 
 		/* create new block with prepared data */
 		kb = BKE_keyblock_add_ctime(key, name, FALSE);
-		kb->totelem = lt->pntsu * lt->pntsv * lt->pntsw;
+		kb->totelem = totelem;
 		kb->data = data;
 	}
 
@@ -3057,11 +3059,12 @@ static KeyBlock *insert_curvekey(Scene *scene, Object *ob, const char *name, int
 	}
 	else {
 		/* copy from current values */
-		float *data = do_ob_key(scene, ob);
+		int totelem;
+		float *data = BKE_key_evaluate_object(scene, ob, &totelem);
 
 		/* create new block with prepared data */
 		kb = BKE_keyblock_add_ctime(key, name, FALSE);
-		kb->totelem = BKE_nurbList_verts_count(lb);
+		kb->totelem = totelem;
 		kb->data = data;
 	}
 
diff --git a/source/blender/modifiers/intern/MOD_shapekey.c b/source/blender/modifiers/intern/MOD_shapekey.c
index 7fe8dc69790..697ccdc49a4 100644
--- a/source/blender/modifiers/intern/MOD_shapekey.c
+++ b/source/blender/modifiers/intern/MOD_shapekey.c
@@ -54,13 +54,16 @@ static void deformVerts(ModifierData *md, Object *ob,
                         int numVerts,
                         ModifierApplyFlag UNUSED(flag))
 {
-	KeyBlock *kb = BKE_keyblock_from_object(ob);
+	Key *key = BKE_key_from_object(ob);
 	float (*deformedVerts)[3];
 
-	if (kb && kb->totelem == numVerts) {
-		deformedVerts = (float(*)[3])do_ob_key(md->scene, ob);
+	if (key && key->block.first) {
+		int deformedVerts_tot;
+		deformedVerts = (float(*)[3])BKE_key_evaluate_object(md->scene, ob, &deformedVerts_tot);
 		if (deformedVerts) {
-			memcpy(vertexCos, deformedVerts, sizeof(float) * 3 * numVerts);
+			if (numVerts == deformedVerts_tot) {
+				memcpy(vertexCos, deformedVerts, sizeof(float) * 3 * numVerts);
+			}
 			MEM_freeN(deformedVerts);
 		}
 	}
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index 3fa646ac884..72f11326af7 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -779,8 +779,7 @@ add_dependencies(blender makesdna)
 
 get_property(BLENDER_LINK_LIBS GLOBAL PROPERTY BLENDER_LINK_LIBS)
 
-set(BLENDER_LINK_LIBS
-	${BLENDER_LINK_LIBS}
+list(APPEND BLENDER_LINK_LIBS
 	bf_windowmanager
 	bf_render
 )
-- 
cgit v1.2.3


From 7b212b3bd0b583fc45ddaa8e500f482659ad1bab Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Thu, 3 Jan 2013 07:53:30 +0000
Subject: fix [#33689] Crash with decimate modifier

in fact a more general bug in BM_face_create_ngon() where edges containing the same vertex multiple times were not accounted for.
---
 source/blender/bmesh/intern/bmesh_construct.c | 5 +++++
 1 file changed, 5 insertions(+)

(limited to 'source')

diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c
index 468a80f44f8..53ce5728879 100644
--- a/source/blender/bmesh/intern/bmesh_construct.c
+++ b/source/blender/bmesh/intern/bmesh_construct.c
@@ -215,6 +215,11 @@ BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, i
 	do {
 		BMEdge *e2 = e;
 
+		/* vertex array is (len + 1) */
+		if (UNLIKELY(v_index > len)) {
+			goto err; /* vertex in loop twice */
+		}
+
 		verts[v_index++] = v;
 		edges2[e2_index++] = e;
 
-- 
cgit v1.2.3


From b2f6e6b11352725bb0f90a7149e80d39af7b39a2 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Thu, 3 Jan 2013 08:06:12 +0000
Subject: code cleanup: BM_face_create_ngon()

Change some of the paranoid checks into an assert since they should never happen.
---
 source/blender/bmesh/intern/bmesh_construct.c | 69 +++++++++++++--------------
 1 file changed, 34 insertions(+), 35 deletions(-)

(limited to 'source')

diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c
index 53ce5728879..31f795823b1 100644
--- a/source/blender/bmesh/intern/bmesh_construct.c
+++ b/source/blender/bmesh/intern/bmesh_construct.c
@@ -173,15 +173,16 @@ void BM_face_copy_shared(BMesh *bm, BMFace *f)
  */
 BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, const int create_flag)
 {
-	BMEdge **edges2 = BLI_array_alloca(edges2, len);
-	BMVert **verts = BLI_array_alloca(verts, len + 1);
-	int e2_index = 0;
-	int v_index = 0;
+	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;
-	int i, /* j, */ v1found, reverse;
+	int i;
+	bool is_v1_found, is_reverse;
 
 
 	/* this code is hideous, yeek.  I'll have to think about ways of
@@ -189,10 +190,7 @@ BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, i
 	 *  _and_ the old bmesh_mf functions, so its kindof smashed together
 	 * - joeedh */
 
-	if (!len || !v1 || !v2 || !edges || !bm) {
-		BLI_assert(0);
-		return NULL;
-	}
+	BLI_assert(len && v1 && v2 && edges && bm);
 
 	/* put edges in correct order */
 	for (i = 0; i < len; i++) {
@@ -209,19 +207,19 @@ BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, i
 		SWAP(BMVert *, ev1, ev2);
 	}
 
-	verts[v_index++] = ev1;
+	verts_sort[vsort_index++] = ev1;
 	v = ev2;
 	e = edges[0];
 	do {
 		BMEdge *e2 = e;
 
 		/* vertex array is (len + 1) */
-		if (UNLIKELY(v_index > len)) {
+		if (UNLIKELY(vsort_index > len)) {
 			goto err; /* vertex in loop twice */
 		}
 
-		verts[v_index++] = v;
-		edges2[e2_index++] = e;
+		verts_sort[vsort_index++] = v;
+		edges_sort[esort_index++] = e;
 
 		/* we only flag the verts to check if they are in the face more then once */
 		BM_ELEM_API_FLAG_ENABLE(v, _FLAG_MV);
@@ -234,66 +232,67 @@ BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, i
 			}
 		} while (e2 != e);
 
-		if (e2 == e)
+		if (UNLIKELY(e2 == e)) {
 			goto err; /* the edges do not form a closed loop */
+		}
 
 		e = e2;
 	} while (e != edges[0]);
 
-	if (e2_index != len) {
+	if (UNLIKELY(esort_index != len)) {
 		goto err; /* we didn't use all edges in forming the boundary loop */
 	}
 
 	/* ok, edges are in correct order, now ensure they are going
 	 * in the correct direction */
-	v1found = reverse = FALSE;
+	is_v1_found = is_reverse = false;
 	for (i = 0; i < len; i++) {
-		if (BM_vert_in_edge(edges2[i], v1)) {
+		if (BM_vert_in_edge(edges_sort[i], v1)) {
 			/* see if v1 and v2 are in the same edge */
-			if (BM_vert_in_edge(edges2[i], v2)) {
+			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(edges2[(i + 1) % len], v1)) {
-					reverse = TRUE;
+				if (BM_vert_in_edge(edges_sort[(i + 1) % len], v1)) {
+					is_reverse = true;
 					break;
 				}
 			}
 
-			v1found = TRUE;
+			is_v1_found = true;
 		}
 
-		if ((v1found == FALSE) && BM_vert_in_edge(edges2[i], v2)) {
-			reverse = TRUE;
+		if ((is_v1_found == false) && BM_vert_in_edge(edges_sort[i], v2)) {
+			is_reverse = true;
 			break;
 		}
 	}
 
-	if (reverse) {
+	if (is_reverse) {
 		for (i = 0; i < len / 2; i++) {
-			v = verts[i];
-			verts[i] = verts[len - i - 1];
-			verts[len - i - 1] = v;
+			v = verts_sort[i];
+			verts_sort[i] = verts_sort[len - i - 1];
+			verts_sort[len - i - 1] = v;
 		}
 	}
 
 	for (i = 0; i < len; i++) {
-		edges2[i] = BM_edge_exists(verts[i], verts[(i + 1) % len]);
-		if (!edges2[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 then once. if the flag is disabled. we've already visited */
-		if (!BM_ELEM_API_FLAG_TEST(verts[i], _FLAG_MV)) {
+		if (UNLIKELY(!BM_ELEM_API_FLAG_TEST(verts_sort[i], _FLAG_MV))) {
 			goto err;
 		}
-		BM_ELEM_API_FLAG_DISABLE(verts[i], _FLAG_MV);
+		BM_ELEM_API_FLAG_DISABLE(verts_sort[i], _FLAG_MV);
 	}
 
-	f = BM_face_create(bm, verts, edges2, len, create_flag);
+	f = BM_face_create(bm, verts_sort, edges_sort, len, create_flag);
 
 	/* clean up flags */
 	for (i = 0; i < len; i++) {
-		BM_ELEM_API_FLAG_DISABLE(edges2[i], _FLAG_MF);
+		BM_ELEM_API_FLAG_DISABLE(edges_sort[i], _FLAG_MF);
 	}
 
 	return f;
@@ -302,8 +301,8 @@ err:
 	for (i = 0; i < len; i++) {
 		BM_ELEM_API_FLAG_DISABLE(edges[i], _FLAG_MF);
 	}
-	for (i = 0; i < v_index; i++) {
-		BM_ELEM_API_FLAG_DISABLE(verts[i], _FLAG_MV);
+	for (i = 0; i < vsort_index; i++) {
+		BM_ELEM_API_FLAG_DISABLE(verts_sort[i], _FLAG_MV);
 	}
 
 	return NULL;
-- 
cgit v1.2.3


From 8ca977b16e745f716d044a5b6ccbb5be4a70ac94 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Thu, 3 Jan 2013 08:09:57 +0000
Subject: change limited dissolve angle limit default from 15 -> 5 deg. since
 15deg is quite high for 2 surfaces to be considered co-planar

---
 source/blender/editors/mesh/editmesh_tools.c   | 2 +-
 source/blender/modifiers/intern/MOD_decimate.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index b25b3cc683c..1ab130a950f 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -3582,7 +3582,7 @@ void MESH_OT_dissolve_limited(wmOperatorType *ot)
 
 	prop = RNA_def_float_rotation(ot->srna, "angle_limit", 0, NULL, 0.0f, DEG2RADF(180.0f),
 	                              "Max Angle", "Angle limit", 0.0f, DEG2RADF(180.0f));
-	RNA_def_property_float_default(prop, DEG2RADF(15.0f));
+	RNA_def_property_float_default(prop, DEG2RADF(5.0f));
 	RNA_def_boolean(ot->srna, "use_dissolve_boundaries", 0, "All Boundaries",
 	                "Dissolve all vertices inbetween face boundaries");
 }
diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c
index a23b677f8e6..2d3d5c97af7 100644
--- a/source/blender/modifiers/intern/MOD_decimate.c
+++ b/source/blender/modifiers/intern/MOD_decimate.c
@@ -63,7 +63,7 @@ static void initData(ModifierData *md)
 	DecimateModifierData *dmd = (DecimateModifierData *) md;
 
 	dmd->percent = 1.0;
-	dmd->angle   = DEG2RADF(15.0f);
+	dmd->angle   = DEG2RADF(5.0f);
 }
 
 static void copyData(ModifierData *md, ModifierData *target)
-- 
cgit v1.2.3


From 220a233921c088b31b06c59a92ab121e61610ae8 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Thu, 3 Jan 2013 13:19:16 +0000
Subject: correct invalid filter value being use for icon scaling.

---
 source/blender/editors/interface/interface_icons.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index d146fe25187..ec9374400a7 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -583,7 +583,7 @@ static void init_internal_icons(void)
 				}
 				
 				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
-				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 				
 				glBindTexture(GL_TEXTURE_2D, 0);
 				
-- 
cgit v1.2.3


From 835ebd576c7e96324d12aca189aedf21a6897451 Mon Sep 17 00:00:00 2001
From: Howard Trickey 
Date: Thu, 3 Jan 2013 13:37:17 +0000
Subject: Fix bevel crash bug #33714.  Had to disable elem tag on new vertices.

---
 source/blender/bmesh/tools/bmesh_bevel.c | 1 +
 1 file changed, 1 insertion(+)

(limited to 'source')

diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index 4bcdc7d24ff..759246c38e0 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -167,6 +167,7 @@ static void create_mesh_bmvert(BMesh *bm, VMesh *vm, int i, int j, int k, BMVert
 {
 	NewVert *nv = mesh_vert(vm, i, j, k);
 	nv->v = BM_vert_create(bm, nv->co, eg, 0);
+	BM_elem_flag_disable(nv->v, BM_ELEM_TAG);
 }
 
 static void copy_mesh_vert(VMesh *vm, int ito, int jto, int kto,
-- 
cgit v1.2.3


From 2ce08bb2d4fa3838eb7fc1c987c4576e420dec9d Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Thu, 3 Jan 2013 15:15:51 +0000
Subject: fix for bug rendering text at small sizes, padding was incorrectly
 being applied to the characters y offset causing out of bounds pixels to be
 requested from glTexSubImage2D(). also clamp width, height of the character
 bitmap to the bitmap bounds since this can still happen for very small text
 (2-3 pixels high).

---
 source/blender/blenfont/intern/blf_glyph.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index 91ecded88be..2c582133b15 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -383,7 +383,7 @@ int blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
 		if (gc->cur_tex == -1) {
 			blf_glyph_cache_texture(font, gc);
 			gc->x_offs = gc->pad;
-			gc->y_offs = gc->pad;
+			gc->y_offs = 0;
 		}
 
 		if (gc->x_offs > (gc->p2_width - gc->max_glyph_width)) {
@@ -391,7 +391,7 @@ int blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
 			gc->y_offs += gc->max_glyph_height;
 
 			if (gc->y_offs > (gc->p2_height - gc->max_glyph_height)) {
-				gc->y_offs = gc->pad;
+				gc->y_offs = 0;
 				blf_glyph_cache_texture(font, gc);
 			}
 		}
@@ -400,6 +400,19 @@ int blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
 		g->xoff = gc->x_offs;
 		g->yoff = gc->y_offs;
 
+		/* prevent glTexSubImage2D from failing if the character
+		 * asks for pixels out of bounds, this tends only to happen
+		 * with very small sizes (5px high or less) */
+		if (UNLIKELY((g->xoff + g->width)  > gc->p2_width)) {
+			g->width  -= (g->xoff + g->width)  - gc->p2_width;
+			BLI_assert(g->width > 0);
+		}
+		if (UNLIKELY((g->yoff + g->height) > gc->p2_height)) {
+			g->height -= (g->yoff + g->height) - gc->p2_height;
+			BLI_assert(g->height > 0);
+		}
+
+
 		glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
 		glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
 		glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
@@ -407,6 +420,7 @@ int blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
 
 		glBindTexture(GL_TEXTURE_2D, g->tex);
 		glTexSubImage2D(GL_TEXTURE_2D, 0, g->xoff, g->yoff, g->width, g->height, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap);
+		BLI_assert(glGetError() == GL_NO_ERROR);
 		glPopClientAttrib();
 
 		g->uv[0][0] = ((float)g->xoff) / ((float)gc->p2_width);
-- 
cgit v1.2.3


From c03d1270c8f537778a92dff46abfcf37c6bc64e5 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Thu, 3 Jan 2013 15:52:31 +0000
Subject: fix bad left aligned text when zoomed out. also minor change to
 cylinder_project_exec() - delay getting the MTFace.

---
 source/blender/editors/interface/interface_widgets.c | 10 ++++++----
 source/blender/editors/uvedit/uvedit_unwrap_ops.c    |  2 +-
 2 files changed, 7 insertions(+), 5 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index eb1c1a64e68..e4ad3a4f73b 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -1324,11 +1324,13 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
 			/* icons default draw 0.8f x height */
 			rect->xmin += (int)(0.8f * BLI_rcti_size_y(rect));
 
-			if (but->editstr || (but->flag & UI_TEXT_LEFT))
-				rect->xmin += 0.4f * U.widget_unit;
+			if (but->editstr || (but->flag & UI_TEXT_LEFT)) {
+				rect->xmin += (0.4f * U.widget_unit) / but->block->aspect;
+			}
+		}
+		else if ((but->flag & UI_TEXT_LEFT)) {
+			rect->xmin += (0.4f * U.widget_unit) / but->block->aspect;
 		}
-		else if ((but->flag & UI_TEXT_LEFT))
-			rect->xmin += 0.4f * U.widget_unit;
 
 		/* always draw text for textbutton cursor */
 		widget_draw_text(fstyle, wcol, but, rect);
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index ddd42ded769..81f548b2b5d 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -1563,7 +1563,6 @@ static int cylinder_project_exec(bContext *C, wmOperator *op)
 	uv_map_transform(C, op, center, rotmat);
 
 	BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
-		tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 		if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
 			continue;
 		
@@ -1573,6 +1572,7 @@ static int cylinder_project_exec(bContext *C, wmOperator *op)
 			uv_cylinder_project(luv->uv, l->v->co, center, rotmat);
 		}
 
+		tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 		uv_map_mirror(em, efa, tf);
 	}
 
-- 
cgit v1.2.3


From 922aeb33c840f6bce1cc62e551a2729eaf8f7a29 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Thu, 3 Jan 2013 16:36:17 +0000
Subject: fix for NODE_OT_view_all / NODE_OT_view_selected not working
 properly.

---
 source/blender/editors/space_node/node_view.c | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c
index f386657c460..492ff0dcbd4 100644
--- a/source/blender/editors/space_node/node_view.c
+++ b/source/blender/editors/space_node/node_view.c
@@ -69,12 +69,15 @@ static int space_node_view_flag(bContext *C, SpaceNode *snode, ARegion *ar, cons
 	bNode *node;
 	rctf cur_new;
 	float oldwidth, oldheight, width, height;
+	float oldasp, asp;
 	int tot = 0;
 	int has_frame = FALSE;
 	
 	oldwidth  = BLI_rctf_size_x(&ar->v2d.cur);
 	oldheight = BLI_rctf_size_y(&ar->v2d.cur);
 
+	oldasp = oldwidth / oldheight;
+
 	BLI_rctf_init_minmax(&cur_new);
 
 	if (snode->edittree) {
@@ -93,6 +96,7 @@ static int space_node_view_flag(bContext *C, SpaceNode *snode, ARegion *ar, cons
 	if (tot) {
 		width  = BLI_rctf_size_x(&cur_new);
 		height = BLI_rctf_size_y(&cur_new);
+		asp = width / height;
 
 		/* for single non-frame nodes, don't zoom in, just pan view,
 		 * but do allow zooming out, this allows for big nodes to be zoomed out */
@@ -104,17 +108,15 @@ static int space_node_view_flag(bContext *C, SpaceNode *snode, ARegion *ar, cons
 			BLI_rctf_resize(&cur_new, oldwidth, oldheight);
 		}
 		else {
-			if (width > height) {
-				float newheight;
-				newheight = oldheight * width / oldwidth;
-				cur_new.ymin = cur_new.ymin - newheight / 4;
-				cur_new.ymax = cur_new.ymax + newheight / 4;
+			if (oldasp < asp) {
+				const float height_new = width / oldasp;
+				cur_new.ymin = cur_new.ymin - height_new / 2.0f;
+				cur_new.ymax = cur_new.ymax + height_new / 2.0f;
 			}
 			else {
-				float newwidth;
-				newwidth = oldwidth * height / oldheight;
-				cur_new.xmin = cur_new.xmin - newwidth / 4;
-				cur_new.xmax = cur_new.xmax + newwidth / 4;
+				const float width_new = height * oldasp;
+				cur_new.xmin = cur_new.xmin - width_new / 2.0f;
+				cur_new.xmax = cur_new.xmax + width_new / 2.0f;
 			}
 		}
 
-- 
cgit v1.2.3


From c7b7cba2380e6885bc23b2d5fc485cd6938e55da Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Fri, 4 Jan 2013 02:13:29 +0000
Subject: code cleanup: warnings

---
 source/blender/editors/interface/interface_icons.c                  | 4 ++--
 source/blender/editors/sculpt_paint/paint_vertex.c                  | 6 ++----
 source/blender/modifiers/intern/MOD_edgesplit.c                     | 1 -
 .../gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h | 1 -
 4 files changed, 4 insertions(+), 8 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index ec9374400a7..ebc80d61af3 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -76,8 +76,8 @@
 #include "interface_intern.h"
 
 
-#define ICON_IMAGE_W        600
-#define ICON_IMAGE_H        640
+// #define ICON_IMAGE_W        600
+// #define ICON_IMAGE_H        640
 
 #define ICON_GRID_COLS      26
 #define ICON_GRID_ROWS      30
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index ead6320c7d2..08c26aaa755 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -3091,11 +3091,9 @@ static void gradientVert__mapFunc(void *userData, int index, const float co[3],
 			if (grad_data->type == WPAINT_GRADIENT_TYPE_LINEAR) {
 				alpha = line_point_factor_v2(vs->sco, grad_data->sco_start, grad_data->sco_end);
 			}
-			else if (grad_data->type == WPAINT_GRADIENT_TYPE_RADIAL) {
-				alpha = len_v2v2(grad_data->sco_start, vs->sco) * grad_data->sco_line_div;
-			}
 			else {
-				BLI_assert(0);
+				BLI_assert(grad_data->type == WPAINT_GRADIENT_TYPE_RADIAL);
+				alpha = len_v2v2(grad_data->sco_start, vs->sco) * grad_data->sco_line_div;
 			}
 			/* no need to clamp 'alpha' yet */
 
diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c
index 5c786626c94..33601c197b9 100644
--- a/source/blender/modifiers/intern/MOD_edgesplit.c
+++ b/source/blender/modifiers/intern/MOD_edgesplit.c
@@ -48,7 +48,6 @@
 
 #include "DNA_object_types.h"
 
-#define EDGE_MARK  1
 
 static DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd, Object *UNUSED(ob))
 {
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h
index 0eddde7c203..558850a9173 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h
@@ -51,7 +51,6 @@ typedef std::map		  RAS_DerivedMeshLists;
 
 class RAS_ListRasterizer : public RAS_OpenGLRasterizer
 {
-	bool mUseVertexArrays;
 	bool mATI;
 	RAS_ArrayLists mArrayLists;
 	RAS_DerivedMeshLists mDerivedMeshLists;
-- 
cgit v1.2.3


From 27343d07326f999c097dafcc9c0809a200542f5a Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Fri, 4 Jan 2013 02:14:31 +0000
Subject: fix own regression in cdDM_drawFacesTex_common() when
 drawParamsMapped isnt available.

---
 source/blender/blenkernel/intern/cdderivedmesh.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 164faba1b1d..51890851ebc 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -684,8 +684,9 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
 					}
 					else {
 						if (nors) {
-							nors += 3; continue;
+							nors += 3;
 						}
+						continue;
 					}
 				}
 				else if (drawParamsMapped) {
@@ -693,8 +694,9 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
 				}
 				else {
 					if (nors) {
-						nors += 3; continue;
+						nors += 3;
 					}
+					continue;
 				}
 			}
 			
-- 
cgit v1.2.3


From 2a7ee4e3731eff5b064b14ad28bed9d55f6f2c9a Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Fri, 4 Jan 2013 02:54:38 +0000
Subject: no need to initialize the 2D paint node tree when project painting.

---
 source/blender/editors/sculpt_paint/paint_image.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 8c9531e5554..fb62408c687 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -5142,15 +5142,13 @@ static int texture_paint_init(bContext *C, wmOperator *op)
 			return 0;
 		}
 	}
-	
-	paint_brush_init_tex(pop->s.brush);
-	
+
 	/* note, if we have no UVs on the derived mesh, then we must return here */
 	if (pop->mode == PAINT_MODE_3D_PROJECT) {
 
 		/* initialize all data from the context */
 		project_state_init(C, OBACT, &pop->ps);
-		
+
 		paint_brush_init_tex(pop->ps.brush);
 
 		pop->ps.source = PROJ_SRC_VIEW;
@@ -5168,6 +5166,9 @@ static int texture_paint_init(bContext *C, wmOperator *op)
 		if (pop->ps.dm == NULL)
 			return 0;
 	}
+	else {
+		paint_brush_init_tex(pop->s.brush);
+	}
 	
 	settings->imapaint.flag |= IMAGEPAINT_DRAWING;
 	undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
@@ -5237,8 +5238,6 @@ static void paint_exit(bContext *C, wmOperator *op)
 	if (pop->restore_projection)
 		settings->imapaint.flag &= ~IMAGEPAINT_PROJECT_DISABLE;
 
-	paint_brush_exit_tex(pop->s.brush);
-	
 	settings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
 	imapaint_canvas_free(&pop->s);
 	BKE_brush_painter_free(pop->painter);
@@ -5250,6 +5249,8 @@ static void paint_exit(bContext *C, wmOperator *op)
 		project_paint_end(&pop->ps);
 	}
 	else {
+		paint_brush_exit_tex(pop->s.brush);
+
 		/* non projection 3d paint, could move into own function of more needs adding */
 		if (pop->s.dm_release)
 			pop->s.dm->release(pop->s.dm);
-- 
cgit v1.2.3


From a50794e4f93cb2756fce5c585ad46327cfe27f46 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Fri, 4 Jan 2013 03:07:25 +0000
Subject: fix occasional memory leak in projection paint - multiple threads
 could initialize the brush curve at once. also some header cleanup.

---
 source/blender/editors/sculpt_paint/paint_image.c    | 12 ++++--------
 source/blender/editors/sculpt_paint/paint_image_2d.c |  1 -
 2 files changed, 4 insertions(+), 9 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index fb62408c687..fa8252c824d 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -42,7 +42,6 @@
 
 #include "BLI_math.h"
 #include "BLI_blenlib.h"
-#include "BLI_dynstr.h"
 #include "BLI_linklist.h"
 #include "BLI_memarena.h"
 #include "BLI_threads.h"
@@ -54,13 +53,9 @@
 #include "IMB_imbuf_types.h"
 
 #include "DNA_brush_types.h"
-#include "DNA_camera_types.h"
 #include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
 #include "DNA_node_types.h"
 #include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_texture_types.h"
 
 #include "BKE_camera.h"
 #include "BKE_context.h"
@@ -77,8 +72,7 @@
 #include "BKE_paint.h"
 #include "BKE_report.h"
 #include "BKE_scene.h"
-#include "BKE_global.h"
-#include "BKE_deform.h"
+#include "BKE_colortools.h"
 
 #include "BKE_tessmesh.h"
 
@@ -102,7 +96,6 @@
 #include "RNA_enum_types.h"
 
 #include "GPU_draw.h"
-#include "GPU_extensions.h"
 
 #include "IMB_colormanagement.h"
 
@@ -5149,6 +5142,9 @@ static int texture_paint_init(bContext *C, wmOperator *op)
 		/* initialize all data from the context */
 		project_state_init(C, OBACT, &pop->ps);
 
+		/* needed so multiple threads don't try to initialize the brush at once (can leak memory) */
+		curvemapping_initialize(pop->ps.brush->curve);
+
 		paint_brush_init_tex(pop->ps.brush);
 
 		pop->ps.source = PROJ_SRC_VIEW;
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
index 2e5ab757be3..c30996f03de 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -37,7 +37,6 @@
 #include "DNA_scene_types.h"
 
 #include "BKE_brush.h"
-#include "BKE_texture.h"
 
 #include "BLI_math.h"
 
-- 
cgit v1.2.3


From 9dbe85c17ea0e3a9279780e51a9caea69ea056ed Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Fri, 4 Jan 2013 03:47:37 +0000
Subject: expose common extensions for image/movie/audio types, since python
 scripts had to do this internally. - bpy.path.extensions_image -
 bpy.path.extensions_movie - bpy.path.extensions_audio

eg:

  if os.path.splitext(filename)[1].lower() in bpy.path.extensions_image:
      ... we have an image ...
---
 source/blender/python/generic/py_capi_utils.c | 17 +++++++++++++++++
 source/blender/python/generic/py_capi_utils.h |  1 +
 source/blender/python/intern/CMakeLists.txt   |  2 ++
 source/blender/python/intern/bpy_interface.c  |  2 ++
 4 files changed, 22 insertions(+)

(limited to 'source')

diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c
index f62fdaf09db..9a064923736 100644
--- a/source/blender/python/generic/py_capi_utils.c
+++ b/source/blender/python/generic/py_capi_utils.c
@@ -241,6 +241,23 @@ PyObject *PyC_Object_GetAttrStringArgs(PyObject *o, Py_ssize_t n, ...)
 	return item;
 }
 
+PyObject *PyC_FrozenSetFromStrings(const char **strings)
+{
+	const char **str;
+	PyObject *ret;
+
+	ret = PyFrozenSet_New(NULL);
+
+	for (str = strings; *str; str++) {
+		PyObject *py_str = PyUnicode_FromString(*str);
+		PySet_Add(ret, py_str);
+		Py_DECREF(py_str);
+	}
+
+	return ret;
+}
+
+
 /* similar to PyErr_Format(),
  *
  * implementation - we cant actually preprend the existing exception,
diff --git a/source/blender/python/generic/py_capi_utils.h b/source/blender/python/generic/py_capi_utils.h
index 45c9247d710..db582bd7086 100644
--- a/source/blender/python/generic/py_capi_utils.h
+++ b/source/blender/python/generic/py_capi_utils.h
@@ -33,6 +33,7 @@ void			PyC_LineSpit(void);
 void			PyC_StackSpit(void);
 PyObject *		PyC_ExceptionBuffer(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, ...);
 void			PyC_FileAndNum(const char **filename, int *lineno);
 void			PyC_FileAndNum_Safe(const char **filename, int *lineno); /* checks python is running */
diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt
index 6f2c5a75730..b94869c6ca5 100644
--- a/source/blender/python/intern/CMakeLists.txt
+++ b/source/blender/python/intern/CMakeLists.txt
@@ -56,6 +56,7 @@ set(SRC
 	bpy_library.c
 	bpy_operator.c
 	bpy_operator_wrap.c
+	bpy_path.c
 	bpy_props.c
 	bpy_rna.c
 	bpy_rna_anim.c
@@ -76,6 +77,7 @@ set(SRC
 	bpy_library.h
 	bpy_operator.h
 	bpy_operator_wrap.h
+	bpy_path.h
 	bpy_props.h
 	bpy_rna.h
 	bpy_rna_anim.h
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index d71c85bc3a0..7bce8673943 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -44,6 +44,7 @@
 #include "bpy.h"
 #include "gpu.h"
 #include "bpy_rna.h"
+#include "bpy_path.h"
 #include "bpy_util.h"
 #include "bpy_traceback.h"
 #include "bpy_intern_string.h"
@@ -212,6 +213,7 @@ static struct _inittab bpy_internal_modules[] = {
 	{(char *)"mathutils", PyInit_mathutils},
 //	{(char *)"mathutils.geometry", PyInit_mathutils_geometry},
 //	{(char *)"mathutils.noise", PyInit_mathutils_noise},
+	{(char *)"_bpy_path", BPyInit__bpy_path},
 	{(char *)"bgl", BPyInit_bgl},
 	{(char *)"blf", BPyInit_blf},
 	{(char *)"bmesh", BPyInit_bmesh},
-- 
cgit v1.2.3


From 1e762a29eec29c193f29f41444b243a7836dbdea Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Fri, 4 Jan 2013 04:43:49 +0000
Subject: change bpy.app.build_options from frozen set to
 PyStructSequence_Field, mathes similar members of bpy.app and less error
 prone (typos won't fail silently).

---
 source/blender/python/SConscript                   |  12 +-
 source/blender/python/intern/CMakeLists.txt        |  20 +-
 .../blender/python/intern/bpy_app_build_options.c  | 221 ++++++++++++++++-----
 3 files changed, 195 insertions(+), 58 deletions(-)

(limited to 'source')

diff --git a/source/blender/python/SConscript b/source/blender/python/SConscript
index 0a117f842e5..c28987eb156 100644
--- a/source/blender/python/SConscript
+++ b/source/blender/python/SConscript
@@ -130,6 +130,12 @@ if env['WITH_BF_TIFF']:
 if env['WITH_BF_INTERNATIONAL']:
     defs.append('WITH_INTERNATIONAL')
 
+if env['WITH_BF_OPENAL']:
+    defs.append('WITH_OPENAL')
+
+if env['WITH_BF_SDL']:
+    defs.append('WITH_SDL')
+
 if env['WITH_BF_JACK']:
     defs.append('WITH_JACK')
 
@@ -151,12 +157,12 @@ if env['WITH_BF_REMESH']:
 if env['WITH_BF_SMOKE']:
     defs.append('WITH_SMOKE')
 
-if env['WITH_BF_OPENAL']:
-    defs.append('WITH_OPENAL')
-
 if env['WITH_BF_COLLADA']:
     defs.append('WITH_COLLADA')
 
+if env['WITH_BF_OIIO']:
+    defs.append('WITH_OCIO')
+
 if env['WITH_BF_PLAYER']:
     defs.append('WITH_PLAYER')
 
diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt
index b94869c6ca5..575185ece2d 100644
--- a/source/blender/python/intern/CMakeLists.txt
+++ b/source/blender/python/intern/CMakeLists.txt
@@ -185,12 +185,16 @@ if(WITH_INTERNATIONAL)
 	add_definitions(-DWITH_INTERNATIONAL)
 endif()
 
-if(WITH_JACK)
-	add_definitions(-DWITH_JACK)
+if(WITH_OPENAL)
+	add_definitions(-DWITH_OPENAL)
 endif()
 
-if(WITH_LIBMV)
-	add_definitions(-DWITH_LIBMV)
+if(WITH_SDL)
+	add_definitions(-DWITH_SDL)
+endif()
+
+if(WITH_JACK)
+	add_definitions(-DWITH_JACK)
 endif()
 
 if(WITH_LIBMV)
@@ -217,14 +221,14 @@ if(WITH_MOD_SMOKE)
 	add_definitions(-DWITH_SMOKE)
 endif()
 
-if(WITH_OPENAL)
-	add_definitions(-DWITH_OPENAL)
-endif()
-
 if(WITH_OPENCOLLADA)
 	add_definitions(-DWITH_COLLADA)
 endif()
 
+if(WITH_OPENCOLORIO)
+	add_definitions(-DWITH_OCIO)
+endif()
+
 if(WITH_PLAYER)
 	add_definitions(-DWITH_PLAYER)
 endif()
diff --git a/source/blender/python/intern/bpy_app_build_options.c b/source/blender/python/intern/bpy_app_build_options.c
index 607613b592c..0036b377d3c 100644
--- a/source/blender/python/intern/bpy_app_build_options.c
+++ b/source/blender/python/intern/bpy_app_build_options.c
@@ -15,7 +15,7 @@
  * 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
+ * Contributor(s): Sergey Sharybin
  *
  * ***** END GPL LICENSE BLOCK *****
  */
@@ -29,148 +29,275 @@
 
 #include "bpy_app_build_options.h"
 
-static PyObject *make_build_options(void)
+static PyTypeObject BlenderAppBuildOptionsType;
+
+static PyStructSequence_Field app_builtopts_info_fields[] = {
+	/* names mostly follow CMake options, lowecases, after WITH_ */
+	{(char *)"bullet", NULL},
+	{(char *)"codec_avi", NULL},
+	{(char *)"codec_ffmpeg", NULL},
+	{(char *)"codec_quicktime", NULL},
+	{(char *)"codec_sndfile", NULL},
+	{(char *)"compositor", NULL},
+	{(char *)"cycles", NULL},
+	{(char *)"cycles_osl", NULL},
+	{(char *)"gameengine", NULL},
+	{(char *)"image_cineon", NULL},
+	{(char *)"image_dds", NULL},
+	{(char *)"image_frameserver", NULL},
+	{(char *)"image_hdr", NULL},
+	{(char *)"image_openexr", NULL},
+	{(char *)"image_openjpeg", NULL},
+	{(char *)"image_redcode", NULL},
+	{(char *)"image_tiff", NULL},
+	{(char *)"input_ndof", NULL},
+	{(char *)"audaspace", NULL},
+	{(char *)"international", NULL},
+	{(char *)"openal", NULL},
+	{(char *)"sdl", NULL},
+	{(char *)"jack", NULL},
+	{(char *)"libmv", NULL},
+	{(char *)"mod_boolean", NULL},
+	{(char *)"mod_fluid", NULL},
+	{(char *)"mod_oceansim", NULL},
+	{(char *)"mod_remesh", NULL},
+	{(char *)"mod_smoke", NULL},
+	{(char *)"collada", NULL},
+	{(char *)"opencolorio", NULL},
+	{(char *)"player", NULL},
+	{NULL}
+};
+
+
+static PyStructSequence_Desc app_builtopts_info_desc = {
+	(char *)"bpy.app.build_options",     /* name */
+	(char *)"This module contains information about FFmpeg blender is linked against",    /* doc */
+	app_builtopts_info_fields,    /* fields */
+	(sizeof(app_builtopts_info_fields) / sizeof(PyStructSequence_Field)) - 1
+};
+
+static PyObject *make_builtopts_info(void)
 {
-	PyObject *build_options = PyFrozenSet_New(NULL);
+	PyObject *builtopts_info;
+	int pos = 0;
 
-#define SetStrItem(str) \
-	PySet_Add(build_options, PyUnicode_FromString(str));
+	builtopts_info = PyStructSequence_New(&BlenderAppBuildOptionsType);
+	if (builtopts_info == NULL) {
+		return NULL;
+	}
 
-#ifdef WITH_AUDASPACE
-	SetStrItem("AUDASPACE");
-#endif
+#define SetObjIncref(item) \
+	PyStructSequence_SET_ITEM(builtopts_info, pos++, (Py_IncRef(item), item))
 
 #ifdef WITH_BULLET
-	SetStrItem("BULLET");
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
 #endif
 
 #ifdef WITH_AVI
-	SetStrItem("CODEC_AVI");
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
 #endif
 
 #ifdef WITH_FFMPEG
-	SetStrItem("CODEC_FFMPEG");
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
 #endif
 
 #ifdef WITH_QUICKTIME
-	SetStrItem("CODEC_QUICKTIME");
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
 #endif
 
 #ifdef WITH_SNDFILE
-	SetStrItem("CODEC_SNDFILE");
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
 #endif
 
 #ifdef WITH_COMPOSITOR
-	SetStrItem("COMPOSITOR");
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
 #endif
 
 #ifdef WITH_CYCLES
-	SetStrItem("CYCLES");
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
 #endif
 
 #ifdef WITH_CYCLES_OSL
-	SetStrItem("CYCLES_OSL");
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
 #endif
 
 #ifdef WITH_GAMEENGINE
-	SetStrItem("GAMEENGINE");
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
 #endif
 
 #ifdef WITH_CINEON
-	SetStrItem("IMAGE_CINEON");
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
 #endif
 
 #ifdef WITH_DDS
-	SetStrItem("IMAGE_DDS");
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
 #endif
 
 #ifdef WITH_FRAMESERVER
-	SetStrItem("IMAGE_FRAMESERVER");
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
 #endif
 
 #ifdef WITH_HDR
-	SetStrItem("IMAGE_HDR");
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
 #endif
 
 #ifdef WITH_OPENEXR
-	SetStrItem("IMAGE_OPENEXR");
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
 #endif
 
 #ifdef WITH_OPENJPEG
-	SetStrItem("IMAGE_OPENJPEG");
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
 #endif
 
 #ifdef WITH_REDCODE
-	SetStrItem("IMAGE_REDCODE");
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
 #endif
 
 #ifdef WITH_TIFF
-	SetStrItem("IMAGE_TIFF");
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
 #endif
 
 #ifdef WITH_INPUT_NDOF
-	SetStrItem("INPUT_NDOF");
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_AUDASPACE
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
 #endif
 
 #ifdef WITH_INTERNATIONAL
-	SetStrItem("INTERNATIONAL");
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_OPENAL
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_SDL
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
 #endif
 
 #ifdef WITH_JACK
-	SetStrItem("JACK");
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
 #endif
 
 #ifdef WITH_LIBMV
-	SetStrItem("LIBMV");
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
 #endif
 
 #ifdef WITH_MOD_BOOLEAN
-	SetStrItem("MOD_BOOLEAN");
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
 #endif
 
 #ifdef WITH_MOD_FLUID
-	SetStrItem("MOD_FLUID");
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
 #endif
 
 #ifdef WITH_OCEANSIM
-	SetStrItem("MOD_OCEANSIM");
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
 #endif
 
 #ifdef WITH_MOD_REMESH
-	SetStrItem("MOD_REMESH");
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
 #endif
 
 #ifdef WITH_SMOKE
-	SetStrItem("MOD_SMOKE");
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
 #endif
 
-#ifdef WITH_OPENAL
-	SetStrItem("OPENAL");
+#ifdef WITH_COLLADA
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
 #endif
 
-#ifdef WITH_COLLADA
-	SetStrItem("COLLADA");
+#ifdef WITH_OCIO
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
 #endif
 
 #ifdef WITH_PLAYER
-	SetStrItem("PLAYER");
+	SetObjIncref(Py_True);
+#else
+	SetObjIncref(Py_False);
 #endif
 
-#undef SetStrItem
+#undef SetObjIncref
 
-	if (PyErr_Occurred()) {
-		Py_CLEAR(build_options);
-		return NULL;
-	}
-
-	return build_options;
+	return builtopts_info;
 }
 
 PyObject *BPY_app_build_options_struct(void)
 {
 	PyObject *ret;
 
-	ret = make_build_options();
+	PyStructSequence_InitType(&BlenderAppBuildOptionsType, &app_builtopts_info_desc);
+
+	ret = make_builtopts_info();
+
+	/* prevent user from creating new instances */
+	BlenderAppBuildOptionsType.tp_init = NULL;
+	BlenderAppBuildOptionsType.tp_new = NULL;
+	BlenderAppBuildOptionsType.tp_hash = (hashfunc)_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */
 
 	return ret;
 }
-- 
cgit v1.2.3


From 6fabbcb4dde782448df2079d6dba625720d9b487 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Fri, 4 Jan 2013 05:43:26 +0000
Subject: fix [#33758] Blender crashes when user goes to choose "build
 navigation mesh"

Give useful reports when the 'MESH_OT_navmesh_make' fails too.
---
 source/blender/editors/mesh/mesh_navmesh.c | 46 ++++++++++++++++++++----------
 1 file changed, 31 insertions(+), 15 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/mesh/mesh_navmesh.c b/source/blender/editors/mesh/mesh_navmesh.c
index 1a81cab8de7..a7f77d0d483 100644
--- a/source/blender/editors/mesh/mesh_navmesh.c
+++ b/source/blender/editors/mesh/mesh_navmesh.c
@@ -157,8 +157,9 @@ static void createVertsTrisData(bContext *C, LinkNode *obs, int *nverts_r, float
 	*tris_r = tris;
 }
 
-static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts, int ntris, int *tris,
-                        struct recast_polyMesh **pmesh, struct recast_polyMeshDetail **dmesh)
+static bool buildNavMesh(const RecastData *recastParams, int nverts, float *verts, int ntris, int *tris,
+                         struct recast_polyMesh **pmesh, struct recast_polyMeshDetail **dmesh,
+                         ReportList *reports)
 {
 	float bmin[3], bmax[3];
 	struct recast_heightfield *solid;
@@ -185,14 +186,20 @@ static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts
 	/* Set the area where the navigation will be build. */
 	recast_calcGridSize(bmin, bmax, recastParams->cellsize, &width, &height);
 
+	/* zero dimensions cause zero alloc later on [#33758] */
+	if (width <= 0 || height <= 0) {
+		BKE_report(reports, RPT_ERROR, "Object has no volume");
+		return false;
+	}
+
 	/* ** Step 2: Rasterize input polygon soup ** */
 	/* Allocate voxel heightfield where we rasterize our input data to */
 	solid = recast_newHeightfield();
 
 	if (!recast_createHeightfield(solid, width, height, bmin, bmax, recastParams->cellsize, recastParams->cellheight)) {
 		recast_destroyHeightfield(solid);
-
-		return 0;
+		BKE_report(reports, RPT_ERROR, "Faled to create hight field");
+		return false;
 	}
 
 	/* Allocate array that can hold triangle flags */
@@ -215,7 +222,8 @@ static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts
 		recast_destroyHeightfield(solid);
 		recast_destroyCompactHeightfield(chf);
 
-		return 0;
+		BKE_report(reports, RPT_ERROR, "Faled to create compact hight field");
+		return false;
 	}
 
 	recast_destroyHeightfield(solid);
@@ -224,21 +232,24 @@ static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts
 	if (!recast_erodeWalkableArea(walkableRadius, chf)) {
 		recast_destroyCompactHeightfield(chf);
 
-		return 0;
+		BKE_report(reports, RPT_ERROR, "Faled to erode walkable area");
+		return false;
 	}
 
 	/* Prepare for region partitioning, by calculating distance field along the walkable surface */
 	if (!recast_buildDistanceField(chf)) {
 		recast_destroyCompactHeightfield(chf);
 
-		return 0;
+		BKE_report(reports, RPT_ERROR, "Faled to build distance field");
+		return false;
 	}
 
 	/* Partition the walkable surface into simple regions without holes */
 	if (!recast_buildRegions(chf, 0, minRegionArea, mergeRegionArea)) {
 		recast_destroyCompactHeightfield(chf);
 
-		return 0;
+		BKE_report(reports, RPT_ERROR, "Faled to build regions");
+		return false;
 	}
 
 	/* ** Step 5: Trace and simplify region contours ** */
@@ -249,7 +260,8 @@ static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts
 		recast_destroyCompactHeightfield(chf);
 		recast_destroyContourSet(cset);
 
-		return 0;
+		BKE_report(reports, RPT_ERROR, "Faled to build contours");
+		return false;
 	}
 
 	/* ** Step 6: Build polygons mesh from contours ** */
@@ -259,7 +271,8 @@ static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts
 		recast_destroyContourSet(cset);
 		recast_destroyPolyMesh(*pmesh);
 
-		return 0;
+		BKE_report(reports, RPT_ERROR, "Faled to build poly mesh");
+		return false;
 	}
 
 
@@ -272,13 +285,14 @@ static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts
 		recast_destroyPolyMesh(*pmesh);
 		recast_destroyPolyMeshDetail(*dmesh);
 
-		return 0;
+		BKE_report(reports, RPT_ERROR, "Faled to build poly mesh detail");
+		return false;
 	}
 
 	recast_destroyCompactHeightfield(chf);
 	recast_destroyContourSet(cset);
 
-	return 1;
+	return true;
 }
 
 static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh, struct recast_polyMeshDetail *dmesh, Base *base)
@@ -437,6 +451,7 @@ static int navmesh_create_exec(bContext *C, wmOperator *op)
 	if (obs) {
 		struct recast_polyMesh *pmesh = NULL;
 		struct recast_polyMeshDetail *dmesh = NULL;
+		bool ok;
 
 		int nverts = 0, ntris = 0;
 		int *tris = 0;
@@ -444,13 +459,14 @@ static int navmesh_create_exec(bContext *C, wmOperator *op)
 
 		createVertsTrisData(C, obs, &nverts, &verts, &ntris, &tris);
 		BLI_linklist_free(obs, NULL);
-		buildNavMesh(&scene->gm.recastData, nverts, verts, ntris, tris, &pmesh, &dmesh);
-		createRepresentation(C, pmesh, dmesh, navmeshBase);
+		if ((ok = buildNavMesh(&scene->gm.recastData, nverts, verts, ntris, tris, &pmesh, &dmesh, op->reports))) {
+			createRepresentation(C, pmesh, dmesh, navmeshBase);
+		}
 
 		MEM_freeN(verts);
 		MEM_freeN(tris);
 
-		return OPERATOR_FINISHED;
+		return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
 	}
 	else {
 		BKE_report(op->reports, RPT_ERROR, "No mesh objects found");
-- 
cgit v1.2.3


From ab913fe15de957faf38aac11635d68e83df457f4 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Fri, 4 Jan 2013 07:57:33 +0000
Subject: add length average option to 'Follow Active Quads' unwrap, gives
 nicer results.

---
 source/blender/editors/mesh/mesh_navmesh.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/editors/mesh/mesh_navmesh.c b/source/blender/editors/mesh/mesh_navmesh.c
index a7f77d0d483..41d4d4aafec 100644
--- a/source/blender/editors/mesh/mesh_navmesh.c
+++ b/source/blender/editors/mesh/mesh_navmesh.c
@@ -188,7 +188,7 @@ static bool buildNavMesh(const RecastData *recastParams, int nverts, float *vert
 
 	/* zero dimensions cause zero alloc later on [#33758] */
 	if (width <= 0 || height <= 0) {
-		BKE_report(reports, RPT_ERROR, "Object has no volume");
+		BKE_report(reports, RPT_ERROR, "Object has a width or height of zero");
 		return false;
 	}
 
-- 
cgit v1.2.3


From 3b3c0b97fd5a5d4d1a936e9e31b80d0befdb4956 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Fri, 4 Jan 2013 07:58:47 +0000
Subject: commit bpy_path files, missed these in recent commit.

---
 source/blender/python/intern/bpy_path.c | 65 +++++++++++++++++++++++++++++++++
 source/blender/python/intern/bpy_path.h | 33 +++++++++++++++++
 2 files changed, 98 insertions(+)
 create mode 100644 source/blender/python/intern/bpy_path.c
 create mode 100644 source/blender/python/intern/bpy_path.h

(limited to 'source')

diff --git a/source/blender/python/intern/bpy_path.c b/source/blender/python/intern/bpy_path.c
new file mode 100644
index 00000000000..8df7ed2364f
--- /dev/null
+++ b/source/blender/python/intern/bpy_path.c
@@ -0,0 +1,65 @@
+/*
+ * ***** 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): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/bpy_path.c
+ *  \ingroup pythonintern
+ *
+ * This file defines '_bpy_path' module, Some 'C' funtionality used by 'bpy.path'
+ */
+
+#include 
+
+#include "bpy_path.h"
+
+#include "../generic/py_capi_utils.h"
+
+/* #include "IMB_imbuf_types.h" */
+extern const char *imb_ext_image[];
+extern const char *imb_ext_movie[];
+extern const char *imb_ext_audio[];
+
+/*----------------------------MODULE INIT-------------------------*/
+static struct PyModuleDef _bpy_path_module_def = {
+	PyModuleDef_HEAD_INIT,
+	"_bpy_path",  /* m_name */
+	NULL,  /* m_doc */
+	0,  /* m_size */
+	NULL,  /* m_methods */
+	NULL,  /* m_reload */
+	NULL,  /* m_traverse */
+	NULL,  /* m_clear */
+	NULL,  /* m_free */
+};
+
+PyObject *BPyInit__bpy_path(void)
+{
+	PyObject *submodule;
+
+	submodule = PyModule_Create(&_bpy_path_module_def);
+
+	PyModule_AddObject(submodule, "extensions_image", PyC_FrozenSetFromStrings(imb_ext_image));
+	PyModule_AddObject(submodule, "extensions_movie", PyC_FrozenSetFromStrings(imb_ext_movie));
+	PyModule_AddObject(submodule, "extensions_audio", PyC_FrozenSetFromStrings(imb_ext_audio));
+
+	return submodule;
+}
+
diff --git a/source/blender/python/intern/bpy_path.h b/source/blender/python/intern/bpy_path.h
new file mode 100644
index 00000000000..a0f31202264
--- /dev/null
+++ b/source/blender/python/intern/bpy_path.h
@@ -0,0 +1,33 @@
+/*
+ * ***** 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): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/bpy_path.h
+ *  \ingroup pythonintern
+ */
+
+
+#ifndef __BPY_PATH_H__
+#define __BPY_PATH_H__
+
+PyObject *BPyInit__bpy_path(void);
+
+#endif
-- 
cgit v1.2.3


From b94a5d59bffc75e67498ec542fa1ca9394a10c0a Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Fri, 4 Jan 2013 08:17:09 +0000
Subject: fix [#33742] Solidify - Material index problem missed copying
 material offset values.

---
 source/blender/modifiers/intern/MOD_solidify.c | 2 ++
 1 file changed, 2 insertions(+)

(limited to 'source')

diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c
index 75e54d77b15..038fb4913ec 100644
--- a/source/blender/modifiers/intern/MOD_solidify.c
+++ b/source/blender/modifiers/intern/MOD_solidify.c
@@ -185,6 +185,8 @@ static void copyData(ModifierData *md, ModifierData *target)
 	tsmd->crease_outer = smd->crease_outer;
 	tsmd->crease_rim = smd->crease_rim;
 	tsmd->flag = smd->flag;
+	tsmd->mat_ofs = smd->mat_ofs;
+	tsmd->mat_ofs_rim = smd->mat_ofs_rim;
 	BLI_strncpy(tsmd->defgrp_name, smd->defgrp_name, sizeof(tsmd->defgrp_name));
 }
 
-- 
cgit v1.2.3


From 03044290cea2f3e38ee8a4d7249ecd48f475ce23 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Fri, 4 Jan 2013 09:35:38 +0000
Subject: remove stray glBegin() during transform that caused a glError

---
 source/blender/editors/transform/transform.c | 1 -
 1 file changed, 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index cbd8521cc33..3b443e8bbac 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -1518,7 +1518,6 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
 				glTranslatef(mval[0], mval[1], 0);
 
 				glLineWidth(3.0);
-				glBegin(GL_LINES);
 				drawArrow(UP, 5, 10, 5);
 				drawArrow(DOWN, 5, 10, 5);
 				glLineWidth(1.0);
-- 
cgit v1.2.3


From 1022151d6ef644280074c29fd88c42007e17d45b Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Fri, 4 Jan 2013 11:02:35 +0000
Subject: fix for missing NULL check in BKE_sequence_init_colorspace().

---
 source/blender/blenkernel/intern/sequencer.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index a5c1c990b9e..465b1bc4e29 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -3967,13 +3967,13 @@ void BKE_sequence_init_colorspace(Sequence *seq)
 			/* byte images are default to straight alpha, however sequencer
 			 * works in premul space, so mark strip to be premultiplied first
 			 */
-			if (!ibuf->rect_float)
-				seq->alpha_mode = SEQ_ALPHA_STRAIGHT;
-			else
-				seq->alpha_mode = SEQ_ALPHA_PREMUL;
-
-			if (ibuf)
+			seq->alpha_mode = SEQ_ALPHA_PREMUL;
+			if (ibuf) {
+				if (ibuf->rect_float) {
+					seq->alpha_mode = SEQ_ALPHA_PREMUL;
+				}
 				IMB_freeImBuf(ibuf);
+			}
 		}
 	}
 }
-- 
cgit v1.2.3


From ec33cacc62054fb1ca90aa860e6b9866ca4a7126 Mon Sep 17 00:00:00 2001
From: Stuart Broadfoot 
Date: Fri, 4 Jan 2013 12:44:38 +0000
Subject: Added vertex color attributes (currently limited to one) and UVs
 included for triangle mesh hair.

I have also included a small speedup for the intersection test.
---
 source/blender/makesrna/intern/rna_particle.c | 121 ++++++++++++++++++++++++++
 1 file changed, 121 insertions(+)

(limited to 'source')

diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index c6d1adac19a..be3cbfaece3 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -452,6 +452,115 @@ static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, Par
 	}
 }
 
+static void rna_ParticleSystem_mcol_on_emitter(ParticleSystem *particlesystem, ParticleSystemModifierData *modifier, ParticleData *particle, int particle_no, int vcol_no,
+                                             float n_mcol[3])
+{
+	ParticleSettings *part = 0;
+	int totpart;
+	int totchild = 0;
+	int num;
+	MCol mcol = {255, 255, 255, 255};
+
+	/* 1. check that everything is ok & updated */
+	if (particlesystem == NULL)
+		return;
+
+	part = particlesystem->part;
+
+		totchild = particlesystem->totchild;
+
+	/* can happen for disconnected/global hair */
+	if (part->type == PART_HAIR && !particlesystem->childcache)
+		totchild = 0;
+
+	totpart = particlesystem->totpart;
+
+	if (particle_no >= totpart + totchild)
+		return;
+
+/* 3. start creating renderable things */
+	/* setup per particle individual stuff */
+	if (particle_no < totpart) {
+
+		/* get uvco & mcol */
+		num = particle->num_dmcache;
+
+		if (num == DMCACHE_NOTFOUND)
+			if (particle->num < modifier->dm->getNumTessFaces(modifier->dm))
+				num = particle->num;
+
+		if (n_mcol && ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
+			if (num != DMCACHE_NOTFOUND) {
+				MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
+				MCol *mc = (MCol*)CustomData_get_layer_n(&modifier->dm->faceData, CD_MCOL, vcol_no);
+				mc += num * 4;
+
+				psys_interpolate_mcol(mc, mface->v4, particle->fuv, &mcol);
+				n_mcol[0] = (float)mcol.b / 255.0f;
+				n_mcol[1] = (float)mcol.g / 255.0f;
+				n_mcol[2] = (float)mcol.r / 255.0f;
+			}
+			else {
+				n_mcol[0] = 0.0f;
+				n_mcol[1] = 0.0f;
+				n_mcol[2] = 0.0f;
+			}
+		}
+	}
+	else {
+		ChildParticle *cpa = particlesystem->child + particle_no - totpart;
+
+		num = cpa->num;
+
+		/* get uvco & mcol */
+		if (part->childtype == PART_CHILD_FACES) {
+			if (n_mcol && ELEM(PART_FROM_FACE, PART_FROM_FACE, PART_FROM_VOLUME)) {
+				if (cpa->num != DMCACHE_NOTFOUND) {
+					MFace *mface = modifier->dm->getTessFaceData(modifier->dm, cpa->num, CD_MFACE);
+					MCol *mc = (MCol*)CustomData_get_layer_n(&modifier->dm->faceData, CD_MCOL, 0);
+					mc += cpa->num * 4;
+
+					psys_interpolate_mcol(mc, mface->v4, cpa->fuv, &mcol);
+					n_mcol[0] = (float)mcol.b / 255.0f;
+					n_mcol[1] = (float)mcol.g / 255.0f;
+					n_mcol[2] = (float)mcol.r / 255.0f;
+				}
+				else {
+					n_mcol[0] = 0.0f;
+					n_mcol[1] = 0.0f;
+					n_mcol[2] = 0.0f;
+				}
+			}
+		}
+		else {
+			ParticleData *parent = particlesystem->particles + cpa->parent;
+			num = parent->num_dmcache;
+
+			if (num == DMCACHE_NOTFOUND)
+				if (parent->num < modifier->dm->getNumTessFaces(modifier->dm))
+					num = parent->num;
+
+			if (n_mcol && ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
+				if (num != DMCACHE_NOTFOUND) {
+					MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
+					MCol *mc = (MCol*)CustomData_get_layer_n(&modifier->dm->faceData, CD_MCOL, 0);
+					mc += num * 4;
+
+					psys_interpolate_mcol(mc, mface->v4, parent->fuv, &mcol);
+					n_mcol[0] = (float)mcol.b / 255.0f;
+					n_mcol[1] = (float)mcol.g / 255.0f;
+					n_mcol[2] = (float)mcol.r / 255.0f;
+				}
+				else {
+					n_mcol[0] = 0.0f;
+					n_mcol[1] = 0.0f;
+					n_mcol[2] = 0.0f;
+				}
+			}
+		}
+	}
+}
+
 static void particle_recalc(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr, short flag)
 {
 	if (ptr->type == &RNA_ParticleSystem) {
@@ -3258,6 +3367,18 @@ static void rna_def_particle_system(BlenderRNA *brna)
 	RNA_def_property_flag(prop, PROP_THICK_WRAP);
 	RNA_def_function_output(func, prop);
 
+	/* extract hair mcols */
+	func = RNA_def_function(srna, "mcol_on_emitter", "rna_ParticleSystem_mcol_on_emitter");
+	RNA_def_function_ui_description(func, "Obtain mcol for all particles");
+	prop = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier");
+	prop = RNA_def_pointer(func, "particle", "Particle", "", "Particle");
+	prop = RNA_def_int(func, "particle_no", 0, INT_MIN, INT_MAX, "Particle no", "", INT_MIN, INT_MAX);
+	prop = RNA_def_int(func, "vcol_no", 0, INT_MIN, INT_MAX, "vcol no", "", INT_MIN, INT_MAX);
+	prop = RNA_def_property(func, "mcol", PROP_FLOAT, PROP_COLOR);
+	RNA_def_property_array(prop, 3);
+	RNA_def_property_flag(prop, PROP_THICK_WRAP);
+	RNA_def_function_output(func, prop);
+
 }
 
 void RNA_def_particle(BlenderRNA *brna)
-- 
cgit v1.2.3


From 821d481f53b77a3b14ab8d1343dab7ae26f089c9 Mon Sep 17 00:00:00 2001
From: Sergey Sharybin 
Date: Fri, 4 Jan 2013 13:19:57 +0000
Subject: Correction for rev53555 which was obviously wrong -- always setting
 alpha to premul

Also optimized it a bit by skipping byte/float buffer allocation.
---
 source/blender/blenkernel/intern/sequencer.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 465b1bc4e29..8d010de408a 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -3962,16 +3962,16 @@ void BKE_sequence_init_colorspace(Sequence *seq)
 
 		/* initialize input color space */
 		if (seq->type == SEQ_TYPE_IMAGE) {
-			ibuf = IMB_loadiffname(name, IB_rect, seq->strip->colorspace_settings.name);
+			ibuf = IMB_loadiffname(name, IB_test | IB_alphamode_detect, seq->strip->colorspace_settings.name);
 
 			/* byte images are default to straight alpha, however sequencer
 			 * works in premul space, so mark strip to be premultiplied first
 			 */
-			seq->alpha_mode = SEQ_ALPHA_PREMUL;
+			seq->alpha_mode = SEQ_ALPHA_STRAIGHT;
 			if (ibuf) {
-				if (ibuf->rect_float) {
-					seq->alpha_mode = SEQ_ALPHA_PREMUL;
-				}
+				if (ibuf->flags & IB_alphamode_premul)
+					seq->alpha_mode = IMA_ALPHA_PREMUL;
+
 				IMB_freeImBuf(ibuf);
 			}
 		}
-- 
cgit v1.2.3


From 4fa340c71691c68148ca72379f21f000f0f35664 Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Fri, 4 Jan 2013 14:51:02 +0000
Subject: Fixes - post 2.65a

- Trackpad swipes now behave same as scrollwheel for listview scrolls
  (disabling 2d view scroll when mouse over)

- Added back 2.4 debug print for glGetError()
  Only useful for developers - to check what goes on when ogl messes up.

- Made more clear print for read factory default. It's not error :)
---
 .../blender/editors/interface/interface_handlers.c | 103 +++++++++++----------
 .../blender/windowmanager/intern/wm_event_system.c |  10 +-
 source/blender/windowmanager/intern/wm_files.c     |   4 +-
 3 files changed, 67 insertions(+), 50 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 83f1cc4851d..1c9cd92271c 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -6131,70 +6131,79 @@ static int ui_handle_list_event(bContext *C, wmEvent *event, ARegion *ar)
 	int value, min, max;
 	int type = event->type, val = event->val;
 
-	/* convert pan to scrollwheel */
-	if (type == MOUSEPAN)
-		ui_pan_to_scroll(event, &type, &val);
-	
-	if (but && (val == KM_PRESS)) {
+	if (but) {
 		uiList *ui_list = but->custom_data;
 
 		if (ui_list) {
+			
+			/* convert pan to scrollwheel */
+			if (type == MOUSEPAN) {
+				ui_pan_to_scroll(event, &type, &val);
+				
+				/* if type still is mousepan, we call it handled, since delta-y accumulate */
+				/* also see wm_event_system.c do_wheel_ui hack */
+				if (type == MOUSEPAN)
+					retval = WM_UI_HANDLER_BREAK;
+			}
+			
+			if (val == KM_PRESS) {
+				
+				if (ELEM(type, UPARROWKEY, DOWNARROWKEY) ||
+					((ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->alt)))
+				{
+					/* activate up/down the list */
+					value = RNA_property_int_get(&but->rnapoin, but->rnaprop);
 
-			if (ELEM(type, UPARROWKEY, DOWNARROWKEY) ||
-				((ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->alt)))
-			{
-				/* activate up/down the list */
-				value = RNA_property_int_get(&but->rnapoin, but->rnaprop);
-
-				if (ELEM(type, UPARROWKEY, WHEELUPMOUSE))
-					value--;
-				else
-					value++;
-
-				CLAMP(value, 0, ui_list->list_last_len - 1);
-
-				if (value < ui_list->list_scroll)
-					ui_list->list_scroll = value;
-				else if (value >= ui_list->list_scroll + ui_list->list_size)
-					ui_list->list_scroll = value - ui_list->list_size + 1;
-
-				RNA_property_int_range(&but->rnapoin, but->rnaprop, &min, &max);
-				value = CLAMPIS(value, min, max);
+					if (ELEM(type, UPARROWKEY, WHEELUPMOUSE))
+						value--;
+					else
+						value++;
 
-				RNA_property_int_set(&but->rnapoin, but->rnaprop, value);
-				RNA_property_update(C, &but->rnapoin, but->rnaprop);
-				ED_region_tag_redraw(ar);
+					CLAMP(value, 0, ui_list->list_last_len - 1);
 
-				retval = WM_UI_HANDLER_BREAK;
-			}
-			else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->shift) {
-				/* silly replacement for proper grip */
-				if (ui_list->list_grip_size == 0)
-					ui_list->list_grip_size = ui_list->list_size;
+					if (value < ui_list->list_scroll)
+						ui_list->list_scroll = value;
+					else if (value >= ui_list->list_scroll + ui_list->list_size)
+						ui_list->list_scroll = value - ui_list->list_size + 1;
 
-				if (type == WHEELUPMOUSE)
-					ui_list->list_grip_size--;
-				else
-					ui_list->list_grip_size++;
+					RNA_property_int_range(&but->rnapoin, but->rnaprop, &min, &max);
+					value = CLAMPIS(value, min, max);
 
-				ui_list->list_grip_size = MAX2(ui_list->list_grip_size, 1);
+					RNA_property_int_set(&but->rnapoin, but->rnaprop, value);
+					RNA_property_update(C, &but->rnapoin, but->rnaprop);
+					ED_region_tag_redraw(ar);
 
-				ED_region_tag_redraw(ar);
+					retval = WM_UI_HANDLER_BREAK;
+				}
+				else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->shift) {
+					/* silly replacement for proper grip */
+					if (ui_list->list_grip_size == 0)
+						ui_list->list_grip_size = ui_list->list_size;
 
-				retval = WM_UI_HANDLER_BREAK;
-			}
-			else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
-				if (ui_list->list_last_len > ui_list->list_size) {
-					/* list template will clamp */
 					if (type == WHEELUPMOUSE)
-						ui_list->list_scroll--;
+						ui_list->list_grip_size--;
 					else
-						ui_list->list_scroll++;
+						ui_list->list_grip_size++;
+
+					ui_list->list_grip_size = MAX2(ui_list->list_grip_size, 1);
 
 					ED_region_tag_redraw(ar);
 
 					retval = WM_UI_HANDLER_BREAK;
 				}
+				else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
+					if (ui_list->list_last_len > ui_list->list_size) {
+						/* list template will clamp */
+						if (type == WHEELUPMOUSE)
+							ui_list->list_scroll--;
+						else
+							ui_list->list_scroll++;
+
+						ED_region_tag_redraw(ar);
+
+						retval = WM_UI_HANDLER_BREAK;
+					}
+				}
 			}
 		}
 	}
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index e462e21d9f4..a42986eba60 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -66,6 +66,8 @@
 
 #include "RNA_access.h"
 
+#include "BIF_gl.h"
+
 #include "UI_interface.h"
 
 #include "PIL_time.h"
@@ -338,7 +340,7 @@ static int wm_handler_ui_call(bContext *C, wmEventHandler *handler, wmEvent *eve
 	ARegion *region = CTX_wm_region(C);
 	ARegion *menu = CTX_wm_menu(C);
 	static int do_wheel_ui = TRUE;
-	int is_wheel = ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE);
+	int is_wheel = ELEM3(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE, MOUSEPAN);
 	int retval;
 	
 	/* UI code doesn't handle return values - it just always returns break. 
@@ -2180,6 +2182,12 @@ void wm_event_do_handlers(bContext *C)
 
 	/* update key configuration after handling events */
 	WM_keyconfig_update(wm);
+	
+	if(G.debug) {
+		GLenum error = glGetError();
+		if (error)
+			printf("GL error: %s\n", gluErrorString(error));
+	}
 }
 
 /* ********** filesector handling ************ */
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 6a84e3e4e7d..f31aff3d3f8 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -531,7 +531,7 @@ int wm_homefile_read(bContext *C, ReportList *UNUSED(reports), short from_memory
 	}
 	
 	if (U.themes.first == NULL) {
-		printf("\nError: No valid "STRINGIFY (BLENDER_STARTUP_FILE)", fall back to built-in default.\n\n");
+		printf("\nNote: No (valid) "STRINGIFY (BLENDER_STARTUP_FILE)" found, fall back to built-in default.\n\n");
 		success = 0;
 	}
 
@@ -549,7 +549,7 @@ int wm_homefile_read(bContext *C, ReportList *UNUSED(reports), short from_memory
 	/* check new prefs only after startup.blend was finished */
 	if (!from_memory && BLI_exists(prefstr)) {
 		int done = BKE_read_file_userdef(prefstr, NULL);
-		if (done) printf("read new prefs: %s\n", prefstr);
+		if (done) printf("Read new prefs: %s\n", prefstr);
 	}
 	
 	/* prevent buggy files that had G_FILE_RELATIVE_REMAP written out by mistake. Screws up autosaves otherwise
-- 
cgit v1.2.3


From 0f565149864ac34d54c5a0e517a8db88cf67a6d6 Mon Sep 17 00:00:00 2001
From: Howard Trickey 
Date: Fri, 4 Jan 2013 15:06:34 +0000
Subject: Fix knife cut bug #33625, failure to cut in otho mode sometimes.
 Problem was that the code to limit the front and back planes for better
 precision assumed line would have center near origin.

---
 source/blender/editors/mesh/editmesh_knife.c | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index c8a1264fd10..542d568f7b8 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -1315,7 +1315,7 @@ static void knife_bgl_get_mats(KnifeTool_OpData *UNUSED(kcd), bglMats *mats)
 	//copy_m4_m4(mats->projection, kcd->vc.rv3d->winmat);
 }
 
-/* Calculate maximum excursion (doubled) from (0,0,0) of mesh */
+/* Calculate maximum excursion from (0,0,0) of mesh */
 static void calc_ortho_extent(KnifeTool_OpData *kcd)
 {
 	BMIter iter;
@@ -1328,7 +1328,18 @@ static void calc_ortho_extent(KnifeTool_OpData *kcd)
 		for (i = 0; i < 3; i++)
 			max_xyz = max_ff(max_xyz, fabs(v->co[i]));
 	}
-	kcd->ortho_extent = 2 * max_xyz;
+	kcd->ortho_extent = max_xyz;
+}
+
+/* Clip the line (v1, v2) to planes perpendicular to it and distances d from
+ * the closest point on the line to the origin */
+static void clip_to_ortho_planes(float v1[3], float v2[3], float d) {
+	float closest[3];
+	const float origin[3] = {0.0f, 0.0f, 0.0f};
+
+	closest_to_line_v3(closest, origin, v1, v2);
+	dist_ensure_v3_v3fl(v1, closest, d);
+	dist_ensure_v3_v3fl(v2, closest, d);
 }
 
 /* Finds visible (or all, if cutting through) edges that intersects the current screen drag line */
@@ -1375,8 +1386,8 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
 	if (kcd->is_ortho) {
 		if (kcd->ortho_extent == 0.0f)
 			calc_ortho_extent(kcd);
-		limit_dist_v3(v1, v3, kcd->ortho_extent + 10.0f);
-		limit_dist_v3(v2, v4, kcd->ortho_extent + 10.0f);
+		clip_to_ortho_planes(v1, v3, kcd->ortho_extent + 10.0f);
+		clip_to_ortho_planes(v2, v4, kcd->ortho_extent + 10.0f);
 	}
 
 	BLI_smallhash_init(ehash);
-- 
cgit v1.2.3


From 419016928216707f95fa7b94d233b0bb8707ff3c Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Fri, 4 Jan 2013 17:24:40 +0000
Subject: code cleanup, also remove glError check in font drawing code since
 its now a debug option.

---
 source/blender/blenfont/intern/blf_glyph.c            | 1 -
 source/blender/editors/mesh/editmesh_knife.c          | 3 ++-
 source/blender/render/intern/source/rendercore.c      | 3 ++-
 source/blender/windowmanager/intern/wm_event_system.c | 7 ++++---
 4 files changed, 8 insertions(+), 6 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index 2c582133b15..9c7623f3757 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -420,7 +420,6 @@ int blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
 
 		glBindTexture(GL_TEXTURE_2D, g->tex);
 		glTexSubImage2D(GL_TEXTURE_2D, 0, g->xoff, g->yoff, g->width, g->height, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap);
-		BLI_assert(glGetError() == GL_NO_ERROR);
 		glPopClientAttrib();
 
 		g->uv[0][0] = ((float)g->xoff) / ((float)gc->p2_width);
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index 542d568f7b8..590bcd5939e 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -1333,7 +1333,8 @@ static void calc_ortho_extent(KnifeTool_OpData *kcd)
 
 /* Clip the line (v1, v2) to planes perpendicular to it and distances d from
  * the closest point on the line to the origin */
-static void clip_to_ortho_planes(float v1[3], float v2[3], float d) {
+static void clip_to_ortho_planes(float v1[3], float v2[3], float d)
+{
 	float closest[3];
 	const float origin[3] = {0.0f, 0.0f, 0.0f};
 
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index 90ff96d7a64..14586f16478 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -2613,7 +2613,8 @@ static int get_next_bake_face(BakeShade *bs)
 	return 0;
 }
 
-static void bake_single_vertex(BakeShade *bs, VertRen *vert, float u, float v) {
+static void bake_single_vertex(BakeShade *bs, VertRen *vert, float u, float v)
+{
 	int *origindex, i;
 	MLoopCol *basevcol;
 	MLoop *mloop;
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index a42986eba60..a6b3efd30bf 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -2182,11 +2182,12 @@ void wm_event_do_handlers(bContext *C)
 
 	/* update key configuration after handling events */
 	WM_keyconfig_update(wm);
-	
-	if(G.debug) {
+
+	if (G.debug) {
 		GLenum error = glGetError();
-		if (error)
+		if (error != GL_NO_ERROR) {
 			printf("GL error: %s\n", gluErrorString(error));
+		}
 	}
 }
 
-- 
cgit v1.2.3


From 499088366421d2a240721267f46bf5ca335e1ed4 Mon Sep 17 00:00:00 2001
From: Sergey Sharybin 
Date: Fri, 4 Jan 2013 17:28:58 +0000
Subject: Optimization for speed regression in mipmap generation

Regression was caused by alpha premul cleanup commit and the reason
of slowdown was uchar <-> float conversion which is slow.

Replaced with uchar <-> int conversion which seeps to be accurate
enough and mostly eliminates slowdown.

Slowdown was easy to notice when movie clip is used for 3d vierport
background and undistortion is enabled. In this case every frame
will re-calculate mipmaps.

It's still a nit slower than mipmap generation before cleanup
commit, but couldn't think about extra boost here atm.
---
 source/blender/blenlib/BLI_math_color.h           |  2 ++
 source/blender/blenlib/intern/math_color_inline.c | 28 +++++++++++++++++++++++
 source/blender/imbuf/intern/scaling.c             | 20 ++++++++--------
 3 files changed, 40 insertions(+), 10 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h
index 3831ec3cbb4..1af6985deaa 100644
--- a/source/blender/blenlib/BLI_math_color.h
+++ b/source/blender/blenlib/BLI_math_color.h
@@ -106,6 +106,8 @@ MINLINE void premul_to_straight_v4(float straight[4], const float premul[4]);
 MINLINE void straight_to_premul_v4(float straight[4], const float premul[4]);
 MINLINE void straight_uchar_to_premul_float(float result[4], const unsigned char color[4]);
 MINLINE void premul_float_to_straight_uchar(unsigned char *result, const float color[4]);
+MINLINE void straight_uchar_to_premul_int(int result[4], const unsigned char color[4]);
+MINLINE void premul_int_to_straight_uchar(unsigned char *result, const int color[4]);
 
 /************************** Other *************************/
 
diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c
index b8eeca50db6..f8bb6b81a1d 100644
--- a/source/blender/blenlib/intern/math_color_inline.c
+++ b/source/blender/blenlib/intern/math_color_inline.c
@@ -326,4 +326,32 @@ MINLINE void premul_float_to_straight_uchar(unsigned char *result, const float c
 	}
 }
 
+MINLINE void straight_uchar_to_premul_int(int result[4], const unsigned char color[4])
+{
+	int alpha = color[3];
+
+	result[0] = (color[0] * alpha) / 255;
+	result[1] = (color[1] * alpha) / 255;
+	result[2] = (color[2] * alpha) / 255;
+	result[3] = alpha;
+}
+
+MINLINE void premul_int_to_straight_uchar(unsigned char *result, const int color[4])
+{
+	if (color[3] == 0 || color[3] == 255) {
+		result[0] = color[0];
+		result[1] = color[1];
+		result[2] = color[2];
+		result[3] = color[3];
+	}
+	else {
+		int alpha = color[3];
+
+		result[0] = color[0] * 255 / alpha;
+		result[0] = color[1] * 255 / alpha;
+		result[0] = color[2] * 255 / alpha;
+		result[3] = alpha;
+	}
+}
+
 #endif /* __MATH_COLOR_INLINE_C__ */
diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c
index 75d1f4c412d..8d3cd648fc1 100644
--- a/source/blender/imbuf/intern/scaling.c
+++ b/source/blender/imbuf/intern/scaling.c
@@ -311,19 +311,19 @@ void imb_onehalf_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1)
 		for (y = ibuf2->y; y > 0; y--) {
 			cp2 = cp1 + (ibuf1->x << 2);
 			for (x = ibuf2->x; x > 0; x--) {
-				float p1f[8], p2f[8], destf[4];
+				int p1i[8], p2i[8], desti[4];
 
-				straight_uchar_to_premul_float(p1f, cp1);
-				straight_uchar_to_premul_float(p2f, cp2);
-				straight_uchar_to_premul_float(p1f + 4, cp1 + 4);
-				straight_uchar_to_premul_float(p2f + 4, cp2 + 4);
+				straight_uchar_to_premul_int(p1i, cp1);
+				straight_uchar_to_premul_int(p2i, cp2);
+				straight_uchar_to_premul_int(p1i + 4, cp1 + 4);
+				straight_uchar_to_premul_int(p2i + 4, cp2 + 4);
 
-				destf[0] = 0.25f * (p1f[0] + p2f[0] + p1f[4] + p2f[4]);
-				destf[1] = 0.25f * (p1f[1] + p2f[1] + p1f[5] + p2f[5]);
-				destf[2] = 0.25f * (p1f[2] + p2f[2] + p1f[6] + p2f[6]);
-				destf[3] = 0.25f * (p1f[3] + p2f[3] + p1f[7] + p2f[7]);
+				desti[0] = (p1i[0] + p2i[0] + p1i[4] + p2i[4]) >> 2;
+				desti[1] = (p1i[1] + p2i[1] + p1i[5] + p2i[5]) >> 2;
+				desti[2] = (p1i[2] + p2i[2] + p1i[6] + p2i[6]) >> 2;
+				desti[3] = (p1i[3] + p2i[3] + p1i[7] + p2i[7]) >> 2;
 
-				premul_float_to_straight_uchar(dest, destf);
+				premul_int_to_straight_uchar(dest, desti);
 
 				cp1 += 8;
 				cp2 += 8;
-- 
cgit v1.2.3


From 52a81c8364c1da5d7607b6964d5e64d1cd00703a Mon Sep 17 00:00:00 2001
From: Sergey Sharybin 
Date: Fri, 4 Jan 2013 20:34:06 +0000
Subject: There was a typo in previous commit

Additional changes:

- Made mipmapping operate with unsigned short instead of char
  which allowed to eliminate extra division by 255, so prevision
  should be a bit better now.

- Actually, this is not real unsigned short range, but it's a
  range of 255*255 which is more convenient for mipmapping, so
  made conversion functions private for scaling.c

  Not sure it worth making this functions operate in 65535
  range, for now current behavior seems to be just fine.
---
 source/blender/blenlib/BLI_math_color.h           |  2 -
 source/blender/blenlib/intern/math_color_inline.c | 28 -------------
 source/blender/imbuf/intern/scaling.c             | 51 ++++++++++++++++++-----
 3 files changed, 41 insertions(+), 40 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h
index 1af6985deaa..3831ec3cbb4 100644
--- a/source/blender/blenlib/BLI_math_color.h
+++ b/source/blender/blenlib/BLI_math_color.h
@@ -106,8 +106,6 @@ MINLINE void premul_to_straight_v4(float straight[4], const float premul[4]);
 MINLINE void straight_to_premul_v4(float straight[4], const float premul[4]);
 MINLINE void straight_uchar_to_premul_float(float result[4], const unsigned char color[4]);
 MINLINE void premul_float_to_straight_uchar(unsigned char *result, const float color[4]);
-MINLINE void straight_uchar_to_premul_int(int result[4], const unsigned char color[4]);
-MINLINE void premul_int_to_straight_uchar(unsigned char *result, const int color[4]);
 
 /************************** Other *************************/
 
diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c
index f8bb6b81a1d..b8eeca50db6 100644
--- a/source/blender/blenlib/intern/math_color_inline.c
+++ b/source/blender/blenlib/intern/math_color_inline.c
@@ -326,32 +326,4 @@ MINLINE void premul_float_to_straight_uchar(unsigned char *result, const float c
 	}
 }
 
-MINLINE void straight_uchar_to_premul_int(int result[4], const unsigned char color[4])
-{
-	int alpha = color[3];
-
-	result[0] = (color[0] * alpha) / 255;
-	result[1] = (color[1] * alpha) / 255;
-	result[2] = (color[2] * alpha) / 255;
-	result[3] = alpha;
-}
-
-MINLINE void premul_int_to_straight_uchar(unsigned char *result, const int color[4])
-{
-	if (color[3] == 0 || color[3] == 255) {
-		result[0] = color[0];
-		result[1] = color[1];
-		result[2] = color[2];
-		result[3] = color[3];
-	}
-	else {
-		int alpha = color[3];
-
-		result[0] = color[0] * 255 / alpha;
-		result[0] = color[1] * 255 / alpha;
-		result[0] = color[2] * 255 / alpha;
-		result[3] = alpha;
-	}
-}
-
 #endif /* __MATH_COLOR_INLINE_C__ */
diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c
index 8d3cd648fc1..1050d3f8715 100644
--- a/source/blender/imbuf/intern/scaling.c
+++ b/source/blender/imbuf/intern/scaling.c
@@ -292,6 +292,37 @@ struct ImBuf *IMB_double_y(struct ImBuf *ibuf1)
 	return (ibuf2);
 }
 
+/* pretty much specific functions which converts uchar <-> ushort but assumes
+ * ushort range of 255*255 which is more convenient here
+ */
+MINLINE void straight_uchar_to_premul_ushort(unsigned short result[4], const unsigned char color[4])
+{
+	unsigned short alpha = color[3];
+
+	result[0] = color[0] * alpha;
+	result[1] = color[1] * alpha;
+	result[2] = color[2] * alpha;
+	result[3] = alpha * 255;
+}
+
+MINLINE void premul_ushort_to_straight_uchar(unsigned char *result, const unsigned short color[4])
+{
+	if (color[3] <= 255) {
+		result[0] = color[0] / 255;
+		result[1] = color[1] / 255;
+		result[2] = color[2] / 255;
+		result[3] = color[3] / 255;
+	}
+	else {
+		unsigned short alpha = color[3] / 255;
+
+		result[0] = color[0] / alpha;
+		result[1] = color[1] / alpha;
+		result[2] = color[2] / alpha;
+		result[3] = alpha;
+	}
+}
+
 /* result in ibuf2, scaling should be done correctly */
 void imb_onehalf_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1)
 {
@@ -311,19 +342,19 @@ void imb_onehalf_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1)
 		for (y = ibuf2->y; y > 0; y--) {
 			cp2 = cp1 + (ibuf1->x << 2);
 			for (x = ibuf2->x; x > 0; x--) {
-				int p1i[8], p2i[8], desti[4];
+				unsigned short p1i[8], p2i[8], desti[4];
 
-				straight_uchar_to_premul_int(p1i, cp1);
-				straight_uchar_to_premul_int(p2i, cp2);
-				straight_uchar_to_premul_int(p1i + 4, cp1 + 4);
-				straight_uchar_to_premul_int(p2i + 4, cp2 + 4);
+				straight_uchar_to_premul_ushort(p1i, cp1);
+				straight_uchar_to_premul_ushort(p2i, cp2);
+				straight_uchar_to_premul_ushort(p1i + 4, cp1 + 4);
+				straight_uchar_to_premul_ushort(p2i + 4, cp2 + 4);
 
-				desti[0] = (p1i[0] + p2i[0] + p1i[4] + p2i[4]) >> 2;
-				desti[1] = (p1i[1] + p2i[1] + p1i[5] + p2i[5]) >> 2;
-				desti[2] = (p1i[2] + p2i[2] + p1i[6] + p2i[6]) >> 2;
-				desti[3] = (p1i[3] + p2i[3] + p1i[7] + p2i[7]) >> 2;
+				desti[0] = ((unsigned int) p1i[0] + p2i[0] + p1i[4] + p2i[4]) >> 2;
+				desti[1] = ((unsigned int) p1i[1] + p2i[1] + p1i[5] + p2i[5]) >> 2;
+				desti[2] = ((unsigned int) p1i[2] + p2i[2] + p1i[6] + p2i[6]) >> 2;
+				desti[3] = ((unsigned int) p1i[3] + p2i[3] + p1i[7] + p2i[7]) >> 2;
 
-				premul_int_to_straight_uchar(dest, desti);
+				premul_ushort_to_straight_uchar(dest, desti);
 
 				cp1 += 8;
 				cp2 += 8;
-- 
cgit v1.2.3


From d9001335ffd4c875b0bca7d36956b96012a34a1e Mon Sep 17 00:00:00 2001
From: Mitchell Stokes 
Date: Sat, 5 Jan 2013 03:30:56 +0000
Subject: BGE: The Blenderplayer wasn't calling PyEval_InitThreads, which
 caused async lib loading to crash.

---
 source/gameengine/Ketsji/KX_PythonInit.cpp | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'source')

diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp
index 0d39eb844b5..02995a53954 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.cpp
+++ b/source/gameengine/Ketsji/KX_PythonInit.cpp
@@ -1921,6 +1921,9 @@ PyObject *initGamePlayerPythonScripting(const STR_String& progname, TPythonSecur
 		PySys_SetObject("argv", py_argv);
 		Py_DECREF(py_argv);
 	}
+	
+	/* Initialize thread support (also acquires lock) */
+	PyEval_InitThreads();
 
 	bpy_import_init(PyEval_GetBuiltins());
 
-- 
cgit v1.2.3


From 3b3d419dcb534e12a3b58ef792a6ce287bb113be Mon Sep 17 00:00:00 2001
From: Sergey Sharybin 
Date: Sat, 5 Jan 2013 07:08:54 +0000
Subject: Fix #33767: Edge of objects rendered out jerky when using OpenGL
 Rendering

Made OpenGL sky opaque, so now it behaves exactly the same as sky for final render.
---
 source/blender/editors/space_view3d/view3d_draw.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 7475f65317a..e7243e9d4b9 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -2596,10 +2596,11 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar,
 			linearrgb_to_srgb_v3_v3(backcol, &scene->world->horr);
 		}
 
-		glClearColor(backcol[0], backcol[1], backcol[2], 0.0);
+		glClearColor(backcol[0], backcol[1], backcol[2], 1.0f);
 	}
 	else {
-		UI_ThemeClearColor(TH_BACK);
+		UI_GetThemeColor3fv(TH_BACK, backcol);
+		glClearColor(backcol[0], backcol[1], backcol[2], 1.0f);
 	}
 
 
-- 
cgit v1.2.3


From a3f3c205cd89a687199723294f3fb029c48429b7 Mon Sep 17 00:00:00 2001
From: Sergey Sharybin 
Date: Sat, 5 Jan 2013 07:25:02 +0000
Subject: Fix #33768: BGE segfaults in do_versions during libload

---
 source/blender/blenloader/intern/readfile.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'source')

diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 7827a3a9bf1..9ca393a946b 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -8594,10 +8594,10 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
 
 		for (tex = main->tex.first; tex; tex = tex->id.next) {
 			if (tex->type == TEX_IMAGE && (tex->imaflag & TEX_USEALPHA) == 0) {
-				if (tex->ima) {
-					image = blo_do_versions_newlibadr(fd, lib, tex->ima);
+				image = blo_do_versions_newlibadr(fd, tex->id.lib, tex->ima);
+
+				if (image)
 					image->flag |= IMA_IGNORE_ALPHA;
-				}
 			}
 		}
 	}
-- 
cgit v1.2.3


From 93a6872a254f4507d07ffb17919a32e234715ce1 Mon Sep 17 00:00:00 2001
From: Sergey Sharybin 
Date: Sat, 5 Jan 2013 07:30:52 +0000
Subject: Fix #33761: Infinite loop in space_image if tile size > image size

---
 source/blender/editors/space_image/image_draw.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index 79130ccca2f..0534b9f4ffd 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -587,8 +587,8 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene,
 		sima->curtile = ima->xrep * ima->yrep - 1;
 	
 	/* retrieve part of image buffer */
-	dx = ibuf->x / ima->xrep;
-	dy = ibuf->y / ima->yrep;
+	dx = max_ii(ibuf->x / ima->xrep, 1);
+	dy = max_ii(ibuf->y / ima->yrep, 1);
 	sx = (sima->curtile % ima->xrep) * dx;
 	sy = (sima->curtile / ima->xrep) * dy;
 	rect = get_part_from_buffer((unsigned int *)display_buffer, ibuf->x, sx, sy, sx + dx, sy + dy);
-- 
cgit v1.2.3


From 0d678e71a833ef8a8055160f00b11121c9488fe1 Mon Sep 17 00:00:00 2001
From: Sergey Sharybin 
Date: Sat, 5 Jan 2013 08:03:16 +0000
Subject: Fix #33674: Meta strip could overlap with other strips when exiting
 edit mode

Not sure what's the best thing to do here, for now just added vertical shuffle
of meta strip if it overlaps with other strips when existing edit mode.
---
 source/blender/editors/space_sequencer/sequencer_edit.c | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'source')

diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 892f0a3f489..c6c70ccb424 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -1906,6 +1906,9 @@ static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op))
 		for (seq = ed->seqbasep->first; seq; seq = seq->next)
 			BKE_sequence_calc(scene, seq);
 
+		if (BKE_sequence_test_overlap(ed->seqbasep, ms->parseq))
+			BKE_sequence_base_shuffle(ed->seqbasep, ms->parseq, scene);
+
 		BKE_sequencer_active_set(scene, ms->parseq);
 
 		ms->parseq->flag |= SELECT;
-- 
cgit v1.2.3


From 9611202f285547d9791a793581c2641349bc2211 Mon Sep 17 00:00:00 2001
From: Sergey Sharybin 
Date: Sat, 5 Jan 2013 08:24:22 +0000
Subject: Fix #33753: Not selected surface objects don't update in view if
 shading is changed

In fact surfaces should be displaying the same way in textures and solid shading,
but they used to change a way they're displaying by draw_textured_end not resetting
light model properly, leaving two-sided shading for all further objects draw.
---
 source/blender/editors/space_view3d/drawmesh.c | 1 +
 1 file changed, 1 insertion(+)

(limited to 'source')

diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c
index 0e86438997c..fa72f28cc44 100644
--- a/source/blender/editors/space_view3d/drawmesh.c
+++ b/source/blender/editors/space_view3d/drawmesh.c
@@ -396,6 +396,7 @@ static void draw_textured_end(void)
 
 	glShadeModel(GL_FLAT);
 	glDisable(GL_CULL_FACE);
+	glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
 
 	/* XXX, bad patch - GPU_default_lights() calls
 	 * glLightfv(GL_POSITION, ...) which
-- 
cgit v1.2.3


From 9106b3b10782da51814d3a859eebae51085c374c Mon Sep 17 00:00:00 2001
From: Mitchell Stokes 
Date: Sat, 5 Jan 2013 08:53:39 +0000
Subject: BGE: Fix for [#33769] "Material friction settings are ignored"
 reported by Alex Fraser (z0r).

As of r53332, give_current_material() won't accept a 0 index and return NULL. CreateMaterialFromBlenderObject() was using index 0 to just grab the first material. Since this now returned NULL, it would use default settings. We'll just ask for index 1 now instead.
---
 source/gameengine/Converter/BL_BlenderDataConversion.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index a873f8ba281..a4c4253754e 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -1264,7 +1264,7 @@ static PHY_MaterialProps *CreateMaterialFromBlenderObject(struct Object* blender
 	
 	MT_assert(materialProps && "Create physics material properties failed");
 		
-	Material* blendermat = give_current_material(blenderobject, 0);
+	Material* blendermat = give_current_material(blenderobject, 1);
 		
 	if (blendermat)
 	{
-- 
cgit v1.2.3


From bb744090317962faf66093ccccef2fe8c1947017 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Sat, 5 Jan 2013 10:26:33 +0000
Subject: revert r53570, alpha background is useful for projection paint 'Quick
 Edit', it would also give odd results drawing semi transparent faces will
 give partial alpha which is strange to have with solid backdrop.

---
 source/blender/editors/space_view3d/view3d_draw.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index e7243e9d4b9..4ccf26e12b1 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -2596,11 +2596,10 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar,
 			linearrgb_to_srgb_v3_v3(backcol, &scene->world->horr);
 		}
 
-		glClearColor(backcol[0], backcol[1], backcol[2], 1.0f);
+		glClearColor(backcol[0], backcol[1], backcol[2], 0.0f);
 	}
 	else {
-		UI_GetThemeColor3fv(TH_BACK, backcol);
-		glClearColor(backcol[0], backcol[1], backcol[2], 1.0f);
+		 UI_ThemeClearColor(TH_BACK);
 	}
 
 
-- 
cgit v1.2.3


From 5b72578a1350881866600b2fe9e4a7d0231bf02c Mon Sep 17 00:00:00 2001
From: Bastien Montagne 
Date: Sat, 5 Jan 2013 11:50:36 +0000
Subject: Tsst... "faled"... :p

---
 source/blender/editors/mesh/mesh_navmesh.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/mesh/mesh_navmesh.c b/source/blender/editors/mesh/mesh_navmesh.c
index 41d4d4aafec..99fa85b3ee7 100644
--- a/source/blender/editors/mesh/mesh_navmesh.c
+++ b/source/blender/editors/mesh/mesh_navmesh.c
@@ -198,7 +198,7 @@ static bool buildNavMesh(const RecastData *recastParams, int nverts, float *vert
 
 	if (!recast_createHeightfield(solid, width, height, bmin, bmax, recastParams->cellsize, recastParams->cellheight)) {
 		recast_destroyHeightfield(solid);
-		BKE_report(reports, RPT_ERROR, "Faled to create hight field");
+		BKE_report(reports, RPT_ERROR, "Failed to create height field");
 		return false;
 	}
 
@@ -222,7 +222,7 @@ static bool buildNavMesh(const RecastData *recastParams, int nverts, float *vert
 		recast_destroyHeightfield(solid);
 		recast_destroyCompactHeightfield(chf);
 
-		BKE_report(reports, RPT_ERROR, "Faled to create compact hight field");
+		BKE_report(reports, RPT_ERROR, "Failed to create compact height field");
 		return false;
 	}
 
@@ -232,7 +232,7 @@ static bool buildNavMesh(const RecastData *recastParams, int nverts, float *vert
 	if (!recast_erodeWalkableArea(walkableRadius, chf)) {
 		recast_destroyCompactHeightfield(chf);
 
-		BKE_report(reports, RPT_ERROR, "Faled to erode walkable area");
+		BKE_report(reports, RPT_ERROR, "Failed to erode walkable area");
 		return false;
 	}
 
@@ -240,7 +240,7 @@ static bool buildNavMesh(const RecastData *recastParams, int nverts, float *vert
 	if (!recast_buildDistanceField(chf)) {
 		recast_destroyCompactHeightfield(chf);
 
-		BKE_report(reports, RPT_ERROR, "Faled to build distance field");
+		BKE_report(reports, RPT_ERROR, "Failed to build distance field");
 		return false;
 	}
 
@@ -248,7 +248,7 @@ static bool buildNavMesh(const RecastData *recastParams, int nverts, float *vert
 	if (!recast_buildRegions(chf, 0, minRegionArea, mergeRegionArea)) {
 		recast_destroyCompactHeightfield(chf);
 
-		BKE_report(reports, RPT_ERROR, "Faled to build regions");
+		BKE_report(reports, RPT_ERROR, "Failed to build regions");
 		return false;
 	}
 
@@ -260,7 +260,7 @@ static bool buildNavMesh(const RecastData *recastParams, int nverts, float *vert
 		recast_destroyCompactHeightfield(chf);
 		recast_destroyContourSet(cset);
 
-		BKE_report(reports, RPT_ERROR, "Faled to build contours");
+		BKE_report(reports, RPT_ERROR, "Failed to build contours");
 		return false;
 	}
 
@@ -271,7 +271,7 @@ static bool buildNavMesh(const RecastData *recastParams, int nverts, float *vert
 		recast_destroyContourSet(cset);
 		recast_destroyPolyMesh(*pmesh);
 
-		BKE_report(reports, RPT_ERROR, "Faled to build poly mesh");
+		BKE_report(reports, RPT_ERROR, "Failed to build poly mesh");
 		return false;
 	}
 
@@ -285,7 +285,7 @@ static bool buildNavMesh(const RecastData *recastParams, int nverts, float *vert
 		recast_destroyPolyMesh(*pmesh);
 		recast_destroyPolyMeshDetail(*dmesh);
 
-		BKE_report(reports, RPT_ERROR, "Faled to build poly mesh detail");
+		BKE_report(reports, RPT_ERROR, "Failed to build poly mesh detail");
 		return false;
 	}
 
-- 
cgit v1.2.3


From 6cf52cc80c4cee6d6d4dbc0c18ea7f2bb8c69ee6 Mon Sep 17 00:00:00 2001
From: Joshua Leung 
Date: Sat, 5 Jan 2013 11:56:20 +0000
Subject: Bugfix: "Change Frame" operator for setting current frame by
 clicking/scrubbing in a timeline view would show up search results in other
 editors (e.g. 3D View).

This only really works where there is a timeline view as:
1) The modal interactive stuff is built on the assumption that a suitable 2D
view mapping exists
2) The operator is not "registered" (i.e. no props display after usage, and
doesn't get shown in undo) as it's more "view state" than "scene data"

Rewrote poll callback to handlethis properly
---
 source/blender/editors/animation/anim_ops.c | 30 ++++++++++++++++++++---------
 1 file changed, 21 insertions(+), 9 deletions(-)

(limited to 'source')

diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c
index ca036a8540e..6687cce88cd 100644
--- a/source/blender/editors/animation/anim_ops.c
+++ b/source/blender/editors/animation/anim_ops.c
@@ -62,16 +62,28 @@
 /* Check if the operator can be run from the current context */
 static int change_frame_poll(bContext *C)
 {
-	ScrArea *curarea = CTX_wm_area(C);
+	ScrArea *sa = CTX_wm_area(C);
 	
 	/* XXX temp? prevent changes during render */
-	if (G.is_rendering) return 0;
+	if (G.is_rendering) return FALSE;
 	
-	/* as long as there is an active area, and it isn't a Graph Editor 
-	 * (since the Graph Editor has its own version which does extra stuff),
-	 * we're fine
+	/* although it's only included in keymaps for regions using ED_KEYMAP_ANIMATION,
+	 * this shouldn't show up in 3D editor (or others without 2D timeline view) via search
 	 */
-	return ((curarea) && (curarea->spacetype != SPACE_IPO));
+	if (sa) {
+		if (ELEM5(sa->spacetype, SPACE_TIME, SPACE_ACTION, SPACE_NLA, SPACE_SEQ, SPACE_CLIP)) {
+			return TRUE;
+		}
+		else if (sa->spacetype == SPACE_IPO) {
+			/* NOTE: Graph Editor has special version which does some extra stuff.
+			 * No need to show the generic error message for that case though!
+			 */
+			return FALSE;
+		}
+	}
+	
+	CTX_wm_operator_poll_msg_set(C, "Expected an timeline/animation area to be active");
+	return FALSE;
 }
 
 /* Set the new frame number */
@@ -83,7 +95,7 @@ static void change_frame_apply(bContext *C, wmOperator *op)
 	/* set the new frame number */
 	CFRA = RNA_int_get(op->ptr, "frame");
 	FRAMENUMBER_MIN_CLAMP(CFRA);
-	SUBFRA = 0.f;
+	SUBFRA = 0.0f;
 	
 	/* do updates */
 	sound_seek_scene(bmain, scene);
@@ -161,7 +173,7 @@ static int change_frame_modal(bContext *C, wmOperator *op, wmEvent *event)
 static void ANIM_OT_change_frame(wmOperatorType *ot)
 {
 	/* identifiers */
-	ot->name = "Change frame";
+	ot->name = "Change Frame";
 	ot->idname = "ANIM_OT_change_frame";
 	ot->description = "Interactively change the current frame number";
 	
@@ -175,7 +187,7 @@ static void ANIM_OT_change_frame(wmOperatorType *ot)
 	ot->flag = OPTYPE_BLOCKING | OPTYPE_UNDO | OPTYPE_GRAB_POINTER;
 
 	/* rna */
-	RNA_def_int(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
+	ot->prop = RNA_def_int(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
 }
 
 /* ****************** set preview range operator ****************************/
-- 
cgit v1.2.3


From 5ffcde851b5c2dbde7df4551bdf8979d51ce0447 Mon Sep 17 00:00:00 2001
From: "Sv. Lockal" 
Date: Sat, 5 Jan 2013 12:06:50 +0000
Subject: Add translation contexts for line, mute and clip

---
 source/blender/editors/space_sequencer/sequencer_add.c | 3 +++
 source/blender/editors/space_text/text_ops.c           | 5 ++++-
 source/blender/makesrna/intern/rna_space.c             | 1 +
 source/blender/makesrna/intern/rna_speaker.c           | 1 +
 source/blender/makesrna/intern/rna_text.c              | 3 +++
 5 files changed, 12 insertions(+), 1 deletion(-)

(limited to 'source')

diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index 0ade57b7ca9..29a6a1f6d50 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -49,6 +49,8 @@
 #include "DNA_mask_types.h"
 #include "DNA_userdef_types.h"
 
+#include "BLF_translation.h"
+
 #include "BKE_context.h"
 #include "BKE_global.h"
 #include "BKE_library.h"
@@ -400,6 +402,7 @@ void SEQUENCER_OT_movieclip_strip_add(struct wmOperatorType *ot)
 	sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
 	prop = RNA_def_enum(ot->srna, "clip", DummyRNA_NULL_items, 0, "Clip", "");
 	RNA_def_enum_funcs(prop, RNA_movieclip_itemf);
+	RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_MOVIECLIP);
 	ot->prop = prop;
 }
 
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index 89cc396efbb..21966ef614c 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -1931,6 +1931,8 @@ static int text_jump_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
 
 void TEXT_OT_jump(wmOperatorType *ot)
 {
+	PropertyRNA *prop;
+
 	/* identifiers */
 	ot->name = "Jump";
 	ot->idname = "TEXT_OT_jump";
@@ -1942,7 +1944,8 @@ void TEXT_OT_jump(wmOperatorType *ot)
 	ot->poll = text_edit_poll;
 
 	/* properties */
-	RNA_def_int(ot->srna, "line", 1, 1, INT_MAX, "Line", "Line number to jump to", 1, 10000);
+	prop = RNA_def_int(ot->srna, "line", 1, 1, INT_MAX, "Line", "Line number to jump to", 1, 10000);
+	RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_TEXT);
 }
 
 /******************* delete operator **********************/
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index c3fd7d92a9d..fab7450f0c5 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -2722,6 +2722,7 @@ static void rna_def_console_line(BlenderRNA *brna)
 	                              "rna_ConsoleLine_body_set");
 	RNA_def_property_ui_text(prop, "Line", "Text in the line");
 	RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CONSOLE, NULL);
+	RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_TEXT);
 	
 	prop = RNA_def_property(srna, "current_character", PROP_INT, PROP_NONE); /* copied from text editor */
 	RNA_def_property_int_sdna(prop, NULL, "cursor");
diff --git a/source/blender/makesrna/intern/rna_speaker.c b/source/blender/makesrna/intern/rna_speaker.c
index 139582104ee..8a75aa2d227 100644
--- a/source/blender/makesrna/intern/rna_speaker.c
+++ b/source/blender/makesrna/intern/rna_speaker.c
@@ -62,6 +62,7 @@ static void rna_def_speaker(BlenderRNA *brna)
 	RNA_def_property_boolean_sdna(prop, NULL, "flag", SPK_MUTED);
 	RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
 	RNA_def_property_ui_text(prop, "Mute", "Mute the speaker");
+	RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND);
 	/* RNA_def_property_update(prop, 0, "rna_Speaker_update"); */
 
 #if 0 /* This shouldn't be changed actually, hiding it! */
diff --git a/source/blender/makesrna/intern/rna_text.c b/source/blender/makesrna/intern/rna_text.c
index b1637ef4c8a..df6181af4b2 100644
--- a/source/blender/makesrna/intern/rna_text.c
+++ b/source/blender/makesrna/intern/rna_text.c
@@ -30,6 +30,8 @@
 
 #include "MEM_guardedalloc.h"
 
+#include "BLF_translation.h"
+
 #include "BKE_text.h"
 
 #include "RNA_define.h"
@@ -127,6 +129,7 @@ static void rna_def_text_line(BlenderRNA *brna)
 	RNA_def_property_string_funcs(prop, "rna_TextLine_body_get", "rna_TextLine_body_length", "rna_TextLine_body_set");
 	RNA_def_property_ui_text(prop, "Line", "Text in the line");
 	RNA_def_property_update(prop, NC_TEXT | NA_EDITED, NULL);
+	RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_TEXT);
 }
 
 static void rna_def_text(BlenderRNA *brna)
-- 
cgit v1.2.3


From 37ba969c74840142682cf22f34610f3b65b86cf4 Mon Sep 17 00:00:00 2001
From: Joshua Leung 
Date: Sat, 5 Jan 2013 12:27:54 +0000
Subject: Making a few tooltips more descriptive, in light of recent confusion
 over the purpose of some of these features

* ClampTo Constraint, Target Object field: now mentions that it is for curve
objects only
* Dopesheet Editor Modes: now describe what data is editable in each mode. The
wording may be a bit clumsy here, but (apart from Mask Editor one, which I'm not
entirely sure about) should at least be technically correct
---
 source/blender/makesrna/intern/rna_constraint.c |  2 +-
 source/blender/makesrna/intern/rna_space.c      | 10 +++++-----
 2 files changed, 6 insertions(+), 6 deletions(-)

(limited to 'source')

diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index 5a110802acd..0c8fb3d6a36 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -1528,7 +1528,7 @@ static void rna_def_constraint_clamp_to(BlenderRNA *brna)
 	prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
 	RNA_def_property_pointer_sdna(prop, NULL, "tar");
 	RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Curve_object_poll");
-	RNA_def_property_ui_text(prop, "Target", "Target Object");
+	RNA_def_property_ui_text(prop, "Target", "Target Object (Curves only)");
 	RNA_def_property_flag(prop, PROP_EDITABLE);
 	RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update");
 
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index fab7450f0c5..926b141ef24 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -2374,11 +2374,11 @@ static void rna_def_space_dopesheet(BlenderRNA *brna)
 	
 	/* XXX: action-editor is currently for object-level only actions, so show that using object-icon hint */
 	static EnumPropertyItem mode_items[] = {
-		{SACTCONT_DOPESHEET, "DOPESHEET", ICON_OOPS, "DopeSheet", "DopeSheet Editor"},
-		{SACTCONT_ACTION, "ACTION", ICON_OBJECT_DATA, "Action Editor", "Action Editor"},
-		{SACTCONT_SHAPEKEY, "SHAPEKEY", ICON_SHAPEKEY_DATA, "ShapeKey Editor", "ShapeKey Editor"},
-		{SACTCONT_GPENCIL, "GPENCIL", ICON_GREASEPENCIL, "Grease Pencil", "Grease Pencil"},
-		{SACTCONT_MASK, "MASK", ICON_MOD_MASK, "Mask", "Mask Editor"},
+		{SACTCONT_DOPESHEET, "DOPESHEET", ICON_OOPS, "DopeSheet", "Edit all keyframes in scene"},
+		{SACTCONT_ACTION, "ACTION", ICON_OBJECT_DATA, "Action Editor", "Edit keyframes in active object's Object-level action"},
+		{SACTCONT_SHAPEKEY, "SHAPEKEY", ICON_SHAPEKEY_DATA, "ShapeKey Editor", "Edit keyframes in active object's Shape Keys action"},
+		{SACTCONT_GPENCIL, "GPENCIL", ICON_GREASEPENCIL, "Grease Pencil", "Edit timings for all Grease Pencil sketches in file"},
+		{SACTCONT_MASK, "MASK", ICON_MOD_MASK, "Mask", "Edit timings for Mask Editor splines"},
 		{0, NULL, 0, NULL, NULL}
 	};
 		
-- 
cgit v1.2.3