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(-) 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.
---
 release/scripts/startup/bl_ui/space_view3d.py      |  3 +-
 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 +-
 7 files changed, 88 insertions(+), 28 deletions(-)

diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index b1dfc397ce0..d2183b80476 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -70,7 +70,8 @@ class VIEW3D_HT_header(Header):
                 row.prop(toolsettings.particle_edit, "select_mode", text="", expand=True)
 
             # Occlude geometry
-            if view.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'} and (mode == 'PARTICLE_EDIT' or (mode == 'EDIT' and obj.type == 'MESH')):
+            if ((view.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'} and (mode == 'PARTICLE_EDIT' or (mode == 'EDIT' and obj.type == 'MESH'))) or
+                    (mode == 'WEIGHT_PAINT' and obj.data.use_paint_mask_vertex)):
                 row.prop(view, "use_occlude_geometry", text="")
 
             # Proportional editing
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(-)

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(-)

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(-)

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(-)

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(-)

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).

---
 release/scripts/startup/keyingsets_builtins.py |  98 +++++++++++++++++-
 source/blender/editors/animation/keyframing.c  | 131 +++++++++++++------------
 2 files changed, 162 insertions(+), 67 deletions(-)

diff --git a/release/scripts/startup/keyingsets_builtins.py b/release/scripts/startup/keyingsets_builtins.py
index 6ad87375738..4f06f8a7be3 100644
--- a/release/scripts/startup/keyingsets_builtins.py
+++ b/release/scripts/startup/keyingsets_builtins.py
@@ -181,7 +181,7 @@ class BUILTIN_KSI_RotScale(KeyingSetInfo):
 # ------------
 
 
-# Location
+# VisualLocation
 class BUILTIN_KSI_VisualLoc(KeyingSetInfo):
     """
     Insert a keyframe on each of the location channels, taking into account
@@ -201,7 +201,7 @@ class BUILTIN_KSI_VisualLoc(KeyingSetInfo):
     generate = keyingsets_utils.RKS_GEN_location
 
 
-# Rotation
+# VisualRotation
 class BUILTIN_KSI_VisualRot(KeyingSetInfo):
     """
     Insert a keyframe on each of the rotation channels, taking into account
@@ -221,6 +221,26 @@ class BUILTIN_KSI_VisualRot(KeyingSetInfo):
     generate = keyingsets_utils.RKS_GEN_rotation
 
 
+# VisualScaling
+class BUILTIN_KSI_VisualScaling(KeyingSetInfo):
+    """
+    Insert a keyframe on each of the scale channels, taking into account
+    effects of constraints and relationships
+    """
+    bl_label = "Visual Scaling"
+
+    bl_options = {'INSERTKEY_VISUAL'}
+
+    # poll - use predefined callback for selected bones/objects
+    poll = keyingsets_utils.RKS_POLL_selected_items
+
+    # iterator - use callback for selected bones/objects
+    iterator = keyingsets_utils.RKS_ITER_selected_item
+
+    # generator - use callback for location
+    generate = keyingsets_utils.RKS_GEN_scaling
+
+
 # VisualLocRot
 class BUILTIN_KSI_VisualLocRot(KeyingSetInfo):
     """
@@ -244,6 +264,80 @@ class BUILTIN_KSI_VisualLocRot(KeyingSetInfo):
         # rotation
         keyingsets_utils.RKS_GEN_rotation(self, context, ks, data)
 
+
+# VisualLocScale
+class BUILTIN_KSI_VisualLocScale(KeyingSetInfo):
+    """
+    Insert a keyframe on each of the location and scaling channels,
+    taking into account effects of constraints and relationships
+    """
+    bl_label = "Visual LocScale"
+
+    bl_options = {'INSERTKEY_VISUAL'}
+
+    # poll - use predefined callback for selected bones/objects
+    poll = keyingsets_utils.RKS_POLL_selected_items
+
+    # iterator - use callback for selected bones/objects
+    iterator = keyingsets_utils.RKS_ITER_selected_item
+
+    # generator
+    def generate(self, context, ks, data):
+        # location
+        keyingsets_utils.RKS_GEN_location(self, context, ks, data)
+        # scaling
+        keyingsets_utils.RKS_GEN_scaling(self, context, ks, data)
+
+
+# VisualLocRotScale
+class BUILTIN_KSI_VisualLocRotScale(KeyingSetInfo):
+    """
+    Insert a keyframe on each of the location, rotation and scaling channels,
+    taking into account effects of constraints and relationships
+    """
+    bl_label = "Visual LocRotScale"
+
+    bl_options = {'INSERTKEY_VISUAL'}
+
+    # poll - use predefined callback for selected bones/objects
+    poll = keyingsets_utils.RKS_POLL_selected_items
+
+    # iterator - use callback for selected bones/objects
+    iterator = keyingsets_utils.RKS_ITER_selected_item
+
+    # generator
+    def generate(self, context, ks, data):
+        # location
+        keyingsets_utils.RKS_GEN_location(self, context, ks, data)
+        # rotation
+        keyingsets_utils.RKS_GEN_rotation(self, context, ks, data)
+        # scaling
+        keyingsets_utils.RKS_GEN_scaling(self, context, ks, data)
+
+
+# VisualRotScale
+class BUILTIN_KSI_VisualRotScale(KeyingSetInfo):
+    """
+    Insert a keyframe on each of the rotation and scaling channels,
+    taking into account effects of constraints and relationships
+    """
+    bl_label = "Visual RotScale"
+
+    bl_options = {'INSERTKEY_VISUAL'}
+
+    # poll - use predefined callback for selected bones/objects
+    poll = keyingsets_utils.RKS_POLL_selected_items
+
+    # iterator - use callback for selected bones/objects
+    iterator = keyingsets_utils.RKS_ITER_selected_item
+
+    # generator
+    def generate(self, context, ks, data):
+        # rotation
+        keyingsets_utils.RKS_GEN_rotation(self, context, ks, data)
+        # scaling
+        keyingsets_utils.RKS_GEN_scaling(self, context, ks, data)
+
 # ------------
 
 
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(-)

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 779662aff7e815962b43eacff46c9a5710c48e3f Mon Sep 17 00:00:00 2001
From: Brecht Van Lommel 
Date: Sun, 23 Dec 2012 12:52:10 +0000
Subject: Fix #33641: cycles self intersection artifacts with motion blur and
 one of the X/Y/Z coordinates close to 0.

---
 intern/cycles/kernel/kernel_bvh.h | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/intern/cycles/kernel/kernel_bvh.h b/intern/cycles/kernel/kernel_bvh.h
index d70485fd6cf..73e7fb0e5d6 100644
--- a/intern/cycles/kernel/kernel_bvh.h
+++ b/intern/cycles/kernel/kernel_bvh.h
@@ -457,12 +457,15 @@ __device_inline float3 ray_offset(float3 P, float3 Ng)
 {
 #ifdef __INTERSECTION_REFINE__
 	const float epsilon_f = 1e-5f;
+	/* ideally this should match epsilon_f, but instancing/mblur
+	 * precision makes it problematic */
+	const float epsilon_test = 1e-1f;
 	const int epsilon_i = 32;
 
 	float3 res;
 
 	/* x component */
-	if(fabsf(P.x) < epsilon_f) {
+	if(fabsf(P.x) < epsilon_test) {
 		res.x = P.x + Ng.x*epsilon_f;
 	}
 	else {
@@ -472,7 +475,7 @@ __device_inline float3 ray_offset(float3 P, float3 Ng)
 	}
 
 	/* y component */
-	if(fabsf(P.y) < epsilon_f) {
+	if(fabsf(P.y) < epsilon_test) {
 		res.y = P.y + Ng.y*epsilon_f;
 	}
 	else {
@@ -482,7 +485,7 @@ __device_inline float3 ray_offset(float3 P, float3 Ng)
 	}
 
 	/* z component */
-	if(fabsf(P.z) < epsilon_f) {
+	if(fabsf(P.z) < epsilon_test) {
 		res.z = P.z + Ng.z*epsilon_f;
 	}
 	else {
-- 
cgit v1.2.3


From 35c0b821a5b8d13079cbdf8258391c59d7043082 Mon Sep 17 00:00:00 2001
From: Brecht Van Lommel 
Date: Sun, 23 Dec 2012 12:53:58 +0000
Subject: Cycles: deal a bit better with errors when CUDA runs out of memory,
 try to avoid crashes.

---
 intern/cycles/device/device.h        |  1 +
 intern/cycles/device/device_cuda.cpp | 40 +++++++++++++++++++++++++++++-------
 2 files changed, 34 insertions(+), 7 deletions(-)

diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h
index 9840687b76a..7b31b9ba157 100644
--- a/intern/cycles/device/device.h
+++ b/intern/cycles/device/device.h
@@ -84,6 +84,7 @@ public:
 	/* info */
 	DeviceInfo info;
 	virtual const string& error_message() { return error_msg; }
+	bool have_error() { return !error_message().empty(); }
 
 	/* statistics */
 	Stats &stats;
diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp
index 14f8cfa8767..040f3044457 100644
--- a/intern/cycles/device/device_cuda.cpp
+++ b/intern/cycles/device/device_cuda.cpp
@@ -124,7 +124,7 @@ public:
 			if(error_msg == "") \
 				error_msg = message; \
 			fprintf(stderr, "%s\n", message.c_str()); \
-			cuda_abort(); \
+			/*cuda_abort();*/ \
 		} \
 	}
 
@@ -326,7 +326,8 @@ public:
 	void mem_copy_to(device_memory& mem)
 	{
 		cuda_push_context();
-		cuda_assert(cuMemcpyHtoD(cuda_device_ptr(mem.device_pointer), (void*)mem.data_pointer, mem.memory_size()))
+		if(mem.device_pointer)
+			cuda_assert(cuMemcpyHtoD(cuda_device_ptr(mem.device_pointer), (void*)mem.data_pointer, mem.memory_size()))
 		cuda_pop_context();
 	}
 
@@ -336,8 +337,13 @@ public:
 		size_t size = elem*w*h;
 
 		cuda_push_context();
-		cuda_assert(cuMemcpyDtoH((uchar*)mem.data_pointer + offset,
-			(CUdeviceptr)((uchar*)mem.device_pointer + offset), size))
+		if(mem.device_pointer) {
+			cuda_assert(cuMemcpyDtoH((uchar*)mem.data_pointer + offset,
+				(CUdeviceptr)((uchar*)mem.device_pointer + offset), size))
+		}
+		else {
+			memset((char*)mem.data_pointer + offset, 0, size);
+		}
 		cuda_pop_context();
 	}
 
@@ -346,7 +352,8 @@ public:
 		memset((void*)mem.data_pointer, 0, mem.memory_size());
 
 		cuda_push_context();
-		cuda_assert(cuMemsetD8(cuda_device_ptr(mem.device_pointer), 0, mem.memory_size()))
+		if(mem.device_pointer)
+			cuda_assert(cuMemsetD8(cuda_device_ptr(mem.device_pointer), 0, mem.memory_size()))
 		cuda_pop_context();
 	}
 
@@ -390,13 +397,18 @@ public:
 			default: assert(0); return;
 		}
 
-		CUtexref texref;
+		CUtexref texref = NULL;
 
 		cuda_push_context();
 		cuda_assert(cuModuleGetTexRef(&texref, cuModule, name))
 
+		if(!texref) {
+			cuda_pop_context();
+			return;
+		}
+
 		if(interpolation) {
-			CUarray handle;
+			CUarray handle = NULL;
 			CUDA_ARRAY_DESCRIPTOR desc;
 
 			desc.Width = mem.data_width;
@@ -406,6 +418,11 @@ public:
 
 			cuda_assert(cuArrayCreate(&handle, &desc))
 
+			if(!handle) {
+				cuda_pop_context();
+				return;
+			}
+
 			if(mem.data_height > 1) {
 				CUDA_MEMCPY2D param;
 				memset(¶m, 0, sizeof(param));
@@ -481,6 +498,9 @@ public:
 
 	void path_trace(RenderTile& rtile, int sample)
 	{
+		if(have_error())
+			return;
+
 		cuda_push_context();
 
 		CUfunction cuPathTrace;
@@ -546,6 +566,9 @@ public:
 
 	void tonemap(DeviceTask& task, device_ptr buffer, device_ptr rgba)
 	{
+		if(have_error())
+			return;
+
 		cuda_push_context();
 
 		CUfunction cuFilmConvert;
@@ -615,6 +638,9 @@ public:
 
 	void shader(DeviceTask& task)
 	{
+		if(have_error())
+			return;
+
 		cuda_push_context();
 
 		CUfunction cuDisplace;
-- 
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(-)

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(-)

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(-)

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 4ee0087e3584c762d02d5d049557131fa0ed47c6 Mon Sep 17 00:00:00 2001
From: Brecht Van Lommel 
Date: Sun, 23 Dec 2012 14:29:43 +0000
Subject: Fix cycles displacement not working well with OSL and multiple
 objects.

---
 intern/cycles/render/mesh_displace.cpp | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/intern/cycles/render/mesh_displace.cpp b/intern/cycles/render/mesh_displace.cpp
index dea694a811e..fdfaaf4d7de 100644
--- a/intern/cycles/render/mesh_displace.cpp
+++ b/intern/cycles/render/mesh_displace.cpp
@@ -19,6 +19,7 @@
 #include "device.h"
 
 #include "mesh.h"
+#include "object.h"
 #include "scene.h"
 #include "shader.h"
 
@@ -41,6 +42,19 @@ bool MeshManager::displace(Device *device, Scene *scene, Mesh *mesh, Progress& p
 	if(!has_displacement)
 		return false;
 
+	string msg = string_printf("Computing Displacement %s", mesh->name.c_str());
+	progress.set_status("Updating Mesh", msg);
+
+	/* find object index. todo: is arbitrary */
+	size_t object_index = ~0;
+
+	for(size_t i = 0; i < scene->objects.size(); i++) {
+		if(scene->objects[i]->mesh == mesh) {
+			object_index = i;
+			break;
+		}
+	}
+
 	/* setup input for device task */
 	vector done(mesh->verts.size(), false);
 	device_vector d_input;
@@ -61,8 +75,8 @@ bool MeshManager::displace(Device *device, Scene *scene, Mesh *mesh, Progress& p
 			done[t.v[j]] = true;
 
 			/* set up object, primitive and barycentric coordinates */
-			/* when used, non-instanced convention: object = -object-1; */
-			int object = ~0; /* todo */
+			/* when used, non-instanced convention: object = ~object */
+			int object = ~object_index;
 			int prim = mesh->tri_offset + i;
 			float u, v;
 
-- 
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(-)

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(-)

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(-)

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(-)

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(-)

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.

---
 release/scripts/startup/bl_ui/space_userpref.py | 36 +++++++++++++++++++++++++
 source/blender/makesrna/intern/rna_userdef.c    |  3 ++-
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 695e09ee025..1a80a32f957 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -22,6 +22,27 @@ from bpy.types import Header, Menu, Panel
 import os
 
 
+def ui_style_items(col, context):
+    """ UI Style settings """
+    
+    split = col.split()
+    
+    col = split.column()
+    col.label(text="Kerning Style:")
+    col.row().prop(context, "font_kerning_style", expand=True)
+    col.prop(context, "points")
+    
+    col = split.column()
+    col.label(text="Shadow Offset:")
+    col.prop(context, "shadow_offset_x", text="X")
+    col.prop(context, "shadow_offset_y", text="Y")
+    
+    col = split.column()
+    col.prop(context, "shadow")
+    col.prop(context, "shadowalpha")
+    col.prop(context, "shadowcolor")
+
+    
 def ui_items_general(col, context):
     """ General UI Theme Settings (User Interface)
     """
@@ -774,6 +795,21 @@ class USERPREF_PT_theme(Panel):
                 colsub = padding.column()
                 colsub = padding.column()
                 colsub.row().prop(ui, "show_colored_constraints")
+        elif theme.theme_area == 'STYLE':
+            col = split.column()
+            
+            style = context.user_preferences.ui_styles[0]
+            
+            ui = style.widget
+            col.label(text="Widget:")
+            ui_style_items(col, ui)
+            
+            col.separator()
+            col.separator()
+            
+            ui = style.widget_label
+            col.label(text="Widget Label:")
+            ui_style_items(col, ui)
         else:
             self._theme_generic(split, getattr(theme, theme.theme_area.lower()))
 
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(-)

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.
---
 release/scripts/startup/bl_ui/properties_game.py          |  1 +
 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 ++++
 9 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/release/scripts/startup/bl_ui/properties_game.py b/release/scripts/startup/bl_ui/properties_game.py
index 42f651de6df..58b6aa6916c 100644
--- a/release/scripts/startup/bl_ui/properties_game.py
+++ b/release/scripts/startup/bl_ui/properties_game.py
@@ -407,6 +407,7 @@ class RENDER_PT_game_system(RenderButtonsPanel, Panel):
         col = row.column()
         col.prop(gs, "use_frame_rate")
         col.prop(gs, "restrict_animation_updates")
+        col.prop(gs, "use_material_caching")
         col = row.column()
         col.prop(gs, "use_display_lists")
         col.active = gs.raster_storage != 'VERTEX_BUFFER_OBJECT'
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(-)

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(-)

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(-)

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(-)

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(-)

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...

---
 .../modules/bl_i18n_utils/spell_check_utils.py     |  3 ++-
 source/blender/makesrna/intern/rna_scene.c         | 22 ++++++++++++++--------
 2 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/release/scripts/modules/bl_i18n_utils/spell_check_utils.py b/release/scripts/modules/bl_i18n_utils/spell_check_utils.py
index 049ec9ca969..393b2d17697 100644
--- a/release/scripts/modules/bl_i18n_utils/spell_check_utils.py
+++ b/release/scripts/modules/bl_i18n_utils/spell_check_utils.py
@@ -188,6 +188,7 @@ dict_uimsgs = {
     "occluder",
     "passepartout",
     "perspectively",
+    "pixelate",
     "polygonization",
     "selectability",
     "slurph",
@@ -195,7 +196,7 @@ dict_uimsgs = {
     "symmetrize",
     "trackability",
     "transmissivity",
-    "rasterized", "rasterization",
+    "rasterized", "rasterization",, "rasterizer"
     "renderer", "renderable", "renderability",
 
     # Abbreviations
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 f339c63584526a56e5053dc288ccf557a722a202 Mon Sep 17 00:00:00 2001
From: Bastien Montagne 
Date: Mon, 24 Dec 2012 17:55:00 +0000
Subject: We now have some Catalan, but no Amharic nor Estonian yet!

---
 release/scripts/modules/bl_i18n_utils/settings.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/release/scripts/modules/bl_i18n_utils/settings.py b/release/scripts/modules/bl_i18n_utils/settings.py
index fabc2306c41..df87a288cfe 100644
--- a/release/scripts/modules/bl_i18n_utils/settings.py
+++ b/release/scripts/modules/bl_i18n_utils/settings.py
@@ -91,7 +91,7 @@ LANGUAGES_FILE = "languages"
 IMPORT_MIN_LEVEL = -1
 
 # Languages in /branches we do not want to import in /trunk currently...
-IMPORT_LANGUAGES_SKIP = {'bg', 'ca', 'fi', 'el', 'ko', 'ne', 'pl', 'ro'}
+IMPORT_LANGUAGES_SKIP = {'am', 'bg', 'fi', 'el', 'et', 'ko', 'ne', 'pl', 'ro'}
 
 # The comment prefix used in generated messages.txt file.
 COMMENT_PREFIX = "#~ "
-- 
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(-)

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(-)

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(-)

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(-)

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(-)

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.

---
 doc/python_api/rst/bge.types.rst                   |  6 +++
 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 ++
 7 files changed, 110 insertions(+), 23 deletions(-)

diff --git a/doc/python_api/rst/bge.types.rst b/doc/python_api/rst/bge.types.rst
index 470e1c56bac..ae03debb4f8 100644
--- a/doc/python_api/rst/bge.types.rst
+++ b/doc/python_api/rst/bge.types.rst
@@ -3749,6 +3749,12 @@ Types
 
       :type: float
 
+   .. attribute:: maxJumps
+
+      The maximum number of jumps a character can perform before having to touch the ground. By default this is set to 1. 2 allows for a double jump, etc.
+
+      :type: int
+
    .. method:: jump()
 
       The character jumps based on it's jump speed.
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(-)

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(-)

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(-)

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(-)

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(-)

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(-)

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(-)

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(-)

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 7cbfe1839bf1402f430715292418f2cd5180107d Mon Sep 17 00:00:00 2001
From: Brecht Van Lommel 
Date: Wed, 26 Dec 2012 20:59:35 +0000
Subject: Fix part of #33662: cycles crash using displacement on meshes with
 vertices not attached to any face.

---
 intern/cycles/render/mesh_displace.cpp | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/intern/cycles/render/mesh_displace.cpp b/intern/cycles/render/mesh_displace.cpp
index fdfaaf4d7de..04267697b29 100644
--- a/intern/cycles/render/mesh_displace.cpp
+++ b/intern/cycles/render/mesh_displace.cpp
@@ -59,7 +59,7 @@ bool MeshManager::displace(Device *device, Scene *scene, Mesh *mesh, Progress& p
 	vector done(mesh->verts.size(), false);
 	device_vector d_input;
 	uint4 *d_input_data = d_input.resize(mesh->verts.size());
-	size_t d_input_offset = 0;
+	size_t d_input_size = 0;
 
 	for(size_t i = 0; i < mesh->triangles.size(); i++) {
 		Mesh::Triangle t = mesh->triangles[i];
@@ -95,16 +95,16 @@ bool MeshManager::displace(Device *device, Scene *scene, Mesh *mesh, Progress& p
 
 			/* back */
 			uint4 in = make_uint4(object, prim, __float_as_int(u), __float_as_int(v));
-			d_input_data[d_input_offset++] = in;
+			d_input_data[d_input_size++] = in;
 		}
 	}
 
-	if(d_input_offset == 0)
+	if(d_input_size == 0)
 		return false;
 	
 	/* run device task */
 	device_vector d_output;
-	d_output.resize(d_input.size());
+	d_output.resize(d_input_size);
 
 	device->mem_alloc(d_input, MEM_READ_ONLY);
 	device->mem_copy_to(d_input);
@@ -115,7 +115,7 @@ bool MeshManager::displace(Device *device, Scene *scene, Mesh *mesh, Progress& p
 	task.shader_output = d_output.device_pointer;
 	task.shader_eval_type = SHADER_EVAL_DISPLACE;
 	task.shader_x = 0;
-	task.shader_w = d_input.size();
+	task.shader_w = d_output.size();
 
 	device->task_add(task);
 	device->task_wait();
-- 
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(-)

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(-)

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(-)

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(-)

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(-)

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(-)

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(-)

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(-)

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(-)

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(-)

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(-)

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(+)

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(+)

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(-)

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(-)

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(-)

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(-)

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(-)

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(-)

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(-)

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.
---
 release/scripts/modules/bpy_types.py               |   4 +
 release/scripts/startup/bl_ui/__init__.py          |   6 +
 .../startup/bl_ui/properties_data_armature.py      |   4 +-
 .../scripts/startup/bl_ui/properties_data_mesh.py  |  62 ++-
 .../startup/bl_ui/properties_mask_common.py        |  23 +-
 .../scripts/startup/bl_ui/properties_material.py   |  24 +-
 .../scripts/startup/bl_ui/properties_particle.py   |  10 +-
 .../startup/bl_ui/properties_physics_common.py     |   2 +-
 .../bl_ui/properties_physics_dynamicpaint.py       |  27 +-
 release/scripts/startup/bl_ui/properties_render.py |  22 +-
 release/scripts/startup/bl_ui/properties_scene.py  |  19 +-
 .../scripts/startup/bl_ui/properties_texture.py    |  21 +-
 release/scripts/startup/bl_ui/space_clip.py        |  19 +-
 .../scripts/startup/bl_ui/space_view3d_toolbar.py  |   6 +-
 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 +-
 36 files changed, 974 insertions(+), 457 deletions(-)

diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py
index 11e1115fa4c..1c861aa3be2 100644
--- a/release/scripts/modules/bpy_types.py
+++ b/release/scripts/modules/bpy_types.py
@@ -673,6 +673,10 @@ class Panel(StructRNA, _GenericUI, metaclass=RNAMeta):
     __slots__ = ()
 
 
+class UIList(StructRNA, _GenericUI, metaclass=RNAMeta):
+    __slots__ = ()
+
+
 class Header(StructRNA, _GenericUI, metaclass=RNAMeta):
     __slots__ = ()
 
diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py
index e4be84d5396..aa1a8a9a25b 100644
--- a/release/scripts/startup/bl_ui/__init__.py
+++ b/release/scripts/startup/bl_ui/__init__.py
@@ -132,3 +132,9 @@ def register():
 
 def unregister():
     bpy.utils.unregister_module(__name__)
+
+# Define a default UIList, when a list does not need any custom drawing...
+class UI_UL_list(bpy.types.UIList):
+    pass
+
+bpy.utils.register_class(UI_UL_list)
diff --git a/release/scripts/startup/bl_ui/properties_data_armature.py b/release/scripts/startup/bl_ui/properties_data_armature.py
index 845beb0f862..1643210704e 100644
--- a/release/scripts/startup/bl_ui/properties_data_armature.py
+++ b/release/scripts/startup/bl_ui/properties_data_armature.py
@@ -124,7 +124,7 @@ class DATA_PT_bone_groups(ArmatureButtonsPanel, Panel):
         rows = 2
         if group:
             rows = 5
-        row.template_list(pose, "bone_groups", pose.bone_groups, "active_index", rows=rows)
+        row.template_list("UI_UL_list", "", pose, "bone_groups", pose.bone_groups, "active_index", rows=rows)
 
         col = row.column(align=True)
         col.active = (ob.proxy is None)
@@ -184,7 +184,7 @@ class DATA_PT_pose_library(ArmatureButtonsPanel, Panel):
         if poselib:
             # list of poses in pose library
             row = layout.row()
-            row.template_list(poselib, "pose_markers", poselib.pose_markers, "active_index", rows=5)
+            row.template_list("UI_UL_list", "", poselib, "pose_markers", poselib.pose_markers, "active_index", rows=5)
 
             # column of operators for active pose
             # - goes beside list
diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index e33bed7ec6d..7a7c847f040 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -18,7 +18,7 @@
 
 # 
 import bpy
-from bpy.types import Menu, Panel
+from bpy.types import Menu, Panel, UIList
 from rna_prop_ui import PropertyPanel
 
 
@@ -54,6 +54,57 @@ class MESH_MT_shape_key_specials(Menu):
         layout.operator("object.shape_key_add", icon='ZOOMIN', text="New Shape From Mix").from_mix = True
 
 
+class MESH_UL_vgroups(UIList):
+    def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+        if not isinstance(item, bpy.types.VertexGroup):
+            return
+        vgroup = item
+        if self.layout_type in {'DEFAULT', 'COMPACT'}:
+            layout.label(vgroup.name, icon_value=icon)
+            icon = 'LOCKED' if vgroup.lock_weight else 'UNLOCKED'
+            layout.prop(vgroup, "lock_weight", text="", icon=icon, emboss=False)
+        elif self.layout_type in {'GRID'}:
+            layout.alignment = 'CENTER'
+            layout.label("", icon_value=icon)
+
+
+class MESH_UL_shape_keys(UIList):
+    def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+        if not isinstance(item, bpy.types.ShapeKey):
+            return
+        obj = active_data
+        key = data
+        key_block = item
+        if self.layout_type in {'DEFAULT', 'COMPACT'}:
+            split = layout.split(0.66, False)
+            split.label(item.name, icon_value=icon)
+            row = split.row(True)
+            if key_block.mute or (obj.mode == 'EDIT' and not (obj.use_shape_key_edit_mode and obj.type == 'MESH')):
+                row.active = False
+            if not item.relative_key or index > 0:
+                row.prop(key_block, "value", text="", emboss=False)
+            else:
+                row.label("")
+            row.prop(key_block, "mute", text="", emboss=False)
+        elif self.layout_type in {'GRID'}:
+            layout.alignment = 'CENTER'
+            layout.label("", icon_value=icon)
+
+
+class MESH_UL_uvmaps_vcols(UIList):
+    def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+        if not isinstance(item, (bpy.types.MeshTexturePolyLayer, bpy.types.MeshLoopColorLayer)):
+            print(item.__class__)
+            return
+        if self.layout_type in {'DEFAULT', 'COMPACT'}:
+            layout.label(item.name, icon_value=icon)
+            icon = 'RESTRICT_RENDER_OFF' if item.active_render else 'RESTRICT_RENDER_ON'
+            layout.prop(item, "active_render", text="", icon=icon, emboss=False)
+        elif self.layout_type in {'GRID'}:
+            layout.alignment = 'CENTER'
+            layout.label("", icon_value=icon)
+
+
 class MeshButtonsPanel():
     bl_space_type = 'PROPERTIES'
     bl_region_type = 'WINDOW'
@@ -144,7 +195,8 @@ class DATA_PT_vertex_groups(MeshButtonsPanel, Panel):
             rows = 5
 
         row = layout.row()
-        row.template_list(ob, "vertex_groups", ob.vertex_groups, "active_index", rows=rows)
+        row.template_list("MESH_UL_vgroups", "", ob, "vertex_groups", ob.vertex_groups, "active_index", rows=rows)
+
 
         col = row.column(align=True)
         col.operator("object.vertex_group_add", icon='ZOOMIN', text="")
@@ -202,7 +254,7 @@ class DATA_PT_shape_keys(MeshButtonsPanel, Panel):
         rows = 2
         if kb:
             rows = 5
-        row.template_list(key, "key_blocks", ob, "active_shape_key_index", rows=rows)
+        row.template_list("MESH_UL_shape_keys", "", key, "key_blocks", ob, "active_shape_key_index", rows=rows)
 
         col = row.column()
 
@@ -282,7 +334,7 @@ class DATA_PT_uv_texture(MeshButtonsPanel, Panel):
         row = layout.row()
         col = row.column()
 
-        col.template_list(me, "uv_textures", me.uv_textures, "active_index", rows=2)
+        col.template_list("MESH_UL_uvmaps_vcols", "", me, "uv_textures", me.uv_textures, "active_index", rows=2)
 
         col = row.column(align=True)
         col.operator("mesh.uv_texture_add", icon='ZOOMIN', text="")
@@ -305,7 +357,7 @@ class DATA_PT_vertex_colors(MeshButtonsPanel, Panel):
         row = layout.row()
         col = row.column()
 
-        col.template_list(me, "vertex_colors", me.vertex_colors, "active_index", rows=2)
+        col.template_list("MESH_UL_uvmaps_vcols", "", me, "vertex_colors", me.vertex_colors, "active_index", rows=2)
 
         col = row.column(align=True)
         col.operator("mesh.vertex_color_add", icon='ZOOMIN', text="")
diff --git a/release/scripts/startup/bl_ui/properties_mask_common.py b/release/scripts/startup/bl_ui/properties_mask_common.py
index 208b0a63075..ea04b79357e 100644
--- a/release/scripts/startup/bl_ui/properties_mask_common.py
+++ b/release/scripts/startup/bl_ui/properties_mask_common.py
@@ -22,7 +22,25 @@
 # menus are referenced `as is`
 
 import bpy
-from bpy.types import Menu
+from bpy.types import Menu, UIList
+
+
+class MASK_UL_layers(UIList):
+    def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+        if not isinstance(item, bpy.types.MaskLayer):
+            return
+        mask = item
+        if self.layout_type in {'DEFAULT', 'COMPACT'}:
+            split = layout.split()
+            split.label(mask.name, icon_value=icon)
+            row = split.row(align=True)
+            row.prop(mask, "alpha", text="", emboss=False)
+            row.prop(mask, "hide", text="", emboss=False)
+            row.prop(mask, "hide_select", text="", emboss=False)
+            row.prop(mask, "hide_render", text="", emboss=False)
+        elif self.layout_type in {'GRID'}:
+            layout.alignment = 'CENTER'
+            layout.label("", icon_value=icon)
 
 
 class MASK_PT_mask:
@@ -69,8 +87,7 @@ class MASK_PT_layers:
         rows = 5 if active_layer else 2
 
         row = layout.row()
-        row.template_list(mask, "layers",
-                          mask, "active_layer_index", rows=rows)
+        row.template_list("MASK_UL_layers", "", mask, "layers", mask, "active_layer_index", rows=rows)
 
         sub = row.column(align=True)
 
diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py
index 951644db752..df676499cfb 100644
--- a/release/scripts/startup/bl_ui/properties_material.py
+++ b/release/scripts/startup/bl_ui/properties_material.py
@@ -18,7 +18,7 @@
 
 # 
 import bpy
-from bpy.types import Menu, Panel
+from bpy.types import Menu, Panel, UIList
 from rna_prop_ui import PropertyPanel
 
 
@@ -69,6 +69,26 @@ class MATERIAL_MT_specials(Menu):
         layout.operator("material.paste", icon='PASTEDOWN')
 
 
+class MATERIAL_UL_matslots(UIList):
+    def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+        if not isinstance(item, bpy.types.MaterialSlot):
+            return
+        ob = data
+        slot = item
+        ma = slot.material
+        if self.layout_type in {'DEFAULT', 'COMPACT'}:
+            layout.label(ma.name if ma else "", icon_value=icon)
+            if ma and not context.scene.render.use_shading_nodes:
+                manode = ma.active_node_material
+                if manode:
+                    layout.label("Node %s" % manode.name, icon_value=layout.icon(manode))
+                elif ma.use_nodes:
+                    layout.label("Node ")
+        elif self.layout_type in {'GRID'}:
+            layout.alignment = 'CENTER'
+            layout.label("", icon_value=icon)
+
+
 class MaterialButtonsPanel():
     bl_space_type = 'PROPERTIES'
     bl_region_type = 'WINDOW'
@@ -104,7 +124,7 @@ class MATERIAL_PT_context_material(MaterialButtonsPanel, Panel):
         if ob:
             row = layout.row()
 
-            row.template_list(ob, "material_slots", ob, "active_material_index", rows=2)
+            row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=2)
 
             col = row.column(align=True)
             col.operator("object.material_slot_add", icon='ZOOMIN', text="")
diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py
index 2c2ced5db0c..90dcf594137 100644
--- a/release/scripts/startup/bl_ui/properties_particle.py
+++ b/release/scripts/startup/bl_ui/properties_particle.py
@@ -96,7 +96,7 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, Panel):
         if ob:
             row = layout.row()
 
-            row.template_list(ob, "particle_systems", ob.particle_systems, "active_index", rows=2)
+            row.template_list("UI_UL_list", "", ob, "particle_systems", ob.particle_systems, "active_index", rows=2)
 
             col = row.column(align=True)
             col.operator("object.particle_system_add", icon='ZOOMIN', text="")
@@ -636,7 +636,7 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, Panel):
                 layout.label(text="Fluid interaction:")
 
             row = layout.row()
-            row.template_list(psys, "targets", psys, "active_particle_target_index")
+            row.template_list("UI_UL_list", "", psys, "targets", psys, "active_particle_target_index")
 
             col = row.column()
             sub = col.row()
@@ -702,7 +702,7 @@ class PARTICLE_PT_boidbrain(ParticleButtonsPanel, Panel):
 
         # Currently boids can only use the first state so these are commented out for now.
         #row = layout.row()
-        #row.template_list(boids, "states", boids, "active_boid_state_index", compact="True")
+        #row.template_list("UI_UL_list", "", boids, "states", boids, "active_boid_state_index", compact="True")
         #col = row.row()
         #sub = col.row(align=True)
         #sub.operator("boid.state_add", icon='ZOOMIN', text="")
@@ -723,7 +723,7 @@ class PARTICLE_PT_boidbrain(ParticleButtonsPanel, Panel):
             row.label(text="")
 
         row = layout.row()
-        row.template_list(state, "rules", state, "active_boid_rule_index")
+        row.template_list("UI_UL_list", "", state, "rules", state, "active_boid_rule_index")
 
         col = row.column()
         sub = col.row()
@@ -886,7 +886,7 @@ class PARTICLE_PT_render(ParticleButtonsPanel, Panel):
 
             if part.use_group_count and not part.use_whole_group:
                 row = layout.row()
-                row.template_list(part, "dupli_weights", part, "active_dupliweight_index")
+                row.template_list("UI_UL_list", "", part, "dupli_weights", part, "active_dupliweight_index")
 
                 col = row.column()
                 sub = col.row()
diff --git a/release/scripts/startup/bl_ui/properties_physics_common.py b/release/scripts/startup/bl_ui/properties_physics_common.py
index 405e877d1e2..b70ff322765 100644
--- a/release/scripts/startup/bl_ui/properties_physics_common.py
+++ b/release/scripts/startup/bl_ui/properties_physics_common.py
@@ -85,7 +85,7 @@ def point_cache_ui(self, context, cache, enabled, cachetype):
     layout.context_pointer_set("point_cache", cache)
 
     row = layout.row()
-    row.template_list(cache, "point_caches", cache.point_caches, "active_index", rows=2)
+    row.template_list("UI_UL_list", "", cache, "point_caches", cache.point_caches, "active_index", rows=2)
     col = row.column(align=True)
     col.operator("ptcache.add", icon='ZOOMIN', text="")
     col.operator("ptcache.remove", icon='ZOOMOUT', text="")
diff --git a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
index 1df2936b2d4..b102f1b09d0 100644
--- a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
+++ b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
@@ -18,13 +18,35 @@
 
 # 
 import bpy
-from bpy.types import Panel
+from bpy.types import Panel, UIList
 
 from bl_ui.properties_physics_common import (point_cache_ui,
                                              effector_weights_ui,
                                              )
 
 
+class PHYSICS_UL_dynapaint_surfaces(UIList):
+    def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+        if not isinstance(item, bpy.types.DynamicPaintSurface):
+            return
+        surf = item
+        sticon = layout.enum_item_icon(surf, "surface_type", surf.surface_type)
+        if self.layout_type in {'DEFAULT', 'COMPACT'}:
+            row = layout.row(align=True)
+            row.label(text="", icon_value=icon)
+            row.label(text=surf.name, icon_value=sticon)
+            row = layout.row(align=True)
+            if surf.use_color_preview:
+                row.prop(surf, "show_preview", text="", emboss=False,
+                         icon='RESTRICT_VIEW_OFF' if surf.show_preview else 'RESTRICT_VIEW_ON')
+            row.prop(surf, "is_active", text="")
+        elif self.layout_type in {'GRID'}:
+            layout.alignment = 'CENTER'
+            row = layout.row(align=True)
+            row.label(text="", icon_value=icon)
+            row.label(text="", icon_value=sticon)
+
+
 class PhysicButtonsPanel():
     bl_space_type = 'PROPERTIES'
     bl_region_type = 'WINDOW'
@@ -58,7 +80,8 @@ class PHYSICS_PT_dynamic_paint(PhysicButtonsPanel, Panel):
                 surface = canvas.canvas_surfaces.active
 
                 row = layout.row()
-                row.template_list(canvas, "canvas_surfaces", canvas.canvas_surfaces, "active_index", rows=2)
+                row.template_list("PHYSICS_UL_dynapaint_surfaces", "", canvas, "canvas_surfaces",
+                                   canvas.canvas_surfaces, "active_index", rows=2)
 
                 col = row.column(align=True)
                 col.operator("dpaint.surface_slot_add", icon='ZOOMIN', text="")
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index 3fdcf946180..6f0cf6bc691 100644
--- a/release/scripts/startup/bl_ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -19,7 +19,7 @@
 
 # 
 import bpy
-from bpy.types import Menu, Panel
+from bpy.types import Menu, Panel, UIList
 
 
 class RENDER_MT_presets(Menu):
@@ -43,6 +43,24 @@ class RENDER_MT_framerate_presets(Menu):
     draw = Menu.draw_preset
 
 
+class RENDER_UL_renderlayers(UIList):
+    def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+        if not isinstance(item, bpy.types.SceneRenderLayer):
+            return
+        layer = item
+        if self.layout_type in {'DEFAULT', 'COMPACT'}:
+            layout.label(layer.name, icon_value=icon)
+            layout.prop(layer, "use", text="", index=index)
+        elif self.layout_type in {'GRID'}:
+            layout.alignment = 'CENTER'
+            layout.label("", icon_value=icon)
+
+#	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);
+#	}
+
 class RenderButtonsPanel():
     bl_space_type = 'PROPERTIES'
     bl_region_type = 'WINDOW'
@@ -84,7 +102,7 @@ class RENDER_PT_layers(RenderButtonsPanel, Panel):
         rd = scene.render
 
         row = layout.row()
-        row.template_list(rd, "layers", rd.layers, "active_index", rows=2)
+        row.template_list("RENDER_UL_renderlayers", "", rd, "layers", rd.layers, "active_index", rows=2)
 
         col = row.column(align=True)
         col.operator("scene.render_layer_add", icon='ZOOMIN', text="")
diff --git a/release/scripts/startup/bl_ui/properties_scene.py b/release/scripts/startup/bl_ui/properties_scene.py
index 518b253d0b0..100c7d93c77 100644
--- a/release/scripts/startup/bl_ui/properties_scene.py
+++ b/release/scripts/startup/bl_ui/properties_scene.py
@@ -18,10 +18,23 @@
 
 # 
 import bpy
-from bpy.types import Panel
+from bpy.types import Panel, UIList
 from rna_prop_ui import PropertyPanel
 
 
+class SCENE_UL_keying_set_paths(UIList):
+    def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+        if not isinstance(item, bpy.types.KeyingSetPath):
+            return
+        kspath = item
+        icon = layout.enum_item_icon(kspath, "id_type", kspath.id_type)
+        if self.layout_type in {'DEFAULT', 'COMPACT'}:
+            layout.label(kspath.data_path, icon_value=icon)
+        elif self.layout_type in {'GRID'}:
+            layout.alignment = 'CENTER'
+            layout.label("", icon_value=icon)
+
+
 class SceneButtonsPanel():
     bl_space_type = 'PROPERTIES'
     bl_region_type = 'WINDOW'
@@ -107,7 +120,7 @@ class SCENE_PT_keying_sets(SceneButtonsPanel, Panel):
         row = layout.row()
 
         col = row.column()
-        col.template_list(scene, "keying_sets", scene.keying_sets, "active_index", rows=2)
+        col.template_list("UI_UL_list", "", scene, "keying_sets", scene.keying_sets, "active_index", rows=2)
 
         col = row.column(align=True)
         col.operator("anim.keying_set_add", icon='ZOOMIN', text="")
@@ -151,7 +164,7 @@ class SCENE_PT_keying_set_paths(SceneButtonsPanel, Panel):
         row = layout.row()
 
         col = row.column()
-        col.template_list(ks, "paths", ks.paths, "active_index", rows=2)
+        col.template_list("SCENE_UL_keying_set_paths", "", ks, "paths", ks.paths, "active_index", rows=2)
 
         col = row.column(align=True)
         col.operator("anim.keying_set_path_add", icon='ZOOMIN', text="")
diff --git a/release/scripts/startup/bl_ui/properties_texture.py b/release/scripts/startup/bl_ui/properties_texture.py
index e623d034b48..33b8e126398 100644
--- a/release/scripts/startup/bl_ui/properties_texture.py
+++ b/release/scripts/startup/bl_ui/properties_texture.py
@@ -18,7 +18,7 @@
 
 # 
 import bpy
-from bpy.types import Menu, Panel
+from bpy.types import Menu, Panel, UIList
 
 from bpy.types import (Brush,
                        Lamp,
@@ -55,6 +55,23 @@ class TEXTURE_MT_envmap_specials(Menu):
         layout.operator("texture.envmap_clear", icon='FILE_REFRESH')
         layout.operator("texture.envmap_clear_all", icon='FILE_REFRESH')
 
+
+class TEXTURE_UL_texslots(UIList):
+    def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+        if not (item is None or isinstance(item, bpy.types.MaterialTextureSlot)):
+            return
+        ma = data
+        slot = item
+        tex = slot.texture if slot else None
+        if self.layout_type in {'DEFAULT', 'COMPACT'}:
+            layout.label(tex.name if tex else "", icon_value=icon)
+            if tex:
+                layout.prop(ma, "use_textures", text="", index=index)
+        elif self.layout_type in {'GRID'}:
+            layout.alignment = 'CENTER'
+            layout.label("", icon_value=icon)
+
+
 from bl_ui.properties_material import active_node_mat
 
 
@@ -142,7 +159,7 @@ class TEXTURE_PT_context_texture(TextureButtonsPanel, Panel):
         if tex_collection:
             row = layout.row()
 
-            row.template_list(idblock, "texture_slots", idblock, "active_texture_index", rows=2)
+            row.template_list("TEXTURE_UL_texslots", "", idblock, "texture_slots", idblock, "active_texture_index", rows=2)
 
             col = row.column(align=True)
             col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP'
diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py
index cb88226b55a..cf5b94277e7 100644
--- a/release/scripts/startup/bl_ui/space_clip.py
+++ b/release/scripts/startup/bl_ui/space_clip.py
@@ -19,7 +19,19 @@
 # 
 
 import bpy
-from bpy.types import Panel, Header, Menu
+from bpy.types import Panel, Header, Menu, UIList
+
+
+class CLIP_UL_tracking_objects(UIList):
+    def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+        if not (item is None or isinstance(item, bpy.types.MovieTrackingObject)):
+            return
+        tobj = item
+        if self.layout_type in {'DEFAULT', 'COMPACT'}:
+            layout.label(tobj.name, icon='CAMERA_DATA' if tobj.is_camera else 'OBJECT_DATA')
+        elif self.layout_type in {'GRID'}:
+            layout.alignment = 'CENTER'
+            layout.label("", icon='CAMERA_DATA' if tobj.is_camera else 'OBJECT_DATA')
 
 
 class CLIP_HT_header(Header):
@@ -471,8 +483,7 @@ class CLIP_PT_objects(CLIP_PT_clip_view_panel, Panel):
         tracking = sc.clip.tracking
 
         row = layout.row()
-        row.template_list(tracking, "objects",
-                          tracking, "active_object_index", rows=3)
+        row.template_list("CLIP_UL_tracking_objects", "", tracking, "objects", tracking, "active_object_index", rows=3)
 
         sub = row.column(align=True)
 
@@ -728,7 +739,7 @@ class CLIP_PT_stabilization(CLIP_PT_reconstruction_panel, Panel):
         layout.active = stab.use_2d_stabilization
 
         row = layout.row()
-        row.template_list(stab, "tracks", stab, "active_track_index", rows=3)
+        row.template_list("UI_UL_list", "", stab, "tracks", stab, "active_track_index", rows=3)
 
         sub = row.column(align=True)
 
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 09b32cd0c56..fb5e4a56aa1 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -1167,7 +1167,8 @@ class VIEW3D_PT_tools_particlemode(View3DPanel, Panel):
         if pe.type == 'PARTICLES':
             if ob.particle_systems:
                 if len(ob.particle_systems) > 1:
-                    layout.template_list(ob, "particle_systems", ob.particle_systems, "active_index", rows=2, maxrows=3)
+                    layout.template_list("UI_UL_list", "", ob, "particle_systems",
+                                         ob.particle_systems, "active_index", rows=2, maxrows=3)
 
                 ptcache = ob.particle_systems.active.point_cache
         else:
@@ -1176,7 +1177,8 @@ class VIEW3D_PT_tools_particlemode(View3DPanel, Panel):
                     ptcache = md.point_cache
 
         if ptcache and len(ptcache.point_caches) > 1:
-            layout.template_list(ptcache, "point_caches", ptcache.point_caches, "active_index", rows=2, maxrows=3)
+            layout.template_list("UI_UL_list", "", ptcache, "point_caches", ptcache.point_caches, "active_index",
+                                 rows=2, maxrows=3)
 
         if not pe.is_editable:
             layout.label(text="Point cache must be baked")
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(-)

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(-)

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(+)

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(-)

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(+)

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(-)

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 d984c46701280ab50a3ce2987d184ce780e113c6 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Fri, 28 Dec 2012 10:45:59 +0000
Subject: remove type checks on drawing uiList's,

if the list is given the wrong item then the script needs to be fixed, better not fail silently.

left in checks as commented out asserts.
---
 release/scripts/startup/bl_ui/properties_data_mesh.py          | 10 +++-------
 release/scripts/startup/bl_ui/properties_mask_common.py        |  3 +--
 release/scripts/startup/bl_ui/properties_material.py           |  3 +--
 .../scripts/startup/bl_ui/properties_physics_dynamicpaint.py   |  3 +--
 release/scripts/startup/bl_ui/properties_render.py             |  3 +--
 release/scripts/startup/bl_ui/properties_scene.py              |  3 +--
 release/scripts/startup/bl_ui/properties_texture.py            |  3 +--
 release/scripts/startup/bl_ui/space_clip.py                    |  3 +--
 8 files changed, 10 insertions(+), 21 deletions(-)

diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index 7a7c847f040..538063cb038 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -56,8 +56,7 @@ class MESH_MT_shape_key_specials(Menu):
 
 class MESH_UL_vgroups(UIList):
     def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
-        if not isinstance(item, bpy.types.VertexGroup):
-            return
+        # assert(isinstance(item, bpy.types.VertexGroup)
         vgroup = item
         if self.layout_type in {'DEFAULT', 'COMPACT'}:
             layout.label(vgroup.name, icon_value=icon)
@@ -70,8 +69,7 @@ class MESH_UL_vgroups(UIList):
 
 class MESH_UL_shape_keys(UIList):
     def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
-        if not isinstance(item, bpy.types.ShapeKey):
-            return
+        # assert(isinstance(item, bpy.types.ShapeKey)
         obj = active_data
         key = data
         key_block = item
@@ -93,9 +91,7 @@ class MESH_UL_shape_keys(UIList):
 
 class MESH_UL_uvmaps_vcols(UIList):
     def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
-        if not isinstance(item, (bpy.types.MeshTexturePolyLayer, bpy.types.MeshLoopColorLayer)):
-            print(item.__class__)
-            return
+        # assert(isinstance(item, (bpy.types.MeshTexturePolyLayer, bpy.types.MeshLoopColorLayer))
         if self.layout_type in {'DEFAULT', 'COMPACT'}:
             layout.label(item.name, icon_value=icon)
             icon = 'RESTRICT_RENDER_OFF' if item.active_render else 'RESTRICT_RENDER_ON'
diff --git a/release/scripts/startup/bl_ui/properties_mask_common.py b/release/scripts/startup/bl_ui/properties_mask_common.py
index ea04b79357e..9861db39f30 100644
--- a/release/scripts/startup/bl_ui/properties_mask_common.py
+++ b/release/scripts/startup/bl_ui/properties_mask_common.py
@@ -27,8 +27,7 @@ from bpy.types import Menu, UIList
 
 class MASK_UL_layers(UIList):
     def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
-        if not isinstance(item, bpy.types.MaskLayer):
-            return
+        # assert(isinstance(item, bpy.types.MaskLayer)
         mask = item
         if self.layout_type in {'DEFAULT', 'COMPACT'}:
             split = layout.split()
diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py
index df676499cfb..7e18cf89080 100644
--- a/release/scripts/startup/bl_ui/properties_material.py
+++ b/release/scripts/startup/bl_ui/properties_material.py
@@ -71,8 +71,7 @@ class MATERIAL_MT_specials(Menu):
 
 class MATERIAL_UL_matslots(UIList):
     def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
-        if not isinstance(item, bpy.types.MaterialSlot):
-            return
+        # assert(isinstance(item, bpy.types.MaterialSlot)
         ob = data
         slot = item
         ma = slot.material
diff --git a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
index b102f1b09d0..9393852b8a5 100644
--- a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
+++ b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
@@ -27,8 +27,7 @@ from bl_ui.properties_physics_common import (point_cache_ui,
 
 class PHYSICS_UL_dynapaint_surfaces(UIList):
     def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
-        if not isinstance(item, bpy.types.DynamicPaintSurface):
-            return
+        # assert(isinstance(item, bpy.types.DynamicPaintSurface)
         surf = item
         sticon = layout.enum_item_icon(surf, "surface_type", surf.surface_type)
         if self.layout_type in {'DEFAULT', 'COMPACT'}:
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index 6f0cf6bc691..8dfa954dade 100644
--- a/release/scripts/startup/bl_ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -45,8 +45,7 @@ class RENDER_MT_framerate_presets(Menu):
 
 class RENDER_UL_renderlayers(UIList):
     def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
-        if not isinstance(item, bpy.types.SceneRenderLayer):
-            return
+        # assert(isinstance(item, bpy.types.SceneRenderLayer)
         layer = item
         if self.layout_type in {'DEFAULT', 'COMPACT'}:
             layout.label(layer.name, icon_value=icon)
diff --git a/release/scripts/startup/bl_ui/properties_scene.py b/release/scripts/startup/bl_ui/properties_scene.py
index 100c7d93c77..3230fb7392b 100644
--- a/release/scripts/startup/bl_ui/properties_scene.py
+++ b/release/scripts/startup/bl_ui/properties_scene.py
@@ -24,8 +24,7 @@ from rna_prop_ui import PropertyPanel
 
 class SCENE_UL_keying_set_paths(UIList):
     def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
-        if not isinstance(item, bpy.types.KeyingSetPath):
-            return
+        # assert(isinstance(item, bpy.types.KeyingSetPath)
         kspath = item
         icon = layout.enum_item_icon(kspath, "id_type", kspath.id_type)
         if self.layout_type in {'DEFAULT', 'COMPACT'}:
diff --git a/release/scripts/startup/bl_ui/properties_texture.py b/release/scripts/startup/bl_ui/properties_texture.py
index 33b8e126398..cb7cc1d42d2 100644
--- a/release/scripts/startup/bl_ui/properties_texture.py
+++ b/release/scripts/startup/bl_ui/properties_texture.py
@@ -58,8 +58,7 @@ class TEXTURE_MT_envmap_specials(Menu):
 
 class TEXTURE_UL_texslots(UIList):
     def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
-        if not (item is None or isinstance(item, bpy.types.MaterialTextureSlot)):
-            return
+        # assert(isinstance(item, bpy.types.MaterialTextureSlot)
         ma = data
         slot = item
         tex = slot.texture if slot else None
diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py
index cf5b94277e7..5fc57133767 100644
--- a/release/scripts/startup/bl_ui/space_clip.py
+++ b/release/scripts/startup/bl_ui/space_clip.py
@@ -24,8 +24,7 @@ from bpy.types import Panel, Header, Menu, UIList
 
 class CLIP_UL_tracking_objects(UIList):
     def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
-        if not (item is None or isinstance(item, bpy.types.MovieTrackingObject)):
-            return
+        # assert(isinstance(item, bpy.types.MovieTrackingObject)
         tobj = item
         if self.layout_type in {'DEFAULT', 'COMPACT'}:
             layout.label(tobj.name, icon='CAMERA_DATA' if tobj.is_camera else 'OBJECT_DATA')
-- 
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(-)

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(-)

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(-)

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 c04631f0bb716583e4678add34d09ac3494515ea Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Fri, 28 Dec 2012 12:12:04 +0000
Subject: patch [#33669] SConstruct: Tell how to pass BF_PYTHON_INC to SCons is
 it is not found from anatoly techtonik (techtonik)

---
 SConstruct | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/SConstruct b/SConstruct
index 4630b7b8c87..f73aabc6767 100644
--- a/SConstruct
+++ b/SConstruct
@@ -442,11 +442,12 @@ if env['WITH_BF_PYTHON']:
             found_pyconfig_h = True
 
     if not (found_python_h and found_pyconfig_h):
-        print("\nMissing: Python.h and/or pyconfig.h in\"" + env.subst('${BF_PYTHON_INC}') + "\",\n"
-              "  Set 'BF_PYTHON_INC' to point "
-              "to valid python include path(s).\n Containing "
-              "Python.h and pyconfig.h for python version \"" + env.subst('${BF_PYTHON_VERSION}') + "\"")
+        print("""\nMissing: Python.h and/or pyconfig.h in "%s"
+         Set 'BF_PYTHON_INC' to point to valid include path(s),
+         containing Python.h and pyconfig.h for Python version "%s".
 
+         Example: python scons/scons.py BF_PYTHON_INC=../Python/include
+              """ % (env.subst('${BF_PYTHON_INC}'), env.subst('${BF_PYTHON_VERSION}')))
         Exit()
 
 
-- 
cgit v1.2.3


From 9f9e35c82a7c96e6f3a20b379f48109f4f8f03de Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Fri, 28 Dec 2012 12:48:45 +0000
Subject: Bugfix #33681

Blender didn't detect properly whether event came from a mouse-wheel or
from a trackpad in OS X.

Now you can both, and both are handled independently.

Removed back hack from 2 years ago - which disabled mouse wheel for laptops.
---
 intern/ghost/intern/GHOST_SystemCocoa.h  |  3 ---
 intern/ghost/intern/GHOST_SystemCocoa.mm | 25 ++++---------------------
 2 files changed, 4 insertions(+), 24 deletions(-)

diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h
index a1b372dac9a..8598bd0862f 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.h
+++ b/intern/ghost/intern/GHOST_SystemCocoa.h
@@ -293,9 +293,6 @@ protected:
 	 */
 	GHOST_TInt32 m_cursorDelta_x, m_cursorDelta_y;
 	
-	/** Multitouch trackpad availability */
-	bool m_hasMultiTouchTrackpad;
-	
 };
 
 #endif // __GHOST_SYSTEMCOCOA_H__
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index 39fd038d568..742bf944946 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -548,7 +548,6 @@ GHOST_SystemCocoa::GHOST_SystemCocoa()
 	int mib[2];
 	struct timeval boottime;
 	size_t len;
-	char *rstring = NULL;
 	
 	m_modifierMask =0;
 	m_cursorDelta_x=0;
@@ -566,25 +565,7 @@ GHOST_SystemCocoa::GHOST_SystemCocoa()
 	
 	sysctl(mib, 2, &boottime, &len, NULL, 0);
 	m_start_time = ((boottime.tv_sec*1000)+(boottime.tv_usec/1000));
-	
-	//Detect multitouch trackpad
-	mib[0] = CTL_HW;
-	mib[1] = HW_MODEL;
-	sysctl( mib, 2, NULL, &len, NULL, 0 );
-	rstring = (char*)malloc( len );
-	sysctl( mib, 2, rstring, &len, NULL, 0 );
-	
-	//Hack on MacBook revision, as multitouch avail. function missing
-	//MacbookAir or MacBook version >= 5 (retina is MacBookPro10,1)
-	if (strstr(rstring,"MacBookAir") ||
-		(strstr(rstring,"MacBook") && (rstring[strlen(rstring)-3]>='5') && (rstring[strlen(rstring)-3]<='9')) ||
-		(strstr(rstring,"MacBook") && (rstring[strlen(rstring)-4]>='1') && (rstring[strlen(rstring)-4]<='9')))
-		m_hasMultiTouchTrackpad = true;
-	else m_hasMultiTouchTrackpad = false;
-	
-	free( rstring );
-	rstring = NULL;
-	
+		
 	m_ignoreWindowSizedMessages = false;
 }
 
@@ -1579,7 +1560,9 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
 			
 		case NSScrollWheel:
 			{
-				if (!m_hasMultiTouchTrackpad) {
+				
+				/* proper detection of trackpad or mouse scrollwheel */
+				if ([event momentumPhase] == NSEventPhaseNone && [event phase] == NSEventPhaseNone) {
 					GHOST_TInt32 delta;
 					
 					double deltaF = [event deltaY];
-- 
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(-)

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 c587c985e81c8fdd4ab47470d0f2d2d4a0773647 Mon Sep 17 00:00:00 2001
From: Bastien Montagne 
Date: Fri, 28 Dec 2012 13:34:19 +0000
Subject: Fix [#33424] Inadequate bake action.

bake_action tries to make kind of a 'visual keying'... On one side, this is rather stupid when you keep constraints (in this case, keying actual loc/rot/scale transforms, i.e. matrix_basis, is enough, doing more would lead to unexpected behavior with some constraints). On the other one, making a good visual keying of bones is *really* tricky, so now using the new object's convert_space() func to compute that (when the user chooses to remove the constraints).

Incidentally, this greatly simplifies the code of bake_action!
---
 release/scripts/modules/bpy_extras/anim_utils.py | 189 ++++++++---------------
 release/scripts/startup/bl_operators/anim.py     |  19 ++-
 2 files changed, 75 insertions(+), 133 deletions(-)

diff --git a/release/scripts/modules/bpy_extras/anim_utils.py b/release/scripts/modules/bpy_extras/anim_utils.py
index b8d08628de4..7a5d1692971 100644
--- a/release/scripts/modules/bpy_extras/anim_utils.py
+++ b/release/scripts/modules/bpy_extras/anim_utils.py
@@ -16,7 +16,7 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
-# 
+# 
 
 __all__ = (
     "bake_action",
@@ -52,7 +52,7 @@ def bake_action(frame_start,
     :type do_pose: bool
     :arg do_object: Bake objects.
     :type do_object: bool
-    :arg do_constraint_clear: Remove constraints.
+    :arg do_constraint_clear: Remove constraints (and do 'visual keying').
     :type do_constraint_clear: bool
     :arg do_clean: Remove redundant keyframes after baking.
     :type do_clean: bool
@@ -65,61 +65,20 @@ def bake_action(frame_start,
     """
 
     # -------------------------------------------------------------------------
-    # Helper Functions
+    # Helper Functions and vars
 
-    def pose_frame_info(obj):
-        from mathutils import Matrix
+    def pose_frame_info(obj, do_visual_keying):
+        matrix = {}
+        for name, pbone in obj.pose.bones.items():
+            if do_visual_keying:
+                # Get the final transform of the bone in its own local space...
+                matrix[name] = obj.convert_space(pbone, pbone.matrix, 'POSE', 'LOCAL')
+            else:
+                matrix[name] = pbone.matrix_basis.copy()
+        return matrix
 
-        info = {}
-
-        pose = obj.pose
-
-        pose_items = pose.bones.items()
-
-        for name, pbone in pose_items:
-            binfo = {}
-            bone = pbone.bone
-
-            binfo["parent"] = getattr(bone.parent, "name", None)
-            binfo["bone"] = bone
-            binfo["pbone"] = pbone
-            binfo["matrix_local"] = bone.matrix_local.copy()
-            try:
-                binfo["matrix_local_inv"] = binfo["matrix_local"].inverted()
-            except:
-                binfo["matrix_local_inv"] = Matrix()
-
-            binfo["matrix"] = bone.matrix.copy()
-            binfo["matrix_pose"] = pbone.matrix.copy()
-            try:
-                binfo["matrix_pose_inv"] = binfo["matrix_pose"].inverted()
-            except:
-                binfo["matrix_pose_inv"] = Matrix()
-
-            info[name] = binfo
-
-        for name, pbone in pose_items:
-            binfo = info[name]
-            binfo_parent = binfo.get("parent", None)
-            if binfo_parent:
-                binfo_parent = info[binfo_parent]
-
-            matrix = binfo["matrix_pose"]
-            rest_matrix = binfo["matrix_local"]
-
-            if binfo_parent:
-                matrix = binfo_parent["matrix_pose_inv"] * matrix
-                rest_matrix = binfo_parent["matrix_local_inv"] * rest_matrix
-
-            binfo["matrix_key"] = rest_matrix.inverted() * matrix
-
-        return info
-
-    def obj_frame_info(obj):
-        info = {}
-        # parent = obj.parent
-        info["matrix_key"] = obj.matrix_local.copy()
-        return info
+    def obj_frame_info(obj, do_visual_keying):
+        return obj.matrix_local.copy() if do_visual_keying else obj.matrix_basis.copy()
 
     # -------------------------------------------------------------------------
     # Setup the Context
@@ -127,33 +86,30 @@ def bake_action(frame_start,
     # TODO, pass data rather then grabbing from the context!
     scene = bpy.context.scene
     obj = bpy.context.object
-    pose = obj.pose
     frame_back = scene.frame_current
 
-    if pose is None:
+    if obj.pose is None:
         do_pose = False
 
-    if do_pose is None and do_object is None:
+    if not (do_pose or do_object):
         return None
 
     pose_info = []
     obj_info = []
 
+    options = {'INSERTKEY_NEEDED'}
+
     frame_range = range(frame_start, frame_end + 1, frame_step)
 
     # -------------------------------------------------------------------------
     # Collect transformations
 
-    # could speed this up by applying steps here too...
     for f in frame_range:
         scene.frame_set(f)
-
         if do_pose:
-            pose_info.append(pose_frame_info(obj))
+            pose_info.append(pose_frame_info(obj, do_constraint_clear))
         if do_object:
-            obj_info.append(obj_frame_info(obj))
-
-        f += 1
+            obj_info.append(obj_frame_info(obj, do_constraint_clear))
 
     # -------------------------------------------------------------------------
     # Create action
@@ -164,57 +120,44 @@ def bake_action(frame_start,
         action = bpy.data.actions.new("Action")
     atd.action = action
 
-    if do_pose:
-        pose_items = pose.bones.items()
-    else:
-        pose_items = []  # skip
-
     # -------------------------------------------------------------------------
     # Apply transformations to action
 
     # pose
-    for name, pbone in (pose_items if do_pose else ()):
-        if only_selected and not pbone.bone.select:
-            continue
-
-        if do_constraint_clear:
-            while pbone.constraints:
-                pbone.constraints.remove(pbone.constraints[0])
-
-        # create compatible eulers
-        euler_prev = None
-
-        for f in frame_range:
-            f_step = (f - frame_start) // frame_step
-            matrix = pose_info[f_step][name]["matrix_key"]
-
-            # pbone.location = matrix.to_translation()
-            # pbone.rotation_quaternion = matrix.to_quaternion()
-            pbone.matrix_basis = matrix
-
-            pbone.keyframe_insert("location", -1, f, name)
-
-            rotation_mode = pbone.rotation_mode
-
-            if rotation_mode == 'QUATERNION':
-                pbone.keyframe_insert("rotation_quaternion", -1, f, name)
-            elif rotation_mode == 'AXIS_ANGLE':
-                pbone.keyframe_insert("rotation_axis_angle", -1, f, name)
-            else:  # euler, XYZ, ZXY etc
-
-                if euler_prev is not None:
-                    euler = pbone.rotation_euler.copy()
-                    euler.make_compatible(euler_prev)
-                    pbone.rotation_euler = euler
-                    euler_prev = euler
-                    del euler
-
-                pbone.keyframe_insert("rotation_euler", -1, f, name)
-
-                if euler_prev is None:
-                    euler_prev = pbone.rotation_euler.copy()
-
-            pbone.keyframe_insert("scale", -1, f, name)
+    if do_pose:
+        for name, pbone in obj.pose.bones.items():
+            if only_selected and not pbone.bone.select:
+                continue
+
+            if do_constraint_clear:
+                while pbone.constraints:
+                    pbone.constraints.remove(pbone.constraints[0])
+
+            # create compatible eulers
+            euler_prev = None
+
+            for (f, matrix) in zip(frame_range, pose_info):
+                pbone.matrix_basis = matrix[name].copy()
+
+                pbone.keyframe_insert("location", -1, f, name, options)
+
+                rotation_mode = pbone.rotation_mode
+                if rotation_mode == 'QUATERNION':
+                    pbone.keyframe_insert("rotation_quaternion", -1, f, name, options)
+                elif rotation_mode == 'AXIS_ANGLE':
+                    pbone.keyframe_insert("rotation_axis_angle", -1, f, name, options)
+                else:  # euler, XYZ, ZXY etc
+                    if euler_prev is not None:
+                        euler = pbone.rotation_euler.copy()
+                        euler.make_compatible(euler_prev)
+                        pbone.rotation_euler = euler
+                        euler_prev = euler
+                        del euler
+                    else:
+                        euler_prev = pbone.rotation_euler.copy()
+                    pbone.keyframe_insert("rotation_euler", -1, f, name, options)
+
+                pbone.keyframe_insert("scale", -1, f, name, options)
 
     # object. TODO. multiple objects
     if do_object:
@@ -225,18 +168,16 @@ def bake_action(frame_start,
         # create compatible eulers
         euler_prev = None
 
-        for f in frame_range:
-            matrix = obj_info[(f - frame_start) // frame_step]["matrix_key"]
-            obj.matrix_local = matrix
+        for (f, matrix) in zip(frame_range, obj_info):
+            obj.matrix_basis = matrix[name]
 
-            obj.keyframe_insert("location", -1, f)
+            obj.keyframe_insert("location", -1, f, options)
 
             rotation_mode = obj.rotation_mode
-
             if rotation_mode == 'QUATERNION':
-                obj.keyframe_insert("rotation_quaternion", -1, f)
+                obj.keyframe_insert("rotation_quaternion", -1, f, options)
             elif rotation_mode == 'AXIS_ANGLE':
-                obj.keyframe_insert("rotation_axis_angle", -1, f)
+                obj.keyframe_insert("rotation_axis_angle", -1, f, options)
             else:  # euler, XYZ, ZXY etc
                 if euler_prev is not None:
                     euler = obj.rotation_euler.copy()
@@ -244,15 +185,11 @@ def bake_action(frame_start,
                     obj.rotation_euler = euler
                     euler_prev = euler
                     del euler
-
-                obj.keyframe_insert("rotation_euler", -1, f)
-
-                if euler_prev is None:
+                else:
                     euler_prev = obj.rotation_euler.copy()
+                obj.keyframe_insert("rotation_euler", -1, f, options)
 
-            obj.keyframe_insert("scale", -1, f)
-
-    scene.frame_set(frame_back)
+            obj.keyframe_insert("scale", -1, f, options)
 
     # -------------------------------------------------------------------------
     # Clean
@@ -271,4 +208,6 @@ def bake_action(frame_start,
                 else:
                     i += 1
 
+    scene.frame_set(frame_back)
+
     return action
diff --git a/release/scripts/startup/bl_operators/anim.py b/release/scripts/startup/bl_operators/anim.py
index 902c7007fb9..e34e9a981a6 100644
--- a/release/scripts/startup/bl_operators/anim.py
+++ b/release/scripts/startup/bl_operators/anim.py
@@ -187,17 +187,20 @@ class BakeAction(Operator):
             )
     only_selected = BoolProperty(
             name="Only Selected",
+            description="Only key selected object/bones",
             default=True,
             )
     clear_constraints = BoolProperty(
             name="Clear Constraints",
+            description="Remove all constraints from keyed object/bones, and do 'visual' keying",
             default=False,
             )
     bake_types = EnumProperty(
             name="Bake Data",
+            description="Which data's transformations to bake",
             options={'ENUM_FLAG'},
-            items=(('POSE', "Pose", ""),
-                   ('OBJECT', "Object", ""),
+            items=(('POSE', "Pose", "Bake bones transformations"),
+                   ('OBJECT', "Object", "Bake object transformations"),
                    ),
             default={'POSE'},
             )
@@ -208,12 +211,12 @@ class BakeAction(Operator):
 
         action = anim_utils.bake_action(self.frame_start,
                                         self.frame_end,
-                                        self.step,
-                                        self.only_selected,
-                                        'POSE' in self.bake_types,
-                                        'OBJECT' in self.bake_types,
-                                        self.clear_constraints,
-                                        True,
+                                        frame_step=self.step,
+                                        only_selected=self.only_selected,
+                                        do_pose='POSE' in self.bake_types,
+                                        do_object='OBJECT' in self.bake_types,
+                                        do_constraint_clear=self.clear_constraints,
+                                        do_clean=True,
                                         )
 
         if action is None:
-- 
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(-)

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(-)

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(-)

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.
---
 intern/cycles/blender/CMakeLists.txt               |   1 +
 intern/cycles/blender/addon/properties.py          | 188 +++++
 intern/cycles/blender/addon/ui.py                  |  88 ++
 intern/cycles/blender/blender_curves.cpp           | 898 +++++++++++++++++++++
 intern/cycles/blender/blender_mesh.cpp             |  25 +-
 intern/cycles/blender/blender_object.cpp           |  26 +-
 intern/cycles/blender/blender_session.cpp          |   4 +-
 intern/cycles/blender/blender_shader.cpp           |   4 +
 intern/cycles/blender/blender_sync.cpp             |   5 +-
 intern/cycles/blender/blender_sync.h               |   9 +-
 intern/cycles/bvh/bvh.cpp                          | 132 ++-
 intern/cycles/bvh/bvh.h                            |   9 +-
 intern/cycles/bvh/bvh_build.cpp                    |  37 +-
 intern/cycles/bvh/bvh_build.h                      |   2 +
 intern/cycles/bvh/bvh_params.h                     |   5 +-
 intern/cycles/bvh/bvh_sort.cpp                     |   2 +
 intern/cycles/bvh/bvh_split.cpp                    |  55 +-
 intern/cycles/kernel/kernel_bvh.h                  | 267 +++++-
 intern/cycles/kernel/kernel_emission.h             |  12 +-
 intern/cycles/kernel/kernel_light.h                |  64 +-
 intern/cycles/kernel/kernel_object.h               |  50 ++
 intern/cycles/kernel/kernel_shader.h               | 115 ++-
 intern/cycles/kernel/kernel_textures.h             |   5 +
 intern/cycles/kernel/kernel_triangle.h             | 176 ++--
 intern/cycles/kernel/kernel_types.h                |  34 +-
 intern/cycles/kernel/svm/svm.h                     |   6 +
 intern/cycles/kernel/svm/svm_attribute.h           | 144 ++--
 intern/cycles/kernel/svm/svm_geometry.h            |  38 +-
 intern/cycles/kernel/svm/svm_tex_coord.h           |  14 +-
 intern/cycles/kernel/svm/svm_types.h               |  10 +-
 intern/cycles/render/CMakeLists.txt                |   2 +
 intern/cycles/render/curves.cpp                    | 160 ++++
 intern/cycles/render/curves.h                      | 134 +++
 intern/cycles/render/light.cpp                     |  37 +-
 intern/cycles/render/mesh.cpp                      | 151 +++-
 intern/cycles/render/mesh.h                        |  34 +
 intern/cycles/render/nodes.cpp                     |  46 ++
 intern/cycles/render/nodes.h                       |   5 +
 intern/cycles/render/object.cpp                    |  31 +
 intern/cycles/render/object.h                      |   1 +
 intern/cycles/render/scene.cpp                     |  12 +-
 intern/cycles/render/scene.h                       |   6 +
 intern/cycles/util/util_boundbox.h                 |   7 +
 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 ++
 50 files changed, 3131 insertions(+), 250 deletions(-)
 create mode 100644 intern/cycles/blender/blender_curves.cpp
 create mode 100644 intern/cycles/render/curves.cpp
 create mode 100644 intern/cycles/render/curves.h
 create mode 100644 source/blender/nodes/shader/nodes/node_shader_hair_info.c

diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt
index 88363758364..710e8ba6a90 100644
--- a/intern/cycles/blender/CMakeLists.txt
+++ b/intern/cycles/blender/CMakeLists.txt
@@ -24,6 +24,7 @@ set(SRC
 	blender_mesh.cpp
 	blender_object.cpp
 	blender_particles.cpp
+	blender_curves.cpp
 	blender_python.cpp
 	blender_session.cpp
 	blender_shader.cpp
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index 26fc7a81936..35ea8501eb7 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -63,6 +63,38 @@ enum_panorama_types = (
     ('FISHEYE_EQUISOLID', "Fisheye Equisolid",
                           "Similar to most fisheye modern lens, takes sensor dimensions into consideration"),
     )
+    
+enum_curve_presets = (
+    ('CUSTOM', "Custom", "Set general parameters"),
+    ('TANGENT_SHADING', "Tangent Normal", "Use planar geometry and tangent normals"),
+    ('TRUE_NORMAL', "True Normal", "Use true normals (good for thin strands)"),
+    ('ACCURATE_PRESET', "Accurate", "Use best settings (suitable for glass materials)"),
+    )
+    
+enum_curve_primitives = (
+    ('TRIANGLES', "Triangles", "create triangle geometry around strands"),
+    ('LINE_SEGMENTS', "Line Segments", "use line segment primitives"),
+    ('CURVE_SEGMENTS', "?Curve Segments?", "use curve segment primitives (not implemented)"),
+    )
+        
+enum_triangle_curves = (
+	('CAMERA', "Planes", "create individual triangles forming planes that face camera"),
+    ('RIBBONS', "Ribbons", "create individual triangles forming ribbon"),
+    ('TESSELATED', "Tesselated", "create mesh surrounding each strand"),
+    )
+    
+enum_line_curves = (
+    ('ACCURATE', "Accurate", "always take into consideration strand width for intersections"),
+    ('QT_CORRECTED', "corrected", "ignores width for initial intersection and corrects later"),
+    ('ENDCORRECTED', "correct found", "ignores width for all intersections and only corrects closest"),
+    ('QT_UNCORRECTED', "uncorrected", "calculates intersection without considering width"),
+    )
+    
+enum_curves_interpolation = (
+    ('LINEAR', "Linear interpolation", "uses Linear interpolation between segments"),
+    ('CARDINAL', "Cardinal interpolation", "uses CARDINAL interpolation between segments"),
+    ('BSPLINE', "b-spline interpolation", "uses b-spline interpolation between segments"),
+    )
 
 class CyclesRenderSettings(bpy.types.PropertyGroup):
     @classmethod
@@ -573,6 +605,158 @@ class CyclesMeshSettings(bpy.types.PropertyGroup):
         del bpy.types.Curve.cycles
         del bpy.types.MetaBall.cycles
 
+class CyclesCurveRenderSettings(bpy.types.PropertyGroup):
+    @classmethod
+    def register(cls):
+        bpy.types.Scene.cycles_curves = PointerProperty(
+                name="Cycles Hair Rendering Settings",
+                description="Cycles hair rendering settings",
+                type=cls,
+                )
+        cls.preset = EnumProperty(
+                name="Mode",
+                description="Hair rendering mode",
+                items=enum_curve_presets,
+                default='TRUE_NORMAL',
+                )
+        cls.primitive = EnumProperty(
+                name="Primitive",
+                description="Type of primitive used for hair rendering",
+                items=enum_curve_primitives,
+                default='LINE_SEGMENTS',
+                )
+        cls.triangle_method = EnumProperty(
+                name="Mesh Geometry",
+                description="Method for creating triangle geometry",
+                items=enum_triangle_curves,
+                default='CAMERA',
+                )
+        cls.line_method = EnumProperty(
+                name="Intersection Method",
+                description="Method for line segment intersection",
+                items=enum_line_curves,
+                default='ACCURATE',
+                )
+        cls.interpolation = EnumProperty(
+                name="Interpolation",
+                description="Interpolation method",
+                items=enum_curves_interpolation,
+                default='BSPLINE',
+                )
+        cls.use_backfacing = BoolProperty(
+                name="Check back-faces",
+                description="Tests back-faces of strands",
+                default=False,
+                )
+        cls.use_encasing = BoolProperty(
+                name="Exclude encasing",
+                description="Ignores strands encasing a ray's initial location",
+                default=True,
+                )
+        cls.use_tangent_normal_geometry = BoolProperty(
+                name="Tangent normal geometry",
+                description="Uses the tangent normal for actual normal",
+                default=False,
+                )
+        cls.use_tangent_normal = BoolProperty(
+                name="Tangent normal default",
+                description="Uses the tangent normal for all normals",
+                default=False,
+                )
+        cls.use_tangent_normal_correction = BoolProperty(
+                name="strand slope correction",
+                description="Corrects the tangent normal for the strands slope",
+                default=False,
+                )
+        cls.use_cache = BoolProperty(
+                name="Export Cached data",
+                description="Export cached data with child strands (uses 'draw step' for subdivisions)",
+                default=True,
+                )
+        cls.use_parents = BoolProperty(
+                name="Use parent strands",
+                description="Use parents with children",
+                default=False,
+                )
+        cls.use_smooth = BoolProperty(
+                name="Smooth Strands",
+                description="Use vertex normals",
+                default=True,
+                )
+        cls.use_joined = BoolProperty(
+                name="Join",
+                description="Fills gaps between segments (requires more memory)",
+                default=False,
+                )
+        cls.use_curves = BoolProperty(
+                name="Use Cycles Hair Rendering",
+                description="Activate cycles hair rendering for particle system",
+                default=True,
+                )        
+        cls.segments = IntProperty(
+                name="Segments",
+                description="Number of segments between path keys (Note that this combines with the `draw step' value)",
+                min=1, max=64,
+                default=1,
+                )
+        cls.resolution = IntProperty(
+                name="Resolution",
+                description="Resolution of generated mesh",
+                min=3, max=64,
+                default=3,
+                )
+        cls.normalmix = FloatProperty(
+                name="Normal mix",
+                description="Scale factor for tangent normal removal (zero gives ray normal)",
+                min=0, max=2.0,
+                default=1,
+                )
+        cls.encasing_ratio = FloatProperty(
+                name="Encasing ratio",
+                description="Scale factor for encasing strand width",
+                min=0, max=100.0,
+                default=1.01,
+                )
+
+    @classmethod
+    def unregister(cls):
+        del bpy.types.Scene.cycles_curves
+
+class CyclesCurveSettings(bpy.types.PropertyGroup):
+    @classmethod
+    def register(cls):
+        bpy.types.ParticleSettings.cycles = PointerProperty(
+                name="Cycles Hair Settings",
+                description="Cycles hair settings",
+                type=cls,
+                )
+        cls.root_width = FloatProperty(
+                name="Root Size Multiplier",
+                description="Multiplier of particle size for the strand's width at root",
+                min=0.0, max=1000.0,
+                default=1.0,
+                )
+        cls.tip_width = FloatProperty(
+                name="Tip Size Multiplier",
+                description="Multiplier of particle size for the strand's width at tip",
+                min=0.0, max=1000.0,
+                default=0.0,
+                )
+        cls.shape = FloatProperty(
+                name="Strand Shape",
+                description="Strand shape parameter",
+                min=-1.0, max=1.0,
+                default=0.0,
+                )
+        cls.use_closetip = BoolProperty(
+                name="Close tip",
+                description="Sets tip radius to zero",
+                default=True,
+                )                
+
+    @classmethod
+    def unregister(cls):
+        del bpy.types.ParticleSettings.cycles
 
 def register():
     bpy.utils.register_class(CyclesRenderSettings)
@@ -582,6 +766,8 @@ def register():
     bpy.utils.register_class(CyclesWorldSettings)
     bpy.utils.register_class(CyclesVisibilitySettings)
     bpy.utils.register_class(CyclesMeshSettings)
+    bpy.utils.register_class(CyclesCurveRenderSettings)
+    bpy.utils.register_class(CyclesCurveSettings)
 
 
 def unregister():
@@ -592,3 +778,5 @@ def unregister():
     bpy.utils.unregister_class(CyclesWorldSettings)
     bpy.utils.unregister_class(CyclesMeshSettings)
     bpy.utils.unregister_class(CyclesVisibilitySettings)
+    bpy.utils.unregister_class(CyclesCurveRenderSettings)
+    bpy.utils.unregister_class(CyclesCurveSettings)
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 86a1ab3c3e0..5253f5789ec 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -944,7 +944,95 @@ class CyclesParticle_PT_textures(CyclesButtonsPanel, Panel):
         else:
             slot = part.texture_slots[part.active_texture_index]
             layout.template_ID(slot, "texture", new="texture.new")
+            
+class CyclesParticle_PT_CurveSettings(CyclesButtonsPanel, Panel):
+    bl_label = "Cycles Hair Settings"
+    bl_context = "particle"
+    
+    @classmethod
+    def poll(cls, context):
+        psys = context.particle_system
+        device_type = context.user_preferences.system.compute_device_type
+        if context.scene.cycles.feature_set == 'EXPERIMENTAL' and (context.scene.cycles.device == 'CPU' or device_type == 'NONE'):
+            if CyclesButtonsPanel.poll(context) and psys:
+                return True
+
+        return False
+
+    def draw(self, context):
+        layout = self.layout
+        
+        psys = context.particle_settings
+        
+        cpsys = psys.cycles
+        
+        row = layout.row()
+        row.prop(cpsys, "shape", text="Shape")
+        row.prop(cpsys, "use_closetip", text="Close tip")
+        row = layout.row()
+        row.prop(cpsys, "root_width", text="Root Width multiplier")
+        row = layout.row()
+        row.prop(cpsys, "tip_width", text="Tip Width multiplier")
+
+class CyclesRender_PT_CurveRendering(CyclesButtonsPanel, Panel):
+    bl_label = "Cycles Hair Rendering"
+    bl_context = "particle"
+    
+    @classmethod
+    def poll(cls, context):
+        device_type = context.user_preferences.system.compute_device_type
+        if CyclesButtonsPanel.poll(context):
+            if context.scene.cycles.feature_set == 'EXPERIMENTAL' and (context.scene.cycles.device == 'CPU' or device_type == 'NONE'):
+                return True
 
+        return False
+    
+    def draw(self, context):
+        layout = self.layout
+        scene = context.scene
+        csscene = scene.cycles_curves
+        
+        row = layout.row()
+        row.prop(csscene, "use_curves", text="Enable Cycles Hair")
+        row = layout.row()
+        row.prop(csscene, "preset", text="Mode")
+        
+        if csscene.preset == 'CUSTOM':
+            row = layout.row()
+            row.prop(csscene, "primitive", text="Primitive")
+            row = layout.row()
+        
+            if csscene.primitive == 'TRIANGLES':
+                row.prop(csscene, "triangle_method", text="Method")
+                if csscene.triangle_method == 'TESSELATED':
+                    row = layout.row()
+                    row.prop(csscene, "resolution", text="Resolution")
+                row = layout.row()
+                row.prop(csscene, "use_smooth", text="Smooth")
+            elif csscene.primitive == 'LINE_SEGMENTS':
+                row.prop(csscene, "use_backfacing", text="Check back-faces")
+                row = layout.row()
+                row.prop(csscene, "use_encasing", text="Exclude encasing")
+                if csscene.use_encasing:
+                    row.prop(csscene, "encasing_ratio", text="Ratio for encasing")
+                row = layout.row()
+                row.prop(csscene, "line_method", text="Method")
+                row = layout.row()
+                row.prop(csscene, "use_tangent_normal", text="Use tangent normal as default")
+                row = layout.row()
+                row.prop(csscene, "use_tangent_normal_geometry", text="Use tangent normal geometry")
+                row = layout.row()
+                row.prop(csscene, "use_tangent_normal_correction", text="Correct tangent normal for slope")
+                row = layout.row()
+                row.prop(csscene, "interpolation", text="Interpolation")
+                row = layout.row()
+                row.prop(csscene, "segments", text="Segments")
+                row = layout.row()
+                row.prop(csscene, "normalmix", text="Ray Mix")
+            row = layout.row()
+            row.prop(csscene, "use_cache", text="Export cache with children")
+            if csscene.use_cache:
+                row.prop(csscene, "use_parents", text="Include parents")  
 
 class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel):
     bl_label = "Simplify"
diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp
new file mode 100644
index 00000000000..81358e51eb2
--- /dev/null
+++ b/intern/cycles/blender/blender_curves.cpp
@@ -0,0 +1,898 @@
+/*
+ * Copyright 2011, 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.
+ */
+
+#include "mesh.h"
+#include "object.h"
+#include "scene.h"
+#include "curves.h"
+
+#include "blender_sync.h"
+#include "blender_util.h"
+
+#include "subd_mesh.h"
+#include "subd_patch.h"
+#include "subd_split.h"
+
+#include "util_foreach.h"
+
+#include "DNA_modifier_types.h"
+#include "DNA_particle_types.h"
+#include "DNA_meshdata_types.h"
+
+CCL_NAMESPACE_BEGIN
+
+/* Utilities */
+
+/* Hair curve functions */
+
+void curveinterp_v3_v3v3v3v3(float3 *p, float3 *v1, float3 *v2, float3 *v3, float3 *v4, const float w[4]);
+void interp_weights(float t, float data[4], int type);
+float shaperadius(float shape, float root, float tip, float time);
+void InterpolateKeySegments(int seg, int segno, int key, int curve, float3 *keyloc, float *time, ParticleCurveData *CData, int interpolation);
+bool ObtainParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData);
+bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents);
+void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int segments, float3 RotCam);
+void ExportCurveTriangleRibbons(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int segments);
+void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int resolution, int segments);
+void ExportCurveSegments(Mesh *mesh, ParticleCurveData *CData, int interpolation, int segments);
+
+ParticleCurveData::ParticleCurveData()
+{
+}
+
+ParticleCurveData::~ParticleCurveData()
+{
+	psys_firstcurve.clear();
+	psys_curvenum.clear();
+	psys_shader.clear();
+	psys_rootradius.clear();
+	psys_tipradius.clear();
+	psys_shape.clear();
+
+	curve_firstkey.clear();
+	curve_keynum.clear();
+	curve_length.clear();
+	curve_u.clear();
+	curve_v.clear();
+
+	curvekey_co.clear();
+	curvekey_time.clear();
+}
+
+void interp_weights(float t, float data[4], int type)
+{
+	float t2, t3, fc;
+
+	if (type == CURVE_LINEAR) {
+		data[0] =          0.0f;
+		data[1] = -t     + 1.0f;
+		data[2] =  t;
+		data[3] =          0.0f;
+	}
+	else if (type == CURVE_CARDINAL) {
+		t2 = t * t;
+		t3 = t2 * t;
+		fc = 0.71f;
+
+		data[0] = -fc          * t3  + 2.0f * fc          * t2 - fc * t;
+		data[1] =  (2.0f - fc) * t3  + (fc - 3.0f)        * t2 + 1.0f;
+		data[2] =  (fc - 2.0f) * t3  + (3.0f - 2.0f * fc) * t2 + fc * t;
+		data[3] =  fc          * t3  - fc * t2;
+	}
+	else if (type == CURVE_BSPLINE) {
+		t2 = t * t;
+		t3 = t2 * t;
+
+		data[0] = -0.16666666f * t3  + 0.5f * t2   - 0.5f * t    + 0.16666666f;
+		data[1] =  0.5f        * t3  - t2                        + 0.66666666f;
+		data[2] = -0.5f        * t3  + 0.5f * t2   + 0.5f * t    + 0.16666666f;
+		data[3] =  0.16666666f * t3;
+	}
+}
+
+void curveinterp_v3_v3v3v3v3(float3 *p, float3 *v1, float3 *v2, float3 *v3, float3 *v4, const float w[4])
+{
+	p->x = v1->x * w[0] + v2->x * w[1] + v3->x * w[2] + v4->x * w[3];
+	p->y = v1->y * w[0] + v2->y * w[1] + v3->y * w[2] + v4->y * w[3];
+	p->z = v1->z * w[0] + v2->z * w[1] + v3->z * w[2] + v4->z * w[3];
+}
+
+float shaperadius(float shape, float root, float tip, float time)
+{
+	float radius = 1.0f - time;
+	if (shape != 0.0f) {
+		if (shape < 0.0f)
+			radius = (float)pow(1.0f - time, 1.f + shape);
+		else
+			radius = (float)pow(1.0f - time, 1.f / (1.f - shape));
+	}
+	return (radius * (root - tip)) + tip;
+}
+
+/* curve functions */
+
+void InterpolateKeySegments(int seg, int segno, int key, int curve, float3 *keyloc, float *time, ParticleCurveData *CData, int interpolation)
+{
+	float3 ckey_loc1 = CData->curvekey_co[key];
+	float3 ckey_loc2 = ckey_loc1;
+	float3 ckey_loc3 = CData->curvekey_co[key+1];
+	float3 ckey_loc4 = ckey_loc3;
+
+	if (key > CData->curve_firstkey[curve])
+		ckey_loc1 = CData->curvekey_co[key - 1];
+
+	if (key < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2)
+		ckey_loc4 = CData->curvekey_co[key + 2];
+
+
+	float time1 = CData->curvekey_time[key]/CData->curve_length[curve];
+	float time2 = CData->curvekey_time[key + 1]/CData->curve_length[curve];
+
+	float dfra = (time2 - time1) / (float)segno;
+
+	if(time)
+		*time = (dfra * seg) + time1;
+
+	float t[4];
+
+	interp_weights((float)seg / (float)segno, t, interpolation);
+
+	if(keyloc)
+		curveinterp_v3_v3v3v3v3(keyloc, &ckey_loc1, &ckey_loc2, &ckey_loc3, &ckey_loc4, t);
+}
+
+bool ObtainParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData)
+{
+
+	int curvenum = 0;
+	int keyno = 0;
+
+	if(!(mesh && b_mesh && b_ob && CData))
+		return false;
+
+	BL::Object::modifiers_iterator b_mod;
+	for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
+		if ((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (b_mod->show_viewport()) && (b_mod->show_render())) {
+
+			BL::ParticleSystemModifier psmd(b_mod->ptr);
+
+			BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
+
+			BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
+
+			if((b_psys.settings().render_type()==BL::ParticleSettings::render_type_PATH)&&(b_psys.settings().type()==BL::ParticleSettings::type_HAIR)) {
+
+				int mi = clamp(b_psys.settings().material()-1, 0, mesh->used_shaders.size()-1);
+				int shader = mesh->used_shaders[mi];
+
+				int totcurves = b_psys.particles.length();
+
+				if(totcurves == 0)
+					continue;
+
+				PointerRNA cpsys = RNA_pointer_get(&b_part.ptr, "cycles");
+
+				CData->psys_firstcurve.push_back(curvenum);
+				CData->psys_curvenum.push_back(totcurves);
+				CData->psys_shader.push_back(shader);
+
+				float radius = b_psys.settings().particle_size() * 0.5f;
+	
+				CData->psys_rootradius.push_back(radius * get_float(cpsys, "root_width"));
+				CData->psys_tipradius.push_back(radius * get_float(cpsys, "tip_width"));
+				CData->psys_shape.push_back(get_float(cpsys, "shape"));
+				CData->psys_closetip.push_back(get_boolean(cpsys, "use_closetip"));
+
+				BL::ParticleSystem::particles_iterator b_pa;
+				for(b_psys.particles.begin(b_pa); b_pa != b_psys.particles.end(); ++b_pa) {
+					CData->curve_firstkey.push_back(keyno);
+
+					int keylength = b_pa->hair_keys.length();
+					CData->curve_keynum.push_back(keylength);
+
+					float curve_length = 0.0f;
+					float3 pcKey;
+					int step_no = 0;
+					BL::Particle::hair_keys_iterator b_cKey;
+					for(b_pa->hair_keys.begin(b_cKey); b_cKey != b_pa->hair_keys.end(); ++b_cKey) {
+						float nco[3];
+						b_cKey->co_object( *b_ob, psmd, *b_pa, nco);
+						float3 cKey = make_float3(nco[0],nco[1],nco[2]);
+						if (step_no > 0)
+							curve_length += len(cKey - pcKey);
+						CData->curvekey_co.push_back(cKey);
+						CData->curvekey_time.push_back(curve_length);
+						pcKey = cKey;
+						keyno++;
+						step_no++;
+					}
+
+					CData->curve_length.push_back(curve_length);
+					/*add uvs*/
+					BL::Mesh::tessface_uv_textures_iterator l;
+					b_mesh->tessface_uv_textures.begin(l);
+
+					float uvs[3] = {0,0};
+					if(b_mesh->tessface_uv_textures.length())
+						b_pa->uv_on_emitter(psmd,uvs);
+					CData->curve_u.push_back(uvs[0]);
+					CData->curve_v.push_back(uvs[1]);
+
+					curvenum++;
+
+				}
+			}
+		}
+	}
+
+	return true;
+
+}
+
+bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents)
+{
+
+	int curvenum = 0;
+	int keyno = 0;
+
+	if(!(mesh && b_mesh && b_ob && CData))
+		return false;
+
+	Transform tfm = get_transform(b_ob->matrix_world());
+	Transform itfm = transform_quick_inverse(tfm);
+
+	BL::Object::modifiers_iterator b_mod;
+	for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
+		if ((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (b_mod->show_viewport()) && (b_mod->show_render())) {
+			BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
+
+			BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
+
+			BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
+
+			if((b_psys.settings().render_type()==BL::ParticleSettings::render_type_PATH)&&(b_psys.settings().type()==BL::ParticleSettings::type_HAIR)) {
+
+				int mi = clamp(b_psys.settings().material()-1, 0, mesh->used_shaders.size()-1);
+				int shader = mesh->used_shaders[mi];
+				int draw_step = b_psys.settings().draw_step();
+				int ren_step = (int)pow((float)2.0f,(float)draw_step);
+				/*b_psys.settings().render_step(draw_step);*/
+
+				int totparts = b_psys.particles.length();
+				int totchild = b_psys.child_particles.length() * b_psys.settings().draw_percentage() / 100;
+				int totcurves = totchild;
+				
+				if (use_parents || b_psys.settings().child_type() == 0)
+					totcurves += totparts;
+
+				if (totcurves == 0)
+					continue;
+
+				PointerRNA cpsys = RNA_pointer_get(&b_part.ptr, "cycles");
+
+				CData->psys_firstcurve.push_back(curvenum);
+				CData->psys_curvenum.push_back(totcurves);
+				CData->psys_shader.push_back(shader);
+
+				float radius = b_psys.settings().particle_size() * 0.5f;
+	
+				CData->psys_rootradius.push_back(radius * get_float(cpsys, "root_width"));
+				CData->psys_tipradius.push_back(radius * get_float(cpsys, "tip_width"));
+				CData->psys_shape.push_back(get_float(cpsys, "shape"));
+				CData->psys_closetip.push_back(get_boolean(cpsys, "use_closetip"));
+
+				int pa_no = 0;
+				if(!use_parents && !(b_psys.settings().child_type() == 0))
+					pa_no = totparts;
+
+				BL::ParticleSystem::particles_iterator b_pa;
+				b_psys.particles.begin(b_pa);
+				for(; pa_no < totparts+totchild; pa_no++) {
+
+					CData->curve_firstkey.push_back(keyno);
+					CData->curve_keynum.push_back(ren_step+1);
+					
+					float curve_length = 0.0f;
+					float3 pcKey;
+					for(int step_no = 0; step_no <= ren_step; step_no++) {
+						float nco[3];
+						b_psys.co_hair(*b_ob, psmd, pa_no, step_no, nco);
+						float3 cKey = make_float3(nco[0],nco[1],nco[2]);
+						cKey = transform_point(&itfm, cKey);
+						if (step_no > 0)
+							curve_length += len(cKey - pcKey);
+						CData->curvekey_co.push_back(cKey);
+						CData->curvekey_time.push_back(curve_length);
+						pcKey = cKey;
+						keyno++;
+					}
+					CData->curve_length.push_back(curve_length);
+
+					/*add uvs*/
+					BL::Mesh::tessface_uv_textures_iterator l;
+					b_mesh->tessface_uv_textures.begin(l);
+
+					float uvs[2] = {0,0};
+					if(b_mesh->tessface_uv_textures.length())
+						b_psys.uv_on_emitter(psmd, *b_pa, pa_no, uvs);
+						
+
+					if(pa_no < totparts && b_pa != b_psys.particles.end())
+						++b_pa;
+
+					CData->curve_u.push_back(uvs[0]);
+					CData->curve_v.push_back(uvs[1]);
+
+					curvenum++;
+
+				}
+			}
+
+		}
+	}
+
+	return true;
+
+}
+
+void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int segments, float3 RotCam)
+{
+	int vertexno = mesh->verts.size();
+	int vertexindex = vertexno;
+
+	for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
+		for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
+
+			for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
+
+				int subv = 1;
+				float3 xbasis;
+
+				float3 v1;
+
+				if (curvekey == CData->curve_firstkey[curve]) {
+					subv = 0;
+					v1 = CData->curvekey_co[curvekey+2] - CData->curvekey_co[curvekey];
+				}
+				else if (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2)
+					v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey - 2];
+				else 
+					v1 = CData->curvekey_co[curvekey + 1] - CData->curvekey_co[curvekey - 1];
+
+
+				for (; subv <= segments; subv++) {
+
+					float3 ickey_loc = make_float3(0.0f,0.0f,0.0f);
+					float time = 0.0f;
+
+					if ((interpolation == 2) && (curvekey == CData->curve_firstkey[curve]) && (subv == 0))
+						ickey_loc = CData->curvekey_co[curvekey];
+					else
+						InterpolateKeySegments(subv, segments, curvekey, curve, &ickey_loc, &time, CData , interpolation);
+
+					float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
+
+					if (CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
+						radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);
+
+					if ((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) && (subv == segments))
+						radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.95f);
+
+					xbasis = normalize(cross(v1,RotCam - ickey_loc));
+					float3 ickey_loc_shfl = ickey_loc - radius * xbasis;
+					float3 ickey_loc_shfr = ickey_loc + radius * xbasis;
+					mesh->verts.push_back(ickey_loc_shfl);
+					mesh->verts.push_back(ickey_loc_shfr);
+					if(subv!=0) {
+						mesh->add_triangle(vertexindex-2, vertexindex, vertexindex-1, CData->psys_shader[sys], use_smooth);
+						mesh->add_triangle(vertexindex+1, vertexindex-1, vertexindex, CData->psys_shader[sys], use_smooth);
+					}
+					vertexindex += 2;
+				}
+			}
+		}
+	}
+
+	mesh->reserve(mesh->verts.size(), mesh->triangles.size());
+	mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
+	mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
+	mesh->add_face_normals();
+	mesh->add_vertex_normals();
+
+	/* texture coords still needed */
+
+}
+
+void ExportCurveTriangleRibbons(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int segments)
+{
+	int vertexno = mesh->verts.size();
+	int vertexindex = vertexno;
+
+	for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
+		for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
+
+			float3 firstxbasis = cross(make_float3(1.0f,0.0f,0.0f),CData->curvekey_co[CData->curve_firstkey[curve]+1] - CData->curvekey_co[CData->curve_firstkey[curve]]);
+			if(len_squared(firstxbasis)!= 0.0f)
+				firstxbasis = normalize(firstxbasis);
+			else
+				firstxbasis = normalize(cross(make_float3(0.0f,1.0f,0.0f),CData->curvekey_co[CData->curve_firstkey[curve]+1] - CData->curvekey_co[CData->curve_firstkey[curve]]));
+
+			for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
+
+				float3 xbasis = firstxbasis;
+				float3 v1;
+				float3 v2;
+
+				if (curvekey == CData->curve_firstkey[curve]) {
+					v1 = CData->curvekey_co[curvekey+2] - CData->curvekey_co[curvekey+1];
+					v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
+				}
+				else if (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) {
+					v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
+					v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[curvekey-2];
+				}
+				else {
+					v1 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
+					v2 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
+				}
+
+				xbasis = cross(v1,v2);
+
+				if(len_squared(xbasis) >= 0.05f * len_squared(v1) * len_squared(v2)) {
+					firstxbasis = normalize(xbasis);
+					break;
+				}
+			}
+
+			for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
+
+				int subv = 1;
+				float3 v1;
+				float3 v2;
+				float3 xbasis;
+
+				if (curvekey == CData->curve_firstkey[curve]) {
+					subv = 0;
+					v1 = CData->curvekey_co[curvekey+2] - CData->curvekey_co[curvekey+1];
+					v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
+				}
+				else if (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) {
+					v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
+					v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[curvekey-2];
+				}
+				else {
+					v1 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
+					v2 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
+				}
+
+				xbasis = cross(v1,v2);
+
+				if(len_squared(xbasis) >= 0.05f * len_squared(v1) * len_squared(v2)) {
+					xbasis = normalize(xbasis);
+					firstxbasis = xbasis;
+				}
+				else
+					xbasis = firstxbasis;
+
+				for (; subv <= segments; subv++) {
+
+					float3 ickey_loc = make_float3(0.0f,0.0f,0.0f);
+					float time = 0.0f;
+
+					if ((interpolation == 2) && (curvekey == CData->curve_firstkey[curve]) && (subv == 0))
+						ickey_loc = CData->curvekey_co[curvekey];
+					else
+						InterpolateKeySegments(subv, segments, curvekey, curve, &ickey_loc, &time, CData , interpolation);
+
+					float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
+
+					if (CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
+						radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);
+
+					if ((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) && (subv == segments))
+						radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.95f);
+
+					float3 ickey_loc_shfl = ickey_loc - radius * xbasis;
+					float3 ickey_loc_shfr = ickey_loc + radius * xbasis;
+					mesh->verts.push_back(ickey_loc_shfl);
+					mesh->verts.push_back(ickey_loc_shfr);
+					if(subv!=0) {
+						mesh->add_triangle(vertexindex-2, vertexindex, vertexindex-1, CData->psys_shader[sys], use_smooth);
+						mesh->add_triangle(vertexindex+1, vertexindex-1, vertexindex, CData->psys_shader[sys], use_smooth);
+					}
+					vertexindex += 2;
+				}
+			}
+		}
+	}
+
+	mesh->reserve(mesh->verts.size(), mesh->triangles.size());
+	mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
+	mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
+	mesh->add_face_normals();
+	mesh->add_vertex_normals();
+
+	/* texture coords still needed */
+
+}
+
+void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int resolution, int segments)
+{
+	int vertexno = mesh->verts.size();
+	int vertexindex = vertexno;
+
+	for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
+		for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
+
+			float3 firstxbasis = cross(make_float3(1.0f,0.0f,0.0f),CData->curvekey_co[CData->curve_firstkey[curve]+1] - CData->curvekey_co[CData->curve_firstkey[curve]]);
+			if(len_squared(firstxbasis)!= 0.0f)
+				firstxbasis = normalize(firstxbasis);
+			else
+				firstxbasis = normalize(cross(make_float3(0.0f,1.0f,0.0f),CData->curvekey_co[CData->curve_firstkey[curve]+1] - CData->curvekey_co[CData->curve_firstkey[curve]]));
+
+
+			for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
+
+				float3 xbasis = firstxbasis;
+				float3 v1;
+				float3 v2;
+
+				if (curvekey == CData->curve_firstkey[curve]) {
+					v1 = CData->curvekey_co[curvekey+2] - CData->curvekey_co[curvekey+1];
+					v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
+				}
+				else if (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) {
+					v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
+					v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[curvekey-2];
+				}
+				else {
+					v1 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
+					v2 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
+				}
+
+				xbasis = cross(v1,v2);
+
+				if(len_squared(xbasis) >= 0.05f * len_squared(v1) * len_squared(v2)) {
+					firstxbasis = normalize(xbasis);
+					break;
+				}
+			}
+
+			for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
+
+				int subv = 1;
+				float3 xbasis;
+				float3 ybasis;
+				float3 v1;
+				float3 v2;
+
+				if (curvekey == CData->curve_firstkey[curve]) {
+					subv = 0;
+					v1 = CData->curvekey_co[curvekey+2] - CData->curvekey_co[curvekey+1];
+					v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
+				}
+				else if (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) {
+					v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
+					v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[curvekey-2];
+				}
+				else {
+					v1 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
+					v2 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
+				}
+
+				xbasis = cross(v1,v2);
+
+				if(len_squared(xbasis) >= 0.05f * len_squared(v1) * len_squared(v2)) {
+					xbasis = normalize(xbasis);
+					firstxbasis = xbasis;
+				}
+				else
+					xbasis = firstxbasis;
+
+				ybasis = normalize(cross(xbasis,v2));
+
+				for (; subv <= segments; subv++) {
+
+					float3 ickey_loc = make_float3(0.0f,0.0f,0.0f);
+					float time = 0.0f;
+
+					if ((interpolation == 2) && (curvekey == CData->curve_firstkey[curve]) && (subv == 0))
+						ickey_loc = CData->curvekey_co[curvekey];
+					else
+						InterpolateKeySegments(subv, segments, curvekey, curve, &ickey_loc, &time, CData , interpolation);
+
+					float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
+
+					if (CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
+						radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);
+
+					if ((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) && (subv == segments))
+						radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.95f);
+
+					float angle = 2 * M_PI_F / (float)resolution;
+					for(int section = 0 ; section < resolution; section++) {
+						float3 ickey_loc_shf = ickey_loc + radius * (cosf(angle * section) * xbasis + sinf(angle * section) * ybasis);
+						mesh->verts.push_back(ickey_loc_shf);
+					}
+
+					if(subv!=0) {
+						for(int section = 0 ; section < resolution - 1; section++) {
+							mesh->add_triangle(vertexindex - resolution + section, vertexindex + section, vertexindex - resolution + section + 1, CData->psys_shader[sys], use_smooth);
+							mesh->add_triangle(vertexindex + section + 1, vertexindex - resolution + section + 1, vertexindex + section, CData->psys_shader[sys], use_smooth);
+						}
+						mesh->add_triangle(vertexindex-1, vertexindex + resolution - 1, vertexindex - resolution, CData->psys_shader[sys], use_smooth);
+						mesh->add_triangle(vertexindex, vertexindex - resolution , vertexindex + resolution - 1, CData->psys_shader[sys], use_smooth);
+					}
+					vertexindex += resolution;
+				}
+			}
+		}
+	}
+
+	mesh->reserve(mesh->verts.size(), mesh->triangles.size());
+	mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
+	mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
+	mesh->add_face_normals();
+	mesh->add_vertex_normals();
+
+	/* texture coords still needed */
+}
+
+void ExportCurveSegments(Mesh *mesh, ParticleCurveData *CData, int interpolation, int segments)
+{
+	int cks = 0;
+	int curs = 0;
+	int segs = 0;
+
+	if(!(mesh->curve_segs.empty() && mesh->curve_keys.empty() && mesh->curve_attrib.empty()))
+		return;
+
+	for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
+
+		if(CData->psys_curvenum[sys] == 0)
+			continue;
+
+		for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
+
+			if(CData->curve_keynum[curve] <= 1)
+				continue;
+
+			for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
+
+				int subv = 1;
+				if (curvekey == CData->curve_firstkey[curve])
+					subv = 0;
+
+				for (; subv <= segments; subv++) {
+
+					float3 ickey_loc = make_float3(0.0f,0.0f,0.0f);
+					float time = 0.0f;
+
+					if ((interpolation == CURVE_BSPLINE) && (curvekey == CData->curve_firstkey[curve]) && (subv == 0))
+						ickey_loc = CData->curvekey_co[curvekey];
+					else
+						InterpolateKeySegments(subv, segments, curvekey, curve, &ickey_loc, &time, CData , interpolation);
+
+					float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
+
+					if (CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
+						radius =0.0f;
+
+					mesh->add_curvekey(ickey_loc, radius, time);
+
+					if(subv != 0) {
+						mesh->add_curve(cks - 1, cks, CData->psys_shader[sys], curs);
+						segs++;
+					}
+
+					cks++;
+				}
+			}
+
+			mesh->add_curveattrib(CData->curve_u[curve], CData->curve_v[curve]);
+			curs++;
+
+		}
+	}
+
+	/* check allocation*/
+	if((mesh->curve_keys.size() !=  cks) || (mesh->curve_segs.size() !=  segs) || (mesh->curve_attrib.size() != curs)) {
+		/* allocation failed -> clear data */
+		mesh->curve_keys.clear();
+		mesh->curve_segs.clear();
+		mesh->curve_attrib.clear();
+	}
+}
+
+/* Hair Curve Sync */
+
+void BlenderSync::sync_curve_settings()
+{
+	PointerRNA csscene = RNA_pointer_get(&b_scene.ptr, "cycles_curves");
+	
+	int preset = get_enum(csscene, "preset");
+
+	CurveSystemManager *curve_system_manager = scene->curve_system_manager;
+	CurveSystemManager prev_curve_system_manager = *curve_system_manager;
+
+	curve_system_manager->use_curves = get_boolean(csscene, "use_curves");
+
+	if (preset == CURVE_CUSTOM) {
+		/*custom properties*/
+		curve_system_manager->primitive = get_enum(csscene, "primitive");
+		curve_system_manager->line_method = get_enum(csscene, "line_method");
+		curve_system_manager->interpolation = get_enum(csscene, "interpolation");
+		curve_system_manager->triangle_method = get_enum(csscene, "triangle_method");
+		curve_system_manager->resolution = get_int(csscene, "resolution");
+		curve_system_manager->segments = get_int(csscene, "segments");
+		curve_system_manager->use_smooth = get_boolean(csscene, "use_smooth");
+
+		curve_system_manager->normalmix = get_float(csscene, "normalmix");
+		curve_system_manager->encasing_ratio = get_float(csscene, "encasing_ratio");
+
+		curve_system_manager->use_cache = get_boolean(csscene, "use_cache");
+		curve_system_manager->use_parents = get_boolean(csscene, "use_parents");
+		curve_system_manager->use_encasing = get_boolean(csscene, "use_encasing");
+		curve_system_manager->use_backfacing = get_boolean(csscene, "use_backfacing");
+		curve_system_manager->use_joined = get_boolean(csscene, "use_joined");
+		curve_system_manager->use_tangent_normal = get_boolean(csscene, "use_tangent_normal");
+		curve_system_manager->use_tangent_normal_geometry = get_boolean(csscene, "use_tangent_normal_geometry");
+		curve_system_manager->use_tangent_normal_correction = get_boolean(csscene, "use_tangent_normal_correction");
+	}
+	else {
+		curve_system_manager->primitive = CURVE_LINE_SEGMENTS;
+		curve_system_manager->interpolation = CURVE_CARDINAL;
+		curve_system_manager->normalmix = 1.0f;
+		curve_system_manager->encasing_ratio = 1.01f;
+		curve_system_manager->use_cache = true;
+		curve_system_manager->use_parents = false;
+		curve_system_manager->segments = 1;
+		curve_system_manager->use_joined = false;
+
+		switch(preset) {
+			case CURVE_TANGENT_SHADING:
+				/*tangent shading*/
+				curve_system_manager->line_method = CURVE_UNCORRECTED;
+				curve_system_manager->use_encasing = true;
+				curve_system_manager->use_backfacing = false;
+				curve_system_manager->use_tangent_normal = true;
+				curve_system_manager->use_tangent_normal_geometry = true;
+				curve_system_manager->use_tangent_normal_correction = false;
+				break;
+			case CURVE_TRUE_NORMAL:
+				/*True Normal*/
+				curve_system_manager->line_method = CURVE_CORRECTED;
+				curve_system_manager->use_encasing = true;
+				curve_system_manager->use_backfacing = false;
+				curve_system_manager->use_tangent_normal = false;
+				curve_system_manager->use_tangent_normal_geometry = false;
+				curve_system_manager->use_tangent_normal_correction = false;
+				break;
+			case CURVE_ACCURATE_PRESET:
+				/*Accurate*/
+				curve_system_manager->line_method = CURVE_ACCURATE;
+				curve_system_manager->use_encasing = false;
+				curve_system_manager->use_backfacing = true;
+				curve_system_manager->use_tangent_normal = false;
+				curve_system_manager->use_tangent_normal_geometry = false;
+				curve_system_manager->use_tangent_normal_correction = false;
+				break;
+		}
+		
+	}
+
+	if(curve_system_manager->modified_mesh(prev_curve_system_manager))
+	{
+		BL::BlendData::objects_iterator b_ob;
+
+		for(b_data.objects.begin(b_ob); b_ob != b_data.objects.end(); ++b_ob) {
+			if(object_is_mesh(*b_ob)) {
+				BL::Object::particle_systems_iterator b_psys;
+				for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) {
+					if((b_psys->settings().render_type()==BL::ParticleSettings::render_type_PATH)&&(b_psys->settings().type()==BL::ParticleSettings::type_HAIR)) {
+						BL::ID key = BKE_object_is_modified(*b_ob)? *b_ob: b_ob->data();
+						mesh_map.set_recalc(key);
+						object_map.set_recalc(*b_ob);
+					}
+				}
+			}
+		}
+	}
+
+	if(curve_system_manager->modified(prev_curve_system_manager))
+		curve_system_manager->tag_update(scene);
+
+}
+
+void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool object_updated)
+{
+	/* Clear stored curve data */
+	mesh->curve_attrib.clear();
+	mesh->curve_keys.clear();
+	mesh->curve_keysCD.clear();
+	mesh->curve_segs.clear();
+
+	/* obtain general settings */
+	bool use_curves = scene->curve_system_manager->use_curves;
+
+	if(use_curves && b_ob.mode() == b_ob.mode_OBJECT) {
+	int primitive = scene->curve_system_manager->primitive;
+	int interpolation = scene->curve_system_manager->interpolation;
+	int triangle_method = scene->curve_system_manager->triangle_method;
+	int resolution = scene->curve_system_manager->resolution;
+	int segments = scene->curve_system_manager->segments;
+	bool use_smooth = scene->curve_system_manager->use_smooth;
+	bool use_cache = scene->curve_system_manager->use_cache;
+	bool use_parents = scene->curve_system_manager->use_parents;
+	bool export_tgs = scene->curve_system_manager->use_joined;
+
+	/* extract particle hair data - should be combined with connecting to mesh later*/
+
+	ParticleCurveData *CData = new ParticleCurveData();
+
+	if (use_cache)
+		ObtainCacheParticleData(mesh, &b_mesh, &b_ob, CData, use_parents);
+	else
+		ObtainParticleData(mesh, &b_mesh, &b_ob, CData);
+
+	/* attach strands to mesh */
+	BL::Object b_CamOb = b_scene.camera();
+	float3 RotCam = make_float3(0.0f, 0.0f, 0.0f);
+	if(b_CamOb) {
+		Transform ctfm = get_transform(b_CamOb.matrix_world());
+		Transform tfm = get_transform(b_ob.matrix_world());
+		Transform itfm = transform_quick_inverse(tfm);
+		RotCam = transform_point(&itfm, make_float3(ctfm.x.w, ctfm.y.w, ctfm.z.w));
+	}
+
+	if (primitive == CURVE_TRIANGLES){
+		if (triangle_method == CURVE_CAMERA)
+			ExportCurveTrianglePlanes(mesh, CData, interpolation, use_smooth, segments, RotCam);
+		else if (triangle_method == CURVE_RIBBONS)
+			ExportCurveTriangleRibbons(mesh, CData, interpolation, use_smooth, segments);
+		else
+			ExportCurveTriangleGeometry(mesh, CData, interpolation, use_smooth, resolution, segments);
+	}
+	else {
+		ExportCurveSegments(mesh, CData, interpolation, segments);
+		int ckey_num = mesh->curve_keys.size();
+
+		/*export tangents or curve data? - not functional yet*/
+		if (export_tgs && ckey_num > 1) {
+			
+			for(int ck = 0; ck < ckey_num; ck++) {
+				Mesh::CurveData SCD;
+				SCD.tg = normalize(normalize(mesh->curve_keys[min(ck + 1, ckey_num - 1)].loc - mesh->curve_keys[ck].loc) -
+					normalize(mesh->curve_keys[max(ck - 1, 0)].loc - mesh->curve_keys[ck].loc));
+				mesh->curve_keysCD.push_back(SCD);
+			}
+		}
+	}
+
+
+	delete CData;
+
+	}
+
+	mesh->compute_bounds();
+
+}
+
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index c9748756d43..e9250ec3eff 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -376,7 +376,7 @@ static void create_subd_mesh(Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, con
 
 /* Sync */
 
-Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated)
+Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tris)
 {
 	/* test if we can instance or if the object is modified */
 	BL::ID b_ob_data = b_ob.data();
@@ -435,16 +435,24 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated)
 	PointerRNA cmesh = RNA_pointer_get(&b_ob_data.ptr, "cycles");
 
 	vector oldtriangle = mesh->triangles;
+	
+	/* compares curve_keys rather than strands in order to handle quick hair adjustsments in dynamic BVH - other methods could probably do this better*/
+	vector oldcurve_keys = mesh->curve_keys;
 
 	mesh->clear();
 	mesh->used_shaders = used_shaders;
 	mesh->name = ustring(b_ob_data.name().c_str());
 
 	if(b_mesh) {
-		if(cmesh.data && experimental && RNA_boolean_get(&cmesh, "use_subdivision"))
-			create_subd_mesh(mesh, b_mesh, &cmesh, used_shaders);
-		else
-			create_mesh(scene, mesh, b_mesh, used_shaders);
+		if(!(hide_tris && experimental && is_cpu)) {
+			if(cmesh.data && experimental && RNA_boolean_get(&cmesh, "use_subdivision"))
+				create_subd_mesh(mesh, b_mesh, &cmesh, used_shaders);
+			else
+				create_mesh(scene, mesh, b_mesh, used_shaders);
+		}
+
+		if(experimental && is_cpu)
+			sync_curves(mesh, b_mesh, b_ob, object_updated);
 
 		/* free derived mesh */
 		b_data.meshes.remove(b_mesh);
@@ -471,6 +479,13 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated)
 		if(memcmp(&oldtriangle[0], &mesh->triangles[0], sizeof(Mesh::Triangle)*oldtriangle.size()) != 0)
 			rebuild = true;
 	}
+
+	if(oldcurve_keys.size() != mesh->curve_keys.size())
+		rebuild = true;
+	else if(oldcurve_keys.size()) {
+		if(memcmp(&oldcurve_keys[0], &mesh->curve_keys[0], sizeof(Mesh::CurveKey)*oldcurve_keys.size()) != 0)
+			rebuild = true;
+	}
 	
 	mesh->tag_update(scene, rebuild);
 
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index 38f27bcf2af..ad701266c5b 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -196,7 +196,7 @@ void BlenderSync::sync_background_light()
 
 /* Object */
 
-Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_ob, Transform& tfm, uint layer_flag, int motion)
+Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_ob, Transform& tfm, uint layer_flag, int motion, bool hide_tris)
 {
 	BL::Object b_ob = (b_dupli_ob ? b_dupli_ob.object() : b_parent);
 	
@@ -247,7 +247,7 @@ Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_P
 	bool use_holdout = (layer_flag & render_layer.holdout_layer) != 0;
 	
 	/* mesh sync */
-	object->mesh = sync_mesh(b_ob, object_updated);
+	object->mesh = sync_mesh(b_ob, object_updated, hide_tris);
 
 	/* sspecial case not tracked by object update flags */
 	if(use_holdout != object->use_holdout) {
@@ -390,7 +390,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion)
 							BL::Array persistent_id = b_dup->persistent_id();
 
 							/* sync object and mesh or light data */
-							Object *object = sync_object(*b_ob, persistent_id.data, *b_dup, tfm, ob_layer, motion);
+							Object *object = sync_object(*b_ob, persistent_id.data, *b_dup, tfm, ob_layer, motion, false);
 
 							/* sync possible particle data, note particle_id
 							 * starts counting at 1, first is dummy particle */
@@ -412,9 +412,23 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion)
 				/* check if we should render or hide particle emitter */
 				BL::Object::particle_systems_iterator b_psys;
 
-				for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys)
-					if(b_psys->settings().use_render_emitter())
+				bool hair_present = false;
+				bool show_emitter = false;
+				bool hide_tris = false;
+
+				for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) {
+
+					if((b_psys->settings().render_type()==BL::ParticleSettings::render_type_PATH)&&(b_psys->settings().type()==BL::ParticleSettings::type_HAIR))
+						hair_present = true;
+
+					if(b_psys->settings().use_render_emitter()) {
 						hide = false;
+						show_emitter = true;
+					}
+				}
+
+				if(hair_present && !show_emitter)
+					hide_tris = true;
 
 				/* hide original object for duplis */
 				BL::Object parent = b_ob->parent();
@@ -424,7 +438,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion)
 				if(!hide) {
 					/* object itself */
 					Transform tfm = get_transform(b_ob->matrix_world());
-					sync_object(*b_ob, NULL, PointerRNA_NULL, tfm, ob_layer, motion);
+					sync_object(*b_ob, NULL, PointerRNA_NULL, tfm, ob_layer, motion, hide_tris);
 				}
 			}
 
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index b8ed942f5b6..cd31a5b5bb6 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -96,7 +96,7 @@ void BlenderSession::create_session()
 	session->set_pause(BlenderSync::get_session_pause(b_scene, background));
 
 	/* create sync */
-	sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress);
+	sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress, session_params.device.type == DEVICE_CPU);
 	sync->sync_data(b_v3d, b_engine.camera_override());
 
 	if(b_rv3d)
@@ -143,7 +143,7 @@ void BlenderSession::reset_session(BL::BlendData b_data_, BL::Scene b_scene_)
 	session->stats.mem_peak = session->stats.mem_used;
 
 	/* sync object should be re-created */
-	sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress);
+	sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress, session_params.device.type == DEVICE_CPU);
 	sync->sync_data(b_v3d, b_engine.camera_override());
 	sync->sync_camera(b_engine.camera_override(), width, height);
 
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index 848a9a199f9..ddbd7f935e4 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -447,6 +447,10 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
 			node = new ParticleInfoNode();
 			break;
 		}
+		case BL::ShaderNode::type_HAIR_INFO: {
+			node = new HairInfoNode();
+			break;
+		}
 		case BL::ShaderNode::type_BUMP: {
 			node = new BumpNode();
 			break;
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index d455bdbe8e2..b9860ca90f2 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -28,6 +28,7 @@
 #include "object.h"
 #include "scene.h"
 #include "shader.h"
+#include "curves.h"
 
 #include "device.h"
 
@@ -41,7 +42,7 @@ CCL_NAMESPACE_BEGIN
 
 /* Constructor */
 
-BlenderSync::BlenderSync(BL::RenderEngine b_engine_, BL::BlendData b_data_, BL::Scene b_scene_, Scene *scene_, bool preview_, Progress &progress_)
+BlenderSync::BlenderSync(BL::RenderEngine b_engine_, BL::BlendData b_data_, BL::Scene b_scene_, Scene *scene_, bool preview_, Progress &progress_, bool is_cpu_)
 : b_engine(b_engine_),
   b_data(b_data_), b_scene(b_scene_),
   shader_map(&scene_->shaders),
@@ -56,6 +57,7 @@ BlenderSync::BlenderSync(BL::RenderEngine b_engine_, BL::BlendData b_data_, BL::
 {
 	scene = scene_;
 	preview = preview_;
+	is_cpu = is_cpu_;
 }
 
 BlenderSync::~BlenderSync()
@@ -141,6 +143,7 @@ void BlenderSync::sync_data(BL::SpaceView3D b_v3d, BL::Object b_override, const
 	sync_integrator();
 	sync_film();
 	sync_shaders();
+	sync_curve_settings();
 	sync_objects(b_v3d);
 	sync_motion(b_v3d, b_override);
 }
diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h
index d3d21fbdf72..5050743f1cf 100644
--- a/intern/cycles/blender/blender_sync.h
+++ b/intern/cycles/blender/blender_sync.h
@@ -50,7 +50,7 @@ class ShaderNode;
 
 class BlenderSync {
 public:
-	BlenderSync(BL::RenderEngine b_engine_, BL::BlendData b_data, BL::Scene b_scene, Scene *scene_, bool preview_, Progress &progress_);
+	BlenderSync(BL::RenderEngine b_engine_, BL::BlendData b_data, BL::Scene b_scene, Scene *scene_, bool preview_, Progress &progress_, bool is_cpu_);
 	~BlenderSync();
 
 	/* sync */
@@ -78,10 +78,12 @@ private:
 	void sync_world(bool update_all);
 	void sync_render_layers(BL::SpaceView3D b_v3d, const char *layer);
 	void sync_shaders();
+	void sync_curve_settings();
 
 	void sync_nodes(Shader *shader, BL::ShaderNodeTree b_ntree);
-	Mesh *sync_mesh(BL::Object b_ob, bool object_updated);
-	Object *sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_object, Transform& tfm, uint layer_flag, int motion);
+	Mesh *sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tris);
+	void sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool object_updated);
+	Object *sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_object, Transform& tfm, uint layer_flag, int motion, bool hide_tris);
 	void sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm);
 	void sync_background_light();
 	void sync_mesh_motion(BL::Object b_ob, Mesh *mesh, int motion);
@@ -113,6 +115,7 @@ private:
 	Scene *scene;
 	bool preview;
 	bool experimental;
+	bool is_cpu;
 
 	struct RenderLayerInfo {
 		RenderLayerInfo()
diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp
index b58a34f9942..102414e4a3d 100644
--- a/intern/cycles/bvh/bvh.cpp
+++ b/intern/cycles/bvh/bvh.cpp
@@ -75,6 +75,10 @@ bool BVH::cache_read(CacheData& key)
 	foreach(Object *ob, objects) {
 		key.add(ob->mesh->verts);
 		key.add(ob->mesh->triangles);
+		key.add(ob->mesh->curve_keys);
+		key.add(ob->mesh->curve_keysCD);
+		key.add(ob->mesh->curve_segs);
+		key.add(ob->mesh->curve_attrib);
 		key.add(&ob->bounds, sizeof(ob->bounds));
 		key.add(&ob->visibility, sizeof(ob->visibility));
 		key.add(&ob->mesh->transform_applied, sizeof(bool));
@@ -91,6 +95,7 @@ bool BVH::cache_read(CacheData& key)
 		value.read(pack.nodes);
 		value.read(pack.object_node);
 		value.read(pack.tri_woop);
+		value.read(pack.prim_type);
 		value.read(pack.prim_visibility);
 		value.read(pack.prim_index);
 		value.read(pack.prim_object);
@@ -112,6 +117,7 @@ void BVH::cache_write(CacheData& key)
 	value.add(pack.nodes);
 	value.add(pack.object_node);
 	value.add(pack.tri_woop);
+	value.add(pack.prim_type);
 	value.add(pack.prim_visibility);
 	value.add(pack.prim_index);
 	value.add(pack.prim_object);
@@ -157,10 +163,11 @@ void BVH::build(Progress& progress)
 	}
 
 	/* build nodes */
+	vector prim_type;
 	vector prim_index;
 	vector prim_object;
 
-	BVHBuild bvh_build(objects, prim_index, prim_object, params, progress);
+	BVHBuild bvh_build(objects, prim_type, prim_index, prim_object, params, progress);
 	BVHNode *root = bvh_build.run();
 
 	if(progress.get_cancel()) {
@@ -169,6 +176,7 @@ void BVH::build(Progress& progress)
 	}
 
 	/* todo: get rid of this copy */
+	pack.prim_type = prim_type;
 	pack.prim_index = prim_index;
 	pack.prim_object = prim_object;
 
@@ -182,8 +190,8 @@ void BVH::build(Progress& progress)
 	}
 
 	/* pack triangles */
-	progress.set_substatus("Packing BVH triangles");
-	pack_triangles();
+	progress.set_substatus("Packing BVH triangles and strands");
+	pack_primitives();
 
 	if(progress.get_cancel()) {
 		root->deleteSubtree();
@@ -215,8 +223,8 @@ void BVH::build(Progress& progress)
 
 void BVH::refit(Progress& progress)
 {
-	progress.set_substatus("Packing BVH triangles");
-	pack_triangles();
+	progress.set_substatus("Packing BVH primitives");
+	pack_primitives();
 
 	if(progress.get_cancel()) return;
 
@@ -263,7 +271,50 @@ void BVH::pack_triangle(int idx, float4 woop[3])
 	}
 }
 
-void BVH::pack_triangles()
+/* Curves*/
+
+void BVH::pack_curve_seg(int idx, float4 woop[3])
+{
+	int tob = pack.prim_object[idx];
+	const Mesh *mesh = objects[tob]->mesh;
+	int tidx = pack.prim_index[idx];
+	float3 v0 = mesh->curve_keys[mesh->curve_segs[tidx].v[0]].loc;
+	float3 v1 = mesh->curve_keys[mesh->curve_segs[tidx].v[1]].loc;
+	float t0 = mesh->curve_keys[mesh->curve_segs[tidx].v[0]].time;
+	float t1 = mesh->curve_keys[mesh->curve_segs[tidx].v[1]].time;
+
+	float3 d0 = v1 - v0;
+	float l =  len(d0);
+	
+	float u = mesh->curve_attrib[mesh->curve_segs[tidx].curve].uv[0];
+	float v = mesh->curve_attrib[mesh->curve_segs[tidx].curve].uv[1];
+
+	/*Plan
+	*Transform tfm = make_transform(
+	*	location <3>    , l,
+	*	extra curve data <3>    , StrID,
+	*	nextkey, flags/tip?,    r, t);
+	*/
+	float3 tg1 = make_float3(1.0f,0.0f,0.0f);
+	float3 tg2 = make_float3(1.0f,0.0f,0.0f);
+	if(mesh->curve_keysCD.size()) {
+		tg1 = mesh->curve_keysCD[mesh->curve_segs[tidx].v[0]].tg;
+		tg2 = mesh->curve_keysCD[mesh->curve_segs[tidx].v[1]].tg;
+	}
+	
+	Transform tfm = make_transform(
+		tg1.x, tg1.y, tg1.z, l,
+		tg2.x, tg2.y, tg2.z, 0,
+		t0, t1, u, v,
+		0, 0, 0, 1);
+
+	woop[0] = tfm.x;
+	woop[1] = tfm.y;
+	woop[2] = tfm.z;
+
+}
+
+void BVH::pack_primitives()
 {
 	int nsize = TRI_NODE_SIZE;
 	size_t tidx_size = pack.prim_index.size();
@@ -277,7 +328,11 @@ void BVH::pack_triangles()
 		if(pack.prim_index[i] != -1) {
 			float4 woop[3];
 
-			pack_triangle(i, woop);
+			if(pack.prim_type[i])
+				pack_curve_seg(i, woop);
+			else
+				pack_triangle(i, woop);
+			
 			memcpy(&pack.tri_woop[i * nsize], woop, sizeof(float4)*3);
 
 			int tob = pack.prim_object[i];
@@ -300,11 +355,15 @@ void BVH::pack_instances(size_t nodes_size)
 	/* adjust primitive index to point to the triangle in the global array, for
 	 * meshes with transform applied and already in the top level BVH */
 	for(size_t i = 0; i < pack.prim_index.size(); i++)
-		if(pack.prim_index[i] != -1)
-			pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->tri_offset;
+		if(pack.prim_index[i] != -1) {
+			if(pack.prim_type[i])
+				pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->curveseg_offset;
+			else
+				pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->tri_offset;
+		}
 
 	/* track offsets of instanced BVH data in global array */
-	size_t tri_offset = pack.prim_index.size();
+	size_t prim_offset = pack.prim_index.size();
 	size_t nodes_offset = nodes_size;
 
 	/* clear array that gives the node indexes for instanced objects */
@@ -339,6 +398,7 @@ void BVH::pack_instances(size_t nodes_size)
 	mesh_map.clear();
 
 	pack.prim_index.resize(prim_index_size);
+	pack.prim_type.resize(prim_index_size);
 	pack.prim_object.resize(prim_index_size);
 	pack.prim_visibility.resize(prim_index_size);
 	pack.tri_woop.resize(tri_woop_size);
@@ -346,6 +406,7 @@ void BVH::pack_instances(size_t nodes_size)
 	pack.object_node.resize(objects.size());
 
 	int *pack_prim_index = (pack.prim_index.size())? &pack.prim_index[0]: NULL;
+	int *pack_prim_type = (pack.prim_type.size())? &pack.prim_type[0]: NULL;
 	int *pack_prim_object = (pack.prim_object.size())? &pack.prim_object[0]: NULL;
 	uint *pack_prim_visibility = (pack.prim_visibility.size())? &pack.prim_visibility[0]: NULL;
 	float4 *pack_tri_woop = (pack.tri_woop.size())? &pack.tri_woop[0]: NULL;
@@ -376,6 +437,7 @@ void BVH::pack_instances(size_t nodes_size)
 
 		int noffset = nodes_offset/nsize;
 		int mesh_tri_offset = mesh->tri_offset;
+		int mesh_curve_offset = mesh->curveseg_offset;
 
 		/* fill in node indexes for instances */
 		if((bvh->pack.is_leaf.size() != 0) && bvh->pack.is_leaf[0])
@@ -389,10 +451,16 @@ void BVH::pack_instances(size_t nodes_size)
 		if(bvh->pack.prim_index.size()) {
 			size_t bvh_prim_index_size = bvh->pack.prim_index.size();
 			int *bvh_prim_index = &bvh->pack.prim_index[0];
+			int *bvh_prim_type = &bvh->pack.prim_type[0];
 			uint *bvh_prim_visibility = &bvh->pack.prim_visibility[0];
 
 			for(size_t i = 0; i < bvh_prim_index_size; i++) {
-				pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_tri_offset;
+				if(bvh->pack.prim_type[i])
+					pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_curve_offset;
+				else
+					pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_tri_offset;
+
+				pack_prim_type[pack_prim_index_offset] = bvh_prim_type[i];
 				pack_prim_visibility[pack_prim_index_offset] = bvh_prim_visibility[i];
 				pack_prim_object[pack_prim_index_offset] = 0;  // unused for instances
 				pack_prim_index_offset++;
@@ -401,7 +469,7 @@ void BVH::pack_instances(size_t nodes_size)
 
 		/* merge triangle intersection data */
 		if(bvh->pack.tri_woop.size()) {
-			memcpy(pack_tri_woop+pack_tri_woop_offset, &bvh->pack.tri_woop[0],
+			memcpy(pack_tri_woop + pack_tri_woop_offset, &bvh->pack.tri_woop[0],
 				bvh->pack.tri_woop.size()*sizeof(float4));
 			pack_tri_woop_offset += bvh->pack.tri_woop.size();
 		}
@@ -420,8 +488,8 @@ void BVH::pack_instances(size_t nodes_size)
 				int4 data = bvh_nodes[i + nsize_bbox];
 
 				if(bvh_is_leaf && bvh_is_leaf[j]) {
-					data.x += tri_offset;
-					data.y += tri_offset;
+					data.x += prim_offset;
+					data.y += prim_offset;
 				}
 				else {
 					data.x += (data.x < 0)? -noffset: noffset;
@@ -443,7 +511,7 @@ void BVH::pack_instances(size_t nodes_size)
 		}
 
 		nodes_offset += bvh->pack.nodes.size();
-		tri_offset += bvh->pack.prim_index.size();
+		prim_offset += bvh->pack.prim_index.size();
 	}
 }
 
@@ -544,25 +612,37 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility
 
 	if(leaf) {
 		/* refit leaf node */
-		for(int tri = c0; tri < c1; tri++) {
-			int tidx = pack.prim_index[tri];
-			int tob = pack.prim_object[tri];
+		for(int prim = c0; prim < c1; prim++) {
+			int pidx = pack.prim_index[prim];
+			int tob = pack.prim_object[prim];
 			Object *ob = objects[tob];
 
-			if(tidx == -1) {
+			if(pidx == -1) {
 				/* object instance */
 				bbox.grow(ob->bounds);
 			}
 			else {
-				/* triangles */
+				/* primitives */
 				const Mesh *mesh = ob->mesh;
-				int tri_offset = (params.top_level)? mesh->tri_offset: 0;
-				const int *vidx = mesh->triangles[tidx - tri_offset].v;
-				const float3 *vpos = &mesh->verts[0];
 
-				bbox.grow(vpos[vidx[0]]);
-				bbox.grow(vpos[vidx[1]]);
-				bbox.grow(vpos[vidx[2]]);
+				if(pack.prim_type[prim]) {
+					/* strands */
+					int str_offset = (params.top_level)? mesh->curveseg_offset: 0;
+					const int *hidx = mesh->curve_segs[pidx - str_offset].v;
+
+					bbox.grow(mesh->curve_keys[hidx[0]].loc, mesh->curve_keys[hidx[0]].radius);
+					bbox.grow(mesh->curve_keys[hidx[1]].loc, mesh->curve_keys[hidx[1]].radius);
+				}
+				else {
+					/* triangles */
+					int tri_offset = (params.top_level)? mesh->tri_offset: 0;
+					const int *vidx = mesh->triangles[pidx - tri_offset].v;
+					const float3 *vpos = &mesh->verts[0];
+
+					bbox.grow(vpos[vidx[0]]);
+					bbox.grow(vpos[vidx[1]]);
+					bbox.grow(vpos[vidx[2]]);
+				}
 			}
 
 			visibility |= ob->visibility;
diff --git a/intern/cycles/bvh/bvh.h b/intern/cycles/bvh/bvh.h
index 549f1e3ac1d..d81bb312148 100644
--- a/intern/cycles/bvh/bvh.h
+++ b/intern/cycles/bvh/bvh.h
@@ -51,7 +51,9 @@ struct PackedBVH {
 	/* object index to BVH node index mapping for instances */
 	array object_node; 
 	/* precomputed triangle intersection data, one triangle is 4x float4 */
-	array tri_woop; 
+	array tri_woop;
+	/* primitive type - triangle or strand (should be moved to flag?) */
+	array prim_type;
 	/* visibility visibilitys for primitives */
 	array prim_visibility;
 	/* mapping from BVH primitive index to true primitive index, as primitives
@@ -101,9 +103,10 @@ protected:
 	bool cache_read(CacheData& key);
 	void cache_write(CacheData& key);
 
-	/* triangles */
-	void pack_triangles();
+	/* triangles and strands*/
+	void pack_primitives();
 	void pack_triangle(int idx, float4 woop[3]);
+	void pack_curve_seg(int idx, float4 woop[3]);
 
 	/* merge instance BVH's */
 	void pack_instances(size_t nodes_size);
diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp
index 705b805a3a9..cdd94324f53 100644
--- a/intern/cycles/bvh/bvh_build.cpp
+++ b/intern/cycles/bvh/bvh_build.cpp
@@ -48,9 +48,10 @@ public:
 /* Constructor / Destructor */
 
 BVHBuild::BVHBuild(const vector& objects_,
-	vector& prim_index_, vector& prim_object_,
+	vector& prim_type_, vector& prim_index_, vector& prim_object_,
 	const BVHParams& params_, Progress& progress_)
 : objects(objects_),
+  prim_type(prim_type_),
   prim_index(prim_index_),
   prim_object(prim_object_),
   params(params_),
@@ -78,7 +79,23 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh,
 		}
 
 		if(bounds.valid()) {
-			references.push_back(BVHReference(bounds, j, i));
+			references.push_back(BVHReference(bounds, j, i, false));
+			root.grow(bounds);
+			center.grow(bounds.center2());
+		}
+	}
+
+	for(uint j = 0; j < mesh->curve_segs.size(); j++) {
+		Mesh::CurveSeg s = mesh->curve_segs[j];
+		BoundBox bounds = BoundBox::empty;
+
+		for(int k = 0; k < 2; k++) {
+			float3 pt = mesh->curve_keys[s.v[k]].loc;
+			bounds.grow(pt, mesh->curve_keys[s.v[k]].radius);
+		}
+
+		if(bounds.valid()) {
+			references.push_back(BVHReference(bounds, j, i, true));
 			root.grow(bounds);
 			center.grow(bounds.center2());
 		}
@@ -87,7 +104,7 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh,
 
 void BVHBuild::add_reference_object(BoundBox& root, BoundBox& center, Object *ob, int i)
 {
-	references.push_back(BVHReference(ob->bounds, -1, i));
+	references.push_back(BVHReference(ob->bounds, -1, i, false));
 	root.grow(ob->bounds);
 	center.grow(ob->bounds.center2());
 }
@@ -99,13 +116,17 @@ void BVHBuild::add_references(BVHRange& root)
 
 	foreach(Object *ob, objects) {
 		if(params.top_level) {
-			if(ob->mesh->transform_applied)
+			if(ob->mesh->transform_applied) {
 				num_alloc_references += ob->mesh->triangles.size();
+				num_alloc_references += ob->mesh->curve_segs.size();
+			}
 			else
 				num_alloc_references++;
 		}
-		else
+		else {
 			num_alloc_references += ob->mesh->triangles.size();
+			num_alloc_references += ob->mesh->curve_segs.size();
+		}
 	}
 
 	references.reserve(num_alloc_references);
@@ -162,6 +183,7 @@ BVHNode* BVHBuild::run()
 	progress_total = references.size();
 	progress_original_total = progress_total;
 
+	prim_type.resize(references.size());
 	prim_index.resize(references.size());
 	prim_object.resize(references.size());
 
@@ -319,10 +341,12 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start,
 		if(start == prim_index.size()) {
 			assert(params.use_spatial_split);
 
+			prim_type.push_back(ref->prim_type());
 			prim_index.push_back(ref->prim_index());
 			prim_object.push_back(ref->prim_object());
 		}
 		else {
+			prim_type[start] = ref->prim_type();
 			prim_index[start] = ref->prim_index();
 			prim_object[start] = ref->prim_object();
 		}
@@ -345,6 +369,7 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start,
 
 BVHNode* BVHBuild::create_leaf_node(const BVHRange& range)
 {
+	vector& p_type = prim_type;
 	vector& p_index = prim_index;
 	vector& p_object = prim_object;
 	BoundBox bounds = BoundBox::empty;
@@ -358,10 +383,12 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range)
 			if(range.start() + num == prim_index.size()) {
 				assert(params.use_spatial_split);
 
+				p_type.push_back(ref.prim_type());
 				p_index.push_back(ref.prim_index());
 				p_object.push_back(ref.prim_object());
 			}
 			else {
+				p_type[range.start() + num] = ref.prim_type();
 				p_index[range.start() + num] = ref.prim_index();
 				p_object[range.start() + num] = ref.prim_object();
 			}
diff --git a/intern/cycles/bvh/bvh_build.h b/intern/cycles/bvh/bvh_build.h
index 44ef918b326..ba10eb49412 100644
--- a/intern/cycles/bvh/bvh_build.h
+++ b/intern/cycles/bvh/bvh_build.h
@@ -44,6 +44,7 @@ public:
 	/* Constructor/Destructor */
 	BVHBuild(
 		const vector& objects,
+		vector& prim_type,
 		vector& prim_index,
 		vector& prim_object,
 		const BVHParams& params,
@@ -87,6 +88,7 @@ protected:
 	int num_original_references;
 
 	/* output primitive indexes and objects */
+	vector& prim_type;
 	vector& prim_index;
 	vector& prim_object;
 
diff --git a/intern/cycles/bvh/bvh_params.h b/intern/cycles/bvh/bvh_params.h
index a78496d841d..7a1555ae548 100644
--- a/intern/cycles/bvh/bvh_params.h
+++ b/intern/cycles/bvh/bvh_params.h
@@ -98,19 +98,22 @@ class BVHReference
 public:
 	__forceinline BVHReference() {}
 
-	__forceinline BVHReference(const BoundBox& bounds_, int prim_index_, int prim_object_)
+	__forceinline BVHReference(const BoundBox& bounds_, int prim_index_, int prim_object_, int prim_type)
 	: rbounds(bounds_)
 	{
 		rbounds.min.w = __int_as_float(prim_index_);
 		rbounds.max.w = __int_as_float(prim_object_);
+		type = prim_type;
 	}
 
 	__forceinline const BoundBox& bounds() const { return rbounds; }
 	__forceinline int prim_index() const { return __float_as_int(rbounds.min.w); }
 	__forceinline int prim_object() const { return __float_as_int(rbounds.max.w); }
+	__forceinline int prim_type() const { return type; }
 
 protected:
 	BoundBox rbounds;
+	uint type;
 };
 
 /* BVH Range
diff --git a/intern/cycles/bvh/bvh_sort.cpp b/intern/cycles/bvh/bvh_sort.cpp
index bef384be592..9a8961c8b15 100644
--- a/intern/cycles/bvh/bvh_sort.cpp
+++ b/intern/cycles/bvh/bvh_sort.cpp
@@ -43,6 +43,8 @@ public:
 		else if(ra.prim_object() > rb.prim_object()) return false;
 		else if(ra.prim_index() < rb.prim_index()) return true;
 		else if(ra.prim_index() > rb.prim_index()) return false;
+		else if(ra.prim_type() < rb.prim_type()) return true;
+		else if(ra.prim_type() > rb.prim_type()) return false;
 
 		return false;
 	}
diff --git a/intern/cycles/bvh/bvh_split.cpp b/intern/cycles/bvh/bvh_split.cpp
index 263c5834428..860e2c8d7df 100644
--- a/intern/cycles/bvh/bvh_split.cpp
+++ b/intern/cycles/bvh/bvh_split.cpp
@@ -252,14 +252,41 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH
 	/* loop over vertices/edges. */
 	Object *ob = builder->objects[ref.prim_object()];
 	const Mesh *mesh = ob->mesh;
-	const int *inds = mesh->triangles[ref.prim_index()].v;
-	const float3 *verts = &mesh->verts[0];
-	const float3* v1 = &verts[inds[2]];
-
-	for(int i = 0; i < 3; i++) {
-		const float3* v0 = v1;
-		int vindex = inds[i];
-		v1 = &verts[vindex];
+
+	if (!ref.prim_type()) {
+		const int *inds = mesh->triangles[ref.prim_index()].v;
+		const float3 *verts = &mesh->verts[0];
+		const float3* v1 = &verts[inds[2]];
+
+		for(int i = 0; i < 3; i++) {
+			const float3* v0 = v1;
+			int vindex = inds[i];
+			v1 = &verts[vindex];
+			float v0p = (*v0)[dim];
+			float v1p = (*v1)[dim];
+
+			/* insert vertex to the boxes it belongs to. */
+			if(v0p <= pos)
+				left_bounds.grow(*v0);
+
+			if(v0p >= pos)
+				right_bounds.grow(*v0);
+
+			/* edge intersects the plane => insert intersection to both boxes. */
+			if((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) {
+				float3 t = lerp(*v0, *v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f));
+				left_bounds.grow(t);
+				right_bounds.grow(t);
+			}
+		}
+	}
+	else {
+		/* Strand split: NOTE - Currently ignores strand width and needs to be fixed.*/
+
+		const int *inds = mesh->curve_segs[ref.prim_index()].v;
+		const float3* v0 = &mesh->curve_keys[inds[0]].loc;
+		const float3* v1 = &mesh->curve_keys[inds[1]].loc;
+
 		float v0p = (*v0)[dim];
 		float v1p = (*v1)[dim];
 
@@ -270,6 +297,12 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH
 		if(v0p >= pos)
 			right_bounds.grow(*v0);
 
+		if(v1p <= pos)
+			left_bounds.grow(*v1);
+
+		if(v1p >= pos)
+			right_bounds.grow(*v1);
+
 		/* edge intersects the plane => insert intersection to both boxes. */
 		if((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) {
 			float3 t = lerp(*v0, *v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f));
@@ -284,9 +317,9 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH
 	left_bounds.intersect(ref.bounds());
 	right_bounds.intersect(ref.bounds());
 
-	/* set referecnes */
-	left = BVHReference(left_bounds, ref.prim_index(), ref.prim_object());
-	right = BVHReference(right_bounds, ref.prim_index(), ref.prim_object());
+	/* set references */
+	left = BVHReference(left_bounds, ref.prim_index(), ref.prim_object(), ref.prim_type());
+	right = BVHReference(right_bounds, ref.prim_index(), ref.prim_object(), ref.prim_type());
 }
 
 CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_bvh.h b/intern/cycles/kernel/kernel_bvh.h
index 73e7fb0e5d6..15af35a05f8 100644
--- a/intern/cycles/kernel/kernel_bvh.h
+++ b/intern/cycles/kernel/kernel_bvh.h
@@ -205,6 +205,151 @@ __device_inline void bvh_triangle_intersect(KernelGlobals *kg, Intersection *ise
 	}
 }
 
+#ifdef __HAIR__
+__device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect,
+	float3 P, float3 idir, uint visibility, int object, int triAddr)
+{
+	/* curve Intersection check */
+	
+	int flags = kernel_data.curve_kernel_data.curveflags;
+
+	int prim = kernel_tex_fetch(__prim_index, triAddr);
+	float4 v00 = kernel_tex_fetch(__cur_segs, prim);
+
+	int v1 = __float_as_int(v00.x);
+	int v2 = __float_as_int(v00.y);
+
+	float4 P1 = kernel_tex_fetch(__cur_keys, v1);
+	float4 P2 = kernel_tex_fetch(__cur_keys, v2);
+
+	float l = v00.w;
+	float r1 = P1.w;
+	float r2 = P2.w;
+	float mr = max(r1,r2);
+	float3 p1 = float4_to_float3(P1);
+	float3 p2 = float4_to_float3(P2);
+	float3 dif = P - p1;
+	float3 dir = 1.0f/idir;
+
+	/* test bounding sphere intersection (introduce circular artifacts)*/
+	/*float3 bvector = 0.5f * (p1 + p2) - P;
+	float bvectorl_sq = len_squared(bvector);
+	float dot_bv_dir = dot(bvector,dir);
+	float maxdist = l * 0.5f + mr;
+	if(bvectorl_sq - dot_bv_dir * dot_bv_dir > maxdist * maxdist)
+		return;*/
+
+	/* obtain parameters and test midpoint distance for suitable modes*/
+	float3 tg = (p2 - p1) / l;
+	float gd = (r2 - r1) / l;
+	float dirz = dot(dir,tg);
+	float difz = dot(dif,tg);
+
+	float a = 1.0f - (dirz*dirz*(1 + gd*gd));
+	float halfb = (dot(dir,dif) - dirz*(difz + gd*(difz*gd + r1)));
+
+	float tcentre = -halfb/a;
+	float zcentre = difz + (dirz * tcentre);
+
+	if((tcentre > isect->t) && !(flags & CURVE_KN_ACCURATE))
+		return;
+	if((zcentre < 0 || zcentre > l) && !(flags & CURVE_KN_ACCURATE) && !(flags & CURVE_KN_INTERSECTCORRECTION))
+		return;
+
+	/* test minimum separation*/
+	float3 cprod = cross(tg, dir);
+	float3 cprod2 = cross(tg, dif);
+	float cprodsq = len_squared(cprod);
+	float cprod2sq = len_squared(cprod2);
+	float distscaled = dot(cprod,dif);
+
+	if(cprodsq == 0)
+		distscaled = cprod2sq;
+	else
+		distscaled = (distscaled*distscaled)/cprodsq;
+
+	if(distscaled > mr*mr)
+		return;
+
+	/* calculate true intersection*/
+	float3 tdif = P - p1 + tcentre * dir;
+	float tdifz = dot(tdif,tg);
+	float tb = 2*(dot(dir,tdif) - dirz*(tdifz + gd*(tdifz*gd + r1)));
+	float tc = dot(tdif,tdif) - tdifz * tdifz * (1 + gd*gd) - r1*r1 - 2*r1*tdifz*gd;
+	float td = tb*tb - 4*a*tc;
+
+	if (td<0)
+		return;
+
+	float rootd = 0.0f;
+	float correction = 0.0f;
+	if(flags & CURVE_KN_ACCURATE) {
+		rootd = sqrtf(td);
+		correction = ((-tb - rootd)/(2*a));
+	}
+
+	float t = tcentre + correction;
+
+	if(t < isect->t) {
+
+		if(flags & CURVE_KN_INTERSECTCORRECTION) {
+			rootd = sqrtf(td);
+			correction = ((-tb - rootd)/(2*a));
+			t = tcentre + correction;
+		}
+
+		float z = zcentre + (dirz * correction);
+		bool backface = false;
+
+		if(flags & CURVE_KN_BACKFACING && (t < 0.0f || z < 0 || z > l)) {
+			backface = true;
+			correction = ((-tb + rootd)/(2*a));
+			t = tcentre + correction;
+			z = zcentre + (dirz * correction);
+		}
+
+		if(t > 0.0f && t < isect->t && z >= 0 && z <= l) {
+
+			if (flags & CURVE_KN_ENCLOSEFILTER) {
+
+				float enc_ratio = kernel_data.curve_kernel_data.encasing_ratio;
+				if((dot(P - p1, tg) > -r1 * enc_ratio) && (dot(P - p2, tg) < r2 * enc_ratio)) {
+					float a2 = 1.0f - (dirz*dirz*(1 + gd*gd*enc_ratio*enc_ratio));
+					float c2 = dot(dif,dif) - difz * difz * (1 + gd*gd*enc_ratio*enc_ratio) - r1*r1*enc_ratio*enc_ratio - 2*r1*difz*gd*enc_ratio;
+					if(a2*c2 < 0.0f)
+						return;
+				}
+			}
+
+			/*remove overlap - not functional yet*/
+			/*if (flags & CURVE_KN_CURVEDATA) {
+				float3 tg1 = float4_to_float3(kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+0));
+				float3 tg2 = float4_to_float3(kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+1));
+				if((dot(P + t * dir - p1, tg1) < 0.0f) || (dot(P + t * dir - p2, tg2) > 0.0f))
+					return;
+			}*/
+
+	#ifdef __VISIBILITY_FLAG__
+			/* visibility flag test. we do it here under the assumption
+			 * that most triangles are culled by node flags */
+			if(kernel_tex_fetch(__prim_visibility, triAddr) & visibility)
+	#endif
+			{
+				/* record intersection */
+				isect->prim = triAddr;
+				isect->object = object;
+				isect->u = z/l;
+				isect->v = td/(4*a*a);
+				isect->t = t;
+
+				if(backface) 
+					isect->u = -isect->u;
+			}
+		}
+	}
+}
+#endif
+
 __device_inline bool bvh_intersect(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect)
 {
 	/* traversal stack in CUDA thread-local memory */
@@ -281,10 +426,15 @@ __device_inline bool bvh_intersect(KernelGlobals *kg, const Ray *ray, const uint
 					nodeAddr = traversalStack[stackPtr];
 					--stackPtr;
 
-					/* triangle intersection */
+					/* primitive intersection */
 					while(primAddr < primAddr2) {
-						/* intersect ray against triangle */
-						bvh_triangle_intersect(kg, isect, P, idir, visibility, object, primAddr);
+						/* intersect ray against primitive */
+#ifdef __HAIR__
+						if(kernel_tex_fetch(__prim_type, primAddr))
+							bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr);
+						else
+#endif
+							bvh_triangle_intersect(kg, isect, P, idir, visibility, object, primAddr);
 
 						/* shadow ray early termination */
 						if(visibility == PATH_RAY_SHADOW_OPAQUE && isect->prim != ~0)
@@ -401,10 +551,15 @@ __device_inline bool bvh_intersect_motion(KernelGlobals *kg, const Ray *ray, con
 					nodeAddr = traversalStack[stackPtr];
 					--stackPtr;
 
-					/* triangle intersection */
+					/* primitive intersection */
 					while(primAddr < primAddr2) {
-						/* intersect ray against triangle */
-						bvh_triangle_intersect(kg, isect, P, idir, visibility, object, primAddr);
+						/* intersect ray against primitive */
+#ifdef __HAIR__
+						if(kernel_tex_fetch(__prim_type, primAddr))
+							bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr);
+						else
+#endif
+							bvh_triangle_intersect(kg, isect, P, idir, visibility, object, primAddr);
 
 						/* shadow ray early termination */
 						if(visibility == PATH_RAY_SHADOW_OPAQUE && isect->prim != ~0)
@@ -545,5 +700,105 @@ __device_inline float3 bvh_triangle_refine(KernelGlobals *kg, ShaderData *sd, co
 #endif
 }
 
+#ifdef __HAIR__
+__device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray, float t)
+{
+	int flag = kernel_data.curve_kernel_data.curveflags;
+	float3 P = ray->P;
+	float3 D = ray->D;
+
+	if(isect->object != ~0) {
+#ifdef __OBJECT_MOTION__
+		Transform tfm = sd->ob_itfm;
+#else
+		Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
+#endif
+
+		P = transform_point(&tfm, P);
+		D = transform_direction(&tfm, D*t);
+		D = normalize_len(D, &t);
+	}
+
+	int prim = kernel_tex_fetch(__prim_index, isect->prim);
+	float4 v00 = kernel_tex_fetch(__cur_segs, prim);
+
+	int v1 = __float_as_int(v00.x);
+	int v2 = __float_as_int(v00.y);
+
+	float4 P1 = kernel_tex_fetch(__cur_keys, v1);
+	float4 P2 = kernel_tex_fetch(__cur_keys, v2);
+	float l = v00.w;
+	float r1 = P1.w;
+	float r2 = P2.w;
+	float3 tg = float4_to_float3(P2 - P1) / l;
+	float3 dif = P - float4_to_float3(P1) + t * D;
+	float gd = ((r2 - r1)/l);
+
+	P = P + D*t;
+
+	dif = P - float4_to_float3(P1);
+
+	#ifdef __UV__
+	sd->u = dot(dif,tg)/l;
+	sd->v = 0.0f;
+	#endif
+
+	if (flag & CURVE_KN_TRUETANGENTGNORMAL) {
+		sd->Ng = -(D - tg * (dot(tg,D) * kernel_data.curve_kernel_data.normalmix));
+		sd->Ng = normalize(sd->Ng);
+		if (flag & CURVE_KN_NORMALCORRECTION)
+		{
+			//sd->Ng = normalize(sd->Ng);
+			sd->Ng = sd->Ng - gd * tg;
+			sd->Ng = normalize(sd->Ng);
+		}
+	}
+	else {
+		sd->Ng = (dif - tg * sd->u * l) / (P1.w + sd->u * l * gd);
+		if (gd != 0.0f) {
+			sd->Ng = sd->Ng - gd * tg ;
+			sd->Ng = normalize(sd->Ng);
+		}
+	}
+
+	sd->N = sd->Ng;
+
+	if (flag & CURVE_KN_TANGENTGNORMAL && !(flag & CURVE_KN_TRUETANGENTGNORMAL)) {
+		sd->N = -(D - tg * (dot(tg,D) * kernel_data.curve_kernel_data.normalmix));
+		sd->N = normalize(sd->N);
+		if (flag & CURVE_KN_NORMALCORRECTION) {
+			//sd->N = normalize(sd->N);
+			sd->N = sd->N - gd * tg;
+			sd->N = normalize(sd->N);
+		}
+	}
+	if (!(flag & CURVE_KN_TANGENTGNORMAL) && flag & CURVE_KN_TRUETANGENTGNORMAL) {
+		sd->N = (dif - tg * sd->u * l) / (P1.w + sd->u * l * gd);
+		if (gd != 0.0f) {
+			sd->N = sd->N - gd * tg ;
+			sd->N = normalize(sd->N);
+		}
+	}
+
+	#ifdef __DPDU__
+	/* dPdu/dPdv */
+	sd->dPdu = tg;
+	sd->dPdv = cross(tg,sd->Ng);
+	#endif
+
+	if(isect->object != ~0) {
+#ifdef __OBJECT_MOTION__
+		Transform tfm = sd->ob_tfm;
+#else
+		Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
+#endif
+
+		P = transform_point(&tfm, P);
+	}
+
+	return P;
+}
+#endif
+
 CCL_NAMESPACE_END
 
diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h
index e56633c9358..adf7e8eca82 100644
--- a/intern/cycles/kernel/kernel_emission.h
+++ b/intern/cycles/kernel/kernel_emission.h
@@ -47,7 +47,13 @@ __device float3 direct_emissive_eval(KernelGlobals *kg, float rando,
 	else
 #endif
 	{
-		shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, u, v, t, time);
+#ifdef __HAIR__
+		if(ls->type == LIGHT_STRAND)
+			shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, u, v, t, time, ls->prim);
+		else
+#endif
+			shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, u, v, t, time);
+
 		ls->Ng = sd.Ng;
 
 		/* no path flag, we're evaluating this for all closures. that's weak but
@@ -150,7 +156,11 @@ __device float3 indirect_emission(KernelGlobals *kg, ShaderData *sd, float t, in
 	/* evaluate emissive closure */
 	float3 L = shader_emissive_eval(kg, sd);
 
+#ifdef __HAIR__
+	if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_SAMPLE_AS_LIGHT) && (sd->curve_seg == ~0)) {
+#else
 	if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_SAMPLE_AS_LIGHT)) {
+#endif
 		/* multiple importance sampling, get triangle light pdf,
 		 * and compute weight with respect to BSDF pdf */
 		float pdf = triangle_light_pdf(kg, sd->Ng, sd->I, t);
diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h
index 97ae2d3db87..0f74ab75dd4 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -326,6 +326,59 @@ __device float triangle_light_pdf(KernelGlobals *kg,
 	return (t*t*kernel_data.integrator.pdf_triangles)/cos_pi;
 }
 
+#ifdef __HAIR__
+/* Strand Light */
+
+__device void curve_seg_light_sample(KernelGlobals *kg, int prim, int object,
+	float randu, float randv, float time, LightSample *ls)
+{
+	/* this strand code needs completion */
+	float4 v00 = kernel_tex_fetch(__cur_segs, prim);
+
+	int v1 = __float_as_int(v00.x);
+	int v2 = __float_as_int(v00.y);
+	float l = v00.w;
+
+	float4 P1 = kernel_tex_fetch(__cur_keys, v1);
+	float4 P2 = kernel_tex_fetch(__cur_keys, v2);
+	float r1 = P1.w;
+	float r2 = P2.w;
+	float3 tg = float4_to_float3(P2 - P1) / l;
+	float3 xc = make_float3(tg.x * tg.z, tg.y * tg.z, -(tg.x * tg.x + tg.y * tg.y));
+	if (dot(xc, xc) == 0.0f)
+		xc = make_float3(tg.x * tg.y, -(tg.x * tg.x + tg.z * tg.z), tg.z * tg.y);
+	xc = normalize(xc);
+	float3 yc = cross(tg, xc);
+	float gd = ((r2 - r1)/l);
+
+	/* normal currently ignores gradient */
+	ls->Ng = sinf(2 * M_PI_F * randv) * xc + cosf(2 * M_PI_F * randv) * yc;
+	ls->P = randu * l * tg + (gd * l + r1) * ls->Ng;
+	ls->object = object;
+	ls->prim = prim;
+	ls->t = 0.0f;
+	ls->type = LIGHT_STRAND;
+	ls->eval_fac = 1.0f;
+	ls->shader = __float_as_int(v00.z);
+
+#ifdef __INSTANCING__
+	/* instance transform */
+	if(ls->object >= 0) {
+#ifdef __OBJECT_MOTION__
+		Transform itfm;
+		Transform tfm = object_fetch_transform_motion_test(kg, object, time, &itfm);
+#else
+		Transform tfm = object_fetch_transform(kg, ls->object, OBJECT_TRANSFORM);
+		Transform itfm = object_fetch_transform(kg, ls->object, OBJECT_INVERSE_TRANSFORM);
+#endif
+
+		ls->P = transform_point(&tfm, ls->P);
+		ls->Ng = normalize(transform_direction(&tfm, ls->Ng));
+	}
+#endif
+}
+#endif
+
 /* Light Distribution */
 
 __device int light_distribution_sample(KernelGlobals *kg, float randt)
@@ -365,10 +418,19 @@ __device void light_sample(KernelGlobals *kg, float randt, float randu, float ra
 	/* fetch light data */
 	float4 l = kernel_tex_fetch(__light_distribution, index);
 	int prim = __float_as_int(l.y);
+#ifdef __HAIR__
+/* currently use l.z to indicate is strand sample which isn't ideal */
+	bool is_curve = __float_as_int(l.z) == 0.0f;
+#endif
 
 	if(prim >= 0) {
 		int object = __float_as_int(l.w);
-		triangle_light_sample(kg, prim, object, randu, randv, time, ls);
+#ifdef __HAIR__
+		if (is_curve)
+			curve_seg_light_sample(kg, prim, object, randu, randv, time, ls);
+		else
+#endif
+			triangle_light_sample(kg, prim, object, randu, randv, time, ls);
 	}
 	else {
 		int point = -prim-1;
diff --git a/intern/cycles/kernel/kernel_object.h b/intern/cycles/kernel/kernel_object.h
index 40aa4753daa..2260094aa70 100644
--- a/intern/cycles/kernel/kernel_object.h
+++ b/intern/cycles/kernel/kernel_object.h
@@ -288,5 +288,55 @@ __device float3 particle_angular_velocity(KernelGlobals *kg, int particle)
 	return make_float3(f3.z, f3.w, f4.x);
 }
 
+#ifdef __HAIR__
+/* Hair Info Node fns */
+
+__device float hair_radius(KernelGlobals *kg, int prim, float u)
+{	
+	float r = 0.0f;
+
+	if (prim != -1) {
+		float4 v00 = kernel_tex_fetch(__cur_segs, prim);
+
+		int v1 = __float_as_int(v00.x);
+		int v2 = __float_as_int(v00.y);
+
+		float4 P1 = kernel_tex_fetch(__cur_keys, v1);
+		float4 P2 = kernel_tex_fetch(__cur_keys, v2);
+		r = (P2.w - P1.w) * u + P1.w;
+	}
+
+	return r;
+}
+
+__device float3 hair_tangent_normal(KernelGlobals *kg, ShaderData *sd)
+{	
+	float3 tgN = make_float3(0.0f,0.0f,0.0f);
+
+	if (sd->curve_seg != ~0) {
+		tgN = -(-sd->I - sd->dPdu * (dot(sd->dPdu,-sd->I) * kernel_data.curve_kernel_data.normalmix / len_squared(sd->dPdu)));
+		tgN = normalize(tgN);
+		/*if (kernel_data.curve_kernel_data.use_tangent_normal_correction) need to find suitable scaled gd for corrected normal
+		{
+			tgN = normalize(tgN - gd * sd->dPdu);
+		}*/
+	}
+
+	return tgN;
+}
+
+__device float intercept(KernelGlobals *kg, int prim, int triAddr, float u)
+{	
+	float t = 0.0f;
+
+	if (prim != -1) {
+		float4 sd2 = kernel_tex_fetch(__tri_woop, triAddr*3+2);
+		t = (sd2.y - sd2.x) * u + sd2.x;
+	}
+
+	return t;
+}
+#endif
+
 CCL_NAMESPACE_END
 
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index 47b4d02e5bf..36cd21c1b48 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -56,24 +56,9 @@ __device_noinline void shader_setup_object_transforms(KernelGlobals *kg, ShaderD
 __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
 	const Intersection *isect, const Ray *ray)
 {
-	/* fetch triangle data */
-	int prim = kernel_tex_fetch(__prim_index, isect->prim);
-	float4 Ns = kernel_tex_fetch(__tri_normal, prim);
-	float3 Ng = make_float3(Ns.x, Ns.y, Ns.z);
-	int shader = __float_as_int(Ns.w);
-
-	/* triangle */
 #ifdef __INSTANCING__
 	sd->object = (isect->object == ~0)? kernel_tex_fetch(__prim_object, isect->prim): isect->object;
 #endif
-	sd->prim = prim;
-#ifdef __UV__
-	sd->u = isect->u;
-	sd->v = isect->v;
-#endif
-
-	sd->flag = kernel_tex_fetch(__shader_flag, (shader & SHADER_MASK)*2);
-	sd->flag |= kernel_tex_fetch(__object_flag, sd->object);
 
 	/* matrices and time */
 #ifdef __OBJECT_MOTION__
@@ -81,23 +66,64 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
 	sd->time = ray->time;
 #endif
 
-	/* vectors */
-	sd->P = bvh_triangle_refine(kg, sd, isect, ray);
-	sd->Ng = Ng;
-	sd->N = Ng;
-	sd->I = -ray->D;
-	sd->shader = shader;
+	sd->prim = kernel_tex_fetch(__prim_index, isect->prim);
+#ifdef __HAIR__
+	sd->curve_seg = ~0;
+#endif
 	sd->ray_length = isect->t;
 
-	/* smooth normal */
-	if(sd->shader & SHADER_SMOOTH_NORMAL)
-		sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
+#ifdef __HAIR__
+	if(kernel_tex_fetch(__prim_type, isect->prim)) {
+		/* Strand Shader setting*/
+		float4 CurSeg = kernel_tex_fetch(__cur_segs, sd->prim);
+		sd->shader = __float_as_int(CurSeg.z);
+
+		sd->curve_seg = sd->prim;
+		sd->prim = isect->prim;
+
+		float tcorr = isect->t;
+		if(kernel_data.curve_kernel_data.curveflags & CURVE_KN_POSTINTERSECTCORRECTION) {
+			tcorr = (isect->u < 0)? tcorr + sqrtf(isect->v) : tcorr - sqrtf(isect->v);
+			sd->ray_length = tcorr;
+		}
+		sd->P = bvh_curve_refine(kg, sd, isect, ray, tcorr);
+	}
+	else {
+#endif
+		/* fetch triangle data */
+		float4 Ns = kernel_tex_fetch(__tri_normal, sd->prim);
+		float3 Ng = make_float3(Ns.x, Ns.y, Ns.z);
+		sd->shader = __float_as_int(Ns.w);
+
+#ifdef __UV__
+		sd->u = isect->u;
+		sd->v = isect->v;
+#endif
+
+		/* vectors */
+		sd->P = bvh_triangle_refine(kg, sd, isect, ray);
+		sd->Ng = Ng;
+		sd->N = Ng;
+		
+
+		/* smooth normal */
+		if(sd->shader & SHADER_SMOOTH_NORMAL)
+			sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
 
 #ifdef __DPDU__
-	/* dPdu/dPdv */
-	triangle_dPdudv(kg, &sd->dPdu, &sd->dPdv, sd->prim);
+		/* dPdu/dPdv */
+		triangle_dPdudv(kg, &sd->dPdu, &sd->dPdv, sd->prim);
 #endif
 
+#ifdef __HAIR__
+	}
+#endif
+
+	sd->I = -ray->D;
+
+	sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2);
+	sd->flag |= kernel_tex_fetch(__object_flag, sd->object);
+
 #ifdef __INSTANCING__
 	if(isect->object != ~0) {
 		/* instance transform */
@@ -135,7 +161,7 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
 
 __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
 	const float3 P, const float3 Ng, const float3 I,
-	int shader, int object, int prim, float u, float v, float t, float time)
+	int shader, int object, int prim, float u, float v, float t, float time, int curve = ~0)
 {
 	/* vectors */
 	sd->P = P;
@@ -143,11 +169,15 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
 	sd->Ng = Ng;
 	sd->I = I;
 	sd->shader = shader;
+#ifdef __HAIR__
+	sd->curve_seg = curve;
+#endif
 
 	/* primitive */
 #ifdef __INSTANCING__
 	sd->object = object;
 #endif
+	/* currently no access to bvh prim index for strand sd->prim - this will cause errors with needs fixing*/
 	sd->prim = prim;
 #ifdef __UV__
 	sd->u = u;
@@ -183,8 +213,13 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
 #endif
 
 	/* smooth normal */
+#ifdef __HAIR__
+	if(sd->shader & SHADER_SMOOTH_NORMAL && sd->curve_seg == ~0) {
+		sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
+#else
 	if(sd->shader & SHADER_SMOOTH_NORMAL) {
 		sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
+#endif
 
 #ifdef __INSTANCING__
 		if(instanced)
@@ -194,10 +229,17 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
 
 #ifdef __DPDU__
 	/* dPdu/dPdv */
+#ifdef __HAIR__
+	if(sd->prim == ~0 || sd->curve_seg != ~0) {
+		sd->dPdu = make_float3(0.0f, 0.0f, 0.0f);
+		sd->dPdv = make_float3(0.0f, 0.0f, 0.0f);
+	}
+#else
 	if(sd->prim == ~0) {
 		sd->dPdu = make_float3(0.0f, 0.0f, 0.0f);
 		sd->dPdv = make_float3(0.0f, 0.0f, 0.0f);
 	}
+#endif
 	else {
 		triangle_dPdudv(kg, &sd->dPdu, &sd->dPdv, sd->prim);
 
@@ -279,6 +321,9 @@ __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData
 	sd->object = ~0;
 #endif
 	sd->prim = ~0;
+#ifdef __HAIR__
+	sd->curve_seg = ~0;
+#endif
 #ifdef __UV__
 	sd->u = 0.0f;
 	sd->v = 0.0f;
@@ -732,8 +777,20 @@ __device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd, Shader
 __device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect)
 {
 	int prim = kernel_tex_fetch(__prim_index, isect->prim);
-	float4 Ns = kernel_tex_fetch(__tri_normal, prim);
-	int shader = __float_as_int(Ns.w);
+	int shader = 0;
+
+#ifdef __HAIR__
+	if(!kernel_tex_fetch(__prim_type, isect->prim)) {
+#endif
+		float4 Ns = kernel_tex_fetch(__tri_normal, prim);
+		shader = __float_as_int(Ns.w);
+#ifdef __HAIR__
+	}
+	else {
+		float4 str = kernel_tex_fetch(__cur_segs, prim);
+		shader = __float_as_int(str.z);
+	}
+#endif
 	int flag = kernel_tex_fetch(__shader_flag, (shader & SHADER_MASK)*2);
 
 	return (flag & SD_HAS_SURFACE_TRANSPARENT) != 0;
diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h
index 29f6b3f072c..0b6107b398e 100644
--- a/intern/cycles/kernel/kernel_textures.h
+++ b/intern/cycles/kernel/kernel_textures.h
@@ -27,6 +27,7 @@
 /* bvh */
 KERNEL_TEX(float4, texture_float4, __bvh_nodes)
 KERNEL_TEX(float4, texture_float4, __tri_woop)
+KERNEL_TEX(uint, texture_uint, __prim_type)
 KERNEL_TEX(uint, texture_uint, __prim_visibility)
 KERNEL_TEX(uint, texture_uint, __prim_index)
 KERNEL_TEX(uint, texture_uint, __prim_object)
@@ -42,6 +43,10 @@ KERNEL_TEX(float4, texture_float4, __tri_vnormal)
 KERNEL_TEX(float4, texture_float4, __tri_vindex)
 KERNEL_TEX(float4, texture_float4, __tri_verts)
 
+/* curves */
+KERNEL_TEX(float4, texture_float4, __cur_segs)
+KERNEL_TEX(float4, texture_float4, __cur_keys)
+
 /* attributes */
 KERNEL_TEX(uint4, texture_uint4, __attributes_map)
 KERNEL_TEX(float, texture_float, __attributes_float)
diff --git a/intern/cycles/kernel/kernel_triangle.h b/intern/cycles/kernel/kernel_triangle.h
index 570ae52d6c2..1f2618d3507 100644
--- a/intern/cycles/kernel/kernel_triangle.h
+++ b/intern/cycles/kernel/kernel_triangle.h
@@ -106,88 +106,107 @@ __device_inline void triangle_dPdudv(KernelGlobals *kg, float3 *dPdu, float3 *dP
 
 __device float triangle_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
 {
-	if(elem == ATTR_ELEMENT_FACE) {
-		if(dx) *dx = 0.0f;
-		if(dy) *dy = 0.0f;
-
-		return kernel_tex_fetch(__attributes_float, offset + sd->prim);
-	}
-	else if(elem == ATTR_ELEMENT_VERTEX) {
-		float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, sd->prim));
-
-		float f0 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.x));
-		float f1 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.y));
-		float f2 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.z));
-
-#ifdef __RAY_DIFFERENTIALS__
-		if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
-		if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
-#endif
-
-		return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
-	}
-	else if(elem == ATTR_ELEMENT_CORNER) {
-		int tri = offset + sd->prim*3;
-		float f0 = kernel_tex_fetch(__attributes_float, tri + 0);
-		float f1 = kernel_tex_fetch(__attributes_float, tri + 1);
-		float f2 = kernel_tex_fetch(__attributes_float, tri + 2);
-
-#ifdef __RAY_DIFFERENTIALS__
-		if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
-		if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
+#ifdef __HAIR__
+	if(sd->curve_seg == ~0) {
 #endif
-
-		return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
+		if(elem == ATTR_ELEMENT_FACE) {
+			if(dx) *dx = 0.0f;
+			if(dy) *dy = 0.0f;
+
+			return kernel_tex_fetch(__attributes_float, offset + sd->prim);
+		}
+		else if(elem == ATTR_ELEMENT_VERTEX) {
+			float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, sd->prim));
+
+			float f0 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.x));
+			float f1 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.y));
+			float f2 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.z));
+
+	#ifdef __RAY_DIFFERENTIALS__
+			if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
+			if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
+	#endif
+
+			return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
+		}
+		else if(elem == ATTR_ELEMENT_CORNER) {
+			int tri = offset + sd->prim*3;
+			float f0 = kernel_tex_fetch(__attributes_float, tri + 0);
+			float f1 = kernel_tex_fetch(__attributes_float, tri + 1);
+			float f2 = kernel_tex_fetch(__attributes_float, tri + 2);
+
+	#ifdef __RAY_DIFFERENTIALS__
+			if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
+			if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
+	#endif
+
+			return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
+		}
+		else {
+			if(dx) *dx = 0.0f;
+			if(dy) *dy = 0.0f;
+
+			return 0.0f;
+		}
+#ifdef __HAIR__
 	}
 	else {
-		if(dx) *dx = 0.0f;
-		if(dy) *dy = 0.0f;
-
 		return 0.0f;
 	}
+#endif
 }
 
 __device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
 {
-	if(elem == ATTR_ELEMENT_FACE) {
-		if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
-		if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
-
-		return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + sd->prim));
-	}
-	else if(elem == ATTR_ELEMENT_VERTEX) {
-		float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, sd->prim));
-
-		float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.x)));
-		float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.y)));
-		float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.z)));
-
-#ifdef __RAY_DIFFERENTIALS__
-		if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
-		if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
+#ifdef __HAIR__
+	if(sd->curve_seg == ~0) {
 #endif
-
-		return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
-	}
-	else if(elem == ATTR_ELEMENT_CORNER) {
-		int tri = offset + sd->prim*3;
-		float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 0));
-		float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1));
-		float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2));
-
-#ifdef __RAY_DIFFERENTIALS__
-		if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
-		if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
-#endif
-
-		return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
+		if(elem == ATTR_ELEMENT_FACE) {
+			if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
+			if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
+
+			return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + sd->prim));
+		}
+		else if(elem == ATTR_ELEMENT_VERTEX) {
+			float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, sd->prim));
+
+			float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.x)));
+			float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.y)));
+			float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.z)));
+
+	#ifdef __RAY_DIFFERENTIALS__
+			if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
+			if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
+	#endif
+
+			return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
+		}
+		else if(elem == ATTR_ELEMENT_CORNER) {
+			int tri = offset + sd->prim*3;
+			float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 0));
+			float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1));
+			float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2));
+
+	#ifdef __RAY_DIFFERENTIALS__
+			if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
+			if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
+	#endif
+
+			return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
+		}
+		else {
+			if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
+			if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
+
+			return make_float3(0.0f, 0.0f, 0.0f);
+		}
+#ifdef __HAIR__
 	}
-	else {
-		if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
-		if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
-
+	else
+	{
 		return make_float3(0.0f, 0.0f, 0.0f);
 	}
+#endif
 }
 
 /* motion */
@@ -200,10 +219,16 @@ __device float4 triangle_motion_vector(KernelGlobals *kg, ShaderData *sd)
 	int offset_pre = find_attribute(kg, sd, ATTR_STD_MOTION_PRE);
 	int offset_post = find_attribute(kg, sd, ATTR_STD_MOTION_POST);
 
-	if(offset_pre != ATTR_STD_NOT_FOUND)
-		motion_pre = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, offset_pre, NULL, NULL);
-	if(offset_post != ATTR_STD_NOT_FOUND)
-		motion_post = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, offset_post, NULL, NULL);
+#ifdef __HAIR__
+	if(sd->curve_seg == ~0) {
+#endif
+		if(offset_pre != ATTR_STD_NOT_FOUND)
+			motion_pre = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, offset_pre, NULL, NULL);
+		if(offset_post != ATTR_STD_NOT_FOUND)
+			motion_post = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, offset_post, NULL, NULL);
+#ifdef __HAIR__
+	}
+#endif
 
 	/* object motion. note that depending on the mesh having motion vectors, this
 	 * transformation was set match the world/object space of motion_pre/post */
@@ -259,8 +284,13 @@ __device float3 triangle_uv(KernelGlobals *kg, ShaderData *sd)
 {
 	int offset_uv = find_attribute(kg, sd, ATTR_STD_UV);
 
+#ifdef __HAIR__
+	if(offset_uv == ATTR_STD_NOT_FOUND || sd->curve_seg != ~0)
+		return make_float3(0.0f, 0.0f, 0.0f);
+#else
 	if(offset_uv == ATTR_STD_NOT_FOUND)
 		return make_float3(0.0f, 0.0f, 0.0f);
+#endif
 
 	float3 uv = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, offset_uv, NULL, NULL);
 	uv.z = 1.0f;
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index d11b96503d9..d051006f165 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -47,6 +47,7 @@ CCL_NAMESPACE_BEGIN
 #define __OSL__
 #endif
 #define __NON_PROGRESSIVE__
+#define __HAIR__
 #endif
 
 #ifdef __KERNEL_CUDA__
@@ -116,7 +117,6 @@ CCL_NAMESPACE_BEGIN
 #define __ANISOTROPIC__
 #define __OBJECT_MOTION__
 #endif
-
 //#define __SOBOL_FULL_SCREEN__
 
 /* Shader Evaluation */
@@ -292,7 +292,8 @@ typedef enum LightType {
 	LIGHT_BACKGROUND,
 	LIGHT_AREA,
 	LIGHT_AO,
-	LIGHT_SPOT
+	LIGHT_SPOT,
+	LIGHT_STRAND
 } LightType;
 
 /* Camera Type */
@@ -436,6 +437,11 @@ typedef struct ShaderData {
 
 	/* primitive id if there is one, ~0 otherwise */
 	int prim;
+
+#ifdef __HAIR__
+	/* strand id if there is one, -1 otherwise */
+	int curve_seg;
+#endif
 	/* parametric coordinates
 	 * - barycentric weights for triangles */
 	float u, v;
@@ -650,6 +656,29 @@ typedef struct KernelBVH {
 	int pad2;
 } KernelBVH;
 
+typedef enum CurveFlag {
+	/* runtime flags */
+	CURVE_KN_BACKFACING = 1,				/* backside of cylinder? */
+	CURVE_KN_ENCLOSEFILTER = 2,				/* don't consider strands surrounding start point? */
+	CURVE_KN_CURVEDATA = 4,				/* curve data available? */
+	CURVE_KN_INTERPOLATE = 8,				/* render as a curve? - not supported yet */
+	CURVE_KN_ACCURATE = 16,				/* use accurate intersections test? */
+	CURVE_KN_INTERSECTCORRECTION = 32,		/* correct for width after determing closest midpoint? */
+	CURVE_KN_POSTINTERSECTCORRECTION = 64,	/* correct for width after intersect? */
+	CURVE_KN_NORMALCORRECTION = 128,		/* correct tangent normal for slope? */
+	CURVE_KN_TRUETANGENTGNORMAL = 256,		/* use tangent normal for geometry? */
+	CURVE_KN_TANGENTGNORMAL = 512,			/* use tangent normal for shader? */
+} CurveFlag;
+
+typedef struct KernelCurves {
+	/* strand intersect and normal parameters - many can be changed to flags*/
+	float normalmix;
+	float encasing_ratio;
+	int curveflags;
+	int pad;
+
+} KernelCurves;
+
 typedef struct KernelData {
 	KernelCamera cam;
 	KernelFilm film;
@@ -657,6 +686,7 @@ typedef struct KernelData {
 	KernelSunSky sunsky;
 	KernelIntegrator integrator;
 	KernelBVH bvh;
+	KernelCurves curve_kernel_data;
 } KernelData;
 
 CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h
index ec7978066c2..1f4857c0924 100644
--- a/intern/cycles/kernel/svm/svm.h
+++ b/intern/cycles/kernel/svm/svm.h
@@ -301,6 +301,12 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
 			case NODE_PARTICLE_INFO:
 				svm_node_particle_info(kg, sd, stack, node.y, node.z);
 				break;
+#ifdef __HAIR__
+			case NODE_HAIR_INFO:
+				svm_node_hair_info(kg, sd, stack, node.y, node.z);
+				break;
+#endif
+
 #endif
 			case NODE_CONVERT:
 				svm_node_convert(sd, stack, node.y, node.z, node.w);
diff --git a/intern/cycles/kernel/svm/svm_attribute.h b/intern/cycles/kernel/svm/svm_attribute.h
index ed70a6dc423..4f9dc4af007 100644
--- a/intern/cycles/kernel/svm/svm_attribute.h
+++ b/intern/cycles/kernel/svm/svm_attribute.h
@@ -58,27 +58,45 @@ __device void svm_node_attr(KernelGlobals *kg, ShaderData *sd, float *stack, uin
 
 	svm_node_attr_init(kg, sd, node, &type, &mesh_type, &elem, &offset, &out_offset);
 
-	/* fetch and store attribute */
-	if(type == NODE_ATTR_FLOAT) {
-		if(mesh_type == NODE_ATTR_FLOAT) {
-			float f = triangle_attribute_float(kg, sd, elem, offset, NULL, NULL);
-			stack_store_float(stack, out_offset, f);
-		}
+#ifdef __HAIR__
+	if (sd->curve_seg != ~0) {
+		/*currently strand attributes aren't enabled - only exports stored uvs*/
+		if(type == NODE_ATTR_FLOAT)
+			stack_store_float(stack, out_offset, 0.0f);
 		else {
-			float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, NULL);
-			stack_store_float(stack, out_offset, average(f));
+			float4 sd2 = kernel_tex_fetch(__tri_woop, sd->prim*3+2);
+			float3 uv =  make_float3(sd2.z,sd2.w,0.0f);
+			stack_store_float3(stack, out_offset, uv);
 		}
 	}
-	else {
-		if(mesh_type == NODE_ATTR_FLOAT3) {
-			float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, NULL);
-			stack_store_float3(stack, out_offset, f);
+	else
+	{
+#endif
+
+		/* fetch and store attribute */
+		if(type == NODE_ATTR_FLOAT) {
+			if(mesh_type == NODE_ATTR_FLOAT) {
+				float f = triangle_attribute_float(kg, sd, elem, offset, NULL, NULL);
+				stack_store_float(stack, out_offset, f);
+			}
+			else {
+				float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, NULL);
+				stack_store_float(stack, out_offset, average(f));
+			}
 		}
 		else {
-			float f = triangle_attribute_float(kg, sd, elem, offset, NULL, NULL);
-			stack_store_float3(stack, out_offset, make_float3(f, f, f));
+			if(mesh_type == NODE_ATTR_FLOAT3) {
+				float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, NULL);
+				stack_store_float3(stack, out_offset, f);
+			}
+			else {
+				float f = triangle_attribute_float(kg, sd, elem, offset, NULL, NULL);
+				stack_store_float3(stack, out_offset, make_float3(f, f, f));
+			}
 		}
+#ifdef __HAIR__
 	}
+#endif
 }
 
 __device void svm_node_attr_bump_dx(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
@@ -91,30 +109,43 @@ __device void svm_node_attr_bump_dx(KernelGlobals *kg, ShaderData *sd, float *st
 	svm_node_attr_init(kg, sd, node, &type, &mesh_type, &elem, &offset, &out_offset);
 
 	/* fetch and store attribute */
-	if(type == NODE_ATTR_FLOAT) {
-		if(mesh_type == NODE_ATTR_FLOAT) {
-			float dx;
-			float f = triangle_attribute_float(kg, sd, elem, offset, &dx, NULL);
-			stack_store_float(stack, out_offset, f+dx);
-		}
-		else {
-			float3 dx;
-			float3 f = triangle_attribute_float3(kg, sd, elem, offset, &dx, NULL);
-			stack_store_float(stack, out_offset, average(f+dx));
-		}
+#ifdef __HAIR__
+	if (sd->curve_seg != ~0) {
+		/*currently strand attributes aren't enabled*/
+		if(type == NODE_ATTR_FLOAT)
+			stack_store_float(stack, out_offset, 0.0f);
+		else
+			stack_store_float3(stack, out_offset,  make_float3(0.0f, 0.0f, 0.0f));
 	}
 	else {
-		if(mesh_type == NODE_ATTR_FLOAT3) {
-			float3 dx;
-			float3 f = triangle_attribute_float3(kg, sd, elem, offset, &dx, NULL);
-			stack_store_float3(stack, out_offset, f+dx);
+#endif
+		if(type == NODE_ATTR_FLOAT) {
+			if(mesh_type == NODE_ATTR_FLOAT) {
+				float dx;
+				float f = triangle_attribute_float(kg, sd, elem, offset, &dx, NULL);
+				stack_store_float(stack, out_offset, f+dx);
+			}
+			else {
+				float3 dx;
+				float3 f = triangle_attribute_float3(kg, sd, elem, offset, &dx, NULL);
+				stack_store_float(stack, out_offset, average(f+dx));
+			}
 		}
 		else {
-			float dx;
-			float f = triangle_attribute_float(kg, sd, elem, offset, &dx, NULL);
-			stack_store_float3(stack, out_offset, make_float3(f+dx, f+dx, f+dx));
+			if(mesh_type == NODE_ATTR_FLOAT3) {
+				float3 dx;
+				float3 f = triangle_attribute_float3(kg, sd, elem, offset, &dx, NULL);
+				stack_store_float3(stack, out_offset, f+dx);
+			}
+			else {
+				float dx;
+				float f = triangle_attribute_float(kg, sd, elem, offset, &dx, NULL);
+				stack_store_float3(stack, out_offset, make_float3(f+dx, f+dx, f+dx));
+			}
 		}
+#ifdef __HAIR__
 	}
+#endif
 }
 
 __device void svm_node_attr_bump_dy(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
@@ -127,30 +158,43 @@ __device void svm_node_attr_bump_dy(KernelGlobals *kg, ShaderData *sd, float *st
 	svm_node_attr_init(kg, sd, node, &type, &mesh_type, &elem, &offset, &out_offset);
 
 	/* fetch and store attribute */
-	if(type == NODE_ATTR_FLOAT) {
-		if(mesh_type == NODE_ATTR_FLOAT) {
-			float dy;
-			float f = triangle_attribute_float(kg, sd, elem, offset, NULL, &dy);
-			stack_store_float(stack, out_offset, f+dy);
-		}
-		else {
-			float3 dy;
-			float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, &dy);
-			stack_store_float(stack, out_offset, average(f+dy));
-		}
+#ifdef __HAIR__
+	if (sd->curve_seg != ~0) {
+		/*currently strand attributes aren't enabled*/
+		if(type == NODE_ATTR_FLOAT)
+			stack_store_float(stack, out_offset, 0.0f);
+		else 
+			stack_store_float3(stack, out_offset,  make_float3(0.0f, 0.0f, 0.0f));
 	}
 	else {
-		if(mesh_type == NODE_ATTR_FLOAT3) {
-			float3 dy;
-			float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, &dy);
-			stack_store_float3(stack, out_offset, f+dy);
+#endif
+		if(type == NODE_ATTR_FLOAT) {
+			if(mesh_type == NODE_ATTR_FLOAT) {
+				float dy;
+				float f = triangle_attribute_float(kg, sd, elem, offset, NULL, &dy);
+				stack_store_float(stack, out_offset, f+dy);
+			}
+			else {
+				float3 dy;
+				float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, &dy);
+				stack_store_float(stack, out_offset, average(f+dy));
+			}
 		}
 		else {
-			float dy;
-			float f = triangle_attribute_float(kg, sd, elem, offset, NULL, &dy);
-			stack_store_float3(stack, out_offset, make_float3(f+dy, f+dy, f+dy));
+			if(mesh_type == NODE_ATTR_FLOAT3) {
+				float3 dy;
+				float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, &dy);
+				stack_store_float3(stack, out_offset, f+dy);
+			}
+			else {
+				float dy;
+				float f = triangle_attribute_float(kg, sd, elem, offset, NULL, &dy);
+				stack_store_float3(stack, out_offset, make_float3(f+dy, f+dy, f+dy));
+			}
 		}
+#ifdef __HAIR__
 	}
+#endif
 }
 
 CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_geometry.h b/intern/cycles/kernel/svm/svm_geometry.h
index c4d03c1f948..e1b898e9b14 100644
--- a/intern/cycles/kernel/svm/svm_geometry.h
+++ b/intern/cycles/kernel/svm/svm_geometry.h
@@ -31,8 +31,11 @@ __device void svm_node_geometry(KernelGlobals *kg, ShaderData *sd, float *stack,
 		case NODE_GEOM_T: {
 			/* try to create spherical tangent from generated coordinates */
 			int attr_offset = (sd->object != ~0)? find_attribute(kg, sd, ATTR_STD_GENERATED): ATTR_STD_NOT_FOUND;
-
+#ifdef __HAIR__
+			if(attr_offset != ATTR_STD_NOT_FOUND && sd->curve_seg == ~0) {
+#else
 			if(attr_offset != ATTR_STD_NOT_FOUND) {
+#endif
 				data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL);
 				data = make_float3(-(data.y - 0.5f), (data.x - 0.5f), 0.0f);
 				object_normal_transform(kg, sd, &data);
@@ -160,5 +163,38 @@ __device void svm_node_particle_info(KernelGlobals *kg, ShaderData *sd, float *s
 	}
 }
 
+#ifdef __HAIR__
+/* Hair Info */
+
+__device void svm_node_hair_info(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
+{
+	float data;
+	float3 data3;
+
+	switch(type) {
+		case NODE_INFO_CURVE_IS_STRAND: {
+			data = !(sd->curve_seg == ~0);
+			stack_store_float(stack, out_offset, data);
+			break;
+		}
+		case NODE_INFO_CURVE_INTERCEPT: {
+			data = intercept(kg, sd->curve_seg, sd->prim, sd->u);
+			stack_store_float(stack, out_offset, data);
+			break;
+		}
+		case NODE_INFO_CURVE_THICKNESS: {
+			data = 2 * hair_radius(kg, sd->curve_seg, sd->u);
+			stack_store_float(stack, out_offset, data);
+			break;
+		}
+		case NODE_INFO_CURVE_TANGENT_NORMAL: {
+			data3 = hair_tangent_normal(kg, sd);
+			stack_store_float3(stack, out_offset, data3);
+			break;
+		}
+	}
+}
+#endif
+
 CCL_NAMESPACE_END
 
diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h
index 9f2d3367420..5e7c92ba93c 100644
--- a/intern/cycles/kernel/svm/svm_tex_coord.h
+++ b/intern/cycles/kernel/svm/svm_tex_coord.h
@@ -242,7 +242,11 @@ __device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *stac
 
 	if(space == NODE_NORMAL_MAP_TANGENT) {
 		/* tangent space */
-		if(sd->object == ~0) {
+#ifdef __HAIR__
+			if(sd->object == ~0 || sd->curve_seg != ~0) {
+#else
+			if(sd->object == ~0) {
+#endif
 			stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f));
 			return;
 		}
@@ -297,7 +301,11 @@ __device void svm_node_tangent(KernelGlobals *kg, ShaderData *sd, float *stack,
 		/* UV map */
 		int attr_offset = find_attribute(kg, sd, node.z);
 
+#ifdef __HAIR__
+		if(attr_offset == ATTR_STD_NOT_FOUND || sd->curve_seg != ~0)
+#else
 		if(attr_offset == ATTR_STD_NOT_FOUND)
+#endif
 			tangent = make_float3(0.0f, 0.0f, 0.0f);
 		else
 			tangent = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, attr_offset, NULL, NULL);
@@ -307,7 +315,11 @@ __device void svm_node_tangent(KernelGlobals *kg, ShaderData *sd, float *stack,
 		int attr_offset = find_attribute(kg, sd, node.z);
 		float3 generated;
 
+#ifdef __HAIR__
+		if(attr_offset == ATTR_STD_NOT_FOUND || sd->curve_seg != ~0)
+#else
 		if(attr_offset == ATTR_STD_NOT_FOUND)
+#endif
 			generated = sd->P;
 		else
 			generated = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL);
diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h
index e1a583625fc..57177eec48f 100644
--- a/intern/cycles/kernel/svm/svm_types.h
+++ b/intern/cycles/kernel/svm/svm_types.h
@@ -97,7 +97,8 @@ typedef enum NodeType {
 	NODE_CLOSURE_SET_NORMAL,
 	NODE_CLOSURE_AMBIENT_OCCLUSION,
 	NODE_TANGENT,
-	NODE_NORMAL_MAP
+	NODE_NORMAL_MAP,
+	NODE_HAIR_INFO
 } NodeType;
 
 typedef enum NodeAttributeType {
@@ -132,6 +133,13 @@ typedef enum NodeParticleInfo {
 	NODE_INFO_PAR_ANGULAR_VELOCITY
 } NodeParticleInfo;
 
+typedef enum NodeHairInfo {
+	NODE_INFO_CURVE_IS_STRAND,
+	NODE_INFO_CURVE_INTERCEPT,
+	NODE_INFO_CURVE_THICKNESS,
+	NODE_INFO_CURVE_TANGENT_NORMAL
+} NodeHairInfo;
+
 typedef enum NodeLightPath {
 	NODE_LP_camera = 0,
 	NODE_LP_shadow,
diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt
index 7907061c19c..d67a686d1e8 100644
--- a/intern/cycles/render/CMakeLists.txt
+++ b/intern/cycles/render/CMakeLists.txt
@@ -31,6 +31,7 @@ set(SRC
 	object.cpp
 	osl.cpp
 	particles.cpp
+	curves.cpp
 	scene.cpp
 	session.cpp
 	shader.cpp
@@ -56,6 +57,7 @@ set(SRC_HEADERS
 	object.h
 	osl.h
 	particles.h
+	curves.h
 	scene.h
 	session.h
 	shader.h
diff --git a/intern/cycles/render/curves.cpp b/intern/cycles/render/curves.cpp
new file mode 100644
index 00000000000..3299503b4ab
--- /dev/null
+++ b/intern/cycles/render/curves.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2011, 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.
+ */
+
+#include "device.h"
+#include "curves.h"
+#include "mesh.h"
+#include "object.h"
+#include "scene.h"
+
+#include "util_foreach.h"
+#include "util_map.h"
+#include "util_progress.h"
+#include "util_vector.h"
+
+CCL_NAMESPACE_BEGIN
+
+/* Hair System Manager */
+
+CurveSystemManager::CurveSystemManager()
+{
+	primitive = CURVE_LINE_SEGMENTS;
+	line_method = CURVE_CORRECTED;
+	interpolation = CURVE_CARDINAL;
+	triangle_method = CURVE_CAMERA;
+	resolution = 3;
+	segments = 1;
+
+	normalmix = 1.0f;
+	encasing_ratio = 1.01f;
+
+	use_curves = true;
+	use_smooth = true;
+	use_cache = true;
+	use_parents = false;
+	use_encasing = true;
+	use_backfacing = false;
+	use_joined = false;
+	use_tangent_normal = false;
+	use_tangent_normal_geometry = false;
+	use_tangent_normal_correction = false;
+
+	need_update = true;
+	need_mesh_update = false;
+}
+
+CurveSystemManager::~CurveSystemManager()
+{
+}
+
+void CurveSystemManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
+{
+	if(!need_update)
+		return;
+
+	device_free(device, dscene);
+
+	progress.set_status("Updating Hair settings", "Copying Hair settings to device");
+
+	KernelCurves *kcurve= &dscene->data.curve_kernel_data;
+
+	kcurve->curveflags = 0;
+
+	if(primitive == CURVE_SEGMENTS)
+		kcurve->curveflags |= CURVE_KN_INTERPOLATE;
+
+	if(line_method == CURVE_ACCURATE)
+		kcurve->curveflags |= CURVE_KN_ACCURATE;
+	if(line_method == CURVE_CORRECTED)
+		kcurve->curveflags |= CURVE_KN_INTERSECTCORRECTION;
+	if(line_method == CURVE_POSTCORRECTED)
+		kcurve->curveflags |= CURVE_KN_POSTINTERSECTCORRECTION;
+
+	if(use_tangent_normal)
+		kcurve->curveflags |= CURVE_KN_TANGENTGNORMAL;
+	if(use_tangent_normal_correction)
+		kcurve->curveflags |= CURVE_KN_NORMALCORRECTION;
+	if(use_tangent_normal_geometry)
+		kcurve->curveflags |= CURVE_KN_TRUETANGENTGNORMAL;
+	if(use_joined)
+		kcurve->curveflags |= CURVE_KN_CURVEDATA;
+	if(use_backfacing)
+		kcurve->curveflags |= CURVE_KN_BACKFACING;
+	if(use_encasing)
+		kcurve->curveflags |= CURVE_KN_ENCLOSEFILTER;
+
+	kcurve->normalmix = normalmix;
+	kcurve->encasing_ratio = encasing_ratio;
+
+	if(progress.get_cancel()) return;
+
+	need_update = false;
+}
+
+void CurveSystemManager::device_free(Device *device, DeviceScene *dscene)
+{
+
+}
+
+bool CurveSystemManager::modified(const CurveSystemManager& CurveSystemManager)
+{
+	return !(line_method == CurveSystemManager.line_method &&
+		interpolation == CurveSystemManager.interpolation &&
+		primitive == CurveSystemManager.primitive &&
+		use_encasing == CurveSystemManager.use_encasing &&
+		use_tangent_normal == CurveSystemManager.use_tangent_normal &&
+		use_tangent_normal_correction == CurveSystemManager.use_tangent_normal_correction &&
+		use_tangent_normal_geometry == CurveSystemManager.use_tangent_normal_geometry &&
+		encasing_ratio == CurveSystemManager.encasing_ratio &&
+		use_backfacing == CurveSystemManager.use_backfacing &&
+		normalmix == CurveSystemManager.normalmix &&
+		use_cache == CurveSystemManager.use_cache &&
+		use_smooth == CurveSystemManager.use_smooth &&
+		triangle_method == CurveSystemManager.triangle_method &&
+		resolution == CurveSystemManager.resolution &&
+		use_curves == CurveSystemManager.use_curves &&
+		use_joined == CurveSystemManager.use_joined &&
+		segments == CurveSystemManager.segments &&
+		use_parents == CurveSystemManager.use_parents);
+}
+
+bool CurveSystemManager::modified_mesh(const CurveSystemManager& CurveSystemManager)
+{
+	return !(primitive == CurveSystemManager.primitive &&
+		interpolation == CurveSystemManager.interpolation &&
+		use_parents == CurveSystemManager.use_parents &&
+		use_smooth == CurveSystemManager.use_smooth &&
+		triangle_method == CurveSystemManager.triangle_method &&
+		resolution == CurveSystemManager.resolution &&
+		use_curves == CurveSystemManager.use_curves &&
+		use_joined == CurveSystemManager.use_joined &&
+		segments == CurveSystemManager.segments &&
+		use_cache == CurveSystemManager.use_cache);
+}
+
+void CurveSystemManager::tag_update(Scene *scene)
+{
+	need_update = true;
+}
+
+void CurveSystemManager::tag_update_mesh()
+{
+	need_mesh_update = true;
+}
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/render/curves.h b/intern/cycles/render/curves.h
new file mode 100644
index 00000000000..581b3010d77
--- /dev/null
+++ b/intern/cycles/render/curves.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2011, 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.
+ */
+
+#ifndef __CURVES_H__
+#define __CURVES_H__
+
+#include "util_types.h"
+#include "util_vector.h"
+
+CCL_NAMESPACE_BEGIN
+
+class Device;
+class DeviceScene;
+class Progress;
+class Scene;
+
+typedef enum curve_presets {
+	CURVE_CUSTOM,
+	CURVE_TANGENT_SHADING,
+	CURVE_TRUE_NORMAL,
+	CURVE_ACCURATE_PRESET
+} curve_presets;
+
+typedef enum curve_primitives {
+	CURVE_TRIANGLES,
+	CURVE_LINE_SEGMENTS,
+	CURVE_SEGMENTS
+} curve_primitives;
+
+typedef enum curve_triangles {
+	CURVE_CAMERA,
+	CURVE_RIBBONS,
+	CURVE_TESSELATED
+} curve_triangles;
+
+typedef enum curve_lines {
+	CURVE_ACCURATE,
+	CURVE_CORRECTED,
+	CURVE_POSTCORRECTED,
+	CURVE_UNCORRECTED
+} curve_lines;
+
+typedef enum curve_interpolation {
+	CURVE_LINEAR,
+	CURVE_CARDINAL,
+	CURVE_BSPLINE
+} curve_interpolation;
+
+class ParticleCurveData {
+
+public:
+
+	ParticleCurveData();
+	~ParticleCurveData();
+
+	vector psys_firstcurve;
+	vector psys_curvenum;
+	vector psys_shader;
+
+	vector psys_rootradius;
+	vector psys_tipradius;
+	vector psys_shape;
+	vector psys_closetip;
+
+	vector curve_firstkey;
+	vector curve_keynum;
+	vector curve_length;
+	vector curve_u;
+	vector curve_v;
+
+	vector curvekey_co;
+	vector curvekey_time;
+};
+
+/* HairSystem Manager */
+
+class CurveSystemManager {
+public:
+
+	int primitive;
+	int line_method;
+	int interpolation;
+	int triangle_method;
+	int resolution;
+	int segments;
+
+	float normalmix;
+	float encasing_ratio;
+
+	bool use_curves;
+	bool use_smooth;
+	bool use_cache;
+	bool use_parents;
+	bool use_encasing;
+	bool use_backfacing;
+	bool use_tangent_normal;
+	bool use_tangent_normal_correction;
+	bool use_tangent_normal_geometry;
+	bool use_joined;
+
+	bool need_update;
+	bool need_mesh_update;
+
+	CurveSystemManager();
+	~CurveSystemManager();
+
+	void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
+	void device_free(Device *device, DeviceScene *dscene);
+	bool modified(const CurveSystemManager& CurveSystemManager);
+	bool modified_mesh(const CurveSystemManager& CurveSystemManager);
+
+	void tag_update(Scene *scene);
+	void tag_update_mesh();
+};
+
+CCL_NAMESPACE_END
+
+#endif /* __CURVES_H__ */
+
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index 4173da453fd..66e528c7230 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -142,6 +142,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
 	/* count */
 	size_t num_lights = scene->lights.size();
 	size_t num_triangles = 0;
+	size_t num_curve_segs = 0;
 
 	foreach(Object *object, scene->objects) {
 		Mesh *mesh = object->mesh;
@@ -169,10 +170,18 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
 				if(shader->sample_as_light && shader->has_surface_emission)
 					num_triangles++;
 			}
+
+			/* disabled for strands*/
+			/*for(size_t i = 0; i < mesh->curve_segs.size(); i++) {
+			*	Shader *shader = scene->shaders[mesh->curve_segs[i].curveshader];
+			*
+			*	if(shader->sample_as_light && shader->has_surface_emission)
+			*		num_curve_segs++;
+			}*/
 		}
 	}
 
-	size_t num_distribution = num_triangles;
+	size_t num_distribution = num_triangles + num_curve_segs;
 	num_distribution += num_lights;
 
 	/* emission area */
@@ -234,6 +243,32 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
 					totarea += triangle_area(p1, p2, p3);
 				}
 			}
+
+			/*sample as light disabled for strands*/
+			/*for(size_t i = 0; i < mesh->curve_segs.size(); i++) {
+			*	Shader *shader = scene->shaders[mesh->curve_segs[i].curveshader];
+			*
+			*	if(shader->sample_as_light && shader->has_surface_emission) {
+			*		distribution[offset].x = totarea;
+			*		distribution[offset].y = __int_as_float(i + mesh->curveseg_offset);
+			*		distribution[offset].z = 0.0f;
+			*		distribution[offset].w = __int_as_float(object_id);
+			*		offset++;
+			*
+			*		Mesh::CurveSeg s = mesh->curve_segs[i];
+			*		float3 p1 = mesh->curve_keys[s.v[0]].loc;
+			*		float r1 = mesh->curve_keys[s.v[0]].radius;
+			*		float3 p2 = mesh->curve_keys[s.v[1]].loc;
+			*		float r2 = mesh->curve_keys[s.v[1]].radius;
+			*
+			*		if(!transform_applied) {
+			*			p1 = transform_point(&tfm, p1);
+			*			p2 = transform_point(&tfm, p2);
+			*		}
+			*
+			*		totarea += M_PI_F * (r1 + r2) * len(p1 - p2);
+			*	}
+			}*/
 		}
 
 		if(progress.get_cancel()) return;
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index bc782a78c60..a2d545d51c0 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -51,6 +51,9 @@ Mesh::Mesh()
 	tri_offset = 0;
 	vert_offset = 0;
 
+	curveseg_offset = 0;
+	curvekey_offset = 0;
+
 	attributes.mesh = this;
 }
 
@@ -66,6 +69,7 @@ void Mesh::reserve(int numverts, int numtris)
 	triangles.resize(numtris);
 	shader.resize(numtris);
 	smooth.resize(numtris);
+	/*currently no need in hair segment resize and curve data needs including*/
 	attributes.reserve(numverts, numtris);
 }
 
@@ -77,6 +81,11 @@ void Mesh::clear()
 	shader.clear();
 	smooth.clear();
 
+	curve_keys.clear();
+	curve_keysCD.clear();
+	curve_segs.clear();
+	curve_attrib.clear();
+
 	attributes.clear();
 	used_shaders.clear();
 
@@ -96,14 +105,48 @@ void Mesh::add_triangle(int v0, int v1, int v2, int shader_, bool smooth_)
 	smooth.push_back(smooth_);
 }
 
+void Mesh::add_curvekey(float3 loc, float radius, float time)
+{
+	CurveKey ck;
+	ck.loc = loc;
+	ck.radius = radius;
+	ck.time = time;
+
+	curve_keys.push_back(ck);
+}
+
+void Mesh::add_curve(int v0, int v1, int shader, int curveid)
+{
+	CurveSeg s;
+	s.v[0] = v0;
+	s.v[1] = v1;
+	s.curveshader = shader;
+	s.curve = curveid;
+
+	curve_segs.push_back(s);
+}
+
+void Mesh::add_curveattrib(float u, float v)
+{
+	Curve_Attribute s;
+	s.uv[0] = u;
+	s.uv[1] = v;
+
+	curve_attrib.push_back(s);
+}
+
 void Mesh::compute_bounds()
 {
 	BoundBox bnds = BoundBox::empty;
 	size_t verts_size = verts.size();
+	size_t curve_keys_size = curve_keys.size();
 
 	for(size_t i = 0; i < verts_size; i++)
 		bnds.grow(verts[i]);
 
+	for(size_t i = 0; i < curve_keys_size; i++)
+		bnds.grow(curve_keys[i].loc, curve_keys[i].radius);
+
 	/* happens mostly on empty meshes */
 	if(!bnds.valid())
 		bnds.grow(make_float3(0.0f, 0.0f, 0.0f));
@@ -243,6 +286,45 @@ void Mesh::pack_verts(float4 *tri_verts, float4 *tri_vindex, size_t vert_offset)
 	}
 }
 
+void Mesh::pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_seg_keys, size_t curvekey_offset)
+{
+	size_t curve_keys_size = curve_keys.size();
+	CurveKey *keys_ptr = NULL;
+
+	if(curve_keys_size) {
+
+		keys_ptr = &curve_keys[0];
+
+		for(size_t i = 0; i < curve_keys_size; i++) {
+			float3 p = keys_ptr[i].loc;
+			curve_key_co[i] = make_float4(p.x, p.y, p.z, keys_ptr[i].radius);
+		}
+	}
+
+	size_t curve_seg_num = curve_segs.size();
+
+	if(curve_seg_num) {
+		CurveSeg *curve_ptr = &curve_segs[0];
+
+		int shader_id = 0;
+		
+		for(size_t i = 0; i < curve_seg_num; i++) {
+			CurveSeg s = curve_ptr[i];
+			shader_id = scene->shader_manager->get_shader_id(s.curveshader, this, false);
+
+			float3 p1 = keys_ptr[s.v[0]].loc;
+			float3 p2 = keys_ptr[s.v[1]].loc;
+			float length = len(p2 - p1);
+
+			curve_seg_keys[i] = make_float4(
+				__int_as_float(s.v[0] + curvekey_offset),
+				__int_as_float(s.v[1] + curvekey_offset),
+				__int_as_float(shader_id),
+				length);
+		}
+	}
+}
+
 void Mesh::compute_bvh(SceneParams *params, Progress *progress, int n, int total)
 {
 	if(progress->get_cancel())
@@ -573,39 +655,62 @@ void MeshManager::device_update_mesh(Device *device, DeviceScene *dscene, Scene
 	size_t vert_size = 0;
 	size_t tri_size = 0;
 
+	size_t CurveKey_size = 0;
+	size_t curve_seg_keys = 0;
+
 	foreach(Mesh *mesh, scene->meshes) {
 		mesh->vert_offset = vert_size;
 		mesh->tri_offset = tri_size;
 
+		mesh->curvekey_offset = CurveKey_size;
+		mesh->curveseg_offset = curve_seg_keys;
+
 		vert_size += mesh->verts.size();
 		tri_size += mesh->triangles.size();
+
+		CurveKey_size += mesh->curve_keys.size();
+		curve_seg_keys += mesh->curve_segs.size();
 	}
 
-	if(tri_size == 0)
-		return;
+	if(tri_size != 0) {
+		/* normals */
+		progress.set_status("Updating Mesh", "Computing normals");
 
-	/* normals */
-	progress.set_status("Updating Mesh", "Computing normals");
+		float4 *normal = dscene->tri_normal.resize(tri_size);
+		float4 *vnormal = dscene->tri_vnormal.resize(vert_size);
+		float4 *tri_verts = dscene->tri_verts.resize(vert_size);
+		float4 *tri_vindex = dscene->tri_vindex.resize(tri_size);
 
-	float4 *normal = dscene->tri_normal.resize(tri_size);
-	float4 *vnormal = dscene->tri_vnormal.resize(vert_size);
-	float4 *tri_verts = dscene->tri_verts.resize(vert_size);
-	float4 *tri_vindex = dscene->tri_vindex.resize(tri_size);
+		foreach(Mesh *mesh, scene->meshes) {
+			mesh->pack_normals(scene, &normal[mesh->tri_offset], &vnormal[mesh->vert_offset]);
+			mesh->pack_verts(&tri_verts[mesh->vert_offset], &tri_vindex[mesh->tri_offset], mesh->vert_offset);
 
-	foreach(Mesh *mesh, scene->meshes) {
-		mesh->pack_normals(scene, &normal[mesh->tri_offset], &vnormal[mesh->vert_offset]);
-		mesh->pack_verts(&tri_verts[mesh->vert_offset], &tri_vindex[mesh->tri_offset], mesh->vert_offset);
+			if(progress.get_cancel()) return;
+		}
 
-		if(progress.get_cancel()) return;
+		/* vertex coordinates */
+		progress.set_status("Updating Mesh", "Copying Mesh to device");
+
+		device->tex_alloc("__tri_normal", dscene->tri_normal);
+		device->tex_alloc("__tri_vnormal", dscene->tri_vnormal);
+		device->tex_alloc("__tri_verts", dscene->tri_verts);
+		device->tex_alloc("__tri_vindex", dscene->tri_vindex);
 	}
 
-	/* vertex coordinates */
-	progress.set_status("Updating Mesh", "Copying Mesh to device");
+	if(curve_seg_keys != 0) {
+		progress.set_status("Updating Mesh", "Copying Strands to device");
+
+		float4 *cur_keys = dscene->cur_keys.resize(CurveKey_size);
+		float4 *cur_segs = dscene->cur_segs.resize(curve_seg_keys);
 
-	device->tex_alloc("__tri_normal", dscene->tri_normal);
-	device->tex_alloc("__tri_vnormal", dscene->tri_vnormal);
-	device->tex_alloc("__tri_verts", dscene->tri_verts);
-	device->tex_alloc("__tri_vindex", dscene->tri_vindex);
+		foreach(Mesh *mesh, scene->meshes) {
+			mesh->pack_curves(scene, &cur_keys[mesh->curvekey_offset], &cur_segs[mesh->curveseg_offset], mesh->curvekey_offset);
+			if(progress.get_cancel()) return;
+		}
+
+		device->tex_alloc("__cur_keys", dscene->cur_keys);
+		device->tex_alloc("__cur_segs", dscene->cur_segs);
+	}
 }
 
 void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
@@ -642,6 +747,10 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *
 		dscene->tri_woop.reference(&pack.tri_woop[0], pack.tri_woop.size());
 		device->tex_alloc("__tri_woop", dscene->tri_woop);
 	}
+	if(pack.prim_type.size()) {
+		dscene->prim_type.reference((uint*)&pack.prim_type[0], pack.prim_type.size());
+		device->tex_alloc("__prim_type", dscene->prim_type);
+	}
 	if(pack.prim_visibility.size()) {
 		dscene->prim_visibility.reference((uint*)&pack.prim_visibility[0], pack.prim_visibility.size());
 		device->tex_alloc("__prim_visibility", dscene->prim_visibility);
@@ -751,6 +860,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
 	device->tex_free(dscene->bvh_nodes);
 	device->tex_free(dscene->object_node);
 	device->tex_free(dscene->tri_woop);
+	device->tex_free(dscene->prim_type);
 	device->tex_free(dscene->prim_visibility);
 	device->tex_free(dscene->prim_index);
 	device->tex_free(dscene->prim_object);
@@ -758,6 +868,8 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
 	device->tex_free(dscene->tri_vnormal);
 	device->tex_free(dscene->tri_vindex);
 	device->tex_free(dscene->tri_verts);
+	device->tex_free(dscene->cur_segs);
+	device->tex_free(dscene->cur_keys);
 	device->tex_free(dscene->attributes_map);
 	device->tex_free(dscene->attributes_float);
 	device->tex_free(dscene->attributes_float3);
@@ -765,6 +877,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
 	dscene->bvh_nodes.clear();
 	dscene->object_node.clear();
 	dscene->tri_woop.clear();
+	dscene->prim_type.clear();
 	dscene->prim_visibility.clear();
 	dscene->prim_index.clear();
 	dscene->prim_object.clear();
@@ -772,6 +885,8 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
 	dscene->tri_vnormal.clear();
 	dscene->tri_vindex.clear();
 	dscene->tri_verts.clear();
+	dscene->cur_segs.clear();
+	dscene->cur_keys.clear();
 	dscene->attributes_map.clear();
 	dscene->attributes_float.clear();
 	dscene->attributes_float3.clear();
diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h
index 637143f5adf..24d3f02e082 100644
--- a/intern/cycles/render/mesh.h
+++ b/intern/cycles/render/mesh.h
@@ -50,6 +50,28 @@ public:
 		int v[3];
 	};
 
+	/* Mesh Strand Data*/
+	struct CurveSeg {
+		int v[2];
+		uint curveshader;
+		int curve;
+	};
+
+	struct Curve_Attribute {
+		float uv[2];
+	};
+
+	struct CurveKey {
+		float3 loc;
+		float radius;
+		float time;
+	};
+
+	/*curve data for hair - currently only contains key tangent instead*/
+	struct CurveData {
+		float3 tg;
+	};
+
 	/* Displacement */
 	enum DisplacementMethod {
 		DISPLACE_BUMP,
@@ -65,6 +87,11 @@ public:
 	vector shader;
 	vector smooth;
 
+	vector curve_keys;
+	vector curve_keysCD;
+	vector curve_segs;
+	vector curve_attrib;
+
 	vector used_shaders;
 	AttributeSet attributes;
 
@@ -82,6 +109,9 @@ public:
 	size_t tri_offset;
 	size_t vert_offset;
 
+	size_t curveseg_offset;
+	size_t curvekey_offset;
+
 	/* Functions */
 	Mesh();
 	~Mesh();
@@ -89,6 +119,9 @@ public:
 	void reserve(int numverts, int numfaces);
 	void clear();
 	void add_triangle(int v0, int v1, int v2, int shader, bool smooth);
+	void add_curvekey(float3 loc, float radius, float time);
+	void add_curve(int v0, int v1, int shader, int curveid);
+	void add_curveattrib(float u, float v);
 
 	void compute_bounds();
 	void add_face_normals();
@@ -96,6 +129,7 @@ public:
 
 	void pack_normals(Scene *scene, float4 *normal, float4 *vnormal);
 	void pack_verts(float4 *tri_verts, float4 *tri_vindex, size_t vert_offset);
+	void pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_seg_keys, size_t curvekey_offset);
 	void compute_bvh(SceneParams *params, Progress *progress, int n, int total);
 
 	bool need_attribute(Scene *scene, AttributeStandard std);
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index aef28449e44..23d6432616c 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -2240,6 +2240,52 @@ void ParticleInfoNode::compile(OSLCompiler& compiler)
 	compiler.add(this, "node_particle_info");
 }
 
+/* Hair Info */
+
+HairInfoNode::HairInfoNode()
+: ShaderNode("hair_info")
+{
+	add_output("Is Strand", SHADER_SOCKET_FLOAT);
+	add_output("Intercept", SHADER_SOCKET_FLOAT);
+	add_output("Thickness", SHADER_SOCKET_FLOAT);
+	add_output("Tangent Normal", SHADER_SOCKET_NORMAL);
+}
+
+void HairInfoNode::compile(SVMCompiler& compiler)
+{
+	ShaderOutput *out;
+	
+	out = output("Is Strand");
+	if(!out->links.empty()) {
+		compiler.stack_assign(out);
+		compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_IS_STRAND, out->stack_offset);
+	}
+
+	out = output("Intercept");
+	if(!out->links.empty()) {
+		compiler.stack_assign(out);
+		compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_INTERCEPT, out->stack_offset);
+	}
+
+	out = output("Thickness");
+	if(!out->links.empty()) {
+		compiler.stack_assign(out);
+		compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_THICKNESS, out->stack_offset);
+	}
+
+	out = output("Tangent Normal");
+	if(!out->links.empty()) {
+		compiler.stack_assign(out);
+		compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_TANGENT_NORMAL, out->stack_offset);
+	}
+
+}
+
+void HairInfoNode::compile(OSLCompiler& compiler)
+{
+	compiler.add(this, "NODE_HAIR_INFO");
+}
+
 /* Value */
 
 ValueNode::ValueNode()
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index 8012a99ff05..ee7afccb0e1 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -331,6 +331,11 @@ public:
 	void attributes(AttributeRequestSet *attributes);
 };
 
+class HairInfoNode : public ShaderNode {
+public:
+	SHADER_NODE_CLASS(HairInfoNode)
+};
+
 class ValueNode : public ShaderNode {
 public:
 	SHADER_NODE_CLASS(ValueNode)
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index 5df8e8c1368..588b4d50e1b 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -19,6 +19,7 @@
 #include "device.h"
 #include "light.h"
 #include "mesh.h"
+#include "curves.h"
 #include "object.h"
 #include "scene.h"
 
@@ -45,6 +46,7 @@ Object::Object()
 	motion.post = transform_identity();
 	use_motion = false;
 	use_holdout = false;
+	curverender = false;
 }
 
 Object::~Object()
@@ -86,6 +88,13 @@ void Object::apply_transform()
 	for(size_t i = 0; i < mesh->verts.size(); i++)
 		mesh->verts[i] = transform_point(&tfm, mesh->verts[i]);
 
+	for(size_t i = 0; i < mesh->curve_keys.size(); i++)
+		mesh->curve_keys[i].loc = transform_point(&tfm, mesh->curve_keys[i].loc);
+
+	for(size_t i = 0; i < mesh->curve_keysCD.size(); i++)
+		mesh->curve_keysCD[i].tg = transform_direction(&tfm, mesh->curve_keysCD[i].tg);
+
+
 	Attribute *attr_fN = mesh->attributes.find(ATTR_STD_FACE_NORMAL);
 	Attribute *attr_vN = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL);
 
@@ -133,6 +142,7 @@ void Object::tag_update(Scene *scene)
 		}
 	}
 
+	scene->curve_system_manager->need_update = true;
 	scene->mesh_manager->need_update = true;
 	scene->object_manager->need_update = true;
 }
@@ -189,6 +199,16 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
 					surface_area += triangle_area(p1, p2, p3);
 				}
 
+				foreach(Mesh::CurveSeg& t, mesh->curve_segs) {
+					float3 p1 = mesh->curve_keys[t.v[0]].loc;
+					float r1 = mesh->curve_keys[t.v[0]].radius;
+					float3 p2 = mesh->curve_keys[t.v[1]].loc;
+					float r2 = mesh->curve_keys[t.v[1]].radius;
+
+					/* currently ignores segment overlaps*/
+					surface_area += M_PI_F *(r1 + r2) * len(p1 - p2);
+				}
+
 				surface_area_map[mesh] = surface_area;
 			}
 			else
@@ -204,6 +224,16 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
 
 				surface_area += triangle_area(p1, p2, p3);
 			}
+
+			foreach(Mesh::CurveSeg& t, mesh->curve_segs) {
+				float3 p1 = mesh->curve_keys[t.v[0]].loc;
+				float r1 = mesh->curve_keys[t.v[0]].radius;
+				float3 p2 = mesh->curve_keys[t.v[1]].loc;
+				float r2 = mesh->curve_keys[t.v[1]].radius;
+
+				/* currently ignores segment overlaps*/
+				surface_area += M_PI_F *(r1 + r2) * len(p1 - p2);
+			}
 		}
 
 		/* pack in texture */
@@ -355,6 +385,7 @@ void ObjectManager::apply_static_transforms(Scene *scene, uint *object_flag, Pro
 void ObjectManager::tag_update(Scene *scene)
 {
 	need_update = true;
+	scene->curve_system_manager->need_update = true;
 	scene->mesh_manager->need_update = true;
 	scene->light_manager->need_update = true;
 }
diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h
index 9c9b11bc29c..9ba500ca4d6 100644
--- a/intern/cycles/render/object.h
+++ b/intern/cycles/render/object.h
@@ -48,6 +48,7 @@ public:
 	MotionTransform motion;
 	bool use_motion;
 	bool use_holdout;
+	bool curverender;
 
 	float3 dupli_generated;
 	float2 dupli_uv;
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index 8085cfdd3e6..093bfecf88e 100644
--- a/intern/cycles/render/scene.cpp
+++ b/intern/cycles/render/scene.cpp
@@ -29,6 +29,7 @@
 #include "mesh.h"
 #include "object.h"
 #include "particles.h"
+#include "curves.h"
 #include "scene.h"
 #include "svm.h"
 #include "osl.h"
@@ -54,6 +55,7 @@ Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_)
 	integrator = new Integrator();
 	image_manager = new ImageManager();
 	particle_system_manager = new ParticleSystemManager();
+	curve_system_manager = new CurveSystemManager();
 
 	/* OSL only works on the CPU */
 	if(device_info_.type == DEVICE_CPU)
@@ -96,6 +98,7 @@ void Scene::free_memory(bool final)
 		light_manager->device_free(device, &dscene);
 
 		particle_system_manager->device_free(device, &dscene);
+		curve_system_manager->device_free(device, &dscene);
 
 		if(!params.persistent_images || final)
 			image_manager->device_free(device, &dscene);
@@ -112,6 +115,7 @@ void Scene::free_memory(bool final)
 		delete shader_manager;
 		delete light_manager;
 		delete particle_system_manager;
+		delete curve_system_manager;
 		delete image_manager;
 	}
 	else {
@@ -165,6 +169,11 @@ void Scene::device_update(Device *device_, Progress& progress)
 
 	if(progress.get_cancel()) return;
 
+	progress.set_status("Updating Hair Systems");
+	curve_system_manager->device_update(device, &dscene, this, progress);
+
+	if(progress.get_cancel()) return;
+
 	progress.set_status("Updating Meshes");
 	mesh_manager->device_update(device, &dscene, this, progress);
 
@@ -242,7 +251,8 @@ bool Scene::need_reset()
 		|| filter->need_update
 		|| integrator->need_update
 		|| shader_manager->need_update
-		|| particle_system_manager->need_update);
+		|| particle_system_manager->need_update
+		|| curve_system_manager->need_update);
 }
 
 void Scene::reset()
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index ebe932e40e7..8b121d3b2fb 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -50,6 +50,7 @@ class Object;
 class ObjectManager;
 class ParticleSystemManager;
 class ParticleSystem;
+class CurveSystemManager;
 class Shader;
 class ShaderManager;
 class Progress;
@@ -62,6 +63,7 @@ public:
 	device_vector bvh_nodes;
 	device_vector object_node;
 	device_vector tri_woop;
+	device_vector prim_type;
 	device_vector prim_visibility;
 	device_vector prim_index;
 	device_vector prim_object;
@@ -72,6 +74,9 @@ public:
 	device_vector tri_vindex;
 	device_vector tri_verts;
 
+	device_vector cur_segs;
+	device_vector cur_keys;
+
 	/* objects */
 	device_vector objects;
 	device_vector objects_vector;
@@ -170,6 +175,7 @@ public:
 	MeshManager *mesh_manager;
 	ObjectManager *object_manager;
 	ParticleSystemManager *particle_system_manager;
+	CurveSystemManager *curve_system_manager;
 
 	/* default shaders */
 	int default_surface;
diff --git a/intern/cycles/util/util_boundbox.h b/intern/cycles/util/util_boundbox.h
index 6dd1c6c71e8..0c857f906ee 100644
--- a/intern/cycles/util/util_boundbox.h
+++ b/intern/cycles/util/util_boundbox.h
@@ -65,6 +65,13 @@ public:
 		max = ccl::max(max, pt);
 	}
 
+	__forceinline void grow(const float3& pt, float border)  
+	{
+		float3 shift = {border, border, border, 0.0f};
+		min = ccl::min(min, pt - shift);
+		max = ccl::max(max, pt + shift);
+	}
+
 	__forceinline void grow(const BoundBox& bbox)
 	{
 		grow(bbox.min);
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

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 74a30d91d20531dc257179362654ec205ca6894c Mon Sep 17 00:00:00 2001
From: Brecht Van Lommel 
Date: Fri, 28 Dec 2012 14:46:43 +0000
Subject: Fix cycles python error in some panels, was not updated for new list
 template yet.

---
 intern/cycles/blender/addon/ui.py | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 5253f5789ec..03724c9bb4c 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -231,7 +231,7 @@ class CyclesRender_PT_layers(CyclesButtonsPanel, Panel):
         rd = scene.render
 
         row = layout.row()
-        row.template_list(rd, "layers", rd.layers, "active_index", rows=2)
+        row.template_list("RENDER_UL_renderlayers", "", rd, "layers", rd.layers, "active_index", rows=2)
 
         col = row.column(align=True)
         col.operator("scene.render_layer_add", icon='ZOOMIN', text="")
@@ -377,7 +377,7 @@ class Cycles_PT_context_material(CyclesButtonsPanel, Panel):
         if ob:
             row = layout.row()
 
-            row.template_list(ob, "material_slots", ob, "active_material_index", rows=2)
+            row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=2)
 
             col = row.column(align=True)
             col.operator("object.material_slot_add", icon='ZOOMIN', text="")
@@ -932,7 +932,7 @@ class CyclesParticle_PT_textures(CyclesButtonsPanel, Panel):
         part = psys.settings
 
         row = layout.row()
-        row.template_list(part, "texture_slots", part, "active_texture_index", rows=2)
+        row.template_list("TEXTURE_UL_texslots", "", part, "texture_slots", part, "active_texture_index", rows=2)
 
         col = row.column(align=True)
         col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP'
-- 
cgit v1.2.3


From 357b02f65ff31392fd3b0b8a875af73bcd7977c9 Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Fri, 28 Dec 2012 16:11:04 +0000
Subject: Reversion of previous fix for Mac OS X scrollwheel, it appears I used
 10.7+ options, fails for 10.6.

Back to drawing board!
---
 intern/ghost/intern/GHOST_SystemCocoa.h  |  3 +++
 intern/ghost/intern/GHOST_SystemCocoa.mm | 25 +++++++++++++++++++++----
 2 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h
index 8598bd0862f..a1b372dac9a 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.h
+++ b/intern/ghost/intern/GHOST_SystemCocoa.h
@@ -293,6 +293,9 @@ protected:
 	 */
 	GHOST_TInt32 m_cursorDelta_x, m_cursorDelta_y;
 	
+	/** Multitouch trackpad availability */
+	bool m_hasMultiTouchTrackpad;
+	
 };
 
 #endif // __GHOST_SYSTEMCOCOA_H__
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index 742bf944946..39fd038d568 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -548,6 +548,7 @@ GHOST_SystemCocoa::GHOST_SystemCocoa()
 	int mib[2];
 	struct timeval boottime;
 	size_t len;
+	char *rstring = NULL;
 	
 	m_modifierMask =0;
 	m_cursorDelta_x=0;
@@ -565,7 +566,25 @@ GHOST_SystemCocoa::GHOST_SystemCocoa()
 	
 	sysctl(mib, 2, &boottime, &len, NULL, 0);
 	m_start_time = ((boottime.tv_sec*1000)+(boottime.tv_usec/1000));
-		
+	
+	//Detect multitouch trackpad
+	mib[0] = CTL_HW;
+	mib[1] = HW_MODEL;
+	sysctl( mib, 2, NULL, &len, NULL, 0 );
+	rstring = (char*)malloc( len );
+	sysctl( mib, 2, rstring, &len, NULL, 0 );
+	
+	//Hack on MacBook revision, as multitouch avail. function missing
+	//MacbookAir or MacBook version >= 5 (retina is MacBookPro10,1)
+	if (strstr(rstring,"MacBookAir") ||
+		(strstr(rstring,"MacBook") && (rstring[strlen(rstring)-3]>='5') && (rstring[strlen(rstring)-3]<='9')) ||
+		(strstr(rstring,"MacBook") && (rstring[strlen(rstring)-4]>='1') && (rstring[strlen(rstring)-4]<='9')))
+		m_hasMultiTouchTrackpad = true;
+	else m_hasMultiTouchTrackpad = false;
+	
+	free( rstring );
+	rstring = NULL;
+	
 	m_ignoreWindowSizedMessages = false;
 }
 
@@ -1560,9 +1579,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
 			
 		case NSScrollWheel:
 			{
-				
-				/* proper detection of trackpad or mouse scrollwheel */
-				if ([event momentumPhase] == NSEventPhaseNone && [event phase] == NSEventPhaseNone) {
+				if (!m_hasMultiTouchTrackpad) {
 					GHOST_TInt32 delta;
 					
 					double deltaF = [event deltaY];
-- 
cgit v1.2.3


From 81b371a451407f77a7a79e4ca1aec4744cb845aa Mon Sep 17 00:00:00 2001
From: Thomas Dinges 
Date: Fri, 28 Dec 2012 16:25:41 +0000
Subject: Cycles Hair UI: * Code cleanup, removed some unneeded code * Moved
 "Cycles Hair Rendering" panel above "Cycles Hair settings" * "Cycles Hair
 settings" panel is only visible when hair rendering ("use_curves") is
 enabled.

---
 intern/cycles/blender/addon/ui.py | 129 ++++++++++++++++++--------------------
 1 file changed, 62 insertions(+), 67 deletions(-)

diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 03724c9bb4c..c990e4e4e40 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -944,95 +944,90 @@ class CyclesParticle_PT_textures(CyclesButtonsPanel, Panel):
         else:
             slot = part.texture_slots[part.active_texture_index]
             layout.template_ID(slot, "texture", new="texture.new")
-            
-class CyclesParticle_PT_CurveSettings(CyclesButtonsPanel, Panel):
-    bl_label = "Cycles Hair Settings"
+
+class CyclesRender_PT_CurveRendering(CyclesButtonsPanel, Panel):
+    bl_label = "Cycles Hair Rendering"
     bl_context = "particle"
     
     @classmethod
     def poll(cls, context):
         psys = context.particle_system
         device_type = context.user_preferences.system.compute_device_type
-        if context.scene.cycles.feature_set == 'EXPERIMENTAL' and (context.scene.cycles.device == 'CPU' or device_type == 'NONE'):
-            if CyclesButtonsPanel.poll(context) and psys:
-                return True
-
-        return False
-
+        experimental = context.scene.cycles.feature_set == 'EXPERIMENTAL' and (context.scene.cycles.device == 'CPU' or device_type == 'NONE')
+        return CyclesButtonsPanel.poll(context) and experimental and psys
+        
+    def draw_header(self, context):
+        cscene = context.scene.cycles_curves
+        self.layout.prop(cscene, "use_curves", text="")
+    
     def draw(self, context):
         layout = self.layout
         
-        psys = context.particle_settings
+        scene = context.scene
+        cscene = scene.cycles_curves
         
-        cpsys = psys.cycles
+        layout.active = cscene.use_curves
         
-        row = layout.row()
-        row.prop(cpsys, "shape", text="Shape")
-        row.prop(cpsys, "use_closetip", text="Close tip")
-        row = layout.row()
-        row.prop(cpsys, "root_width", text="Root Width multiplier")
-        row = layout.row()
-        row.prop(cpsys, "tip_width", text="Tip Width multiplier")
-
-class CyclesRender_PT_CurveRendering(CyclesButtonsPanel, Panel):
-    bl_label = "Cycles Hair Rendering"
+        layout.prop(cscene, "preset", text="Mode")
+        
+        if cscene.preset == 'CUSTOM':
+            layout.prop(cscene, "primitive", text="Primitive")
+        
+            if cscene.primitive == 'TRIANGLES':
+                layout.prop(cscene, "triangle_method", text="Method")
+                if cscene.triangle_method == 'TESSELATED':
+                    layout.prop(cscene, "resolution", text="Resolution")
+                layout.prop(cscene, "use_smooth", text="Smooth")
+            elif cscene.primitive == 'LINE_SEGMENTS':
+                layout.prop(cscene, "use_backfacing", text="Check back-faces")
+                
+                row = layout.row()
+                row.prop(cscene, "use_encasing", text="Exclude encasing")
+                sub = row.row()
+                sub.active = cscene.use_encasing
+                sub.prop(cscene, "encasing_ratio", text="Ratio for encasing")
+                
+                layout.prop(cscene, "line_method", text="Method")
+                layout.prop(cscene, "use_tangent_normal", text="Use tangent normal as default")
+                layout.prop(cscene, "use_tangent_normal_geometry", text="Use tangent normal geometry")
+                layout.prop(cscene, "use_tangent_normal_correction", text="Correct tangent normal for slope")
+                layout.prop(cscene, "interpolation", text="Interpolation")
+                
+                row = layout.row()
+                row.prop(cscene, "segments", text="Segments")
+                row.prop(cscene, "normalmix", text="Ray Mix")
+            
+            row = layout.row()
+            row.prop(cscene, "use_cache", text="Export cache with children")
+            if cscene.use_cache:
+                row.prop(cscene, "use_parents", text="Include parents")  
+            
+class CyclesParticle_PT_CurveSettings(CyclesButtonsPanel, Panel):
+    bl_label = "Cycles Hair Settings"
     bl_context = "particle"
     
     @classmethod
     def poll(cls, context):
+        use_curves = context.scene.cycles_curves.use_curves
         device_type = context.user_preferences.system.compute_device_type
-        if CyclesButtonsPanel.poll(context):
-            if context.scene.cycles.feature_set == 'EXPERIMENTAL' and (context.scene.cycles.device == 'CPU' or device_type == 'NONE'):
-                return True
+        experimental = context.scene.cycles.feature_set == 'EXPERIMENTAL' and (context.scene.cycles.device == 'CPU' or device_type == 'NONE')
+        return CyclesButtonsPanel.poll(context) and experimental and use_curves
 
-        return False
-    
     def draw(self, context):
         layout = self.layout
-        scene = context.scene
-        csscene = scene.cycles_curves
         
-        row = layout.row()
-        row.prop(csscene, "use_curves", text="Enable Cycles Hair")
-        row = layout.row()
-        row.prop(csscene, "preset", text="Mode")
+        psys = context.particle_settings
+        cpsys = psys.cycles
         
-        if csscene.preset == 'CUSTOM':
-            row = layout.row()
-            row.prop(csscene, "primitive", text="Primitive")
-            row = layout.row()
+        row = layout.row()
+        row.prop(cpsys, "shape", text="Shape")
+        row.prop(cpsys, "use_closetip", text="Close tip")
         
-            if csscene.primitive == 'TRIANGLES':
-                row.prop(csscene, "triangle_method", text="Method")
-                if csscene.triangle_method == 'TESSELATED':
-                    row = layout.row()
-                    row.prop(csscene, "resolution", text="Resolution")
-                row = layout.row()
-                row.prop(csscene, "use_smooth", text="Smooth")
-            elif csscene.primitive == 'LINE_SEGMENTS':
-                row.prop(csscene, "use_backfacing", text="Check back-faces")
-                row = layout.row()
-                row.prop(csscene, "use_encasing", text="Exclude encasing")
-                if csscene.use_encasing:
-                    row.prop(csscene, "encasing_ratio", text="Ratio for encasing")
-                row = layout.row()
-                row.prop(csscene, "line_method", text="Method")
-                row = layout.row()
-                row.prop(csscene, "use_tangent_normal", text="Use tangent normal as default")
-                row = layout.row()
-                row.prop(csscene, "use_tangent_normal_geometry", text="Use tangent normal geometry")
-                row = layout.row()
-                row.prop(csscene, "use_tangent_normal_correction", text="Correct tangent normal for slope")
-                row = layout.row()
-                row.prop(csscene, "interpolation", text="Interpolation")
-                row = layout.row()
-                row.prop(csscene, "segments", text="Segments")
-                row = layout.row()
-                row.prop(csscene, "normalmix", text="Ray Mix")
-            row = layout.row()
-            row.prop(csscene, "use_cache", text="Export cache with children")
-            if csscene.use_cache:
-                row.prop(csscene, "use_parents", text="Include parents")  
+        layout.label(text="Width multiplier:")
+        row = layout.row()
+        row.prop(cpsys, "root_width", text="Root")
+        row.prop(cpsys, "tip_width", text="Tip")
+
 
 class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel):
     bl_label = "Simplify"
-- 
cgit v1.2.3


From cfd0b3c5f2efc80ae0276721b5cae0686cf94093 Mon Sep 17 00:00:00 2001
From: Brecht Van Lommel 
Date: Fri, 28 Dec 2012 18:21:07 +0000
Subject: Fix OSL distance() of point to line segment function not being
 available, implemented now in stdosl.h.

---
 intern/cycles/kernel/shaders/stdosl.h | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/intern/cycles/kernel/shaders/stdosl.h b/intern/cycles/kernel/shaders/stdosl.h
index 69ca6b32c36..f340eaff95f 100644
--- a/intern/cycles/kernel/shaders/stdosl.h
+++ b/intern/cycles/kernel/shaders/stdosl.h
@@ -161,6 +161,15 @@ vector cross (vector a, vector b) BUILTIN;
 float dot (vector a, vector b) BUILTIN;
 float length (vector v) BUILTIN;
 float distance (point a, point b) BUILTIN;
+float distance (point a, point b, point q)
+{
+    vector d = b - a;
+    float dd = dot(d, d);
+    if(dd == 0.0)
+        return distance(q, a);
+    float t = dot(q - a, d)/dd;
+    return distance(q, a + clamp(t, 0.0, 1.0)*d);
+}
 normal normalize (normal v) BUILTIN;
 vector normalize (vector v) BUILTIN;
 vector faceforward (vector N, vector I, vector Nref) BUILTIN;
@@ -304,7 +313,7 @@ color transformc (string to, color x)
         r = color (dot (vector(0.299,  0.587,  0.114), (vector)x),
                    dot (vector(0.596, -0.275, -0.321), (vector)x),
                    dot (vector(0.212, -0.523,  0.311), (vector)x));
-    else if (to == "xyz")
+    else if (to == "XYZ")
         r = color (dot (vector(0.412453, 0.357580, 0.180423), (vector)x),
                    dot (vector(0.212671, 0.715160, 0.072169), (vector)x),
                    dot (vector(0.019334, 0.119193, 0.950227), (vector)x));
@@ -366,7 +375,7 @@ color transformc (string from, string to, color x)
         r = color (dot (vector(1,  0.9557,  0.6199), (vector)x),
                    dot (vector(1, -0.2716, -0.6469), (vector)x),
                    dot (vector(1, -1.1082,  1.7051), (vector)x));
-    else if (from == "xyz")
+    else if (from == "XYZ")
         r = color (dot (vector( 3.240479, -1.537150, -0.498535), (vector)x),
                    dot (vector(-0.969256,  1.875991,  0.041556), (vector)x),
                    dot (vector( 0.055648, -0.204043,  1.057311), (vector)x));
@@ -409,6 +418,8 @@ int startswith (string s, string prefix) BUILTIN;
 int endswith (string s, string suffix) BUILTIN;
 string substr (string s, int start, int len) BUILTIN;
 string substr (string s, int start) { return substr (s, start, strlen(s)); }
+float strtof (string str) BUILTIN;
+int strtoi (string str) BUILTIN;
 
 // Define concat in terms of shorter concat
 string concat (string a, string b, string c) {
-- 
cgit v1.2.3


From 4e24bcf6c98d0a76288ac61e8d4c910d6e34933a Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Fri, 28 Dec 2012 19:10:21 +0000
Subject: Testing commit for OS X trackpad and scroll events.

Now:
- code is wrapped for OS X releases (10.6 and 10.7)
- It now detects scrollwheel (old mouse) and gesture strokes (mighty mouse or trackpad).

If you have 10.6, things will work as for release.

Next todo for tomorrow: make trackpad work actually smooth and not with steps.
Will also try to figure out the device type, to handle mighty mouse differently.
---
 intern/ghost/intern/GHOST_SystemCocoa.mm | 14 +++++++++++++-
 intern/ghost/intern/GHOST_WindowCocoa.mm |  5 +++++
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index 39fd038d568..a32759feb59 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -1577,9 +1577,21 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
 			}
 			break;
 			
+		case NSEventTypeBeginGesture:
+			m_hasMultiTouchTrackpad = true;
+			break;
+		case NSEventTypeEndGesture:
+			m_hasMultiTouchTrackpad = false;
+			break;
+			
 		case NSScrollWheel:
 			{
-				if (!m_hasMultiTouchTrackpad) {
+				int momentum = 0;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
+				momentum = [event momentumPhase];
+#endif
+				
+				if (!m_hasMultiTouchTrackpad && momentum==0) {
 					GHOST_TInt32 delta;
 					
 					double deltaF = [event deltaY];
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm
index 471505538ba..bceb795c47d 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.mm
+++ b/intern/ghost/intern/GHOST_WindowCocoa.mm
@@ -595,6 +595,11 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
 	
 	[m_window setAcceptsMouseMovedEvents:YES];
 	
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
+	NSView *view = [m_window contentView];
+	[view setAcceptsTouchEvents:YES];
+#endif
+	
 	[m_window registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType,
 										  NSStringPboardType, NSTIFFPboardType, nil]];
 										  
-- 
cgit v1.2.3


From 01fe30f50b47e14a3fea1c4255221420595c3e3c Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Fri, 28 Dec 2012 19:26:25 +0000
Subject: Hrm... replacing

MAC_OS_X_VERSION_MAX_ALLOWED
with
MAC_OS_X_VERSION_MIN_REQUIRED
---
 intern/ghost/intern/GHOST_SystemCocoa.mm | 2 +-
 intern/ghost/intern/GHOST_WindowCocoa.mm | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index a32759feb59..08750d940b4 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -1587,7 +1587,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
 		case NSScrollWheel:
 			{
 				int momentum = 0;
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
 				momentum = [event momentumPhase];
 #endif
 				
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm
index bceb795c47d..2d58f0612ce 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.mm
+++ b/intern/ghost/intern/GHOST_WindowCocoa.mm
@@ -595,7 +595,7 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
 	
 	[m_window setAcceptsMouseMovedEvents:YES];
 	
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
 	NSView *view = [m_window contentView];
 	[view setAcceptsTouchEvents:YES];
 #endif
-- 
cgit v1.2.3


From f098407f027572962f3d5494e9c9f0679b8f81b2 Mon Sep 17 00:00:00 2001
From: Thomas Dinges 
Date: Fri, 28 Dec 2012 20:32:29 +0000
Subject: i18 Spell check: * Wrong comma sequence in spell_check_utils.py

---
 release/scripts/modules/bl_i18n_utils/spell_check_utils.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/release/scripts/modules/bl_i18n_utils/spell_check_utils.py b/release/scripts/modules/bl_i18n_utils/spell_check_utils.py
index 393b2d17697..591b92dba42 100644
--- a/release/scripts/modules/bl_i18n_utils/spell_check_utils.py
+++ b/release/scripts/modules/bl_i18n_utils/spell_check_utils.py
@@ -196,7 +196,7 @@ dict_uimsgs = {
     "symmetrize",
     "trackability",
     "transmissivity",
-    "rasterized", "rasterization",, "rasterizer"
+    "rasterized", "rasterization", "rasterizer",
     "renderer", "renderable", "renderability",
 
     # Abbreviations
-- 
cgit v1.2.3


From 19c4ae50e4255a978b4fb7cdc2a97c235af68929 Mon Sep 17 00:00:00 2001
From: Dan Eicher 
Date: Fri, 28 Dec 2012 23:30:34 +0000
Subject: Add datafiles/locale/languages to blender.spec.in for CPack

---
 build_files/package_spec/rpm/blender.spec.in | 1 +
 1 file changed, 1 insertion(+)

diff --git a/build_files/package_spec/rpm/blender.spec.in b/build_files/package_spec/rpm/blender.spec.in
index a95fce80103..e75cc8ec7a6 100644
--- a/build_files/package_spec/rpm/blender.spec.in
+++ b/build_files/package_spec/rpm/blender.spec.in
@@ -77,6 +77,7 @@ fi || :
 %{_bindir}/%{name}
 %{_datadir}/%{name}/%{blender_api}/datafiles/fonts
 %{_datadir}/%{name}/%{blender_api}/datafiles/colormanagement
+%{_datadir}/%{name}/%{blender_api}/datafiles/locale/languages
 %{_datadir}/%{name}/%{blender_api}/scripts
 %{_datadir}/icons/hicolor/*/apps/%{name}.*
 %{_datadir}/applications/%{name}.desktop
-- 
cgit v1.2.3


From 6b211bac153aefce1087e6ac337613de17c4a53f Mon Sep 17 00:00:00 2001
From: Thomas Dinges 
Date: Sat, 29 Dec 2012 01:14:03 +0000
Subject: Fix for last commit, hair settings panel should also check on psys.

---
 intern/cycles/blender/addon/ui.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index c990e4e4e40..2d059b365a1 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -1008,7 +1008,7 @@ class CyclesParticle_PT_CurveSettings(CyclesButtonsPanel, Panel):
     
     @classmethod
     def poll(cls, context):
-        use_curves = context.scene.cycles_curves.use_curves
+        use_curves = context.scene.cycles_curves.use_curves and context.particle_system
         device_type = context.user_preferences.system.compute_device_type
         experimental = context.scene.cycles.feature_set == 'EXPERIMENTAL' and (context.scene.cycles.device == 'CPU' or device_type == 'NONE')
         return CyclesButtonsPanel.poll(context) and experimental and use_curves
-- 
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(-)

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 6b05c887d3395e6377a24e0fdac6500a61d594c7 Mon Sep 17 00:00:00 2001
From: Thomas Dinges 
Date: Sat, 29 Dec 2012 01:57:32 +0000
Subject: Cycles Hair: * Implemented the Hair Info Node for OSL.

---
 intern/cycles/kernel/osl/osl_services.cpp       | 28 ++++++++++++++++++++++
 intern/cycles/kernel/osl/osl_services.h         |  4 ++++
 intern/cycles/kernel/shaders/CMakeLists.txt     |  1 +
 intern/cycles/kernel/shaders/node_hair_info.osl | 32 +++++++++++++++++++++++++
 intern/cycles/render/nodes.cpp                  |  2 +-
 5 files changed, 66 insertions(+), 1 deletion(-)
 create mode 100644 intern/cycles/kernel/shaders/node_hair_info.osl

diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp
index 498d10f385b..64c4d109452 100644
--- a/intern/cycles/kernel/osl/osl_services.cpp
+++ b/intern/cycles/kernel/osl/osl_services.cpp
@@ -74,6 +74,12 @@ ustring OSLRenderServices::u_geom_numpolyvertices("geom:numpolyvertices");
 ustring OSLRenderServices::u_geom_trianglevertices("geom:trianglevertices");
 ustring OSLRenderServices::u_geom_polyvertices("geom:polyvertices");
 ustring OSLRenderServices::u_geom_name("geom:name");
+#ifdef __HAIR__
+ustring OSLRenderServices::u_curve_is_strand("curve:is_strand");
+ustring OSLRenderServices::u_curve_intercept("curve:intercept");
+ustring OSLRenderServices::u_curve_thickness("curve:thickness");
+ustring OSLRenderServices::u_curve_tangent_normal("curve:tangent_normal");
+#endif
 ustring OSLRenderServices::u_path_ray_length("path:ray_length");
 ustring OSLRenderServices::u_trace("trace");
 ustring OSLRenderServices::u_hit("hit");
@@ -593,6 +599,8 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD
 		float3 f = particle_angular_velocity(kg, particle_id);
 		return set_attribute_float3(f, type, derivatives, val);
 	}
+	
+	/* Geometry Attributes */
 	else if (name == u_geom_numpolyvertices) {
 		return set_attribute_int(3, type, derivatives, val);
 	}
@@ -612,6 +620,26 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD
 		ustring object_name = kg->osl->object_names[sd->object];
 		return set_attribute_string(object_name, type, derivatives, val);
 	}
+	
+#ifdef __HAIR__
+	/* Hair Attributes */
+	else if (name == u_curve_is_strand) {
+		float f = !(sd->curve_seg == ~0);
+		return set_attribute_float(f, type, derivatives, val);
+	}
+	else if (name == u_curve_intercept) {
+		float f = intercept(kg, sd->curve_seg, sd->prim, sd->u);
+		return set_attribute_float(f, type, derivatives, val);
+	}
+	else if (name == u_curve_thickness) {
+		float f = 2 * hair_radius(kg, sd->curve_seg, sd->u);
+		return set_attribute_float(f, type, derivatives, val);
+	}
+	else if (name == u_curve_tangent_normal) {
+		float3 f = hair_tangent_normal(kg, sd);
+		return set_attribute_float3(f, type, derivatives, val);
+	}
+#endif
 	else
 		return false;
 }
diff --git a/intern/cycles/kernel/osl/osl_services.h b/intern/cycles/kernel/osl/osl_services.h
index cd4a4163209..9b7c9a423ff 100644
--- a/intern/cycles/kernel/osl/osl_services.h
+++ b/intern/cycles/kernel/osl/osl_services.h
@@ -130,6 +130,10 @@ public:
 	static ustring u_geom_trianglevertices;
 	static ustring u_geom_polyvertices;
 	static ustring u_geom_name;
+	static ustring u_curve_is_strand;
+	static ustring u_curve_intercept;
+	static ustring u_curve_thickness;
+	static ustring u_curve_tangent_normal;
 	static ustring u_path_ray_length;
 	static ustring u_trace;
 	static ustring u_hit;
diff --git a/intern/cycles/kernel/shaders/CMakeLists.txt b/intern/cycles/kernel/shaders/CMakeLists.txt
index 70fc8610c98..acae46f1615 100644
--- a/intern/cycles/kernel/shaders/CMakeLists.txt
+++ b/intern/cycles/kernel/shaders/CMakeLists.txt
@@ -27,6 +27,7 @@ set(SRC_OSL
 	node_glass_bsdf.osl
 	node_glossy_bsdf.osl
 	node_gradient_texture.osl
+	node_hair_info.osl
 	node_holdout.osl
 	node_hsv.osl
 	node_image_texture.osl
diff --git a/intern/cycles/kernel/shaders/node_hair_info.osl b/intern/cycles/kernel/shaders/node_hair_info.osl
new file mode 100644
index 00000000000..a44fc67f4bc
--- /dev/null
+++ b/intern/cycles/kernel/shaders/node_hair_info.osl
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+#include "stdosl.h"
+
+shader node_hair_info(
+	output float IsStrand = 0.0,
+	output float Intercept = 0.0,
+	output float Thickness = 0.0,
+	output normal TangentNormal = N)
+{
+	getattribute("curve:is_strand", IsStrand);
+	getattribute("curve:intercept", Intercept);
+	getattribute("curve:thickness", Thickness);
+	getattribute("curve:tangent_normal", TangentNormal);
+}
+
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 23d6432616c..13e9ae81cf0 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -2283,7 +2283,7 @@ void HairInfoNode::compile(SVMCompiler& compiler)
 
 void HairInfoNode::compile(OSLCompiler& compiler)
 {
-	compiler.add(this, "NODE_HAIR_INFO");
+	compiler.add(this, "node_hair_info");
 }
 
 /* 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(-)

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 bc9ad1270bf3d9b2dbcc34afb39590db3dadee87 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Sat, 29 Dec 2012 03:19:30 +0000
Subject: set line endings to native & mime type to text/plain for
 .app/Contents/MacOS/xxx files.

---
 release/darwin/blender.app/Contents/MacOS/blender             | 2 +-
 release/darwin/blenderplayer.app/Contents/MacOS/blenderplayer | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/release/darwin/blender.app/Contents/MacOS/blender b/release/darwin/blender.app/Contents/MacOS/blender
index 5e05e74a307..48cdce85287 100644
--- a/release/darwin/blender.app/Contents/MacOS/blender
+++ b/release/darwin/blender.app/Contents/MacOS/blender
@@ -1 +1 @@
-placeholder
+placeholder
diff --git a/release/darwin/blenderplayer.app/Contents/MacOS/blenderplayer b/release/darwin/blenderplayer.app/Contents/MacOS/blenderplayer
index 5e05e74a307..48cdce85287 100644
--- a/release/darwin/blenderplayer.app/Contents/MacOS/blenderplayer
+++ b/release/darwin/blenderplayer.app/Contents/MacOS/blenderplayer
@@ -1 +1 @@
-placeholder
+placeholder
-- 
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(-)

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(-)

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 ed713803f5ef4f0ad13e99e595556857d397f26d Mon Sep 17 00:00:00 2001
From: Lukas Toenne 
Date: Sat, 29 Dec 2012 08:46:27 +0000
Subject: Fix for the NODE_OT_add_node operator. The way python classes were
 subclassed does not work with the registration mechanism. Combined both
 node_add and node_add_move operators into a single general operator with a
 flag. When use_transform is set, the operator will start transform on the new
 nodes after inserting.

---
 release/scripts/startup/bl_operators/node.py | 31 ++++++++++------------------
 1 file changed, 11 insertions(+), 20 deletions(-)

diff --git a/release/scripts/startup/bl_operators/node.py b/release/scripts/startup/bl_operators/node.py
index 071eb2e75f9..39e00f94953 100644
--- a/release/scripts/startup/bl_operators/node.py
+++ b/release/scripts/startup/bl_operators/node.py
@@ -20,7 +20,7 @@
 
 import bpy
 from bpy.types import Operator
-from bpy.props import EnumProperty, StringProperty
+from bpy.props import BoolProperty, EnumProperty, StringProperty
 
 # Base class for node 'Add' operators
 class NodeAddOperator():
@@ -75,6 +75,11 @@ class NODE_OT_add_node(NodeAddOperator, Operator):
             name="Group tree",
             description="Group node tree name",
             )
+    use_transform = BoolProperty(
+            name="Use Transform",
+            description="Start transform operator after inserting the node",
+            default = False,
+            )
     def execute(self, context):
         node = self.create_node(context, self.type)
 
@@ -84,27 +89,13 @@ class NODE_OT_add_node(NodeAddOperator, Operator):
 
         return {'FINISHED'}
 
-
-# Adds a node and immediately starts the transform operator for inserting in a tree
-class NODE_OT_add_node_move(NODE_OT_add_node):
-    '''Add a node to the active tree and start transform'''
-    bl_idname = "node.add_node_move"
-    bl_label = "Add Node and Move"
-
-    type = StringProperty(
-            name="Node Type",
-            description="Node type",
-            )
-    # optional group tree parameter for group nodes
-    group_tree = StringProperty(
-            name="Group tree",
-            description="Group node tree name",
-            )
-
     def invoke(self, context, event):
         self.store_mouse_cursor(context, event)
-        self.execute(context)
-        return bpy.ops.transform.translate('INVOKE_DEFAULT')
+        result = self.execute(context)
+        if self.use_transform and ('FINISHED' in result):
+            return bpy.ops.transform.translate('INVOKE_DEFAULT')
+        else:
+            return result
 
 
 # XXX These node item lists should actually be generated by a callback at
-- 
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(-)

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.

---
 doc/python_api/rst/bge.types.rst                           | 6 ++++++
 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 ++
 7 files changed, 30 insertions(+)

diff --git a/doc/python_api/rst/bge.types.rst b/doc/python_api/rst/bge.types.rst
index ae03debb4f8..a86272ddf5c 100644
--- a/doc/python_api/rst/bge.types.rst
+++ b/doc/python_api/rst/bge.types.rst
@@ -3755,6 +3755,12 @@ Types
 
       :type: int
 
+   .. attribute:: jumpCount
+
+      The current jump count. 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.
+
+      :type: int
+
    .. method:: jump()
 
       The character jumps based on it's jump speed.
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.

---
 release/scripts/startup/bl_ui/space_userpref.py    |  22 +++-
 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 +
 11 files changed, 309 insertions(+), 4 deletions(-)
 create mode 100644 source/blender/blenkernel/BKE_addon.h
 create mode 100644 source/blender/blenkernel/intern/addon.c

diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 1a80a32f957..4b5e2839cf1 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -1162,7 +1162,8 @@ class USERPREF_PT_addons(Panel):
                         continue
 
                 # Addon UI Code
-                box = col.column().box()
+                col_box = col.column()
+                box = col_box.box()
                 colsub = box.column()
                 row = colsub.row()
 
@@ -1225,6 +1226,25 @@ class USERPREF_PT_addons(Panel):
                         for i in range(4 - tot_row):
                             split.separator()
 
+                    # Show addon user preferences
+                    if is_enabled:
+                        addon_preferences = userpref.addons[module_name].preferences
+                        if addon_preferences is not None:
+                            draw = getattr(addon_preferences, "draw", None)
+                            if draw is not None:
+                                addon_preferences_class = type(addon_preferences)
+                                box_prefs = col_box.box()
+                                box_prefs.label("Preferences:")
+                                addon_preferences_class.layout = box_prefs
+                                try:
+                                    draw(context)
+                                except:
+                                    import traceback
+                                    traceback.print_exc()
+                                    box_prefs.label(text="Error (see console)", icon='ERROR')
+                                del addon_preferences_class.layout
+
+
         # Append missing scripts
         # First collect scripts that are used but have no script file.
         module_names = {mod.__name__ for mod, info in addons}
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 7684f2e5ac7a5b2457684592972846c7636efaea Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Sat, 29 Dec 2012 11:00:45 +0000
Subject: Mac OS X 10.7 supports new trackpad (and mighty mouse) events with
 nice seamless scrolling and inertia.

Now Blender uses this - if you have 10.7. Otherwise it just falls back on the
old code.

Try it, makes a huge difference :)

Next todo: how to configure this well, so you can have trackpad (or mighty mouse)
zoom as default in 3d views.
---
 intern/ghost/intern/GHOST_SystemCocoa.mm | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index 08750d940b4..fd777bd234f 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -1590,7 +1590,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
 				momentum = [event momentumPhase];
 #endif
-				
+				/* standard scrollwheel case */
 				if (!m_hasMultiTouchTrackpad && momentum==0) {
 					GHOST_TInt32 delta;
 					
@@ -1605,9 +1605,18 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
 				else {
 					NSPoint mousePos = [cocoawindow mouseLocationOutsideOfEventStream];
 					GHOST_TInt32 x, y;
-					double dx = [event deltaX];
-					double dy = -[event deltaY];
+					double dx;
+					double dy;
 					
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
+					/* with 10.7 nice scrolling deltas are supported */
+					dx = [event scrollingDeltaX];
+					dy = [event scrollingDeltaY];
+
+#else
+					/* trying to pretend you have nice scrolls... */
+					dx = [event deltaX];
+					dy = -[event deltaY];
 					const double deltaMax = 50.0;
 					
 					if ((dx == 0) && (dy == 0)) break;
@@ -1624,9 +1633,10 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
 					else          dy += 0.5;
 					if      (dy < -deltaMax) dy= -deltaMax;
 					else if (dy >  deltaMax) dy=  deltaMax;
-
-					window->clientToScreenIntern(mousePos.x, mousePos.y, x, y);
+					
 					dy = -dy;
+#endif
+					window->clientToScreenIntern(mousePos.x, mousePos.y, x, y);
 
 					pushEvent(new GHOST_EventTrackpad([event timestamp] * 1000, window, GHOST_kTrackpadEventScroll, x, y, dx, dy));
 				}
-- 
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(-)

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 4ed4be1fc225e714e21445b82fa129c26552d449 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Sat, 29 Dec 2012 11:07:31 +0000
Subject: example use of addon preferences.

---
 .../examples/bpy.types.AddonPreferences.1.py       | 70 ++++++++++++++++++++++
 1 file changed, 70 insertions(+)
 create mode 100644 doc/python_api/examples/bpy.types.AddonPreferences.1.py

diff --git a/doc/python_api/examples/bpy.types.AddonPreferences.1.py b/doc/python_api/examples/bpy.types.AddonPreferences.1.py
new file mode 100644
index 00000000000..08de6f4f5a9
--- /dev/null
+++ b/doc/python_api/examples/bpy.types.AddonPreferences.1.py
@@ -0,0 +1,70 @@
+bl_info = {
+    "name": "Example Addon Preferences",
+    "author": "Your Name Here",
+    "version": (1, 0),
+    "blender": (2, 65, 0),
+    "location": "SpaceBar Search -> Addon Preferences Example",
+    "description": "Example Addon",
+    "warning": "",
+    "wiki_url": "",
+    "tracker_url": "",
+    "category": "Object"}
+
+
+import bpy
+from bpy.types import Operator, AddonPreferences
+from bpy.props import StringProperty, IntProperty, BoolProperty
+
+
+class ExampleAddonPreferences(AddonPreferences):
+    bl_idname = __name__
+
+    filepath = StringProperty(
+            name="Example File Path",
+            subtype='FILE_PATH',
+            )
+    number = IntProperty(
+            name="Example Number",
+            default=4,
+            )
+    boolean = BoolProperty(
+            name="Example Boolean",
+            default=False,
+            )
+
+    def draw(self, context):
+        layout = self.layout
+        layout.label(text="This is a preferences view for our addon")
+        layout.prop(self, "filepath")
+        layout.prop(self, "number")
+        layout.prop(self, "boolean")
+
+
+class OBJECT_OT_addon_prefs_example(Operator):
+    """Display example preferences"""
+    bl_idname = "object.addon_prefs_example"
+    bl_label = "Addon Preferences Example"
+    bl_options = {'REGISTER', 'UNDO'}
+
+    def execute(self, context):
+        user_preferences = context.user_preferences
+        addon_prefs = user_preferences.addons[__name__].preferences
+
+        info = ("Path: %s, Number: %d, Boolean %r" %
+                (addon_prefs.filepath, addon_prefs.number, addon_prefs.boolean))
+
+        self.report({'INFO'}, info)
+        print(info)
+
+        return {'FINISHED'}
+
+
+# Registration
+def register():
+    bpy.utils.register_class(OBJECT_OT_addon_prefs_example)
+    bpy.utils.register_class(ExampleAddonPreferences)
+
+
+def unregister():
+    bpy.utils.unregister_class(OBJECT_OT_addon_prefs_example)
+    bpy.utils.unregister_class(ExampleAddonPreferences)
-- 
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(-)

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(-)

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(-)

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(-)

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(-)

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(-)

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(-)

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(-)

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(-)

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'.
---
 doc/python_api/sphinx_doc_gen.py                   |   4 +
 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 +-
 13 files changed, 391 insertions(+), 8 deletions(-)
 create mode 100644 source/blender/editors/space_text/text_format_osl.c

diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py
index 441a6c04efe..af6ddac937e 100644
--- a/doc/python_api/sphinx_doc_gen.py
+++ b/doc/python_api/sphinx_doc_gen.py
@@ -612,6 +612,10 @@ def pyfunc2sphinx(ident, fw, identifier, py_func, is_class=True):
     '''
     function or class method to sphinx
     '''
+    
+    if type(py_func) == type(bpy.types.Space.draw_handler_add):
+        return
+    
     arg_str = inspect.formatargspec(*inspect.getargspec(py_func))
 
     if not is_class:
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(-)

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 eae167998a17481d4758b87ad068111fa8e3d881 Mon Sep 17 00:00:00 2001
From: Jens Verwiebe 
Date: Sat, 29 Dec 2012 19:51:44 +0000
Subject: OSX: fix magic mouse swipes compiling on with
 MAC_OS_X_VERSION_MIN_REQUIRED by checking address not value

---
 intern/ghost/intern/GHOST_SystemCocoa.mm | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index fd777bd234f..d88b90d8f05 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -1590,8 +1590,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
 				momentum = [event momentumPhase];
 #endif
-				/* standard scrollwheel case */
-				if (!m_hasMultiTouchTrackpad && momentum==0) {
+				/* standard scrollwheel case, NULL check address !!! of momentum */
+				if (!m_hasMultiTouchTrackpad && &momentum == NULL) {
 					GHOST_TInt32 delta;
 					
 					double deltaF = [event deltaY];
-- 
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(-)

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(-)

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(-)

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(-)

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(-)

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.

---
 release/scripts/startup/bl_ui/space_text.py        |  25 ++++-
 release/scripts/templates/addon_add_object.py      |  92 ----------------
 release/scripts/templates/background_job.py        | 122 ---------------------
 release/scripts/templates/batch_export.py          |  33 ------
 release/scripts/templates/bmesh_simple.py          |  22 ----
 release/scripts/templates/bmesh_simple_editmode.py |  23 ----
 release/scripts/templates/builtin_keyingset.py     |  37 -------
 release/scripts/templates/driver_functions.py      |  35 ------
 release/scripts/templates/gamelogic.py             |  73 ------------
 release/scripts/templates/gamelogic_module.py      |  27 -----
 release/scripts/templates/gamelogic_simple.py      |  17 ---
 release/scripts/templates/operator_file_export.py  |  72 ------------
 release/scripts/templates/operator_file_import.py  |  75 -------------
 release/scripts/templates/operator_mesh_add.py     | 122 ---------------------
 release/scripts/templates/operator_modal.py        |  51 ---------
 release/scripts/templates/operator_modal_draw.py   |  79 -------------
 release/scripts/templates/operator_modal_timer.py  |  45 --------
 release/scripts/templates/operator_modal_view3d.py |  70 ------------
 .../templates/operator_modal_view3d_raycast.py     | 110 -------------------
 release/scripts/templates/operator_node.py         |  59 ----------
 release/scripts/templates/operator_simple.py       |  35 ------
 release/scripts/templates/operator_uv.py           |  56 ----------
 release/scripts/templates/script_stub.py           |  14 ---
 release/scripts/templates/ui_menu.py               |  49 ---------
 release/scripts/templates/ui_menu_simple.py        |  26 -----
 release/scripts/templates/ui_panel.py              |  73 ------------
 release/scripts/templates/ui_panel_simple.py       |  38 -------
 release/scripts/templates_py/addon_add_object.py   |  92 ++++++++++++++++
 release/scripts/templates_py/background_job.py     | 122 +++++++++++++++++++++
 release/scripts/templates_py/batch_export.py       |  33 ++++++
 release/scripts/templates_py/bmesh_simple.py       |  22 ++++
 .../scripts/templates_py/bmesh_simple_editmode.py  |  23 ++++
 release/scripts/templates_py/builtin_keyingset.py  |  37 +++++++
 release/scripts/templates_py/driver_functions.py   |  35 ++++++
 release/scripts/templates_py/gamelogic.py          |  73 ++++++++++++
 release/scripts/templates_py/gamelogic_module.py   |  27 +++++
 release/scripts/templates_py/gamelogic_simple.py   |  17 +++
 .../scripts/templates_py/operator_file_export.py   |  72 ++++++++++++
 .../scripts/templates_py/operator_file_import.py   |  75 +++++++++++++
 release/scripts/templates_py/operator_mesh_add.py  | 122 +++++++++++++++++++++
 release/scripts/templates_py/operator_modal.py     |  51 +++++++++
 .../scripts/templates_py/operator_modal_draw.py    |  79 +++++++++++++
 .../scripts/templates_py/operator_modal_timer.py   |  45 ++++++++
 .../scripts/templates_py/operator_modal_view3d.py  |  70 ++++++++++++
 .../templates_py/operator_modal_view3d_raycast.py  | 110 +++++++++++++++++++
 release/scripts/templates_py/operator_node.py      |  59 ++++++++++
 release/scripts/templates_py/operator_simple.py    |  35 ++++++
 release/scripts/templates_py/operator_uv.py        |  56 ++++++++++
 release/scripts/templates_py/script_stub.py        |  14 +++
 release/scripts/templates_py/ui_menu.py            |  49 +++++++++
 release/scripts/templates_py/ui_menu_simple.py     |  26 +++++
 release/scripts/templates_py/ui_panel.py           |  73 ++++++++++++
 release/scripts/templates_py/ui_panel_simple.py    |  38 +++++++
 source/blender/editors/space_text/text_format_py.c |   2 +-
 54 files changed, 1478 insertions(+), 1459 deletions(-)
 delete mode 100644 release/scripts/templates/addon_add_object.py
 delete mode 100644 release/scripts/templates/background_job.py
 delete mode 100644 release/scripts/templates/batch_export.py
 delete mode 100644 release/scripts/templates/bmesh_simple.py
 delete mode 100644 release/scripts/templates/bmesh_simple_editmode.py
 delete mode 100644 release/scripts/templates/builtin_keyingset.py
 delete mode 100644 release/scripts/templates/driver_functions.py
 delete mode 100644 release/scripts/templates/gamelogic.py
 delete mode 100644 release/scripts/templates/gamelogic_module.py
 delete mode 100644 release/scripts/templates/gamelogic_simple.py
 delete mode 100644 release/scripts/templates/operator_file_export.py
 delete mode 100644 release/scripts/templates/operator_file_import.py
 delete mode 100644 release/scripts/templates/operator_mesh_add.py
 delete mode 100644 release/scripts/templates/operator_modal.py
 delete mode 100644 release/scripts/templates/operator_modal_draw.py
 delete mode 100644 release/scripts/templates/operator_modal_timer.py
 delete mode 100644 release/scripts/templates/operator_modal_view3d.py
 delete mode 100644 release/scripts/templates/operator_modal_view3d_raycast.py
 delete mode 100644 release/scripts/templates/operator_node.py
 delete mode 100644 release/scripts/templates/operator_simple.py
 delete mode 100644 release/scripts/templates/operator_uv.py
 delete mode 100644 release/scripts/templates/script_stub.py
 delete mode 100644 release/scripts/templates/ui_menu.py
 delete mode 100644 release/scripts/templates/ui_menu_simple.py
 delete mode 100644 release/scripts/templates/ui_panel.py
 delete mode 100644 release/scripts/templates/ui_panel_simple.py
 create mode 100644 release/scripts/templates_py/addon_add_object.py
 create mode 100644 release/scripts/templates_py/background_job.py
 create mode 100644 release/scripts/templates_py/batch_export.py
 create mode 100644 release/scripts/templates_py/bmesh_simple.py
 create mode 100644 release/scripts/templates_py/bmesh_simple_editmode.py
 create mode 100644 release/scripts/templates_py/builtin_keyingset.py
 create mode 100644 release/scripts/templates_py/driver_functions.py
 create mode 100644 release/scripts/templates_py/gamelogic.py
 create mode 100644 release/scripts/templates_py/gamelogic_module.py
 create mode 100644 release/scripts/templates_py/gamelogic_simple.py
 create mode 100644 release/scripts/templates_py/operator_file_export.py
 create mode 100644 release/scripts/templates_py/operator_file_import.py
 create mode 100644 release/scripts/templates_py/operator_mesh_add.py
 create mode 100644 release/scripts/templates_py/operator_modal.py
 create mode 100644 release/scripts/templates_py/operator_modal_draw.py
 create mode 100644 release/scripts/templates_py/operator_modal_timer.py
 create mode 100644 release/scripts/templates_py/operator_modal_view3d.py
 create mode 100644 release/scripts/templates_py/operator_modal_view3d_raycast.py
 create mode 100644 release/scripts/templates_py/operator_node.py
 create mode 100644 release/scripts/templates_py/operator_simple.py
 create mode 100644 release/scripts/templates_py/operator_uv.py
 create mode 100644 release/scripts/templates_py/script_stub.py
 create mode 100644 release/scripts/templates_py/ui_menu.py
 create mode 100644 release/scripts/templates_py/ui_menu_simple.py
 create mode 100644 release/scripts/templates_py/ui_panel.py
 create mode 100644 release/scripts/templates_py/ui_panel_simple.py

diff --git a/release/scripts/startup/bl_ui/space_text.py b/release/scripts/startup/bl_ui/space_text.py
index b54fccf45f1..5b7d6e69f4b 100644
--- a/release/scripts/startup/bl_ui/space_text.py
+++ b/release/scripts/startup/bl_ui/space_text.py
@@ -194,16 +194,35 @@ class TEXT_MT_text(Menu):
             layout.operator("text.run_script")
 
 
-class TEXT_MT_templates(Menu):
-    bl_label = "Templates"
+class TEXT_MT_templates_py(Menu):
+    bl_label = "Python"
+
+    def draw(self, context):
+        self.path_menu(bpy.utils.script_paths("templates_py"),
+                       "text.open",
+                       {"internal": True},
+                       )
+
+
+class TEXT_MT_templates_osl(Menu):
+    bl_label = "Open Shading Language"
 
     def draw(self, context):
-        self.path_menu(bpy.utils.script_paths("templates"),
+        self.path_menu(bpy.utils.script_paths("templates_osl"),
                        "text.open",
                        {"internal": True},
                        )
 
 
+class TEXT_MT_templates(Menu):
+    bl_label = "Templates"
+
+    def draw(self, context):
+        layout = self.layout
+        layout.menu("TEXT_MT_templates_py")
+        layout.menu("TEXT_MT_templates_osl")
+
+
 class TEXT_MT_edit_select(Menu):
     bl_label = "Select"
 
diff --git a/release/scripts/templates/addon_add_object.py b/release/scripts/templates/addon_add_object.py
deleted file mode 100644
index 66da6a969c7..00000000000
--- a/release/scripts/templates/addon_add_object.py
+++ /dev/null
@@ -1,92 +0,0 @@
-bl_info = {
-    "name": "New Object",
-    "author": "Your Name Here",
-    "version": (1, 0),
-    "blender": (2, 65, 0),
-    "location": "View3D > Add > Mesh > New Object",
-    "description": "Adds a new Mesh Object",
-    "warning": "",
-    "wiki_url": "",
-    "tracker_url": "",
-    "category": "Add Mesh"}
-
-
-import bpy
-from bpy.types import Operator
-from bpy.props import FloatVectorProperty
-from bpy_extras.object_utils import AddObjectHelper, object_data_add
-from mathutils import Vector
-
-
-def add_object(self, context):
-    scale_x = self.scale.x
-    scale_y = self.scale.y
-
-    verts = [Vector((-1 * scale_x, 1 * scale_y, 0)),
-             Vector((1 * scale_x, 1 * scale_y, 0)),
-             Vector((1 * scale_x, -1 * scale_y, 0)),
-             Vector((-1 * scale_x, -1 * scale_y, 0)),
-            ]
-
-    edges = []
-    faces = [[0, 1, 2, 3]]
-
-    mesh = bpy.data.meshes.new(name="New Object Mesh")
-    mesh.from_pydata(verts, edges, faces)
-    # useful for development when the mesh may be invalid.
-    # mesh.validate(verbose=True)
-    object_data_add(context, mesh, operator=self)
-
-
-class OBJECT_OT_add_object(Operator, AddObjectHelper):
-    """Create a new Mesh Object"""
-    bl_idname = "mesh.add_object"
-    bl_label = "Add Mesh Object"
-    bl_options = {'REGISTER', 'UNDO'}
-
-    scale = FloatVectorProperty(
-            name="scale",
-            default=(1.0, 1.0, 1.0),
-            subtype='TRANSLATION',
-            description="scaling",
-            )
-
-    def execute(self, context):
-
-        add_object(self, context)
-
-        return {'FINISHED'}
-
-
-# Registration
-
-def add_object_button(self, context):
-    self.layout.operator(
-        OBJECT_OT_add_object.bl_idname,
-        text="Add Object",
-        icon='PLUGIN')
-
-
-# This allows you to right click on a button and link to the manual
-def add_object_manual_map():
-    url_manual_prefix = "http://wiki.blender.org/index.php/Doc:2.6/Manual/"
-    url_manual_mapping = (
-        ("bpy.ops.mesh.add_object", "Modeling/Objects"),
-        )
-    return url_manual_prefix, url_manual_mapping
-
-
-def register():
-    bpy.utils.register_class(OBJECT_OT_add_object)
-    bpy.utils.register_manual_map(add_object_manual_map)
-    bpy.types.INFO_MT_mesh_add.append(add_object_button)
-
-
-def unregister():
-    bpy.utils.unregister_class(OBJECT_OT_add_object)
-    bpy.utils.unregister_manual_map(add_object_manual_map)
-    bpy.types.INFO_MT_mesh_add.remove(add_object_button)
-
-
-if __name__ == "__main__":
-    register()
diff --git a/release/scripts/templates/background_job.py b/release/scripts/templates/background_job.py
deleted file mode 100644
index 11b51e5a9b5..00000000000
--- a/release/scripts/templates/background_job.py
+++ /dev/null
@@ -1,122 +0,0 @@
-# This script is an example of how you can run blender from the command line
-# (in background mode with no interface) to automate tasks, in this example it
-# creates a text object, camera and light, then renders and/or saves it.
-# This example also shows how you can parse command line options to scripts.
-#
-# Example usage for this test.
-#  blender --background --factory-startup --python $HOME/background_job.py -- \
-#          --text="Hello World" \
-#          --render="/tmp/hello" \
-#          --save="/tmp/hello.blend"
-#
-# Notice:
-# '--factory-startup' is used to avoid the user default settings from
-#                     interfearing with automated scene generation.
-#
-# '--' causes blender to ignore all following arguments so python can use them.
-#
-# See blender --help for details.
-
-import bpy
-
-
-def example_function(text, save_path, render_path):
-
-    scene = bpy.context.scene
-
-    # Clear existing objects.
-    scene.camera = None
-    for obj in scene.objects:
-        scene.objects.unlink(obj)
-
-    txt_data = bpy.data.curves.new(name="MyText", type='FONT')
-
-    # Text Object
-    txt_ob = bpy.data.objects.new(name="MyText", object_data=txt_data)
-    scene.objects.link(txt_ob)  # add the data to the scene as an object
-    txt_data.body = text        # the body text to the command line arg given
-    txt_data.align = 'CENTER'   # center text
-
-    # Camera
-    cam_data = bpy.data.cameras.new("MyCam")
-    cam_ob = bpy.data.objects.new(name="MyCam", object_data=cam_data)
-    scene.objects.link(cam_ob)  # instance the camera object in the scene
-    scene.camera = cam_ob       # set the active camera
-    cam_ob.location = 0.0, 0.0, 10.0
-
-    # Lamp
-    lamp_data = bpy.data.lamps.new("MyLamp", 'POINT')
-    lamp_ob = bpy.data.objects.new(name="MyCam", object_data=lamp_data)
-    scene.objects.link(lamp_ob)
-    lamp_ob.location = 2.0, 2.0, 5.0
-
-    if save_path:
-        try:
-            f = open(save_path, 'w')
-            f.close()
-            ok = True
-        except:
-            print("Cannot save to path %r" % save_path)
-
-            import traceback
-            traceback.print_exc()
-
-        if ok:
-            bpy.ops.wm.save_as_mainfile(filepath=save_path)
-
-    if render_path:
-        render = scene.render
-        render.use_file_extension = True
-        render.filepath = render_path
-        bpy.ops.render.render(write_still=True)
-
-
-def main():
-    import sys       # to get command line args
-    import argparse  # to parse options for us and print a nice help message
-
-    # get the args passed to blender after "--", all of which are ignored by
-    # blender so scripts may receive their own arguments
-    argv = sys.argv
-
-    if "--" not in argv:
-        argv = []  # as if no args are passed
-    else:
-        argv = argv[argv.index("--") + 1:]  # get all args after "--"
-
-    # When --help or no args are given, print this help
-    usage_text = \
-    "Run blender in background mode with this script:"
-    "  blender --background --python " + __file__ + " -- [options]"
-
-    parser = argparse.ArgumentParser(description=usage_text)
-
-    # Example utility, add some text and renders or saves it (with options)
-    # Possible types are: string, int, long, choice, float and complex.
-    parser.add_argument("-t", "--text", dest="text", type=str, required=True,
-            help="This text will be used to render an image")
-
-    parser.add_argument("-s", "--save", dest="save_path", metavar='FILE',
-            help="Save the generated file to the specified path")
-    parser.add_argument("-r", "--render", dest="render_path", metavar='FILE',
-            help="Render an image to the specified path")
-
-    args = parser.parse_args(argv)  # In this example we wont use the args
-
-    if not argv:
-        parser.print_help()
-        return
-
-    if not args.text:
-        print("Error: --text=\"some string\" argument not given, aborting.")
-        parser.print_help()
-        return
-
-    # Run the example function
-    example_function(args.text, args.save_path, args.render_path)
-
-    print("batch job finished, exiting")
-
-
-if __name__ == "__main__":
-    main()
diff --git a/release/scripts/templates/batch_export.py b/release/scripts/templates/batch_export.py
deleted file mode 100644
index 45d26f4b525..00000000000
--- a/release/scripts/templates/batch_export.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# exports each selected object into its own file
-
-import bpy
-import os
-
-# export to blend file location
-basedir = os.path.dirname(bpy.data.filepath)
-
-if not basedir:
-    raise Exception("Blend file is not saved")
-
-selection = bpy.context.selected_objects
-
-bpy.ops.object.select_all(action='DESELECT')
-
-for obj in selection:
-
-    obj.select = True
-
-    name = bpy.path.clean_name(obj.name)
-    fn = os.path.join(basedir, name)
-
-    bpy.ops.export_scene.fbx(filepath=fn + ".fbx", use_selection=True)
-
-    ## Can be used for multiple formats
-    # bpy.ops.export_scene.x3d(filepath=fn + ".x3d", use_selection=True)
-
-    obj.select = False
-
-    print("written:", fn)
-
-for obj in selection:
-    obj.select = True
diff --git a/release/scripts/templates/bmesh_simple.py b/release/scripts/templates/bmesh_simple.py
deleted file mode 100644
index 45e6b52d578..00000000000
--- a/release/scripts/templates/bmesh_simple.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# This example assumes we have a mesh object selected
-
-import bpy
-import bmesh
-
-# Get the active mesh
-me = bpy.context.object.data
-
-
-# Get a BMesh representation
-bm = bmesh.new()   # create an empty BMesh
-bm.from_mesh(me)   # fill it in from a Mesh
-
-
-# Modify the BMesh, can do anything here...
-for v in bm.verts:
-    v.co.x += 1.0
-
-
-# Finish up, write the bmesh back to the mesh
-bm.to_mesh(me)
-bm.free()  # free and prevent further access
diff --git a/release/scripts/templates/bmesh_simple_editmode.py b/release/scripts/templates/bmesh_simple_editmode.py
deleted file mode 100644
index d79ba02c2cb..00000000000
--- a/release/scripts/templates/bmesh_simple_editmode.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# This example assumes we have a mesh object in edit-mode
-
-import bpy
-import bmesh
-
-# Get the active mesh
-obj = bpy.context.edit_object
-me = obj.data
-
-
-# Get a BMesh representation
-bm = bmesh.from_edit_mesh(me)
-
-bm.faces.active = None
-
-# Modify the BMesh, can do anything here...
-for v in bm.verts:
-    v.co.x += 1.0
-
-
-# Show the updates in the viewport
-# and recalculate n-gon tessellation.
-bmesh.update_edit_mesh(me, True)
diff --git a/release/scripts/templates/builtin_keyingset.py b/release/scripts/templates/builtin_keyingset.py
deleted file mode 100644
index 19f92dc75e7..00000000000
--- a/release/scripts/templates/builtin_keyingset.py
+++ /dev/null
@@ -1,37 +0,0 @@
-import bpy
-
-
-class BUILTIN_KSI_hello(bpy.types.KeyingSetInfo):
-    bl_label = "Hello World KeyingSet"
-
-    # poll - test for whether Keying Set can be used at all
-    def poll(ksi, context):
-        return context.active_object or context.selected_objects
-
-    # iterator - go over all relevant data, calling generate()
-    def iterator(ksi, context, ks):
-        for ob in context.selected_objects:
-            ksi.generate(context, ks, ob)
-
-    # generator - populate Keying Set with property paths to use
-    def generate(ksi, context, ks, data):
-        id_block = data.id_data
-
-        ks.paths.add(id_block, "location")
-
-        for i in range(5):
-            ks.paths.add(id_block, "layers", i, group_method='NAMED', group_name="5x Hello Layers")
-
-        ks.paths.add(id_block, "show_x_ray", group_method='NONE')
-
-
-def register():
-    bpy.utils.register_class(BUILTIN_KSI_hello)
-
-
-def unregister():
-    bpy.utils.unregister_class(BUILTIN_KSI_hello)
-
-
-if __name__ == '__main__':
-    register()
diff --git a/release/scripts/templates/driver_functions.py b/release/scripts/templates/driver_functions.py
deleted file mode 100644
index 1c6af0e574f..00000000000
--- a/release/scripts/templates/driver_functions.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# This script defines functions to be used directly in drivers expressions to
-# extend the builtin set of python functions.
-#
-# This can be executed on manually or set to 'Register' to
-# initialize thefunctions on file load.
-
-
-# two sample functions
-def invert(f):
-    """ Simple function call:
-
-            invert(val)
-    """
-    return 1.0 - f
-
-
-uuid_store = {}
-
-
-def slow_value(value, fac, uuid):
-    """ Delay the value by a factor, use a unique string to allow
-        use in multiple drivers without conflict:
-
-            slow_value(val, 0.5, "my_value")
-    """
-    value_prev = uuid_store.get(uuid, value)
-    uuid_store[uuid] = value_new = (value_prev * fac) + (value * (1.0 - fac))
-    return value_new
-
-
-import bpy
-
-# Add variable defined in this script into the drivers namespace.
-bpy.app.driver_namespace["invert"] = invert
-bpy.app.driver_namespace["slow_value"] = slow_value
diff --git a/release/scripts/templates/gamelogic.py b/release/scripts/templates/gamelogic.py
deleted file mode 100644
index 01ac27c56cd..00000000000
--- a/release/scripts/templates/gamelogic.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# This script must be assigned to a python controller
-# where it can access the object that owns it and the sensors/actuators that it connects to.
-
-import bge
-
-# support for Vector(), Matrix() types and advanced functions like Matrix.Scale(...) and Matrix.Rotation(...)
-# import mathutils
-
-# for functions like getWindowWidth(), getWindowHeight()
-# import Rasterizer
-
-
-def main():
-    cont = bge.logic.getCurrentController()
-
-    # The KX_GameObject that owns this controller.
-    own = cont.owner
-
-    # for scripts that deal with spacial logic
-    own_pos = own.worldPosition
-
-    # Some example functions, remove to write your own script.
-    # check for a positive sensor, will run on any object without errors.
-    print("Logic info for KX_GameObject", own.name)
-    input = False
-
-    for sens in cont.sensors:
-        # The sensor can be on another object, we may want to use it
-        own_sens = sens.owner
-        print("    sensor:", sens.name, end=" ")
-        if sens.positive:
-            print("(true)")
-            input = True
-        else:
-            print("(false)")
-
-    for actu in cont.actuators:
-        # The actuator can be on another object, we may want to use it
-        own_actu = actu.owner
-        print("    actuator:", actu.name)
-
-        # This runs the actuator or turns it off
-        # note that actuators will continue to run unless explicitly turned off.
-        if input:
-            cont.activate(actu)
-        else:
-            cont.deactivate(actu)
-
-    # Its also good practice to get sensors and actuators by name
-    # rather then index so any changes to their order wont break the script.
-
-    # sens_key = cont.sensors["key_sensor"]
-    # actu_motion = cont.actuators["motion"]
-
-    # Loop through all other objects in the scene
-    sce = bge.logic.getCurrentScene()
-    print("Scene Objects:", sce.name)
-    for ob in sce.objects:
-        print("   ", ob.name, ob.worldPosition)
-
-    # Example where collision objects are checked for their properties
-    # adding to our objects "life" property
-    """
-    actu_collide = cont.sensors["collision_sens"]
-    for ob in actu_collide.objectHitList:
-        # Check to see the object has this property
-        if "life" in ob:
-            own["life"] += ob["life"]
-            ob["life"] = 0
-    print(own["life"])
-    """
-
-main()
diff --git a/release/scripts/templates/gamelogic_module.py b/release/scripts/templates/gamelogic_module.py
deleted file mode 100644
index 88c8cf0d75b..00000000000
--- a/release/scripts/templates/gamelogic_module.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# This module can be accessed by a python controller with
-# its execution method set to 'Module'
-# * Set the module string to "gamelogic_module.main" (without quotes)
-# * When renaming the script it MUST have a .py extension
-# * External text modules are supported as long as they are at
-#   the same location as the blendfile or one of its libraries.
-
-import bge
-
-# variables defined here will only be set once when the
-# module is first imported. Set object specific vars
-# inside the function if you intend to use the module
-# with multiple objects.
-
-
-def main(cont):
-    own = cont.owner
-
-    sens = cont.sensors['mySensor']
-    actu = cont.actuators['myActuator']
-
-    if sens.positive:
-        cont.activate(actu)
-    else:
-        cont.deactivate(actu)
-
-# dont call main(bge.logic.getCurrentController()), the py controller will
diff --git a/release/scripts/templates/gamelogic_simple.py b/release/scripts/templates/gamelogic_simple.py
deleted file mode 100644
index dbfcf948b18..00000000000
--- a/release/scripts/templates/gamelogic_simple.py
+++ /dev/null
@@ -1,17 +0,0 @@
-import bge
-
-
-def main():
-
-    cont = bge.logic.getCurrentController()
-    own = cont.owner
-
-    sens = cont.sensors['mySensor']
-    actu = cont.actuators['myActuator']
-
-    if sens.positive:
-        cont.activate(actu)
-    else:
-        cont.deactivate(actu)
-
-main()
diff --git a/release/scripts/templates/operator_file_export.py b/release/scripts/templates/operator_file_export.py
deleted file mode 100644
index 9511cb163bc..00000000000
--- a/release/scripts/templates/operator_file_export.py
+++ /dev/null
@@ -1,72 +0,0 @@
-import bpy
-
-
-def write_some_data(context, filepath, use_some_setting):
-    print("running write_some_data...")
-    f = open(filepath, 'w', encoding='utf-8')
-    f.write("Hello World %s" % use_some_setting)
-    f.close()
-
-    return {'FINISHED'}
-
-
-# ExportHelper is a helper class, defines filename and
-# invoke() function which calls the file selector.
-from bpy_extras.io_utils import ExportHelper
-from bpy.props import StringProperty, BoolProperty, EnumProperty
-from bpy.types import Operator
-
-
-class ExportSomeData(Operator, ExportHelper):
-    """This appears in the tooltip of the operator and in the generated docs"""
-    bl_idname = "export_test.some_data"  # important since its how bpy.ops.import_test.some_data is constructed
-    bl_label = "Export Some Data"
-
-    # ExportHelper mixin class uses this
-    filename_ext = ".txt"
-
-    filter_glob = StringProperty(
-            default="*.txt",
-            options={'HIDDEN'},
-            )
-
-    # List of operator properties, the attributes will be assigned
-    # to the class instance from the operator settings before calling.
-    use_setting = BoolProperty(
-            name="Example Boolean",
-            description="Example Tooltip",
-            default=True,
-            )
-
-    type = EnumProperty(
-            name="Example Enum",
-            description="Choose between two items",
-            items=(('OPT_A', "First Option", "Description one"),
-                   ('OPT_B', "Second Option", "Description two")),
-            default='OPT_A',
-            )
-
-    def execute(self, context):
-        return write_some_data(context, self.filepath, self.use_setting)
-
-
-# Only needed if you want to add into a dynamic menu
-def menu_func_export(self, context):
-    self.layout.operator(ExportSomeData.bl_idname, text="Text Export Operator")
-
-
-def register():
-    bpy.utils.register_class(ExportSomeData)
-    bpy.types.INFO_MT_file_export.append(menu_func_export)
-
-
-def unregister():
-    bpy.utils.unregister_class(ExportSomeData)
-    bpy.types.INFO_MT_file_export.remove(menu_func_export)
-
-
-if __name__ == "__main__":
-    register()
-
-    # test call
-    bpy.ops.export_test.some_data('INVOKE_DEFAULT')
diff --git a/release/scripts/templates/operator_file_import.py b/release/scripts/templates/operator_file_import.py
deleted file mode 100644
index 9940a1b98eb..00000000000
--- a/release/scripts/templates/operator_file_import.py
+++ /dev/null
@@ -1,75 +0,0 @@
-import bpy
-
-
-def read_some_data(context, filepath, use_some_setting):
-    print("running read_some_data...")
-    f = open(filepath, 'r', encoding='utf-8')
-    data = f.read()
-    f.close()
-
-    # would normally load the data here
-    print(data)
-
-    return {'FINISHED'}
-
-
-# ImportHelper is a helper class, defines filename and
-# invoke() function which calls the file selector.
-from bpy_extras.io_utils import ImportHelper
-from bpy.props import StringProperty, BoolProperty, EnumProperty
-from bpy.types import Operator
-
-
-class ImportSomeData(Operator, ImportHelper):
-    """This appears in the tooltip of the operator and in the generated docs"""
-    bl_idname = "import_test.some_data"  # important since its how bpy.ops.import_test.some_data is constructed
-    bl_label = "Import Some Data"
-
-    # ImportHelper mixin class uses this
-    filename_ext = ".txt"
-
-    filter_glob = StringProperty(
-            default="*.txt",
-            options={'HIDDEN'},
-            )
-
-    # List of operator properties, the attributes will be assigned
-    # to the class instance from the operator settings before calling.
-    use_setting = BoolProperty(
-            name="Example Boolean",
-            description="Example Tooltip",
-            default=True,
-            )
-
-    type = EnumProperty(
-            name="Example Enum",
-            description="Choose between two items",
-            items=(('OPT_A', "First Option", "Description one"),
-                   ('OPT_B', "Second Option", "Description two")),
-            default='OPT_A',
-            )
-
-    def execute(self, context):
-        return read_some_data(context, self.filepath, self.use_setting)
-
-
-# Only needed if you want to add into a dynamic menu
-def menu_func_import(self, context):
-    self.layout.operator(ImportSomeData.bl_idname, text="Text Import Operator")
-
-
-def register():
-    bpy.utils.register_class(ImportSomeData)
-    bpy.types.INFO_MT_file_import.append(menu_func_import)
-
-
-def unregister():
-    bpy.utils.unregister_class(ImportSomeData)
-    bpy.types.INFO_MT_file_import.remove(menu_func_import)
-
-
-if __name__ == "__main__":
-    register()
-
-    # test call
-    bpy.ops.import_test.some_data('INVOKE_DEFAULT')
diff --git a/release/scripts/templates/operator_mesh_add.py b/release/scripts/templates/operator_mesh_add.py
deleted file mode 100644
index fa248cb9005..00000000000
--- a/release/scripts/templates/operator_mesh_add.py
+++ /dev/null
@@ -1,122 +0,0 @@
-import bpy
-import bmesh
-
-
-def add_box(width, height, depth):
-    """
-    This function takes inputs and returns vertex and face arrays.
-    no actual mesh data creation is done here.
-    """
-
-    verts = [(+1.0, +1.0, -1.0),
-             (+1.0, -1.0, -1.0),
-             (-1.0, -1.0, -1.0),
-             (-1.0, +1.0, -1.0),
-             (+1.0, +1.0, +1.0),
-             (+1.0, -1.0, +1.0),
-             (-1.0, -1.0, +1.0),
-             (-1.0, +1.0, +1.0),
-             ]
-
-    faces = [(0, 1, 2, 3),
-             (4, 7, 6, 5),
-             (0, 4, 5, 1),
-             (1, 5, 6, 2),
-             (2, 6, 7, 3),
-             (4, 0, 3, 7),
-            ]
-
-    # apply size
-    for i, v in enumerate(verts):
-        verts[i] = v[0] * width, v[1] * depth, v[2] * height
-
-    return verts, faces
-
-
-from bpy.props import FloatProperty, BoolProperty, FloatVectorProperty
-
-
-class AddBox(bpy.types.Operator):
-    """Add a simple box mesh"""
-    bl_idname = "mesh.primitive_box_add"
-    bl_label = "Add Box"
-    bl_options = {'REGISTER', 'UNDO'}
-
-    width = FloatProperty(
-            name="Width",
-            description="Box Width",
-            min=0.01, max=100.0,
-            default=1.0,
-            )
-    height = FloatProperty(
-            name="Height",
-            description="Box Height",
-            min=0.01, max=100.0,
-            default=1.0,
-            )
-    depth = FloatProperty(
-            name="Depth",
-            description="Box Depth",
-            min=0.01, max=100.0,
-            default=1.0,
-            )
-
-    # generic transform props
-    view_align = BoolProperty(
-            name="Align to View",
-            default=False,
-            )
-    location = FloatVectorProperty(
-            name="Location",
-            subtype='TRANSLATION',
-            )
-    rotation = FloatVectorProperty(
-            name="Rotation",
-            subtype='EULER',
-            )
-
-    def execute(self, context):
-
-        verts_loc, faces = add_box(self.width,
-                                   self.height,
-                                   self.depth,
-                                   )
-
-        mesh = bpy.data.meshes.new("Box")
-
-        bm = bmesh.new()
-
-        for v_co in verts_loc:
-            bm.verts.new(v_co)
-
-        for f_idx in faces:
-            bm.faces.new([bm.verts[i] for i in f_idx])
-
-        bm.to_mesh(mesh)
-        mesh.update()
-
-        # add the mesh as an object into the scene with this utility module
-        from bpy_extras import object_utils
-        object_utils.object_data_add(context, mesh, operator=self)
-
-        return {'FINISHED'}
-
-
-def menu_func(self, context):
-    self.layout.operator(AddBox.bl_idname, icon='MESH_CUBE')
-
-
-def register():
-    bpy.utils.register_class(AddBox)
-    bpy.types.INFO_MT_mesh_add.append(menu_func)
-
-
-def unregister():
-    bpy.utils.unregister_class(AddBox)
-    bpy.types.INFO_MT_mesh_add.remove(menu_func)
-
-if __name__ == "__main__":
-    register()
-
-    # test call
-    bpy.ops.mesh.primitive_box_add()
diff --git a/release/scripts/templates/operator_modal.py b/release/scripts/templates/operator_modal.py
deleted file mode 100644
index 88e5ee80590..00000000000
--- a/release/scripts/templates/operator_modal.py
+++ /dev/null
@@ -1,51 +0,0 @@
-import bpy
-from bpy.props import IntProperty, FloatProperty
-
-
-class ModalOperator(bpy.types.Operator):
-    """Move an object with the mouse, example"""
-    bl_idname = "object.modal_operator"
-    bl_label = "Simple Modal Operator"
-
-    first_mouse_x = IntProperty()
-    first_value = FloatProperty()
-
-    def modal(self, context, event):
-        if event.type == 'MOUSEMOVE':
-            delta = self.first_mouse_x - event.mouse_x
-            context.object.location.x = self.first_value + delta * 0.01
-
-        elif event.type == 'LEFTMOUSE':
-            return {'FINISHED'}
-
-        elif event.type in {'RIGHTMOUSE', 'ESC'}:
-            context.object.location.x = self.first_value
-            return {'CANCELLED'}
-
-        return {'RUNNING_MODAL'}
-
-    def invoke(self, context, event):
-        if context.object:
-            self.first_mouse_x = event.mouse_x
-            self.first_value = context.object.location.x
-
-            context.window_manager.modal_handler_add(self)
-            return {'RUNNING_MODAL'}
-        else:
-            self.report({'WARNING'}, "No active object, could not finish")
-            return {'CANCELLED'}
-
-
-def register():
-    bpy.utils.register_class(ModalOperator)
-
-
-def unregister():
-    bpy.utils.unregister_class(ModalOperator)
-
-
-if __name__ == "__main__":
-    register()
-
-    # test call
-    bpy.ops.object.modal_operator('INVOKE_DEFAULT')
diff --git a/release/scripts/templates/operator_modal_draw.py b/release/scripts/templates/operator_modal_draw.py
deleted file mode 100644
index d11ddf0b467..00000000000
--- a/release/scripts/templates/operator_modal_draw.py
+++ /dev/null
@@ -1,79 +0,0 @@
-import bpy
-import bgl
-import blf
-
-
-def draw_callback_px(self, context):
-    print("mouse points", len(self.mouse_path))
-
-    font_id = 0  # XXX, need to find out how best to get this.
-
-    # draw some text
-    blf.position(font_id, 15, 30, 0)
-    blf.size(font_id, 20, 72)
-    blf.draw(font_id, "Hello Word " + str(len(self.mouse_path)))
-
-    # 50% alpha, 2 pixel width line
-    bgl.glEnable(bgl.GL_BLEND)
-    bgl.glColor4f(0.0, 0.0, 0.0, 0.5)
-    bgl.glLineWidth(2)
-
-    bgl.glBegin(bgl.GL_LINE_STRIP)
-    for x, y in self.mouse_path:
-        bgl.glVertex2i(x, y)
-
-    bgl.glEnd()
-
-    # restore opengl defaults
-    bgl.glLineWidth(1)
-    bgl.glDisable(bgl.GL_BLEND)
-    bgl.glColor4f(0.0, 0.0, 0.0, 1.0)
-
-
-class ModalDrawOperator(bpy.types.Operator):
-    """Draw a line with the mouse"""
-    bl_idname = "view3d.modal_operator"
-    bl_label = "Simple Modal View3D Operator"
-
-    def modal(self, context, event):
-        context.area.tag_redraw()
-
-        if event.type == 'MOUSEMOVE':
-            self.mouse_path.append((event.mouse_region_x, event.mouse_region_y))
-
-        elif event.type == 'LEFTMOUSE':
-            bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
-            return {'FINISHED'}
-
-        elif event.type in {'RIGHTMOUSE', 'ESC'}:
-            bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
-            return {'CANCELLED'}
-
-        return {'RUNNING_MODAL'}
-
-    def invoke(self, context, event):
-        if context.area.type == 'VIEW_3D':
-            # the arguments we pass the the callback
-            args = (self, context)
-            # Add the region OpenGL drawing callback
-            # draw in view space with 'POST_VIEW' and 'PRE_VIEW'
-            self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_callback_px, args, 'WINDOW', 'POST_PIXEL')
-
-            self.mouse_path = []
-
-            context.window_manager.modal_handler_add(self)
-            return {'RUNNING_MODAL'}
-        else:
-            self.report({'WARNING'}, "View3D not found, cannot run operator")
-            return {'CANCELLED'}
-
-
-def register():
-    bpy.utils.register_class(ModalDrawOperator)
-
-
-def unregister():
-    bpy.utils.unregister_class(ModalDrawOperator)
-
-if __name__ == "__main__":
-    register()
diff --git a/release/scripts/templates/operator_modal_timer.py b/release/scripts/templates/operator_modal_timer.py
deleted file mode 100644
index 72c153df9d2..00000000000
--- a/release/scripts/templates/operator_modal_timer.py
+++ /dev/null
@@ -1,45 +0,0 @@
-import bpy
-
-
-class ModalTimerOperator(bpy.types.Operator):
-    """Operator which runs its self from a timer"""
-    bl_idname = "wm.modal_timer_operator"
-    bl_label = "Modal Timer Operator"
-
-    _timer = None
-
-    def modal(self, context, event):
-        if event.type == 'ESC':
-            return self.cancel(context)
-
-        if event.type == 'TIMER':
-            # change theme color, silly!
-            color = context.user_preferences.themes[0].view_3d.space.back
-            color.s = 1.0
-            color.h += 0.01
-
-        return {'PASS_THROUGH'}
-
-    def execute(self, context):
-        self._timer = context.window_manager.event_timer_add(0.1, context.window)
-        context.window_manager.modal_handler_add(self)
-        return {'RUNNING_MODAL'}
-
-    def cancel(self, context):
-        context.window_manager.event_timer_remove(self._timer)
-        return {'CANCELLED'}
-
-
-def register():
-    bpy.utils.register_class(ModalTimerOperator)
-
-
-def unregister():
-    bpy.utils.unregister_class(ModalTimerOperator)
-
-
-if __name__ == "__main__":
-    register()
-
-    # test call
-    bpy.ops.wm.modal_timer_operator()
diff --git a/release/scripts/templates/operator_modal_view3d.py b/release/scripts/templates/operator_modal_view3d.py
deleted file mode 100644
index c870bbffdcf..00000000000
--- a/release/scripts/templates/operator_modal_view3d.py
+++ /dev/null
@@ -1,70 +0,0 @@
-import bpy
-from mathutils import Vector
-from bpy.props import FloatVectorProperty
-
-
-class ViewOperator(bpy.types.Operator):
-    """Translate the view using mouse events"""
-    bl_idname = "view3d.modal_operator"
-    bl_label = "Simple View Operator"
-
-    offset = FloatVectorProperty(
-            name="Offset",
-            size=3,
-            )
-
-    def execute(self, context):
-        v3d = context.space_data
-        rv3d = v3d.region_3d
-
-        rv3d.view_location = self._initial_location + Vector(self.offset)
-
-    def modal(self, context, event):
-        v3d = context.space_data
-        rv3d = v3d.region_3d
-
-        if event.type == 'MOUSEMOVE':
-            self.offset = (self._initial_mouse - Vector((event.mouse_x, event.mouse_y, 0.0))) * 0.02
-            self.execute(context)
-            context.area.header_text_set("Offset %.4f %.4f %.4f" % tuple(self.offset))
-
-        elif event.type == 'LEFTMOUSE':
-            context.area.header_text_set()
-            return {'FINISHED'}
-
-        elif event.type in {'RIGHTMOUSE', 'ESC'}:
-            rv3d.view_location = self._initial_location
-            context.area.header_text_set()
-            return {'CANCELLED'}
-
-        return {'RUNNING_MODAL'}
-
-    def invoke(self, context, event):
-
-        if context.space_data.type == 'VIEW_3D':
-            v3d = context.space_data
-            rv3d = v3d.region_3d
-
-            if rv3d.view_perspective == 'CAMERA':
-                rv3d.view_perspective = 'PERSP'
-
-            self._initial_mouse = Vector((event.mouse_x, event.mouse_y, 0.0))
-            self._initial_location = rv3d.view_location.copy()
-
-            context.window_manager.modal_handler_add(self)
-            return {'RUNNING_MODAL'}
-        else:
-            self.report({'WARNING'}, "Active space must be a View3d")
-            return {'CANCELLED'}
-
-
-def register():
-    bpy.utils.register_class(ViewOperator)
-
-
-def unregister():
-    bpy.utils.unregister_class(ViewOperator)
-
-
-if __name__ == "__main__":
-    register()
diff --git a/release/scripts/templates/operator_modal_view3d_raycast.py b/release/scripts/templates/operator_modal_view3d_raycast.py
deleted file mode 100644
index eac76922187..00000000000
--- a/release/scripts/templates/operator_modal_view3d_raycast.py
+++ /dev/null
@@ -1,110 +0,0 @@
-import bpy
-from mathutils import Vector
-from bpy_extras import view3d_utils
-
-
-def main(context, event, ray_max=10000.0):
-    """Run this function on left mouse, execute the ray cast"""
-    # get the context arguments
-    scene = context.scene
-    region = context.region
-    rv3d = context.region_data
-    coord = event.mouse_region_x, event.mouse_region_y
-
-    # get the ray from the viewport and mouse
-    view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
-    ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)
-    ray_target = ray_origin + (view_vector * ray_max)
-
-
-    def visible_objects_and_duplis():
-        """Loop over (object, matrix) pairs (mesh only)"""
-
-        for obj in context.visible_objects:
-            if obj.type == 'MESH':
-                yield (obj, obj.matrix_world.copy())
-
-            if obj.dupli_type != 'NONE':
-                obj.dupli_list_create(scene)
-                for dob in obj.dupli_list:
-                    obj_dupli = dob.object
-                    if obj_dupli.type == 'MESH':
-                        yield (obj_dupli, dob.matrix.copy())
-
-            obj.dupli_list_clear()
-
-    def obj_ray_cast(obj, matrix):
-        """Wrapper for ray casting that moves the ray into object space"""
-
-        # get the ray relative to the object
-        matrix_inv = matrix.inverted()
-        ray_origin_obj = matrix_inv * ray_origin
-        ray_target_obj = matrix_inv * ray_target
-
-        # cast the ray
-        hit, normal, face_index = obj.ray_cast(ray_origin_obj, ray_target_obj)
-
-        if face_index != -1:
-            return hit, normal, face_index
-        else:
-            return None, None, None
-
-    # cast rays and find the closest object
-    best_length_squared = ray_max * ray_max
-    best_obj = None
-
-    for obj, matrix in visible_objects_and_duplis():
-        if obj.type == 'MESH':
-            hit, normal, face_index = obj_ray_cast(obj, matrix)
-            if hit is not None:
-                hit_world = matrix * hit
-                scene.cursor_location = hit_world
-                length_squared = (hit_world - ray_origin).length_squared
-                if length_squared < best_length_squared:
-                    best_length_squared = length_squared
-                    best_obj = obj
-
-    # now we have the object under the mouse cursor,
-    # we could do lots of stuff but for the example just select.
-    if best_obj is not None:
-        best_obj.select = True
-        context.scene.objects.active = best_obj
-
-
-class ViewOperatorRayCast(bpy.types.Operator):
-    """Modal object selection with a ray cast"""
-    bl_idname = "view3d.modal_operator_raycast"
-    bl_label = "RayCast View Operator"
-
-    def modal(self, context, event):
-        if event.type in {'MIDDLEMOUSE', 'WHEELUPMOUSE', 'WHEELDOWNMOUSE'}:
-            # allow navigation
-            return {'PASS_THROUGH'}
-        elif event.type == 'LEFTMOUSE':
-            main(context, event)
-            return {'RUNNING_MODAL'}
-        elif event.type in {'RIGHTMOUSE', 'ESC'}:
-            return {'CANCELLED'}
-
-        return {'RUNNING_MODAL'}
-
-    def invoke(self, context, event):
-        if context.space_data.type == 'VIEW_3D':
-            context.window_manager.modal_handler_add(self)
-            return {'RUNNING_MODAL'}
-        else:
-            self.report({'WARNING'}, "Active space must be a View3d")
-            return {'CANCELLED'}
-
-
-def register():
-    bpy.utils.register_class(ViewOperatorRayCast)
-
-
-def unregister():
-    bpy.utils.unregister_class(ViewOperatorRayCast)
-
-
-if __name__ == "__main__":
-    register()
-
diff --git a/release/scripts/templates/operator_node.py b/release/scripts/templates/operator_node.py
deleted file mode 100644
index b689ce7634e..00000000000
--- a/release/scripts/templates/operator_node.py
+++ /dev/null
@@ -1,59 +0,0 @@
-import bpy
-
-
-def main(context):
-    space = context.space_data
-    node_tree = space.node_tree
-    node_active = context.active_node
-    node_selected = context.selected_nodes
-
-    # now we have the context, perform a simple operation
-    if node_active in node_selected:
-        node_selected.remove(node_active)
-    if len(node_selected) != 1:
-        operator.report({'ERROR'}, "2 nodes must be selected")
-        return
-
-    node_other, = node_selected
-
-    # now we have 2 nodes to operate on
-    if not node_active.inputs:
-        operator.report({'ERROR'}, "Active node has no inputs")
-        return
-
-    if not node_other.outputs:
-        operator.report({'ERROR'}, "Selected node has no outputs")
-        return
-
-    socket_in = node_active.inputs[0]
-    socket_out = node_other.outputs[0]
-
-    # add a link between the two nodes
-    node_link = node_tree.links.new(socket_in, socket_out)
-
-
-class NodeOperator(bpy.types.Operator):
-    """Tooltip"""
-    bl_idname = "node.simple_operator"
-    bl_label = "Simple Node Operator"
-
-    @classmethod
-    def poll(cls, context):
-        space = context.space_data
-        return space.type == 'NODE_EDITOR'
-
-    def execute(self, context):
-        main(context)
-        return {'FINISHED'}
-
-
-def register():
-    bpy.utils.register_class(NodeOperator)
-
-
-def unregister():
-    bpy.utils.unregister_class(NodeOperator)
-
-
-if __name__ == "__main__":
-    register()
diff --git a/release/scripts/templates/operator_simple.py b/release/scripts/templates/operator_simple.py
deleted file mode 100644
index 715daa3a8b4..00000000000
--- a/release/scripts/templates/operator_simple.py
+++ /dev/null
@@ -1,35 +0,0 @@
-import bpy
-
-
-def main(context):
-    for ob in context.scene.objects:
-        print(ob)
-
-
-class SimpleOperator(bpy.types.Operator):
-    """Tooltip"""
-    bl_idname = "object.simple_operator"
-    bl_label = "Simple Object Operator"
-
-    @classmethod
-    def poll(cls, context):
-        return context.active_object is not None
-
-    def execute(self, context):
-        main(context)
-        return {'FINISHED'}
-
-
-def register():
-    bpy.utils.register_class(SimpleOperator)
-
-
-def unregister():
-    bpy.utils.unregister_class(SimpleOperator)
-
-
-if __name__ == "__main__":
-    register()
-
-    # test call
-    bpy.ops.object.simple_operator()
diff --git a/release/scripts/templates/operator_uv.py b/release/scripts/templates/operator_uv.py
deleted file mode 100644
index fdd0b993f8b..00000000000
--- a/release/scripts/templates/operator_uv.py
+++ /dev/null
@@ -1,56 +0,0 @@
-import bpy
-
-
-def main(context):
-    obj = context.active_object
-    mesh = obj.data
-
-    is_editmode = (obj.mode == 'EDIT')
-    if is_editmode:
-        bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
-
-    if not mesh.uv_textures:
-        uvtex = bpy.ops.mesh.uv_texture_add()
-    else:
-        uvtex = mesh.uv_textures.active
-
-    # adjust UVs
-    for i, uv in enumerate(uvtex.data):
-        uvs = uv.uv1, uv.uv2, uv.uv3, uv.uv4
-        for j, v_idx in enumerate(mesh.faces[i].vertices):
-            if uv.select_uv[j]:
-                # apply the location of the vertex as a UV
-                uvs[j][:] = mesh.vertices[v_idx].co.xy
-
-    if is_editmode:
-        bpy.ops.object.mode_set(mode='EDIT', toggle=False)
-
-
-class UvOperator(bpy.types.Operator):
-    """UV Operator description"""
-    bl_idname = "uv.simple_operator"
-    bl_label = "Simple UV Operator"
-
-    @classmethod
-    def poll(cls, context):
-        obj = context.active_object
-        return (obj and obj.type == 'MESH')
-
-    def execute(self, context):
-        main(context)
-        return {'FINISHED'}
-
-
-def register():
-    bpy.utils.register_class(UvOperator)
-
-
-def unregister():
-    bpy.utils.unregister_class(UvOperator)
-
-
-if __name__ == "__main__":
-    register()
-
-    # test call
-    bpy.ops.uv.simple_operator()
diff --git a/release/scripts/templates/script_stub.py b/release/scripts/templates/script_stub.py
deleted file mode 100644
index 44c7b802e2c..00000000000
--- a/release/scripts/templates/script_stub.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# This stub runs a python script relative to the currently open
-# blend file, useful when editing scripts externally.
-
-import bpy
-import os
-
-# Use your own script name here:
-filename = "my_script.py"
-
-filepath = os.path.join(os.path.dirname(bpy.data.filepath), filename)
-global_namespace = {"__file__": filepath, "__name__": "__main__"}
-file = open(filepath, 'rb')
-exec(compile(file.read(), filepath, 'exec'), global_namespace)
-file.close()
diff --git a/release/scripts/templates/ui_menu.py b/release/scripts/templates/ui_menu.py
deleted file mode 100644
index a21e5ed86c8..00000000000
--- a/release/scripts/templates/ui_menu.py
+++ /dev/null
@@ -1,49 +0,0 @@
-import bpy
-
-
-class CustomMenu(bpy.types.Menu):
-    bl_label = "Custom Menu"
-    bl_idname = "OBJECT_MT_custom_menu"
-
-    def draw(self, context):
-        layout = self.layout
-
-        layout.operator("wm.open_mainfile")
-        layout.operator("wm.save_as_mainfile").copy = True
-
-        layout.operator("object.shade_smooth")
-
-        layout.label(text="Hello world!", icon='WORLD_DATA')
-
-        # use an operator enum property to populate a sub-menu
-        layout.operator_menu_enum("object.select_by_type",
-                                  property="type",
-                                  text="Select All by Type...",
-                                  )
-
-        # call another menu
-        layout.operator("wm.call_menu", text="Unwrap").name = "VIEW3D_MT_uv_map"
-
-
-def draw_item(self, context):
-    layout = self.layout
-    layout.menu(CustomMenu.bl_idname)
-
-
-def register():
-    bpy.utils.register_class(CustomMenu)
-
-    # lets add ourselves to the main header
-    bpy.types.INFO_HT_header.append(draw_item)
-
-
-def unregister():
-    bpy.utils.unregister_class(CustomMenu)
-
-    bpy.types.INFO_HT_header.remove(draw_item)
-
-if __name__ == "__main__":
-    register()
-
-    # The menu can also be called from scripts
-    bpy.ops.wm.call_menu(name=CustomMenu.bl_idname)
diff --git a/release/scripts/templates/ui_menu_simple.py b/release/scripts/templates/ui_menu_simple.py
deleted file mode 100644
index 2129dfd81a4..00000000000
--- a/release/scripts/templates/ui_menu_simple.py
+++ /dev/null
@@ -1,26 +0,0 @@
-import bpy
-
-
-class SimpleCustomMenu(bpy.types.Menu):
-    bl_label = "Simple Custom Menu"
-    bl_idname = "OBJECT_MT_simple_custom_menu"
-
-    def draw(self, context):
-        layout = self.layout
-
-        layout.operator("wm.open_mainfile")
-        layout.operator("wm.save_as_mainfile")
-
-
-def register():
-    bpy.utils.register_class(SimpleCustomMenu)
-
-
-def unregister():
-    bpy.utils.unregister_class(SimpleCustomMenu)
-
-if __name__ == "__main__":
-    register()
-
-    # The menu can also be called from scripts
-    bpy.ops.wm.call_menu(name=SimpleCustomMenu.bl_idname)
diff --git a/release/scripts/templates/ui_panel.py b/release/scripts/templates/ui_panel.py
deleted file mode 100644
index cacdb83e815..00000000000
--- a/release/scripts/templates/ui_panel.py
+++ /dev/null
@@ -1,73 +0,0 @@
-import bpy
-
-
-class LayoutDemoPanel(bpy.types.Panel):
-    """Creates a Panel in the scene context of the properties editor"""
-    bl_label = "Layout Demo"
-    bl_idname = "SCENE_PT_layout"
-    bl_space_type = 'PROPERTIES'
-    bl_region_type = 'WINDOW'
-    bl_context = "scene"
-
-    def draw(self, context):
-        layout = self.layout
-
-        scene = context.scene
-
-        # Create a simple row.
-        layout.label(text=" Simple Row:")
-
-        row = layout.row()
-        row.prop(scene, "frame_start")
-        row.prop(scene, "frame_end")
-
-        # Create an row where the buttons are aligned to each other.
-        layout.label(text=" Aligned Row:")
-
-        row = layout.row(align=True)
-        row.prop(scene, "frame_start")
-        row.prop(scene, "frame_end")
-
-        # Create two columns, by using a split layout.
-        split = layout.split()
-
-        # First column
-        col = split.column()
-        col.label(text="Column One:")
-        col.prop(scene, "frame_end")
-        col.prop(scene, "frame_start")
-
-        # Second column, aligned
-        col = split.column(align=True)
-        col.label(text="Column Two:")
-        col.prop(scene, "frame_start")
-        col.prop(scene, "frame_end")
-        
-        # Big render button
-        layout.label(text="Big Button:")
-        row = layout.row()
-        row.scale_y = 3.0
-        row.operator("render.render")
-        
-        # Different sizes in a row
-        layout.label(text="Different button sizes:")
-        row = layout.row(align=True)
-        row.operator("render.render")
-        
-        sub = row.row()
-        sub.scale_x = 2.0
-        sub.operator("render.render")
-        
-        row.operator("render.render")
-
-
-def register():
-    bpy.utils.register_class(LayoutDemoPanel)
-
-
-def unregister():
-    bpy.utils.unregister_class(LayoutDemoPanel)
-
-
-if __name__ == "__main__":
-    register()
diff --git a/release/scripts/templates/ui_panel_simple.py b/release/scripts/templates/ui_panel_simple.py
deleted file mode 100644
index 9bcc750560f..00000000000
--- a/release/scripts/templates/ui_panel_simple.py
+++ /dev/null
@@ -1,38 +0,0 @@
-import bpy
-
-
-class HelloWorldPanel(bpy.types.Panel):
-    """Creates a Panel in the Object properties window"""
-    bl_label = "Hello World Panel"
-    bl_idname = "OBJECT_PT_hello"
-    bl_space_type = 'PROPERTIES'
-    bl_region_type = 'WINDOW'
-    bl_context = "object"
-
-    def draw(self, context):
-        layout = self.layout
-
-        obj = context.object
-
-        row = layout.row()
-        row.label(text="Hello world!", icon='WORLD_DATA')
-
-        row = layout.row()
-        row.label(text="Active object is: " + obj.name)
-        row = layout.row()
-        row.prop(obj, "name")
-
-        row = layout.row()
-        row.operator("mesh.primitive_cube_add")
-
-
-def register():
-    bpy.utils.register_class(HelloWorldPanel)
-
-
-def unregister():
-    bpy.utils.unregister_class(HelloWorldPanel)
-
-
-if __name__ == "__main__":
-    register()
diff --git a/release/scripts/templates_py/addon_add_object.py b/release/scripts/templates_py/addon_add_object.py
new file mode 100644
index 00000000000..66da6a969c7
--- /dev/null
+++ b/release/scripts/templates_py/addon_add_object.py
@@ -0,0 +1,92 @@
+bl_info = {
+    "name": "New Object",
+    "author": "Your Name Here",
+    "version": (1, 0),
+    "blender": (2, 65, 0),
+    "location": "View3D > Add > Mesh > New Object",
+    "description": "Adds a new Mesh Object",
+    "warning": "",
+    "wiki_url": "",
+    "tracker_url": "",
+    "category": "Add Mesh"}
+
+
+import bpy
+from bpy.types import Operator
+from bpy.props import FloatVectorProperty
+from bpy_extras.object_utils import AddObjectHelper, object_data_add
+from mathutils import Vector
+
+
+def add_object(self, context):
+    scale_x = self.scale.x
+    scale_y = self.scale.y
+
+    verts = [Vector((-1 * scale_x, 1 * scale_y, 0)),
+             Vector((1 * scale_x, 1 * scale_y, 0)),
+             Vector((1 * scale_x, -1 * scale_y, 0)),
+             Vector((-1 * scale_x, -1 * scale_y, 0)),
+            ]
+
+    edges = []
+    faces = [[0, 1, 2, 3]]
+
+    mesh = bpy.data.meshes.new(name="New Object Mesh")
+    mesh.from_pydata(verts, edges, faces)
+    # useful for development when the mesh may be invalid.
+    # mesh.validate(verbose=True)
+    object_data_add(context, mesh, operator=self)
+
+
+class OBJECT_OT_add_object(Operator, AddObjectHelper):
+    """Create a new Mesh Object"""
+    bl_idname = "mesh.add_object"
+    bl_label = "Add Mesh Object"
+    bl_options = {'REGISTER', 'UNDO'}
+
+    scale = FloatVectorProperty(
+            name="scale",
+            default=(1.0, 1.0, 1.0),
+            subtype='TRANSLATION',
+            description="scaling",
+            )
+
+    def execute(self, context):
+
+        add_object(self, context)
+
+        return {'FINISHED'}
+
+
+# Registration
+
+def add_object_button(self, context):
+    self.layout.operator(
+        OBJECT_OT_add_object.bl_idname,
+        text="Add Object",
+        icon='PLUGIN')
+
+
+# This allows you to right click on a button and link to the manual
+def add_object_manual_map():
+    url_manual_prefix = "http://wiki.blender.org/index.php/Doc:2.6/Manual/"
+    url_manual_mapping = (
+        ("bpy.ops.mesh.add_object", "Modeling/Objects"),
+        )
+    return url_manual_prefix, url_manual_mapping
+
+
+def register():
+    bpy.utils.register_class(OBJECT_OT_add_object)
+    bpy.utils.register_manual_map(add_object_manual_map)
+    bpy.types.INFO_MT_mesh_add.append(add_object_button)
+
+
+def unregister():
+    bpy.utils.unregister_class(OBJECT_OT_add_object)
+    bpy.utils.unregister_manual_map(add_object_manual_map)
+    bpy.types.INFO_MT_mesh_add.remove(add_object_button)
+
+
+if __name__ == "__main__":
+    register()
diff --git a/release/scripts/templates_py/background_job.py b/release/scripts/templates_py/background_job.py
new file mode 100644
index 00000000000..11b51e5a9b5
--- /dev/null
+++ b/release/scripts/templates_py/background_job.py
@@ -0,0 +1,122 @@
+# This script is an example of how you can run blender from the command line
+# (in background mode with no interface) to automate tasks, in this example it
+# creates a text object, camera and light, then renders and/or saves it.
+# This example also shows how you can parse command line options to scripts.
+#
+# Example usage for this test.
+#  blender --background --factory-startup --python $HOME/background_job.py -- \
+#          --text="Hello World" \
+#          --render="/tmp/hello" \
+#          --save="/tmp/hello.blend"
+#
+# Notice:
+# '--factory-startup' is used to avoid the user default settings from
+#                     interfearing with automated scene generation.
+#
+# '--' causes blender to ignore all following arguments so python can use them.
+#
+# See blender --help for details.
+
+import bpy
+
+
+def example_function(text, save_path, render_path):
+
+    scene = bpy.context.scene
+
+    # Clear existing objects.
+    scene.camera = None
+    for obj in scene.objects:
+        scene.objects.unlink(obj)
+
+    txt_data = bpy.data.curves.new(name="MyText", type='FONT')
+
+    # Text Object
+    txt_ob = bpy.data.objects.new(name="MyText", object_data=txt_data)
+    scene.objects.link(txt_ob)  # add the data to the scene as an object
+    txt_data.body = text        # the body text to the command line arg given
+    txt_data.align = 'CENTER'   # center text
+
+    # Camera
+    cam_data = bpy.data.cameras.new("MyCam")
+    cam_ob = bpy.data.objects.new(name="MyCam", object_data=cam_data)
+    scene.objects.link(cam_ob)  # instance the camera object in the scene
+    scene.camera = cam_ob       # set the active camera
+    cam_ob.location = 0.0, 0.0, 10.0
+
+    # Lamp
+    lamp_data = bpy.data.lamps.new("MyLamp", 'POINT')
+    lamp_ob = bpy.data.objects.new(name="MyCam", object_data=lamp_data)
+    scene.objects.link(lamp_ob)
+    lamp_ob.location = 2.0, 2.0, 5.0
+
+    if save_path:
+        try:
+            f = open(save_path, 'w')
+            f.close()
+            ok = True
+        except:
+            print("Cannot save to path %r" % save_path)
+
+            import traceback
+            traceback.print_exc()
+
+        if ok:
+            bpy.ops.wm.save_as_mainfile(filepath=save_path)
+
+    if render_path:
+        render = scene.render
+        render.use_file_extension = True
+        render.filepath = render_path
+        bpy.ops.render.render(write_still=True)
+
+
+def main():
+    import sys       # to get command line args
+    import argparse  # to parse options for us and print a nice help message
+
+    # get the args passed to blender after "--", all of which are ignored by
+    # blender so scripts may receive their own arguments
+    argv = sys.argv
+
+    if "--" not in argv:
+        argv = []  # as if no args are passed
+    else:
+        argv = argv[argv.index("--") + 1:]  # get all args after "--"
+
+    # When --help or no args are given, print this help
+    usage_text = \
+    "Run blender in background mode with this script:"
+    "  blender --background --python " + __file__ + " -- [options]"
+
+    parser = argparse.ArgumentParser(description=usage_text)
+
+    # Example utility, add some text and renders or saves it (with options)
+    # Possible types are: string, int, long, choice, float and complex.
+    parser.add_argument("-t", "--text", dest="text", type=str, required=True,
+            help="This text will be used to render an image")
+
+    parser.add_argument("-s", "--save", dest="save_path", metavar='FILE',
+            help="Save the generated file to the specified path")
+    parser.add_argument("-r", "--render", dest="render_path", metavar='FILE',
+            help="Render an image to the specified path")
+
+    args = parser.parse_args(argv)  # In this example we wont use the args
+
+    if not argv:
+        parser.print_help()
+        return
+
+    if not args.text:
+        print("Error: --text=\"some string\" argument not given, aborting.")
+        parser.print_help()
+        return
+
+    # Run the example function
+    example_function(args.text, args.save_path, args.render_path)
+
+    print("batch job finished, exiting")
+
+
+if __name__ == "__main__":
+    main()
diff --git a/release/scripts/templates_py/batch_export.py b/release/scripts/templates_py/batch_export.py
new file mode 100644
index 00000000000..45d26f4b525
--- /dev/null
+++ b/release/scripts/templates_py/batch_export.py
@@ -0,0 +1,33 @@
+# exports each selected object into its own file
+
+import bpy
+import os
+
+# export to blend file location
+basedir = os.path.dirname(bpy.data.filepath)
+
+if not basedir:
+    raise Exception("Blend file is not saved")
+
+selection = bpy.context.selected_objects
+
+bpy.ops.object.select_all(action='DESELECT')
+
+for obj in selection:
+
+    obj.select = True
+
+    name = bpy.path.clean_name(obj.name)
+    fn = os.path.join(basedir, name)
+
+    bpy.ops.export_scene.fbx(filepath=fn + ".fbx", use_selection=True)
+
+    ## Can be used for multiple formats
+    # bpy.ops.export_scene.x3d(filepath=fn + ".x3d", use_selection=True)
+
+    obj.select = False
+
+    print("written:", fn)
+
+for obj in selection:
+    obj.select = True
diff --git a/release/scripts/templates_py/bmesh_simple.py b/release/scripts/templates_py/bmesh_simple.py
new file mode 100644
index 00000000000..45e6b52d578
--- /dev/null
+++ b/release/scripts/templates_py/bmesh_simple.py
@@ -0,0 +1,22 @@
+# This example assumes we have a mesh object selected
+
+import bpy
+import bmesh
+
+# Get the active mesh
+me = bpy.context.object.data
+
+
+# Get a BMesh representation
+bm = bmesh.new()   # create an empty BMesh
+bm.from_mesh(me)   # fill it in from a Mesh
+
+
+# Modify the BMesh, can do anything here...
+for v in bm.verts:
+    v.co.x += 1.0
+
+
+# Finish up, write the bmesh back to the mesh
+bm.to_mesh(me)
+bm.free()  # free and prevent further access
diff --git a/release/scripts/templates_py/bmesh_simple_editmode.py b/release/scripts/templates_py/bmesh_simple_editmode.py
new file mode 100644
index 00000000000..d79ba02c2cb
--- /dev/null
+++ b/release/scripts/templates_py/bmesh_simple_editmode.py
@@ -0,0 +1,23 @@
+# This example assumes we have a mesh object in edit-mode
+
+import bpy
+import bmesh
+
+# Get the active mesh
+obj = bpy.context.edit_object
+me = obj.data
+
+
+# Get a BMesh representation
+bm = bmesh.from_edit_mesh(me)
+
+bm.faces.active = None
+
+# Modify the BMesh, can do anything here...
+for v in bm.verts:
+    v.co.x += 1.0
+
+
+# Show the updates in the viewport
+# and recalculate n-gon tessellation.
+bmesh.update_edit_mesh(me, True)
diff --git a/release/scripts/templates_py/builtin_keyingset.py b/release/scripts/templates_py/builtin_keyingset.py
new file mode 100644
index 00000000000..19f92dc75e7
--- /dev/null
+++ b/release/scripts/templates_py/builtin_keyingset.py
@@ -0,0 +1,37 @@
+import bpy
+
+
+class BUILTIN_KSI_hello(bpy.types.KeyingSetInfo):
+    bl_label = "Hello World KeyingSet"
+
+    # poll - test for whether Keying Set can be used at all
+    def poll(ksi, context):
+        return context.active_object or context.selected_objects
+
+    # iterator - go over all relevant data, calling generate()
+    def iterator(ksi, context, ks):
+        for ob in context.selected_objects:
+            ksi.generate(context, ks, ob)
+
+    # generator - populate Keying Set with property paths to use
+    def generate(ksi, context, ks, data):
+        id_block = data.id_data
+
+        ks.paths.add(id_block, "location")
+
+        for i in range(5):
+            ks.paths.add(id_block, "layers", i, group_method='NAMED', group_name="5x Hello Layers")
+
+        ks.paths.add(id_block, "show_x_ray", group_method='NONE')
+
+
+def register():
+    bpy.utils.register_class(BUILTIN_KSI_hello)
+
+
+def unregister():
+    bpy.utils.unregister_class(BUILTIN_KSI_hello)
+
+
+if __name__ == '__main__':
+    register()
diff --git a/release/scripts/templates_py/driver_functions.py b/release/scripts/templates_py/driver_functions.py
new file mode 100644
index 00000000000..1c6af0e574f
--- /dev/null
+++ b/release/scripts/templates_py/driver_functions.py
@@ -0,0 +1,35 @@
+# This script defines functions to be used directly in drivers expressions to
+# extend the builtin set of python functions.
+#
+# This can be executed on manually or set to 'Register' to
+# initialize thefunctions on file load.
+
+
+# two sample functions
+def invert(f):
+    """ Simple function call:
+
+            invert(val)
+    """
+    return 1.0 - f
+
+
+uuid_store = {}
+
+
+def slow_value(value, fac, uuid):
+    """ Delay the value by a factor, use a unique string to allow
+        use in multiple drivers without conflict:
+
+            slow_value(val, 0.5, "my_value")
+    """
+    value_prev = uuid_store.get(uuid, value)
+    uuid_store[uuid] = value_new = (value_prev * fac) + (value * (1.0 - fac))
+    return value_new
+
+
+import bpy
+
+# Add variable defined in this script into the drivers namespace.
+bpy.app.driver_namespace["invert"] = invert
+bpy.app.driver_namespace["slow_value"] = slow_value
diff --git a/release/scripts/templates_py/gamelogic.py b/release/scripts/templates_py/gamelogic.py
new file mode 100644
index 00000000000..01ac27c56cd
--- /dev/null
+++ b/release/scripts/templates_py/gamelogic.py
@@ -0,0 +1,73 @@
+# This script must be assigned to a python controller
+# where it can access the object that owns it and the sensors/actuators that it connects to.
+
+import bge
+
+# support for Vector(), Matrix() types and advanced functions like Matrix.Scale(...) and Matrix.Rotation(...)
+# import mathutils
+
+# for functions like getWindowWidth(), getWindowHeight()
+# import Rasterizer
+
+
+def main():
+    cont = bge.logic.getCurrentController()
+
+    # The KX_GameObject that owns this controller.
+    own = cont.owner
+
+    # for scripts that deal with spacial logic
+    own_pos = own.worldPosition
+
+    # Some example functions, remove to write your own script.
+    # check for a positive sensor, will run on any object without errors.
+    print("Logic info for KX_GameObject", own.name)
+    input = False
+
+    for sens in cont.sensors:
+        # The sensor can be on another object, we may want to use it
+        own_sens = sens.owner
+        print("    sensor:", sens.name, end=" ")
+        if sens.positive:
+            print("(true)")
+            input = True
+        else:
+            print("(false)")
+
+    for actu in cont.actuators:
+        # The actuator can be on another object, we may want to use it
+        own_actu = actu.owner
+        print("    actuator:", actu.name)
+
+        # This runs the actuator or turns it off
+        # note that actuators will continue to run unless explicitly turned off.
+        if input:
+            cont.activate(actu)
+        else:
+            cont.deactivate(actu)
+
+    # Its also good practice to get sensors and actuators by name
+    # rather then index so any changes to their order wont break the script.
+
+    # sens_key = cont.sensors["key_sensor"]
+    # actu_motion = cont.actuators["motion"]
+
+    # Loop through all other objects in the scene
+    sce = bge.logic.getCurrentScene()
+    print("Scene Objects:", sce.name)
+    for ob in sce.objects:
+        print("   ", ob.name, ob.worldPosition)
+
+    # Example where collision objects are checked for their properties
+    # adding to our objects "life" property
+    """
+    actu_collide = cont.sensors["collision_sens"]
+    for ob in actu_collide.objectHitList:
+        # Check to see the object has this property
+        if "life" in ob:
+            own["life"] += ob["life"]
+            ob["life"] = 0
+    print(own["life"])
+    """
+
+main()
diff --git a/release/scripts/templates_py/gamelogic_module.py b/release/scripts/templates_py/gamelogic_module.py
new file mode 100644
index 00000000000..88c8cf0d75b
--- /dev/null
+++ b/release/scripts/templates_py/gamelogic_module.py
@@ -0,0 +1,27 @@
+# This module can be accessed by a python controller with
+# its execution method set to 'Module'
+# * Set the module string to "gamelogic_module.main" (without quotes)
+# * When renaming the script it MUST have a .py extension
+# * External text modules are supported as long as they are at
+#   the same location as the blendfile or one of its libraries.
+
+import bge
+
+# variables defined here will only be set once when the
+# module is first imported. Set object specific vars
+# inside the function if you intend to use the module
+# with multiple objects.
+
+
+def main(cont):
+    own = cont.owner
+
+    sens = cont.sensors['mySensor']
+    actu = cont.actuators['myActuator']
+
+    if sens.positive:
+        cont.activate(actu)
+    else:
+        cont.deactivate(actu)
+
+# dont call main(bge.logic.getCurrentController()), the py controller will
diff --git a/release/scripts/templates_py/gamelogic_simple.py b/release/scripts/templates_py/gamelogic_simple.py
new file mode 100644
index 00000000000..dbfcf948b18
--- /dev/null
+++ b/release/scripts/templates_py/gamelogic_simple.py
@@ -0,0 +1,17 @@
+import bge
+
+
+def main():
+
+    cont = bge.logic.getCurrentController()
+    own = cont.owner
+
+    sens = cont.sensors['mySensor']
+    actu = cont.actuators['myActuator']
+
+    if sens.positive:
+        cont.activate(actu)
+    else:
+        cont.deactivate(actu)
+
+main()
diff --git a/release/scripts/templates_py/operator_file_export.py b/release/scripts/templates_py/operator_file_export.py
new file mode 100644
index 00000000000..9511cb163bc
--- /dev/null
+++ b/release/scripts/templates_py/operator_file_export.py
@@ -0,0 +1,72 @@
+import bpy
+
+
+def write_some_data(context, filepath, use_some_setting):
+    print("running write_some_data...")
+    f = open(filepath, 'w', encoding='utf-8')
+    f.write("Hello World %s" % use_some_setting)
+    f.close()
+
+    return {'FINISHED'}
+
+
+# ExportHelper is a helper class, defines filename and
+# invoke() function which calls the file selector.
+from bpy_extras.io_utils import ExportHelper
+from bpy.props import StringProperty, BoolProperty, EnumProperty
+from bpy.types import Operator
+
+
+class ExportSomeData(Operator, ExportHelper):
+    """This appears in the tooltip of the operator and in the generated docs"""
+    bl_idname = "export_test.some_data"  # important since its how bpy.ops.import_test.some_data is constructed
+    bl_label = "Export Some Data"
+
+    # ExportHelper mixin class uses this
+    filename_ext = ".txt"
+
+    filter_glob = StringProperty(
+            default="*.txt",
+            options={'HIDDEN'},
+            )
+
+    # List of operator properties, the attributes will be assigned
+    # to the class instance from the operator settings before calling.
+    use_setting = BoolProperty(
+            name="Example Boolean",
+            description="Example Tooltip",
+            default=True,
+            )
+
+    type = EnumProperty(
+            name="Example Enum",
+            description="Choose between two items",
+            items=(('OPT_A', "First Option", "Description one"),
+                   ('OPT_B', "Second Option", "Description two")),
+            default='OPT_A',
+            )
+
+    def execute(self, context):
+        return write_some_data(context, self.filepath, self.use_setting)
+
+
+# Only needed if you want to add into a dynamic menu
+def menu_func_export(self, context):
+    self.layout.operator(ExportSomeData.bl_idname, text="Text Export Operator")
+
+
+def register():
+    bpy.utils.register_class(ExportSomeData)
+    bpy.types.INFO_MT_file_export.append(menu_func_export)
+
+
+def unregister():
+    bpy.utils.unregister_class(ExportSomeData)
+    bpy.types.INFO_MT_file_export.remove(menu_func_export)
+
+
+if __name__ == "__main__":
+    register()
+
+    # test call
+    bpy.ops.export_test.some_data('INVOKE_DEFAULT')
diff --git a/release/scripts/templates_py/operator_file_import.py b/release/scripts/templates_py/operator_file_import.py
new file mode 100644
index 00000000000..9940a1b98eb
--- /dev/null
+++ b/release/scripts/templates_py/operator_file_import.py
@@ -0,0 +1,75 @@
+import bpy
+
+
+def read_some_data(context, filepath, use_some_setting):
+    print("running read_some_data...")
+    f = open(filepath, 'r', encoding='utf-8')
+    data = f.read()
+    f.close()
+
+    # would normally load the data here
+    print(data)
+
+    return {'FINISHED'}
+
+
+# ImportHelper is a helper class, defines filename and
+# invoke() function which calls the file selector.
+from bpy_extras.io_utils import ImportHelper
+from bpy.props import StringProperty, BoolProperty, EnumProperty
+from bpy.types import Operator
+
+
+class ImportSomeData(Operator, ImportHelper):
+    """This appears in the tooltip of the operator and in the generated docs"""
+    bl_idname = "import_test.some_data"  # important since its how bpy.ops.import_test.some_data is constructed
+    bl_label = "Import Some Data"
+
+    # ImportHelper mixin class uses this
+    filename_ext = ".txt"
+
+    filter_glob = StringProperty(
+            default="*.txt",
+            options={'HIDDEN'},
+            )
+
+    # List of operator properties, the attributes will be assigned
+    # to the class instance from the operator settings before calling.
+    use_setting = BoolProperty(
+            name="Example Boolean",
+            description="Example Tooltip",
+            default=True,
+            )
+
+    type = EnumProperty(
+            name="Example Enum",
+            description="Choose between two items",
+            items=(('OPT_A', "First Option", "Description one"),
+                   ('OPT_B', "Second Option", "Description two")),
+            default='OPT_A',
+            )
+
+    def execute(self, context):
+        return read_some_data(context, self.filepath, self.use_setting)
+
+
+# Only needed if you want to add into a dynamic menu
+def menu_func_import(self, context):
+    self.layout.operator(ImportSomeData.bl_idname, text="Text Import Operator")
+
+
+def register():
+    bpy.utils.register_class(ImportSomeData)
+    bpy.types.INFO_MT_file_import.append(menu_func_import)
+
+
+def unregister():
+    bpy.utils.unregister_class(ImportSomeData)
+    bpy.types.INFO_MT_file_import.remove(menu_func_import)
+
+
+if __name__ == "__main__":
+    register()
+
+    # test call
+    bpy.ops.import_test.some_data('INVOKE_DEFAULT')
diff --git a/release/scripts/templates_py/operator_mesh_add.py b/release/scripts/templates_py/operator_mesh_add.py
new file mode 100644
index 00000000000..fa248cb9005
--- /dev/null
+++ b/release/scripts/templates_py/operator_mesh_add.py
@@ -0,0 +1,122 @@
+import bpy
+import bmesh
+
+
+def add_box(width, height, depth):
+    """
+    This function takes inputs and returns vertex and face arrays.
+    no actual mesh data creation is done here.
+    """
+
+    verts = [(+1.0, +1.0, -1.0),
+             (+1.0, -1.0, -1.0),
+             (-1.0, -1.0, -1.0),
+             (-1.0, +1.0, -1.0),
+             (+1.0, +1.0, +1.0),
+             (+1.0, -1.0, +1.0),
+             (-1.0, -1.0, +1.0),
+             (-1.0, +1.0, +1.0),
+             ]
+
+    faces = [(0, 1, 2, 3),
+             (4, 7, 6, 5),
+             (0, 4, 5, 1),
+             (1, 5, 6, 2),
+             (2, 6, 7, 3),
+             (4, 0, 3, 7),
+            ]
+
+    # apply size
+    for i, v in enumerate(verts):
+        verts[i] = v[0] * width, v[1] * depth, v[2] * height
+
+    return verts, faces
+
+
+from bpy.props import FloatProperty, BoolProperty, FloatVectorProperty
+
+
+class AddBox(bpy.types.Operator):
+    """Add a simple box mesh"""
+    bl_idname = "mesh.primitive_box_add"
+    bl_label = "Add Box"
+    bl_options = {'REGISTER', 'UNDO'}
+
+    width = FloatProperty(
+            name="Width",
+            description="Box Width",
+            min=0.01, max=100.0,
+            default=1.0,
+            )
+    height = FloatProperty(
+            name="Height",
+            description="Box Height",
+            min=0.01, max=100.0,
+            default=1.0,
+            )
+    depth = FloatProperty(
+            name="Depth",
+            description="Box Depth",
+            min=0.01, max=100.0,
+            default=1.0,
+            )
+
+    # generic transform props
+    view_align = BoolProperty(
+            name="Align to View",
+            default=False,
+            )
+    location = FloatVectorProperty(
+            name="Location",
+            subtype='TRANSLATION',
+            )
+    rotation = FloatVectorProperty(
+            name="Rotation",
+            subtype='EULER',
+            )
+
+    def execute(self, context):
+
+        verts_loc, faces = add_box(self.width,
+                                   self.height,
+                                   self.depth,
+                                   )
+
+        mesh = bpy.data.meshes.new("Box")
+
+        bm = bmesh.new()
+
+        for v_co in verts_loc:
+            bm.verts.new(v_co)
+
+        for f_idx in faces:
+            bm.faces.new([bm.verts[i] for i in f_idx])
+
+        bm.to_mesh(mesh)
+        mesh.update()
+
+        # add the mesh as an object into the scene with this utility module
+        from bpy_extras import object_utils
+        object_utils.object_data_add(context, mesh, operator=self)
+
+        return {'FINISHED'}
+
+
+def menu_func(self, context):
+    self.layout.operator(AddBox.bl_idname, icon='MESH_CUBE')
+
+
+def register():
+    bpy.utils.register_class(AddBox)
+    bpy.types.INFO_MT_mesh_add.append(menu_func)
+
+
+def unregister():
+    bpy.utils.unregister_class(AddBox)
+    bpy.types.INFO_MT_mesh_add.remove(menu_func)
+
+if __name__ == "__main__":
+    register()
+
+    # test call
+    bpy.ops.mesh.primitive_box_add()
diff --git a/release/scripts/templates_py/operator_modal.py b/release/scripts/templates_py/operator_modal.py
new file mode 100644
index 00000000000..88e5ee80590
--- /dev/null
+++ b/release/scripts/templates_py/operator_modal.py
@@ -0,0 +1,51 @@
+import bpy
+from bpy.props import IntProperty, FloatProperty
+
+
+class ModalOperator(bpy.types.Operator):
+    """Move an object with the mouse, example"""
+    bl_idname = "object.modal_operator"
+    bl_label = "Simple Modal Operator"
+
+    first_mouse_x = IntProperty()
+    first_value = FloatProperty()
+
+    def modal(self, context, event):
+        if event.type == 'MOUSEMOVE':
+            delta = self.first_mouse_x - event.mouse_x
+            context.object.location.x = self.first_value + delta * 0.01
+
+        elif event.type == 'LEFTMOUSE':
+            return {'FINISHED'}
+
+        elif event.type in {'RIGHTMOUSE', 'ESC'}:
+            context.object.location.x = self.first_value
+            return {'CANCELLED'}
+
+        return {'RUNNING_MODAL'}
+
+    def invoke(self, context, event):
+        if context.object:
+            self.first_mouse_x = event.mouse_x
+            self.first_value = context.object.location.x
+
+            context.window_manager.modal_handler_add(self)
+            return {'RUNNING_MODAL'}
+        else:
+            self.report({'WARNING'}, "No active object, could not finish")
+            return {'CANCELLED'}
+
+
+def register():
+    bpy.utils.register_class(ModalOperator)
+
+
+def unregister():
+    bpy.utils.unregister_class(ModalOperator)
+
+
+if __name__ == "__main__":
+    register()
+
+    # test call
+    bpy.ops.object.modal_operator('INVOKE_DEFAULT')
diff --git a/release/scripts/templates_py/operator_modal_draw.py b/release/scripts/templates_py/operator_modal_draw.py
new file mode 100644
index 00000000000..d11ddf0b467
--- /dev/null
+++ b/release/scripts/templates_py/operator_modal_draw.py
@@ -0,0 +1,79 @@
+import bpy
+import bgl
+import blf
+
+
+def draw_callback_px(self, context):
+    print("mouse points", len(self.mouse_path))
+
+    font_id = 0  # XXX, need to find out how best to get this.
+
+    # draw some text
+    blf.position(font_id, 15, 30, 0)
+    blf.size(font_id, 20, 72)
+    blf.draw(font_id, "Hello Word " + str(len(self.mouse_path)))
+
+    # 50% alpha, 2 pixel width line
+    bgl.glEnable(bgl.GL_BLEND)
+    bgl.glColor4f(0.0, 0.0, 0.0, 0.5)
+    bgl.glLineWidth(2)
+
+    bgl.glBegin(bgl.GL_LINE_STRIP)
+    for x, y in self.mouse_path:
+        bgl.glVertex2i(x, y)
+
+    bgl.glEnd()
+
+    # restore opengl defaults
+    bgl.glLineWidth(1)
+    bgl.glDisable(bgl.GL_BLEND)
+    bgl.glColor4f(0.0, 0.0, 0.0, 1.0)
+
+
+class ModalDrawOperator(bpy.types.Operator):
+    """Draw a line with the mouse"""
+    bl_idname = "view3d.modal_operator"
+    bl_label = "Simple Modal View3D Operator"
+
+    def modal(self, context, event):
+        context.area.tag_redraw()
+
+        if event.type == 'MOUSEMOVE':
+            self.mouse_path.append((event.mouse_region_x, event.mouse_region_y))
+
+        elif event.type == 'LEFTMOUSE':
+            bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
+            return {'FINISHED'}
+
+        elif event.type in {'RIGHTMOUSE', 'ESC'}:
+            bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
+            return {'CANCELLED'}
+
+        return {'RUNNING_MODAL'}
+
+    def invoke(self, context, event):
+        if context.area.type == 'VIEW_3D':
+            # the arguments we pass the the callback
+            args = (self, context)
+            # Add the region OpenGL drawing callback
+            # draw in view space with 'POST_VIEW' and 'PRE_VIEW'
+            self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_callback_px, args, 'WINDOW', 'POST_PIXEL')
+
+            self.mouse_path = []
+
+            context.window_manager.modal_handler_add(self)
+            return {'RUNNING_MODAL'}
+        else:
+            self.report({'WARNING'}, "View3D not found, cannot run operator")
+            return {'CANCELLED'}
+
+
+def register():
+    bpy.utils.register_class(ModalDrawOperator)
+
+
+def unregister():
+    bpy.utils.unregister_class(ModalDrawOperator)
+
+if __name__ == "__main__":
+    register()
diff --git a/release/scripts/templates_py/operator_modal_timer.py b/release/scripts/templates_py/operator_modal_timer.py
new file mode 100644
index 00000000000..72c153df9d2
--- /dev/null
+++ b/release/scripts/templates_py/operator_modal_timer.py
@@ -0,0 +1,45 @@
+import bpy
+
+
+class ModalTimerOperator(bpy.types.Operator):
+    """Operator which runs its self from a timer"""
+    bl_idname = "wm.modal_timer_operator"
+    bl_label = "Modal Timer Operator"
+
+    _timer = None
+
+    def modal(self, context, event):
+        if event.type == 'ESC':
+            return self.cancel(context)
+
+        if event.type == 'TIMER':
+            # change theme color, silly!
+            color = context.user_preferences.themes[0].view_3d.space.back
+            color.s = 1.0
+            color.h += 0.01
+
+        return {'PASS_THROUGH'}
+
+    def execute(self, context):
+        self._timer = context.window_manager.event_timer_add(0.1, context.window)
+        context.window_manager.modal_handler_add(self)
+        return {'RUNNING_MODAL'}
+
+    def cancel(self, context):
+        context.window_manager.event_timer_remove(self._timer)
+        return {'CANCELLED'}
+
+
+def register():
+    bpy.utils.register_class(ModalTimerOperator)
+
+
+def unregister():
+    bpy.utils.unregister_class(ModalTimerOperator)
+
+
+if __name__ == "__main__":
+    register()
+
+    # test call
+    bpy.ops.wm.modal_timer_operator()
diff --git a/release/scripts/templates_py/operator_modal_view3d.py b/release/scripts/templates_py/operator_modal_view3d.py
new file mode 100644
index 00000000000..c870bbffdcf
--- /dev/null
+++ b/release/scripts/templates_py/operator_modal_view3d.py
@@ -0,0 +1,70 @@
+import bpy
+from mathutils import Vector
+from bpy.props import FloatVectorProperty
+
+
+class ViewOperator(bpy.types.Operator):
+    """Translate the view using mouse events"""
+    bl_idname = "view3d.modal_operator"
+    bl_label = "Simple View Operator"
+
+    offset = FloatVectorProperty(
+            name="Offset",
+            size=3,
+            )
+
+    def execute(self, context):
+        v3d = context.space_data
+        rv3d = v3d.region_3d
+
+        rv3d.view_location = self._initial_location + Vector(self.offset)
+
+    def modal(self, context, event):
+        v3d = context.space_data
+        rv3d = v3d.region_3d
+
+        if event.type == 'MOUSEMOVE':
+            self.offset = (self._initial_mouse - Vector((event.mouse_x, event.mouse_y, 0.0))) * 0.02
+            self.execute(context)
+            context.area.header_text_set("Offset %.4f %.4f %.4f" % tuple(self.offset))
+
+        elif event.type == 'LEFTMOUSE':
+            context.area.header_text_set()
+            return {'FINISHED'}
+
+        elif event.type in {'RIGHTMOUSE', 'ESC'}:
+            rv3d.view_location = self._initial_location
+            context.area.header_text_set()
+            return {'CANCELLED'}
+
+        return {'RUNNING_MODAL'}
+
+    def invoke(self, context, event):
+
+        if context.space_data.type == 'VIEW_3D':
+            v3d = context.space_data
+            rv3d = v3d.region_3d
+
+            if rv3d.view_perspective == 'CAMERA':
+                rv3d.view_perspective = 'PERSP'
+
+            self._initial_mouse = Vector((event.mouse_x, event.mouse_y, 0.0))
+            self._initial_location = rv3d.view_location.copy()
+
+            context.window_manager.modal_handler_add(self)
+            return {'RUNNING_MODAL'}
+        else:
+            self.report({'WARNING'}, "Active space must be a View3d")
+            return {'CANCELLED'}
+
+
+def register():
+    bpy.utils.register_class(ViewOperator)
+
+
+def unregister():
+    bpy.utils.unregister_class(ViewOperator)
+
+
+if __name__ == "__main__":
+    register()
diff --git a/release/scripts/templates_py/operator_modal_view3d_raycast.py b/release/scripts/templates_py/operator_modal_view3d_raycast.py
new file mode 100644
index 00000000000..eac76922187
--- /dev/null
+++ b/release/scripts/templates_py/operator_modal_view3d_raycast.py
@@ -0,0 +1,110 @@
+import bpy
+from mathutils import Vector
+from bpy_extras import view3d_utils
+
+
+def main(context, event, ray_max=10000.0):
+    """Run this function on left mouse, execute the ray cast"""
+    # get the context arguments
+    scene = context.scene
+    region = context.region
+    rv3d = context.region_data
+    coord = event.mouse_region_x, event.mouse_region_y
+
+    # get the ray from the viewport and mouse
+    view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
+    ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)
+    ray_target = ray_origin + (view_vector * ray_max)
+
+
+    def visible_objects_and_duplis():
+        """Loop over (object, matrix) pairs (mesh only)"""
+
+        for obj in context.visible_objects:
+            if obj.type == 'MESH':
+                yield (obj, obj.matrix_world.copy())
+
+            if obj.dupli_type != 'NONE':
+                obj.dupli_list_create(scene)
+                for dob in obj.dupli_list:
+                    obj_dupli = dob.object
+                    if obj_dupli.type == 'MESH':
+                        yield (obj_dupli, dob.matrix.copy())
+
+            obj.dupli_list_clear()
+
+    def obj_ray_cast(obj, matrix):
+        """Wrapper for ray casting that moves the ray into object space"""
+
+        # get the ray relative to the object
+        matrix_inv = matrix.inverted()
+        ray_origin_obj = matrix_inv * ray_origin
+        ray_target_obj = matrix_inv * ray_target
+
+        # cast the ray
+        hit, normal, face_index = obj.ray_cast(ray_origin_obj, ray_target_obj)
+
+        if face_index != -1:
+            return hit, normal, face_index
+        else:
+            return None, None, None
+
+    # cast rays and find the closest object
+    best_length_squared = ray_max * ray_max
+    best_obj = None
+
+    for obj, matrix in visible_objects_and_duplis():
+        if obj.type == 'MESH':
+            hit, normal, face_index = obj_ray_cast(obj, matrix)
+            if hit is not None:
+                hit_world = matrix * hit
+                scene.cursor_location = hit_world
+                length_squared = (hit_world - ray_origin).length_squared
+                if length_squared < best_length_squared:
+                    best_length_squared = length_squared
+                    best_obj = obj
+
+    # now we have the object under the mouse cursor,
+    # we could do lots of stuff but for the example just select.
+    if best_obj is not None:
+        best_obj.select = True
+        context.scene.objects.active = best_obj
+
+
+class ViewOperatorRayCast(bpy.types.Operator):
+    """Modal object selection with a ray cast"""
+    bl_idname = "view3d.modal_operator_raycast"
+    bl_label = "RayCast View Operator"
+
+    def modal(self, context, event):
+        if event.type in {'MIDDLEMOUSE', 'WHEELUPMOUSE', 'WHEELDOWNMOUSE'}:
+            # allow navigation
+            return {'PASS_THROUGH'}
+        elif event.type == 'LEFTMOUSE':
+            main(context, event)
+            return {'RUNNING_MODAL'}
+        elif event.type in {'RIGHTMOUSE', 'ESC'}:
+            return {'CANCELLED'}
+
+        return {'RUNNING_MODAL'}
+
+    def invoke(self, context, event):
+        if context.space_data.type == 'VIEW_3D':
+            context.window_manager.modal_handler_add(self)
+            return {'RUNNING_MODAL'}
+        else:
+            self.report({'WARNING'}, "Active space must be a View3d")
+            return {'CANCELLED'}
+
+
+def register():
+    bpy.utils.register_class(ViewOperatorRayCast)
+
+
+def unregister():
+    bpy.utils.unregister_class(ViewOperatorRayCast)
+
+
+if __name__ == "__main__":
+    register()
+
diff --git a/release/scripts/templates_py/operator_node.py b/release/scripts/templates_py/operator_node.py
new file mode 100644
index 00000000000..b689ce7634e
--- /dev/null
+++ b/release/scripts/templates_py/operator_node.py
@@ -0,0 +1,59 @@
+import bpy
+
+
+def main(context):
+    space = context.space_data
+    node_tree = space.node_tree
+    node_active = context.active_node
+    node_selected = context.selected_nodes
+
+    # now we have the context, perform a simple operation
+    if node_active in node_selected:
+        node_selected.remove(node_active)
+    if len(node_selected) != 1:
+        operator.report({'ERROR'}, "2 nodes must be selected")
+        return
+
+    node_other, = node_selected
+
+    # now we have 2 nodes to operate on
+    if not node_active.inputs:
+        operator.report({'ERROR'}, "Active node has no inputs")
+        return
+
+    if not node_other.outputs:
+        operator.report({'ERROR'}, "Selected node has no outputs")
+        return
+
+    socket_in = node_active.inputs[0]
+    socket_out = node_other.outputs[0]
+
+    # add a link between the two nodes
+    node_link = node_tree.links.new(socket_in, socket_out)
+
+
+class NodeOperator(bpy.types.Operator):
+    """Tooltip"""
+    bl_idname = "node.simple_operator"
+    bl_label = "Simple Node Operator"
+
+    @classmethod
+    def poll(cls, context):
+        space = context.space_data
+        return space.type == 'NODE_EDITOR'
+
+    def execute(self, context):
+        main(context)
+        return {'FINISHED'}
+
+
+def register():
+    bpy.utils.register_class(NodeOperator)
+
+
+def unregister():
+    bpy.utils.unregister_class(NodeOperator)
+
+
+if __name__ == "__main__":
+    register()
diff --git a/release/scripts/templates_py/operator_simple.py b/release/scripts/templates_py/operator_simple.py
new file mode 100644
index 00000000000..715daa3a8b4
--- /dev/null
+++ b/release/scripts/templates_py/operator_simple.py
@@ -0,0 +1,35 @@
+import bpy
+
+
+def main(context):
+    for ob in context.scene.objects:
+        print(ob)
+
+
+class SimpleOperator(bpy.types.Operator):
+    """Tooltip"""
+    bl_idname = "object.simple_operator"
+    bl_label = "Simple Object Operator"
+
+    @classmethod
+    def poll(cls, context):
+        return context.active_object is not None
+
+    def execute(self, context):
+        main(context)
+        return {'FINISHED'}
+
+
+def register():
+    bpy.utils.register_class(SimpleOperator)
+
+
+def unregister():
+    bpy.utils.unregister_class(SimpleOperator)
+
+
+if __name__ == "__main__":
+    register()
+
+    # test call
+    bpy.ops.object.simple_operator()
diff --git a/release/scripts/templates_py/operator_uv.py b/release/scripts/templates_py/operator_uv.py
new file mode 100644
index 00000000000..fdd0b993f8b
--- /dev/null
+++ b/release/scripts/templates_py/operator_uv.py
@@ -0,0 +1,56 @@
+import bpy
+
+
+def main(context):
+    obj = context.active_object
+    mesh = obj.data
+
+    is_editmode = (obj.mode == 'EDIT')
+    if is_editmode:
+        bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+
+    if not mesh.uv_textures:
+        uvtex = bpy.ops.mesh.uv_texture_add()
+    else:
+        uvtex = mesh.uv_textures.active
+
+    # adjust UVs
+    for i, uv in enumerate(uvtex.data):
+        uvs = uv.uv1, uv.uv2, uv.uv3, uv.uv4
+        for j, v_idx in enumerate(mesh.faces[i].vertices):
+            if uv.select_uv[j]:
+                # apply the location of the vertex as a UV
+                uvs[j][:] = mesh.vertices[v_idx].co.xy
+
+    if is_editmode:
+        bpy.ops.object.mode_set(mode='EDIT', toggle=False)
+
+
+class UvOperator(bpy.types.Operator):
+    """UV Operator description"""
+    bl_idname = "uv.simple_operator"
+    bl_label = "Simple UV Operator"
+
+    @classmethod
+    def poll(cls, context):
+        obj = context.active_object
+        return (obj and obj.type == 'MESH')
+
+    def execute(self, context):
+        main(context)
+        return {'FINISHED'}
+
+
+def register():
+    bpy.utils.register_class(UvOperator)
+
+
+def unregister():
+    bpy.utils.unregister_class(UvOperator)
+
+
+if __name__ == "__main__":
+    register()
+
+    # test call
+    bpy.ops.uv.simple_operator()
diff --git a/release/scripts/templates_py/script_stub.py b/release/scripts/templates_py/script_stub.py
new file mode 100644
index 00000000000..44c7b802e2c
--- /dev/null
+++ b/release/scripts/templates_py/script_stub.py
@@ -0,0 +1,14 @@
+# This stub runs a python script relative to the currently open
+# blend file, useful when editing scripts externally.
+
+import bpy
+import os
+
+# Use your own script name here:
+filename = "my_script.py"
+
+filepath = os.path.join(os.path.dirname(bpy.data.filepath), filename)
+global_namespace = {"__file__": filepath, "__name__": "__main__"}
+file = open(filepath, 'rb')
+exec(compile(file.read(), filepath, 'exec'), global_namespace)
+file.close()
diff --git a/release/scripts/templates_py/ui_menu.py b/release/scripts/templates_py/ui_menu.py
new file mode 100644
index 00000000000..a21e5ed86c8
--- /dev/null
+++ b/release/scripts/templates_py/ui_menu.py
@@ -0,0 +1,49 @@
+import bpy
+
+
+class CustomMenu(bpy.types.Menu):
+    bl_label = "Custom Menu"
+    bl_idname = "OBJECT_MT_custom_menu"
+
+    def draw(self, context):
+        layout = self.layout
+
+        layout.operator("wm.open_mainfile")
+        layout.operator("wm.save_as_mainfile").copy = True
+
+        layout.operator("object.shade_smooth")
+
+        layout.label(text="Hello world!", icon='WORLD_DATA')
+
+        # use an operator enum property to populate a sub-menu
+        layout.operator_menu_enum("object.select_by_type",
+                                  property="type",
+                                  text="Select All by Type...",
+                                  )
+
+        # call another menu
+        layout.operator("wm.call_menu", text="Unwrap").name = "VIEW3D_MT_uv_map"
+
+
+def draw_item(self, context):
+    layout = self.layout
+    layout.menu(CustomMenu.bl_idname)
+
+
+def register():
+    bpy.utils.register_class(CustomMenu)
+
+    # lets add ourselves to the main header
+    bpy.types.INFO_HT_header.append(draw_item)
+
+
+def unregister():
+    bpy.utils.unregister_class(CustomMenu)
+
+    bpy.types.INFO_HT_header.remove(draw_item)
+
+if __name__ == "__main__":
+    register()
+
+    # The menu can also be called from scripts
+    bpy.ops.wm.call_menu(name=CustomMenu.bl_idname)
diff --git a/release/scripts/templates_py/ui_menu_simple.py b/release/scripts/templates_py/ui_menu_simple.py
new file mode 100644
index 00000000000..2129dfd81a4
--- /dev/null
+++ b/release/scripts/templates_py/ui_menu_simple.py
@@ -0,0 +1,26 @@
+import bpy
+
+
+class SimpleCustomMenu(bpy.types.Menu):
+    bl_label = "Simple Custom Menu"
+    bl_idname = "OBJECT_MT_simple_custom_menu"
+
+    def draw(self, context):
+        layout = self.layout
+
+        layout.operator("wm.open_mainfile")
+        layout.operator("wm.save_as_mainfile")
+
+
+def register():
+    bpy.utils.register_class(SimpleCustomMenu)
+
+
+def unregister():
+    bpy.utils.unregister_class(SimpleCustomMenu)
+
+if __name__ == "__main__":
+    register()
+
+    # The menu can also be called from scripts
+    bpy.ops.wm.call_menu(name=SimpleCustomMenu.bl_idname)
diff --git a/release/scripts/templates_py/ui_panel.py b/release/scripts/templates_py/ui_panel.py
new file mode 100644
index 00000000000..cacdb83e815
--- /dev/null
+++ b/release/scripts/templates_py/ui_panel.py
@@ -0,0 +1,73 @@
+import bpy
+
+
+class LayoutDemoPanel(bpy.types.Panel):
+    """Creates a Panel in the scene context of the properties editor"""
+    bl_label = "Layout Demo"
+    bl_idname = "SCENE_PT_layout"
+    bl_space_type = 'PROPERTIES'
+    bl_region_type = 'WINDOW'
+    bl_context = "scene"
+
+    def draw(self, context):
+        layout = self.layout
+
+        scene = context.scene
+
+        # Create a simple row.
+        layout.label(text=" Simple Row:")
+
+        row = layout.row()
+        row.prop(scene, "frame_start")
+        row.prop(scene, "frame_end")
+
+        # Create an row where the buttons are aligned to each other.
+        layout.label(text=" Aligned Row:")
+
+        row = layout.row(align=True)
+        row.prop(scene, "frame_start")
+        row.prop(scene, "frame_end")
+
+        # Create two columns, by using a split layout.
+        split = layout.split()
+
+        # First column
+        col = split.column()
+        col.label(text="Column One:")
+        col.prop(scene, "frame_end")
+        col.prop(scene, "frame_start")
+
+        # Second column, aligned
+        col = split.column(align=True)
+        col.label(text="Column Two:")
+        col.prop(scene, "frame_start")
+        col.prop(scene, "frame_end")
+        
+        # Big render button
+        layout.label(text="Big Button:")
+        row = layout.row()
+        row.scale_y = 3.0
+        row.operator("render.render")
+        
+        # Different sizes in a row
+        layout.label(text="Different button sizes:")
+        row = layout.row(align=True)
+        row.operator("render.render")
+        
+        sub = row.row()
+        sub.scale_x = 2.0
+        sub.operator("render.render")
+        
+        row.operator("render.render")
+
+
+def register():
+    bpy.utils.register_class(LayoutDemoPanel)
+
+
+def unregister():
+    bpy.utils.unregister_class(LayoutDemoPanel)
+
+
+if __name__ == "__main__":
+    register()
diff --git a/release/scripts/templates_py/ui_panel_simple.py b/release/scripts/templates_py/ui_panel_simple.py
new file mode 100644
index 00000000000..9bcc750560f
--- /dev/null
+++ b/release/scripts/templates_py/ui_panel_simple.py
@@ -0,0 +1,38 @@
+import bpy
+
+
+class HelloWorldPanel(bpy.types.Panel):
+    """Creates a Panel in the Object properties window"""
+    bl_label = "Hello World Panel"
+    bl_idname = "OBJECT_PT_hello"
+    bl_space_type = 'PROPERTIES'
+    bl_region_type = 'WINDOW'
+    bl_context = "object"
+
+    def draw(self, context):
+        layout = self.layout
+
+        obj = context.object
+
+        row = layout.row()
+        row.label(text="Hello world!", icon='WORLD_DATA')
+
+        row = layout.row()
+        row.label(text="Active object is: " + obj.name)
+        row = layout.row()
+        row.prop(obj, "name")
+
+        row = layout.row()
+        row.operator("mesh.primitive_cube_add")
+
+
+def register():
+    bpy.utils.register_class(HelloWorldPanel)
+
+
+def unregister():
+    bpy.utils.unregister_class(HelloWorldPanel)
+
+
+if __name__ == "__main__":
+    register()
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(-)

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.

---
 release/scripts/templates_osl/empty_shader.osl      |  6 ++++++
 release/scripts/templates_osl/noise.osl             | 18 ++++++++++++++++++
 release/scripts/templates_osl/wireframe.osl         | 10 ++++++++++
 source/blender/editors/space_text/text_format_osl.c |  2 +-
 4 files changed, 35 insertions(+), 1 deletion(-)
 create mode 100644 release/scripts/templates_osl/empty_shader.osl
 create mode 100644 release/scripts/templates_osl/noise.osl
 create mode 100644 release/scripts/templates_osl/wireframe.osl

diff --git a/release/scripts/templates_osl/empty_shader.osl b/release/scripts/templates_osl/empty_shader.osl
new file mode 100644
index 00000000000..8526e0f2e9b
--- /dev/null
+++ b/release/scripts/templates_osl/empty_shader.osl
@@ -0,0 +1,6 @@
+#include "stdosl.h"
+
+shader name()
+{
+
+}
\ No newline at end of file
diff --git a/release/scripts/templates_osl/noise.osl b/release/scripts/templates_osl/noise.osl
new file mode 100644
index 00000000000..e152824b192
--- /dev/null
+++ b/release/scripts/templates_osl/noise.osl
@@ -0,0 +1,18 @@
+#include 
+
+shader noise(
+	float Time = 1.0,
+	point Point = P,
+	output float Cell = 0.0,
+	output color Perlin = 0.8,
+	output color UPerlin = 0.8)
+{   
+	/* Cell Noise */
+	Cell = noise("cell", Point);
+	
+    /* Perlin 4D Noise*/
+    Perlin = noise("perlin", Point, Time);
+   
+    /* UPerlin 4D Noise*/
+    UPerlin = noise("uperlin", Point, Time);
+}
\ No newline at end of file
diff --git a/release/scripts/templates_osl/wireframe.osl b/release/scripts/templates_osl/wireframe.osl
new file mode 100644
index 00000000000..193dc7ee925
--- /dev/null
+++ b/release/scripts/templates_osl/wireframe.osl
@@ -0,0 +1,10 @@
+#include "stdosl.h"
+#include "oslutil.h"
+
+shader wireframe(
+    float Line_Width = 2.0,
+    int Raster = 1,
+    output float Wire = 0.0)
+{
+    Wire = wireframe("triangles", Line_Width, Raster);
+}
\ No newline at end of file
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 b3d365289f379ea6838432d7131458a6dce5ceea Mon Sep 17 00:00:00 2001
From: Brecht Van Lommel 
Date: Sun, 30 Dec 2012 10:37:32 +0000
Subject: OSL Templates: remove unnecessary stdosl.h include.

---
 release/scripts/templates_osl/empty_shader.osl | 4 ++--
 release/scripts/templates_osl/noise.osl        | 4 ++--
 release/scripts/templates_osl/wireframe.osl    | 5 +++--
 3 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/release/scripts/templates_osl/empty_shader.osl b/release/scripts/templates_osl/empty_shader.osl
index 8526e0f2e9b..e2c9a4a257e 100644
--- a/release/scripts/templates_osl/empty_shader.osl
+++ b/release/scripts/templates_osl/empty_shader.osl
@@ -1,6 +1,6 @@
-#include "stdosl.h"
 
 shader name()
 {
 
-}
\ No newline at end of file
+}
+
diff --git a/release/scripts/templates_osl/noise.osl b/release/scripts/templates_osl/noise.osl
index e152824b192..05cc31687c0 100644
--- a/release/scripts/templates_osl/noise.osl
+++ b/release/scripts/templates_osl/noise.osl
@@ -1,4 +1,3 @@
-#include 
 
 shader noise(
 	float Time = 1.0,
@@ -15,4 +14,5 @@ shader noise(
    
     /* UPerlin 4D Noise*/
     UPerlin = noise("uperlin", Point, Time);
-}
\ No newline at end of file
+}
+
diff --git a/release/scripts/templates_osl/wireframe.osl b/release/scripts/templates_osl/wireframe.osl
index 193dc7ee925..00e4506e73c 100644
--- a/release/scripts/templates_osl/wireframe.osl
+++ b/release/scripts/templates_osl/wireframe.osl
@@ -1,4 +1,4 @@
-#include "stdosl.h"
+
 #include "oslutil.h"
 
 shader wireframe(
@@ -7,4 +7,5 @@ shader wireframe(
     output float Wire = 0.0)
 {
     Wire = wireframe("triangles", Line_Width, Raster);
-}
\ No newline at end of file
+}
+
-- 
cgit v1.2.3


From fde101c50c3d7ad6bb43a578d7622cea084001a3 Mon Sep 17 00:00:00 2001
From: Ton Roosendaal 
Date: Sun, 30 Dec 2012 10:38:56 +0000
Subject: Revert change from Jens, wrong pointer check in the code.

That change made all scrollwheel events be handled as if it was a swipe gesture.
Old style mouse wheel didn't work anymore.

This version should work for everyone, but we need more mac testers :)
---
 intern/ghost/intern/GHOST_SystemCocoa.mm | 14 ++++----------
 1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index d88b90d8f05..2d9d89d9ad0 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -1577,21 +1577,15 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
 			}
 			break;
 			
-		case NSEventTypeBeginGesture:
-			m_hasMultiTouchTrackpad = true;
-			break;
-		case NSEventTypeEndGesture:
-			m_hasMultiTouchTrackpad = false;
-			break;
-			
 		case NSScrollWheel:
 			{
 				int momentum = 0;
 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
-				momentum = [event momentumPhase];
+				m_hasMultiTouchTrackpad = 0;
+				momentum = [event momentumPhase] || [event phase];
 #endif
-				/* standard scrollwheel case, NULL check address !!! of momentum */
-				if (!m_hasMultiTouchTrackpad && &momentum == NULL) {
+				/* standard scrollwheel case */
+				if (!m_hasMultiTouchTrackpad && momentum == 0) {
 					GHOST_TInt32 delta;
 					
 					double deltaF = [event deltaY];
-- 
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(-)

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(-)

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(-)

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(-)

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(-)

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.
---
 extern/CMakeLists.txt                |   1 +
 extern/SConscript                    |   1 +
 extern/rangetree/CMakeLists.txt      |  31 +++++
 extern/rangetree/README.org          |  13 ++
 extern/rangetree/SConscript          |   9 ++
 extern/rangetree/range_tree.hh       | 228 +++++++++++++++++++++++++++++++++++
 extern/rangetree/range_tree_c_api.cc |  86 +++++++++++++
 extern/rangetree/range_tree_c_api.h  |  60 +++++++++
 source/blenderplayer/CMakeLists.txt  |   1 +
 source/creator/CMakeLists.txt        |   1 +
 10 files changed, 431 insertions(+)
 create mode 100644 extern/rangetree/CMakeLists.txt
 create mode 100644 extern/rangetree/README.org
 create mode 100644 extern/rangetree/SConscript
 create mode 100644 extern/rangetree/range_tree.hh
 create mode 100644 extern/rangetree/range_tree_c_api.cc
 create mode 100644 extern/rangetree/range_tree_c_api.h

diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt
index 2640c528c94..2f7f6584f0f 100644
--- a/extern/CMakeLists.txt
+++ b/extern/CMakeLists.txt
@@ -27,6 +27,7 @@
 remove_strict_flags()
 
 add_subdirectory(colamd)
+add_subdirectory(rangetree)
 
 if(WITH_BULLET)
 	add_subdirectory(bullet2)
diff --git a/extern/SConscript b/extern/SConscript
index 71998ee072c..6a0ffa3f588 100644
--- a/extern/SConscript
+++ b/extern/SConscript
@@ -4,6 +4,7 @@ Import('env')
 
 SConscript(['glew/SConscript'])
 SConscript(['colamd/SConscript'])
+SConscript(['rangetree/SConscript'])
 
 if env['WITH_BF_GAMEENGINE']:
     SConscript(['recastnavigation/SConscript'])
diff --git a/extern/rangetree/CMakeLists.txt b/extern/rangetree/CMakeLists.txt
new file mode 100644
index 00000000000..ba682233381
--- /dev/null
+++ b/extern/rangetree/CMakeLists.txt
@@ -0,0 +1,31 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+	.
+)
+
+set(SRC
+	range_tree.hh
+	range_tree_c_api.h
+
+	range_tree_c_api.cc
+)
+
+blender_add_lib(extern_rangetree "${SRC}" "${INC}" "")
+
diff --git a/extern/rangetree/README.org b/extern/rangetree/README.org
new file mode 100644
index 00000000000..46a4cedaf8f
--- /dev/null
+++ b/extern/rangetree/README.org
@@ -0,0 +1,13 @@
+* Overview
+  Basic class for storing non-overlapping scalar ranges. Underlying
+  representation is a C++ STL set for fast lookups.
+
+* License
+  GPL version 2 or later (see COPYING)
+
+* Author Note
+  This implementation is intended for storing free unique IDs in a new
+  undo system for BMesh in Blender, but could be useful elsewhere.
+
+* Website
+  https://github.com/nicholasbishop/RangeTree
diff --git a/extern/rangetree/SConscript b/extern/rangetree/SConscript
new file mode 100644
index 00000000000..787decd599e
--- /dev/null
+++ b/extern/rangetree/SConscript
@@ -0,0 +1,9 @@
+2#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.cc')
+
+incs = '.'
+defs = ''
+
+env.BlenderLib ('extern_rangetree', sources, Split(incs), Split(defs), libtype=['extern'], priority=[100] )
diff --git a/extern/rangetree/range_tree.hh b/extern/rangetree/range_tree.hh
new file mode 100644
index 00000000000..2a47c5a1d93
--- /dev/null
+++ b/extern/rangetree/range_tree.hh
@@ -0,0 +1,228 @@
+/* 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.
+*/
+
+#include 
+#include 
+#include 
+#include 
+
+#ifndef RANGE_TREE_DEBUG_PRINT_FUNCTION
+#    define RANGE_TREE_DEBUG_PRINT_FUNCTION 0
+#endif
+
+template 
+struct RangeTree {
+	struct Range {
+		Range(T min_, T max_)
+			: min(min_), max(max_), single(min_ == max_) {
+			assert(min_ <= max_);
+		}
+
+		Range(T t)
+			: min(t), max(t), single(true)
+		{}
+
+		bool operator<(const Range& v) const {
+			return max < v.min;
+		}
+
+		const T min;
+		const T max;
+		const bool single;
+	};
+
+	typedef std::set Tree;
+	typedef typename Tree::iterator TreeIter;
+	typedef typename Tree::reverse_iterator TreeIterReverse;
+	typedef typename Tree::const_iterator TreeIterConst;
+
+	/* Initialize with a single range from 'min' to 'max', inclusive. */
+	RangeTree(T min, T max) {
+		tree.insert(Range(min, max));
+	}
+
+	/* Initialize with a single range from 0 to 'max', inclusive. */
+	RangeTree(T max) {
+		tree.insert(Range(0, max));
+	}
+
+	RangeTree(const RangeTree& src) {
+		tree = src.tree;
+	}
+
+	/* Remove 't' from the associated range in the tree. Precondition:
+	   a range including 't' must exist in the tree. */
+	void take(T t) {
+		#if RANGE_TREE_DEBUG_PRINT_FUNCTION
+		std::cout << __func__ << "(" << t << ")\n";
+		#endif
+
+		/* Find the range that includes 't' and its neighbors */
+		TreeIter iter = tree.find(Range(t));
+		assert(iter != tree.end());
+		Range cur = *iter;
+		TreeIter prev = iter;
+		TreeIter next = iter;
+		--prev;
+		++next;
+
+		/* Remove the original range (note that this does not
+		   invalidate the prev/next iterators) */
+		tree.erase(iter);
+
+		/* Construct two new ranges that together cover the original
+		   range, except for 't' */
+		if (t > cur.min)
+			tree.insert(Range(cur.min, t - 1));
+		if (t + 1 <= cur.max)
+			tree.insert(Range(t + 1, cur.max));
+	}
+
+	/* Take the first element out of the first range in the
+	   tree. Precondition: tree must not be empty. */
+	T take_any() {
+		#if RANGE_TREE_DEBUG_PRINT_FUNCTION
+		std::cout << __func__ << "()\n";
+		#endif
+
+		/* Find the first element */
+		TreeIter iter = tree.begin();
+		assert(iter != tree.end());
+		T first = iter->min;
+
+		/* Take the first element */
+		take(first);
+		return first;
+	}
+
+	/* Return 't' to the tree, either expanding/merging existing
+	   ranges or adding a range to cover it. Precondition: 't' cannot
+	   be in an existing range. */
+	void release(T t) {
+		#if RANGE_TREE_DEBUG_PRINT_FUNCTION
+		std::cout << __func__ << "(" << t << ")\n";
+		#endif
+
+		/* TODO: these cases should be simplified/unified */
+
+		TreeIter right = tree.upper_bound(t);
+		if (right != tree.end()) {
+			TreeIter left = right;
+			if (left != tree.begin())
+				--left;
+
+			if (left == right) {
+				/* 't' lies before any existing ranges */
+				if (t + 1 == left->min) {
+					/* 't' lies directly before the first range,
+					   resize and replace that range */
+					const Range r(t, left->max);
+					tree.erase(left);
+					tree.insert(r);
+				}
+				else {
+					/* There's a gap between 't' and the first range,
+					   add a new range */
+					tree.insert(Range(t));
+				}
+			}
+			else if ((left->max + 1 == t) &&
+				(t + 1 == right->min)) {
+				/* 't' fills a hole. Remove left and right, and insert a
+				   new range that covers both. */
+				const Range r(left->min, right->max);
+				tree.erase(left);
+				tree.erase(right);
+				tree.insert(r);
+			}
+			else if (left->max + 1 == t) {
+				/* 't' lies directly after 'left' range, resize and
+				   replace that range */
+				const Range r(left->min, t);
+				tree.erase(left);
+				tree.insert(r);
+			}
+			else if (t + 1 == right->min) {
+				/* 't' lies directly before 'right' range, resize and
+				   replace that range */
+				const Range r(t, right->max);
+				tree.erase(right);
+				tree.insert(r);
+			}
+			else {
+				/* There's a gap between 't' and both adjacent ranges,
+				   add a new range */
+				tree.insert(Range(t));
+			}
+		}
+		else {
+			/* 't' lies after any existing ranges */
+			right = tree.end();
+			right--;
+			if (right->max + 1 == t) {
+				/* 't' lies directly after last range, resize and
+				   replace that range */
+				const Range r(right->min, t);
+				tree.erase(right);
+				tree.insert(r);
+			}
+			else {
+				/* There's a gap between the last range and 't', add a
+				   new range */
+				tree.insert(Range(t));
+			}
+		}
+	}
+
+	bool has(T t) const {
+		TreeIterConst iter = tree.find(Range(t));
+		return (iter != tree.end()) && (t <= iter->max);
+	}
+
+	bool has_range(T min, T max) const {
+		TreeIterConst iter = tree.find(Range(min, max));
+		return (iter != tree.end()) && (min == iter->min && max == iter->max);
+	}
+
+	bool empty() const {
+		return tree.empty();
+	}
+
+	int size() const {
+		return tree.size();
+	}
+
+	void print() const {
+		std::cout << "RangeTree:\n";
+		for (TreeIterConst iter = tree.begin(); iter != tree.end(); ++iter) {
+			const Range& r = *iter;
+			if (r.single)
+				std::cout << "  [" << r.min << "]\n";
+			else
+				std::cout << "  [" << r.min << ", " << r.max << "]\n";
+		}
+		if (empty())
+			std::cout << "  ";
+		std::cout << "\n";
+	}
+
+	unsigned int allocation_lower_bound() const {
+		return tree.size() * sizeof(Range);
+	}
+
+private:
+	Tree tree;
+};
diff --git a/extern/rangetree/range_tree_c_api.cc b/extern/rangetree/range_tree_c_api.cc
new file mode 100644
index 00000000000..56f2d90d329
--- /dev/null
+++ b/extern/rangetree/range_tree_c_api.cc
@@ -0,0 +1,86 @@
+/* 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.
+*/
+
+#include "range_tree.hh"
+
+/* Give RangeTreeUInt a real type rather than the opaque struct type
+   defined for external use. */
+#define RANGE_TREE_C_API_INTERNAL
+typedef RangeTree RangeTreeUInt;
+
+#include "range_tree_c_api.h"
+
+RangeTreeUInt *range_tree_uint_alloc(unsigned min, unsigned max)
+{
+	return new RangeTreeUInt(min, max);
+}
+
+RangeTreeUInt *range_tree_uint_copy(RangeTreeUInt *src)
+{
+	return new RangeTreeUInt(*src);
+}
+
+void range_tree_uint_free(RangeTreeUInt *rt)
+{
+	delete rt;
+}
+
+void range_tree_uint_take(RangeTreeUInt *rt, unsigned v)
+{
+	rt->take(v);
+}
+
+unsigned range_tree_uint_take_any(RangeTreeUInt *rt)
+{
+	return rt->take_any();
+}
+
+void range_tree_uint_release(RangeTreeUInt *rt, unsigned v)
+{
+	rt->release(v);
+}
+
+int range_tree_uint_has(const RangeTreeUInt *rt, unsigned v)
+{
+	return rt->has(v);
+}
+
+int range_tree_uint_has_range(const RangeTreeUInt *rt,
+							  unsigned vmin,
+							  unsigned vmax)
+{
+	return rt->has_range(vmin, vmax);
+}
+
+int range_tree_uint_empty(const RangeTreeUInt *rt)
+{
+	return rt->empty();
+}
+
+unsigned range_tree_uint_size(const RangeTreeUInt *rt)
+{
+	return rt->size();
+}
+
+void range_tree_uint_print(const RangeTreeUInt *rt)
+{
+	rt->print();
+}
+
+unsigned int range_tree_uint_allocation_lower_bound(const RangeTreeUInt *rt)
+{
+	return rt->allocation_lower_bound();
+}
diff --git a/extern/rangetree/range_tree_c_api.h b/extern/rangetree/range_tree_c_api.h
new file mode 100644
index 00000000000..af6a7b161a8
--- /dev/null
+++ b/extern/rangetree/range_tree_c_api.h
@@ -0,0 +1,60 @@
+/* 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.
+*/
+
+#ifndef RANGE_TREE_C_API_H
+#define RANGE_TREE_C_API_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Simple C-accessible wrapper for RangeTree */
+
+#ifndef RANGE_TREE_C_API_INTERNAL
+typedef struct RangeTreeUInt RangeTreeUInt;
+#endif
+
+RangeTreeUInt *range_tree_uint_alloc(unsigned min, unsigned max);
+
+RangeTreeUInt *range_tree_uint_copy(RangeTreeUInt *src);
+
+void range_tree_uint_free(RangeTreeUInt *rt);
+
+void range_tree_uint_take(RangeTreeUInt *rt, unsigned v);
+
+unsigned range_tree_uint_take_any(RangeTreeUInt *rt);
+
+void range_tree_uint_release(RangeTreeUInt *rt, unsigned v);
+
+int range_tree_uint_has(const RangeTreeUInt *rt, unsigned v);
+
+int range_tree_uint_has_range(const RangeTreeUInt *rt,
+							  unsigned vmin,
+							  unsigned vmax);
+
+int range_tree_uint_empty(const RangeTreeUInt *rt);
+
+unsigned range_tree_uint_size(const RangeTreeUInt *rt);
+
+void range_tree_uint_print(const RangeTreeUInt *rt);
+
+unsigned int range_tree_uint_allocation_lower_bound(const RangeTreeUInt *rt);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DUALCON_H__ */
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(-)

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(+)

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(-)

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

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(-)

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

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(-)

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
---
 release/datafiles/blender_icons.svg               | 1202 +++++++++++----------
 release/datafiles/blender_icons16.png             |  Bin 230256 -> 230991 bytes
 release/datafiles/blender_icons32.png             |  Bin 575666 -> 576373 bytes
 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 +
 10 files changed, 697 insertions(+), 594 deletions(-)

diff --git a/release/datafiles/blender_icons.svg b/release/datafiles/blender_icons.svg
index 08a7c92935f..fcade5b38c5 100644
--- a/release/datafiles/blender_icons.svg
+++ b/release/datafiles/blender_icons.svg
@@ -14,9 +14,9 @@
    height="640"
    id="svg2"
    sodipodi:version="0.32"
-   inkscape:version="0.48.2 r9819"
+   inkscape:version="0.48.3.1 r9886"
    version="1.0"
-   sodipodi:docname="Blender ICONS - v.2.5.08.svg"
+   sodipodi:docname="blender_icons.svg"
    inkscape:output_extension="org.inkscape.output.svg.inkscape"
    style="display:inline;enable-background:new"
    inkscape:export-filename="/home/wolter/Documenten/Blender/icons/D:\Documents\Blender\icons\BF icons v.2.5.08a.png"
@@ -22237,16 +22237,16 @@
      objecttolerance="10000"
      inkscape:pageopacity="0.0"
      inkscape:pageshadow="2"
-     inkscape:zoom="1"
-     inkscape:cx="537.93701"
-     inkscape:cy="319"
+     inkscape:zoom="2"
+     inkscape:cx="199.42005"
+     inkscape:cy="320.97898"
      inkscape:document-units="px"
      inkscape:current-layer="layer3"
      showgrid="false"
-     inkscape:window-width="1618"
-     inkscape:window-height="1028"
-     inkscape:window-x="54"
-     inkscape:window-y="-8"
+     inkscape:window-width="2560"
+     inkscape:window-height="1571"
+     inkscape:window-x="0"
+     inkscape:window-y="1"
      inkscape:snap-nodes="false"
      inkscape:snap-bbox="true"
      showguides="true"
@@ -22335,7 +22335,7 @@
      inkscape:groupmode="layer"
      id="layer3"
      inkscape:label="bckgrnd"
-     style="display:inline">
+     style="display:none">
     
             
           
           
           
         
         
@@ -30190,7 +30190,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -30208,7 +30208,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -30242,7 +30242,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90"
@@ -30251,7 +30251,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -30265,7 +30265,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -30283,7 +30283,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -30296,7 +30296,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -30339,7 +30339,7 @@
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
            transform="matrix(1.0911926,0,0,1.176776,253.08415,-79.548088)"
-           d="M 72,14.5 C 72,15.328427 71.328427,16 70.5,16 69.671573,16 69,15.328427 69,14.5 69,13.671573 69.671573,13 70.5,13 c 0.828427,0 1.5,0.671573 1.5,1.5 z"
+           d="m 72,14.5 a 1.5,1.5 0 1 1 -3,0 1.5,1.5 0 1 1 3,0 z"
            sodipodi:ry="1.5"
            sodipodi:rx="1.5"
            sodipodi:cy="14.5"
@@ -30806,7 +30806,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -30831,7 +30831,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90" />
@@ -30840,7 +30840,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -30892,7 +30892,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -30909,7 +30909,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90"
@@ -30982,7 +30982,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90" />
@@ -30991,7 +30991,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -31011,7 +31011,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -31028,7 +31028,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90"
@@ -31099,7 +31099,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -31114,7 +31114,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -31131,7 +31131,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90"
@@ -31153,7 +31153,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90" />
@@ -31162,7 +31162,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -31233,7 +31233,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 141.08637,118 c 0,5.0181 -4.06811,9.08607 -9.08637,9.08607 -5.01826,0 -9.08637,-4.06797 -9.08637,-9.08607 0,-5.0181 4.06811,-9.08607 9.08637,-9.08607 5.01826,0 9.08637,4.06797 9.08637,9.08607 z"
+           d="m 141.08637,118 a 9.0863705,9.0860729 0 1 1 -18.17274,0 9.0863705,9.0860729 0 1 1 18.17274,0 z"
            sodipodi:ry="9.0860729"
            sodipodi:rx="9.0863705"
            sodipodi:cy="118"
@@ -31259,7 +31259,7 @@
            sodipodi:cy="118"
            sodipodi:rx="9.0863705"
            sodipodi:ry="9.0860729"
-           d="m 141.08637,118 c 0,5.0181 -4.06811,9.08607 -9.08637,9.08607 -5.01826,0 -9.08637,-4.06797 -9.08637,-9.08607 0,-5.0181 4.06811,-9.08607 9.08637,-9.08607 5.01826,0 9.08637,4.06797 9.08637,9.08607 z"
+           d="m 141.08637,118 a 9.0863705,9.0860729 0 1 1 -18.17274,0 9.0863705,9.0860729 0 1 1 18.17274,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -31506,7 +31506,7 @@
              sodipodi:cy="-222"
              sodipodi:rx="3.3084693"
              sodipodi:ry="1.2798798"
-             d="m 111.30847,-222 c 0,0.70686 -1.48125,1.27988 -3.30847,1.27988 -1.82722,0 -3.30847,-0.57302 -3.30847,-1.27988 0,-0.70686 1.48125,-1.27988 3.30847,-1.27988 1.82722,0 3.30847,0.57302 3.30847,1.27988 z"
+             d="m 111.30847,-222 a 3.3084693,1.2798798 0 1 1 -6.61694,0 3.3084693,1.2798798 0 1 1 6.61694,0 z"
              transform="matrix(1.0307577,0,0,0.9140456,39.651558,-39.251735)" />
           
           
           
@@ -32050,7 +32050,7 @@
                inkscape:export-xdpi="90"
                inkscape:export-ydpi="90">
               
+                 d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z" />
             
             
         
         
@@ -32451,7 +32451,7 @@
          inkscape:export-ydpi="90"
          inkscape:export-xdpi="90"
          inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
-         d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+         d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
          sodipodi:ry="8"
          sodipodi:rx="8"
          sodipodi:cy="118"
@@ -32562,7 +32562,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -32602,7 +32602,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90" />
@@ -32641,7 +32641,7 @@
            sodipodi:cy="119.5"
            sodipodi:rx="5.5"
            sodipodi:ry="5.5"
-           d="m 196,119.5 c 0,3.03757 -2.46243,5.5 -5.5,5.5 -3.03757,0 -5.5,-2.46243 -5.5,-5.5 0,-3.03757 2.46243,-5.5 5.5,-5.5 3.03757,0 5.5,2.46243 5.5,5.5 z"
+           d="m 196,119.5 a 5.5,5.5 0 1 1 -11,0 5.5,5.5 0 1 1 11,0 z"
            transform="matrix(0.61819,0,0,0.618186,73.23488,45.12681)" />
       
     
@@ -32660,7 +32660,7 @@
          id="g24576">
         
         
       
     
@@ -32964,7 +32964,7 @@
            sodipodi:cy="165"
            sodipodi:rx="1"
            sodipodi:ry="1"
-           d="m 148,165 c 0,0.55228 -0.44772,1 -1,1 -0.55228,0 -1,-0.44772 -1,-1 0,-0.55228 0.44772,-1 1,-1 0.55228,0 1,0.44772 1,1 z"
+           d="m 148,165 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
            transform="matrix(1.5,0,0,1.5,-73.5,-83.5)"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
            inkscape:export-xdpi="90"
@@ -32983,7 +32983,7 @@
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
            transform="matrix(1.5,0,0,1.5,-66.5,-83.5)"
-           d="m 148,165 c 0,0.55228 -0.44772,1 -1,1 -0.55228,0 -1,-0.44772 -1,-1 0,-0.55228 0.44772,-1 1,-1 0.55228,0 1,0.44772 1,1 z"
+           d="m 148,165 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
            sodipodi:ry="1"
            sodipodi:rx="1"
            sodipodi:cy="165"
@@ -33024,7 +33024,7 @@
            sodipodi:cy="78.5"
            sodipodi:rx="3.5"
            sodipodi:ry="3.5"
-           d="m 262,78.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+           d="m 262,78.5 a 3.5,3.5 0 1 1 -7,0 3.5,3.5 0 1 1 7,0 z"
            transform="matrix(-1.4308622,0,0,1.4308687,469.36987,363.18486)"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
            inkscape:export-xdpi="90"
@@ -33052,7 +33052,7 @@
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
            transform="matrix(-1.4308622,0,0,1.4308687,469.36987,363.18486)"
-           d="m 262,78.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+           d="m 262,78.5 a 3.5,3.5 0 1 1 -7,0 3.5,3.5 0 1 1 7,0 z"
            sodipodi:ry="3.5"
            sodipodi:rx="3.5"
            sodipodi:cy="78.5"
@@ -33078,13 +33078,13 @@
              sodipodi:cy="78.5"
              sodipodi:rx="3.5"
              sodipodi:ry="3.5"
-             d="m 262,78.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+             d="m 262,78.5 a 3.5,3.5 0 1 1 -7,0 3.5,3.5 0 1 1 7,0 z"
              transform="matrix(-1.14287,0,0,1.142863,463.9317,115.7853)" />
           
             
           
           
@@ -33853,7 +33853,7 @@
            sodipodi:cy="35.5"
            sodipodi:rx="3.5"
            sodipodi:ry="3.5"
-           d="m 334,35.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+           d="m 334,35.5 a 3.5,3.5 0 1 1 -7,0 3.5,3.5 0 1 1 7,0 z"
            transform="matrix(1.000048,0,0,0.999998,-0.01591645,12.000064)" />
         
       
     
@@ -33897,7 +33897,7 @@
            style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;display:inline" />
         
         
         
       
     
@@ -34302,7 +34302,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -34320,7 +34320,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90" />
@@ -34973,7 +34973,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -34999,7 +34999,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90" />
@@ -35134,7 +35134,7 @@
          sodipodi:cy="118"
          sodipodi:rx="8"
          sodipodi:ry="8"
-         d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+         d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
          inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
          inkscape:export-xdpi="90"
          inkscape:export-ydpi="90" />
@@ -35142,7 +35142,7 @@
          inkscape:export-ydpi="90"
          inkscape:export-xdpi="90"
          inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-         d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+         d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
          sodipodi:ry="8"
          sodipodi:rx="8"
          sodipodi:cy="118"
@@ -35161,7 +35161,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90"
@@ -35170,7 +35170,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -36541,7 +36541,7 @@
            sodipodi:cy="35.5"
            sodipodi:rx="2.7944512"
            sodipodi:ry="2.7944512"
-           d="m 333.29445,35.5 c 0,1.543333 -1.25112,2.794451 -2.79445,2.794451 -1.54333,0 -2.79445,-1.251118 -2.79445,-2.794451 0,-1.543333 1.25112,-2.794451 2.79445,-2.794451 1.54333,0 2.79445,1.251118 2.79445,2.794451 z"
+           d="m 333.29445,35.5 a 2.7944512,2.7944512 0 1 1 -5.5889,0 2.7944512,2.7944512 0 1 1 5.5889,0 z"
            transform="matrix(1.4256767,0,0,1.4314068,-320.1963,68.175135)" />
         
         
         
         
           
         
         
         
         
         
         
         
           
         
         
       
     
@@ -37248,7 +37248,7 @@
              sodipodi:cy="502"
              sodipodi:rx="2.5312502"
              sodipodi:ry="2.5"
-             d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+             d="m 80.53125,502 a 2.5312502,2.5 0 1 1 -5.0625,0 2.5312502,2.5 0 1 1 5.0625,0 z"
              transform="matrix(0.7834486,0,0,0.2000006,10.413535,395.5997)" />
           
           
           
           
           
           
           
           
           
           
           
           
         
         
+         d="m 446.5,108.5 a 3,3 0 1 1 -6,0 3,3 0 1 1 6,0 z" />
       
       
+         d="m 440.514,108.7895 a 3,3 0 1 1 2.1568,2.59363" />
       
+         d="m 446.5,108.5 a 3,3 0 1 1 -6,0 3,3 0 1 1 6,0 z" />
       
+         d="m 446.5,108.5 a 3,3 0 1 1 -6,0 3,3 0 1 1 6,0 z" />
       
       
       
+         d="m 446.5,108.5 a 3,3 0 1 1 -6,0 3,3 0 1 1 6,0 z" />
       
+         d="m 446.5,108.5 a 3,3 0 1 1 -6,0 3,3 0 1 1 6,0 z" />
       
       
       
@@ -37864,7 +37864,7 @@
          x="409"
          y="-41" />
       
+         d="m 446.5,108.5 a 3,3 0 1 1 -6,0 3,3 0 1 1 6,0 z" />
       
       
+         d="m 446.5,108.5 a 3,3 0 1 1 -6,0 3,3 0 1 1 6,0 z" />
       
+         d="m 446.5,108.5 a 3,3 0 1 1 -6,0 3,3 0 1 1 6,0 z" />
       
       
       
@@ -38043,7 +38043,7 @@
          x="409"
          y="-41" />
       
+         d="m 446.5,108.5 a 3,3 0 1 1 -6,0 3,3 0 1 1 6,0 z" />
       
           
         
         
           
         
         
           
         
         
           
           
           
           
           
         
       
@@ -40261,7 +40261,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -40278,7 +40278,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90"
@@ -40287,7 +40287,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -41218,7 +41218,7 @@
          inkscape:export-ydpi="90"
          transform="matrix(1.0004639,0,0,0.9963165,-69.122722,304.28985)">
         
       
           
         
@@ -42555,7 +42555,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -42583,7 +42583,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90"
@@ -42592,7 +42592,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -43071,11 +43071,11 @@
            sodipodi:cy="-23"
            sodipodi:rx="1"
            sodipodi:ry="1"
-           d="m 134,-23 c 0,0.552285 -0.44772,1 -1,1 -0.55228,0 -1,-0.447715 -1,-1 0,-0.552285 0.44772,-1 1,-1 0.55228,0 1,0.447715 1,1 z"
+           d="m 134,-23 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
            transform="translate(0.5,-0.46875)" />
         
         
         
         
           
@@ -43351,7 +43351,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90" />
@@ -43364,7 +43364,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90" />
@@ -44093,7 +44093,7 @@
       
       
         
         
@@ -46083,7 +46083,7 @@
            sodipodi:cy="502"
            sodipodi:rx="2.5312502"
            sodipodi:ry="2.5"
-           d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+           d="m 80.53125,502 a 2.5312502,2.5 0 1 1 -5.0625,0 2.5312502,2.5 0 1 1 5.0625,0 z"
            transform="matrix(0.9552133,0,0,0.9315985,-40.901258,-140.2522)" />
         
@@ -46739,9 +46739,9 @@
          sodipodi:cy="79.5"
          sodipodi:rx="3.5"
          sodipodi:ry="3.5"
-         d="m 211,79.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z" />
+         d="m 211,79.5 a 3.5,3.5 0 1 1 -7,0 3.5,3.5 0 1 1 7,0 z" />
       
@@ -47299,7 +47299,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -48171,13 +48171,13 @@
            sodipodi:cy="554"
            sodipodi:rx="4.5"
            sodipodi:ry="2.25"
-           d="m 57.5,554 c 0,1.24264 -2.014719,2.25 -4.5,2.25 -2.485281,0 -4.5,-1.00736 -4.5,-2.25 0,-1.24264 2.014719,-2.25 4.5,-2.25 2.485281,0 4.5,1.00736 4.5,2.25 z"
+           d="m 57.5,554 a 4.5,2.25 0 1 1 -9,0 4.5,2.25 0 1 1 9,0 z"
            transform="matrix(0.7630859,-0.2494396,0.2996015,0.9926766,-151.92281,17.77746)" />
         
               
             
             
             
         
         
         
+           d="m 434.99991,14.5 a 3.9999149,2.91429 0 1 1 -7.99982,0 3.9999149,2.91429 0 1 1 7.99982,0 z" />
         
+           d="m 65,135 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z" />
         
+           d="m 65,135 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z" />
       
     
     
         
@@ -49278,7 +49278,7 @@
          id="g28085">
         
       
       
       
           
           
             
           
           
@@ -49861,13 +49861,13 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90"
            transform="matrix(0.787566,0,0,0.779223,26.709197,21.3179)" />
         
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z" />
         
         
         
@@ -51526,7 +51526,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -51543,7 +51543,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90"
@@ -51557,7 +51557,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -51768,13 +51768,13 @@
          sodipodi:cy="78.5"
          sodipodi:rx="3.5"
          sodipodi:ry="3.5"
-         d="m 262,78.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+         d="m 262,78.5 a 3.5,3.5 0 1 1 -7,0 3.5,3.5 0 1 1 7,0 z"
          transform="matrix(-1.14287,0,0,1.142863,463.9317,115.80133)" />
       
         
       
       
             
             
           
           
+             d="m 65,135 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z" />
         
       
     
@@ -52079,7 +52079,7 @@
          sodipodi:cy="78.5"
          sodipodi:rx="3.5"
          sodipodi:ry="3.5"
-         d="m 262,78.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+         d="m 262,78.5 a 3.5,3.5 0 1 1 -7,0 3.5,3.5 0 1 1 7,0 z"
          transform="matrix(-1.5000024,0,0,1.4990511,528.75064,424.32781)"
          inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
          inkscape:export-xdpi="90"
@@ -52113,7 +52113,7 @@
            sodipodi:cy="78.5"
            sodipodi:rx="3.5"
            sodipodi:ry="3.5"
-           d="m 262,78.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+           d="m 262,78.5 a 3.5,3.5 0 1 1 -7,0 3.5,3.5 0 1 1 7,0 z"
            transform="matrix(-1.5714299,0,0,1.5714268,505.21462,331.643)"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
            inkscape:export-xdpi="90"
@@ -52152,13 +52152,13 @@
              sodipodi:cy="78.5"
              sodipodi:rx="3.5"
              sodipodi:ry="3.5"
-             d="m 262,78.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+             d="m 262,78.5 a 3.5,3.5 0 1 1 -7,0 3.5,3.5 0 1 1 7,0 z"
              transform="matrix(-1.14287,0,0,1.142863,463.9317,115.7853)" />
           
             
           
           
@@ -52353,7 +52353,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -52365,7 +52365,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -52409,7 +52409,7 @@
            sodipodi:cy="78.5"
            sodipodi:rx="3.5"
            sodipodi:ry="3.5"
-           d="m 262,78.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+           d="m 262,78.5 a 3.5,3.5 0 1 1 -7,0 3.5,3.5 0 1 1 7,0 z"
            transform="matrix(-1.5714299,0,0,1.5714268,505.21462,331.643)"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
            inkscape:export-xdpi="90"
@@ -52448,13 +52448,13 @@
              sodipodi:cy="78.5"
              sodipodi:rx="3.5"
              sodipodi:ry="3.5"
-             d="m 262,78.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+             d="m 262,78.5 a 3.5,3.5 0 1 1 -7,0 3.5,3.5 0 1 1 7,0 z"
              transform="matrix(-1.14287,0,0,1.142863,463.9317,115.7853)" />
           
             
           
           
           
             
         
@@ -52751,7 +52751,7 @@
            style="display:inline">
           
         
         
@@ -52999,7 +52999,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -53018,7 +53018,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -53036,7 +53036,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90" />
@@ -53705,7 +53705,7 @@
            id="g36930">
           
           
           
           
           
           
         
         
+             d="m 266.5,330.5 a 2,2 0 1 1 -4,0 2,2 0 1 1 4,0 z" />
         
         
         
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z" />
         
@@ -54769,7 +54769,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+             d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90"
@@ -54785,7 +54785,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+             d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -54803,7 +54803,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+             d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90"
@@ -54819,7 +54819,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+             d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -54837,7 +54837,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+             d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90"
@@ -54851,7 +54851,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+             d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -54866,7 +54866,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -54884,7 +54884,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -55007,7 +55007,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -55016,7 +55016,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -55033,7 +55033,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -55155,7 +55155,7 @@
            style="fill:#f9f9f9;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
         
         
         
         
         
@@ -55497,7 +55497,7 @@
          inkscape:export-ydpi="90"
          inkscape:export-xdpi="90"
          inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-         d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+         d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
          sodipodi:ry="8"
          sodipodi:rx="8"
          sodipodi:cy="118"
@@ -55592,7 +55592,7 @@
          sodipodi:cy="40.5"
          sodipodi:rx="6.5"
          sodipodi:ry="2.5"
-         d="m -213.5,40.5 c 0,1.380712 -2.91015,2.5 -6.5,2.5 -3.58985,0 -6.5,-1.119288 -6.5,-2.5 0,-1.380712 2.91015,-2.5 6.5,-2.5 3.58985,0 6.5,1.119288 6.5,2.5 z"
+         d="m -213.5,40.5 a 6.5,2.5 0 1 1 -13,0 6.5,2.5 0 1 1 13,0 z"
          transform="matrix(0.9999986,0,0,1.799999,-2.971883e-4,111.10004)" />
     
     
@@ -56010,7 +56010,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -56091,7 +56091,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -56108,7 +56108,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90"
@@ -56122,7 +56122,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -56130,7 +56130,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -56216,7 +56216,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90" />
@@ -56224,7 +56224,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -56803,7 +56803,7 @@
          inkscape:connector-curvature="0" />
       
@@ -57050,7 +57050,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -57058,7 +57058,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -57076,7 +57076,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -57089,7 +57089,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -57149,7 +57149,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -57167,7 +57167,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -57175,7 +57175,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -57188,7 +57188,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -57255,7 +57255,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -57263,7 +57263,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -57281,7 +57281,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -57294,7 +57294,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -57346,7 +57346,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90" />
@@ -57354,7 +57354,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -57372,7 +57372,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90" />
@@ -57385,7 +57385,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90" />
@@ -57402,7 +57402,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -57419,7 +57419,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90"
@@ -57433,7 +57433,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -57456,7 +57456,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -57464,7 +57464,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -57482,7 +57482,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -57495,7 +57495,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -57705,7 +57705,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -57713,7 +57713,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -57731,7 +57731,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -57779,7 +57779,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -57797,7 +57797,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -57805,7 +57805,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -57827,7 +57827,7 @@
            sodipodi:cy="292.5"
            sodipodi:rx="4"
            sodipodi:ry="4"
-           d="m 223.5,292.5 c 0,2.20914 -1.79086,4 -4,4 -2.20914,0 -4,-1.79086 -4,-4 0,-2.20914 1.79086,-4 4,-4 2.20914,0 4,1.79086 4,4 z"
+           d="m 223.5,292.5 a 4,4 0 1 1 -8,0 4,4 0 1 1 8,0 z"
            transform="translate(20,0)" />
         
         
         
@@ -57906,7 +57906,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -57964,7 +57964,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -57972,7 +57972,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -57990,7 +57990,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -58001,7 +58001,7 @@
          style="opacity:0.9;display:inline;enable-background:new">
         
         
         
       
     
@@ -58061,11 +58061,11 @@
              sodipodi:cy="192.5"
              sodipodi:rx="1.75"
              sodipodi:ry="1.75"
-             d="m 466.25,192.5 c 0,0.9665 -0.7835,1.75 -1.75,1.75 -0.9665,0 -1.75,-0.7835 -1.75,-1.75 0,-0.9665 0.7835,-1.75 1.75,-1.75 0.9665,0 1.75,0.7835 1.75,1.75 z"
+             d="m 466.25,192.5 a 1.75,1.75 0 1 1 -3.5,0 1.75,1.75 0 1 1 3.5,0 z"
              transform="matrix(1.7142856,0,0,1.7142871,-330.83199,-136.46043)" />
           
         
         
@@ -58136,7 +58136,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -58144,7 +58144,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -58184,7 +58184,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -58193,7 +58193,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -58205,7 +58205,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -58398,7 +58398,7 @@
            sodipodi:cy="14.5"
            sodipodi:rx="1.5"
            sodipodi:ry="1.5"
-           d="M 72,14.5 C 72,15.328427 71.328427,16 70.5,16 69.671573,16 69,15.328427 69,14.5 69,13.671573 69.671573,13 70.5,13 c 0.828427,0 1.5,0.671573 1.5,1.5 z"
+           d="m 72,14.5 a 1.5,1.5 0 1 1 -3,0 1.5,1.5 0 1 1 3,0 z"
            transform="matrix(1.3333333,0,0,1.3333343,3,147.66665)"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
            inkscape:export-xdpi="90"
@@ -58412,7 +58412,7 @@
            sodipodi:cy="14.5"
            sodipodi:rx="1.5"
            sodipodi:ry="1.5"
-           d="M 72,14.5 C 72,15.328427 71.328427,16 70.5,16 69.671573,16 69,15.328427 69,14.5 69,13.671573 69.671573,13 70.5,13 c 0.828427,0 1.5,0.671573 1.5,1.5 z"
+           d="m 72,14.5 a 1.5,1.5 0 1 1 -3,0 1.5,1.5 0 1 1 3,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -58505,7 +58505,7 @@
              sodipodi:end="6.2810509"
              sodipodi:start="0"
              transform="matrix(1.2491741,-1.2491602,0.7680871,0.768079,-75.108556,239.34027)"
-             d="m 182.21113,35 c 0,2.758732 -0.54224,4.995127 -1.21113,4.995127 -0.66889,0 -1.21113,-2.236395 -1.21113,-4.995127 0,-2.758732 0.54224,-4.995127 1.21113,-4.995127 0.66788,0 1.20971,2.229902 1.21113,4.984465"
+             d="m 182.21113,35 a 1.2111344,4.9951267 0 1 1 0,-0.01066"
              sodipodi:ry="4.9951267"
              sodipodi:rx="1.2111344"
              sodipodi:cy="35"
@@ -58521,7 +58521,7 @@
              sodipodi:cy="35"
              sodipodi:rx="1.1763829"
              sodipodi:ry="5.5293522"
-             d="m 182.17638,35 c 0,3.053777 -0.52668,5.529352 -1.17638,5.529352 -0.6497,0 -1.17638,-2.475575 -1.17638,-5.529352 0,-3.053777 0.52668,-5.529352 1.17638,-5.529352 0.6497,0 1.17638,2.475575 1.17638,5.529352 z"
+             d="m 182.17638,35 a 1.1763829,5.5293522 0 1 1 -2.35276,0 1.1763829,5.5293522 0 1 1 2.35276,0 z"
              transform="matrix(0.9589476,-0.9192618,0.5776079,0.5780619,-15.42366,185.77921)" />
           
             
             
           
         
@@ -58932,7 +58932,7 @@
            id="g35449">
           
           
           
           
           
         
         
@@ -59950,7 +59950,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -60109,7 +60109,7 @@
          sodipodi:cy="118"
          sodipodi:rx="8"
          sodipodi:ry="8"
-         d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+         d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
          inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
          inkscape:export-xdpi="90"
          inkscape:export-ydpi="90"
@@ -60122,7 +60122,7 @@
          sodipodi:cy="118"
          sodipodi:rx="8"
          sodipodi:ry="8"
-         d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+         d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
          inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
          inkscape:export-xdpi="90"
          inkscape:export-ydpi="90"
@@ -60170,7 +60170,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -60190,9 +60190,9 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z" />
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z" />
         
@@ -60242,7 +60242,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z" />
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z" />
       
     
     
         
         
@@ -60900,7 +60900,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -60950,7 +60950,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -60982,7 +60982,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90" />
@@ -61332,7 +61332,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -61352,7 +61352,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -61365,7 +61365,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -61379,7 +61379,7 @@
            id="g36537">
           
           
         
@@ -61773,7 +61773,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -61781,7 +61781,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -63691,7 +63691,7 @@
           
           
@@ -63729,7 +63729,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -63859,7 +63859,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -63876,14 +63876,14 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90"
            transform="matrix(-0.683022,-0.07745026,0.0778507,-0.683064,209.4726,314.325)" />
         
           
       
+         d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z" />
       
         
         
         
@@ -65294,7 +65294,7 @@
                inkscape:export-ydpi="90"
                inkscape:export-xdpi="90"
                inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-               d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+               d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
                sodipodi:ry="8"
                sodipodi:rx="8"
                sodipodi:cy="118"
@@ -65362,7 +65362,7 @@
                sodipodi:cy="118"
                sodipodi:rx="8"
                sodipodi:ry="8"
-               d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+               d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
                inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
                inkscape:export-xdpi="90"
                inkscape:export-ydpi="90" />
@@ -65378,7 +65378,7 @@
                inkscape:export-ydpi="90"
                inkscape:export-xdpi="90"
                inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-               d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+               d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
                sodipodi:ry="8"
                sodipodi:rx="8"
                sodipodi:cy="118"
@@ -66073,13 +66073,13 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90"
            transform="matrix(0.787566,0,0,0.779223,26.709197,21.3179)" />
         
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z" />
         
         
           
@@ -68115,13 +68115,13 @@
              sodipodi:cy="554"
              sodipodi:rx="4.5"
              sodipodi:ry="2.25"
-             d="m 57.5,554 c 0,1.24264 -2.014719,2.25 -4.5,2.25 -2.485281,0 -4.5,-1.00736 -4.5,-2.25 0,-1.24264 2.014719,-2.25 4.5,-2.25 2.485281,0 4.5,1.00736 4.5,2.25 z"
+             d="m 57.5,554 a 4.5,2.25 0 1 1 -9,0 4.5,2.25 0 1 1 9,0 z"
              transform="matrix(0.7630859,-0.2494396,0.2996015,0.9926766,-151.92281,17.77746)" />
           
@@ -68300,7 +68300,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -68334,7 +68334,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -68454,7 +68454,7 @@
            transform="matrix(0.5406242,0,0,0.5829534,814.13667,247.65542)">
           
           
           
           
+               d="m 923,342 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z" />
           
           
             
@@ -69643,7 +69643,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -69655,7 +69655,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -70879,7 +70879,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -70888,7 +70888,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -70907,7 +70907,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            transform="matrix(0.5705005,0,0,0.5705012,51.746079,156.18087)" />
       
       
         
@@ -71015,7 +71015,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -71023,7 +71023,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -71036,7 +71036,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -71257,7 +71257,7 @@
              sodipodi:end="1.5729572"
              sodipodi:start="0"
              transform="matrix(-2.421633,0,0,-2.417581,92.2682,-69.13182)"
-             d="m 54,-32.5 c 0,2.485281 -2.014719,4.5 -4.5,4.5 -0.0032,0 -0.0065,-4e-6 -0.0097,-1.1e-5"
+             d="m 54,-32.5 a 4.5,4.5 0 0 1 -4.509724,4.499989"
              sodipodi:ry="4.5"
              sodipodi:rx="4.5"
              sodipodi:cy="-32.5"
@@ -71276,7 +71276,7 @@
              sodipodi:cy="-32.5"
              sodipodi:rx="4.5"
              sodipodi:ry="4.5"
-             d="m 54,-32.5 c 0,2.485281 -2.014719,4.5 -4.5,4.5 -0.0032,0 -0.0065,-4e-6 -0.0097,-1.1e-5"
+             d="m 54,-32.5 a 4.5,4.5 0 0 1 -4.509724,4.499989"
              transform="matrix(-2.421633,0,0,-2.417581,92.2682,-69.13182)"
              sodipodi:start="0"
              sodipodi:end="1.5729572"
@@ -71293,7 +71293,7 @@
              sodipodi:end="1.5729572"
              sodipodi:start="0"
              transform="matrix(-2.421633,0,0,-2.417581,92.2682,-69.13182)"
-             d="m 54,-32.5 c 0,2.485281 -2.014719,4.5 -4.5,4.5 -0.0032,0 -0.0065,-4e-6 -0.0097,-1.1e-5"
+             d="m 54,-32.5 a 4.5,4.5 0 0 1 -4.509724,4.499989"
              sodipodi:ry="4.5"
              sodipodi:rx="4.5"
              sodipodi:cy="-32.5"
@@ -71312,7 +71312,7 @@
              sodipodi:cy="-32.5"
              sodipodi:rx="4.5"
              sodipodi:ry="4.5"
-             d="m 54,-32.5 c 0,2.485281 -2.014719,4.5 -4.5,4.5 -0.0032,0 -0.0065,-4e-6 -0.0097,-1.1e-5"
+             d="m 54,-32.5 a 4.5,4.5 0 0 1 -4.509724,4.499989"
              transform="matrix(-2.587958,0,0,-2.597682,100.48861,-75.018268)"
              sodipodi:start="0"
              sodipodi:end="1.5729572"
@@ -71885,7 +71885,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+             d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -71899,7 +71899,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -71989,7 +71989,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -72025,7 +72025,7 @@
                inkscape:export-ydpi="90"
                inkscape:export-xdpi="90"
                inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-               d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+               d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
                sodipodi:ry="8"
                sodipodi:rx="8"
                sodipodi:cy="118"
@@ -72051,7 +72051,7 @@
                sodipodi:cy="118"
                sodipodi:rx="8"
                sodipodi:ry="8"
-               d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+               d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
                inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
                inkscape:export-xdpi="90"
                inkscape:export-ydpi="90" />
@@ -72231,7 +72231,7 @@
         
         
           
       
       
             
           
         
         
         
           
         
         
         
@@ -73243,7 +73243,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -73257,7 +73257,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -73415,7 +73415,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -73423,7 +73423,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -73437,7 +73437,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -73571,7 +73571,7 @@
            sodipodi:cy="420.25"
            sodipodi:rx="2.5"
            sodipodi:ry="1.75"
-           d="m 751.5,420.25 c 0,0.9665 -1.11929,1.75 -2.5,1.75 -1.38071,0 -2.5,-0.7835 -2.5,-1.75 0,-0.9665 1.11929,-1.75 2.5,-1.75 1.38071,0 2.5,0.7835 2.5,1.75 z"
+           d="m 751.5,420.25 a 2.5,1.75 0 1 1 -5,0 2.5,1.75 0 1 1 5,0 z"
            transform="matrix(1,0,0,0.8571429,-212,-302.2143)" />
         
         
@@ -74347,7 +74347,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -74366,7 +74366,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+             d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -74384,7 +74384,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+             d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90"
@@ -74400,7 +74400,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+             d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -74418,7 +74418,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+             d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90"
@@ -74433,7 +74433,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+             d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -74452,7 +74452,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+             d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90"
@@ -74469,7 +74469,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -74477,7 +74477,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -74507,7 +74507,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -74526,7 +74526,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+             d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -74544,7 +74544,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+             d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90"
@@ -74560,7 +74560,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+             d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -74578,7 +74578,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+             d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90"
@@ -74593,7 +74593,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+             d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -74612,7 +74612,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+             d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90"
@@ -74629,7 +74629,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -74637,7 +74637,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -74667,7 +74667,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -74686,7 +74686,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+             d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -74704,7 +74704,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+             d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90"
@@ -74720,7 +74720,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+             d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -74738,7 +74738,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+             d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90"
@@ -74753,7 +74753,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-             d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+             d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 z"
              sodipodi:ry="8"
              sodipodi:rx="8"
              sodipodi:cy="118"
@@ -74772,7 +74772,7 @@
              sodipodi:cy="118"
              sodipodi:rx="8"
              sodipodi:ry="8"
-             d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+             d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 z"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
              inkscape:export-xdpi="90"
              inkscape:export-ydpi="90"
@@ -74789,7 +74789,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -74797,7 +74797,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -74825,7 +74825,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -74833,7 +74833,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -74851,7 +74851,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -74864,7 +74864,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -74872,7 +74872,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -75991,7 +75991,7 @@
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
              transform="matrix(1.3333333,0,0,1.3333343,3,147.66665)"
-             d="M 72,14.5 C 72,15.328427 71.328427,16 70.5,16 69.671573,16 69,15.328427 69,14.5 69,13.671573 69.671573,13 70.5,13 c 0.828427,0 1.5,0.671573 1.5,1.5 z"
+             d="m 72,14.5 a 1.5,1.5 0 1 1 -3,0 1.5,1.5 0 1 1 3,0 z"
              sodipodi:ry="1.5"
              sodipodi:rx="1.5"
              sodipodi:cy="14.5"
@@ -76003,7 +76003,7 @@
              inkscape:export-ydpi="90"
              inkscape:export-xdpi="90"
              inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
-             d="M 72,14.5 C 72,15.328427 71.328427,16 70.5,16 69.671573,16 69,15.328427 69,14.5 69,13.671573 69.671573,13 70.5,13 c 0.828427,0 1.5,0.671573 1.5,1.5 z"
+             d="m 72,14.5 a 1.5,1.5 0 1 1 -3,0 1.5,1.5 0 1 1 3,0 z"
              sodipodi:ry="1.5"
              sodipodi:rx="1.5"
              sodipodi:cy="14.5"
@@ -76190,7 +76190,7 @@
            sodipodi:cy="14.5"
            sodipodi:rx="1.5"
            sodipodi:ry="1.5"
-           d="M 72,14.5 C 72,15.328427 71.328427,16 70.5,16 69.671573,16 69,15.328427 69,14.5 69,13.671573 69.671573,13 70.5,13 c 0.828427,0 1.5,0.671573 1.5,1.5 z"
+           d="m 72,14.5 a 1.5,1.5 0 1 1 -3,0 1.5,1.5 0 1 1 3,0 z"
            transform="matrix(1.3333333,0,0,1.3333343,170.99998,105.66665)"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
            inkscape:export-xdpi="90"
@@ -76204,7 +76204,7 @@
            sodipodi:cy="14.5"
            sodipodi:rx="1.5"
            sodipodi:ry="1.5"
-           d="M 72,14.5 C 72,15.328427 71.328427,16 70.5,16 69.671573,16 69,15.328427 69,14.5 69,13.671573 69.671573,13 70.5,13 c 0.828427,0 1.5,0.671573 1.5,1.5 z"
+           d="m 72,14.5 a 1.5,1.5 0 1 1 -3,0 1.5,1.5 0 1 1 3,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -76381,7 +76381,7 @@
            sodipodi:cy="14.5"
            sodipodi:rx="1.5"
            sodipodi:ry="1.5"
-           d="M 72,14.5 C 72,15.328427 71.328427,16 70.5,16 69.671573,16 69,15.328427 69,14.5 69,13.671573 69.671573,13 70.5,13 c 0.828427,0 1.5,0.671573 1.5,1.5 z"
+           d="m 72,14.5 a 1.5,1.5 0 1 1 -3,0 1.5,1.5 0 1 1 3,0 z"
            transform="matrix(1.3333333,0,0,1.3333343,209.98999,105.66665)"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
            inkscape:export-xdpi="90"
@@ -76395,7 +76395,7 @@
            sodipodi:cy="14.5"
            sodipodi:rx="1.5"
            sodipodi:ry="1.5"
-           d="M 72,14.5 C 72,15.328427 71.328427,16 70.5,16 69.671573,16 69,15.328427 69,14.5 69,13.671573 69.671573,13 70.5,13 c 0.828427,0 1.5,0.671573 1.5,1.5 z"
+           d="m 72,14.5 a 1.5,1.5 0 1 1 -3,0 1.5,1.5 0 1 1 3,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -78022,7 +78022,7 @@
          height="16"
          width="16"
          id="rect22783-6-9"
-         style="fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:6;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;opacity:0" />
+         style="opacity:0;fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:6;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
       
@@ -78153,7 +78153,7 @@
          height="16"
          width="16"
          id="rect22783-6"
-         style="fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:6;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;opacity:0" />
+         style="opacity:0;fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:6;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
       
         
         
+           style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:url(#linearGradient30129);fill-opacity:1;stroke:none;stroke-width:2.5999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
+           d="m 48.25,351.96875 a 1.30013,1.30013 0 0 0 -1.03125,1.0625 c -0.560356,3.27054 0.822741,6.58876 3.4375,8.5625 a 1.3062537,1.3062537 0 0 0 1.5625,-0.0312 A 0.50389111,0.50389111 0 0 1 51.9375,361.5 c -3.258538,-1.90713 -4.860221,-5.92414 -3.625,-9.53125 a 1.30013,1.30013 0 0 0 -0.0625,0 z m 1.03125,0.21875 c -1.14015,3.1617 0.271743,6.74928 3.15625,8.4375 a 0.50389111,0.50389111 0 0 1 0.25,0.3125 1.3062537,1.3062537 0 0 0 -0.46875,-1.4375 c -1.845415,-1.393 -2.825384,-3.76735 -2.4375,-6.03125 a 1.30013,1.30013 0 0 0 -0.5,-1.28125 z"
+           id="path30105"
+           inkscape:connector-curvature="0" />
         
       
     
+    
   
   
@@ -78312,7 +78334,7 @@
            sodipodi:cy="118"
            sodipodi:rx="8"
            sodipodi:ry="8"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
            inkscape:export-xdpi="90"
            inkscape:export-ydpi="90" />
@@ -78320,7 +78342,7 @@
            inkscape:export-ydpi="90"
            inkscape:export-xdpi="90"
            inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
-           d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+           d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
            sodipodi:ry="8"
            sodipodi:rx="8"
            sodipodi:cy="118"
@@ -78564,7 +78586,7 @@
          id="path32864"
          inkscape:connector-curvature="0" />
       
       
       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

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

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(-)

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(+)

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(-)

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(+)

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(-)

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(-)

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(-)

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
---
 .../scripts/startup/bl_ui/space_view3d_toolbar.py  | 30 ++++++++++++++++++++++
 source/blender/editors/sculpt_paint/paint_ops.c    | 12 +++++++++
 2 files changed, 42 insertions(+)

diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index fb5e4a56aa1..0e1f5d8dff2 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -854,6 +854,36 @@ class VIEW3D_PT_tools_brush_curve(Panel, View3DPaintPanel):
         row.operator("brush.curve_preset", icon='NOCURVE', text="").shape = 'MAX'
 
 
+class VIEW3D_PT_sculpt_topology(Panel, View3DPaintPanel):
+    bl_label = "Topology"
+    bl_options = {'DEFAULT_CLOSED'}
+
+    @classmethod
+    def poll(cls, context):
+        return (context.sculpt_object and context.tool_settings.sculpt)
+
+    def draw(self, context):
+        layout = self.layout
+
+        toolsettings = context.tool_settings
+        sculpt = toolsettings.sculpt
+
+        if context.sculpt_object.use_dynamic_topology_sculpting:
+            layout.operator("sculpt.dynamic_topology_toggle", icon='X', text="Disable Dynamic")
+        else:
+            layout.operator("sculpt.dynamic_topology_toggle", icon='SCULPT_DYNTOPO', text="Enable Dynamic")
+
+        col = layout.column()
+        col.active = context.sculpt_object.use_dynamic_topology_sculpting
+        col.prop(sculpt, "detail_size")
+        col.prop(sculpt, "use_smooth_shading")
+        col.prop(sculpt, "use_edge_collapse")
+        col.operator("sculpt.optimize")
+        col.separator()
+        col.prop(sculpt, "symmetrize_direction")
+        col.operator("sculpt.symmetrize")
+
+
 class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel):
     bl_label = "Options"
     bl_options = {'DEFAULT_CLOSED'}
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(-)

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...

---
 intern/cycles/blender/addon/properties.py          | 59 +++++++++++-----------
 .../modules/bl_i18n_utils/spell_check_utils.py     |  1 +
 source/blender/makesrna/intern/rna_dynamicpaint.c  |  2 +-
 3 files changed, 31 insertions(+), 31 deletions(-)

diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index 35ea8501eb7..abc251dc120 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -63,37 +63,37 @@ enum_panorama_types = (
     ('FISHEYE_EQUISOLID', "Fisheye Equisolid",
                           "Similar to most fisheye modern lens, takes sensor dimensions into consideration"),
     )
-    
+
 enum_curve_presets = (
     ('CUSTOM', "Custom", "Set general parameters"),
     ('TANGENT_SHADING', "Tangent Normal", "Use planar geometry and tangent normals"),
     ('TRUE_NORMAL', "True Normal", "Use true normals (good for thin strands)"),
     ('ACCURATE_PRESET', "Accurate", "Use best settings (suitable for glass materials)"),
     )
-    
+
 enum_curve_primitives = (
-    ('TRIANGLES', "Triangles", "create triangle geometry around strands"),
-    ('LINE_SEGMENTS', "Line Segments", "use line segment primitives"),
-    ('CURVE_SEGMENTS', "?Curve Segments?", "use curve segment primitives (not implemented)"),
+    ('TRIANGLES', "Triangles", "Create triangle geometry around strands"),
+    ('LINE_SEGMENTS', "Line Segments", "Use line segment primitives"),
+    ('CURVE_SEGMENTS', "?Curve Segments?", "Use curve segment primitives (not implemented)"),
     )
-        
+
 enum_triangle_curves = (
-	('CAMERA', "Planes", "create individual triangles forming planes that face camera"),
-    ('RIBBONS', "Ribbons", "create individual triangles forming ribbon"),
-    ('TESSELATED', "Tesselated", "create mesh surrounding each strand"),
+    ('CAMERA', "Planes", "Create individual triangles forming planes that face camera"),
+    ('RIBBONS', "Ribbons", "Create individual triangles forming ribbon"),
+    ('TESSELLATED', "Tessellated", "Create mesh surrounding each strand"),
     )
-    
+
 enum_line_curves = (
-    ('ACCURATE', "Accurate", "always take into consideration strand width for intersections"),
-    ('QT_CORRECTED', "corrected", "ignores width for initial intersection and corrects later"),
-    ('ENDCORRECTED', "correct found", "ignores width for all intersections and only corrects closest"),
-    ('QT_UNCORRECTED', "uncorrected", "calculates intersection without considering width"),
+    ('ACCURATE', "Accurate", "Always take into consideration strand width for intersections"),
+    ('QT_CORRECTED', "Corrected", "Ignore width for initial intersection and correct later"),
+    ('ENDCORRECTED', "Correct found", "Ignore width for all intersections and only correct closest"),
+    ('QT_UNCORRECTED', "Uncorrected", "Calculate intersections without considering width"),
     )
-    
+
 enum_curves_interpolation = (
-    ('LINEAR', "Linear interpolation", "uses Linear interpolation between segments"),
-    ('CARDINAL', "Cardinal interpolation", "uses CARDINAL interpolation between segments"),
-    ('BSPLINE', "b-spline interpolation", "uses b-spline interpolation between segments"),
+    ('LINEAR', "Linear interpolation", "Use Linear interpolation between segments"),
+    ('CARDINAL', "Cardinal interpolation", "Use cardinal interpolation between segments"),
+    ('BSPLINE', "B-spline interpolation", "Use b-spline interpolation between segments"),
     )
 
 class CyclesRenderSettings(bpy.types.PropertyGroup):
@@ -645,32 +645,31 @@ class CyclesCurveRenderSettings(bpy.types.PropertyGroup):
                 )
         cls.use_backfacing = BoolProperty(
                 name="Check back-faces",
-                description="Tests back-faces of strands",
+                description="Test back-faces of strands",
                 default=False,
                 )
         cls.use_encasing = BoolProperty(
                 name="Exclude encasing",
-                description="Ignores strands encasing a ray's initial location",
+                description="Ignore strands encasing a ray's initial location",
                 default=True,
                 )
         cls.use_tangent_normal_geometry = BoolProperty(
                 name="Tangent normal geometry",
-                description="Uses the tangent normal for actual normal",
+                description="Use the tangent normal for actual normal",
                 default=False,
                 )
         cls.use_tangent_normal = BoolProperty(
                 name="Tangent normal default",
-                description="Uses the tangent normal for all normals",
+                description="Use the tangent normal for all normals",
                 default=False,
                 )
         cls.use_tangent_normal_correction = BoolProperty(
-                name="strand slope correction",
-                description="Corrects the tangent normal for the strands slope",
+                name="Strand slope correction",
+                description="Correct the tangent normal for the strand's slope",
                 default=False,
                 )
         cls.use_cache = BoolProperty(
                 name="Export Cached data",
-                description="Export cached data with child strands (uses 'draw step' for subdivisions)",
                 default=True,
                 )
         cls.use_parents = BoolProperty(
@@ -685,17 +684,17 @@ class CyclesCurveRenderSettings(bpy.types.PropertyGroup):
                 )
         cls.use_joined = BoolProperty(
                 name="Join",
-                description="Fills gaps between segments (requires more memory)",
+                description="Fill gaps between segments (requires more memory)",
                 default=False,
                 )
         cls.use_curves = BoolProperty(
                 name="Use Cycles Hair Rendering",
-                description="Activate cycles hair rendering for particle system",
+                description="Activate Cycles hair rendering for particle system",
                 default=True,
                 )        
         cls.segments = IntProperty(
                 name="Segments",
-                description="Number of segments between path keys (Note that this combines with the `draw step' value)",
+                description="Number of segments between path keys (note that this combines with the 'draw step' value)",
                 min=1, max=64,
                 default=1,
                 )
@@ -750,9 +749,9 @@ class CyclesCurveSettings(bpy.types.PropertyGroup):
                 )
         cls.use_closetip = BoolProperty(
                 name="Close tip",
-                description="Sets tip radius to zero",
+                description="Set tip radius to zero",
                 default=True,
-                )                
+                )
 
     @classmethod
     def unregister(cls):
diff --git a/release/scripts/modules/bl_i18n_utils/spell_check_utils.py b/release/scripts/modules/bl_i18n_utils/spell_check_utils.py
index 591b92dba42..3fd039c7436 100644
--- a/release/scripts/modules/bl_i18n_utils/spell_check_utils.py
+++ b/release/scripts/modules/bl_i18n_utils/spell_check_utils.py
@@ -381,6 +381,7 @@ dict_uimsgs = {
     "texface",
     "timeline", "timelines",
     "tosphere",
+    "uilist",
     "vcol", "vcols",
     "vgroup", "vgroups",
     "vinterlace",
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(-)

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(-)

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.

---
 build_files/cmake/cmake_consistency_check.py   | 4 ++--
 build_files/cmake/project_info.py              | 2 +-
 build_files/cmake/project_source_info.py       | 2 +-
 source/blender/blenkernel/intern/pbvh_bmesh.c  | 3 ---
 source/blender/blenkernel/intern/pbvh_intern.h | 2 +-
 source/tests/check_deprecated.py               | 4 ++--
 6 files changed, 7 insertions(+), 10 deletions(-)

diff --git a/build_files/cmake/cmake_consistency_check.py b/build_files/cmake/cmake_consistency_check.py
index b13b0ddb424..665bc600efa 100755
--- a/build_files/cmake/cmake_consistency_check.py
+++ b/build_files/cmake/cmake_consistency_check.py
@@ -75,12 +75,12 @@ def is_cmake(filename):
 
 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):
diff --git a/build_files/cmake/project_info.py b/build_files/cmake/project_info.py
index 34f378a58dd..495ca71263e 100755
--- a/build_files/cmake/project_info.py
+++ b/build_files/cmake/project_info.py
@@ -97,7 +97,7 @@ def is_cmake(filename):
 
 def is_c_header(filename):
     ext = splitext(filename)[1]
-    return (ext in (".h", ".hpp", ".hxx"))
+    return (ext in {".h", ".hpp", ".hxx", ".hh"})
 
 
 def is_py(filename):
diff --git a/build_files/cmake/project_source_info.py b/build_files/cmake/project_source_info.py
index 10bc36ba1a8..69d09b05ac7 100644
--- a/build_files/cmake/project_source_info.py
+++ b/build_files/cmake/project_source_info.py
@@ -43,7 +43,7 @@ SOURCE_DIR = abspath(SOURCE_DIR)
 
 def is_c_header(filename):
     ext = os.path.splitext(filename)[1]
-    return (ext in (".h", ".hpp", ".hxx"))
+    return (ext in {".h", ".hpp", ".hxx", ".hh"})
 
 
 def is_c(filename):
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 c0a697807a9b95e52f47666fcbac76405ed03a65 Mon Sep 17 00:00:00 2001
From: Bastien Montagne 
Date: Mon, 31 Dec 2012 12:12:50 +0000
Subject: Add try/catch around i18n locale setter code, just in case...

---
 intern/locale/boost_locale_wrapper.cpp | 59 ++++++++++++++++++----------------
 1 file changed, 32 insertions(+), 27 deletions(-)

diff --git a/intern/locale/boost_locale_wrapper.cpp b/intern/locale/boost_locale_wrapper.cpp
index 939c66bad13..80e75298d70 100644
--- a/intern/locale/boost_locale_wrapper.cpp
+++ b/intern/locale/boost_locale_wrapper.cpp
@@ -55,44 +55,49 @@ void bl_locale_set(const char *locale)
 	// Specify location of dictionaries.
 	gen.add_messages_path(messages_path);
 	gen.add_messages_domain(default_domain);
-	//gen.set_default_messages_domain(default_domain);	
+	//gen.set_default_messages_domain(default_domain);
 
-	if (locale && locale[0]) {
-		std::locale::global(gen(locale));
-	}
-	else {
-#if defined (__APPLE__)
-		// workaround to get osx system locale from user defaults
-		FILE* fp;
-		std::string locale_osx = "";
-		char result[16];
-		int result_len = 0;
+	try {
+		if (locale && locale[0]) {
+			std::locale::global(gen(locale));
+		}
+		else {
+#ifdef __APPLE__
+			// workaround to get osx system locale from user defaults
+			FILE *fp;
+			std::string locale_osx = "";
+			char result[16];
+			int result_len = 0;
 
-		fp = popen("defaults read .GlobalPreferences AppleLocale", "r");
+			fp = popen("defaults read .GlobalPreferences AppleLocale", "r");
 
-		if(fp) {
-			result_len = fread(result, 1, sizeof(result) - 1, fp);
+			if (fp) {
+				result_len = fread(result, 1, sizeof(result) - 1, fp);
 
-			if(result_len > 0) {
-				result[result_len-1] = '\0'; // \0 terminate and remove \n
-				locale_osx = std::string(result) + std::string(".UTF-8");
-			}
+				if (result_len > 0) {
+					result[result_len - 1] = '\0'; // \0 terminate and remove \n
+					locale_osx = std::string(result) + std::string(".UTF-8");
+				}
 
-			pclose(fp);
-		}
+				pclose(fp);
+			}
 
-		if(locale_osx == "")
-			fprintf(stderr, "Locale set: failed to read AppleLocale read from defaults\n");
+			if (locale_osx == "")
+				fprintf(stderr, "Locale set: failed to read AppleLocale read from defaults\n");
 
-		std::locale::global(gen(locale_osx.c_str()));
+			std::locale::global(gen(locale_osx.c_str()));
 #else
-		std::locale::global(gen(""));
+			std::locale::global(gen(""));
 #endif
+		}
+		// Note: boost always uses "C" LC_NUMERIC by default!
+	}
+	catch(std::exception const &e) {
+		std::cout << "bl_locale_set(" << locale << "): " << e.what() << " \n";
 	}
-	// Note: boost always uses "C" LC_NUMERIC by default!
 }
 
-const char* bl_locale_pgettext(const char *msgctxt, const char *msgid)
+const char *bl_locale_pgettext(const char *msgctxt, const char *msgid)
 {
 	// Note: We cannot use short stuff like boost::locale::gettext, because those return
 	//       std::basic_string objects, which c_ptr()-returned char* is no more valid
@@ -107,7 +112,7 @@ const char* bl_locale_pgettext(const char *msgctxt, const char *msgid)
 		return msgid;
 	}
 	catch(std::exception const &e) {
-//		std::cout << "boost_locale_pgettext: " << e.what() << " \n";
+//		std::cout << "bl_locale_pgettext(" << msgctxt << ", " << msgid << "): " << e.what() << " \n";
 		return msgid;
 	}
 }
-- 
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(-)

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(-)

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.
---
 intern/cycles/kernel/kernel_shader.h       | 5 +++--
 source/blender/makesrna/intern/rna_scene.c | 5 ++---
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index 36cd21c1b48..652efa18b93 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -60,6 +60,8 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
 	sd->object = (isect->object == ~0)? kernel_tex_fetch(__prim_object, isect->prim): isect->object;
 #endif
 
+	sd->flag = kernel_tex_fetch(__object_flag, sd->object);
+
 	/* matrices and time */
 #ifdef __OBJECT_MOTION__
 	shader_setup_object_transforms(kg, sd, ray->time);
@@ -121,8 +123,7 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
 
 	sd->I = -ray->D;
 
-	sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2);
-	sd->flag |= kernel_tex_fetch(__object_flag, sd->object);
+	sd->flag |= kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2);
 
 #ifdef __INSTANCING__
 	if(isect->object != ~0) {
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.
---
 intern/cycles/blender/addon/properties.py          |   2 +-
 release/scripts/startup/bl_ui/properties_scene.py  |   1 -
 .../scripts/startup/bl_ui/properties_texture.py    |   1 -
 release/scripts/startup/bl_ui/space_sequencer.py   |   2 +-
 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 +-
 48 files changed, 797 insertions(+), 498 deletions(-)

diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index abc251dc120..2bc4afe969e 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -269,7 +269,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
                 )
         cls.film_transparent = BoolProperty(
                 name="Transparent",
-                description="World background is transparent",
+                description="World background is transparent with premultiplied alpha",
                 default=False,
                 )
 
diff --git a/release/scripts/startup/bl_ui/properties_scene.py b/release/scripts/startup/bl_ui/properties_scene.py
index 3230fb7392b..66a16daa22f 100644
--- a/release/scripts/startup/bl_ui/properties_scene.py
+++ b/release/scripts/startup/bl_ui/properties_scene.py
@@ -263,7 +263,6 @@ class SCENE_PT_color_management(Panel):
         col.separator()
         col.label(text="Render:")
         col.template_colormanaged_view_settings(scene, "view_settings")
-        col.prop(rd, "use_color_unpremultiply")
 
         col = layout.column()
         col.separator()
diff --git a/release/scripts/startup/bl_ui/properties_texture.py b/release/scripts/startup/bl_ui/properties_texture.py
index cb7cc1d42d2..eddb542ccc3 100644
--- a/release/scripts/startup/bl_ui/properties_texture.py
+++ b/release/scripts/startup/bl_ui/properties_texture.py
@@ -442,7 +442,6 @@ class TEXTURE_PT_image_sampling(TextureTypePanel, Panel):
 
         col = split.column()
         col.label(text="Alpha:")
-        col.prop(tex, "use_alpha", text="Use")
         col.prop(tex, "use_calculate_alpha", text="Calculate")
         col.prop(tex, "invert_alpha", text="Invert")
         col.separator()
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index 5b7a3a82aae..d6f8de93c0f 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -602,6 +602,7 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, Panel):
                 split.prop(elem, "filename", text="")  # strip.elements[0] could be a fallback
 
             layout.prop(strip.colorspace_settings, "name")
+            layout.prop(strip, "alpha_mode")
 
             layout.operator("sequencer.change_path")
 
@@ -797,7 +798,6 @@ class SEQUENCER_PT_filter(SequencerButtonsPanel, Panel):
         col.label(text="Colors:")
         col.prop(strip, "color_saturation", text="Saturation")
         col.prop(strip, "color_multiply", text="Multiply")
-        col.prop(strip, "use_premultiply")
         col.prop(strip, "use_float")
 
 
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(-)

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(+)

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

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!).

---
 release/scripts/startup/bl_ui/properties_data_camera.py |  2 +-
 source/blender/makesrna/intern/rna_camera.c             | 16 ++++++++--------
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/release/scripts/startup/bl_ui/properties_data_camera.py b/release/scripts/startup/bl_ui/properties_data_camera.py
index 25cecc90c70..c74560e14ac 100644
--- a/release/scripts/startup/bl_ui/properties_data_camera.py
+++ b/release/scripts/startup/bl_ui/properties_data_camera.py
@@ -80,7 +80,7 @@ class DATA_PT_lens(CameraButtonsPanel, Panel):
             row = col.row()
             if cam.lens_unit == 'MILLIMETERS':
                 row.prop(cam, "lens")
-            elif cam.lens_unit == 'DEGREES':
+            elif cam.lens_unit == 'FOV':
                 row.prop(cam, "angle")
             row.prop(cam, "lens_unit", text="")
 
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(-)

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(-)

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)
---
 release/scripts/startup/bl_ui/space_text.py        |   1 +
 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 +
 4 files changed, 298 insertions(+), 86 deletions(-)

diff --git a/release/scripts/startup/bl_ui/space_text.py b/release/scripts/startup/bl_ui/space_text.py
index 5b7d6e69f4b..960a945f1c6 100644
--- a/release/scripts/startup/bl_ui/space_text.py
+++ b/release/scripts/startup/bl_ui/space_text.py
@@ -301,6 +301,7 @@ class TEXT_MT_edit(Menu):
 
         layout.operator("text.jump")
         layout.operator("text.properties", text="Find...")
+        layout.operator("text.autocomplete")
 
         layout.separator()
 
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(-)

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(-)

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(-)

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(-)

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(-)

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(-)

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(-)

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(-)

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(+)

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(-)

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 b79ec3ac2edf58749889275f45779f745ffbad04 Mon Sep 17 00:00:00 2001
From: Antony Riakiotakis 
Date: Tue, 1 Jan 2013 11:46:12 +0000
Subject: UI cleanup: fixed texture is a 2d image painting option, hide in 3D
 viewport toolbar

---
 release/scripts/startup/bl_ui/space_view3d_toolbar.py | 2 --
 1 file changed, 2 deletions(-)

diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 0e1f5d8dff2..4d1d2ad10bb 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -720,8 +720,6 @@ class VIEW3D_PT_tools_brush_texture(Panel, View3DPaintPanel):
         col = layout.column()
 
         col.template_ID_preview(brush, "texture", new="texture.new", rows=3, cols=8)
-        if brush.use_paint_image:
-            col.prop(brush, "use_fixed_texture")
 
         if context.sculpt_object:
             sculpt_brush_texture_settings(col, brush)
-- 
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.
---
 release/scripts/startup/bl_ui/space_view3d.py      |  2 +-
 source/blender/editors/sculpt_paint/paint_vertex.c | 10 +++++-----
 source/blender/editors/space_view3d/drawmesh.c     | 20 ++++++++++++++++----
 3 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index d2183b80476..8189ee21bc8 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -71,7 +71,7 @@ class VIEW3D_HT_header(Header):
 
             # Occlude geometry
             if ((view.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'} and (mode == 'PARTICLE_EDIT' or (mode == 'EDIT' and obj.type == 'MESH'))) or
-                    (mode == 'WEIGHT_PAINT' and obj.data.use_paint_mask_vertex)):
+                    (mode == 'WEIGHT_PAINT')):
                 row.prop(view, "use_occlude_geometry", text="")
 
             # Proportional editing
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.
---
 CMakeLists.txt                           | 16 +++++++++++++++-
 SConstruct                               |  3 ++-
 build_files/cmake/macros.cmake           |  9 +++++++++
 source/blender/blenlib/BLI_utildefines.h | 30 ++++++++++++++++++++++++++----
 4 files changed, 52 insertions(+), 6 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 674e532ff2c..a87c3e2d96d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -149,6 +149,9 @@ mark_as_advanced(WITH_HEADLESS)
 option(WITH_AUDASPACE    "Build with blenders audio library (only disable if you know what you're doing!)" ON)
 mark_as_advanced(WITH_AUDASPACE)
 
+option(WITH_BOOL_COMPAT "Continue defining \"TRUE\" and \"FALSE\" until these can be replaced with \"true\" and \"false\" from stdbool.h" ON)
+mark_as_advanced(WITH_BOOL_COMPAT)
+
 
 # (unix defaults to OpenMP On)
 if((UNIX AND NOT APPLE) OR (MINGW))
@@ -264,7 +267,6 @@ mark_as_advanced(WITH_CXX_GUARDEDALLOC)
 option(WITH_ASSERT_ABORT "Call abort() when raising an assertion through BLI_assert()" OFF)
 mark_as_advanced(WITH_ASSERT_ABORT)
 
-
 if(APPLE)
 	cmake_minimum_required(VERSION 2.8.8)
 	cmake_policy(VERSION 2.8.8)
@@ -423,6 +425,13 @@ endif()
 
 TEST_SSE_SUPPORT(COMPILER_SSE_FLAG COMPILER_SSE2_FLAG)
 
+TEST_STDBOOL_SUPPORT()
+if(HAVE_STDBOOL_H)
+	add_definitions(-DHAVE_STDBOOL_H)
+endif()
+if(WITH_BOOL_COMPAT)
+	add_definitions(-DWITH_BOOL_COMPAT)
+endif()
 
 #-----------------------------------------------------------------------------
 # Check for valid directories
@@ -2137,3 +2146,8 @@ if(FIRST_RUN)
 
 	message("${_config_msg}")
 endif()
+
+# debug
+message(
+    STATUS "HAVE_STDBOOL_H = ${HAVE_STDBOOL_H}"
+)
diff --git a/SConstruct b/SConstruct
index f73aabc6767..90c3c45b302 100644
--- a/SConstruct
+++ b/SConstruct
@@ -373,9 +373,10 @@ if btools.ENDIAN == "big":
 else:
     env['CPPFLAGS'].append('-D__LITTLE_ENDIAN__')
 
-# TODO, make optional
+# TODO, make optional (as with CMake)
 env['CPPFLAGS'].append('-DWITH_AUDASPACE')
 env['CPPFLAGS'].append('-DWITH_AVI')
+env['CPPFLAGS'].append('-DWITH_BOOL_COMPAT')
 
 # lastly we check for root_build_dir ( we should not do before, otherwise we might do wrong builddir
 B.root_build_dir = env['BF_BUILDDIR']
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index efa258aa9dc..4a4c0fe6d2d 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -441,6 +441,15 @@ macro(TEST_SSE_SUPPORT
 	unset(CMAKE_REQUIRED_FLAGS)
 endmacro()
 
+macro(TEST_STDBOOL_SUPPORT)
+	# This program will compile correctly if and only if
+	# this C compiler supports C99 stdbool.
+	check_c_source_runs("
+		#include 
+		int main(void) { return (int)false; }"
+	HAVE_STDBOOL_H)
+endmacro()
+
 # when we have warnings as errors applied globally this
 # needs to be removed for some external libs which we dont maintain.
 
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(-)

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(-)

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(+)

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(-)

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(+)

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.
---
 intern/cycles/blender/blender_session.cpp          | 14 +++-
 intern/cycles/render/session.cpp                   |  8 ++-
 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 +-
 9 files changed, 184 insertions(+), 27 deletions(-)

diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index cd31a5b5bb6..770b71afcdc 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -107,6 +107,8 @@ void BlenderSession::create_session()
 	/* set buffer parameters */
 	BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_v3d, b_rv3d, scene->camera, width, height);
 	session->reset(buffer_params, session_params.samples);
+
+	b_engine.use_highlight_tiles(session_params.progressive_refine == false);
 }
 
 void BlenderSession::reset_session(BL::BlendData b_data_, BL::Scene b_scene_)
@@ -149,6 +151,8 @@ void BlenderSession::reset_session(BL::BlendData b_data_, BL::Scene b_scene_)
 
 	BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, PointerRNA_NULL, PointerRNA_NULL, scene->camera, width, height);
 	session->reset(buffer_params, session_params.samples);
+
+	b_engine.use_highlight_tiles(session_params.progressive_refine == false);
 }
 
 void BlenderSession::free_session()
@@ -252,7 +256,15 @@ void BlenderSession::do_write_update_render_tile(RenderTile& rtile, bool do_upda
 
 	if (do_update_only) {
 		/* update only needed */
-		update_render_result(b_rr, b_rlay, rtile);
+
+		if (rtile.sample != 0) {
+			/* sample would be zero at initial tile update, which is only needed
+			 * to tag tile form blender side as IN PROGRESS for proper highlight
+			 * no buffers should be sent to blender yet
+			 */
+			update_render_result(b_rr, b_rlay, rtile);
+		}
+
 		end_render_result(b_engine, b_rr, true);
 	}
 	else {
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index 1d1a3d54893..36948adce17 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -357,7 +357,7 @@ bool Session::acquire_tile(Device *tile_device, RenderTile& rtile)
 
 	tile_lock.unlock();
 
-	/* in case of a permant buffer, return it, otherwise we will allocate
+	/* in case of a permanent buffer, return it, otherwise we will allocate
 	 * a new temporary buffer */
 	if(!params.background) {
 		tile_manager.state.buffer.get_offset_stride(rtile.offset, rtile.stride);
@@ -411,6 +411,12 @@ bool Session::acquire_tile(Device *tile_device, RenderTile& rtile)
 	rtile.rgba = 0;
 	rtile.buffers = tilebuffers;
 
+	/* this will tag tile as IN PROGRESS in blender-side render pipeline,
+	 * which is needed to highlight currently rendering tile before first
+	 * sample was processed for it
+	 */
+	update_tile_sample(rtile);
+
 	return true;
 }
 
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(-)

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(-)

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(-)

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 178a877a95c15e386f4e68d4094391e5265770fa Mon Sep 17 00:00:00 2001
From: Stuart Broadfoot 
Date: Tue, 1 Jan 2013 19:44:09 +0000
Subject: Fix to prevent undefined normals being generated with
 `add_face_normals()', from triangles with zero area.

---
 intern/cycles/blender/blender_mesh.cpp | 17 +++++++++++++----
 intern/cycles/render/mesh.cpp          |  7 ++++++-
 2 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index e9250ec3eff..a01b2e9ee38 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -223,10 +223,19 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
 		int shader = used_shaders[mi];
 		bool smooth = f->use_smooth();
 
-		mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
-
-		if(n == 4)
-			mesh->add_triangle(vi[0], vi[2], vi[3], shader, smooth);
+		if(n == 4) {
+			if(len_squared(cross(mesh->verts[vi[1]] - mesh->verts[vi[0]], mesh->verts[vi[2]] - mesh->verts[vi[0]])) == 0.0f ||
+				len_squared(cross(mesh->verts[vi[2]] - mesh->verts[vi[0]], mesh->verts[vi[3]] - mesh->verts[vi[0]])) == 0.0f) {
+				mesh->add_triangle(vi[0], vi[1], vi[3], shader, smooth);
+				mesh->add_triangle(vi[2], vi[3], vi[1], shader, smooth);
+			}
+			else {
+				mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
+				mesh->add_triangle(vi[0], vi[2], vi[3], shader, smooth);
+			}
+		}
+		else
+			mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
 
 		nverts.push_back(n);
 	}
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index a2d545d51c0..b20e5cebdc5 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -178,7 +178,12 @@ void Mesh::add_face_normals()
 			float3 v1 = verts_ptr[t.v[1]];
 			float3 v2 = verts_ptr[t.v[2]];
 
-			fN[i] = normalize(cross(v1 - v0, v2 - v0));
+			float3 norm = cross(v1 - v0, v2 - v0);
+			float normlen = len(norm);
+			if(normlen == 0.0f)
+				fN[i] = make_float3(0.0f, 0.0f, 0.0f);
+			else
+				fN[i] = norm / normlen;
 
 			if(flip)
 				fN[i] = -fN[i];
-- 
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
---
 intern/cycles/blender/blender_curves.cpp                  | 10 ++++++----
 source/blender/nodes/shader/nodes/node_shader_hair_info.c |  7 +------
 2 files changed, 7 insertions(+), 10 deletions(-)

diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp
index 81358e51eb2..68b5d18a093 100644
--- a/intern/cycles/blender/blender_curves.cpp
+++ b/intern/cycles/blender/blender_curves.cpp
@@ -380,7 +380,7 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, int interpo
 					float3 ickey_loc = make_float3(0.0f,0.0f,0.0f);
 					float time = 0.0f;
 
-					if ((interpolation == 2) && (curvekey == CData->curve_firstkey[curve]) && (subv == 0))
+					if ((interpolation == CURVE_BSPLINE) && (curvekey == CData->curve_firstkey[curve]) && (subv == 0))
 						ickey_loc = CData->curvekey_co[curvekey];
 					else
 						InterpolateKeySegments(subv, segments, curvekey, curve, &ickey_loc, &time, CData , interpolation);
@@ -413,6 +413,7 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, int interpo
 	mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
 	mesh->add_face_normals();
 	mesh->add_vertex_normals();
+	mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
 
 	/* texture coords still needed */
 
@@ -494,7 +495,7 @@ void ExportCurveTriangleRibbons(Mesh *mesh, ParticleCurveData *CData, int interp
 					float3 ickey_loc = make_float3(0.0f,0.0f,0.0f);
 					float time = 0.0f;
 
-					if ((interpolation == 2) && (curvekey == CData->curve_firstkey[curve]) && (subv == 0))
+					if ((interpolation == CURVE_BSPLINE) && (curvekey == CData->curve_firstkey[curve]) && (subv == 0))
 						ickey_loc = CData->curvekey_co[curvekey];
 					else
 						InterpolateKeySegments(subv, segments, curvekey, curve, &ickey_loc, &time, CData , interpolation);
@@ -526,7 +527,7 @@ void ExportCurveTriangleRibbons(Mesh *mesh, ParticleCurveData *CData, int interp
 	mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
 	mesh->add_face_normals();
 	mesh->add_vertex_normals();
-
+	mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
 	/* texture coords still needed */
 
 }
@@ -611,7 +612,7 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int inter
 					float3 ickey_loc = make_float3(0.0f,0.0f,0.0f);
 					float time = 0.0f;
 
-					if ((interpolation == 2) && (curvekey == CData->curve_firstkey[curve]) && (subv == 0))
+					if ((interpolation == CURVE_BSPLINE) && (curvekey == CData->curve_firstkey[curve]) && (subv == 0))
 						ickey_loc = CData->curvekey_co[curvekey];
 					else
 						InterpolateKeySegments(subv, segments, curvekey, curve, &ickey_loc, &time, CData , interpolation);
@@ -649,6 +650,7 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int inter
 	mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
 	mesh->add_face_normals();
 	mesh->add_vertex_normals();
+	mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
 
 	/* texture coords still needed */
 }
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

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

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
---
 release/scripts/startup/bl_ui/properties_render.py |   9 +-
 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 +++++
 7 files changed, 308 insertions(+), 49 deletions(-)

diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index 8dfa954dade..03b3d41b631 100644
--- a/release/scripts/startup/bl_ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -609,9 +609,12 @@ class RENDER_PT_bake(RenderButtonsPanel, Panel):
             split = layout.split()
 
             col = split.column()
-            col.prop(rd, "use_bake_clear")
-            col.prop(rd, "bake_margin")
-            col.prop(rd, "bake_quad_split", text="Split")
+            col.prop(rd, "use_bake_to_vertex_color")
+            sub = col.column()
+            sub.active = not rd.use_bake_to_vertex_color
+            sub.prop(rd, "use_bake_clear")
+            sub.prop(rd, "bake_margin")
+            sub.prop(rd, "bake_quad_split", text="Split")
 
             col = split.column()
             col.prop(rd, "use_bake_selected_to_active")
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(-)

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

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(-)

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(-)

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(-)

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(-)

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(-)

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(-)

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(+)

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)...
---
 .../startup/bl_ui/properties_data_modifier.py      |  18 +-
 source/blender/blenkernel/intern/ocean.c           | 352 ++++++++++++---------
 source/blender/makesrna/intern/rna_modifier.c      |  39 +--
 source/blender/modifiers/intern/MOD_ocean.c        |  28 +-
 4 files changed, 247 insertions(+), 190 deletions(-)

diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index e90d1616929..df29f18853b 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -489,11 +489,13 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
 
         col = split.column()
         col.prop(md, "time")
-        col.prop(md, "resolution")
+        col.prop(md, "depth")
+        col.prop(md, "random_seed")
 
         col = split.column()
+        col.prop(md, "resolution")
+        col.prop(md, "size")
         col.prop(md, "spatial_size")
-        col.prop(md, "depth")
 
         layout.label("Waves:")
 
@@ -534,7 +536,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
         if md.is_cached:
             layout.operator("object.ocean_bake", text="Free Bake").free = True
         else:
-            layout.operator("object.ocean_bake")
+            layout.operator("object.ocean_bake").free = False
 
         split = layout.split()
         split.enabled = not md.is_cached
@@ -547,7 +549,15 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
         col.label(text="Cache path:")
         col.prop(md, "filepath", text="")
 
-        #col.prop(md, "bake_foam_fade")
+        split = layout.split()
+        split.enabled = not md.is_cached
+
+        col = split.column()
+        col.active = md.use_foam
+        col.prop(md, "bake_foam_fade")
+
+        col = split.column()
+
 
     def PARTICLE_INSTANCE(self, layout, ob, md):
         layout.prop(md, "object")
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(-)

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()
---
 release/scripts/modules/bpy_extras/object_utils.py   |  3 +--
 .../scripts/startup/bl_operators/add_mesh_torus.py   |  5 +----
 release/scripts/startup/bl_ui/space_sequencer.py     |  4 ++--
 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 ++++-
 9 files changed, 34 insertions(+), 17 deletions(-)

diff --git a/release/scripts/modules/bpy_extras/object_utils.py b/release/scripts/modules/bpy_extras/object_utils.py
index 46731b807f7..4e1385cff80 100644
--- a/release/scripts/modules/bpy_extras/object_utils.py
+++ b/release/scripts/modules/bpy_extras/object_utils.py
@@ -26,7 +26,6 @@ __all__ = (
 
 
 import bpy
-import mathutils
 
 from bpy.props import BoolProperty, FloatVectorProperty
 
@@ -80,7 +79,7 @@ def add_object_align_init(context, operator):
             rotation = space_data.region_3d.view_matrix.to_3x3().inverted()
             rotation.resize_4x4()
         else:
-            rotation = mathutils.Matrix()
+            rotation = Matrix()
 
         # set the operator properties
         if operator:
diff --git a/release/scripts/startup/bl_operators/add_mesh_torus.py b/release/scripts/startup/bl_operators/add_mesh_torus.py
index 552247f0940..63e796e2b5d 100644
--- a/release/scripts/startup/bl_operators/add_mesh_torus.py
+++ b/release/scripts/startup/bl_operators/add_mesh_torus.py
@@ -19,7 +19,6 @@
 # 
 import bpy
 from bpy.types import Operator
-import mathutils
 
 from bpy.props import (FloatProperty,
                        IntProperty,
@@ -31,9 +30,7 @@ from bpy_extras import object_utils
 
 def add_torus(major_rad, minor_rad, major_seg, minor_seg):
     from math import cos, sin, pi
-
-    Vector = mathutils.Vector
-    Quaternion = mathutils.Quaternion
+    from mathutils import Vector, Quaternion
 
     PI_2 = pi * 2.0
     z_axis = 0.0, 0.0, 1.0
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index d6f8de93c0f..64ad5656bcd 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -433,7 +433,7 @@ class SEQUENCER_PT_edit(SequencerButtonsPanel, Panel):
         elem = False
 
         if strip.type == 'IMAGE':
-            elem = strip.getStripElem(frame_current)
+            elem = strip.strip_elem_from_frame(frame_current)
         elif strip.type == 'MOVIE':
             elem = strip.elements[0]
 
@@ -595,7 +595,7 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, Panel):
 
             # Current element for the filename
 
-            elem = strip.getStripElem(context.scene.frame_current)
+            elem = strip.strip_elem_from_frame(context.scene.frame_current)
             if elem:
                 split = layout.split(percentage=0.2)
                 split.label(text="File:")
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(-)

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 ab9915ba8d2f0c594853dd96bc01170776a774fa Mon Sep 17 00:00:00 2001
From: Antony Riakiotakis 
Date: Wed, 2 Jan 2013 20:51:47 +0000
Subject: revert 53478, it looks this is still useful for a couple of use cases
 in non-projective texture painting such as stamping a static texture and
 using image space size in pixels.

---
 release/scripts/startup/bl_ui/space_view3d_toolbar.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 4d1d2ad10bb..0e1f5d8dff2 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -720,6 +720,8 @@ class VIEW3D_PT_tools_brush_texture(Panel, View3DPaintPanel):
         col = layout.column()
 
         col.template_ID_preview(brush, "texture", new="texture.new", rows=3, cols=8)
+        if brush.use_paint_image:
+            col.prop(brush, "use_fixed_texture")
 
         if context.sculpt_object:
             sculpt_brush_texture_settings(col, brush)
-- 
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(-)

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)

---
 intern/cycles/blender/addon/__init__.py                 | 2 +-
 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 +++++++
 5 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py
index 6d1b6d4f56e..dddf7bafb14 100644
--- a/intern/cycles/blender/addon/__init__.py
+++ b/intern/cycles/blender/addon/__init__.py
@@ -21,7 +21,7 @@
 bl_info = {
     "name": "Cycles Render Engine",
     "author": "",
-    "blender": (2, 6, 5),
+    "blender": (2, 60, 5),
     "location": "Info header, render engine menu",
     "description": "Cycles Render Engine integration",
     "warning": "",
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.
---
 CMakeLists.txt                                   | 18 +++++++++++++++++-
 build_files/cmake/macros.cmake                   |  4 +++-
 extern/CMakeLists.txt                            |  4 +++-
 intern/smoke/CMakeLists.txt                      |  2 +-
 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 +++-
 11 files changed, 45 insertions(+), 11 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index a87c3e2d96d..fd5a3769b2a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -129,6 +129,8 @@ option(WITH_IK_ITASC      "Enable ITASC IK solver (only disable for development
 option(WITH_IK_SOLVER     "Enable Legacy IK solver (only disable for development)" ON)
 option(WITH_FFTW3         "Enable FFTW3 support (Used for smoke and audio effects)" ON)
 option(WITH_BULLET        "Enable Bullet (Physics Engine)" ON)
+option(WITH_SYSTEM_BULLET "Use the systems bullet library (currently unsupported due to missing features in upstream!)" )
+mark_as_advanced(WITH_SYSTEM_BULLET)
 option(WITH_GAMEENGINE    "Enable Game Engine" ON)
 option(WITH_PLAYER        "Build Player" OFF)
 option(WITH_OPENCOLORIO   "Enable OpenColorIO color management" ON)
@@ -1842,12 +1844,26 @@ else()
 	set(GLEW_INCLUDE_PATH "${CMAKE_SOURCE_DIR}/extern/glew/include")
 endif()
 
+
+#-----------------------------------------------------------------------------
+# Configure Bullet
+
+if(WITH_BULLET AND WITH_SYSTEM_BULLET)
+	find_package(Bullet)
+	if(NOT BULLET_FOUND)
+		set(WITH_BULLET OFF)
+	endif()
+else()
+	set(BULLET_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/extern/bullet2/src")
+	# set(BULLET_LIBRARIES "")
+endif()
+
 #-----------------------------------------------------------------------------
 # Configure Python.
 
 if(WITH_PYTHON_MODULE)
 	add_definitions(-DPy_ENABLE_SHARED)
-endif()
+endif().
 
 #-----------------------------------------------------------------------------
 # Extra compile flags
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index 4a4c0fe6d2d..bdd82a4f438 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -282,7 +282,9 @@ macro(setup_liblinks
 	if(WITH_SYSTEM_GLEW)
 		target_link_libraries(${target} ${GLEW_LIBRARY})
 	endif()
-
+	if(WITH_BULLET AND WITH_SYSTEM_BULLET)
+		target_link_libraries(${target} ${BULLET_LIBRARIES})
+	endif()
 	if(WITH_OPENAL)
 		target_link_libraries(${target} ${OPENAL_LIBRARY})
 	endif()
diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt
index 2f7f6584f0f..6ad6bdc316f 100644
--- a/extern/CMakeLists.txt
+++ b/extern/CMakeLists.txt
@@ -30,7 +30,9 @@ add_subdirectory(colamd)
 add_subdirectory(rangetree)
 
 if(WITH_BULLET)
-	add_subdirectory(bullet2)
+	if(NOT WITH_SYSTEM_BULLET)
+		add_subdirectory(bullet2)
+	endif()
 endif()
 
 # now only available in a branch
diff --git a/intern/smoke/CMakeLists.txt b/intern/smoke/CMakeLists.txt
index 3b8a4c06e69..b6338f90ebc 100644
--- a/intern/smoke/CMakeLists.txt
+++ b/intern/smoke/CMakeLists.txt
@@ -29,7 +29,7 @@ set(INC
 )
 
 set(INC_SYS
-	../../extern/bullet2/src
+	${BULLET_INCLUDE_DIRS}
 	${PNG_INCLUDE_DIR}
 	${ZLIB_INCLUDE_DIRS}
 )
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 fd8a2a592432b8693e0ffdad977e0d2529bbfc73 Mon Sep 17 00:00:00 2001
From: Mitchell Stokes 
Date: Thu, 3 Jan 2013 00:29:13 +0000
Subject: CMake: Setting vc10 to use Python 3.3 (it was still set to 3.2). For
 the time being, I'm having vc10 use the vc9 Python libs, which SCons is
 currently doing.

---
 CMakeLists.txt | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index fd5a3769b2a..6d63465641e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1098,14 +1098,16 @@ elseif(WIN32)
 		if(WITH_PYTHON)
 			# normally cached but not since we include them with blender
 			if(MSVC10)
-				set(PYTHON_VERSION 3.2) # CACHE STRING)
+				set(PYTHON_VERSION 3.3) # CACHE STRING)
 			else()
 				set(PYTHON_VERSION 3.3) # CACHE STRING)
 			endif()
 
 			set_lib_path(PYTHON "python")
 			STRING(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION})
-			set(PYTHON_LIBRARY ${PYTHON}/lib/python${_PYTHON_VERSION_NO_DOTS}.lib) #CACHE FILEPATH
+			# Use shared libs for vc2008 and vc2010 until we actually have vc2010 libs
+			set(PYTHON_LIBRARY ${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}.lib)
+			# set(PYTHON_LIBRARY ${PYTHON}/lib/python${_PYTHON_VERSION_NO_DOTS}.lib) #CACHE FILEPATH
 			unset(_PYTHON_VERSION_NO_DOTS)
 
 			#Shared includes for both vc2008 and vc2010
-- 
cgit v1.2.3


From df3e2448871990fb96d6e2149d672e6a6ce43a92 Mon Sep 17 00:00:00 2001
From: Mitchell Stokes 
Date: Thu, 3 Jan 2013 00:35:42 +0000
Subject: CMake: Looks like a period sneaked into r53515, which caused CMake to
 fail.

---
 CMakeLists.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6d63465641e..ecc3f3ea708 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1865,7 +1865,7 @@ endif()
 
 if(WITH_PYTHON_MODULE)
 	add_definitions(-DPy_ENABLE_SHARED)
-endif().
+endif()
 
 #-----------------------------------------------------------------------------
 # Extra compile flags
-- 
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(-)

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 84f229536afceb78e10ebc7f5ff443eb01692188 Mon Sep 17 00:00:00 2001
From: Campbell Barton 
Date: Thu, 3 Jan 2013 07:01:41 +0000
Subject: fix [#33715] Dirty Vertex Colors display problem since 2.65a

---
 .../startup/bl_operators/vertexpaint_dirt.py       | 24 +++++++++++++---------
 1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/release/scripts/startup/bl_operators/vertexpaint_dirt.py b/release/scripts/startup/bl_operators/vertexpaint_dirt.py
index bfbde2f4b07..e2a820b761a 100644
--- a/release/scripts/startup/bl_operators/vertexpaint_dirt.py
+++ b/release/scripts/startup/bl_operators/vertexpaint_dirt.py
@@ -127,13 +127,14 @@ def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean,
                 col[0] = tone * col[0]
                 col[1] = tone * col[1]
                 col[2] = tone * col[2]
-
+    me.update()
     return {'FINISHED'}
 
 
 import bpy
 from bpy.types import Operator
 from bpy.props import FloatProperty, IntProperty, BoolProperty
+from math import pi
 
 
 class VertexPaintDirt(Operator):
@@ -156,14 +157,16 @@ class VertexPaintDirt(Operator):
     clean_angle = FloatProperty(
             name="Highlight Angle",
             description="Less than 90 limits the angle used in the tonal range",
-            min=0.0, max=180.0,
-            default=180.0,
+            min=0.0, max=pi,
+            default=pi,
+            unit="ROTATION",
             )
     dirt_angle = FloatProperty(
             name="Dirt Angle",
             description="Less than 90 limits the angle used in the tonal range",
-            min=0.0, max=180.0,
+            min=0.0, max=pi,
             default=0.0,
+            unit="ROTATION",
             )
     dirt_only = BoolProperty(
             name="Dirt Only",
@@ -171,20 +174,21 @@ class VertexPaintDirt(Operator):
             default=False,
             )
 
+    @classmethod
+    def poll(cls, context):
+        obj = context.object
+        return (obj and obj.type == 'MESH')
+
     def execute(self, context):
         import time
         from math import radians
-        obj = context.object
-
-        if not obj or obj.type != 'MESH':
-            self.report({'ERROR'}, "Error, no active mesh object, aborting")
-            return {'CANCELLED'}
 
+        obj = context.object
         mesh = obj.data
 
         t = time.time()
 
-        ret = applyVertexDirt(mesh, self.blur_iterations, self.blur_strength, radians(self.dirt_angle), radians(self.clean_angle), self.dirt_only)
+        ret = applyVertexDirt(mesh, self.blur_iterations, self.blur_strength, self.dirt_angle, self.clean_angle, self.dirt_only)
 
         print('Dirt calculated in %.6f' % (time.time() - t))
 
-- 
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(+)

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(-)

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(-)

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 57cf48e7c6fd04f864072c21433a822907774f78 Mon Sep 17 00:00:00 2001
From: Brecht Van Lommel 
Date: Thu, 3 Jan 2013 12:08:54 +0000
Subject: Cycles Hair: refactoring to support generic attributes for hair
 curves. There should be no functional changes yet. UV, tangent and intercept
 are now stored as attributes, with the intention to add more like multiple
 uv's, vertex colors, generated coordinates and motion vectors later.

Things got a bit messy due to having both triangle and curve data in the same
mesh data structure, which also gives us two sets of attributes. This will get
cleaned up when we split the mesh class.
---
 intern/cycles/blender/blender_curves.cpp        | 160 ++++++------
 intern/cycles/blender/blender_mesh.cpp          |   8 +-
 intern/cycles/bvh/bvh.cpp                       |  37 ++-
 intern/cycles/bvh/bvh_build.cpp                 |  10 +-
 intern/cycles/bvh/bvh_split.cpp                 |   6 +-
 intern/cycles/kernel/CMakeLists.txt             |   3 +-
 intern/cycles/kernel/kernel_attribute.h         |  50 ----
 intern/cycles/kernel/kernel_bvh.h               |  12 +-
 intern/cycles/kernel/kernel_curve.h             | 140 +++++++++++
 intern/cycles/kernel/kernel_light.h             |   6 +-
 intern/cycles/kernel/kernel_object.h            |  50 ----
 intern/cycles/kernel/kernel_passes.h            |   4 +-
 intern/cycles/kernel/kernel_path.h              |   5 +-
 intern/cycles/kernel/kernel_primitive.h         | 183 ++++++++++++++
 intern/cycles/kernel/kernel_shader.h            |   4 +-
 intern/cycles/kernel/kernel_textures.h          |   4 +-
 intern/cycles/kernel/kernel_triangle.h          | 231 +++++------------
 intern/cycles/kernel/kernel_types.h             |  29 ++-
 intern/cycles/kernel/osl/osl_services.cpp       |  44 ++--
 intern/cycles/kernel/osl/osl_services.h         |   3 +-
 intern/cycles/kernel/osl/osl_shader.cpp         |  11 +-
 intern/cycles/kernel/osl/osl_shader.h           |   2 +-
 intern/cycles/kernel/shaders/node_hair_info.osl |   8 +-
 intern/cycles/kernel/svm/svm_attribute.h        | 153 +++++-------
 intern/cycles/kernel/svm/svm_geometry.h         |  33 +--
 intern/cycles/kernel/svm/svm_tex_coord.h        |  33 +--
 intern/cycles/render/attribute.cpp              | 205 ++++++++++-----
 intern/cycles/render/attribute.h                |  46 ++--
 intern/cycles/render/curves.h                   |   3 +-
 intern/cycles/render/light.cpp                  |  16 +-
 intern/cycles/render/mesh.cpp                   | 316 ++++++++++++++----------
 intern/cycles/render/mesh.h                     |  30 +--
 intern/cycles/render/nodes.cpp                  |  13 +-
 intern/cycles/render/nodes.h                    |   2 +
 intern/cycles/render/object.cpp                 |  26 +-
 intern/cycles/render/scene.h                    |   5 +-
 intern/cycles/subd/subd_dice.cpp                |   2 +-
 intern/cycles/util/CMakeLists.txt               |   2 -
 intern/cycles/util/util_attribute.cpp           |  51 ----
 intern/cycles/util/util_attribute.h             |  31 ---
 intern/cycles/util/util_types.h                 |  18 --
 41 files changed, 1051 insertions(+), 944 deletions(-)
 delete mode 100644 intern/cycles/kernel/kernel_attribute.h
 create mode 100644 intern/cycles/kernel/kernel_curve.h
 create mode 100644 intern/cycles/kernel/kernel_primitive.h
 delete mode 100644 intern/cycles/util/util_attribute.cpp
 delete mode 100644 intern/cycles/util/util_attribute.h

diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp
index 68b5d18a093..61628aae535 100644
--- a/intern/cycles/blender/blender_curves.cpp
+++ b/intern/cycles/blender/blender_curves.cpp
@@ -67,8 +67,7 @@ ParticleCurveData::~ParticleCurveData()
 	curve_firstkey.clear();
 	curve_keynum.clear();
 	curve_length.clear();
-	curve_u.clear();
-	curve_v.clear();
+	curve_uv.clear();
 
 	curvekey_co.clear();
 	curvekey_time.clear();
@@ -78,13 +77,13 @@ void interp_weights(float t, float data[4], int type)
 {
 	float t2, t3, fc;
 
-	if (type == CURVE_LINEAR) {
+	if(type == CURVE_LINEAR) {
 		data[0] =          0.0f;
 		data[1] = -t     + 1.0f;
 		data[2] =  t;
 		data[3] =          0.0f;
 	}
-	else if (type == CURVE_CARDINAL) {
+	else if(type == CURVE_CARDINAL) {
 		t2 = t * t;
 		t3 = t2 * t;
 		fc = 0.71f;
@@ -94,7 +93,7 @@ void interp_weights(float t, float data[4], int type)
 		data[2] =  (fc - 2.0f) * t3  + (3.0f - 2.0f * fc) * t2 + fc * t;
 		data[3] =  fc          * t3  - fc * t2;
 	}
-	else if (type == CURVE_BSPLINE) {
+	else if(type == CURVE_BSPLINE) {
 		t2 = t * t;
 		t3 = t2 * t;
 
@@ -115,8 +114,8 @@ void curveinterp_v3_v3v3v3v3(float3 *p, float3 *v1, float3 *v2, float3 *v3, floa
 float shaperadius(float shape, float root, float tip, float time)
 {
 	float radius = 1.0f - time;
-	if (shape != 0.0f) {
-		if (shape < 0.0f)
+	if(shape != 0.0f) {
+		if(shape < 0.0f)
 			radius = (float)pow(1.0f - time, 1.f + shape);
 		else
 			radius = (float)pow(1.0f - time, 1.f / (1.f - shape));
@@ -133,10 +132,10 @@ void InterpolateKeySegments(int seg, int segno, int key, int curve, float3 *keyl
 	float3 ckey_loc3 = CData->curvekey_co[key+1];
 	float3 ckey_loc4 = ckey_loc3;
 
-	if (key > CData->curve_firstkey[curve])
+	if(key > CData->curve_firstkey[curve])
 		ckey_loc1 = CData->curvekey_co[key - 1];
 
-	if (key < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2)
+	if(key < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2)
 		ckey_loc4 = CData->curvekey_co[key + 2];
 
 
@@ -167,7 +166,7 @@ bool ObtainParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Particle
 
 	BL::Object::modifiers_iterator b_mod;
 	for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
-		if ((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (b_mod->show_viewport()) && (b_mod->show_render())) {
+		if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (b_mod->show_viewport()) && (b_mod->show_render())) {
 
 			BL::ParticleSystemModifier psmd(b_mod->ptr);
 
@@ -213,7 +212,7 @@ bool ObtainParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Particle
 						float nco[3];
 						b_cKey->co_object( *b_ob, psmd, *b_pa, nco);
 						float3 cKey = make_float3(nco[0],nco[1],nco[2]);
-						if (step_no > 0)
+						if(step_no > 0)
 							curve_length += len(cKey - pcKey);
 						CData->curvekey_co.push_back(cKey);
 						CData->curvekey_time.push_back(curve_length);
@@ -227,11 +226,10 @@ bool ObtainParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Particle
 					BL::Mesh::tessface_uv_textures_iterator l;
 					b_mesh->tessface_uv_textures.begin(l);
 
-					float uvs[3] = {0,0};
+					float3 uv = make_float3(0.0f, 0.0f, 0.0f);
 					if(b_mesh->tessface_uv_textures.length())
-						b_pa->uv_on_emitter(psmd,uvs);
-					CData->curve_u.push_back(uvs[0]);
-					CData->curve_v.push_back(uvs[1]);
+						b_pa->uv_on_emitter(psmd,&uv.x);
+					CData->curve_uv.push_back(uv);
 
 					curvenum++;
 
@@ -258,7 +256,7 @@ bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par
 
 	BL::Object::modifiers_iterator b_mod;
 	for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
-		if ((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (b_mod->show_viewport()) && (b_mod->show_render())) {
+		if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (b_mod->show_viewport()) && (b_mod->show_render())) {
 			BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
 
 			BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
@@ -277,10 +275,10 @@ bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par
 				int totchild = b_psys.child_particles.length() * b_psys.settings().draw_percentage() / 100;
 				int totcurves = totchild;
 				
-				if (use_parents || b_psys.settings().child_type() == 0)
+				if(use_parents || b_psys.settings().child_type() == 0)
 					totcurves += totparts;
 
-				if (totcurves == 0)
+				if(totcurves == 0)
 					continue;
 
 				PointerRNA cpsys = RNA_pointer_get(&b_part.ptr, "cycles");
@@ -314,7 +312,7 @@ bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par
 						b_psys.co_hair(*b_ob, psmd, pa_no, step_no, nco);
 						float3 cKey = make_float3(nco[0],nco[1],nco[2]);
 						cKey = transform_point(&itfm, cKey);
-						if (step_no > 0)
+						if(step_no > 0)
 							curve_length += len(cKey - pcKey);
 						CData->curvekey_co.push_back(cKey);
 						CData->curvekey_time.push_back(curve_length);
@@ -327,17 +325,14 @@ bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par
 					BL::Mesh::tessface_uv_textures_iterator l;
 					b_mesh->tessface_uv_textures.begin(l);
 
-					float uvs[2] = {0,0};
+					float3 uv = make_float3(0.0f, 0.0f, 0.0f);
 					if(b_mesh->tessface_uv_textures.length())
-						b_psys.uv_on_emitter(psmd, *b_pa, pa_no, uvs);
-						
+						b_psys.uv_on_emitter(psmd, *b_pa, pa_no, &uv.x);
+					CData->curve_uv.push_back(uv);
 
 					if(pa_no < totparts && b_pa != b_psys.particles.end())
 						++b_pa;
 
-					CData->curve_u.push_back(uvs[0]);
-					CData->curve_v.push_back(uvs[1]);
-
 					curvenum++;
 
 				}
@@ -365,11 +360,11 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, int interpo
 
 				float3 v1;
 
-				if (curvekey == CData->curve_firstkey[curve]) {
+				if(curvekey == CData->curve_firstkey[curve]) {
 					subv = 0;
 					v1 = CData->curvekey_co[curvekey+2] - CData->curvekey_co[curvekey];
 				}
-				else if (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2)
+				else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2)
 					v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey - 2];
 				else 
 					v1 = CData->curvekey_co[curvekey + 1] - CData->curvekey_co[curvekey - 1];
@@ -387,10 +382,10 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, int interpo
 
 					float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
 
-					if (CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
+					if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
 						radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);
 
-					if ((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) && (subv == segments))
+					if((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) && (subv == segments))
 						radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.95f);
 
 					xbasis = normalize(cross(v1,RotCam - ickey_loc));
@@ -408,7 +403,7 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, int interpo
 		}
 	}
 
-	mesh->reserve(mesh->verts.size(), mesh->triangles.size());
+	mesh->reserve(mesh->verts.size(), mesh->triangles.size(), 0, 0);
 	mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
 	mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
 	mesh->add_face_normals();
@@ -439,11 +434,11 @@ void ExportCurveTriangleRibbons(Mesh *mesh, ParticleCurveData *CData, int interp
 				float3 v1;
 				float3 v2;
 
-				if (curvekey == CData->curve_firstkey[curve]) {
+				if(curvekey == CData->curve_firstkey[curve]) {
 					v1 = CData->curvekey_co[curvekey+2] - CData->curvekey_co[curvekey+1];
 					v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
 				}
-				else if (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) {
+				else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) {
 					v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
 					v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[curvekey-2];
 				}
@@ -467,12 +462,12 @@ void ExportCurveTriangleRibbons(Mesh *mesh, ParticleCurveData *CData, int interp
 				float3 v2;
 				float3 xbasis;
 
-				if (curvekey == CData->curve_firstkey[curve]) {
+				if(curvekey == CData->curve_firstkey[curve]) {
 					subv = 0;
 					v1 = CData->curvekey_co[curvekey+2] - CData->curvekey_co[curvekey+1];
 					v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
 				}
-				else if (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) {
+				else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) {
 					v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
 					v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[curvekey-2];
 				}
@@ -502,10 +497,10 @@ void ExportCurveTriangleRibbons(Mesh *mesh, ParticleCurveData *CData, int interp
 
 					float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
 
-					if (CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
+					if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
 						radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);
 
-					if ((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) && (subv == segments))
+					if((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) && (subv == segments))
 						radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.95f);
 
 					float3 ickey_loc_shfl = ickey_loc - radius * xbasis;
@@ -522,7 +517,7 @@ void ExportCurveTriangleRibbons(Mesh *mesh, ParticleCurveData *CData, int interp
 		}
 	}
 
-	mesh->reserve(mesh->verts.size(), mesh->triangles.size());
+	mesh->reserve(mesh->verts.size(), mesh->triangles.size(), 0, 0);
 	mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
 	mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
 	mesh->add_face_normals();
@@ -553,11 +548,11 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int inter
 				float3 v1;
 				float3 v2;
 
-				if (curvekey == CData->curve_firstkey[curve]) {
+				if(curvekey == CData->curve_firstkey[curve]) {
 					v1 = CData->curvekey_co[curvekey+2] - CData->curvekey_co[curvekey+1];
 					v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
 				}
-				else if (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) {
+				else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) {
 					v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
 					v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[curvekey-2];
 				}
@@ -582,12 +577,12 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int inter
 				float3 v1;
 				float3 v2;
 
-				if (curvekey == CData->curve_firstkey[curve]) {
+				if(curvekey == CData->curve_firstkey[curve]) {
 					subv = 0;
 					v1 = CData->curvekey_co[curvekey+2] - CData->curvekey_co[curvekey+1];
 					v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
 				}
-				else if (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) {
+				else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) {
 					v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
 					v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[curvekey-2];
 				}
@@ -619,10 +614,10 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int inter
 
 					float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
 
-					if (CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
+					if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
 						radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);
 
-					if ((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) && (subv == segments))
+					if((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) && (subv == segments))
 						radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.95f);
 
 					float angle = 2 * M_PI_F / (float)resolution;
@@ -645,7 +640,7 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int inter
 		}
 	}
 
-	mesh->reserve(mesh->verts.size(), mesh->triangles.size());
+	mesh->reserve(mesh->verts.size(), mesh->triangles.size(), 0, 0);
 	mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
 	mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
 	mesh->add_face_normals();
@@ -661,9 +656,12 @@ void ExportCurveSegments(Mesh *mesh, ParticleCurveData *CData, int interpolation
 	int curs = 0;
 	int segs = 0;
 
-	if(!(mesh->curve_segs.empty() && mesh->curve_keys.empty() && mesh->curve_attrib.empty()))
+	if(!(mesh->curve_segments.empty() && mesh->curve_keys.empty()))
 		return;
 
+	Attribute *attr_uv = mesh->curve_attributes.add(ATTR_STD_UV);
+	Attribute *attr_intercept = mesh->curve_attributes.add(ATTR_STD_CURVE_INTERCEPT);
+
 	for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
 
 		if(CData->psys_curvenum[sys] == 0)
@@ -677,7 +675,7 @@ void ExportCurveSegments(Mesh *mesh, ParticleCurveData *CData, int interpolation
 			for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
 
 				int subv = 1;
-				if (curvekey == CData->curve_firstkey[curve])
+				if(curvekey == CData->curve_firstkey[curve])
 					subv = 0;
 
 				for (; subv <= segments; subv++) {
@@ -685,20 +683,22 @@ void ExportCurveSegments(Mesh *mesh, ParticleCurveData *CData, int interpolation
 					float3 ickey_loc = make_float3(0.0f,0.0f,0.0f);
 					float time = 0.0f;
 
-					if ((interpolation == CURVE_BSPLINE) && (curvekey == CData->curve_firstkey[curve]) && (subv == 0))
+					if((interpolation == CURVE_BSPLINE) && (curvekey == CData->curve_firstkey[curve]) && (subv == 0))
 						ickey_loc = CData->curvekey_co[curvekey];
 					else
 						InterpolateKeySegments(subv, segments, curvekey, curve, &ickey_loc, &time, CData , interpolation);
 
 					float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
 
-					if (CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
+					if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
 						radius =0.0f;
 
-					mesh->add_curvekey(ickey_loc, radius, time);
+					mesh->add_curve_key(ickey_loc, radius);
+					attr_intercept->add(time);
 
 					if(subv != 0) {
-						mesh->add_curve(cks - 1, cks, CData->psys_shader[sys], curs);
+						attr_uv->add(CData->curve_uv[curve]);
+						mesh->add_curve_segment(cks - 1, cks, CData->psys_shader[sys], curs);
 						segs++;
 					}
 
@@ -706,18 +706,17 @@ void ExportCurveSegments(Mesh *mesh, ParticleCurveData *CData, int interpolation
 				}
 			}
 
-			mesh->add_curveattrib(CData->curve_u[curve], CData->curve_v[curve]);
 			curs++;
 
 		}
 	}
 
 	/* check allocation*/
-	if((mesh->curve_keys.size() !=  cks) || (mesh->curve_segs.size() !=  segs) || (mesh->curve_attrib.size() != curs)) {
+	if((mesh->curve_keys.size() !=  cks) || (mesh->curve_segments.size() !=  segs)) {
 		/* allocation failed -> clear data */
 		mesh->curve_keys.clear();
-		mesh->curve_segs.clear();
-		mesh->curve_attrib.clear();
+		mesh->curve_segments.clear();
+		mesh->curve_attributes.clear();
 	}
 }
 
@@ -734,7 +733,7 @@ void BlenderSync::sync_curve_settings()
 
 	curve_system_manager->use_curves = get_boolean(csscene, "use_curves");
 
-	if (preset == CURVE_CUSTOM) {
+	if(preset == CURVE_CUSTOM) {
 		/*custom properties*/
 		curve_system_manager->primitive = get_enum(csscene, "primitive");
 		curve_system_manager->line_method = get_enum(csscene, "line_method");
@@ -824,15 +823,18 @@ void BlenderSync::sync_curve_settings()
 void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool object_updated)
 {
 	/* Clear stored curve data */
-	mesh->curve_attrib.clear();
 	mesh->curve_keys.clear();
-	mesh->curve_keysCD.clear();
-	mesh->curve_segs.clear();
+	mesh->curve_segments.clear();
+	mesh->curve_attributes.clear();
 
 	/* obtain general settings */
 	bool use_curves = scene->curve_system_manager->use_curves;
 
-	if(use_curves && b_ob.mode() == b_ob.mode_OBJECT) {
+	if(!(use_curves && b_ob.mode() == b_ob.mode_OBJECT)) {
+		mesh->compute_bounds();
+		return;
+	}
+
 	int primitive = scene->curve_system_manager->primitive;
 	int interpolation = scene->curve_system_manager->interpolation;
 	int triangle_method = scene->curve_system_manager->triangle_method;
@@ -845,12 +847,12 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool
 
 	/* extract particle hair data - should be combined with connecting to mesh later*/
 
-	ParticleCurveData *CData = new ParticleCurveData();
+	ParticleCurveData CData;
 
-	if (use_cache)
-		ObtainCacheParticleData(mesh, &b_mesh, &b_ob, CData, use_parents);
+	if(use_cache)
+		ObtainCacheParticleData(mesh, &b_mesh, &b_ob, &CData, use_parents);
 	else
-		ObtainParticleData(mesh, &b_mesh, &b_ob, CData);
+		ObtainParticleData(mesh, &b_mesh, &b_ob, &CData);
 
 	/* attach strands to mesh */
 	BL::Object b_CamOb = b_scene.camera();
@@ -862,37 +864,33 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool
 		RotCam = transform_point(&itfm, make_float3(ctfm.x.w, ctfm.y.w, ctfm.z.w));
 	}
 
-	if (primitive == CURVE_TRIANGLES){
-		if (triangle_method == CURVE_CAMERA)
-			ExportCurveTrianglePlanes(mesh, CData, interpolation, use_smooth, segments, RotCam);
-		else if (triangle_method == CURVE_RIBBONS)
-			ExportCurveTriangleRibbons(mesh, CData, interpolation, use_smooth, segments);
+	if(primitive == CURVE_TRIANGLES){
+		if(triangle_method == CURVE_CAMERA)
+			ExportCurveTrianglePlanes(mesh, &CData, interpolation, use_smooth, segments, RotCam);
+		else if(triangle_method == CURVE_RIBBONS)
+			ExportCurveTriangleRibbons(mesh, &CData, interpolation, use_smooth, segments);
 		else
-			ExportCurveTriangleGeometry(mesh, CData, interpolation, use_smooth, resolution, segments);
+			ExportCurveTriangleGeometry(mesh, &CData, interpolation, use_smooth, resolution, segments);
 	}
 	else {
-		ExportCurveSegments(mesh, CData, interpolation, segments);
+		ExportCurveSegments(mesh, &CData, interpolation, segments);
 		int ckey_num = mesh->curve_keys.size();
 
 		/*export tangents or curve data? - not functional yet*/
-		if (export_tgs && ckey_num > 1) {
+		if(export_tgs && ckey_num > 1) {
+			Attribute *attr_tangent = mesh->curve_attributes.add(ATTR_STD_CURVE_TANGENT);
+			float3 *data_tangent = attr_tangent->data_float3();
 			
 			for(int ck = 0; ck < ckey_num; ck++) {
-				Mesh::CurveData SCD;
-				SCD.tg = normalize(normalize(mesh->curve_keys[min(ck + 1, ckey_num - 1)].loc - mesh->curve_keys[ck].loc) -
-					normalize(mesh->curve_keys[max(ck - 1, 0)].loc - mesh->curve_keys[ck].loc));
-				mesh->curve_keysCD.push_back(SCD);
+				float3 tg = normalize(normalize(mesh->curve_keys[min(ck + 1, ckey_num - 1)].co - mesh->curve_keys[ck].co) -
+					normalize(mesh->curve_keys[max(ck - 1, 0)].co - mesh->curve_keys[ck].co));
+				
+				data_tangent[ck] = tg;
 			}
 		}
 	}
 
-
-	delete CData;
-
-	}
-
 	mesh->compute_bounds();
-
 }
 
 
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index a01b2e9ee38..86f996320cb 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -147,7 +147,7 @@ static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_la
 	if(active_render)
 		attr = mesh->attributes.add(ATTR_STD_UV_TANGENT, name);
 	else
-		attr = mesh->attributes.add(name, TypeDesc::TypeVector, Attribute::CORNER);
+		attr = mesh->attributes.add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER);
 
 	float3 *tangent = attr->data_float3();
 
@@ -161,7 +161,7 @@ static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_la
 		if(active_render)
 			attr_sign = mesh->attributes.add(ATTR_STD_UV_TANGENT_SIGN, name_sign);
 		else
-			attr_sign = mesh->attributes.add(name_sign, TypeDesc::TypeFloat, Attribute::CORNER);
+			attr_sign = mesh->attributes.add(name_sign, TypeDesc::TypeFloat, ATTR_ELEMENT_CORNER);
 
 		tangent_sign = attr_sign->data_float();
 	}
@@ -249,7 +249,7 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
 				continue;
 
 			Attribute *attr = mesh->attributes.add(
-				ustring(l->name().c_str()), TypeDesc::TypeColor, Attribute::CORNER);
+				ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER);
 
 			BL::MeshColorLayer::data_iterator c;
 			float3 *fdata = attr->data_float3();
@@ -288,7 +288,7 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
 				if(active_render)
 					attr = mesh->attributes.add(std, name);
 				else
-					attr = mesh->attributes.add(name, TypeDesc::TypePoint, Attribute::CORNER);
+					attr = mesh->attributes.add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER);
 
 				BL::MeshTextureFaceLayer::data_iterator t;
 				float3 *fdata = attr->data_float3();
diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp
index 102414e4a3d..0b43704b7b8 100644
--- a/intern/cycles/bvh/bvh.cpp
+++ b/intern/cycles/bvh/bvh.cpp
@@ -76,9 +76,7 @@ bool BVH::cache_read(CacheData& key)
 		key.add(ob->mesh->verts);
 		key.add(ob->mesh->triangles);
 		key.add(ob->mesh->curve_keys);
-		key.add(ob->mesh->curve_keysCD);
-		key.add(ob->mesh->curve_segs);
-		key.add(ob->mesh->curve_attrib);
+		key.add(ob->mesh->curve_segments);
 		key.add(&ob->bounds, sizeof(ob->bounds));
 		key.add(&ob->visibility, sizeof(ob->visibility));
 		key.add(&ob->mesh->transform_applied, sizeof(bool));
@@ -278,34 +276,33 @@ void BVH::pack_curve_seg(int idx, float4 woop[3])
 	int tob = pack.prim_object[idx];
 	const Mesh *mesh = objects[tob]->mesh;
 	int tidx = pack.prim_index[idx];
-	float3 v0 = mesh->curve_keys[mesh->curve_segs[tidx].v[0]].loc;
-	float3 v1 = mesh->curve_keys[mesh->curve_segs[tidx].v[1]].loc;
-	float t0 = mesh->curve_keys[mesh->curve_segs[tidx].v[0]].time;
-	float t1 = mesh->curve_keys[mesh->curve_segs[tidx].v[1]].time;
+	float3 v0 = mesh->curve_keys[mesh->curve_segments[tidx].v[0]].co;
+	float3 v1 = mesh->curve_keys[mesh->curve_segments[tidx].v[1]].co;
 
 	float3 d0 = v1 - v0;
 	float l =  len(d0);
 	
-	float u = mesh->curve_attrib[mesh->curve_segs[tidx].curve].uv[0];
-	float v = mesh->curve_attrib[mesh->curve_segs[tidx].curve].uv[1];
-
 	/*Plan
 	*Transform tfm = make_transform(
 	*	location <3>    , l,
 	*	extra curve data <3>    , StrID,
-	*	nextkey, flags/tip?,    r, t);
+	*	nextkey, flags/tip?,    0, 0);
 	*/
-	float3 tg1 = make_float3(1.0f,0.0f,0.0f);
-	float3 tg2 = make_float3(1.0f,0.0f,0.0f);
-	if(mesh->curve_keysCD.size()) {
-		tg1 = mesh->curve_keysCD[mesh->curve_segs[tidx].v[0]].tg;
-		tg2 = mesh->curve_keysCD[mesh->curve_segs[tidx].v[1]].tg;
+	Attribute *attr_tangent = mesh->curve_attributes.find(ATTR_STD_CURVE_TANGENT);
+	float3 tg1 = make_float3(1.0f, 0.0f, 0.0f);
+	float3 tg2 = make_float3(1.0f, 0.0f, 0.0f);
+
+	if(attr_tangent) {
+		const float3 *data_tangent = attr_tangent->data_float3();
+
+		tg1 = data_tangent[mesh->curve_segments[tidx].v[0]];
+		tg2 = data_tangent[mesh->curve_segments[tidx].v[1]];
 	}
 	
 	Transform tfm = make_transform(
 		tg1.x, tg1.y, tg1.z, l,
 		tg2.x, tg2.y, tg2.z, 0,
-		t0, t1, u, v,
+		0, 0, 0, 0,
 		0, 0, 0, 1);
 
 	woop[0] = tfm.x;
@@ -628,10 +625,10 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility
 				if(pack.prim_type[prim]) {
 					/* strands */
 					int str_offset = (params.top_level)? mesh->curveseg_offset: 0;
-					const int *hidx = mesh->curve_segs[pidx - str_offset].v;
+					const int *hidx = mesh->curve_segments[pidx - str_offset].v;
 
-					bbox.grow(mesh->curve_keys[hidx[0]].loc, mesh->curve_keys[hidx[0]].radius);
-					bbox.grow(mesh->curve_keys[hidx[1]].loc, mesh->curve_keys[hidx[1]].radius);
+					bbox.grow(mesh->curve_keys[hidx[0]].co, mesh->curve_keys[hidx[0]].radius);
+					bbox.grow(mesh->curve_keys[hidx[1]].co, mesh->curve_keys[hidx[1]].radius);
 				}
 				else {
 					/* triangles */
diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp
index cdd94324f53..665c783b2d8 100644
--- a/intern/cycles/bvh/bvh_build.cpp
+++ b/intern/cycles/bvh/bvh_build.cpp
@@ -85,12 +85,12 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh,
 		}
 	}
 
-	for(uint j = 0; j < mesh->curve_segs.size(); j++) {
-		Mesh::CurveSeg s = mesh->curve_segs[j];
+	for(uint j = 0; j < mesh->curve_segments.size(); j++) {
+		Mesh::CurveSegment s = mesh->curve_segments[j];
 		BoundBox bounds = BoundBox::empty;
 
 		for(int k = 0; k < 2; k++) {
-			float3 pt = mesh->curve_keys[s.v[k]].loc;
+			float3 pt = mesh->curve_keys[s.v[k]].co;
 			bounds.grow(pt, mesh->curve_keys[s.v[k]].radius);
 		}
 
@@ -118,14 +118,14 @@ void BVHBuild::add_references(BVHRange& root)
 		if(params.top_level) {
 			if(ob->mesh->transform_applied) {
 				num_alloc_references += ob->mesh->triangles.size();
-				num_alloc_references += ob->mesh->curve_segs.size();
+				num_alloc_references += ob->mesh->curve_segments.size();
 			}
 			else
 				num_alloc_references++;
 		}
 		else {
 			num_alloc_references += ob->mesh->triangles.size();
-			num_alloc_references += ob->mesh->curve_segs.size();
+			num_alloc_references += ob->mesh->curve_segments.size();
 		}
 	}
 
diff --git a/intern/cycles/bvh/bvh_split.cpp b/intern/cycles/bvh/bvh_split.cpp
index 860e2c8d7df..67fdfd77657 100644
--- a/intern/cycles/bvh/bvh_split.cpp
+++ b/intern/cycles/bvh/bvh_split.cpp
@@ -283,9 +283,9 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH
 	else {
 		/* Strand split: NOTE - Currently ignores strand width and needs to be fixed.*/
 
-		const int *inds = mesh->curve_segs[ref.prim_index()].v;
-		const float3* v0 = &mesh->curve_keys[inds[0]].loc;
-		const float3* v1 = &mesh->curve_keys[inds[1]].loc;
+		const int *inds = mesh->curve_segments[ref.prim_index()].v;
+		const float3* v0 = &mesh->curve_keys[inds[0]].co;
+		const float3* v1 = &mesh->curve_keys[inds[1]].co;
 
 		float v0p = (*v0)[dim];
 		float v1p = (*v1)[dim];
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index fde881c0a06..6d5b9a063a0 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -20,12 +20,12 @@ set(SRC
 set(SRC_HEADERS
 	kernel.h
 	kernel_accumulate.h
-	kernel_attribute.h
 	kernel_bvh.h
 	kernel_camera.h
 	kernel_compat_cpu.h
 	kernel_compat_cuda.h
 	kernel_compat_opencl.h
+	kernel_curve.h
 	kernel_differential.h
 	kernel_displace.h
 	kernel_emission.h
@@ -37,6 +37,7 @@ set(SRC_HEADERS
 	kernel_object.h
 	kernel_passes.h
 	kernel_path.h
+	kernel_primitive.h
 	kernel_projection.h
 	kernel_random.h
 	kernel_shader.h
diff --git a/intern/cycles/kernel/kernel_attribute.h b/intern/cycles/kernel/kernel_attribute.h
deleted file mode 100644
index b7ad731c883..00000000000
--- a/intern/cycles/kernel/kernel_attribute.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2011, 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.
- */
-
-#ifndef __KERNEL_ATTRIBUTE_CL__
-#define __KERNEL_ATTRIBUTE_CL__
-
-CCL_NAMESPACE_BEGIN
-
-/* note: declared in kernel.h, have to add it here because kernel.h is not available */
-bool kernel_osl_use(KernelGlobals *kg);
-
-__device_inline int find_attribute(KernelGlobals *kg, ShaderData *sd, uint id)
-{
-#ifdef __OSL__
-	if (kg->osl) {
-		return OSLShader::find_attribute(kg, sd, id);
-	}
-	else
-#endif
-	{
-		/* for SVM, find attribute by unique id */
-		uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
-		uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
-		
-		while(attr_map.x != id)
-			attr_map = kernel_tex_fetch(__attributes_map, ++attr_offset);
-		
-		/* return result */
-		return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z;
-	}
-}
-
-CCL_NAMESPACE_END
-
-#endif /* __KERNEL_ATTRIBUTE_CL__ */
diff --git a/intern/cycles/kernel/kernel_bvh.h b/intern/cycles/kernel/kernel_bvh.h
index 15af35a05f8..d32287f91e8 100644
--- a/intern/cycles/kernel/kernel_bvh.h
+++ b/intern/cycles/kernel/kernel_bvh.h
@@ -214,13 +214,13 @@ __device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect,
 	int flags = kernel_data.curve_kernel_data.curveflags;
 
 	int prim = kernel_tex_fetch(__prim_index, triAddr);
-	float4 v00 = kernel_tex_fetch(__cur_segs, prim);
+	float4 v00 = kernel_tex_fetch(__curve_segments, prim);
 
 	int v1 = __float_as_int(v00.x);
 	int v2 = __float_as_int(v00.y);
 
-	float4 P1 = kernel_tex_fetch(__cur_keys, v1);
-	float4 P2 = kernel_tex_fetch(__cur_keys, v2);
+	float4 P1 = kernel_tex_fetch(__curve_keys, v1);
+	float4 P2 = kernel_tex_fetch(__curve_keys, v2);
 
 	float l = v00.w;
 	float r1 = P1.w;
@@ -720,13 +720,13 @@ __device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, const
 	}
 
 	int prim = kernel_tex_fetch(__prim_index, isect->prim);
-	float4 v00 = kernel_tex_fetch(__cur_segs, prim);
+	float4 v00 = kernel_tex_fetch(__curve_segments, prim);
 
 	int v1 = __float_as_int(v00.x);
 	int v2 = __float_as_int(v00.y);
 
-	float4 P1 = kernel_tex_fetch(__cur_keys, v1);
-	float4 P2 = kernel_tex_fetch(__cur_keys, v2);
+	float4 P1 = kernel_tex_fetch(__curve_keys, v1);
+	float4 P2 = kernel_tex_fetch(__curve_keys, v2);
 	float l = v00.w;
 	float r1 = P1.w;
 	float r2 = P2.w;
diff --git a/intern/cycles/kernel/kernel_curve.h b/intern/cycles/kernel/kernel_curve.h
new file mode 100644
index 00000000000..fef1a48644d
--- /dev/null
+++ b/intern/cycles/kernel/kernel_curve.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2011, 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.
+ */
+
+CCL_NAMESPACE_BEGIN
+
+#ifdef __HAIR__
+
+/* curve attributes */
+
+__device float curve_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
+{
+	if(elem == ATTR_ELEMENT_CURVE_SEGMENT) {
+#ifdef __RAY_DIFFERENTIALS__
+		if(dx) *dx = 0.0f;
+		if(dy) *dy = 0.0f;
+#endif
+
+		return kernel_tex_fetch(__attributes_float, offset + sd->curve_seg);
+	}
+	else if(elem == ATTR_ELEMENT_CURVE_KEY) {
+		float4 segment = kernel_tex_fetch(__curve_segments, sd->curve_seg);
+
+		float f0 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(segment.x));
+		float f1 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(segment.y));
+
+#ifdef __RAY_DIFFERENTIALS__
+		if(dx) *dx = sd->du.dx*(f1 - f0);
+		if(dy) *dy = 0.0f;
+#endif
+
+		return (1.0f - sd->u)*f0 + sd->u*f1;
+	}
+	else {
+#ifdef __RAY_DIFFERENTIALS__
+		if(dx) *dx = 0.0f;
+		if(dy) *dy = 0.0f;
+#endif
+
+		return 0.0f;
+	}
+}
+
+__device float3 curve_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
+{
+	if(elem == ATTR_ELEMENT_CURVE_SEGMENT) {
+		/* idea: we can't derive any useful differentials here, but for tiled
+		 * mipmap image caching it would be useful to avoid reading the highest
+		 * detail level always. maybe a derivative based on the hair density
+		 * could be computed somehow? */
+#ifdef __RAY_DIFFERENTIALS__
+		if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
+		if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
+#endif
+
+		return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + sd->curve_seg));
+	}
+	else if(elem == ATTR_ELEMENT_CURVE_KEY) {
+		float4 segment = kernel_tex_fetch(__curve_segments, sd->curve_seg);
+
+		float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(segment.x)));
+		float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(segment.y)));
+
+#ifdef __RAY_DIFFERENTIALS__
+		if(dx) *dx = sd->du.dx*(f1 - f0);
+		if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
+#endif
+
+		return (1.0f - sd->u)*f0 + sd->u*f1;
+	}
+	else {
+#ifdef __RAY_DIFFERENTIALS__
+		if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
+		if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
+#endif
+
+		return make_float3(0.0f, 0.0f, 0.0f);
+	}
+}
+
+/* hair info node functions */
+
+__device float curve_thickness(KernelGlobals *kg, ShaderData *sd)
+{
+	int prim = sd->curve_seg;
+	float u = sd->u;
+	float r = 0.0f;
+
+	if(prim != -1) {
+		float4 v00 = kernel_tex_fetch(__curve_segments, prim);
+
+		int v1 = __float_as_int(v00.x);
+		int v2 = __float_as_int(v00.y);
+
+		float4 P1 = kernel_tex_fetch(__curve_keys, v1);
+		float4 P2 = kernel_tex_fetch(__curve_keys, v2);
+		r = (P2.w - P1.w) * u + P1.w;
+	}
+
+	return r*2.0f;
+}
+
+__device float3 curve_tangent_normal(KernelGlobals *kg, ShaderData *sd)
+{	
+	float3 tgN = make_float3(0.0f,0.0f,0.0f);
+
+	if(sd->curve_seg != ~0) {
+		float normalmix = kernel_data.curve_kernel_data.normalmix;
+
+		tgN = -(-sd->I - sd->dPdu * (dot(sd->dPdu,-sd->I) * normalmix / len_squared(sd->dPdu)));
+		tgN = normalize(tgN);
+
+		/* need to find suitable scaled gd for corrected normal */
+#if 0
+		if (kernel_data.curve_kernel_data.use_tangent_normal_correction)
+			tgN = normalize(tgN - gd * sd->dPdu);
+#endif
+	}
+
+	return tgN;
+}
+
+#endif
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h
index 0f74ab75dd4..09ee1f68e12 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -333,14 +333,14 @@ __device void curve_seg_light_sample(KernelGlobals *kg, int prim, int object,
 	float randu, float randv, float time, LightSample *ls)
 {
 	/* this strand code needs completion */
-	float4 v00 = kernel_tex_fetch(__cur_segs, prim);
+	float4 v00 = kernel_tex_fetch(__curve_segments, prim);
 
 	int v1 = __float_as_int(v00.x);
 	int v2 = __float_as_int(v00.y);
 	float l = v00.w;
 
-	float4 P1 = kernel_tex_fetch(__cur_keys, v1);
-	float4 P2 = kernel_tex_fetch(__cur_keys, v2);
+	float4 P1 = kernel_tex_fetch(__curve_keys, v1);
+	float4 P2 = kernel_tex_fetch(__curve_keys, v2);
 	float r1 = P1.w;
 	float r2 = P2.w;
 	float3 tg = float4_to_float3(P2 - P1) / l;
diff --git a/intern/cycles/kernel/kernel_object.h b/intern/cycles/kernel/kernel_object.h
index 2260094aa70..40aa4753daa 100644
--- a/intern/cycles/kernel/kernel_object.h
+++ b/intern/cycles/kernel/kernel_object.h
@@ -288,55 +288,5 @@ __device float3 particle_angular_velocity(KernelGlobals *kg, int particle)
 	return make_float3(f3.z, f3.w, f4.x);
 }
 
-#ifdef __HAIR__
-/* Hair Info Node fns */
-
-__device float hair_radius(KernelGlobals *kg, int prim, float u)
-{	
-	float r = 0.0f;
-
-	if (prim != -1) {
-		float4 v00 = kernel_tex_fetch(__cur_segs, prim);
-
-		int v1 = __float_as_int(v00.x);
-		int v2 = __float_as_int(v00.y);
-
-		float4 P1 = kernel_tex_fetch(__cur_keys, v1);
-		float4 P2 = kernel_tex_fetch(__cur_keys, v2);
-		r = (P2.w - P1.w) * u + P1.w;
-	}
-
-	return r;
-}
-
-__device float3 hair_tangent_normal(KernelGlobals *kg, ShaderData *sd)
-{	
-	float3 tgN = make_float3(0.0f,0.0f,0.0f);
-
-	if (sd->curve_seg != ~0) {
-		tgN = -(-sd->I - sd->dPdu * (dot(sd->dPdu,-sd->I) * kernel_data.curve_kernel_data.normalmix / len_squared(sd->dPdu)));
-		tgN = normalize(tgN);
-		/*if (kernel_data.curve_kernel_data.use_tangent_normal_correction) need to find suitable scaled gd for corrected normal
-		{
-			tgN = normalize(tgN - gd * sd->dPdu);
-		}*/
-	}
-
-	return tgN;
-}
-
-__device float intercept(KernelGlobals *kg, int prim, int triAddr, float u)
-{	
-	float t = 0.0f;
-
-	if (prim != -1) {
-		float4 sd2 = kernel_tex_fetch(__tri_woop, triAddr*3+2);
-		t = (sd2.y - sd2.x) * u + sd2.x;
-	}
-
-	return t;
-}
-#endif
-
 CCL_NAMESPACE_END
 
diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h
index 7f8b611ba14..727639386ed 100644
--- a/intern/cycles/kernel/kernel_passes.h
+++ b/intern/cycles/kernel/kernel_passes.h
@@ -70,11 +70,11 @@ __device_inline void kernel_write_data_passes(KernelGlobals *kg, __global float
 			kernel_write_pass_float3(buffer + kernel_data.film.pass_normal, sample, normal);
 		}
 		if(flag & PASS_UV) {
-			float3 uv = triangle_uv(kg, sd);
+			float3 uv = primitive_uv(kg, sd);
 			kernel_write_pass_float3(buffer + kernel_data.film.pass_uv, sample, uv);
 		}
 		if(flag & PASS_MOTION) {
-			float4 speed = triangle_motion_vector(kg, sd);
+			float4 speed = primitive_motion_vector(kg, sd);
 			kernel_write_pass_float4(buffer + kernel_data.film.pass_motion, sample, speed);
 			kernel_write_pass_float(buffer + kernel_data.film.pass_motion_weight, sample, 1.0f);
 		}
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index 8da21751cbe..20feaf50a2e 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -24,9 +24,10 @@
 #include "kernel_montecarlo.h"
 #include "kernel_projection.h"
 #include "kernel_object.h"
-#include "kernel_attribute.h"
-#include "kernel_projection.h"
 #include "kernel_triangle.h"
+#include "kernel_curve.h"
+#include "kernel_primitive.h"
+#include "kernel_projection.h"
 #ifdef __QBVH__
 #include "kernel_qbvh.h"
 #else
diff --git a/intern/cycles/kernel/kernel_primitive.h b/intern/cycles/kernel/kernel_primitive.h
new file mode 100644
index 00000000000..2296017c686
--- /dev/null
+++ b/intern/cycles/kernel/kernel_primitive.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2011, 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.
+ */
+
+#ifndef __KERNEL_ATTRIBUTE_CL__
+#define __KERNEL_ATTRIBUTE_CL__
+
+CCL_NAMESPACE_BEGIN
+
+/* attribute lookup */
+
+__device_inline int find_attribute(KernelGlobals *kg, ShaderData *sd, uint id, AttributeElement *elem)
+{
+	if(sd->object == ~0)
+		return (int)ATTR_STD_NOT_FOUND;
+
+#ifdef __OSL__
+	if (kg->osl) {
+		return OSLShader::find_attribute(kg, sd, id, elem);
+	}
+	else
+#endif
+	{
+		/* for SVM, find attribute by unique id */
+		uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
+		attr_offset = (sd->curve_seg == ~0)? attr_offset: attr_offset + ATTR_PRIM_CURVE;
+		uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
+		
+		while(attr_map.x != id) {
+			attr_offset += ATTR_PRIM_TYPES;
+			attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
+		}
+
+		*elem = (AttributeElement)attr_map.y;
+		
+		/* return result */
+		return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z;
+	}
+}
+
+__device float primitive_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
+{
+#ifdef __HAIR__
+	if(sd->curve_seg == ~0)
+#endif
+		return triangle_attribute_float(kg, sd, elem, offset, dx, dy);
+#ifdef __HAIR__
+	else
+		return curve_attribute_float(kg, sd, elem, offset, dx, dy);
+#endif
+}
+
+__device float3 primitive_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
+{
+#ifdef __HAIR__
+	if(sd->curve_seg == ~0)
+#endif
+		return triangle_attribute_float3(kg, sd, elem, offset, dx, dy);
+#ifdef __HAIR__
+	else
+		return curve_attribute_float3(kg, sd, elem, offset, dx, dy);
+#endif
+}
+
+__device float3 primitive_uv(KernelGlobals *kg, ShaderData *sd)
+{
+	AttributeElement elem_uv;
+	int offset_uv = find_attribute(kg, sd, ATTR_STD_UV, &elem_uv);
+
+	if(offset_uv == ATTR_STD_NOT_FOUND)
+		return make_float3(0.0f, 0.0f, 0.0f);
+
+	float3 uv = primitive_attribute_float3(kg, sd, elem_uv, offset_uv, NULL, NULL);
+	uv.z = 1.0f;
+	return uv;
+}
+
+__device float3 primitive_tangent(KernelGlobals *kg, ShaderData *sd)
+{
+#ifdef __HAIR__
+	if(sd->curve_seg != ~0)
+		return normalize(sd->dPdu);
+#endif
+
+	/* try to create spherical tangent from generated coordinates */
+	AttributeElement attr_elem;
+	int attr_offset = find_attribute(kg, sd, ATTR_STD_GENERATED, &attr_elem);
+
+	if(attr_offset != ATTR_STD_NOT_FOUND) {
+		float3 data = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL);
+		data = make_float3(-(data.y - 0.5f), (data.x - 0.5f), 0.0f);
+		object_normal_transform(kg, sd, &data);
+		return cross(sd->N, normalize(cross(data, sd->N)));;
+	}
+	else {
+		/* otherwise use surface derivatives */
+		return normalize(sd->dPdu);
+	}
+}
+
+/* motion */
+
+__device float4 primitive_motion_vector(KernelGlobals *kg, ShaderData *sd)
+{
+	float3 motion_pre = sd->P, motion_post = sd->P;
+
+	/* deformation motion */
+	AttributeElement elem_pre, elem_post;
+	int offset_pre = find_attribute(kg, sd, ATTR_STD_MOTION_PRE, &elem_pre);
+	int offset_post = find_attribute(kg, sd, ATTR_STD_MOTION_POST, &elem_post);
+
+	if(offset_pre != ATTR_STD_NOT_FOUND)
+		motion_pre = primitive_attribute_float3(kg, sd, elem_pre, offset_pre, NULL, NULL);
+	if(offset_post != ATTR_STD_NOT_FOUND)
+		motion_post = primitive_attribute_float3(kg, sd, elem_post, offset_post, NULL, NULL);
+
+	/* object motion. note that depending on the mesh having motion vectors, this
+	 * transformation was set match the world/object space of motion_pre/post */
+	Transform tfm;
+	
+	tfm = object_fetch_vector_transform(kg, sd->object, OBJECT_VECTOR_MOTION_PRE);
+	motion_pre = transform_point(&tfm, motion_pre);
+
+	tfm = object_fetch_vector_transform(kg, sd->object, OBJECT_VECTOR_MOTION_POST);
+	motion_post = transform_point(&tfm, motion_post);
+
+	float3 P;
+
+	/* camera motion, for perspective/orthographic motion.pre/post will be a
+	 * world-to-raster matrix, for panorama it's world-to-camera */
+	if (kernel_data.cam.type != CAMERA_PANORAMA) {
+		tfm = kernel_data.cam.worldtoraster;
+		P = transform_perspective(&tfm, sd->P);
+
+		tfm = kernel_data.cam.motion.pre;
+		motion_pre = transform_perspective(&tfm, motion_pre);
+
+		tfm = kernel_data.cam.motion.post;
+		motion_post = transform_perspective(&tfm, motion_post);
+	}
+	else {
+		tfm = kernel_data.cam.worldtocamera;
+		P = normalize(transform_point(&tfm, sd->P));
+		P = float2_to_float3(direction_to_panorama(kg, P));
+		P.x *= kernel_data.cam.width;
+		P.y *= kernel_data.cam.height;
+
+		tfm = kernel_data.cam.motion.pre;
+		motion_pre = normalize(transform_point(&tfm, motion_pre));
+		motion_pre = float2_to_float3(direction_to_panorama(kg, motion_pre));
+		motion_pre.x *= kernel_data.cam.width;
+		motion_pre.y *= kernel_data.cam.height;
+
+		tfm = kernel_data.cam.motion.post;
+		motion_post = normalize(transform_point(&tfm, motion_post));
+		motion_post = float2_to_float3(direction_to_panorama(kg, motion_post));
+		motion_post.x *= kernel_data.cam.width;
+		motion_post.y *= kernel_data.cam.height;
+	}
+
+	motion_pre = motion_pre - P;
+	motion_post = P - motion_post;
+
+	return make_float4(motion_pre.x, motion_pre.y, motion_post.x, motion_post.y);
+}
+
+CCL_NAMESPACE_END
+
+#endif /* __KERNEL_ATTRIBUTE_CL__ */
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index 652efa18b93..49bbc5a74ab 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -77,7 +77,7 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
 #ifdef __HAIR__
 	if(kernel_tex_fetch(__prim_type, isect->prim)) {
 		/* Strand Shader setting*/
-		float4 CurSeg = kernel_tex_fetch(__cur_segs, sd->prim);
+		float4 CurSeg = kernel_tex_fetch(__curve_segments, sd->prim);
 		sd->shader = __float_as_int(CurSeg.z);
 
 		sd->curve_seg = sd->prim;
@@ -788,7 +788,7 @@ __device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect)
 #ifdef __HAIR__
 	}
 	else {
-		float4 str = kernel_tex_fetch(__cur_segs, prim);
+		float4 str = kernel_tex_fetch(__curve_segments, prim);
 		shader = __float_as_int(str.z);
 	}
 #endif
diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h
index 0b6107b398e..072df21a188 100644
--- a/intern/cycles/kernel/kernel_textures.h
+++ b/intern/cycles/kernel/kernel_textures.h
@@ -44,8 +44,8 @@ KERNEL_TEX(float4, texture_float4, __tri_vindex)
 KERNEL_TEX(float4, texture_float4, __tri_verts)
 
 /* curves */
-KERNEL_TEX(float4, texture_float4, __cur_segs)
-KERNEL_TEX(float4, texture_float4, __cur_keys)
+KERNEL_TEX(float4, texture_float4, __curve_segments)
+KERNEL_TEX(float4, texture_float4, __curve_keys)
 
 /* attributes */
 KERNEL_TEX(uint4, texture_uint4, __attributes_map)
diff --git a/intern/cycles/kernel/kernel_triangle.h b/intern/cycles/kernel/kernel_triangle.h
index 1f2618d3507..d346137760f 100644
--- a/intern/cycles/kernel/kernel_triangle.h
+++ b/intern/cycles/kernel/kernel_triangle.h
@@ -106,195 +106,88 @@ __device_inline void triangle_dPdudv(KernelGlobals *kg, float3 *dPdu, float3 *dP
 
 __device float triangle_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
 {
-#ifdef __HAIR__
-	if(sd->curve_seg == ~0) {
+	if(elem == ATTR_ELEMENT_FACE) {
+		if(dx) *dx = 0.0f;
+		if(dy) *dy = 0.0f;
+
+		return kernel_tex_fetch(__attributes_float, offset + sd->prim);
+	}
+	else if(elem == ATTR_ELEMENT_VERTEX) {
+		float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, sd->prim));
+
+		float f0 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.x));
+		float f1 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.y));
+		float f2 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.z));
+
+#ifdef __RAY_DIFFERENTIALS__
+		if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
+		if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
 #endif
-		if(elem == ATTR_ELEMENT_FACE) {
-			if(dx) *dx = 0.0f;
-			if(dy) *dy = 0.0f;
-
-			return kernel_tex_fetch(__attributes_float, offset + sd->prim);
-		}
-		else if(elem == ATTR_ELEMENT_VERTEX) {
-			float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, sd->prim));
-
-			float f0 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.x));
-			float f1 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.y));
-			float f2 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.z));
-
-	#ifdef __RAY_DIFFERENTIALS__
-			if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
-			if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
-	#endif
-
-			return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
-		}
-		else if(elem == ATTR_ELEMENT_CORNER) {
-			int tri = offset + sd->prim*3;
-			float f0 = kernel_tex_fetch(__attributes_float, tri + 0);
-			float f1 = kernel_tex_fetch(__attributes_float, tri + 1);
-			float f2 = kernel_tex_fetch(__attributes_float, tri + 2);
-
-	#ifdef __RAY_DIFFERENTIALS__
-			if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
-			if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
-	#endif
-
-			return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
-		}
-		else {
-			if(dx) *dx = 0.0f;
-			if(dy) *dy = 0.0f;
-
-			return 0.0f;
-		}
-#ifdef __HAIR__
+
+		return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
+	}
+	else if(elem == ATTR_ELEMENT_CORNER) {
+		int tri = offset + sd->prim*3;
+		float f0 = kernel_tex_fetch(__attributes_float, tri + 0);
+		float f1 = kernel_tex_fetch(__attributes_float, tri + 1);
+		float f2 = kernel_tex_fetch(__attributes_float, tri + 2);
+
+#ifdef __RAY_DIFFERENTIALS__
+		if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
+		if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
+#endif
+
+		return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
 	}
 	else {
+		if(dx) *dx = 0.0f;
+		if(dy) *dy = 0.0f;
+
 		return 0.0f;
 	}
-#endif
 }
 
 __device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
 {
-#ifdef __HAIR__
-	if(sd->curve_seg == ~0) {
-#endif
-		if(elem == ATTR_ELEMENT_FACE) {
-			if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
-			if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
-
-			return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + sd->prim));
-		}
-		else if(elem == ATTR_ELEMENT_VERTEX) {
-			float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, sd->prim));
-
-			float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.x)));
-			float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.y)));
-			float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.z)));
-
-	#ifdef __RAY_DIFFERENTIALS__
-			if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
-			if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
-	#endif
-
-			return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
-		}
-		else if(elem == ATTR_ELEMENT_CORNER) {
-			int tri = offset + sd->prim*3;
-			float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 0));
-			float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1));
-			float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2));
-
-	#ifdef __RAY_DIFFERENTIALS__
-			if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
-			if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
-	#endif
-
-			return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
-		}
-		else {
-			if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
-			if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
-
-			return make_float3(0.0f, 0.0f, 0.0f);
-		}
-#ifdef __HAIR__
-	}
-	else
-	{
-		return make_float3(0.0f, 0.0f, 0.0f);
-	}
-#endif
-}
+	if(elem == ATTR_ELEMENT_FACE) {
+		if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
+		if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
 
-/* motion */
-
-__device float4 triangle_motion_vector(KernelGlobals *kg, ShaderData *sd)
-{
-	float3 motion_pre = sd->P, motion_post = sd->P;
+		return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + sd->prim));
+	}
+	else if(elem == ATTR_ELEMENT_VERTEX) {
+		float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, sd->prim));
 
-	/* deformation motion */
-	int offset_pre = find_attribute(kg, sd, ATTR_STD_MOTION_PRE);
-	int offset_post = find_attribute(kg, sd, ATTR_STD_MOTION_POST);
+		float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.x)));
+		float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.y)));
+		float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.z)));
 
-#ifdef __HAIR__
-	if(sd->curve_seg == ~0) {
+#ifdef __RAY_DIFFERENTIALS__
+		if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
+		if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
 #endif
-		if(offset_pre != ATTR_STD_NOT_FOUND)
-			motion_pre = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, offset_pre, NULL, NULL);
-		if(offset_post != ATTR_STD_NOT_FOUND)
-			motion_post = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, offset_post, NULL, NULL);
-#ifdef __HAIR__
+
+		return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
 	}
+	else if(elem == ATTR_ELEMENT_CORNER) {
+		int tri = offset + sd->prim*3;
+		float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 0));
+		float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1));
+		float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2));
+
+#ifdef __RAY_DIFFERENTIALS__
+		if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
+		if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
 #endif
 
-	/* object motion. note that depending on the mesh having motion vectors, this
-	 * transformation was set match the world/object space of motion_pre/post */
-	Transform tfm;
-	
-	tfm = object_fetch_vector_transform(kg, sd->object, OBJECT_VECTOR_MOTION_PRE);
-	motion_pre = transform_point(&tfm, motion_pre);
-
-	tfm = object_fetch_vector_transform(kg, sd->object, OBJECT_VECTOR_MOTION_POST);
-	motion_post = transform_point(&tfm, motion_post);
-
-	float3 P;
-
-	/* camera motion, for perspective/orthographic motion.pre/post will be a
-	 * world-to-raster matrix, for panorama it's world-to-camera */
-	if (kernel_data.cam.type != CAMERA_PANORAMA) {
-		tfm = kernel_data.cam.worldtoraster;
-		P = transform_perspective(&tfm, sd->P);
-
-		tfm = kernel_data.cam.motion.pre;
-		motion_pre = transform_perspective(&tfm, motion_pre);
-
-		tfm = kernel_data.cam.motion.post;
-		motion_post = transform_perspective(&tfm, motion_post);
+		return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
 	}
 	else {
-		tfm = kernel_data.cam.worldtocamera;
-		P = normalize(transform_point(&tfm, sd->P));
-		P = float2_to_float3(direction_to_panorama(kg, P));
-		P.x *= kernel_data.cam.width;
-		P.y *= kernel_data.cam.height;
-
-		tfm = kernel_data.cam.motion.pre;
-		motion_pre = normalize(transform_point(&tfm, motion_pre));
-		motion_pre = float2_to_float3(direction_to_panorama(kg, motion_pre));
-		motion_pre.x *= kernel_data.cam.width;
-		motion_pre.y *= kernel_data.cam.height;
-
-		tfm = kernel_data.cam.motion.post;
-		motion_post = normalize(transform_point(&tfm, motion_post));
-		motion_post = float2_to_float3(direction_to_panorama(kg, motion_post));
-		motion_post.x *= kernel_data.cam.width;
-		motion_post.y *= kernel_data.cam.height;
-	}
-
-	motion_pre = motion_pre - P;
-	motion_post = P - motion_post;
+		if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
+		if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
 
-	return make_float4(motion_pre.x, motion_pre.y, motion_post.x, motion_post.y);
-}
-
-__device float3 triangle_uv(KernelGlobals *kg, ShaderData *sd)
-{
-	int offset_uv = find_attribute(kg, sd, ATTR_STD_UV);
-
-#ifdef __HAIR__
-	if(offset_uv == ATTR_STD_NOT_FOUND || sd->curve_seg != ~0)
 		return make_float3(0.0f, 0.0f, 0.0f);
-#else
-	if(offset_uv == ATTR_STD_NOT_FOUND)
-		return make_float3(0.0f, 0.0f, 0.0f);
-#endif
-
-	float3 uv = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, offset_uv, NULL, NULL);
-	uv.z = 1.0f;
-	return uv;
+	}
 }
 
 CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index d051006f165..e80772bd4e2 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -348,14 +348,39 @@ typedef struct Intersection {
 
 /* Attributes */
 
+#define ATTR_PRIM_TYPES		2
+#define ATTR_PRIM_CURVE		1
+
 typedef enum AttributeElement {
+	ATTR_ELEMENT_NONE,
+	ATTR_ELEMENT_VALUE,
 	ATTR_ELEMENT_FACE,
 	ATTR_ELEMENT_VERTEX,
 	ATTR_ELEMENT_CORNER,
-	ATTR_ELEMENT_VALUE,
-	ATTR_ELEMENT_NONE
+	ATTR_ELEMENT_CURVE_SEGMENT,
+	ATTR_ELEMENT_CURVE_KEY
 } AttributeElement;
 
+typedef enum AttributeStandard {
+	ATTR_STD_NONE = 0,
+	ATTR_STD_VERTEX_NORMAL,
+	ATTR_STD_FACE_NORMAL,
+	ATTR_STD_UV,
+	ATTR_STD_UV_TANGENT,
+	ATTR_STD_UV_TANGENT_SIGN,
+	ATTR_STD_GENERATED,
+	ATTR_STD_POSITION_UNDEFORMED,
+	ATTR_STD_POSITION_UNDISPLACED,
+	ATTR_STD_MOTION_PRE,
+	ATTR_STD_MOTION_POST,
+	ATTR_STD_PARTICLE,
+	ATTR_STD_CURVE_TANGENT,
+	ATTR_STD_CURVE_INTERCEPT,
+	ATTR_STD_NUM,
+
+	ATTR_STD_NOT_FOUND = ~0
+} AttributeStandard;
+
 /* Closure data */
 
 #define MAX_CLOSURE 8
diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp
index 64c4d109452..afa5211216b 100644
--- a/intern/cycles/kernel/osl/osl_services.cpp
+++ b/intern/cycles/kernel/osl/osl_services.cpp
@@ -37,9 +37,10 @@
 #include "kernel_differential.h"
 #include "kernel_object.h"
 #include "kernel_bvh.h"
-#include "kernel_attribute.h"
-#include "kernel_projection.h"
 #include "kernel_triangle.h"
+#include "kernel_curve.h"
+#include "kernel_primitive.h"
+#include "kernel_projection.h"
 #include "kernel_accumulate.h"
 #include "kernel_shader.h"
 
@@ -75,10 +76,9 @@ ustring OSLRenderServices::u_geom_trianglevertices("geom:trianglevertices");
 ustring OSLRenderServices::u_geom_polyvertices("geom:polyvertices");
 ustring OSLRenderServices::u_geom_name("geom:name");
 #ifdef __HAIR__
-ustring OSLRenderServices::u_curve_is_strand("curve:is_strand");
-ustring OSLRenderServices::u_curve_intercept("curve:intercept");
-ustring OSLRenderServices::u_curve_thickness("curve:thickness");
-ustring OSLRenderServices::u_curve_tangent_normal("curve:tangent_normal");
+ustring OSLRenderServices::u_is_curve("geom:is_curve");
+ustring OSLRenderServices::u_curve_thickness("geom:curve_thickness");
+ustring OSLRenderServices::u_curve_tangent_normal("geom:curve_tangent_normal");
 #endif
 ustring OSLRenderServices::u_path_ray_length("path:ray_length");
 ustring OSLRenderServices::u_trace("trace");
@@ -501,14 +501,14 @@ static bool get_mesh_attribute(KernelGlobals *kg, const ShaderData *sd, const OS
 	    attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor)
 	{
 		float3 fval[3];
-		fval[0] = triangle_attribute_float3(kg, sd, attr.elem, attr.offset,
-		                                    (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
+		fval[0] = primitive_attribute_float3(kg, sd, attr.elem, attr.offset,
+		                                     (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
 		return set_attribute_float3(fval, type, derivatives, val);
 	}
 	else if (attr.type == TypeDesc::TypeFloat) {
 		float fval[3];
-		fval[0] = triangle_attribute_float(kg, sd, attr.elem, attr.offset,
-		                                   (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
+		fval[0] = primitive_attribute_float(kg, sd, attr.elem, attr.offset,
+		                                    (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
 		return set_attribute_float(fval, type, derivatives, val);
 	}
 	else {
@@ -604,7 +604,8 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD
 	else if (name == u_geom_numpolyvertices) {
 		return set_attribute_int(3, type, derivatives, val);
 	}
-	else if (name == u_geom_trianglevertices || name == u_geom_polyvertices) {
+	else if ((name == u_geom_trianglevertices || name == u_geom_polyvertices)
+		     && sd->curve_seg == ~0) {
 		float3 P[3];
 		triangle_vertices(kg, sd->prim, P);
 
@@ -623,20 +624,16 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD
 	
 #ifdef __HAIR__
 	/* Hair Attributes */
-	else if (name == u_curve_is_strand) {
+	else if (name == u_is_curve) {
 		float f = !(sd->curve_seg == ~0);
 		return set_attribute_float(f, type, derivatives, val);
 	}
-	else if (name == u_curve_intercept) {
-		float f = intercept(kg, sd->curve_seg, sd->prim, sd->u);
-		return set_attribute_float(f, type, derivatives, val);
-	}
 	else if (name == u_curve_thickness) {
-		float f = 2 * hair_radius(kg, sd->curve_seg, sd->u);
+		float f = curve_thickness(kg, sd);
 		return set_attribute_float(f, type, derivatives, val);
 	}
 	else if (name == u_curve_tangent_normal) {
-		float3 f = hair_tangent_normal(kg, sd);
+		float3 f = curve_tangent_normal(kg, sd);
 		return set_attribute_float3(f, type, derivatives, val);
 	}
 #endif
@@ -662,7 +659,7 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri
 {
 	KernelGlobals *kg = kernel_globals;
 	ShaderData *sd = (ShaderData *)renderstate;
-	int object, tri;
+	int object, prim, curve_seg;
 
 	/* lookup of attribute on another object */
 	if (object_name != u_empty || sd == NULL) {
@@ -672,17 +669,20 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri
 			return false;
 
 		object = it->second;
-		tri = ~0;
+		prim = ~0;
+		curve_seg = ~0;
 	}
 	else {
 		object = sd->object;
-		tri = sd->prim;
+		prim = sd->prim;
+		curve_seg = sd->curve_seg;
 
 		if (object == ~0)
 			return get_background_attribute(kg, sd, name, type, derivatives, val);
 	}
 
 	/* find attribute on object */
+	object = object*ATTR_PRIM_TYPES + (curve_seg != ~0);
 	OSLGlobals::AttributeMap& attribute_map = kg->osl->attribute_map[object];
 	OSLGlobals::AttributeMap::iterator it = attribute_map.find(name);
 
@@ -691,7 +691,7 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri
 
 		if (attr.elem != ATTR_ELEMENT_VALUE) {
 			/* triangle and vertex attributes */
-			if (tri != ~0)
+			if (prim != ~0)
 				return get_mesh_attribute(kg, sd, attr, type, derivatives, val);
 		}
 		else {
diff --git a/intern/cycles/kernel/osl/osl_services.h b/intern/cycles/kernel/osl/osl_services.h
index 9b7c9a423ff..50c50b9952c 100644
--- a/intern/cycles/kernel/osl/osl_services.h
+++ b/intern/cycles/kernel/osl/osl_services.h
@@ -130,8 +130,7 @@ public:
 	static ustring u_geom_trianglevertices;
 	static ustring u_geom_polyvertices;
 	static ustring u_geom_name;
-	static ustring u_curve_is_strand;
-	static ustring u_curve_intercept;
+	static ustring u_is_curve;
 	static ustring u_curve_thickness;
 	static ustring u_curve_tangent_normal;
 	static ustring u_path_ray_length;
diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp
index 3ff032374fc..18486eba114 100644
--- a/intern/cycles/kernel/osl/osl_shader.cpp
+++ b/intern/cycles/kernel/osl/osl_shader.cpp
@@ -26,9 +26,10 @@
 #include "osl_services.h"
 #include "osl_shader.h"
 
-#include "util_attribute.h"
 #include "util_foreach.h"
 
+#include "attribute.h"
+
 #include 
 
 CCL_NAMESPACE_BEGIN
@@ -453,15 +454,17 @@ float3 OSLShader::volume_eval_phase(const ShaderClosure *sc, const float3 omega_
 
 /* Attributes */
 
-int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id)
+int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeElement *elem)
 {
 	/* for OSL, a hash map is used to lookup the attribute by name. */
-	OSLGlobals::AttributeMap &attr_map = kg->osl->attribute_map[sd->object];
-	ustring stdname(std::string("std::") + std::string(attribute_standard_name((AttributeStandard)id)));
+	int object = sd->object*ATTR_PRIM_TYPES + (sd->curve_seg != ~0);
+	OSLGlobals::AttributeMap &attr_map = kg->osl->attribute_map[object];
+	ustring stdname(std::string("geom:") + std::string(Attribute::standard_name((AttributeStandard)id)));
 	OSLGlobals::AttributeMap::const_iterator it = attr_map.find(stdname);
 
 	if (it != attr_map.end()) {
 		const OSLGlobals::Attribute &osl_attr = it->second;
+		*elem = osl_attr.elem;
 		/* return result */
 		return (osl_attr.elem == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : osl_attr.offset;
 	}
diff --git a/intern/cycles/kernel/osl/osl_shader.h b/intern/cycles/kernel/osl/osl_shader.h
index 2e46a2de42c..2062c651162 100644
--- a/intern/cycles/kernel/osl/osl_shader.h
+++ b/intern/cycles/kernel/osl/osl_shader.h
@@ -74,7 +74,7 @@ public:
 	                                const float3 omega_in, const float3 omega_out);
 
 	/* attributes */
-	static int find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id);
+	static int find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeElement *elem);
 };
 
 CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/shaders/node_hair_info.osl b/intern/cycles/kernel/shaders/node_hair_info.osl
index a44fc67f4bc..cbb3b98383f 100644
--- a/intern/cycles/kernel/shaders/node_hair_info.osl
+++ b/intern/cycles/kernel/shaders/node_hair_info.osl
@@ -24,9 +24,9 @@ shader node_hair_info(
 	output float Thickness = 0.0,
 	output normal TangentNormal = N)
 {
-	getattribute("curve:is_strand", IsStrand);
-	getattribute("curve:intercept", Intercept);
-	getattribute("curve:thickness", Thickness);
-	getattribute("curve:tangent_normal", TangentNormal);
+	getattribute("geom:is_curve", IsStrand);
+	getattribute("geom:curve_intercept", Intercept);
+	getattribute("geom:curve_thickness", Thickness);
+	getattribute("geom:curve_tangent_normal", TangentNormal);
 }
 
diff --git a/intern/cycles/kernel/svm/svm_attribute.h b/intern/cycles/kernel/svm/svm_attribute.h
index 4f9dc4af007..f11b69138d1 100644
--- a/intern/cycles/kernel/svm/svm_attribute.h
+++ b/intern/cycles/kernel/svm/svm_attribute.h
@@ -28,10 +28,13 @@ __device void svm_node_attr_init(KernelGlobals *kg, ShaderData *sd,
 		/* find attribute by unique id */
 		uint id = node.y;
 		uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
+		attr_offset = (sd->curve_seg == ~0)? attr_offset: attr_offset + ATTR_PRIM_CURVE;
 		uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
-
-		while(attr_map.x != id)
-			attr_map = kernel_tex_fetch(__attributes_map, ++attr_offset);
+		
+		while(attr_map.x != id) {
+			attr_offset += ATTR_PRIM_TYPES;
+			attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
+		}
 
 		/* return result */
 		*elem = (AttributeElement)attr_map.y;
@@ -58,45 +61,27 @@ __device void svm_node_attr(KernelGlobals *kg, ShaderData *sd, float *stack, uin
 
 	svm_node_attr_init(kg, sd, node, &type, &mesh_type, &elem, &offset, &out_offset);
 
-#ifdef __HAIR__
-	if (sd->curve_seg != ~0) {
-		/*currently strand attributes aren't enabled - only exports stored uvs*/
-		if(type == NODE_ATTR_FLOAT)
-			stack_store_float(stack, out_offset, 0.0f);
+	/* fetch and store attribute */
+	if(type == NODE_ATTR_FLOAT) {
+		if(mesh_type == NODE_ATTR_FLOAT) {
+			float f = primitive_attribute_float(kg, sd, elem, offset, NULL, NULL);
+			stack_store_float(stack, out_offset, f);
+		}
 		else {
-			float4 sd2 = kernel_tex_fetch(__tri_woop, sd->prim*3+2);
-			float3 uv =  make_float3(sd2.z,sd2.w,0.0f);
-			stack_store_float3(stack, out_offset, uv);
+			float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, NULL);
+			stack_store_float(stack, out_offset, average(f));
 		}
 	}
-	else
-	{
-#endif
-
-		/* fetch and store attribute */
-		if(type == NODE_ATTR_FLOAT) {
-			if(mesh_type == NODE_ATTR_FLOAT) {
-				float f = triangle_attribute_float(kg, sd, elem, offset, NULL, NULL);
-				stack_store_float(stack, out_offset, f);
-			}
-			else {
-				float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, NULL);
-				stack_store_float(stack, out_offset, average(f));
-			}
+	else {
+		if(mesh_type == NODE_ATTR_FLOAT3) {
+			float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, NULL);
+			stack_store_float3(stack, out_offset, f);
 		}
 		else {
-			if(mesh_type == NODE_ATTR_FLOAT3) {
-				float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, NULL);
-				stack_store_float3(stack, out_offset, f);
-			}
-			else {
-				float f = triangle_attribute_float(kg, sd, elem, offset, NULL, NULL);
-				stack_store_float3(stack, out_offset, make_float3(f, f, f));
-			}
+			float f = primitive_attribute_float(kg, sd, elem, offset, NULL, NULL);
+			stack_store_float3(stack, out_offset, make_float3(f, f, f));
 		}
-#ifdef __HAIR__
 	}
-#endif
 }
 
 __device void svm_node_attr_bump_dx(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
@@ -109,43 +94,30 @@ __device void svm_node_attr_bump_dx(KernelGlobals *kg, ShaderData *sd, float *st
 	svm_node_attr_init(kg, sd, node, &type, &mesh_type, &elem, &offset, &out_offset);
 
 	/* fetch and store attribute */
-#ifdef __HAIR__
-	if (sd->curve_seg != ~0) {
-		/*currently strand attributes aren't enabled*/
-		if(type == NODE_ATTR_FLOAT)
-			stack_store_float(stack, out_offset, 0.0f);
-		else
-			stack_store_float3(stack, out_offset,  make_float3(0.0f, 0.0f, 0.0f));
+	if(type == NODE_ATTR_FLOAT) {
+		if(mesh_type == NODE_ATTR_FLOAT) {
+			float dx;
+			float f = primitive_attribute_float(kg, sd, elem, offset, &dx, NULL);
+			stack_store_float(stack, out_offset, f+dx);
+		}
+		else {
+			float3 dx;
+			float3 f = primitive_attribute_float3(kg, sd, elem, offset, &dx, NULL);
+			stack_store_float(stack, out_offset, average(f+dx));
+		}
 	}
 	else {
-#endif
-		if(type == NODE_ATTR_FLOAT) {
-			if(mesh_type == NODE_ATTR_FLOAT) {
-				float dx;
-				float f = triangle_attribute_float(kg, sd, elem, offset, &dx, NULL);
-				stack_store_float(stack, out_offset, f+dx);
-			}
-			else {
-				float3 dx;
-				float3 f = triangle_attribute_float3(kg, sd, elem, offset, &dx, NULL);
-				stack_store_float(stack, out_offset, average(f+dx));
-			}
+		if(mesh_type == NODE_ATTR_FLOAT3) {
+			float3 dx;
+			float3 f = primitive_attribute_float3(kg, sd, elem, offset, &dx, NULL);
+			stack_store_float3(stack, out_offset, f+dx);
 		}
 		else {
-			if(mesh_type == NODE_ATTR_FLOAT3) {
-				float3 dx;
-				float3 f = triangle_attribute_float3(kg, sd, elem, offset, &dx, NULL);
-				stack_store_float3(stack, out_offset, f+dx);
-			}
-			else {
-				float dx;
-				float f = triangle_attribute_float(kg, sd, elem, offset, &dx, NULL);
-				stack_store_float3(stack, out_offset, make_float3(f+dx, f+dx, f+dx));
-			}
+			float dx;
+			float f = primitive_attribute_float(kg, sd, elem, offset, &dx, NULL);
+			stack_store_float3(stack, out_offset, make_float3(f+dx, f+dx, f+dx));
 		}
-#ifdef __HAIR__
 	}
-#endif
 }
 
 __device void svm_node_attr_bump_dy(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
@@ -158,43 +130,30 @@ __device void svm_node_attr_bump_dy(KernelGlobals *kg, ShaderData *sd, float *st
 	svm_node_attr_init(kg, sd, node, &type, &mesh_type, &elem, &offset, &out_offset);
 
 	/* fetch and store attribute */
-#ifdef __HAIR__
-	if (sd->curve_seg != ~0) {
-		/*currently strand attributes aren't enabled*/
-		if(type == NODE_ATTR_FLOAT)
-			stack_store_float(stack, out_offset, 0.0f);
-		else 
-			stack_store_float3(stack, out_offset,  make_float3(0.0f, 0.0f, 0.0f));
+	if(type == NODE_ATTR_FLOAT) {
+		if(mesh_type == NODE_ATTR_FLOAT) {
+			float dy;
+			float f = primitive_attribute_float(kg, sd, elem, offset, NULL, &dy);
+			stack_store_float(stack, out_offset, f+dy);
+		}
+		else {
+			float3 dy;
+			float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, &dy);
+			stack_store_float(stack, out_offset, average(f+dy));
+		}
 	}
 	else {
-#endif
-		if(type == NODE_ATTR_FLOAT) {
-			if(mesh_type == NODE_ATTR_FLOAT) {
-				float dy;
-				float f = triangle_attribute_float(kg, sd, elem, offset, NULL, &dy);
-				stack_store_float(stack, out_offset, f+dy);
-			}
-			else {
-				float3 dy;
-				float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, &dy);
-				stack_store_float(stack, out_offset, average(f+dy));
-			}
+		if(mesh_type == NODE_ATTR_FLOAT3) {
+			float3 dy;
+			float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, &dy);
+			stack_store_float3(stack, out_offset, f+dy);
 		}
 		else {
-			if(mesh_type == NODE_ATTR_FLOAT3) {
-				float3 dy;
-				float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, &dy);
-				stack_store_float3(stack, out_offset, f+dy);
-			}
-			else {
-				float dy;
-				float f = triangle_attribute_float(kg, sd, elem, offset, NULL, &dy);
-				stack_store_float3(stack, out_offset, make_float3(f+dy, f+dy, f+dy));
-			}
+			float dy;
+			float f = primitive_attribute_float(kg, sd, elem, offset, NULL, &dy);
+			stack_store_float3(stack, out_offset, make_float3(f+dy, f+dy, f+dy));
 		}
-#ifdef __HAIR__
 	}
-#endif
 }
 
 CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_geometry.h b/intern/cycles/kernel/svm/svm_geometry.h
index e1b898e9b14..db8bbabe0ec 100644
--- a/intern/cycles/kernel/svm/svm_geometry.h
+++ b/intern/cycles/kernel/svm/svm_geometry.h
@@ -28,26 +28,7 @@ __device void svm_node_geometry(KernelGlobals *kg, ShaderData *sd, float *stack,
 		case NODE_GEOM_P: data = sd->P; break;
 		case NODE_GEOM_N: data = sd->N; break;
 #ifdef __DPDU__
-		case NODE_GEOM_T: {
-			/* try to create spherical tangent from generated coordinates */
-			int attr_offset = (sd->object != ~0)? find_attribute(kg, sd, ATTR_STD_GENERATED): ATTR_STD_NOT_FOUND;
-#ifdef __HAIR__
-			if(attr_offset != ATTR_STD_NOT_FOUND && sd->curve_seg == ~0) {
-#else
-			if(attr_offset != ATTR_STD_NOT_FOUND) {
-#endif
-				data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL);
-				data = make_float3(-(data.y - 0.5f), (data.x - 0.5f), 0.0f);
-				object_normal_transform(kg, sd, &data);
-				data = cross(sd->N, normalize(cross(data, sd->N)));;
-			}
-			else {
-				/* otherwise use surface derivatives */
-				data = normalize(sd->dPdu);
-			}
-
-			break;
-		}
+		case NODE_GEOM_T: data = primitive_tangent(kg, sd); break;
 #endif
 		case NODE_GEOM_I: data = sd->I; break;
 		case NODE_GEOM_Ng: data = sd->Ng; break;
@@ -164,6 +145,7 @@ __device void svm_node_particle_info(KernelGlobals *kg, ShaderData *sd, float *s
 }
 
 #ifdef __HAIR__
+
 /* Hair Info */
 
 __device void svm_node_hair_info(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
@@ -177,18 +159,15 @@ __device void svm_node_hair_info(KernelGlobals *kg, ShaderData *sd, float *stack
 			stack_store_float(stack, out_offset, data);
 			break;
 		}
-		case NODE_INFO_CURVE_INTERCEPT: {
-			data = intercept(kg, sd->curve_seg, sd->prim, sd->u);
-			stack_store_float(stack, out_offset, data);
-			break;
-		}
+		case NODE_INFO_CURVE_INTERCEPT:
+			break; /* handled as attribute */
 		case NODE_INFO_CURVE_THICKNESS: {
-			data = 2 * hair_radius(kg, sd->curve_seg, sd->u);
+			data = curve_thickness(kg, sd);
 			stack_store_float(stack, out_offset, data);
 			break;
 		}
 		case NODE_INFO_CURVE_TANGENT_NORMAL: {
-			data3 = hair_tangent_normal(kg, sd);
+			data3 = curve_tangent_normal(kg, sd);
 			stack_store_float3(stack, out_offset, data3);
 			break;
 		}
diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h
index 5e7c92ba93c..7a1af43b625 100644
--- a/intern/cycles/kernel/svm/svm_tex_coord.h
+++ b/intern/cycles/kernel/svm/svm_tex_coord.h
@@ -242,18 +242,15 @@ __device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *stac
 
 	if(space == NODE_NORMAL_MAP_TANGENT) {
 		/* tangent space */
-#ifdef __HAIR__
-			if(sd->object == ~0 || sd->curve_seg != ~0) {
-#else
-			if(sd->object == ~0) {
-#endif
+		if(sd->object == ~0) {
 			stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f));
 			return;
 		}
 
 		/* first try to get tangent attribute */
-		int attr_offset = find_attribute(kg, sd, node.z);
-		int attr_sign_offset = find_attribute(kg, sd, node.w);
+		AttributeElement attr_elem, attr_sign_elem;
+		int attr_offset = find_attribute(kg, sd, node.z, &attr_elem);
+		int attr_sign_offset = find_attribute(kg, sd, node.w, &attr_sign_elem);
 
 		if(attr_offset == ATTR_STD_NOT_FOUND || attr_sign_offset == ATTR_STD_NOT_FOUND) {
 			stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f));
@@ -261,8 +258,8 @@ __device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *stac
 		}
 
 		/* ensure orthogonal and normalized (interpolation breaks it) */
-		float3 tangent = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, attr_offset, NULL, NULL);
-		float sign = triangle_attribute_float(kg, sd, ATTR_ELEMENT_CORNER, attr_sign_offset, NULL, NULL);
+		float3 tangent = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL);
+		float sign = primitive_attribute_float(kg, sd, attr_sign_elem, attr_sign_offset, NULL, NULL);
 
 		object_normal_transform(kg, sd, &tangent);
 		tangent = cross(sd->N, normalize(cross(tangent, sd->N)));;
@@ -299,30 +296,24 @@ __device void svm_node_tangent(KernelGlobals *kg, ShaderData *sd, float *stack,
 
 	if(direction_type == NODE_TANGENT_UVMAP) {
 		/* UV map */
-		int attr_offset = find_attribute(kg, sd, node.z);
+		AttributeElement attr_elem;
+		int attr_offset = find_attribute(kg, sd, node.z, &attr_elem);
 
-#ifdef __HAIR__
-		if(attr_offset == ATTR_STD_NOT_FOUND || sd->curve_seg != ~0)
-#else
 		if(attr_offset == ATTR_STD_NOT_FOUND)
-#endif
 			tangent = make_float3(0.0f, 0.0f, 0.0f);
 		else
-			tangent = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, attr_offset, NULL, NULL);
+			tangent = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL);
 	}
 	else {
 		/* radial */
-		int attr_offset = find_attribute(kg, sd, node.z);
+		AttributeElement attr_elem;
+		int attr_offset = find_attribute(kg, sd, node.z, &attr_elem);
 		float3 generated;
 
-#ifdef __HAIR__
-		if(attr_offset == ATTR_STD_NOT_FOUND || sd->curve_seg != ~0)
-#else
 		if(attr_offset == ATTR_STD_NOT_FOUND)
-#endif
 			generated = sd->P;
 		else
-			generated = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL);
+			generated = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL);
 
 		if(axis == NODE_TANGENT_AXIS_X)
 			tangent = make_float3(0.0f, -(generated.z - 0.5f), (generated.y - 0.5f));
diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp
index 95941c14b6c..758e4e5e820 100644
--- a/intern/cycles/render/attribute.cpp
+++ b/intern/cycles/render/attribute.cpp
@@ -26,7 +26,7 @@ CCL_NAMESPACE_BEGIN
 
 /* Attribute */
 
-void Attribute::set(ustring name_, TypeDesc type_, Element element_)
+void Attribute::set(ustring name_, TypeDesc type_, AttributeElement element_)
 {
 	name = name_;
 	type = type_;
@@ -39,12 +39,30 @@ void Attribute::set(ustring name_, TypeDesc type_, Element element_)
 		type == TypeDesc::TypeNormal);
 }
 
-void Attribute::reserve(int numverts, int numtris)
+void Attribute::reserve(int numverts, int numtris, int numcurves, int numkeys)
 {
-	buffer.resize(buffer_size(numverts, numtris), 0);
+	buffer.resize(buffer_size(numverts, numtris, numcurves, numkeys), 0);
 }
 
-size_t Attribute::data_sizeof()
+void Attribute::add(const float& f)
+{
+	char *data = (char*)&f;
+	size_t size = sizeof(f);
+
+	for(size_t i = 0; i < size; i++)
+		buffer.push_back(data[i]);
+}
+
+void Attribute::add(const float3& f)
+{
+	char *data = (char*)&f;
+	size_t size = sizeof(f);
+
+	for(size_t i = 0; i < size; i++)
+		buffer.push_back(data[i]);
+}
+
+size_t Attribute::data_sizeof() const
 {
 	if(type == TypeDesc::TypeFloat)
 		return sizeof(float);
@@ -52,19 +70,27 @@ size_t Attribute::data_sizeof()
 		return sizeof(float3);
 }
 
-size_t Attribute::element_size(int numverts, int numtris)
+size_t Attribute::element_size(int numverts, int numtris, int numcurves, int numkeys) const
 {
-	if(element == VERTEX)
+	if(element == ATTR_ELEMENT_VALUE)
+		return 1;
+	if(element == ATTR_ELEMENT_VERTEX)
 		return numverts;
-	else if(element == FACE)
+	else if(element == ATTR_ELEMENT_FACE)
 		return numtris;
-	else
+	else if(element == ATTR_ELEMENT_CORNER)
 		return numtris*3;
+	else if(element == ATTR_ELEMENT_CURVE_SEGMENT)
+		return numcurves;
+	else if(element == ATTR_ELEMENT_CURVE_KEY)
+		return numkeys;
+	
+	return 0;
 }
 
-size_t Attribute::buffer_size(int numverts, int numtris)
+size_t Attribute::buffer_size(int numverts, int numtris, int numcurves, int numkeys) const
 {
-	return element_size(numverts, numtris)*data_sizeof();
+	return element_size(numverts, numtris, numcurves, numkeys)*data_sizeof();
 }
 
 bool Attribute::same_storage(TypeDesc a, TypeDesc b)
@@ -84,18 +110,51 @@ bool Attribute::same_storage(TypeDesc a, TypeDesc b)
 	return false;
 }
 
+const char *Attribute::standard_name(AttributeStandard std)
+{
+	if(std == ATTR_STD_VERTEX_NORMAL)
+		return "N";
+	else if(std == ATTR_STD_FACE_NORMAL)
+		return "Ng";
+	else if(std == ATTR_STD_UV)
+		return "uv";
+	else if(std == ATTR_STD_GENERATED)
+		return "generated";
+	else if(std == ATTR_STD_UV_TANGENT)
+		return "tangent";
+	else if(std == ATTR_STD_UV_TANGENT_SIGN)
+		return "tangent_sign";
+	else if(std == ATTR_STD_POSITION_UNDEFORMED)
+		return "undeformed";
+	else if(std == ATTR_STD_POSITION_UNDISPLACED)
+		return "undisplaced";
+	else if(std == ATTR_STD_MOTION_PRE)
+		return "motion_pre";
+	else if(std == ATTR_STD_MOTION_POST)
+		return "motion_post";
+	else if(std == ATTR_STD_PARTICLE)
+		return "particle";
+	else if(std == ATTR_STD_CURVE_TANGENT)
+		return "curve_tangent";
+	else if(std == ATTR_STD_CURVE_INTERCEPT)
+		return "curve_intercept";
+	
+	return "";
+}
+
 /* Attribute Set */
 
 AttributeSet::AttributeSet()
 {
-	mesh = NULL;
+	triangle_mesh = NULL;
+	curve_mesh = NULL;
 }
 
 AttributeSet::~AttributeSet()
 {
 }
 
-Attribute *AttributeSet::add(ustring name, TypeDesc type, Attribute::Element element)
+Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement element)
 {
 	Attribute *attr = find(name);
 
@@ -111,24 +170,22 @@ Attribute *AttributeSet::add(ustring name, TypeDesc type, Attribute::Element ele
 	attributes.push_back(Attribute());
 	attr = &attributes.back();
 
-	if(element == Attribute::VERTEX)
-		attr->set(name, type, element);
-	else if(element == Attribute::FACE)
-		attr->set(name, type, element);
-	else if(element == Attribute::CORNER)
-		attr->set(name, type, element);
+	attr->set(name, type, element);
 	
-	if(mesh)
-		attr->reserve(mesh->verts.size(), mesh->triangles.size());
+	/* this is weak .. */
+	if(triangle_mesh)
+		attr->reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), 0, 0);
+	if(curve_mesh)
+		attr->reserve(0, 0, curve_mesh->curve_segments.size(), curve_mesh->curve_keys.size());
 	
 	return attr;
 }
 
-Attribute *AttributeSet::find(ustring name)
+Attribute *AttributeSet::find(ustring name) const
 {
-	foreach(Attribute& attr, attributes)
+	foreach(const Attribute& attr, attributes)
 		if(attr.name == name)
-			return &attr;
+			return (Attribute*)&attr;
 
 	return NULL;
 }
@@ -154,41 +211,59 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
 	Attribute *attr = NULL;
 
 	if(name == ustring())
-		name = attribute_standard_name(std);
-
-	if(std == ATTR_STD_VERTEX_NORMAL)
-		attr = add(name, TypeDesc::TypeNormal, Attribute::VERTEX);
-	else if(std == ATTR_STD_FACE_NORMAL)
-		attr = add(name, TypeDesc::TypeNormal, Attribute::FACE);
-	else if(std == ATTR_STD_UV)
-		attr = add(name, TypeDesc::TypePoint, Attribute::CORNER);
-	else if(std == ATTR_STD_UV_TANGENT)
-		attr = add(name, TypeDesc::TypeVector, Attribute::CORNER);
-	else if(std == ATTR_STD_UV_TANGENT_SIGN)
-		attr = add(name, TypeDesc::TypeFloat, Attribute::CORNER);
-	else if(std == ATTR_STD_GENERATED)
-		attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
-	else if(std == ATTR_STD_POSITION_UNDEFORMED)
-		attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
-	else if(std == ATTR_STD_POSITION_UNDISPLACED)
-		attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
-	else if(std == ATTR_STD_MOTION_PRE)
-		attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
-	else if(std == ATTR_STD_MOTION_POST)
-		attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
-	else
-		assert(0);
+		name = Attribute::standard_name(std);
+
+	if(triangle_mesh) {
+		if(std == ATTR_STD_VERTEX_NORMAL)
+			attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX);
+		else if(std == ATTR_STD_FACE_NORMAL)
+			attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_FACE);
+		else if(std == ATTR_STD_UV)
+			attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER);
+		else if(std == ATTR_STD_UV_TANGENT)
+			attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER);
+		else if(std == ATTR_STD_UV_TANGENT_SIGN)
+			attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CORNER);
+		else if(std == ATTR_STD_GENERATED)
+			attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
+		else if(std == ATTR_STD_POSITION_UNDEFORMED)
+			attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
+		else if(std == ATTR_STD_POSITION_UNDISPLACED)
+			attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
+		else if(std == ATTR_STD_MOTION_PRE)
+			attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
+		else if(std == ATTR_STD_MOTION_POST)
+			attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
+		else
+			assert(0);
+	}
+	else if(curve_mesh) {
+		if(std == ATTR_STD_UV)
+			attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_SEGMENT);
+		else if(std == ATTR_STD_GENERATED)
+			attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_SEGMENT);
+		else if(std == ATTR_STD_MOTION_PRE)
+			attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_KEY);
+		else if(std == ATTR_STD_MOTION_POST)
+			attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_KEY);
+		else if(std == ATTR_STD_CURVE_TANGENT)
+			attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CURVE_KEY);
+		else if(std == ATTR_STD_CURVE_INTERCEPT)
+			attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE_KEY);
+		else
+			assert(0);
+	}
 
 	attr->std = std;
 	
 	return attr;
 }
 
-Attribute *AttributeSet::find(AttributeStandard std)
+Attribute *AttributeSet::find(AttributeStandard std) const
 {
-	foreach(Attribute& attr, attributes)
+	foreach(const Attribute& attr, attributes)
 		if(attr.std == std)
-			return &attr;
+			return (Attribute*)&attr;
 
 	return NULL;
 }
@@ -217,10 +292,14 @@ Attribute *AttributeSet::find(AttributeRequest& req)
 		return find(req.std);
 }
 
-void AttributeSet::reserve(int numverts, int numtris)
+void AttributeSet::reserve()
 {
-	foreach(Attribute& attr, attributes)
-		attr.reserve(numverts, numtris);
+	foreach(Attribute& attr, attributes) {
+		if(triangle_mesh)
+			attr.reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), 0, 0);
+		if(curve_mesh)
+			attr.reserve(0, 0, curve_mesh->curve_segments.size(), curve_mesh->curve_keys.size());
+	}
 }
 
 void AttributeSet::clear()
@@ -235,9 +314,13 @@ AttributeRequest::AttributeRequest(ustring name_)
 	name = name_;
 	std = ATTR_STD_NONE;
 
-	type = TypeDesc::TypeFloat;
-	element = ATTR_ELEMENT_NONE;
-	offset = 0;
+	triangle_type = TypeDesc::TypeFloat;
+	triangle_element = ATTR_ELEMENT_NONE;
+	triangle_offset = 0;
+
+	curve_type = TypeDesc::TypeFloat;
+	curve_element = ATTR_ELEMENT_NONE;
+	curve_offset = 0;
 }
 
 AttributeRequest::AttributeRequest(AttributeStandard std_)
@@ -245,9 +328,13 @@ AttributeRequest::AttributeRequest(AttributeStandard std_)
 	name = ustring();
 	std = std_;
 
-	type = TypeDesc::TypeFloat;
-	element = ATTR_ELEMENT_NONE;
-	offset = 0;
+	triangle_type = TypeDesc::TypeFloat;
+	triangle_element = ATTR_ELEMENT_NONE;
+	triangle_offset = 0;
+
+	curve_type = TypeDesc::TypeFloat;
+	curve_element = ATTR_ELEMENT_NONE;
+	curve_offset = 0;
 }
 
 /* AttributeRequestSet */
diff --git a/intern/cycles/render/attribute.h b/intern/cycles/render/attribute.h
index d05952edfd7..6c0c06d0425 100644
--- a/intern/cycles/render/attribute.h
+++ b/intern/cycles/render/attribute.h
@@ -21,7 +21,6 @@
 
 #include "kernel_types.h"
 
-#include "util_attribute.h"
 #include "util_list.h"
 #include "util_param.h"
 #include "util_types.h"
@@ -42,36 +41,34 @@ class Mesh;
 
 class Attribute {
 public:
-	enum Element {
-		VERTEX,
-		FACE,
-		CORNER
-	};
-
 	ustring name;
 	AttributeStandard std;
 
 	TypeDesc type;
 	vector buffer;
-	Element element;
+	AttributeElement element;
 
 	Attribute() {}
-	void set(ustring name, TypeDesc type, Element element);
-	void reserve(int numverts, int numfaces);
+	void set(ustring name, TypeDesc type, AttributeElement element);
+	void reserve(int numverts, int numfaces, int numcurves, int numkeys);
 
-	size_t data_sizeof();
-	size_t element_size(int numverts, int numfaces);
-	size_t buffer_size(int numverts, int numfaces);
+	size_t data_sizeof() const;
+	size_t element_size(int numverts, int numfaces, int numcurves, int numkeys) const;
+	size_t buffer_size(int numverts, int numfaces, int numcurves, int numkeys) const;
 
 	char *data() { return (buffer.size())? &buffer[0]: NULL; };
 	float3 *data_float3() { return (float3*)data(); }
 	float *data_float() { return (float*)data(); }
 
 	const char *data() const { return (buffer.size())? &buffer[0]: NULL; }
-	const float3 *data_float3() const { return (float3*)data(); }
-	const float *data_float() const { return (float*)data(); }
+	const float3 *data_float3() const { return (const float3*)data(); }
+	const float *data_float() const { return (const float*)data(); }
+
+	void add(const float& f);
+	void add(const float3& f);
 
 	static bool same_storage(TypeDesc a, TypeDesc b);
+	static const char *standard_name(AttributeStandard std);
 };
 
 /* Attribute Set
@@ -80,23 +77,24 @@ public:
 
 class AttributeSet {
 public:
-	Mesh *mesh;
+	Mesh *triangle_mesh;
+	Mesh *curve_mesh;
 	list attributes;
 
 	AttributeSet();
 	~AttributeSet();
 
-	Attribute *add(ustring name, TypeDesc type, Attribute::Element element);
-	Attribute *find(ustring name);
+	Attribute *add(ustring name, TypeDesc type, AttributeElement element);
+	Attribute *find(ustring name) const;
 	void remove(ustring name);
 
 	Attribute *add(AttributeStandard std, ustring name = ustring());
-	Attribute *find(AttributeStandard std);
+	Attribute *find(AttributeStandard std) const;
 	void remove(AttributeStandard std);
 
 	Attribute *find(AttributeRequest& req);
 
-	void reserve(int numverts, int numfaces);
+	void reserve();
 	void clear();
 };
 
@@ -104,7 +102,7 @@ public:
  *
  * Request from a shader to use a certain attribute, so we can figure out
  * which ones we need to export from the host app end store for the kernel.
- * The attribute is found either by name or by standard. */
+ * The attribute is found either by name or by standard attribute type. */
 
 class AttributeRequest {
 public:
@@ -112,9 +110,9 @@ public:
 	AttributeStandard std;
 
 	/* temporary variables used by MeshManager */
-	TypeDesc type;
-	AttributeElement element;
-	int offset;
+	TypeDesc triangle_type, curve_type;
+	AttributeElement triangle_element, curve_element;
+	int triangle_offset, curve_offset;
 
 	AttributeRequest(ustring name_);
 	AttributeRequest(AttributeStandard std);
diff --git a/intern/cycles/render/curves.h b/intern/cycles/render/curves.h
index 581b3010d77..85a549082f2 100644
--- a/intern/cycles/render/curves.h
+++ b/intern/cycles/render/curves.h
@@ -80,8 +80,7 @@ public:
 	vector curve_firstkey;
 	vector curve_keynum;
 	vector curve_length;
-	vector curve_u;
-	vector curve_v;
+	vector curve_uv;
 
 	vector curvekey_co;
 	vector curvekey_time;
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index 66e528c7230..cab6008dd7c 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -142,7 +142,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
 	/* count */
 	size_t num_lights = scene->lights.size();
 	size_t num_triangles = 0;
-	size_t num_curve_segs = 0;
+	size_t num_curve_segments = 0;
 
 	foreach(Object *object, scene->objects) {
 		Mesh *mesh = object->mesh;
@@ -172,16 +172,16 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
 			}
 
 			/* disabled for strands*/
-			/*for(size_t i = 0; i < mesh->curve_segs.size(); i++) {
-			*	Shader *shader = scene->shaders[mesh->curve_segs[i].curveshader];
+			/*for(size_t i = 0; i < mesh->curve_segments.size(); i++) {
+			*	Shader *shader = scene->shaders[mesh->curve_segments[i].shader];
 			*
 			*	if(shader->sample_as_light && shader->has_surface_emission)
-			*		num_curve_segs++;
+			*		num_curve_segments++;
 			}*/
 		}
 	}
 
-	size_t num_distribution = num_triangles + num_curve_segs;
+	size_t num_distribution = num_triangles + num_curve_segments;
 	num_distribution += num_lights;
 
 	/* emission area */
@@ -245,8 +245,8 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
 			}
 
 			/*sample as light disabled for strands*/
-			/*for(size_t i = 0; i < mesh->curve_segs.size(); i++) {
-			*	Shader *shader = scene->shaders[mesh->curve_segs[i].curveshader];
+			/*for(size_t i = 0; i < mesh->curve_segments.size(); i++) {
+			*	Shader *shader = scene->shaders[mesh->curve_segments[i].shader];
 			*
 			*	if(shader->sample_as_light && shader->has_surface_emission) {
 			*		distribution[offset].x = totarea;
@@ -255,7 +255,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
 			*		distribution[offset].w = __int_as_float(object_id);
 			*		offset++;
 			*
-			*		Mesh::CurveSeg s = mesh->curve_segs[i];
+			*		Mesh::CurveSeg s = mesh->curve_segments[i];
 			*		float3 p1 = mesh->curve_keys[s.v[0]].loc;
 			*		float r1 = mesh->curve_keys[s.v[0]].radius;
 			*		float3 p2 = mesh->curve_keys[s.v[1]].loc;
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index b20e5cebdc5..53cae53ef69 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -54,7 +54,8 @@ Mesh::Mesh()
 	curveseg_offset = 0;
 	curvekey_offset = 0;
 
-	attributes.mesh = this;
+	attributes.triangle_mesh = this;
+	curve_attributes.curve_mesh = this;
 }
 
 Mesh::~Mesh()
@@ -62,15 +63,18 @@ Mesh::~Mesh()
 	delete bvh;
 }
 
-void Mesh::reserve(int numverts, int numtris)
+void Mesh::reserve(int numverts, int numtris, int numcurves, int numcurvekeys)
 {
 	/* reserve space to add verts and triangles later */
 	verts.resize(numverts);
 	triangles.resize(numtris);
 	shader.resize(numtris);
 	smooth.resize(numtris);
-	/*currently no need in hair segment resize and curve data needs including*/
-	attributes.reserve(numverts, numtris);
+	curve_keys.resize(numcurvekeys);
+	curve_segments.resize(numcurves);
+
+	attributes.reserve();
+	curve_attributes.reserve();
 }
 
 void Mesh::clear()
@@ -82,11 +86,10 @@ void Mesh::clear()
 	smooth.clear();
 
 	curve_keys.clear();
-	curve_keysCD.clear();
-	curve_segs.clear();
-	curve_attrib.clear();
+	curve_segments.clear();
 
 	attributes.clear();
+	curve_attributes.clear();
 	used_shaders.clear();
 
 	transform_applied = false;
@@ -105,34 +108,24 @@ void Mesh::add_triangle(int v0, int v1, int v2, int shader_, bool smooth_)
 	smooth.push_back(smooth_);
 }
 
-void Mesh::add_curvekey(float3 loc, float radius, float time)
+void Mesh::add_curve_key(float3 co, float radius)
 {
 	CurveKey ck;
-	ck.loc = loc;
+	ck.co = co;
 	ck.radius = radius;
-	ck.time = time;
 
 	curve_keys.push_back(ck);
 }
 
-void Mesh::add_curve(int v0, int v1, int shader, int curveid)
+void Mesh::add_curve_segment(int v0, int v1, int shader, int curveid)
 {
-	CurveSeg s;
+	CurveSegment s;
 	s.v[0] = v0;
 	s.v[1] = v1;
-	s.curveshader = shader;
+	s.shader = shader;
 	s.curve = curveid;
 
-	curve_segs.push_back(s);
-}
-
-void Mesh::add_curveattrib(float u, float v)
-{
-	Curve_Attribute s;
-	s.uv[0] = u;
-	s.uv[1] = v;
-
-	curve_attrib.push_back(s);
+	curve_segments.push_back(s);
 }
 
 void Mesh::compute_bounds()
@@ -145,7 +138,7 @@ void Mesh::compute_bounds()
 		bnds.grow(verts[i]);
 
 	for(size_t i = 0; i < curve_keys_size; i++)
-		bnds.grow(curve_keys[i].loc, curve_keys[i].radius);
+		bnds.grow(curve_keys[i].co, curve_keys[i].radius);
 
 	/* happens mostly on empty meshes */
 	if(!bnds.valid())
@@ -296,29 +289,31 @@ void Mesh::pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_seg_key
 	size_t curve_keys_size = curve_keys.size();
 	CurveKey *keys_ptr = NULL;
 
+	/* pack curve keys */
 	if(curve_keys_size) {
-
 		keys_ptr = &curve_keys[0];
 
 		for(size_t i = 0; i < curve_keys_size; i++) {
-			float3 p = keys_ptr[i].loc;
-			curve_key_co[i] = make_float4(p.x, p.y, p.z, keys_ptr[i].radius);
+			float3 p = keys_ptr[i].co;
+			float radius = keys_ptr[i].radius;
+
+			curve_key_co[i] = make_float4(p.x, p.y, p.z, radius);
 		}
 	}
 
-	size_t curve_seg_num = curve_segs.size();
+	/* pack curve segments */
+	size_t curve_seg_num = curve_segments.size();
 
 	if(curve_seg_num) {
-		CurveSeg *curve_ptr = &curve_segs[0];
-
+		CurveSegment *curve_ptr = &curve_segments[0];
 		int shader_id = 0;
 		
 		for(size_t i = 0; i < curve_seg_num; i++) {
-			CurveSeg s = curve_ptr[i];
-			shader_id = scene->shader_manager->get_shader_id(s.curveshader, this, false);
+			CurveSegment s = curve_ptr[i];
+			shader_id = scene->shader_manager->get_shader_id(s.shader, this, false);
 
-			float3 p1 = keys_ptr[s.v[0]].loc;
-			float3 p2 = keys_ptr[s.v[1]].loc;
+			float3 p1 = keys_ptr[s.v[0]].co;
+			float3 p2 = keys_ptr[s.v[1]].co;
 			float length = len(p2 - p1);
 
 			curve_seg_keys[i] = make_float4(
@@ -414,7 +409,7 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vectorattribute_map.clear();
 	og->object_names.clear();
 
-	og->attribute_map.resize(scene->objects.size());
+	og->attribute_map.resize(scene->objects.size()*ATTR_PRIM_TYPES);
 
 	for(size_t i = 0; i < scene->objects.size(); i++) {
 		/* set object name to object index map */
@@ -430,7 +425,8 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vectorattribute_map[i][attr.name()] = osl_attr;
+			og->attribute_map[i*ATTR_PRIM_TYPES][attr.name()] = osl_attr;
+			og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][attr.name()] = osl_attr;
 		}
 
 		/* find mesh attributes */
@@ -444,27 +440,46 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vectorattribute_map[i][stdname] = osl_attr;
+			if(req.triangle_element != ATTR_ELEMENT_NONE) {
+				osl_attr.elem = req.triangle_element;
+				osl_attr.offset = req.triangle_offset;
+
+				if(req.triangle_type == TypeDesc::TypeFloat)
+					osl_attr.type = TypeDesc::TypeFloat;
+				else
+					osl_attr.type = TypeDesc::TypeColor;
+
+				if(req.std != ATTR_STD_NONE) {
+					/* if standard attribute, add lookup by geom: name convention */
+					ustring stdname(string("geom:") + string(Attribute::standard_name(req.std)));
+					og->attribute_map[i*ATTR_PRIM_TYPES][stdname] = osl_attr;
+				}
+				else if(req.name != ustring()) {
+					/* add lookup by mesh attribute name */
+					og->attribute_map[i*ATTR_PRIM_TYPES][req.name] = osl_attr;
+				}
 			}
-			else if(req.name != ustring()) {
-				/* add lookup by mesh attribute name */
-				og->attribute_map[i][req.name] = osl_attr;
+
+			if(req.curve_element != ATTR_ELEMENT_NONE) {
+				osl_attr.elem = req.curve_element;
+				osl_attr.offset = req.curve_offset;
+
+				if(req.curve_type == TypeDesc::TypeFloat)
+					osl_attr.type = TypeDesc::TypeFloat;
+				else
+					osl_attr.type = TypeDesc::TypeColor;
+
+				if(req.std != ATTR_STD_NONE) {
+					/* if standard attribute, add lookup by geom: name convention */
+					ustring stdname(string("geom:") + string(Attribute::standard_name(req.std)));
+					og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][stdname] = osl_attr;
+				}
+				else if(req.name != ustring()) {
+					/* add lookup by mesh attribute name */
+					og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][req.name] = osl_attr;
+				}
 			}
 		}
 	}
@@ -480,7 +495,7 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
 	int attr_map_stride = 0;
 
 	for(size_t i = 0; i < scene->meshes.size(); i++)
-		attr_map_stride = max(attr_map_stride, mesh_attributes[i].size()+1);
+		attr_map_stride = max(attr_map_stride, (mesh_attributes[i].size() + 1)*ATTR_PRIM_TYPES);
 
 	if(attr_map_stride == 0)
 		return;
@@ -491,12 +506,13 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
 
 	for(size_t i = 0; i < scene->objects.size(); i++) {
 		Object *object = scene->objects[i];
+		Mesh *mesh = object->mesh;
 
 		/* find mesh attributes */
 		size_t j;
 
 		for(j = 0; j < scene->meshes.size(); j++)
-			if(scene->meshes[j] == object->mesh)
+			if(scene->meshes[j] == mesh)
 				break;
 
 		AttributeRequestSet& attributes = mesh_attributes[j];
@@ -512,14 +528,29 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
 			else
 				id = scene->shader_manager->get_attribute_id(req.std);
 
-			attr_map[index].x = id;
-			attr_map[index].y = req.element;
-			attr_map[index].z = as_uint(req.offset);
+			if(mesh->triangles.size()) {
+				attr_map[index].x = id;
+				attr_map[index].y = req.triangle_element;
+				attr_map[index].z = as_uint(req.triangle_offset);
 
-			if(req.type == TypeDesc::TypeFloat)
-				attr_map[index].w = NODE_ATTR_FLOAT;
-			else
-				attr_map[index].w = NODE_ATTR_FLOAT3;
+				if(req.triangle_type == TypeDesc::TypeFloat)
+					attr_map[index].w = NODE_ATTR_FLOAT;
+				else
+					attr_map[index].w = NODE_ATTR_FLOAT3;
+			}
+
+			index++;
+
+			if(mesh->curve_segments.size()) {
+				attr_map[index].x = id;
+				attr_map[index].y = req.curve_element;
+				attr_map[index].z = as_uint(req.curve_offset);
+
+				if(req.curve_type == TypeDesc::TypeFloat)
+					attr_map[index].w = NODE_ATTR_FLOAT;
+				else
+					attr_map[index].w = NODE_ATTR_FLOAT3;
+			}
 
 			index++;
 		}
@@ -529,6 +560,15 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
 		attr_map[index].y = 0;
 		attr_map[index].z = 0;
 		attr_map[index].w = 0;
+
+		index++;
+
+		attr_map[index].x = ATTR_STD_NONE;
+		attr_map[index].y = 0;
+		attr_map[index].z = 0;
+		attr_map[index].w = 0;
+
+		index++;
 	}
 
 	/* copy to device */
@@ -536,6 +576,60 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
 	device->tex_alloc("__attributes_map", dscene->attributes_map);
 }
 
+static void update_attribute_element_offset(Mesh *mesh, vector& attr_float, vector& attr_float3,
+	Attribute *mattr, TypeDesc& type, int& offset, AttributeElement& element)
+{
+	if(mattr) {
+		/* store element and type */
+		element = mattr->element;
+		type = mattr->type;
+
+		/* store attribute data in arrays */
+		size_t size = mattr->element_size(
+			mesh->verts.size(),
+			mesh->triangles.size(),
+			mesh->curve_segments.size(),
+			mesh->curve_keys.size());
+
+		if(mattr->type == TypeDesc::TypeFloat) {
+			float *data = mattr->data_float();
+			offset = attr_float.size();
+
+			attr_float.resize(attr_float.size() + size);
+
+			for(size_t k = 0; k < size; k++)
+				attr_float[offset+k] = data[k];
+		}
+		else {
+			float3 *data = mattr->data_float3();
+			offset = attr_float3.size();
+
+			attr_float3.resize(attr_float3.size() + size);
+
+			for(size_t k = 0; k < size; k++)
+				attr_float3[offset+k] = float3_to_float4(data[k]);
+		}
+
+		/* mesh vertex/curve index is global, not per object, so we sneak
+		 * a correction for that in here */
+		if(element == ATTR_ELEMENT_VERTEX)
+			offset -= mesh->vert_offset;
+		else if(element == ATTR_ELEMENT_FACE)
+			offset -= mesh->tri_offset;
+		else if(element == ATTR_ELEMENT_CORNER)
+			offset -= 3*mesh->tri_offset;
+		else if(element == ATTR_ELEMENT_CURVE_SEGMENT)
+			offset -= mesh->curveseg_offset;
+		else if(element == ATTR_ELEMENT_CURVE_KEY)
+			offset -= mesh->curvekey_offset;
+	}
+	else {
+		/* attribute not found */
+		element = ATTR_ELEMENT_NONE;
+		offset = 0;
+	}
+}
+
 void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
 {
 	progress.set_status("Updating Mesh", "Computing attributes");
@@ -569,66 +663,24 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
 		/* todo: we now store std and name attributes from requests even if
 		 * they actually refer to the same mesh attributes, optimize */
 		foreach(AttributeRequest& req, attributes.requests) {
-			Attribute *mattr = mesh->attributes.find(req);
-
-			/* todo: get rid of this exception */
-			if(!mattr && req.std == ATTR_STD_GENERATED) {
-				mattr = mesh->attributes.add(ATTR_STD_GENERATED);
+			Attribute *triangle_mattr = mesh->attributes.find(req);
+			Attribute *curve_mattr = mesh->curve_attributes.find(req);
+
+			/* todo: get rid of this exception, it's only here for giving some
+			 * working texture coordinate for subdivision as we can't preserve
+			 * any attributes yet */
+			if(!triangle_mattr && req.std == ATTR_STD_GENERATED) {
+				triangle_mattr = mesh->attributes.add(ATTR_STD_GENERATED);
 				if(mesh->verts.size())
-					memcpy(mattr->data_float3(), &mesh->verts[0], sizeof(float3)*mesh->verts.size());
+					memcpy(triangle_mattr->data_float3(), &mesh->verts[0], sizeof(float3)*mesh->verts.size());
 			}
 
-			/* attribute not found */
-			if(!mattr) {
-				req.element = ATTR_ELEMENT_NONE;
-				req.offset = 0;
-				continue;
-			}
-
-			/* we abuse AttributeRequest to pass on info like element and
-			 * offset, it doesn't really make sense but is convenient */
-
-			/* store element and type */
-			if(mattr->element == Attribute::VERTEX)
-				req.element = ATTR_ELEMENT_VERTEX;
-			else if(mattr->element == Attribute::FACE)
-				req.element = ATTR_ELEMENT_FACE;
-			else if(mattr->element == Attribute::CORNER)
-				req.element = ATTR_ELEMENT_CORNER;
-
-			req.type = mattr->type;
-
-			/* store attribute data in arrays */
-			size_t size = mattr->element_size(mesh->verts.size(), mesh->triangles.size());
-
-			if(mattr->type == TypeDesc::TypeFloat) {
-				float *data = mattr->data_float();
-				req.offset = attr_float.size();
-
-				attr_float.resize(attr_float.size() + size);
-
-				for(size_t k = 0; k < size; k++)
-					attr_float[req.offset+k] = data[k];
-			}
-			else {
-				float3 *data = mattr->data_float3();
-				req.offset = attr_float3.size();
-
-				attr_float3.resize(attr_float3.size() + size);
-
-				for(size_t k = 0; k < size; k++)
-					attr_float3[req.offset+k] = float3_to_float4(data[k]);
-			}
-
-			/* mesh vertex/triangle index is global, not per object, so we sneak
-			 * a correction for that in here */
-			if(req.element == ATTR_ELEMENT_VERTEX)
-				req.offset -= mesh->vert_offset;
-			else if(mattr->element == Attribute::FACE)
-				req.offset -= mesh->tri_offset;
-			else if(mattr->element == Attribute::CORNER)
-				req.offset -= 3*mesh->tri_offset;
+			update_attribute_element_offset(mesh, attr_float, attr_float3, triangle_mattr,
+				req.triangle_type, req.triangle_offset, req.triangle_element);
 
+			update_attribute_element_offset(mesh, attr_float, attr_float3, curve_mattr,
+				req.curve_type, req.curve_offset, req.curve_element);
+	
 			if(progress.get_cancel()) return;
 		}
 	}
@@ -660,21 +712,21 @@ void MeshManager::device_update_mesh(Device *device, DeviceScene *dscene, Scene
 	size_t vert_size = 0;
 	size_t tri_size = 0;
 
-	size_t CurveKey_size = 0;
+	size_t curve_key_size = 0;
 	size_t curve_seg_keys = 0;
 
 	foreach(Mesh *mesh, scene->meshes) {
 		mesh->vert_offset = vert_size;
 		mesh->tri_offset = tri_size;
 
-		mesh->curvekey_offset = CurveKey_size;
+		mesh->curvekey_offset = curve_key_size;
 		mesh->curveseg_offset = curve_seg_keys;
 
 		vert_size += mesh->verts.size();
 		tri_size += mesh->triangles.size();
 
-		CurveKey_size += mesh->curve_keys.size();
-		curve_seg_keys += mesh->curve_segs.size();
+		curve_key_size += mesh->curve_keys.size();
+		curve_seg_keys += mesh->curve_segments.size();
 	}
 
 	if(tri_size != 0) {
@@ -705,16 +757,16 @@ void MeshManager::device_update_mesh(Device *device, DeviceScene *dscene, Scene
 	if(curve_seg_keys != 0) {
 		progress.set_status("Updating Mesh", "Copying Strands to device");
 
-		float4 *cur_keys = dscene->cur_keys.resize(CurveKey_size);
-		float4 *cur_segs = dscene->cur_segs.resize(curve_seg_keys);
+		float4 *curve_keys = dscene->curve_keys.resize(curve_key_size);
+		float4 *curve_segments = dscene->curve_segments.resize(curve_seg_keys);
 
 		foreach(Mesh *mesh, scene->meshes) {
-			mesh->pack_curves(scene, &cur_keys[mesh->curvekey_offset], &cur_segs[mesh->curveseg_offset], mesh->curvekey_offset);
+			mesh->pack_curves(scene, &curve_keys[mesh->curvekey_offset], &curve_segments[mesh->curveseg_offset], mesh->curvekey_offset);
 			if(progress.get_cancel()) return;
 		}
 
-		device->tex_alloc("__cur_keys", dscene->cur_keys);
-		device->tex_alloc("__cur_segs", dscene->cur_segs);
+		device->tex_alloc("__curve_keys", dscene->curve_keys);
+		device->tex_alloc("__curve_segments", dscene->curve_segments);
 	}
 }
 
@@ -873,8 +925,8 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
 	device->tex_free(dscene->tri_vnormal);
 	device->tex_free(dscene->tri_vindex);
 	device->tex_free(dscene->tri_verts);
-	device->tex_free(dscene->cur_segs);
-	device->tex_free(dscene->cur_keys);
+	device->tex_free(dscene->curve_segments);
+	device->tex_free(dscene->curve_keys);
 	device->tex_free(dscene->attributes_map);
 	device->tex_free(dscene->attributes_float);
 	device->tex_free(dscene->attributes_float3);
@@ -890,8 +942,8 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
 	dscene->tri_vnormal.clear();
 	dscene->tri_vindex.clear();
 	dscene->tri_verts.clear();
-	dscene->cur_segs.clear();
-	dscene->cur_keys.clear();
+	dscene->curve_segments.clear();
+	dscene->curve_keys.clear();
 	dscene->attributes_map.clear();
 	dscene->attributes_float.clear();
 	dscene->attributes_float3.clear();
diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h
index 24d3f02e082..ca8c755671f 100644
--- a/intern/cycles/render/mesh.h
+++ b/intern/cycles/render/mesh.h
@@ -50,26 +50,16 @@ public:
 		int v[3];
 	};
 
-	/* Mesh Strand Data*/
-	struct CurveSeg {
+	/* Mesh Curve */
+	struct CurveSegment {
 		int v[2];
-		uint curveshader;
+		uint shader;
 		int curve;
 	};
 
-	struct Curve_Attribute {
-		float uv[2];
-	};
-
 	struct CurveKey {
-		float3 loc;
+		float3 co;
 		float radius;
-		float time;
-	};
-
-	/*curve data for hair - currently only contains key tangent instead*/
-	struct CurveData {
-		float3 tg;
 	};
 
 	/* Displacement */
@@ -88,12 +78,11 @@ public:
 	vector smooth;
 
 	vector curve_keys;
-	vector curve_keysCD;
-	vector curve_segs;
-	vector curve_attrib;
+	vector curve_segments;
 
 	vector used_shaders;
 	AttributeSet attributes;
+	AttributeSet curve_attributes;
 
 	BoundBox bounds;
 	bool transform_applied;
@@ -116,12 +105,11 @@ public:
 	Mesh();
 	~Mesh();
 
-	void reserve(int numverts, int numfaces);
+	void reserve(int numverts, int numfaces, int numcurves, int numcurvekeys);
 	void clear();
 	void add_triangle(int v0, int v1, int v2, int shader, bool smooth);
-	void add_curvekey(float3 loc, float radius, float time);
-	void add_curve(int v0, int v1, int shader, int curveid);
-	void add_curveattrib(float u, float v);
+	void add_curve_key(float3 loc, float radius);
+	void add_curve_segment(int v0, int v1, int shader, int curveid);
 
 	void compute_bounds();
 	void add_face_normals();
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 13e9ae81cf0..14ef3c68ad3 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -2251,6 +2251,16 @@ HairInfoNode::HairInfoNode()
 	add_output("Tangent Normal", SHADER_SOCKET_NORMAL);
 }
 
+void HairInfoNode::attributes(AttributeRequestSet *attributes)
+{
+	ShaderOutput *intercept_out = output("Intercept");
+
+	if(!intercept_out->links.empty())
+		attributes->add(ATTR_STD_CURVE_INTERCEPT);
+	
+	ShaderNode::attributes(attributes);
+}
+
 void HairInfoNode::compile(SVMCompiler& compiler)
 {
 	ShaderOutput *out;
@@ -2263,8 +2273,9 @@ void HairInfoNode::compile(SVMCompiler& compiler)
 
 	out = output("Intercept");
 	if(!out->links.empty()) {
+		int attr = compiler.attribute(ATTR_STD_CURVE_INTERCEPT);
 		compiler.stack_assign(out);
-		compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_INTERCEPT, out->stack_offset);
+		compiler.add_node(NODE_ATTR, attr, out->stack_offset, NODE_ATTR_FLOAT);
 	}
 
 	out = output("Thickness");
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index ee7afccb0e1..564ceee5a5b 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -334,6 +334,8 @@ public:
 class HairInfoNode : public ShaderNode {
 public:
 	SHADER_NODE_CLASS(HairInfoNode)
+
+	void attributes(AttributeRequestSet *attributes);
 };
 
 class ValueNode : public ShaderNode {
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index 588b4d50e1b..4862b47c342 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -89,12 +89,9 @@ void Object::apply_transform()
 		mesh->verts[i] = transform_point(&tfm, mesh->verts[i]);
 
 	for(size_t i = 0; i < mesh->curve_keys.size(); i++)
-		mesh->curve_keys[i].loc = transform_point(&tfm, mesh->curve_keys[i].loc);
-
-	for(size_t i = 0; i < mesh->curve_keysCD.size(); i++)
-		mesh->curve_keysCD[i].tg = transform_direction(&tfm, mesh->curve_keysCD[i].tg);
-
+		mesh->curve_keys[i].co = transform_point(&tfm, mesh->curve_keys[i].co);
 
+	Attribute *attr_tangent = mesh->curve_attributes.find(ATTR_STD_CURVE_TANGENT);
 	Attribute *attr_fN = mesh->attributes.find(ATTR_STD_FACE_NORMAL);
 	Attribute *attr_vN = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL);
 
@@ -119,6 +116,13 @@ void Object::apply_transform()
 			vN[i] = transform_direction(&ntfm, vN[i]);
 	}
 
+	if(attr_tangent) {
+		float3 *tangent = attr_tangent->data_float3();
+
+		for(size_t i = 0; i < mesh->curve_keys.size(); i++)
+			tangent[i] = transform_direction(&tfm, tangent[i]);
+	}
+
 	if(bounds.valid()) {
 		mesh->compute_bounds();
 		compute_bounds(false, 0.0f);
@@ -199,10 +203,10 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
 					surface_area += triangle_area(p1, p2, p3);
 				}
 
-				foreach(Mesh::CurveSeg& t, mesh->curve_segs) {
-					float3 p1 = mesh->curve_keys[t.v[0]].loc;
+				foreach(Mesh::CurveSegment& t, mesh->curve_segments) {
+					float3 p1 = mesh->curve_keys[t.v[0]].co;
 					float r1 = mesh->curve_keys[t.v[0]].radius;
-					float3 p2 = mesh->curve_keys[t.v[1]].loc;
+					float3 p2 = mesh->curve_keys[t.v[1]].co;
 					float r2 = mesh->curve_keys[t.v[1]].radius;
 
 					/* currently ignores segment overlaps*/
@@ -225,10 +229,10 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
 				surface_area += triangle_area(p1, p2, p3);
 			}
 
-			foreach(Mesh::CurveSeg& t, mesh->curve_segs) {
-				float3 p1 = mesh->curve_keys[t.v[0]].loc;
+			foreach(Mesh::CurveSegment& t, mesh->curve_segments) {
+				float3 p1 = mesh->curve_keys[t.v[0]].co;
 				float r1 = mesh->curve_keys[t.v[0]].radius;
-				float3 p2 = mesh->curve_keys[t.v[1]].loc;
+				float3 p2 = mesh->curve_keys[t.v[1]].co;
 				float r2 = mesh->curve_keys[t.v[1]].radius;
 
 				/* currently ignores segment overlaps*/
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index 8b121d3b2fb..9490fd96be0 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -25,7 +25,6 @@
 
 #include "kernel_types.h"
 
-#include "util_attribute.h"
 #include "util_param.h"
 #include "util_string.h"
 #include "util_thread.h"
@@ -74,8 +73,8 @@ public:
 	device_vector tri_vindex;
 	device_vector tri_verts;
 
-	device_vector cur_segs;
-	device_vector cur_keys;
+	device_vector curve_segments;
+	device_vector curve_keys;
 
 	/* objects */
 	device_vector objects;
diff --git a/intern/cycles/subd/subd_dice.cpp b/intern/cycles/subd/subd_dice.cpp
index 6920df9954c..48e6808bc38 100644
--- a/intern/cycles/subd/subd_dice.cpp
+++ b/intern/cycles/subd/subd_dice.cpp
@@ -47,7 +47,7 @@ void EdgeDice::reserve(int num_verts, int num_tris)
 	vert_offset = mesh->verts.size();
 	tri_offset = mesh->triangles.size();
 
-	mesh->reserve(vert_offset + num_verts, tri_offset + num_tris);
+	mesh->reserve(vert_offset + num_verts, tri_offset + num_tris, 0, 0);
 
 	Attribute *attr_vN = mesh->attributes.add(ATTR_STD_VERTEX_NORMAL);
 
diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt
index dce417704cc..bcaaa9a71b9 100644
--- a/intern/cycles/util/CMakeLists.txt
+++ b/intern/cycles/util/CMakeLists.txt
@@ -9,7 +9,6 @@ set(INC_SYS
 )
 
 set(SRC
-	util_attribute.cpp
 	util_cache.cpp
 	util_cuda.cpp
 	util_dynlib.cpp
@@ -33,7 +32,6 @@ endif()
 set(SRC_HEADERS
 	util_algorithm.h
 	util_args.h
-	util_attribute.h
 	util_boundbox.h
 	util_cache.h
 	util_cuda.h
diff --git a/intern/cycles/util/util_attribute.cpp b/intern/cycles/util/util_attribute.cpp
deleted file mode 100644
index 057fb6213e9..00000000000
--- a/intern/cycles/util/util_attribute.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2011, 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.
- */
-
-#include "util_attribute.h"
-
-CCL_NAMESPACE_BEGIN
-
-const char *attribute_standard_name(AttributeStandard std)
-{
-	if(std == ATTR_STD_VERTEX_NORMAL)
-		return "N";
-	else if(std == ATTR_STD_FACE_NORMAL)
-		return "Ng";
-	else if(std == ATTR_STD_UV)
-		return "uv";
-	else if(std == ATTR_STD_GENERATED)
-		return "generated";
-	else if(std == ATTR_STD_UV_TANGENT)
-		return "tangent";
-	else if(std == ATTR_STD_UV_TANGENT_SIGN)
-		return "tangent_sign";
-	else if(std == ATTR_STD_POSITION_UNDEFORMED)
-		return "undeformed";
-	else if(std == ATTR_STD_POSITION_UNDISPLACED)
-		return "undisplaced";
-	else if(std == ATTR_STD_MOTION_PRE)
-		return "motion_pre";
-	else if(std == ATTR_STD_MOTION_POST)
-		return "motion_post";
-	else if(std == ATTR_STD_PARTICLE)
-		return "particle";
-	
-	return "";
-}
-
-CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_attribute.h b/intern/cycles/util/util_attribute.h
deleted file mode 100644
index 334864c7f44..00000000000
--- a/intern/cycles/util/util_attribute.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2011, 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.
- */
-
-#ifndef __UTIL_ATTRIBUTE_H__
-#define __UTIL_ATTRIBUTE_H__
-
-#include "util_types.h"
-
-CCL_NAMESPACE_BEGIN
-
-const char *attribute_standard_name(AttributeStandard std);
-
-CCL_NAMESPACE_END
-
-#endif /* __UTIL_ATTRIBUTE_H__ */
-
diff --git a/intern/cycles/util/util_types.h b/intern/cycles/util/util_types.h
index 00b6cf5c56e..bb6de1197e7 100644
--- a/intern/cycles/util/util_types.h
+++ b/intern/cycles/util/util_types.h
@@ -448,24 +448,6 @@ __device_inline int4 make_int4(const float3& f)
 
 #endif
 
-typedef enum AttributeStandard {
-	ATTR_STD_NONE = 0,
-	ATTR_STD_VERTEX_NORMAL,
-	ATTR_STD_FACE_NORMAL,
-	ATTR_STD_UV,
-	ATTR_STD_UV_TANGENT,
-	ATTR_STD_UV_TANGENT_SIGN,
-	ATTR_STD_GENERATED,
-	ATTR_STD_POSITION_UNDEFORMED,
-	ATTR_STD_POSITION_UNDISPLACED,
-	ATTR_STD_MOTION_PRE,
-	ATTR_STD_MOTION_POST,
-	ATTR_STD_PARTICLE,
-	ATTR_STD_NUM,
-
-	ATTR_STD_NOT_FOUND = ~0
-} AttributeStandard;
-
 CCL_NAMESPACE_END
 
 #endif /* __UTIL_TYPES_H__ */
-- 
cgit v1.2.3


From bf25f1ea96d01b513907cf3067e8e2dd3c7e41b4 Mon Sep 17 00:00:00 2001
From: Brecht Van Lommel 
Date: Thu, 3 Jan 2013 12:09:09 +0000
Subject: Cycles Hair: refactoring to store curves with the index of the first
 key and the number of keys in the curve, rather than curve segments with the
 indices of two keys. ShaderData.segment now stores the segment number in the
 curve.

---
 intern/cycles/blender/blender_curves.cpp  | 28 ++++-----
 intern/cycles/bvh/bvh.cpp                 | 64 ++++++++++----------
 intern/cycles/bvh/bvh.h                   |  4 +-
 intern/cycles/bvh/bvh_build.cpp           | 62 +++++++++++--------
 intern/cycles/bvh/bvh_build.h             |  4 +-
 intern/cycles/bvh/bvh_params.h            |  8 +--
 intern/cycles/bvh/bvh_sort.cpp            |  4 +-
 intern/cycles/bvh/bvh_split.cpp           | 16 ++---
 intern/cycles/kernel/kernel_bvh.h         | 47 ++++++++-------
 intern/cycles/kernel/kernel_curve.h       | 43 +++++++-------
 intern/cycles/kernel/kernel_emission.h    |  2 +-
 intern/cycles/kernel/kernel_light.h       | 26 ++++----
 intern/cycles/kernel/kernel_primitive.h   |  8 +--
 intern/cycles/kernel/kernel_shader.h      | 32 +++++-----
 intern/cycles/kernel/kernel_textures.h    |  4 +-
 intern/cycles/kernel/kernel_types.h       |  7 ++-
 intern/cycles/kernel/osl/osl_services.cpp | 12 ++--
 intern/cycles/kernel/osl/osl_shader.cpp   |  2 +-
 intern/cycles/kernel/svm/svm_attribute.h  |  2 +-
 intern/cycles/kernel/svm/svm_geometry.h   |  2 +-
 intern/cycles/render/attribute.cpp        | 10 ++--
 intern/cycles/render/light.cpp            | 73 +++++++++++++----------
 intern/cycles/render/mesh.cpp             | 99 +++++++++++++++----------------
 intern/cycles/render/mesh.h               | 17 +++---
 intern/cycles/render/object.cpp           | 41 ++++++++-----
 intern/cycles/render/scene.h              |  4 +-
 26 files changed, 331 insertions(+), 290 deletions(-)

diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp
index 61628aae535..2e9a32f15f2 100644
--- a/intern/cycles/blender/blender_curves.cpp
+++ b/intern/cycles/blender/blender_curves.cpp
@@ -652,11 +652,10 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int inter
 
 void ExportCurveSegments(Mesh *mesh, ParticleCurveData *CData, int interpolation, int segments)
 {
-	int cks = 0;
-	int curs = 0;
-	int segs = 0;
+	int num_keys = 0;
+	int num_curves = 0;
 
-	if(!(mesh->curve_segments.empty() && mesh->curve_keys.empty()))
+	if(!(mesh->curves.empty() && mesh->curve_keys.empty()))
 		return;
 
 	Attribute *attr_uv = mesh->curve_attributes.add(ATTR_STD_UV);
@@ -672,6 +671,8 @@ void ExportCurveSegments(Mesh *mesh, ParticleCurveData *CData, int interpolation
 			if(CData->curve_keynum[curve] <= 1)
 				continue;
 
+			size_t num_curve_keys = 0;
+
 			for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
 
 				int subv = 1;
@@ -696,26 +697,23 @@ void ExportCurveSegments(Mesh *mesh, ParticleCurveData *CData, int interpolation
 					mesh->add_curve_key(ickey_loc, radius);
 					attr_intercept->add(time);
 
-					if(subv != 0) {
-						attr_uv->add(CData->curve_uv[curve]);
-						mesh->add_curve_segment(cks - 1, cks, CData->psys_shader[sys], curs);
-						segs++;
-					}
-
-					cks++;
+					num_curve_keys++;
 				}
 			}
 
-			curs++;
+			mesh->add_curve(num_keys, num_curve_keys, CData->psys_shader[sys]);
+			attr_uv->add(CData->curve_uv[curve]);
 
+			num_keys += num_curve_keys;
+			num_curves++;
 		}
 	}
 
 	/* check allocation*/
-	if((mesh->curve_keys.size() !=  cks) || (mesh->curve_segments.size() !=  segs)) {
+	if((mesh->curve_keys.size() !=  num_keys) || (mesh->curves.size() !=  num_curves)) {
 		/* allocation failed -> clear data */
 		mesh->curve_keys.clear();
-		mesh->curve_segments.clear();
+		mesh->curves.clear();
 		mesh->curve_attributes.clear();
 	}
 }
@@ -824,7 +822,7 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool
 {
 	/* Clear stored curve data */
 	mesh->curve_keys.clear();
-	mesh->curve_segments.clear();
+	mesh->curves.clear();
 	mesh->curve_attributes.clear();
 
 	/* obtain general settings */
diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp
index 0b43704b7b8..412b44031e6 100644
--- a/intern/cycles/bvh/bvh.cpp
+++ b/intern/cycles/bvh/bvh.cpp
@@ -76,7 +76,7 @@ bool BVH::cache_read(CacheData& key)
 		key.add(ob->mesh->verts);
 		key.add(ob->mesh->triangles);
 		key.add(ob->mesh->curve_keys);
-		key.add(ob->mesh->curve_segments);
+		key.add(ob->mesh->curves);
 		key.add(&ob->bounds, sizeof(ob->bounds));
 		key.add(&ob->visibility, sizeof(ob->visibility));
 		key.add(&ob->mesh->transform_applied, sizeof(bool));
@@ -93,7 +93,7 @@ bool BVH::cache_read(CacheData& key)
 		value.read(pack.nodes);
 		value.read(pack.object_node);
 		value.read(pack.tri_woop);
-		value.read(pack.prim_type);
+		value.read(pack.prim_segment);
 		value.read(pack.prim_visibility);
 		value.read(pack.prim_index);
 		value.read(pack.prim_object);
@@ -115,7 +115,7 @@ void BVH::cache_write(CacheData& key)
 	value.add(pack.nodes);
 	value.add(pack.object_node);
 	value.add(pack.tri_woop);
-	value.add(pack.prim_type);
+	value.add(pack.prim_segment);
 	value.add(pack.prim_visibility);
 	value.add(pack.prim_index);
 	value.add(pack.prim_object);
@@ -161,11 +161,11 @@ void BVH::build(Progress& progress)
 	}
 
 	/* build nodes */
-	vector prim_type;
+	vector prim_segment;
 	vector prim_index;
 	vector prim_object;
 
-	BVHBuild bvh_build(objects, prim_type, prim_index, prim_object, params, progress);
+	BVHBuild bvh_build(objects, prim_segment, prim_index, prim_object, params, progress);
 	BVHNode *root = bvh_build.run();
 
 	if(progress.get_cancel()) {
@@ -174,7 +174,7 @@ void BVH::build(Progress& progress)
 	}
 
 	/* todo: get rid of this copy */
-	pack.prim_type = prim_type;
+	pack.prim_segment = prim_segment;
 	pack.prim_index = prim_index;
 	pack.prim_object = prim_object;
 
@@ -271,13 +271,16 @@ void BVH::pack_triangle(int idx, float4 woop[3])
 
 /* Curves*/
 
-void BVH::pack_curve_seg(int idx, float4 woop[3])
+void BVH::pack_curve_segment(int idx, float4 woop[3])
 {
 	int tob = pack.prim_object[idx];
 	const Mesh *mesh = objects[tob]->mesh;
 	int tidx = pack.prim_index[idx];
-	float3 v0 = mesh->curve_keys[mesh->curve_segments[tidx].v[0]].co;
-	float3 v1 = mesh->curve_keys[mesh->curve_segments[tidx].v[1]].co;
+	int segment = pack.prim_segment[idx];
+	int k0 = mesh->curves[tidx].first_key + segment;
+	int k1 = mesh->curves[tidx].first_key + segment + 1;
+	float3 v0 = mesh->curve_keys[k0].co;
+	float3 v1 = mesh->curve_keys[k1].co;
 
 	float3 d0 = v1 - v0;
 	float l =  len(d0);
@@ -289,19 +292,19 @@ void BVH::pack_curve_seg(int idx, float4 woop[3])
 	*	nextkey, flags/tip?,    0, 0);
 	*/
 	Attribute *attr_tangent = mesh->curve_attributes.find(ATTR_STD_CURVE_TANGENT);
+	float3 tg0 = make_float3(1.0f, 0.0f, 0.0f);
 	float3 tg1 = make_float3(1.0f, 0.0f, 0.0f);
-	float3 tg2 = make_float3(1.0f, 0.0f, 0.0f);
 
 	if(attr_tangent) {
 		const float3 *data_tangent = attr_tangent->data_float3();
 
-		tg1 = data_tangent[mesh->curve_segments[tidx].v[0]];
-		tg2 = data_tangent[mesh->curve_segments[tidx].v[1]];
+		tg0 = data_tangent[k0];
+		tg1 = data_tangent[k1];
 	}
 	
 	Transform tfm = make_transform(
-		tg1.x, tg1.y, tg1.z, l,
-		tg2.x, tg2.y, tg2.z, 0,
+		tg0.x, tg0.y, tg0.z, l,
+		tg1.x, tg1.y, tg1.z, 0,
 		0, 0, 0, 0,
 		0, 0, 0, 1);
 
@@ -325,8 +328,8 @@ void BVH::pack_primitives()
 		if(pack.prim_index[i] != -1) {
 			float4 woop[3];
 
-			if(pack.prim_type[i])
-				pack_curve_seg(i, woop);
+			if(pack.prim_segment[i] != ~0)
+				pack_curve_segment(i, woop);
 			else
 				pack_triangle(i, woop);
 			
@@ -353,8 +356,8 @@ void BVH::pack_instances(size_t nodes_size)
 	 * meshes with transform applied and already in the top level BVH */
 	for(size_t i = 0; i < pack.prim_index.size(); i++)
 		if(pack.prim_index[i] != -1) {
-			if(pack.prim_type[i])
-				pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->curveseg_offset;
+			if(pack.prim_segment[i] != ~0)
+				pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->curve_offset;
 			else
 				pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->tri_offset;
 		}
@@ -395,7 +398,7 @@ void BVH::pack_instances(size_t nodes_size)
 	mesh_map.clear();
 
 	pack.prim_index.resize(prim_index_size);
-	pack.prim_type.resize(prim_index_size);
+	pack.prim_segment.resize(prim_index_size);
 	pack.prim_object.resize(prim_index_size);
 	pack.prim_visibility.resize(prim_index_size);
 	pack.tri_woop.resize(tri_woop_size);
@@ -403,7 +406,7 @@ void BVH::pack_instances(size_t nodes_size)
 	pack.object_node.resize(objects.size());
 
 	int *pack_prim_index = (pack.prim_index.size())? &pack.prim_index[0]: NULL;
-	int *pack_prim_type = (pack.prim_type.size())? &pack.prim_type[0]: NULL;
+	int *pack_prim_segment = (pack.prim_segment.size())? &pack.prim_segment[0]: NULL;
 	int *pack_prim_object = (pack.prim_object.size())? &pack.prim_object[0]: NULL;
 	uint *pack_prim_visibility = (pack.prim_visibility.size())? &pack.prim_visibility[0]: NULL;
 	float4 *pack_tri_woop = (pack.tri_woop.size())? &pack.tri_woop[0]: NULL;
@@ -434,7 +437,7 @@ void BVH::pack_instances(size_t nodes_size)
 
 		int noffset = nodes_offset/nsize;
 		int mesh_tri_offset = mesh->tri_offset;
-		int mesh_curve_offset = mesh->curveseg_offset;
+		int mesh_curve_offset = mesh->curve_offset;
 
 		/* fill in node indexes for instances */
 		if((bvh->pack.is_leaf.size() != 0) && bvh->pack.is_leaf[0])
@@ -448,16 +451,16 @@ void BVH::pack_instances(size_t nodes_size)
 		if(bvh->pack.prim_index.size()) {
 			size_t bvh_prim_index_size = bvh->pack.prim_index.size();
 			int *bvh_prim_index = &bvh->pack.prim_index[0];
-			int *bvh_prim_type = &bvh->pack.prim_type[0];
+			int *bvh_prim_segment = &bvh->pack.prim_segment[0];
 			uint *bvh_prim_visibility = &bvh->pack.prim_visibility[0];
 
 			for(size_t i = 0; i < bvh_prim_index_size; i++) {
-				if(bvh->pack.prim_type[i])
+				if(bvh->pack.prim_segment[i] != ~0)
 					pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_curve_offset;
 				else
 					pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_tri_offset;
 
-				pack_prim_type[pack_prim_index_offset] = bvh_prim_type[i];
+				pack_prim_segment[pack_prim_index_offset] = bvh_prim_segment[i];
 				pack_prim_visibility[pack_prim_index_offset] = bvh_prim_visibility[i];
 				pack_prim_object[pack_prim_index_offset] = 0;  // unused for instances
 				pack_prim_index_offset++;
@@ -622,13 +625,14 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility
 				/* primitives */
 				const Mesh *mesh = ob->mesh;
 
-				if(pack.prim_type[prim]) {
-					/* strands */
-					int str_offset = (params.top_level)? mesh->curveseg_offset: 0;
-					const int *hidx = mesh->curve_segments[pidx - str_offset].v;
+				if(pack.prim_segment[prim] != ~0) {
+					/* curves */
+					int str_offset = (params.top_level)? mesh->curve_offset: 0;
+					int k0 = mesh->curves[pidx - str_offset].first_key + pack.prim_segment[prim]; // XXX!
+					int k1 = k0 + 1;
 
-					bbox.grow(mesh->curve_keys[hidx[0]].co, mesh->curve_keys[hidx[0]].radius);
-					bbox.grow(mesh->curve_keys[hidx[1]].co, mesh->curve_keys[hidx[1]].radius);
+					bbox.grow(mesh->curve_keys[k0].co, mesh->curve_keys[k0].radius);
+					bbox.grow(mesh->curve_keys[k1].co, mesh->curve_keys[k1].radius);
 				}
 				else {
 					/* triangles */
diff --git a/intern/cycles/bvh/bvh.h b/intern/cycles/bvh/bvh.h
index d81bb312148..00c146143b8 100644
--- a/intern/cycles/bvh/bvh.h
+++ b/intern/cycles/bvh/bvh.h
@@ -53,7 +53,7 @@ struct PackedBVH {
 	/* precomputed triangle intersection data, one triangle is 4x float4 */
 	array tri_woop;
 	/* primitive type - triangle or strand (should be moved to flag?) */
-	array prim_type;
+	array prim_segment;
 	/* visibility visibilitys for primitives */
 	array prim_visibility;
 	/* mapping from BVH primitive index to true primitive index, as primitives
@@ -106,7 +106,7 @@ protected:
 	/* triangles and strands*/
 	void pack_primitives();
 	void pack_triangle(int idx, float4 woop[3]);
-	void pack_curve_seg(int idx, float4 woop[3]);
+	void pack_curve_segment(int idx, float4 woop[3]);
 
 	/* merge instance BVH's */
 	void pack_instances(size_t nodes_size);
diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp
index 665c783b2d8..38fb1a15a13 100644
--- a/intern/cycles/bvh/bvh_build.cpp
+++ b/intern/cycles/bvh/bvh_build.cpp
@@ -48,10 +48,10 @@ public:
 /* Constructor / Destructor */
 
 BVHBuild::BVHBuild(const vector& objects_,
-	vector& prim_type_, vector& prim_index_, vector& prim_object_,
+	vector& prim_segment_, vector& prim_index_, vector& prim_object_,
 	const BVHParams& params_, Progress& progress_)
 : objects(objects_),
-  prim_type(prim_type_),
+  prim_segment(prim_segment_),
   prim_index(prim_index_),
   prim_object(prim_object_),
   params(params_),
@@ -74,30 +74,34 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh,
 		BoundBox bounds = BoundBox::empty;
 
 		for(int k = 0; k < 3; k++) {
-			float3 pt = mesh->verts[t.v[k]];
-			bounds.grow(pt);
+			float3 co = mesh->verts[t.v[k]];
+			bounds.grow(co);
 		}
 
 		if(bounds.valid()) {
-			references.push_back(BVHReference(bounds, j, i, false));
+			references.push_back(BVHReference(bounds, j, i, ~0));
 			root.grow(bounds);
 			center.grow(bounds.center2());
 		}
 	}
 
-	for(uint j = 0; j < mesh->curve_segments.size(); j++) {
-		Mesh::CurveSegment s = mesh->curve_segments[j];
-		BoundBox bounds = BoundBox::empty;
+	for(uint j = 0; j < mesh->curves.size(); j++) {
+		Mesh::Curve curve = mesh->curves[j];
 
-		for(int k = 0; k < 2; k++) {
-			float3 pt = mesh->curve_keys[s.v[k]].co;
-			bounds.grow(pt, mesh->curve_keys[s.v[k]].radius);
-		}
+		for(int k = 0; k < curve.num_keys - 1; k++) {
+			BoundBox bounds = BoundBox::empty;
 
-		if(bounds.valid()) {
-			references.push_back(BVHReference(bounds, j, i, true));
-			root.grow(bounds);
-			center.grow(bounds.center2());
+			float3 co0 = mesh->curve_keys[curve.first_key + k].co;
+			float3 co1 = mesh->curve_keys[curve.first_key + k + 1].co;
+
+			bounds.grow(co0, mesh->curve_keys[curve.first_key + k].radius);
+			bounds.grow(co1, mesh->curve_keys[curve.first_key + k + 1].radius);
+
+			if(bounds.valid()) {
+				references.push_back(BVHReference(bounds, j, i, k));
+				root.grow(bounds);
+				center.grow(bounds.center2());
+			}
 		}
 	}
 }
@@ -109,6 +113,16 @@ void BVHBuild::add_reference_object(BoundBox& root, BoundBox& center, Object *ob
 	center.grow(ob->bounds.center2());
 }
 
+static size_t count_curve_segments(Mesh *mesh)
+{
+	size_t num = 0, num_curves = mesh->curves.size();
+
+	for(size_t i = 0; i < num_curves; i++)
+		num += mesh->curves[i].num_keys - 1;
+	
+	return num;
+}
+
 void BVHBuild::add_references(BVHRange& root)
 {
 	/* reserve space for references */
@@ -118,14 +132,14 @@ void BVHBuild::add_references(BVHRange& root)
 		if(params.top_level) {
 			if(ob->mesh->transform_applied) {
 				num_alloc_references += ob->mesh->triangles.size();
-				num_alloc_references += ob->mesh->curve_segments.size();
+				num_alloc_references += count_curve_segments(ob->mesh);
 			}
 			else
 				num_alloc_references++;
 		}
 		else {
 			num_alloc_references += ob->mesh->triangles.size();
-			num_alloc_references += ob->mesh->curve_segments.size();
+			num_alloc_references += count_curve_segments(ob->mesh);
 		}
 	}
 
@@ -183,7 +197,7 @@ BVHNode* BVHBuild::run()
 	progress_total = references.size();
 	progress_original_total = progress_total;
 
-	prim_type.resize(references.size());
+	prim_segment.resize(references.size());
 	prim_index.resize(references.size());
 	prim_object.resize(references.size());
 
@@ -341,12 +355,12 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start,
 		if(start == prim_index.size()) {
 			assert(params.use_spatial_split);
 
-			prim_type.push_back(ref->prim_type());
+			prim_segment.push_back(ref->prim_segment());
 			prim_index.push_back(ref->prim_index());
 			prim_object.push_back(ref->prim_object());
 		}
 		else {
-			prim_type[start] = ref->prim_type();
+			prim_segment[start] = ref->prim_segment();
 			prim_index[start] = ref->prim_index();
 			prim_object[start] = ref->prim_object();
 		}
@@ -369,7 +383,7 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start,
 
 BVHNode* BVHBuild::create_leaf_node(const BVHRange& range)
 {
-	vector& p_type = prim_type;
+	vector& p_segment = prim_segment;
 	vector& p_index = prim_index;
 	vector& p_object = prim_object;
 	BoundBox bounds = BoundBox::empty;
@@ -383,12 +397,12 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range)
 			if(range.start() + num == prim_index.size()) {
 				assert(params.use_spatial_split);
 
-				p_type.push_back(ref.prim_type());
+				p_segment.push_back(ref.prim_segment());
 				p_index.push_back(ref.prim_index());
 				p_object.push_back(ref.prim_object());
 			}
 			else {
-				p_type[range.start() + num] = ref.prim_type();
+				p_segment[range.start() + num] = ref.prim_segment();
 				p_index[range.start() + num] = ref.prim_index();
 				p_object[range.start() + num] = ref.prim_object();
 			}
diff --git a/intern/cycles/bvh/bvh_build.h b/intern/cycles/bvh/bvh_build.h
index ba10eb49412..3df4da1739a 100644
--- a/intern/cycles/bvh/bvh_build.h
+++ b/intern/cycles/bvh/bvh_build.h
@@ -44,7 +44,7 @@ public:
 	/* Constructor/Destructor */
 	BVHBuild(
 		const vector& objects,
-		vector& prim_type,
+		vector& prim_segment,
 		vector& prim_index,
 		vector& prim_object,
 		const BVHParams& params,
@@ -88,7 +88,7 @@ protected:
 	int num_original_references;
 
 	/* output primitive indexes and objects */
-	vector& prim_type;
+	vector& prim_segment;
 	vector& prim_index;
 	vector& prim_object;
 
diff --git a/intern/cycles/bvh/bvh_params.h b/intern/cycles/bvh/bvh_params.h
index 7a1555ae548..f7bc79f71e6 100644
--- a/intern/cycles/bvh/bvh_params.h
+++ b/intern/cycles/bvh/bvh_params.h
@@ -98,22 +98,22 @@ class BVHReference
 public:
 	__forceinline BVHReference() {}
 
-	__forceinline BVHReference(const BoundBox& bounds_, int prim_index_, int prim_object_, int prim_type)
+	__forceinline BVHReference(const BoundBox& bounds_, int prim_index_, int prim_object_, int prim_segment)
 	: rbounds(bounds_)
 	{
 		rbounds.min.w = __int_as_float(prim_index_);
 		rbounds.max.w = __int_as_float(prim_object_);
-		type = prim_type;
+		segment = prim_segment;
 	}
 
 	__forceinline const BoundBox& bounds() const { return rbounds; }
 	__forceinline int prim_index() const { return __float_as_int(rbounds.min.w); }
 	__forceinline int prim_object() const { return __float_as_int(rbounds.max.w); }
-	__forceinline int prim_type() const { return type; }
+	__forceinline int prim_segment() const { return segment; }
 
 protected:
 	BoundBox rbounds;
-	uint type;
+	uint segment;
 };
 
 /* BVH Range
diff --git a/intern/cycles/bvh/bvh_sort.cpp b/intern/cycles/bvh/bvh_sort.cpp
index 9a8961c8b15..91994be5b96 100644
--- a/intern/cycles/bvh/bvh_sort.cpp
+++ b/intern/cycles/bvh/bvh_sort.cpp
@@ -43,8 +43,8 @@ public:
 		else if(ra.prim_object() > rb.prim_object()) return false;
 		else if(ra.prim_index() < rb.prim_index()) return true;
 		else if(ra.prim_index() > rb.prim_index()) return false;
-		else if(ra.prim_type() < rb.prim_type()) return true;
-		else if(ra.prim_type() > rb.prim_type()) return false;
+		else if(ra.prim_segment() < rb.prim_segment()) return true;
+		else if(ra.prim_segment() > rb.prim_segment()) return false;
 
 		return false;
 	}
diff --git a/intern/cycles/bvh/bvh_split.cpp b/intern/cycles/bvh/bvh_split.cpp
index 67fdfd77657..03ff69d7b6d 100644
--- a/intern/cycles/bvh/bvh_split.cpp
+++ b/intern/cycles/bvh/bvh_split.cpp
@@ -253,7 +253,7 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH
 	Object *ob = builder->objects[ref.prim_object()];
 	const Mesh *mesh = ob->mesh;
 
-	if (!ref.prim_type()) {
+	if (ref.prim_segment() == ~0) {
 		const int *inds = mesh->triangles[ref.prim_index()].v;
 		const float3 *verts = &mesh->verts[0];
 		const float3* v1 = &verts[inds[2]];
@@ -281,11 +281,11 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH
 		}
 	}
 	else {
-		/* Strand split: NOTE - Currently ignores strand width and needs to be fixed.*/
-
-		const int *inds = mesh->curve_segments[ref.prim_index()].v;
-		const float3* v0 = &mesh->curve_keys[inds[0]].co;
-		const float3* v1 = &mesh->curve_keys[inds[1]].co;
+		/* curve split: NOTE - Currently ignores curve width and needs to be fixed.*/
+		const int k0 = mesh->curves[ref.prim_index()].first_key + ref.prim_segment();
+		const int k1 = k0 + 1;
+		const float3* v0 = &mesh->curve_keys[k0].co;
+		const float3* v1 = &mesh->curve_keys[k1].co;
 
 		float v0p = (*v0)[dim];
 		float v1p = (*v1)[dim];
@@ -318,8 +318,8 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH
 	right_bounds.intersect(ref.bounds());
 
 	/* set references */
-	left = BVHReference(left_bounds, ref.prim_index(), ref.prim_object(), ref.prim_type());
-	right = BVHReference(right_bounds, ref.prim_index(), ref.prim_object(), ref.prim_type());
+	left = BVHReference(left_bounds, ref.prim_index(), ref.prim_object(), ref.prim_segment());
+	right = BVHReference(right_bounds, ref.prim_index(), ref.prim_object(), ref.prim_segment());
 }
 
 CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_bvh.h b/intern/cycles/kernel/kernel_bvh.h
index d32287f91e8..c811d83ad78 100644
--- a/intern/cycles/kernel/kernel_bvh.h
+++ b/intern/cycles/kernel/kernel_bvh.h
@@ -207,22 +207,22 @@ __device_inline void bvh_triangle_intersect(KernelGlobals *kg, Intersection *ise
 
 #ifdef __HAIR__
 __device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect,
-	float3 P, float3 idir, uint visibility, int object, int triAddr)
+	float3 P, float3 idir, uint visibility, int object, int curveAddr, int segment)
 {
 	/* curve Intersection check */
 	
 	int flags = kernel_data.curve_kernel_data.curveflags;
 
-	int prim = kernel_tex_fetch(__prim_index, triAddr);
-	float4 v00 = kernel_tex_fetch(__curve_segments, prim);
+	int prim = kernel_tex_fetch(__prim_index, curveAddr);
+	float4 v00 = kernel_tex_fetch(__curves, prim);
 
-	int v1 = __float_as_int(v00.x);
-	int v2 = __float_as_int(v00.y);
+	int k0 = __float_as_int(v00.x) + segment;
+	int k1 = k0 + 1;
 
-	float4 P1 = kernel_tex_fetch(__curve_keys, v1);
-	float4 P2 = kernel_tex_fetch(__curve_keys, v2);
+	float4 P1 = kernel_tex_fetch(__curve_keys, k0);
+	float4 P2 = kernel_tex_fetch(__curve_keys, k1);
 
-	float l = v00.w;
+	float l = len(P2 - P1); // XXX slower
 	float r1 = P1.w;
 	float r2 = P2.w;
 	float mr = max(r1,r2);
@@ -329,14 +329,15 @@ __device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect,
 					return;
 			}*/
 
-	#ifdef __VISIBILITY_FLAG__
+#ifdef __VISIBILITY_FLAG__
 			/* visibility flag test. we do it here under the assumption
 			 * that most triangles are culled by node flags */
-			if(kernel_tex_fetch(__prim_visibility, triAddr) & visibility)
-	#endif
+			if(kernel_tex_fetch(__prim_visibility, curveAddr) & visibility)
+#endif
 			{
 				/* record intersection */
-				isect->prim = triAddr;
+				isect->prim = curveAddr;
+				isect->segment = segment;
 				isect->object = object;
 				isect->u = z/l;
 				isect->v = td/(4*a*a);
@@ -430,8 +431,9 @@ __device_inline bool bvh_intersect(KernelGlobals *kg, const Ray *ray, const uint
 					while(primAddr < primAddr2) {
 						/* intersect ray against primitive */
 #ifdef __HAIR__
-						if(kernel_tex_fetch(__prim_type, primAddr))
-							bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr);
+						uint segment = kernel_tex_fetch(__prim_segment, primAddr);
+						if(segment != ~0)
+							bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, segment);
 						else
 #endif
 							bvh_triangle_intersect(kg, isect, P, idir, visibility, object, primAddr);
@@ -555,8 +557,9 @@ __device_inline bool bvh_intersect_motion(KernelGlobals *kg, const Ray *ray, con
 					while(primAddr < primAddr2) {
 						/* intersect ray against primitive */
 #ifdef __HAIR__
-						if(kernel_tex_fetch(__prim_type, primAddr))
-							bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr);
+						uint segment = kernel_tex_fetch(__prim_segment, primAddr);
+						if(segment != ~0)
+							bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, segment);
 						else
 #endif
 							bvh_triangle_intersect(kg, isect, P, idir, visibility, object, primAddr);
@@ -720,14 +723,14 @@ __device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, const
 	}
 
 	int prim = kernel_tex_fetch(__prim_index, isect->prim);
-	float4 v00 = kernel_tex_fetch(__curve_segments, prim);
+	float4 v00 = kernel_tex_fetch(__curves, prim);
 
-	int v1 = __float_as_int(v00.x);
-	int v2 = __float_as_int(v00.y);
+	int k0 = __float_as_int(v00.x) + isect->segment;
+	int k1 = k0 + 1;
 
-	float4 P1 = kernel_tex_fetch(__curve_keys, v1);
-	float4 P2 = kernel_tex_fetch(__curve_keys, v2);
-	float l = v00.w;
+	float4 P1 = kernel_tex_fetch(__curve_keys, k0);
+	float4 P2 = kernel_tex_fetch(__curve_keys, k1);
+	float l = len(P2 - P1); // XXX slower
 	float r1 = P1.w;
 	float r2 = P2.w;
 	float3 tg = float4_to_float3(P2 - P1) / l;
diff --git a/intern/cycles/kernel/kernel_curve.h b/intern/cycles/kernel/kernel_curve.h
index fef1a48644d..e065717888c 100644
--- a/intern/cycles/kernel/kernel_curve.h
+++ b/intern/cycles/kernel/kernel_curve.h
@@ -24,19 +24,21 @@ CCL_NAMESPACE_BEGIN
 
 __device float curve_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
 {
-	if(elem == ATTR_ELEMENT_CURVE_SEGMENT) {
+	if(elem == ATTR_ELEMENT_CURVE) {
 #ifdef __RAY_DIFFERENTIALS__
 		if(dx) *dx = 0.0f;
 		if(dy) *dy = 0.0f;
 #endif
 
-		return kernel_tex_fetch(__attributes_float, offset + sd->curve_seg);
+		return kernel_tex_fetch(__attributes_float, offset + sd->prim);
 	}
 	else if(elem == ATTR_ELEMENT_CURVE_KEY) {
-		float4 segment = kernel_tex_fetch(__curve_segments, sd->curve_seg);
+		float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
+		int k0 = __float_as_int(curvedata.x) + sd->segment;
+		int k1 = k0 + 1;
 
-		float f0 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(segment.x));
-		float f1 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(segment.y));
+		float f0 = kernel_tex_fetch(__attributes_float, offset + k0);
+		float f1 = kernel_tex_fetch(__attributes_float, offset + k1);
 
 #ifdef __RAY_DIFFERENTIALS__
 		if(dx) *dx = sd->du.dx*(f1 - f0);
@@ -57,7 +59,7 @@ __device float curve_attribute_float(KernelGlobals *kg, const ShaderData *sd, At
 
 __device float3 curve_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
 {
-	if(elem == ATTR_ELEMENT_CURVE_SEGMENT) {
+	if(elem == ATTR_ELEMENT_CURVE) {
 		/* idea: we can't derive any useful differentials here, but for tiled
 		 * mipmap image caching it would be useful to avoid reading the highest
 		 * detail level always. maybe a derivative based on the hair density
@@ -67,13 +69,15 @@ __device float3 curve_attribute_float3(KernelGlobals *kg, const ShaderData *sd,
 		if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
 #endif
 
-		return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + sd->curve_seg));
+		return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + sd->prim));
 	}
 	else if(elem == ATTR_ELEMENT_CURVE_KEY) {
-		float4 segment = kernel_tex_fetch(__curve_segments, sd->curve_seg);
+		float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
+		int k0 = __float_as_int(curvedata.x) + sd->segment;
+		int k1 = k0 + 1;
 
-		float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(segment.x)));
-		float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(segment.y)));
+		float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + k0));
+		float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + k1));
 
 #ifdef __RAY_DIFFERENTIALS__
 		if(dx) *dx = sd->du.dx*(f1 - f0);
@@ -96,19 +100,16 @@ __device float3 curve_attribute_float3(KernelGlobals *kg, const ShaderData *sd,
 
 __device float curve_thickness(KernelGlobals *kg, ShaderData *sd)
 {
-	int prim = sd->curve_seg;
-	float u = sd->u;
 	float r = 0.0f;
 
-	if(prim != -1) {
-		float4 v00 = kernel_tex_fetch(__curve_segments, prim);
+	if(sd->segment != ~0) {
+		float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
+		int k0 = __float_as_int(curvedata.x) + sd->segment;
+		int k1 = k0 + 1;
 
-		int v1 = __float_as_int(v00.x);
-		int v2 = __float_as_int(v00.y);
-
-		float4 P1 = kernel_tex_fetch(__curve_keys, v1);
-		float4 P2 = kernel_tex_fetch(__curve_keys, v2);
-		r = (P2.w - P1.w) * u + P1.w;
+		float4 P1 = kernel_tex_fetch(__curve_keys, k0);
+		float4 P2 = kernel_tex_fetch(__curve_keys, k1);
+		r = (P2.w - P1.w) * sd->u + P1.w;
 	}
 
 	return r*2.0f;
@@ -118,7 +119,7 @@ __device float3 curve_tangent_normal(KernelGlobals *kg, ShaderData *sd)
 {	
 	float3 tgN = make_float3(0.0f,0.0f,0.0f);
 
-	if(sd->curve_seg != ~0) {
+	if(sd->segment != ~0) {
 		float normalmix = kernel_data.curve_kernel_data.normalmix;
 
 		tgN = -(-sd->I - sd->dPdu * (dot(sd->dPdu,-sd->I) * normalmix / len_squared(sd->dPdu)));
diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h
index adf7e8eca82..d5506ad1dd0 100644
--- a/intern/cycles/kernel/kernel_emission.h
+++ b/intern/cycles/kernel/kernel_emission.h
@@ -157,7 +157,7 @@ __device float3 indirect_emission(KernelGlobals *kg, ShaderData *sd, float t, in
 	float3 L = shader_emissive_eval(kg, sd);
 
 #ifdef __HAIR__
-	if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_SAMPLE_AS_LIGHT) && (sd->curve_seg == ~0)) {
+	if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_SAMPLE_AS_LIGHT) && (sd->segment == ~0)) {
 #else
 	if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_SAMPLE_AS_LIGHT)) {
 #endif
diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h
index 09ee1f68e12..1561ddc9ddd 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -329,18 +329,20 @@ __device float triangle_light_pdf(KernelGlobals *kg,
 #ifdef __HAIR__
 /* Strand Light */
 
-__device void curve_seg_light_sample(KernelGlobals *kg, int prim, int object,
-	float randu, float randv, float time, LightSample *ls)
+__device void curve_segment_light_sample(KernelGlobals *kg, int prim, int object,
+	int segment, float randu, float randv, float time, LightSample *ls)
 {
 	/* this strand code needs completion */
-	float4 v00 = kernel_tex_fetch(__curve_segments, prim);
+	float4 v00 = kernel_tex_fetch(__curves, prim);
+
+	int k0 = __float_as_int(v00.x) + segment;
+	int k1 = k0 + 1;
 
-	int v1 = __float_as_int(v00.x);
-	int v2 = __float_as_int(v00.y);
-	float l = v00.w;
+	float4 P1 = kernel_tex_fetch(__curve_keys, k0);
+	float4 P2 = kernel_tex_fetch(__curve_keys, k1);
+
+	float l = len(P2 - P1); // XXX slower
 
-	float4 P1 = kernel_tex_fetch(__curve_keys, v1);
-	float4 P2 = kernel_tex_fetch(__curve_keys, v2);
 	float r1 = P1.w;
 	float r2 = P2.w;
 	float3 tg = float4_to_float3(P2 - P1) / l;
@@ -419,15 +421,15 @@ __device void light_sample(KernelGlobals *kg, float randt, float randu, float ra
 	float4 l = kernel_tex_fetch(__light_distribution, index);
 	int prim = __float_as_int(l.y);
 #ifdef __HAIR__
-/* currently use l.z to indicate is strand sample which isn't ideal */
-	bool is_curve = __float_as_int(l.z) == 0.0f;
+	int segment = __float_as_int(l.z);
 #endif
 
 	if(prim >= 0) {
 		int object = __float_as_int(l.w);
+
 #ifdef __HAIR__
-		if (is_curve)
-			curve_seg_light_sample(kg, prim, object, randu, randv, time, ls);
+		if (segment != ~0)
+			curve_segment_light_sample(kg, prim, object, segment, randu, randv, time, ls);
 		else
 #endif
 			triangle_light_sample(kg, prim, object, randu, randv, time, ls);
diff --git a/intern/cycles/kernel/kernel_primitive.h b/intern/cycles/kernel/kernel_primitive.h
index 2296017c686..7538b7107d0 100644
--- a/intern/cycles/kernel/kernel_primitive.h
+++ b/intern/cycles/kernel/kernel_primitive.h
@@ -37,7 +37,7 @@ __device_inline int find_attribute(KernelGlobals *kg, ShaderData *sd, uint id, A
 	{
 		/* for SVM, find attribute by unique id */
 		uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
-		attr_offset = (sd->curve_seg == ~0)? attr_offset: attr_offset + ATTR_PRIM_CURVE;
+		attr_offset = (sd->segment == ~0)? attr_offset: attr_offset + ATTR_PRIM_CURVE;
 		uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
 		
 		while(attr_map.x != id) {
@@ -55,7 +55,7 @@ __device_inline int find_attribute(KernelGlobals *kg, ShaderData *sd, uint id, A
 __device float primitive_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
 {
 #ifdef __HAIR__
-	if(sd->curve_seg == ~0)
+	if(sd->segment == ~0)
 #endif
 		return triangle_attribute_float(kg, sd, elem, offset, dx, dy);
 #ifdef __HAIR__
@@ -67,7 +67,7 @@ __device float primitive_attribute_float(KernelGlobals *kg, const ShaderData *sd
 __device float3 primitive_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
 {
 #ifdef __HAIR__
-	if(sd->curve_seg == ~0)
+	if(sd->segment == ~0)
 #endif
 		return triangle_attribute_float3(kg, sd, elem, offset, dx, dy);
 #ifdef __HAIR__
@@ -92,7 +92,7 @@ __device float3 primitive_uv(KernelGlobals *kg, ShaderData *sd)
 __device float3 primitive_tangent(KernelGlobals *kg, ShaderData *sd)
 {
 #ifdef __HAIR__
-	if(sd->curve_seg != ~0)
+	if(sd->segment != ~0)
 		return normalize(sd->dPdu);
 #endif
 
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index 49bbc5a74ab..0a5a2ab54b0 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -69,25 +69,22 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
 #endif
 
 	sd->prim = kernel_tex_fetch(__prim_index, isect->prim);
-#ifdef __HAIR__
-	sd->curve_seg = ~0;
-#endif
 	sd->ray_length = isect->t;
 
 #ifdef __HAIR__
-	if(kernel_tex_fetch(__prim_type, isect->prim)) {
+	if(kernel_tex_fetch(__prim_segment, isect->prim) != ~0) {
 		/* Strand Shader setting*/
-		float4 CurSeg = kernel_tex_fetch(__curve_segments, sd->prim);
-		sd->shader = __float_as_int(CurSeg.z);
+		float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
 
-		sd->curve_seg = sd->prim;
-		sd->prim = isect->prim;
+		sd->shader = __float_as_int(curvedata.z);
+		sd->segment = isect->segment;
 
 		float tcorr = isect->t;
 		if(kernel_data.curve_kernel_data.curveflags & CURVE_KN_POSTINTERSECTCORRECTION) {
 			tcorr = (isect->u < 0)? tcorr + sqrtf(isect->v) : tcorr - sqrtf(isect->v);
 			sd->ray_length = tcorr;
 		}
+
 		sd->P = bvh_curve_refine(kg, sd, isect, ray, tcorr);
 	}
 	else {
@@ -97,6 +94,10 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
 		float3 Ng = make_float3(Ns.x, Ns.y, Ns.z);
 		sd->shader = __float_as_int(Ns.w);
 
+#ifdef __HAIR__
+		sd->segment = ~0;
+#endif
+
 #ifdef __UV__
 		sd->u = isect->u;
 		sd->v = isect->v;
@@ -107,7 +108,6 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
 		sd->Ng = Ng;
 		sd->N = Ng;
 		
-
 		/* smooth normal */
 		if(sd->shader & SHADER_SMOOTH_NORMAL)
 			sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
@@ -162,7 +162,7 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
 
 __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
 	const float3 P, const float3 Ng, const float3 I,
-	int shader, int object, int prim, float u, float v, float t, float time, int curve = ~0)
+	int shader, int object, int prim, float u, float v, float t, float time, int segment = ~0)
 {
 	/* vectors */
 	sd->P = P;
@@ -171,7 +171,7 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
 	sd->I = I;
 	sd->shader = shader;
 #ifdef __HAIR__
-	sd->curve_seg = curve;
+	sd->segment = segment;
 #endif
 
 	/* primitive */
@@ -215,7 +215,7 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
 
 	/* smooth normal */
 #ifdef __HAIR__
-	if(sd->shader & SHADER_SMOOTH_NORMAL && sd->curve_seg == ~0) {
+	if(sd->shader & SHADER_SMOOTH_NORMAL && sd->segment == ~0) {
 		sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
 #else
 	if(sd->shader & SHADER_SMOOTH_NORMAL) {
@@ -231,7 +231,7 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
 #ifdef __DPDU__
 	/* dPdu/dPdv */
 #ifdef __HAIR__
-	if(sd->prim == ~0 || sd->curve_seg != ~0) {
+	if(sd->prim == ~0 || sd->segment != ~0) {
 		sd->dPdu = make_float3(0.0f, 0.0f, 0.0f);
 		sd->dPdv = make_float3(0.0f, 0.0f, 0.0f);
 	}
@@ -323,7 +323,7 @@ __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData
 #endif
 	sd->prim = ~0;
 #ifdef __HAIR__
-	sd->curve_seg = ~0;
+	sd->segment = ~0;
 #endif
 #ifdef __UV__
 	sd->u = 0.0f;
@@ -781,14 +781,14 @@ __device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect)
 	int shader = 0;
 
 #ifdef __HAIR__
-	if(!kernel_tex_fetch(__prim_type, isect->prim)) {
+	if(kernel_tex_fetch(__prim_segment, isect->prim) == ~0) {
 #endif
 		float4 Ns = kernel_tex_fetch(__tri_normal, prim);
 		shader = __float_as_int(Ns.w);
 #ifdef __HAIR__
 	}
 	else {
-		float4 str = kernel_tex_fetch(__curve_segments, prim);
+		float4 str = kernel_tex_fetch(__curves, prim);
 		shader = __float_as_int(str.z);
 	}
 #endif
diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h
index 072df21a188..e27de95e7ab 100644
--- a/intern/cycles/kernel/kernel_textures.h
+++ b/intern/cycles/kernel/kernel_textures.h
@@ -27,7 +27,7 @@
 /* bvh */
 KERNEL_TEX(float4, texture_float4, __bvh_nodes)
 KERNEL_TEX(float4, texture_float4, __tri_woop)
-KERNEL_TEX(uint, texture_uint, __prim_type)
+KERNEL_TEX(uint, texture_uint, __prim_segment)
 KERNEL_TEX(uint, texture_uint, __prim_visibility)
 KERNEL_TEX(uint, texture_uint, __prim_index)
 KERNEL_TEX(uint, texture_uint, __prim_object)
@@ -44,7 +44,7 @@ KERNEL_TEX(float4, texture_float4, __tri_vindex)
 KERNEL_TEX(float4, texture_float4, __tri_verts)
 
 /* curves */
-KERNEL_TEX(float4, texture_float4, __curve_segments)
+KERNEL_TEX(float4, texture_float4, __curves)
 KERNEL_TEX(float4, texture_float4, __curve_keys)
 
 /* attributes */
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index e80772bd4e2..2bd6b5859f3 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -344,6 +344,7 @@ typedef struct Intersection {
 	float t, u, v;
 	int prim;
 	int object;
+	int segment;
 } Intersection;
 
 /* Attributes */
@@ -357,7 +358,7 @@ typedef enum AttributeElement {
 	ATTR_ELEMENT_FACE,
 	ATTR_ELEMENT_VERTEX,
 	ATTR_ELEMENT_CORNER,
-	ATTR_ELEMENT_CURVE_SEGMENT,
+	ATTR_ELEMENT_CURVE,
 	ATTR_ELEMENT_CURVE_KEY
 } AttributeElement;
 
@@ -464,8 +465,8 @@ typedef struct ShaderData {
 	int prim;
 
 #ifdef __HAIR__
-	/* strand id if there is one, -1 otherwise */
-	int curve_seg;
+	/* for curves, segment number in curve, ~0 for triangles */
+	int segment;
 #endif
 	/* parametric coordinates
 	 * - barycentric weights for triangles */
diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp
index afa5211216b..28742d56e3b 100644
--- a/intern/cycles/kernel/osl/osl_services.cpp
+++ b/intern/cycles/kernel/osl/osl_services.cpp
@@ -605,7 +605,7 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD
 		return set_attribute_int(3, type, derivatives, val);
 	}
 	else if ((name == u_geom_trianglevertices || name == u_geom_polyvertices)
-		     && sd->curve_seg == ~0) {
+		     && sd->segment == ~0) {
 		float3 P[3];
 		triangle_vertices(kg, sd->prim, P);
 
@@ -625,7 +625,7 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD
 #ifdef __HAIR__
 	/* Hair Attributes */
 	else if (name == u_is_curve) {
-		float f = !(sd->curve_seg == ~0);
+		float f = (sd->segment != ~0);
 		return set_attribute_float(f, type, derivatives, val);
 	}
 	else if (name == u_curve_thickness) {
@@ -659,7 +659,7 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri
 {
 	KernelGlobals *kg = kernel_globals;
 	ShaderData *sd = (ShaderData *)renderstate;
-	int object, prim, curve_seg;
+	int object, prim, segment;
 
 	/* lookup of attribute on another object */
 	if (object_name != u_empty || sd == NULL) {
@@ -670,19 +670,19 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri
 
 		object = it->second;
 		prim = ~0;
-		curve_seg = ~0;
+		segment = ~0;
 	}
 	else {
 		object = sd->object;
 		prim = sd->prim;
-		curve_seg = sd->curve_seg;
+		segment = sd->segment;
 
 		if (object == ~0)
 			return get_background_attribute(kg, sd, name, type, derivatives, val);
 	}
 
 	/* find attribute on object */
-	object = object*ATTR_PRIM_TYPES + (curve_seg != ~0);
+	object = object*ATTR_PRIM_TYPES + (segment != ~0);
 	OSLGlobals::AttributeMap& attribute_map = kg->osl->attribute_map[object];
 	OSLGlobals::AttributeMap::iterator it = attribute_map.find(name);
 
diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp
index 18486eba114..59e307bb408 100644
--- a/intern/cycles/kernel/osl/osl_shader.cpp
+++ b/intern/cycles/kernel/osl/osl_shader.cpp
@@ -457,7 +457,7 @@ float3 OSLShader::volume_eval_phase(const ShaderClosure *sc, const float3 omega_
 int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeElement *elem)
 {
 	/* for OSL, a hash map is used to lookup the attribute by name. */
-	int object = sd->object*ATTR_PRIM_TYPES + (sd->curve_seg != ~0);
+	int object = sd->object*ATTR_PRIM_TYPES + (sd->segment != ~0);
 	OSLGlobals::AttributeMap &attr_map = kg->osl->attribute_map[object];
 	ustring stdname(std::string("geom:") + std::string(Attribute::standard_name((AttributeStandard)id)));
 	OSLGlobals::AttributeMap::const_iterator it = attr_map.find(stdname);
diff --git a/intern/cycles/kernel/svm/svm_attribute.h b/intern/cycles/kernel/svm/svm_attribute.h
index f11b69138d1..ea0a31610f1 100644
--- a/intern/cycles/kernel/svm/svm_attribute.h
+++ b/intern/cycles/kernel/svm/svm_attribute.h
@@ -28,7 +28,7 @@ __device void svm_node_attr_init(KernelGlobals *kg, ShaderData *sd,
 		/* find attribute by unique id */
 		uint id = node.y;
 		uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
-		attr_offset = (sd->curve_seg == ~0)? attr_offset: attr_offset + ATTR_PRIM_CURVE;
+		attr_offset = (sd->segment == ~0)? attr_offset: attr_offset + ATTR_PRIM_CURVE;
 		uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
 		
 		while(attr_map.x != id) {
diff --git a/intern/cycles/kernel/svm/svm_geometry.h b/intern/cycles/kernel/svm/svm_geometry.h
index db8bbabe0ec..a04f4ea0fa7 100644
--- a/intern/cycles/kernel/svm/svm_geometry.h
+++ b/intern/cycles/kernel/svm/svm_geometry.h
@@ -155,7 +155,7 @@ __device void svm_node_hair_info(KernelGlobals *kg, ShaderData *sd, float *stack
 
 	switch(type) {
 		case NODE_INFO_CURVE_IS_STRAND: {
-			data = !(sd->curve_seg == ~0);
+			data = (sd->segment != ~0);
 			stack_store_float(stack, out_offset, data);
 			break;
 		}
diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp
index 758e4e5e820..b6f6ba47fe8 100644
--- a/intern/cycles/render/attribute.cpp
+++ b/intern/cycles/render/attribute.cpp
@@ -80,7 +80,7 @@ size_t Attribute::element_size(int numverts, int numtris, int numcurves, int num
 		return numtris;
 	else if(element == ATTR_ELEMENT_CORNER)
 		return numtris*3;
-	else if(element == ATTR_ELEMENT_CURVE_SEGMENT)
+	else if(element == ATTR_ELEMENT_CURVE)
 		return numcurves;
 	else if(element == ATTR_ELEMENT_CURVE_KEY)
 		return numkeys;
@@ -176,7 +176,7 @@ Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement eleme
 	if(triangle_mesh)
 		attr->reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), 0, 0);
 	if(curve_mesh)
-		attr->reserve(0, 0, curve_mesh->curve_segments.size(), curve_mesh->curve_keys.size());
+		attr->reserve(0, 0, curve_mesh->curves.size(), curve_mesh->curve_keys.size());
 	
 	return attr;
 }
@@ -239,9 +239,9 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
 	}
 	else if(curve_mesh) {
 		if(std == ATTR_STD_UV)
-			attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_SEGMENT);
+			attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE);
 		else if(std == ATTR_STD_GENERATED)
-			attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_SEGMENT);
+			attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE);
 		else if(std == ATTR_STD_MOTION_PRE)
 			attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_KEY);
 		else if(std == ATTR_STD_MOTION_POST)
@@ -298,7 +298,7 @@ void AttributeSet::reserve()
 		if(triangle_mesh)
 			attr.reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), 0, 0);
 		if(curve_mesh)
-			attr.reserve(0, 0, curve_mesh->curve_segments.size(), curve_mesh->curve_keys.size());
+			attr.reserve(0, 0, curve_mesh->curves.size(), curve_mesh->curve_keys.size());
 	}
 }
 
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index cab6008dd7c..c8e3e94ec98 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -171,13 +171,14 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
 					num_triangles++;
 			}
 
-			/* disabled for strands*/
-			/*for(size_t i = 0; i < mesh->curve_segments.size(); i++) {
-			*	Shader *shader = scene->shaders[mesh->curve_segments[i].shader];
-			*
-			*	if(shader->sample_as_light && shader->has_surface_emission)
-			*		num_curve_segments++;
-			}*/
+			/* disabled for curves */
+#if 0
+			foreach(Mesh::Curve& curve, mesh->curves) {
+				Shader *shader = scene->shaders[curve.shader];
+
+				if(shader->sample_as_light && shader->has_surface_emission)
+					num_curve_segments += curve.num_segments();
+#endif
 		}
 	}
 
@@ -225,7 +226,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
 				if(shader->sample_as_light && shader->has_surface_emission) {
 					distribution[offset].x = totarea;
 					distribution[offset].y = __int_as_float(i + mesh->tri_offset);
-					distribution[offset].z = 1.0f;
+					distribution[offset].z = __int_as_float(~0);
 					distribution[offset].w = __int_as_float(object_id);
 					offset++;
 
@@ -245,30 +246,38 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
 			}
 
 			/*sample as light disabled for strands*/
-			/*for(size_t i = 0; i < mesh->curve_segments.size(); i++) {
-			*	Shader *shader = scene->shaders[mesh->curve_segments[i].shader];
-			*
-			*	if(shader->sample_as_light && shader->has_surface_emission) {
-			*		distribution[offset].x = totarea;
-			*		distribution[offset].y = __int_as_float(i + mesh->curveseg_offset);
-			*		distribution[offset].z = 0.0f;
-			*		distribution[offset].w = __int_as_float(object_id);
-			*		offset++;
-			*
-			*		Mesh::CurveSeg s = mesh->curve_segments[i];
-			*		float3 p1 = mesh->curve_keys[s.v[0]].loc;
-			*		float r1 = mesh->curve_keys[s.v[0]].radius;
-			*		float3 p2 = mesh->curve_keys[s.v[1]].loc;
-			*		float r2 = mesh->curve_keys[s.v[1]].radius;
-			*
-			*		if(!transform_applied) {
-			*			p1 = transform_point(&tfm, p1);
-			*			p2 = transform_point(&tfm, p2);
-			*		}
-			*
-			*		totarea += M_PI_F * (r1 + r2) * len(p1 - p2);
-			*	}
-			}*/
+#if 0
+			size_t i = 0;
+
+			foreach(Mesh::Curve& curve, mesh->curves) {
+				Shader *shader = scene->shaders[curve.shader];
+				int first_key = curve.first_key;
+
+				if(shader->sample_as_light && shader->has_surface_emission) {
+					for(int j = 0; j < curve.num_segments(); j++) {
+						distribution[offset].x = totarea;
+						distribution[offset].y = __int_as_float(i + mesh->curve_offset); // XXX fix kernel code
+						distribution[offset].z = __int_as_float(j);
+						distribution[offset].w = __int_as_float(object_id);
+						offset++;
+				
+						float3 p1 = mesh->curve_keys[first_key + j].loc;
+						float r1 = mesh->curve_keys[first_key + j].radius;
+						float3 p2 = mesh->curve_keys[first_key + j + 1].loc;
+						float r2 = mesh->curve_keys[first_key + j + 1].radius;
+				
+						if(!transform_applied) {
+							p1 = transform_point(&tfm, p1);
+							p2 = transform_point(&tfm, p2);
+						}
+				
+						totarea += M_PI_F * (r1 + r2) * len(p1 - p2);
+					}
+				}
+
+				i++;
+			}
+#endif
 		}
 
 		if(progress.get_cancel()) return;
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index 53cae53ef69..d4619dcff55 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -51,7 +51,7 @@ Mesh::Mesh()
 	tri_offset = 0;
 	vert_offset = 0;
 
-	curveseg_offset = 0;
+	curve_offset = 0;
 	curvekey_offset = 0;
 
 	attributes.triangle_mesh = this;
@@ -71,7 +71,7 @@ void Mesh::reserve(int numverts, int numtris, int numcurves, int numcurvekeys)
 	shader.resize(numtris);
 	smooth.resize(numtris);
 	curve_keys.resize(numcurvekeys);
-	curve_segments.resize(numcurves);
+	curves.resize(numcurves);
 
 	attributes.reserve();
 	curve_attributes.reserve();
@@ -86,7 +86,7 @@ void Mesh::clear()
 	smooth.clear();
 
 	curve_keys.clear();
-	curve_segments.clear();
+	curves.clear();
 
 	attributes.clear();
 	curve_attributes.clear();
@@ -98,34 +98,33 @@ void Mesh::clear()
 
 void Mesh::add_triangle(int v0, int v1, int v2, int shader_, bool smooth_)
 {
-	Triangle t;
-	t.v[0] = v0;
-	t.v[1] = v1;
-	t.v[2] = v2;
+	Triangle tri;
+	tri.v[0] = v0;
+	tri.v[1] = v1;
+	tri.v[2] = v2;
 
-	triangles.push_back(t);
+	triangles.push_back(tri);
 	shader.push_back(shader_);
 	smooth.push_back(smooth_);
 }
 
 void Mesh::add_curve_key(float3 co, float radius)
 {
-	CurveKey ck;
-	ck.co = co;
-	ck.radius = radius;
+	CurveKey key;
+	key.co = co;
+	key.radius = radius;
 
-	curve_keys.push_back(ck);
+	curve_keys.push_back(key);
 }
 
-void Mesh::add_curve_segment(int v0, int v1, int shader, int curveid)
+void Mesh::add_curve(int first_key, int num_keys, int shader)
 {
-	CurveSegment s;
-	s.v[0] = v0;
-	s.v[1] = v1;
-	s.shader = shader;
-	s.curve = curveid;
+	Curve curve;
+	curve.first_key = first_key;
+	curve.num_keys = num_keys;
+	curve.shader = shader;
 
-	curve_segments.push_back(s);
+	curves.push_back(curve);
 }
 
 void Mesh::compute_bounds()
@@ -284,7 +283,7 @@ void Mesh::pack_verts(float4 *tri_verts, float4 *tri_vindex, size_t vert_offset)
 	}
 }
 
-void Mesh::pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_seg_keys, size_t curvekey_offset)
+void Mesh::pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_data, size_t curvekey_offset)
 {
 	size_t curve_keys_size = curve_keys.size();
 	CurveKey *keys_ptr = NULL;
@@ -302,25 +301,21 @@ void Mesh::pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_seg_key
 	}
 
 	/* pack curve segments */
-	size_t curve_seg_num = curve_segments.size();
+	size_t curve_num = curves.size();
 
-	if(curve_seg_num) {
-		CurveSegment *curve_ptr = &curve_segments[0];
+	if(curve_num) {
+		Curve *curve_ptr = &curves[0];
 		int shader_id = 0;
 		
-		for(size_t i = 0; i < curve_seg_num; i++) {
-			CurveSegment s = curve_ptr[i];
-			shader_id = scene->shader_manager->get_shader_id(s.shader, this, false);
+		for(size_t i = 0; i < curve_num; i++) {
+			Curve curve = curve_ptr[i];
+			shader_id = scene->shader_manager->get_shader_id(curve.shader, this, false);
 
-			float3 p1 = keys_ptr[s.v[0]].co;
-			float3 p2 = keys_ptr[s.v[1]].co;
-			float length = len(p2 - p1);
-
-			curve_seg_keys[i] = make_float4(
-				__int_as_float(s.v[0] + curvekey_offset),
-				__int_as_float(s.v[1] + curvekey_offset),
+			curve_data[i] = make_float4(
+				__int_as_float(curve.first_key + curvekey_offset),
+				__int_as_float(curve.num_keys),
 				__int_as_float(shader_id),
-				length);
+				0.0f);
 		}
 	}
 }
@@ -541,7 +536,7 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
 
 			index++;
 
-			if(mesh->curve_segments.size()) {
+			if(mesh->curves.size()) {
 				attr_map[index].x = id;
 				attr_map[index].y = req.curve_element;
 				attr_map[index].z = as_uint(req.curve_offset);
@@ -588,7 +583,7 @@ static void update_attribute_element_offset(Mesh *mesh, vector& attr_floa
 		size_t size = mattr->element_size(
 			mesh->verts.size(),
 			mesh->triangles.size(),
-			mesh->curve_segments.size(),
+			mesh->curves.size(),
 			mesh->curve_keys.size());
 
 		if(mattr->type == TypeDesc::TypeFloat) {
@@ -618,8 +613,8 @@ static void update_attribute_element_offset(Mesh *mesh, vector& attr_floa
 			offset -= mesh->tri_offset;
 		else if(element == ATTR_ELEMENT_CORNER)
 			offset -= 3*mesh->tri_offset;
-		else if(element == ATTR_ELEMENT_CURVE_SEGMENT)
-			offset -= mesh->curveseg_offset;
+		else if(element == ATTR_ELEMENT_CURVE)
+			offset -= mesh->curve_offset;
 		else if(element == ATTR_ELEMENT_CURVE_KEY)
 			offset -= mesh->curvekey_offset;
 	}
@@ -713,20 +708,20 @@ void MeshManager::device_update_mesh(Device *device, DeviceScene *dscene, Scene
 	size_t tri_size = 0;
 
 	size_t curve_key_size = 0;
-	size_t curve_seg_keys = 0;
+	size_t curve_size = 0;
 
 	foreach(Mesh *mesh, scene->meshes) {
 		mesh->vert_offset = vert_size;
 		mesh->tri_offset = tri_size;
 
 		mesh->curvekey_offset = curve_key_size;
-		mesh->curveseg_offset = curve_seg_keys;
+		mesh->curve_offset = curve_size;
 
 		vert_size += mesh->verts.size();
 		tri_size += mesh->triangles.size();
 
 		curve_key_size += mesh->curve_keys.size();
-		curve_seg_keys += mesh->curve_segments.size();
+		curve_size += mesh->curves.size();
 	}
 
 	if(tri_size != 0) {
@@ -754,19 +749,19 @@ void MeshManager::device_update_mesh(Device *device, DeviceScene *dscene, Scene
 		device->tex_alloc("__tri_vindex", dscene->tri_vindex);
 	}
 
-	if(curve_seg_keys != 0) {
+	if(curve_size != 0) {
 		progress.set_status("Updating Mesh", "Copying Strands to device");
 
 		float4 *curve_keys = dscene->curve_keys.resize(curve_key_size);
-		float4 *curve_segments = dscene->curve_segments.resize(curve_seg_keys);
+		float4 *curves = dscene->curves.resize(curve_size);
 
 		foreach(Mesh *mesh, scene->meshes) {
-			mesh->pack_curves(scene, &curve_keys[mesh->curvekey_offset], &curve_segments[mesh->curveseg_offset], mesh->curvekey_offset);
+			mesh->pack_curves(scene, &curve_keys[mesh->curvekey_offset], &curves[mesh->curve_offset], mesh->curvekey_offset);
 			if(progress.get_cancel()) return;
 		}
 
 		device->tex_alloc("__curve_keys", dscene->curve_keys);
-		device->tex_alloc("__curve_segments", dscene->curve_segments);
+		device->tex_alloc("__curves", dscene->curves);
 	}
 }
 
@@ -804,9 +799,9 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *
 		dscene->tri_woop.reference(&pack.tri_woop[0], pack.tri_woop.size());
 		device->tex_alloc("__tri_woop", dscene->tri_woop);
 	}
-	if(pack.prim_type.size()) {
-		dscene->prim_type.reference((uint*)&pack.prim_type[0], pack.prim_type.size());
-		device->tex_alloc("__prim_type", dscene->prim_type);
+	if(pack.prim_segment.size()) {
+		dscene->prim_segment.reference((uint*)&pack.prim_segment[0], pack.prim_segment.size());
+		device->tex_alloc("__prim_segment", dscene->prim_segment);
 	}
 	if(pack.prim_visibility.size()) {
 		dscene->prim_visibility.reference((uint*)&pack.prim_visibility[0], pack.prim_visibility.size());
@@ -917,7 +912,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
 	device->tex_free(dscene->bvh_nodes);
 	device->tex_free(dscene->object_node);
 	device->tex_free(dscene->tri_woop);
-	device->tex_free(dscene->prim_type);
+	device->tex_free(dscene->prim_segment);
 	device->tex_free(dscene->prim_visibility);
 	device->tex_free(dscene->prim_index);
 	device->tex_free(dscene->prim_object);
@@ -925,7 +920,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
 	device->tex_free(dscene->tri_vnormal);
 	device->tex_free(dscene->tri_vindex);
 	device->tex_free(dscene->tri_verts);
-	device->tex_free(dscene->curve_segments);
+	device->tex_free(dscene->curves);
 	device->tex_free(dscene->curve_keys);
 	device->tex_free(dscene->attributes_map);
 	device->tex_free(dscene->attributes_float);
@@ -934,7 +929,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
 	dscene->bvh_nodes.clear();
 	dscene->object_node.clear();
 	dscene->tri_woop.clear();
-	dscene->prim_type.clear();
+	dscene->prim_segment.clear();
 	dscene->prim_visibility.clear();
 	dscene->prim_index.clear();
 	dscene->prim_object.clear();
@@ -942,7 +937,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
 	dscene->tri_vnormal.clear();
 	dscene->tri_vindex.clear();
 	dscene->tri_verts.clear();
-	dscene->curve_segments.clear();
+	dscene->curves.clear();
 	dscene->curve_keys.clear();
 	dscene->attributes_map.clear();
 	dscene->attributes_float.clear();
diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h
index ca8c755671f..b83752ad8df 100644
--- a/intern/cycles/render/mesh.h
+++ b/intern/cycles/render/mesh.h
@@ -51,10 +51,13 @@ public:
 	};
 
 	/* Mesh Curve */
-	struct CurveSegment {
-		int v[2];
+	struct Curve {
+		int first_key;
+		int num_keys;
 		uint shader;
-		int curve;
+		uint pad;
+
+		int num_segments() { return num_keys - 1; }
 	};
 
 	struct CurveKey {
@@ -78,7 +81,7 @@ public:
 	vector smooth;
 
 	vector curve_keys;
-	vector curve_segments;
+	vector curves;
 
 	vector used_shaders;
 	AttributeSet attributes;
@@ -98,7 +101,7 @@ public:
 	size_t tri_offset;
 	size_t vert_offset;
 
-	size_t curveseg_offset;
+	size_t curve_offset;
 	size_t curvekey_offset;
 
 	/* Functions */
@@ -109,7 +112,7 @@ public:
 	void clear();
 	void add_triangle(int v0, int v1, int v2, int shader, bool smooth);
 	void add_curve_key(float3 loc, float radius);
-	void add_curve_segment(int v0, int v1, int shader, int curveid);
+	void add_curve(int first_key, int num_keys, int shader);
 
 	void compute_bounds();
 	void add_face_normals();
@@ -117,7 +120,7 @@ public:
 
 	void pack_normals(Scene *scene, float4 *normal, float4 *vnormal);
 	void pack_verts(float4 *tri_verts, float4 *tri_vindex, size_t vert_offset);
-	void pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_seg_keys, size_t curvekey_offset);
+	void pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_data, size_t curvekey_offset);
 	void compute_bvh(SceneParams *params, Progress *progress, int n, int total);
 
 	bool need_attribute(Scene *scene, AttributeStandard std);
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index 4862b47c342..a89f8afd251 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -203,14 +203,18 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
 					surface_area += triangle_area(p1, p2, p3);
 				}
 
-				foreach(Mesh::CurveSegment& t, mesh->curve_segments) {
-					float3 p1 = mesh->curve_keys[t.v[0]].co;
-					float r1 = mesh->curve_keys[t.v[0]].radius;
-					float3 p2 = mesh->curve_keys[t.v[1]].co;
-					float r2 = mesh->curve_keys[t.v[1]].radius;
-
-					/* currently ignores segment overlaps*/
-					surface_area += M_PI_F *(r1 + r2) * len(p1 - p2);
+				foreach(Mesh::Curve& curve, mesh->curves) {
+					int first_key = curve.first_key;
+
+					for(int i = 0; i < curve.num_segments(); i++) {
+						float3 p1 = mesh->curve_keys[first_key + i].co;
+						float r1 = mesh->curve_keys[first_key + i].radius;
+						float3 p2 = mesh->curve_keys[first_key + i + 1].co;
+						float r2 = mesh->curve_keys[first_key + i + 1].radius;
+
+						/* currently ignores segment overlaps*/
+						surface_area += M_PI_F *(r1 + r2) * len(p1 - p2);
+					}
 				}
 
 				surface_area_map[mesh] = surface_area;
@@ -229,14 +233,21 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
 				surface_area += triangle_area(p1, p2, p3);
 			}
 
-			foreach(Mesh::CurveSegment& t, mesh->curve_segments) {
-				float3 p1 = mesh->curve_keys[t.v[0]].co;
-				float r1 = mesh->curve_keys[t.v[0]].radius;
-				float3 p2 = mesh->curve_keys[t.v[1]].co;
-				float r2 = mesh->curve_keys[t.v[1]].radius;
+			foreach(Mesh::Curve& curve, mesh->curves) {
+				int first_key = curve.first_key;
+
+				for(int i = 0; i < curve.num_segments(); i++) {
+					float3 p1 = mesh->curve_keys[first_key + i].co;
+					float r1 = mesh->curve_keys[first_key + i].radius;
+					float3 p2 = mesh->curve_keys[first_key + i + 1].co;
+					float r2 = mesh->curve_keys[first_key + i + 1].radius;
 
-				/* currently ignores segment overlaps*/
-				surface_area += M_PI_F *(r1 + r2) * len(p1 - p2);
+					p1 = transform_point(&tfm, p1);
+					p2 = transform_point(&tfm, p2);
+
+					/* currently ignores segment overlaps*/
+					surface_area += M_PI_F *(r1 + r2) * len(p1 - p2);
+				}
 			}
 		}
 
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index 9490fd96be0..f6e1daea80d 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -62,7 +62,7 @@ public:
 	device_vector bvh_nodes;
 	device_vector object_node;
 	device_vector tri_woop;
-	device_vector prim_type;
+	device_vector prim_segment;
 	device_vector prim_visibility;
 	device_vector prim_index;
 	device_vector prim_object;
@@ -73,7 +73,7 @@ public:
 	device_vector tri_vindex;
 	device_vector tri_verts;
 
-	device_vector curve_segments;
+	device_vector curves;
 	device_vector curve_keys;
 
 	/* objects */
-- 
cgit v1.2.3


From b3f21a22548db7e8e77001065b9139c44a8e0c62 Mon Sep 17 00:00:00 2001
From: Brecht Van Lommel 
Date: Thu, 3 Jan 2013 12:31:05 +0000
Subject: Cycles Hair: add Generated texture coordinates for curves, so that
 procedural textures now work without having to add a UV map.

Also made UV and intercept attributes only export when needed by the shader.
---
 intern/cycles/blender/blender_curves.cpp | 43 +++++++++++++++++++++-----------
 intern/cycles/blender/blender_mesh.cpp   |  9 ++-----
 intern/cycles/blender/blender_util.h     | 14 +++++++++++
 3 files changed, 45 insertions(+), 21 deletions(-)

diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp
index 2e9a32f15f2..9395fbb3e5d 100644
--- a/intern/cycles/blender/blender_curves.cpp
+++ b/intern/cycles/blender/blender_curves.cpp
@@ -16,6 +16,7 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
+#include "attribute.h"
 #include "mesh.h"
 #include "object.h"
 #include "scene.h"
@@ -24,16 +25,8 @@
 #include "blender_sync.h"
 #include "blender_util.h"
 
-#include "subd_mesh.h"
-#include "subd_patch.h"
-#include "subd_split.h"
-
 #include "util_foreach.h"
 
-#include "DNA_modifier_types.h"
-#include "DNA_particle_types.h"
-#include "DNA_meshdata_types.h"
-
 CCL_NAMESPACE_BEGIN
 
 /* Utilities */
@@ -650,7 +643,7 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int inter
 	/* texture coords still needed */
 }
 
-void ExportCurveSegments(Mesh *mesh, ParticleCurveData *CData, int interpolation, int segments)
+void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData, int interpolation, int segments)
 {
 	int num_keys = 0;
 	int num_curves = 0;
@@ -658,8 +651,12 @@ void ExportCurveSegments(Mesh *mesh, ParticleCurveData *CData, int interpolation
 	if(!(mesh->curves.empty() && mesh->curve_keys.empty()))
 		return;
 
-	Attribute *attr_uv = mesh->curve_attributes.add(ATTR_STD_UV);
-	Attribute *attr_intercept = mesh->curve_attributes.add(ATTR_STD_CURVE_INTERCEPT);
+	Attribute *attr_uv = NULL, *attr_intercept = NULL;
+	
+	if(mesh->need_attribute(scene, ATTR_STD_UV))
+		attr_uv = mesh->curve_attributes.add(ATTR_STD_UV);
+	if(mesh->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT))
+		attr_intercept = mesh->curve_attributes.add(ATTR_STD_CURVE_INTERCEPT);
 
 	for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
 
@@ -695,14 +692,16 @@ void ExportCurveSegments(Mesh *mesh, ParticleCurveData *CData, int interpolation
 						radius =0.0f;
 
 					mesh->add_curve_key(ickey_loc, radius);
-					attr_intercept->add(time);
+					if(attr_intercept)
+						attr_intercept->add(time);
 
 					num_curve_keys++;
 				}
 			}
 
 			mesh->add_curve(num_keys, num_curve_keys, CData->psys_shader[sys]);
-			attr_uv->add(CData->curve_uv[curve]);
+			if(attr_uv)
+				attr_uv->add(CData->curve_uv[curve]);
 
 			num_keys += num_curve_keys;
 			num_curves++;
@@ -871,7 +870,7 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool
 			ExportCurveTriangleGeometry(mesh, &CData, interpolation, use_smooth, resolution, segments);
 	}
 	else {
-		ExportCurveSegments(mesh, &CData, interpolation, segments);
+		ExportCurveSegments(scene, mesh, &CData, interpolation, segments);
 		int ckey_num = mesh->curve_keys.size();
 
 		/*export tangents or curve data? - not functional yet*/
@@ -886,6 +885,22 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool
 				data_tangent[ck] = tg;
 			}
 		}
+
+		/* generated coordinates from first key. we should ideally get this from
+		 * blender to handle deforming objects */
+		if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) {
+			float3 loc, size;
+			mesh_texture_space(b_mesh, loc, size);
+
+			Attribute *attr_generated = mesh->curve_attributes.add(ATTR_STD_GENERATED);
+			float3 *generated = attr_generated->data_float3();
+			size_t i = 0;
+
+			foreach(Mesh::Curve& curve, mesh->curves) {
+				float3 co = mesh->curve_keys[curve.first_key].co;
+				generated[i++] = co*size - loc;
+			}
+		}
 	}
 
 	mesh->compute_bounds();
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index 86f996320cb..1dd7800dfa4 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -328,14 +328,9 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
 	 * is available in the api. */
 	if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) {
 		Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED);
-		float3 loc = get_float3(b_mesh.texspace_location());
-		float3 size = get_float3(b_mesh.texspace_size());
 
-		if(size.x != 0.0f) size.x = 0.5f/size.x;
-		if(size.y != 0.0f) size.y = 0.5f/size.y;
-		if(size.z != 0.0f) size.z = 0.5f/size.z;
-
-		loc = loc*size - make_float3(0.5f, 0.5f, 0.5f);
+		float3 loc, size;
+		mesh_texture_space(b_mesh, loc, size);
 
 		float3 *generated = attr->data_float3();
 		size_t i = 0;
diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index fbcbe15ec5a..88c98860794 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -242,6 +242,20 @@ static inline string blender_absolute_path(BL::BlendData b_data, BL::ID b_id, co
 	return path;
 }
 
+/* Texture Space */
+
+static inline void mesh_texture_space(BL::Mesh b_mesh, float3& loc, float3& size)
+{
+	loc = get_float3(b_mesh.texspace_location());
+	size = get_float3(b_mesh.texspace_size());
+
+	if(size.x != 0.0f) size.x = 0.5f/size.x;
+	if(size.y != 0.0f) size.y = 0.5f/size.y;
+	if(size.z != 0.0f) size.z = 0.5f/size.z;
+
+	loc = loc*size - make_float3(0.5f, 0.5f, 0.5f);
+}
+
 /* ID Map
  *
  * Utility class to keep in sync with blender data.
-- 
cgit v1.2.3


From e1004eb13949f27b98302e7ad71335c8dd22f1a8 Mon Sep 17 00:00:00 2001
From: Brecht Van Lommel 
Date: Thu, 3 Jan 2013 13:18:35 +0000
Subject: Fix CUDA build error after last commit, and remove some comments.

---
 intern/cycles/kernel/kernel_bvh.h        | 4 ++--
 intern/cycles/kernel/kernel_light.h      | 2 +-
 intern/cycles/kernel/kernel_primitive.h  | 2 ++
 intern/cycles/kernel/svm/svm_attribute.h | 2 ++
 4 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/intern/cycles/kernel/kernel_bvh.h b/intern/cycles/kernel/kernel_bvh.h
index c811d83ad78..c73d9328c74 100644
--- a/intern/cycles/kernel/kernel_bvh.h
+++ b/intern/cycles/kernel/kernel_bvh.h
@@ -222,7 +222,7 @@ __device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect,
 	float4 P1 = kernel_tex_fetch(__curve_keys, k0);
 	float4 P2 = kernel_tex_fetch(__curve_keys, k1);
 
-	float l = len(P2 - P1); // XXX slower
+	float l = len(P2 - P1);
 	float r1 = P1.w;
 	float r2 = P2.w;
 	float mr = max(r1,r2);
@@ -730,7 +730,7 @@ __device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, const
 
 	float4 P1 = kernel_tex_fetch(__curve_keys, k0);
 	float4 P2 = kernel_tex_fetch(__curve_keys, k1);
-	float l = len(P2 - P1); // XXX slower
+	float l = len(P2 - P1);
 	float r1 = P1.w;
 	float r2 = P2.w;
 	float3 tg = float4_to_float3(P2 - P1) / l;
diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h
index 1561ddc9ddd..ea0e4d014fe 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -341,7 +341,7 @@ __device void curve_segment_light_sample(KernelGlobals *kg, int prim, int object
 	float4 P1 = kernel_tex_fetch(__curve_keys, k0);
 	float4 P2 = kernel_tex_fetch(__curve_keys, k1);
 
-	float l = len(P2 - P1); // XXX slower
+	float l = len(P2 - P1);
 
 	float r1 = P1.w;
 	float r2 = P2.w;
diff --git a/intern/cycles/kernel/kernel_primitive.h b/intern/cycles/kernel/kernel_primitive.h
index 7538b7107d0..0851af21e87 100644
--- a/intern/cycles/kernel/kernel_primitive.h
+++ b/intern/cycles/kernel/kernel_primitive.h
@@ -37,7 +37,9 @@ __device_inline int find_attribute(KernelGlobals *kg, ShaderData *sd, uint id, A
 	{
 		/* for SVM, find attribute by unique id */
 		uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
+#ifdef __HAIR__
 		attr_offset = (sd->segment == ~0)? attr_offset: attr_offset + ATTR_PRIM_CURVE;
+#endif
 		uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
 		
 		while(attr_map.x != id) {
diff --git a/intern/cycles/kernel/svm/svm_attribute.h b/intern/cycles/kernel/svm/svm_attribute.h
index ea0a31610f1..2beec995151 100644
--- a/intern/cycles/kernel/svm/svm_attribute.h
+++ b/intern/cycles/kernel/svm/svm_attribute.h
@@ -28,7 +28,9 @@ __device void svm_node_attr_init(KernelGlobals *kg, ShaderData *sd,
 		/* find attribute by unique id */
 		uint id = node.y;
 		uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
+#ifdef __HAIR__
 		attr_offset = (sd->segment == ~0)? attr_offset: attr_offset + ATTR_PRIM_CURVE;
+#endif
 		uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
 		
 		while(attr_map.x != id) {
-- 
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(-)

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(+)

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(-)

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 e0869db01f21447fc6573dd88357da454b9d8a78 Mon Sep 17 00:00:00 2001
From: Bastien Montagne 
Date: Thu, 3 Jan 2013 15:35:46 +0000
Subject: Patch from Ejner Fergo: enhancements to install_deps.sh. Mostly, it:
 * Adds numpy and opencollada * Merges both Suse and Fedora/Redhat into a
 single func (not sure this is a good idea, but would have been to painful to
 undo this).
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Notes:
* I changed a bit how numpy is handled, so that the script does not try to build it when py3.3 was installed from package!
* Bumped oiio 'magic number', as now trying to use libtiff5 means we have to rebuild everything using tiff!
* Only made a quick test on my own system, but Ejner made quite some extensive ones, so it should be safe.
* I’m not sure keeping on extending that horrible bash thing is a good idea. Shell scripts are nice for small, limited stuff, but I personnaly find that one (over 53ko!) unreadable and a pita to maintain. Further more, doing the same for windows would mean to rewrite everything in another language... I have started work to port this as a py3 script, so that we have a nice structure (classes...) easy to extend/tweak/implement in various OSs/etc.!
---
 build_files/build_environment/install_deps.sh   | 791 +++++++++++++++---------
 build_files/cmake/Modules/FindOpenCOLLADA.cmake |   1 +
 2 files changed, 498 insertions(+), 294 deletions(-)

diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh
index 5e33bd050ed..97bd94f55b2 100755
--- a/build_files/build_environment/install_deps.sh
+++ b/build_files/build_environment/install_deps.sh
@@ -1,16 +1,37 @@
-#!/bin/bash
+#!/usr/bin/env bash
+# ##### 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 #####
+
+# A shell script installing/building all needed dependencies to build Blender, for some Linux distributions.
 
 # Parse command line!
 ARGS=$( \
 getopt \
 -o s:i:t:h \
---long source:,install:,threads:,help,with-all,with-osl,all-static,force-all,force-python,\
-force-boost,force-ocio,force-oiio,force-llvm,force-osl,force-ffmpeg,\
-skip-python,skip-boost,skip-ocio,skip-oiio,skip-llvm,skip-osl,skip-ffmpeg \
+--long source:,install:,threads:,help,with-all,with-osl,with-opencollada,all-static,force-all,\
+force-python,force-numpy,force-boost,force-ocio,force-oiio,force-llvm,force-osl,force-opencollada,\
+force-ffmpeg,skip-python,skip-numpy,skip-boost,skip-ocio,skip-oiio,skip-llvm,skip-osl,skip-ffmpeg,\
+skip-opencollada \
 -- "$@" \
 )
 
 DISTRO=""
+RPM=""
 SRC="$HOME/src/blender-deps"
 INST="/opt/lib"
 CWD=$PWD
@@ -21,6 +42,9 @@ WITH_ALL=false
 # Do not yet enable osl, use --with-osl (or --with-all) option to try it.
 WITH_OSL=false
 
+# Do not yet enable opencollada, use --with-opencollada (or --with-all) option to try it.
+WITH_OPENCOLLADA=false
+
 # Try to link everything statically. Use this to produce portable versions of blender.
 ALL_STATIC=false
 
@@ -37,8 +61,12 @@ or use --source/--install options, if you want to use other paths!
 Number of threads for building: \$THREADS (automatically detected, use --threads= to override it).
 Full install: \$WITH_ALL (use --with-all option to enable it).
 Building OSL: \$WITH_OSL (use --with-osl option to enable it).
+Building OpenCOLLADA: \$WITH_OPENCOLLADA (use --with-opencollada option to enable it).
 All static linking: \$ALL_STATIC (use --all-static option to enable it).
 
+Example:
+Full install without OpenCOLLADA: --with-all --skip-opencollada
+
 Use --help to show all available options!\""
 
 ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
@@ -64,6 +92,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
         Try to install or build the OpenShadingLanguage libraries (and their dependencies).
         Still experimental!
 
+    --with-opencollada
+        Build and install the OpenCOLLADA libraries.
+
     --all-static
         Build libraries as statically as possible, to create static builds of Blender.
 
@@ -73,6 +104,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
     --force-python
         Force the rebuild of Python.
 
+    --force-numpy
+        Force the rebuild of NumPy.
+
     --force-boost
         Force the rebuild of Boost.
 
@@ -88,6 +122,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
     --force-osl
         Force the rebuild of OpenShadingLanguage.
 
+    --force-opencollada
+        Force the rebuild of OpenCOLLADA.
+
     --force-ffmpeg
         Force the rebuild of FFMpeg.
 
@@ -101,6 +138,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
     --skip-python
         Unconditionally skip Python installation/building.
 
+    --skip-numpy
+        Unconditionally skip NumPy installation/building.
+
     --skip-boost
         Unconditionally skip Boost installation/building.
 
@@ -116,6 +156,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
     --skip-osl
         Unconditionally skip OpenShadingLanguage installation/building.
 
+    --skip-opencollada
+        Unconditionally skip OpenCOLLADA installation/building.
+
     --skip-ffmpeg
         Unconditionally skip FFMpeg installation/building.\""
 
@@ -125,6 +168,13 @@ PYTHON_SOURCE="http://python.org/ftp/python/$PYTHON_VERSION/Python-$PYTHON_VERSI
 PYTHON_FORCE_REBUILD=false
 PYTHON_SKIP=false
 
+#Could not get numpy-1.6.2 to compile with python-3.3
+NUMPY_VERSION="1.7.0rc1"
+NUMPY_VERSION_MIN="1.7"
+NUMPY_SOURCE="http://sourceforge.net/projects/numpy/files/NumPy/$NUMPY_VERSION/numpy-$NUMPY_VERSION.tar.gz"
+NUMPY_FORCE_REBUILD=false
+NUMPY_SKIP=false
+
 BOOST_VERSION="1.51.0"
 _boost_version_nodots=`echo "$BOOST_VERSION" | sed -r 's/\./_/g'`
 BOOST_SOURCE="http://sourceforge.net/projects/boost/files/boost/$BOOST_VERSION/boost_$_boost_version_nodots.tar.bz2/download"
@@ -158,6 +208,12 @@ OSL_SOURCE="https://github.com/mont29/OpenShadingLanguage/archive/blender-fixes.
 OSL_FORCE_REBUILD=false
 OSL_SKIP=false
 
+# Version??
+OPENCOLLADA_VERSION="1.3"
+OPENCOLLADA_SOURCE="https://github.com/KhronosGroup/OpenCOLLADA.git"
+OPENCOLLADA_FORCE_REBUILD=false
+OPENCOLLADA_SKIP=false
+
 FFMPEG_VERSION="1.0"
 FFMPEG_SOURCE="http://ffmpeg.org/releases/ffmpeg-$FFMPEG_VERSION.tar.bz2"
 FFMPEG_VERSION_MIN="0.7.6"
@@ -236,22 +292,30 @@ while true; do
     --with-osl)
       WITH_OSL=true; shift; continue
     ;;
+    --with-opencollada)
+      WITH_OPENCOLLADA=true; shift; continue
+    ;;
     --all-static)
       ALL_STATIC=true; shift; continue
     ;;
     --force-all)
       PYTHON_FORCE_REBUILD=true
+      NUMPY_FORCE_REBUILD=true
       BOOST_FORCE_REBUILD=true
       OCIO_FORCE_REBUILD=true
       OIIO_FORCE_REBUILD=true
       LLVM_FORCE_REBUILD=true
       OSL_FORCE_REBUILD=true
+      OPENCOLLADA_FORCE_REBUILD=true
       FFMPEG_FORCE_REBUILD=true
       shift; continue
     ;;
     --force-python)
       PYTHON_FORCE_REBUILD=true; shift; continue
     ;;
+    --force-numpy)
+      NUMPY_FORCE_REBUILD=true; shift; continue
+    ;;
     --force-boost)
       BOOST_FORCE_REBUILD=true; shift; continue
     ;;
@@ -267,12 +331,18 @@ while true; do
     --force-osl)
       OSL_FORCE_REBUILD=true; shift; continue
     ;;
+    --force-opencollada)
+      OPENCOLLADA_FORCE_REBUILD=true; shift; continue
+    ;;
     --force-ffmpeg)
       FFMPEG_FORCE_REBUILD=true; shift; continue
     ;;
     --skip-python)
       PYTHON_SKIP=true; shift; continue
     ;;
+    --skip-numpy)
+      NUMPY_SKIP=true; shift; continue
+    ;;
     --skip-boost)
       BOOST_SKIP=true; shift; continue
     ;;
@@ -288,6 +358,9 @@ while true; do
     --skip-osl)
       OSL_SKIP=true; shift; continue
     ;;
+    --skip-opencollada)
+      OPENCOLLADA_SKIP=true; shift; continue
+    ;;
     --skip-ffmpeg)
       FFMPEG_SKIP=true; shift; continue
     ;;
@@ -308,6 +381,7 @@ done
 
 if $WITH_ALL; then
   WITH_OSL=true
+  WITH_OPENCOLLADA=true
 fi
 
 # Return 0 if $1 = $2 (i.e. 1.01.0 = 1.1, but 1.1.1 != 1.1), else 1.
@@ -397,10 +471,22 @@ version_match() {
 detect_distro() {
   if [ -f /etc/debian_version ]; then
     DISTRO="DEB"
-  elif [ -f /etc/redhat-release ]; then
+  elif [ -f /etc/redhat-release -o /etc/SuSE-release ]; then
     DISTRO="RPM"
+  elif [ -f /etc/arch-release ]; then
+    DISTRO="ARCH"
+  fi
+}
+
+rpm_flavour() {
+  if [ -f /etc/redhat-release ]; then
+    if [ "`grep '6\.' /etc/redhat-release`" ]; then
+      RPM="RHEL"
+    else
+      RPM="FEDORA"
+    fi
   elif [ -f /etc/SuSE-release ]; then
-    DISTRO="SUSE"
+    RPM="SUSE"
   fi
 }
 
@@ -483,6 +569,56 @@ compile_Python() {
   fi
 }
 
+compile_Numpy() {
+  # To be changed each time we make edits that would modify the compiled result!
+  py_magic=0
+
+  _src=$SRC/numpy-$NUMPY_VERSION
+  _inst=$INST/numpy-$NUMPY_VERSION
+  _python=$INST/python-$PYTHON_VERSION
+  _site=lib/python3.3/site-packages
+
+  # Clean install if needed!
+  magic_compile_check numpy-$NUMPY_VERSION $py_magic
+  if [ $? -eq 1 -o $NUMPY_FORCE_REBUILD == true ]; then
+    rm -rf $_inst
+  fi
+
+  if [ ! -d $_inst ]; then
+    INFO "Building Numpy-$NUMPY_VERSION"
+
+    prepare_opt
+
+    if [ ! -d $_src ]; then
+      mkdir -p $SRC
+      wget -c $NUMPY_SOURCE -O $_src.tar.gz
+
+      INFO "Unpacking Numpy-$NUMPY_VERSION"
+      tar -C $SRC -xf $_src.tar.gz
+    fi
+
+    cd $_src
+
+    $_python/bin/python3 setup.py install --prefix=$_inst
+
+    if [ -d $_inst ]; then
+      rm -f $_python/$_site/numpy
+      ln -s $_inst/$_site/numpy $_python/$_site/numpy
+    else
+      ERROR "Numpy-$NUMPY_VERSION failed to compile, exiting"
+      exit 1
+    fi
+
+    magic_compile_set numpy-$NUMPY_VERSION $py_magic
+
+    cd $CWD
+    INFO "Done compiling Numpy-$NUMPY_VERSION!"
+  else
+    INFO "Own Numpy-$NUMPY_VERSION is up to date, nothing to do!"
+    INFO "If you want to force rebuild of this lib, use the --force-numpy option."
+  fi
+}
+
 compile_Boost() {
   # To be changed each time we make edits that would modify the compiled result!
   boost_magic=7
@@ -620,7 +756,7 @@ compile_OCIO() {
 
 compile_OIIO() {
   # To be changed each time we make edits that would modify the compiled result!
-  oiio_magic=6
+  oiio_magic=7
 
   _src=$SRC/OpenImageIO-$OIIO_VERSION
   _inst=$INST/oiio-$OIIO_VERSION
@@ -797,6 +933,7 @@ EOF
     cmake_d="-D CMAKE_BUILD_TYPE=Release"
     cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst"
     cmake_d="$cmake_d -D LLVM_ENABLE_FFI=ON"
+    cmake_d="$cmake_d -D LLVM_TARGETS_TO_BUILD=X86"
 
     if [ -d $_FFI_INCLUDE_DIR ]; then
       cmake_d="$cmake_d -D FFI_INCLUDE_DIR=$_FFI_INCLUDE_DIR"
@@ -920,6 +1057,70 @@ compile_OSL() {
   fi
 }
 
+compile_OpenCOLLADA() {
+  # To be changed each time we make edits that would modify the compiled results!
+  opencollada_magic=5
+
+  _src=$SRC/OpenCOLLADA-$OPENCOLLADA_VERSION
+  _inst=$INST/opencollada-$OPENCOLLADA_VERSION
+
+  # Clean install if needed!
+  magic_compile_check opencollada-$OPENCOLLADA_VERSION $opencollada_magic
+  if [ $? -eq 1 -o $OPENCOLLADA_FORCE_REBUILD == true ]; then
+    rm -rf $_inst
+  fi
+
+  if [ ! -d $_inst ]; then
+    INFO "Building OpenCOLLADA-$OPENCOLLADA_VERSION"
+
+    prepare_opt
+
+    if [ ! -d $_src ]; then
+      mkdir -p $SRC
+      git clone $OPENCOLLADA_SOURCE $_src
+    fi
+
+    cd $_src
+
+    # XXX For now, always update from latest repo...
+    git pull origin
+
+    # Always refresh the whole build!
+    if [ -d build ]; then
+      rm -rf build
+    fi
+    mkdir build
+    cd build
+
+    cmake_d="-D CMAKE_BUILD_TYPE=Release"
+    cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst"
+    cmake_d="$cmake_d -D USE_EXPAT=OFF"
+    cmake_d="$cmake_d -D USE_LIBXML=ON"
+    cmake_d="$cmake_d -D USE_STATIC=ON"
+
+    cmake $cmake_d ../
+
+    make -j$THREADS && make install
+    make clean
+
+    if [ -d $_inst ]; then
+      rm -f $INST/opencollada
+      ln -s opencollada-$OPENCOLLADA_VERSION $INST/opencollada
+    else
+      ERROR "OpenCOLLADA-$OPENCOLLADA_VERSION failed to compile, exiting"
+      exit 1
+    fi
+
+    magic_compile_set opencollada-$OPENCOLLADA_VERSION $opencollada_magic
+
+    cd $CWD
+    INFO "Done compiling OpenCOLLADA-$OPENCOLLADA_VERSION!"
+  else
+    INFO "Own OpenCOLLADA-$OPENCOLLADA_VERSION is up to date, nothing to do!"
+    INFO "If you want to force rebuild of this lib, use the --force-opencollada option."
+  fi
+}
+
 compile_FFmpeg() {
   # To be changed each time we make edits that would modify the compiled result!
   ffmpeg_magic=3
@@ -992,9 +1193,9 @@ compile_FFmpeg() {
         --enable-avfilter --disable-vdpau \
         --disable-bzlib --disable-libgsm --disable-libspeex \
         --enable-pthreads --enable-zlib --enable-stripping --enable-runtime-cpudetect \
-        --disable-vaapi  --disable-libfaac --disable-nonfree --enable-gpl \
-        --disable-postproc --disable-x11grab  --disable-librtmp  --disable-libopencore-amrnb \
-        --disable-libopencore-amrwb --disable-libdc1394 --disable-version3  --disable-outdev=sdl \
+        --disable-vaapi --disable-libfaac --disable-nonfree --enable-gpl \
+        --disable-postproc --disable-x11grab --disable-librtmp --disable-libopencore-amrnb \
+        --disable-libopencore-amrwb --disable-libdc1394 --disable-version3 --disable-outdev=sdl \
         --disable-outdev=alsa --disable-indev=sdl --disable-indev=alsa --disable-indev=jack \
         --disable-indev=lavfi $extra
 
@@ -1019,6 +1220,8 @@ compile_FFmpeg() {
   fi
 }
 
+
+
 get_package_version_DEB() {
     dpkg-query -W -f '${Version}' $1 | sed -r 's/.*:\s*([0-9]+:)(([0-9]+\.?)+).*/\2/'
 }
@@ -1056,7 +1259,7 @@ check_package_version_ge_DEB() {
 }
 
 install_packages_DEB() {
-  sudo apt-get install -y $@
+  sudo apt-get install -y --force-yes $@
   if [ $? -ge 1 ]; then
     ERROR "apt-get failed to install requested packages, exiting."
     exit 1
@@ -1070,6 +1273,9 @@ install_DEB() {
   INFO "`eval _echo "$COMMON_INFO"`"
   INFO ""
 
+  read -p "Do you want to continue (Y/n)?"
+  [ "$(echo ${REPLY:=Y} | tr [:upper:] [:lower:])" != "y" ] && exit
+
   if [ ! -z "`cat /etc/debian_version | grep ^6`"  ]; then
     if [ -z "`cat /etc/apt/sources.list | grep backports.debian.org`"  ]; then
       INFO "Looks like you're using Debian Squeeze which does have broken CMake"
@@ -1095,27 +1301,37 @@ install_DEB() {
   fi
 
   sudo apt-get update
-# XXX Why in hell? Let's let this stuff to the user's responsability!!!
-#  sudo apt-get -y upgrade
 
   # These libs should always be available in debian/ubuntu official repository...
   OPENJPEG_DEV="libopenjpeg-dev"
-  SCHRO_DEV="libschroedinger-dev"
   VORBIS_DEV="libvorbis-dev"
   THEORA_DEV="libtheora-dev"
 
-  _packages="gawk cmake scons build-essential libjpeg-dev libpng-dev libtiff-dev \
+  _packages="gawk cmake cmake-curses-gui scons build-essential libjpeg-dev libpng-dev \
              libfreetype6-dev libx11-dev libxi-dev wget libsqlite3-dev libbz2-dev \
              libncurses5-dev libssl-dev liblzma-dev libreadline-dev $OPENJPEG_DEV \
-             libopenexr-dev libopenal-dev libglew-dev yasm $THEORA_DEV \
-             $VORBIS_DEV libsdl1.2-dev libfftw3-dev python-dev patch bzip2"
+             libopenexr-dev libopenal-dev libglew-dev yasm $THEORA_DEV $VORBIS_DEV \
+             libsdl1.2-dev libfftw3-dev patch bzip2"
+
   OPENJPEG_USE=true
   VORBIS_USE=true
   THEORA_USE=true
 
+  # Install newest libtiff-dev in debian/ubuntu.
+  TIFF="libtiff5"
+  check_package_DEB $TIFF
+  if [ $? -eq 0 ]; then
+    _packages="$_packages $TIFF-dev"
+  else
+    TIFF="libtiff"
+    check_package_DEB $TIFF
+    if [ $? -eq 0 ]; then
+      _packages="$_packages $TIFF-dev"
+    fi
+  fi
+
   if $WITH_ALL; then
-    _packages="$_packages $SCHRO_DEV libjack0 libjack-dev"
-    SCHRO_USE=true
+    _packages="$_packages libspnav-dev libjack-dev"
   fi
 
   INFO ""
@@ -1132,6 +1348,7 @@ install_DEB() {
   if $WITH_ALL; then
     INFO ""
     # Grmpf, debian is libxvidcore-dev and ubuntu libxvidcore4-dev!
+    # Note: not since ubuntu 10.04
     XVID_DEV="libxvidcore-dev"
     check_package_DEB $XVID_DEV
     if [ $? -eq 0 ]; then
@@ -1163,9 +1380,11 @@ install_DEB() {
     fi
 
     INFO ""
-    check_package_DEB libspnav-dev
+    SCHRO_DEV="libschroedinger-dev"
+    check_package_DEB $SCHRO_DEV
     if [ $? -eq 0 ]; then
-      install_packages_DEB libspnav-dev
+      install_packages_DEB $SCHRO_DEV
+      SCHRO_USE=true
     fi
   fi
 
@@ -1173,11 +1392,28 @@ install_DEB() {
   if $PYTHON_SKIP; then
     INFO "WARNING! Skipping Python installation, as requested..."
   else
-    check_package_DEB python3.3-dev
+    check_package_DEB python$PYTHON_VERSION_MIN-dev
     if [ $? -eq 0 ]; then
-      install_packages_DEB python3.3-dev
+      install_packages_DEB python$PYTHON_VERSION_MIN-dev
+      INFO ""
+      if $NUMPY_SKIP; then
+        INFO "WARNING! Skipping NumPy installation, as requested..."
+      else
+        check_package_DEB python$PYTHON_VERSION_MIN-numpy
+        if [ $? -eq 0 ]; then
+          install_packages_DEB python$PYTHON_VERSION_MIN-numpy
+        else
+          INFO "WARNING! Sorry, using python package but no numpy package available!"
+        fi
+      fi
     else
       compile_Python
+      INFO ""
+      if $NUMPY_SKIP; then
+        INFO "WARNING! Skipping NumPy installation, as requested..."
+      else
+        compile_Numpy
+      fi
     fi
   fi
 
@@ -1237,17 +1473,19 @@ install_DEB() {
       INFO ""
       check_package_DEB llvm-$LLVM_VERSION-dev
       if [ $? -eq 0 ]; then
-        install_packages_DEB llvm-$LLVM_VERSION-dev
+        install_packages_DEB llvm-$LLVM_VERSION-dev clang
         have_llvm=true
         LLVM_VERSION_FOUND=$LLVM_VERSION
       else
         check_package_DEB llvm-$LLVM_VERSION_MIN-dev
         if [ $? -eq 0 ]; then
-          install_packages_DEB llvm-$LLVM_VERSION_MIN-dev
+          install_packages_DEB llvm-$LLVM_VERSION_MIN-dev clang
           have_llvm=true
           LLVM_VERSION_FOUND=$LLVM_VERSION_MIN
         else
           install_packages_DEB libffi-dev
+          # LLVM can't find the debian ffi header dir
+          _FFI_INCLUDE_DIR=`dpkg -L libffi-dev | grep -e ".*/ffi.h" | sed -r 's/(.*)\/ffi.h/\1/'`
           INFO ""
           compile_LLVM
           have_llvm=true
@@ -1257,12 +1495,11 @@ install_DEB() {
     fi
 
     if $OSL_SKIP; then
-      INFO ""
       INFO "WARNING! Skipping OpenShadingLanguage installation, as requested..."
     else
       if $have_llvm; then
         INFO ""
-        install_packages_DEB clang flex bison libtbb-dev git
+        install_packages_DEB flex bison libtbb-dev git
         # No package currently!
         INFO ""
         compile_OSL
@@ -1270,6 +1507,19 @@ install_DEB() {
     fi
   fi
 
+  if $WITH_OPENCOLLADA; then
+    if $OPENCOLLADA_SKIP; then
+      INFO "WARNING! Skipping OpenCOLLADA installation, as requested..."
+    else
+      INFO ""
+      install_packages_DEB git libpcre3-dev libxml2-dev
+      # Find path to libxml shared lib...
+      _XML2_LIB=`dpkg -L libxml2-dev | grep -e ".*/libxml2.so"`
+      # No package
+      INFO ""
+      compile_OpenCOLLADA
+    fi
+  fi
 
   INFO ""
   if $FFMPEG_SKIP; then
@@ -1294,12 +1544,24 @@ install_DEB() {
   fi
 }
 
+
+
 get_package_version_RPM() {
-  yum info $1 | grep Version | tail -n 1 | sed -r 's/.*:\s+(([0-9]+\.?)+).*/\1/'
+  rpm_flavour
+  if [ $RPM = "FEDORA" -o $RPM = "RHEL" ]; then
+    yum info $1 | grep Version | tail -n 1 | sed -r 's/.*:\s+(([0-9]+\.?)+).*/\1/'
+  elif [ $RPM = "SUSE" ]; then
+    zypper info $1 | grep Version | tail -n 1 | sed -r 's/.*:\s+(([0-9]+\.?)+).*/\1/'
+  fi  
 }
 
 check_package_RPM() {
-  r=`yum info $1 | grep -c 'Summary'`
+  rpm_flavour
+  if [ $RPM = "FEDORA" -o $RPM = "RHEL" ]; then
+    r=`yum info $1 | grep -c 'Summary'`
+  elif [ $RPM = "SUSE" ]; then
+    r=`zypper info $1 | grep -c 'Summary'`
+  fi
 
   if [ $r -ge 1 ]; then
     return 0
@@ -1331,10 +1593,20 @@ check_package_version_ge_RPM() {
 }
 
 install_packages_RPM() {
-  sudo yum install -y $@
-  if [ $? -ge 1 ]; then
-    ERROR "yum failed to install requested packages, exiting."
-    exit 1
+  rpm_flavour
+  if [ $RPM = "FEDORA" -o $RPM = "RHEL" ]; then
+    sudo yum install -y $@
+    if [ $? -ge 1 ]; then
+      ERROR "yum failed to install requested packages, exiting."
+      exit 1
+    fi
+
+  elif [ $RPM = "SUSE" ]; then
+    sudo zypper --non-interactive install --auto-agree-with-licenses $@
+    if [ $? -ge 1 ]; then
+      ERROR "zypper failed to install requested packages, exiting."
+      exit 1
+    fi
   fi
 }
 
@@ -1345,48 +1617,138 @@ install_RPM() {
   INFO "`eval _echo "$COMMON_INFO"`"
   INFO ""
 
-  sudo yum -y update
+  read -p "Do you want to continue (Y/n)?"
+  [ "$(echo ${REPLY:=Y} | tr [:upper:] [:lower:])" != "y" ] && exit
 
-  # These libs should always be available in debian/ubuntu official repository...
+  # Enable non-free repositories for all flavours
+  rpm_flavour
+  if [ $RPM = "FEDORA" ]; then
+    sudo yum -y localinstall --nogpgcheck \
+    http://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-stable.noarch.rpm \
+    http://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-stable.noarch.rpm
+
+    sudo yum -y update
+
+    # Install cmake now because of difference with RHEL
+    sudo yum -y install cmake
+
+  elif [ $RPM = "RHEL" ]; then
+    sudo yum -y localinstall --nogpgcheck \
+    http://download.fedoraproject.org/pub/epel/6/$(uname -i)/epel-release-6-8.noarch.rpm \
+    http://download1.rpmfusion.org/free/el/updates/6/$(uname -i)/rpmfusion-free-release-6-1.noarch.rpm \
+    http://download1.rpmfusion.org/nonfree/el/updates/6/$(uname -i)/rpmfusion-nonfree-release-6-1.noarch.rpm
+
+    sudo yum -y update
+
+    # Install cmake 2.8 from other repo
+    mkdir -p $SRC
+    if [ -f $SRC/cmake-2.8.8-4.el6.$(uname -m).rpm ]; then
+      INFO ""
+      INFO "Special cmake already installed"
+    else
+      curl -O ftp://ftp.pbone.net/mirror/atrpms.net/el6-$(uname -i)/atrpms/testing/cmake-2.8.8-4.el6.$(uname -m).rpm
+      mv cmake-2.8.8-4.el6.$(uname -m).rpm $SRC/
+      sudo rpm -ihv $SRC/cmake-2.8.8-4.el6.$(uname -m).rpm
+    fi
+
+  elif [ $RPM = "SUSE" ]; then
+    _suse_rel="`grep VERSION /etc/SuSE-release | gawk '{print $3}'`"
+    sudo zypper ar -f http://packman.inode.at/suse/openSUSE_$_suse_rel/ packman
+
+    sudo zypper --non-interactive --gpg-auto-import-keys update --auto-agree-with-licenses
+  fi
+
+  # These libs should always be available in fedora/suse official repository...
   OPENJPEG_DEV="openjpeg-devel"
-  SCHRO_DEV="schroedinger-devel"
   VORBIS_DEV="libvorbis-devel"
   THEORA_DEV="libtheora-devel"
 
-  _packages="gawk gcc gcc-c++ cmake scons libpng-devel libtiff-devel freetype-devel \
-             libX11-devel libXi-devel wget libsqlite3x-devel ncurses-devel \
-             readline-devel $OPENJPEG_DEV openexr-devel openal-soft-devel \
+  _packages="gcc gcc-c++ make scons libpng-devel libtiff-devel \
+             freetype-devel libX11-devel libXi-devel wget ncurses-devel \
+             readline-devel $OPENJPEG_DEV openal-soft-devel \
              glew-devel yasm $THEORA_DEV $VORBIS_DEV SDL-devel fftw-devel \
-             lame-libs libjpeg-devel patch python-devel"
+             libjpeg-devel patch"
+
   OPENJPEG_USE=true
   VORBIS_USE=true
   THEORA_USE=true
 
-  if $WITH_ALL; then
-    _packages="$_packages $SCHRO_DEV jack-audio-connection-kit-devel libspnav-devel"
-    SCHRO_USE=true
-  fi
+  if [ $RPM = "FEDORA" -o $RPM = "RHEL" ]; then
 
-  INFO ""
-  install_packages_RPM $_packages
+    _packages="$_packages libsqlite3-devel openexr-devel"
 
-  INFO ""
-  X264_DEV="x264-devel"
-  check_package_version_ge_RPM $X264_DEV $X264_VERSION_MIN
-  if [ $? -eq 0 ]; then
-    install_packages_RPM $X264_DEV
-    X264_USE=true
-  fi
+    if $WITH_ALL; then
+      _packages="$_packages jack-audio-connection-kit-devel libspnav-devel"
+    fi
 
-  if $WITH_ALL; then
     INFO ""
-    XVID_DEV="xvidcore-devel"
-    check_package_RPM $XVID_DEV
+    install_packages_RPM $_packages
+
+    INFO ""
+    X264_DEV="x264-devel"
+    check_package_version_ge_RPM $X264_DEV $X264_VERSION_MIN
     if [ $? -eq 0 ]; then
-      install_packages_RPM $XVID_DEV
-      XVID_USE=true
+      install_packages_RPM $X264_DEV
+      X264_USE=true
+    fi
+
+    if $WITH_ALL; then
+      INFO ""
+      XVID_DEV="xvidcore-devel"
+      check_package_RPM $XVID_DEV
+      if [ $? -eq 0 ]; then
+        install_packages_RPM $XVID_DEV
+        XVID_USE=true
+      fi
+
+      INFO ""
+      MP3LAME_DEV="lame-devel"
+      check_package_RPM $MP3LAME_DEV
+      if [ $? -eq 0 ]; then
+        install_packages_RPM $MP3LAME_DEV
+        MP3LAME_USE=true
+      fi
+    fi
+
+  elif [ $RPM = "SUSE" ]; then
+
+    _packages="$_packages cmake sqlite3-devel libopenexr-devel"
+
+    if $WITH_ALL; then
+      _packages="$_packages libjack-devel libspnav-devel"
     fi
 
+    INFO ""
+    install_packages_RPM $_packages
+
+    INFO ""
+    X264_DEV="libx264-devel"
+    check_package_version_ge_RPM $X264_DEV $X264_VERSION_MIN
+    if [ $? -eq 0 ]; then
+      install_packages_RPM $X264_DEV
+      X264_USE=true
+    fi
+
+    if $WITH_ALL; then
+      INFO ""
+      XVID_DEV="libxvidcore-devel"
+      check_package_RPM $XVID_DEV
+      if [ $? -eq 0 ]; then
+        install_packages_RPM $XVID_DEV
+        XVID_USE=true
+      fi
+
+      INFO ""
+      MP3LAME_DEV="libmp3lame-devel"
+      check_package_RPM $MP3LAME_DEV
+      if [ $? -eq 0 ]; then
+        install_packages_RPM $MP3LAME_DEV
+        MP3LAME_USE=true
+      fi
+    fi
+  fi
+
+  if $WITH_ALL; then
     INFO ""
     VPX_DEV="libvpx-devel"
     check_package_version_ge_RPM $VPX_DEV $VPX_VERSION_MIN
@@ -1396,14 +1758,14 @@ install_RPM() {
     fi
 
     INFO ""
-    MP3LAME_DEV="lame-devel"
-    check_package_RPM $MP3LAME_DEV
+    SCHRO_DEV="schroedinger-devel"
+    check_package_RPM $SCHRO_DEV
     if [ $? -eq 0 ]; then
-      install_packages_RPM $MP3LAME_DEV
-      MP3LAME_USE=true
+      install_packages_RPM $SCHRO_DEV
+      SCHRO_USE=true
     fi
   fi
-
+ 
   INFO ""
   if $PYTHON_SKIP; then
     INFO "WARNING! Skipping Python installation, as requested..."
@@ -1411,8 +1773,25 @@ install_RPM() {
     check_package_version_match_RPM python3-devel $PYTHON_VERSION_MIN
     if [ $? -eq 0 ]; then
       install_packages_RPM python3-devel
+      INFO ""
+      if $NUMPY_SKIP; then
+        INFO "WARNING! Skipping NumPy installation, as requested..."
+      else
+        check_package_version_match_RPM python3-numpy $NUMPY_VERSION_MIN
+        if [ $? -eq 0 ]; then
+          install_packages_RPM python3-numpy
+        else
+          INFO "WARNING! Sorry, using python package but no numpy package available!"
+        fi
+      fi
     else
       compile_Python
+      INFO ""
+      if $NUMPY_SKIP; then
+        INFO "WARNING! Skipping NumPy installation, as requested..."
+      else
+        compile_Numpy
+      fi
     fi
   fi
 
@@ -1420,7 +1799,7 @@ install_RPM() {
   if $BOOST_SKIP; then
     INFO "WARNING! Skipping Boost installation, as requested..."
   else
-    check_package_version_ge_RPM boost-devel $BOOST_VERSION_MIN
+    check_package_version_ge_RPM boost-devel $BOOST_VERSION
     if [ $? -eq 0 ]; then
       install_packages_RPM boost-devel
     else
@@ -1461,25 +1840,15 @@ install_RPM() {
     else
       check_package_RPM llvm-$LLVM_VERSION-devel
       if [ $? -eq 0 ]; then
-        install_packages_RPM llvm-$LLVM_VERSION-devel
+        install_packages_RPM llvm-$LLVM_VERSION-devel clang
         have_llvm=true
         LLVM_VERSION_FOUND=$LLVM_VERSION
       else
-#        check_package_RPM llvm-$LLVM_VERSION_MIN-devel
-#        if [ $? -eq 0 ]; then
-#          install_packages_RPM llvm-$LLVM_VERSION_MIN-devel
-#          have_llvm=true
-#          LLVM_VERSION_FOUND=$LLVM_VERSION_MIN
-#        else
-#          check_package_version_ge_RPM llvm-devel $LLVM_VERSION_MIN
-#          if [ $? -eq 0 ]; then
-#            install_packages_RPM llvm-devel
-#            have_llvm=true
-#            LLVM_VERSION_FOUND=`get_package_version_RPM llvm-devel`
-#          fi
-#        fi
+        #
+        # Better to compile it than use minimum version from repo...
+        #
       install_packages_RPM libffi-devel
-      # XXX Stupid fedora puts ffi header into a darn stupid dir!
+      # LLVM can't find the fedora ffi header dir...
       _FFI_INCLUDE_DIR=`rpm -ql libffi-devel | grep -e ".*/ffi.h" | sed -r 's/(.*)\/ffi.h/\1/'`
       INFO ""
       compile_LLVM
@@ -1493,206 +1862,29 @@ install_RPM() {
       INFO "WARNING! Skipping OpenShadingLanguage installation, as requested..."
     else
       if $have_llvm; then
-        INFO ""
-        install_packages_RPM flex bison clang tbb-devel git
         # No package currently!
         INFO ""
+        install_packages_RPM flex bison git
+        if [ $RPM = "FEDORA" -o $RPM = "RHEL" ]; then
+          install_packages_RPM tbb-devel
+        fi
+        INFO ""
         compile_OSL
       fi
     fi
   fi
 
-  INFO ""
-  if $FFMPEG_SKIP; then
-    INFO "WARNING! Skipping FFMpeg installation, as requested..."
-  else
-    # Always for now, not sure which packages should be installed
-    compile_FFmpeg
-  fi
-}
-
-get_package_version_SUSE() {
-  zypper info $1 | grep Version | tail -n 1 | sed -r 's/.*:\s+(([0-9]+\.?)+).*/\1/'
-}
-
-check_package_SUSE() {
-  r=`zypper info $1 | grep -c 'Summary'`
-
-  if [ $r -ge 1 ]; then
-    return 0
-  else
-    return 1
-  fi
-}
-
-check_package_version_match_SUSE() {
-  v=`get_package_version_SUSE $1`
-
-  if [ -z "$v" ]; then
-    return 1
-  fi
-
-  version_match $v $2
-  return $?
-}
-
-check_package_version_ge_SUSE() {
-  v=`get_package_version_SUSE $1`
-
-  if [ -z "$v" ]; then
-    return 1
-  fi
-
-  version_ge $v $2
-  return $?
-}
-
-install_packages_SUSE() {
-  sudo zypper --non-interactive install --auto-agree-with-licenses $@
-  if [ $? -ge 1 ]; then
-    ERROR "zypper failed to install requested packages, exiting."
-    exit 1
-  fi
-}
-
-
-install_SUSE() {
-  INFO ""
-  INFO "Installing dependencies for SuSE-based distribution"
-  INFO ""
-  INFO "`eval _echo "$COMMON_INFO"`"
-  INFO ""
-
-  sudo zypper --non-interactive update --auto-agree-with-licenses
-
-  # These libs should always be available in debian/ubuntu official repository...
-  OPENJPEG_DEV="openjpeg-devel"
-  SCHRO_DEV="schroedinger-devel"
-  VORBIS_DEV="libvorbis-devel"
-  THEORA_DEV="libtheora-devel"
-
-  _packages="gawk gcc gcc-c++ cmake scons libpng12-devel libtiff-devel freetype-devel \
-             libX11-devel libXi-devel wget sqlite3-devel ncurses-devel \
-             readline-devel $OPENJPEG_DEV libopenexr-devel openal-soft-devel \
-             glew-devel yasm $THEORA_DEV $VORBIS_DEV libSDL-devel fftw3-devel \
-             libjpeg62-devel patch python-devel"
-  OPENJPEG_USE=true
-  VORBIS_USE=true
-  THEORA_USE=true
-
-  if $WITH_ALL; then
-    _packages="$_packages $SCHRO_DEV libjack-devel libspnav-devel"
-    SCHRO_USE=true
-  fi
-
-  INFO ""
-  install_packages_SUSE $_packages
-
-  INFO ""
-  X264_DEV="x264-devel"
-  check_package_version_ge_SUSE $X264_DEV $X264_VERSION_MIN
-  if [ $? -eq 0 ]; then
-    install_packages_SUSE $X264_DEV
-    X264_USE=true
-  fi
-
-  if $WITH_ALL; then
-    INFO ""
-    XVID_DEV="xvidcore-devel"
-    check_package_SUSE $XVID_DEV
-    if [ $? -eq 0 ]; then
-      install_packages_SUSE $XVID_DEV
-      XVID_USE=true
-    fi
-
-    INFO ""
-    VPX_DEV="libvpx-devel"
-    check_package_version_ge_SUSE $VPX_DEV $VPX_VERSION_MIN
-    if [ $? -eq 0 ]; then
-      install_packages_SUSE $VPX_DEV
-      VPX_USE=true
-    fi
-
-    INFO ""
-    # No mp3 in suse, it seems.
-    MP3LAME_DEV="lame-devel"
-    check_package_SUSE $MP3LAME_DEV
-    if [ $? -eq 0 ]; then
-      install_packages_SUSE $MP3LAME_DEV
-      MP3LAME_USE=true
-    fi
-  fi
-
-  INFO ""
-  if $PYTHON_SKIP; then
-    INFO "WARNING! Skipping Python installation, as requested..."
-  else
-    check_package_version_match_SUSE python3-devel 3.3.
-    if [ $? -eq 0 ]; then
-      install_packages_SUSE python3-devel
+  if $WITH_OPENCOLLADA; then
+    if $OPENCOLLADA_SKIP; then
+      INFO "WARNING! Skipping OpenCOLLADA installation, as requested..."
     else
-      compile_Python
-    fi
-  fi
-
-  INFO ""
-  if $BOOST_SKIP; then
-    INFO "WARNING! Skipping Boost installation, as requested..."
-  else
-    # No boost_locale currently available, so let's build own boost.
-    compile_Boost
-  fi
-
-  INFO ""
-  if $OCIO_SKIP; then
-    INFO "WARNING! Skipping OpenColorIO installation, as requested..."
-  else
-    # No ocio currently available, so let's build own boost.
-    compile_OCIO
-  fi
-
-  INFO ""
-  if $OIIO_SKIP; then
-    INFO "WARNING! Skipping OpenImageIO installation, as requested..."
-  else
-    # No oiio currently available, so let's build own boost.
-    compile_OIIO
-  fi
-
-  if $WITH_OSL; then
-    have_llvm=false
-
-    INFO ""
-    if $LLVM_SKIP; then
-      INFO "WARNING! Skipping LLVM installation, as requested (this also implies skipping OSL!)..."
-    else
-      # Suse llvm package *_$SUCKS$_* (tm) !!!
-#      check_package_version_ge_SUSE llvm-devel $LLVM_VERSION_MIN
-#      if [ $? -eq 0 ]; then
-#        install_packages_SUSE llvm-devel
-#        have_llvm=true
-#        LLVM_VERSION_FOUND=`get_package_version_SUSE llvm-devel`
-#      fi
-
-      install_packages_SUSE libffi47-devel
       INFO ""
-      compile_LLVM
-      have_llvm=true
-      LLVM_VERSION_FOUND=$LLVM_VERSION
-    fi
-
-    if $OSL_SKIP; then
+      install_packages_RPM pcre-devel libxml2-devel git
+      # Find path to libxml shared lib...
+      _XML2_LIB=`rpm -ql libxml2-devel | grep -e ".*/libxml2.so"`
+      # No package...
       INFO ""
-      INFO "WARNING! Skipping OpenShaderLanguage installation, as requested..."
-    else
-      if $have_llvm; then
-        INFO ""
-        # XXX No tbb lib!
-        install_packages_SUSE flex bison git
-        # No package currently!
-        INFO ""
-        compile_OSL
-      fi
+      compile_OpenCOLLADA
     fi
   fi
 
@@ -1700,11 +1892,13 @@ install_SUSE() {
   if $FFMPEG_SKIP; then
     INFO "WARNING! Skipping FFMpeg installation, as requested..."
   else
-    # No ffmpeg currently available, so let's build own boost.
+    # Always for now, not sure which packages should be installed
     compile_FFmpeg
   fi
 }
 
+
+
 print_info_ffmpeglink_DEB() {
   if $ALL_STATIC; then
     dpkg -L $_packages | grep -e ".*\/lib[^\/]\+\.a" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", $0); nlines++ }'
@@ -1714,19 +1908,12 @@ print_info_ffmpeglink_DEB() {
 }
 
 print_info_ffmpeglink_RPM() {
-  if $ALL_STATIC; then
-    rpm -ql $_packages | grep -e ".*\/lib[^\/]\+\.a" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", $0); nlines++ }'
-  else
-    rpm -ql $_packages | grep -e ".*\/lib[^\/]\+\.so" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", gensub(/.*lib([^\/]+)\.so/, "\\1", "g", $0)); nlines++ }'
-  fi
-}
-
-print_info_ffmpeglink_SUSE() {
-  if $ALL_STATIC; then
-    rpm -ql $_packages | grep -e ".*\/lib[^\/]\+\.a" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", $0); nlines++ }'
-  else
-    rpm -ql $_packages | grep -e ".*\/lib[^\/]\+\.so" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", gensub(/.*lib([^\/]+)\.so/, "\\1", "g", $0)); nlines++ }'
-  fi
+#  # XXX No static libs...
+#  if $ALL_STATIC; then
+#    rpm -ql $_packages | grep -e ".*\/lib[^\/]\+\.a" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", $0); nlines++ }'
+#  else
+  rpm -ql $_packages | grep -e ".*\/lib[^\/]\+\.so" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", gensub(/.*lib([^\/]+)\.so/, "\\1", "g", $0)); nlines++ }'
+#  fi
 }
 
 print_info_ffmpeglink() {
@@ -1767,8 +1954,7 @@ print_info_ffmpeglink() {
     _packages="$_packages $OPENJPEG_DEV"
   fi
 
-  # XXX At least under Debian, static schro gives problem at blender linking time... :/
-  if $SCHRO_USE && ! $ALL_STATIC; then
+  if $SCHRO_USE; then
     _packages="$_packages $SCHRO_DEV"
   fi
 
@@ -1776,8 +1962,8 @@ print_info_ffmpeglink() {
     print_info_ffmpeglink_DEB
   elif [ "$DISTRO" = "RPM" ]; then
     print_info_ffmpeglink_RPM
-  elif [ "$DISTRO" = "SUSE" ]; then
-    print_info_ffmpeglink_SUSE
+#  elif [ "$DISTRO" = "ARCH" ]; then
+#    print_info_ffmpeglink_ARCH
   # XXX TODO!
   else INFO ""
   fi
@@ -1791,8 +1977,11 @@ print_info() {
 
   if $ALL_STATIC; then
     _1="-D WITH_STATIC_LIBS=ON"
+    # XXX Force linking with shared SDL lib!
+    _2="-D SDL_LIBRARY='libSDL.so;-lpthread'"
     INFO "  $_1"
-    _buildargs="$_buildargs $_1"
+    INFO "  $_2"
+    _buildargs="$_buildargs $_1 $_2"
   fi
 
   if [ -d $INST/boost ]; then
@@ -1824,6 +2013,17 @@ print_info() {
     fi
   fi
 
+  if [ -d $INST/opencollada -a $WITH_OPENCOLLADA == true ]; then
+    _1="-D WITH_OPENCOLLADA=ON"
+    INFO "  $_1"
+    _buildargs="$_buildargs $_1"
+    if $ALL_STATIC; then
+      _1="-D XML2_LIBRARY=$_XML2_LIB"
+      INFO "  $_1"
+      _buildargs="$_buildargs $_1"
+    fi
+  fi
+
   if [ -d $INST/ffmpeg ]; then
     _1="-D WITH_CODEC_FFMPEG=ON"
     _2="-D FFMPEG=$INST/ffmpeg"
@@ -1835,14 +2035,14 @@ print_info() {
   fi
 
   INFO ""
-  INFO "Or even simpler, just run (in your build dir):"
+  INFO "Or even simpler, just run (in your blender-source dir):"
   INFO "  make -j$THREADS BUILD_CMAKE_ARGS=\"$_buildargs\""
 
   INFO ""
   INFO "If you're using SCons add this to your user-config:"
 
-  if [ -d $INST/python-3.3 ]; then
-    INFO "BF_PYTHON = '$INST/python-3.3'"
+  if [ -d $INST/python-$PYTHON_VERSION_MIN ]; then
+    INFO "BF_PYTHON = '$INST/python-$PYTHON_VERSION_MIN'"
     INFO "BF_PYTHON_ABI_FLAGS = 'm'"
   fi
 
@@ -1885,11 +2085,14 @@ elif [ "$DISTRO" = "DEB" ]; then
   install_DEB
 elif [ "$DISTRO" = "RPM" ]; then
   install_RPM
-elif [ "$DISTRO" = "SUSE" ]; then
-  install_SUSE
+#elif [ "$DISTRO" = "ARCH" ]; then
+#  install_ARCH
 fi
 
-print_info
+print_info | tee BUILD_NOTES.txt
+INFO ""
+INFO "This information has been written to BUILD_NOTES.txt"
+INFO ""
 
 # Switch back to user language.
 LANG=LANG_BACK
diff --git a/build_files/cmake/Modules/FindOpenCOLLADA.cmake b/build_files/cmake/Modules/FindOpenCOLLADA.cmake
index 169d3a82fc7..84aead58b60 100644
--- a/build_files/cmake/Modules/FindOpenCOLLADA.cmake
+++ b/build_files/cmake/Modules/FindOpenCOLLADA.cmake
@@ -66,6 +66,7 @@ SET(_opencollada_SEARCH_DIRS
   /sw # Fink
   /opt/local # DarwinPorts
   /opt/csw # Blastwave
+  /opt/lib/opencollada
 )
 
 SET(_opencollada_INCLUDES)
-- 
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(-)

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(-)

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(-)

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(-)

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(-)

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(-)

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 ...
---
 release/scripts/modules/bpy/path.py           |  7 +++++++
 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 ++
 5 files changed, 29 insertions(+)

diff --git a/release/scripts/modules/bpy/path.py b/release/scripts/modules/bpy/path.py
index d32b69b501c..69ed4314f6f 100644
--- a/release/scripts/modules/bpy/path.py
+++ b/release/scripts/modules/bpy/path.py
@@ -30,6 +30,9 @@ __all__ = (
     "display_name",
     "display_name_from_filepath",
     "ensure_ext",
+    "extensions_image",
+    "extensions_movie",
+    "extensions_audio",
     "is_subdir",
     "module_names",
     "relpath",
@@ -39,6 +42,10 @@ __all__ = (
 import bpy as _bpy
 import os as _os
 
+from _bpy_path import (extensions_audio,
+                       extensions_movie,
+                       extensions_image,
+                       )
 
 def abspath(path, start=None, library=None):
     """
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).

---
 release/scripts/startup/bl_ui/space_userpref.py    |   2 +-
 source/blender/python/SConscript                   |  12 +-
 source/blender/python/intern/CMakeLists.txt        |  20 +-
 .../blender/python/intern/bpy_app_build_options.c  | 221 ++++++++++++++++-----
 4 files changed, 196 insertions(+), 59 deletions(-)

diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 4b5e2839cf1..58c433d3772 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -513,7 +513,7 @@ class USERPREF_PT_system(Panel):
         sub.active = system.use_weight_color_range
         sub.template_color_ramp(system, "weight_color_range", expand=True)
 
-        if 'INTERNATIONAL' in bpy.app.build_options:
+        if bpy.app.build_options.international:
             column.separator()
             column.prop(system, "use_international_fonts")
             if system.use_international_fonts:
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(-)

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.

---
 .../startup/bl_operators/uvcalc_follow_active.py   | 79 +++++++++++++++++++---
 source/blender/editors/mesh/mesh_navmesh.c         |  2 +-
 2 files changed, 72 insertions(+), 9 deletions(-)

diff --git a/release/scripts/startup/bl_operators/uvcalc_follow_active.py b/release/scripts/startup/bl_operators/uvcalc_follow_active.py
index 727c4ad739f..d870ef963ea 100644
--- a/release/scripts/startup/bl_operators/uvcalc_follow_active.py
+++ b/release/scripts/startup/bl_operators/uvcalc_follow_active.py
@@ -26,6 +26,7 @@ from bpy.types import Operator
 
 
 def extend(obj, operator, EXTEND_MODE):
+    
     import bmesh
     me = obj.data
     # script will fail without UVs
@@ -46,12 +47,12 @@ def extend(obj, operator, EXTEND_MODE):
 
     faces = [f for f in bm.faces if f.select and len(f.verts) == 4]
 
-    for f in faces:
-        f.tag = False
-    f_act.tag = True
-
-
     # our own local walker
+    def walk_face_init(faces, f_act):
+        for f in faces:
+            f.tag = False
+        f_act.tag = True
+    
     def walk_face(f):
         # all faces in this list must be tagged
         f.tag = True
@@ -73,6 +74,30 @@ def extend(obj, operator, EXTEND_MODE):
             faces_a, faces_b = faces_b, faces_a
             faces_b.clear()
 
+    def walk_edgeloop(l):
+        """
+        Could make this a generic function
+        """
+        e_first = l.edge
+        e = None
+        while True:
+            e = l.edge
+            yield e
+
+            # don't step past non-manifold edges
+            if e.is_manifold:
+                # welk around the quad and then onto the next face
+                l = l.link_loop_radial_next
+                if len(l.face.verts) == 4:
+                    l = l.link_loop_next.link_loop_next
+                    if l.edge is e_first:
+                        break
+                else:
+                    break
+            else:
+                break
+
+
     def extrapolate_uv(fac,
                        l_a_outer, l_a_inner,
                        l_b_outer, l_b_inner):
@@ -119,7 +144,9 @@ def extend(obj, operator, EXTEND_MODE):
         l_a_uv = [l[uv_act].uv for l in l_a]
         l_b_uv = [l[uv_act].uv for l in l_b]
 
-        if EXTEND_MODE == 'LENGTH':
+        if EXTEND_MODE == 'LENGTH_AVERAGE':
+            fac = edge_lengths[l_b[2].edge.index][0] / edge_lengths[l_a[1].edge.index][0]
+        elif EXTEND_MODE == 'LENGTH':
             a0, b0, c0 = l_a[3].vert.co, l_a[0].vert.co, l_b[3].vert.co
             a1, b1, c1 = l_a[2].vert.co, l_a[1].vert.co, l_b[2].vert.co
 
@@ -140,6 +167,40 @@ def extend(obj, operator, EXTEND_MODE):
                        l_a_uv[2], l_a_uv[1],
                        l_b_uv[2], l_b_uv[1])
 
+    # -------------------------------------------
+    # Calculate average length per loop if needed
+
+    if EXTEND_MODE == 'LENGTH_AVERAGE':
+        bm.edges.index_update()
+        edge_lengths = [None] * len(bm.edges)
+
+        for f in faces:
+            # we know its a quad
+            l_quad = f.loops[:]
+            l_pair_a = (l_quad[0], l_quad[2])
+            l_pair_b = (l_quad[1], l_quad[3])
+
+            for l_pair in (l_pair_a, l_pair_b):
+                if edge_lengths[l_pair[0].edge.index] is None:
+
+                    edge_length_store = [-1.0]
+                    edge_length_accum = 0.0
+                    edge_length_total = 0
+
+                    for l in l_pair:
+                        if edge_lengths[l.edge.index] is None:
+                            for e in walk_edgeloop(l):
+                                if edge_lengths[e.index] is None:
+                                    edge_lengths[e.index] = edge_length_store
+                                    edge_length_accum += e.calc_length()
+                                    edge_length_total += 1
+
+                    edge_length_store[0] = edge_length_accum / edge_length_total
+
+    # done with average length
+    # ------------------------
+
+    walk_face_init(faces, f_act)
     for f_triple in walk_face(f_act):
         apply_uv(*f_triple)
 
@@ -162,8 +223,10 @@ class FollowActiveQuads(Operator):
             name="Edge Length Mode",
             description="Method to space UV edge loops",
             items=(('EVEN', "Even", "Space all UVs evenly"),
-                   ('LENGTH', "Length", "Average space UVs edge length of each loop")),
-            default='LENGTH',
+                   ('LENGTH', "Length", "Average space UVs edge length of each loop"),
+                   ('LENGTH_AVERAGE', "Length Average", "Average space UVs edge length of each loop"),
+                   ),
+            default='LENGTH_AVERAGE',
             )
 
     @classmethod
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

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 25d9fa95f9ed9f6e680e46948ab7a1e7c392f417 Mon Sep 17 00:00:00 2001
From: Sergey Sharybin 
Date: Fri, 4 Jan 2013 08:01:35 +0000
Subject: Silent "no previous prototype" warning, which was treating as error
 here

---
 intern/cycles/blender/blender_curves.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp
index 9395fbb3e5d..c38d0fe76dc 100644
--- a/intern/cycles/blender/blender_curves.cpp
+++ b/intern/cycles/blender/blender_curves.cpp
@@ -643,7 +643,7 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int inter
 	/* texture coords still needed */
 }
 
-void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData, int interpolation, int segments)
+static void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData, int interpolation, int segments)
 {
 	int num_keys = 0;
 	int num_curves = 0;
-- 
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(+)

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(-)

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(-)

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.
---
 intern/cycles/blender/addon/ui.py             |   2 +-
 intern/cycles/blender/blender_curves.cpp      | 277 +++++++++++++++++++++++---
 intern/cycles/kernel/kernel_bvh.h             |  25 +--
 intern/cycles/render/curves.h                 |   1 +
 source/blender/makesrna/intern/rna_particle.c | 121 +++++++++++
 5 files changed, 380 insertions(+), 46 deletions(-)

diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 2d059b365a1..81ee34b6b5e 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -975,7 +975,7 @@ class CyclesRender_PT_CurveRendering(CyclesButtonsPanel, Panel):
         
             if cscene.primitive == 'TRIANGLES':
                 layout.prop(cscene, "triangle_method", text="Method")
-                if cscene.triangle_method == 'TESSELATED':
+                if cscene.triangle_method == 'TESSELLATED':
                     layout.prop(cscene, "resolution", text="Resolution")
                 layout.prop(cscene, "use_smooth", text="Smooth")
             elif cscene.primitive == 'LINE_SEGMENTS':
diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp
index c38d0fe76dc..4fad7d45162 100644
--- a/intern/cycles/blender/blender_curves.cpp
+++ b/intern/cycles/blender/blender_curves.cpp
@@ -38,11 +38,14 @@ void interp_weights(float t, float data[4], int type);
 float shaperadius(float shape, float root, float tip, float time);
 void InterpolateKeySegments(int seg, int segno, int key, int curve, float3 *keyloc, float *time, ParticleCurveData *CData, int interpolation);
 bool ObtainParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData);
+bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents);
+bool ObtainCacheParticleVcol(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents, int vcol_num);
 bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents);
 void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int segments, float3 RotCam);
 void ExportCurveTriangleRibbons(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int segments);
 void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int resolution, int segments);
 void ExportCurveSegments(Mesh *mesh, ParticleCurveData *CData, int interpolation, int segments);
+void ExportCurveTriangleUVs(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int segments, int vert_offset, int resol);
 
 ParticleCurveData::ParticleCurveData()
 {
@@ -61,6 +64,7 @@ ParticleCurveData::~ParticleCurveData()
 	curve_keynum.clear();
 	curve_length.clear();
 	curve_uv.clear();
+	curve_vcol.clear();
 
 	curvekey_co.clear();
 	curvekey_time.clear();
@@ -291,8 +295,6 @@ bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par
 				if(!use_parents && !(b_psys.settings().child_type() == 0))
 					pa_no = totparts;
 
-				BL::ParticleSystem::particles_iterator b_pa;
-				b_psys.particles.begin(b_pa);
 				for(; pa_no < totparts+totchild; pa_no++) {
 
 					CData->curve_firstkey.push_back(keyno);
@@ -314,6 +316,63 @@ bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par
 					}
 					CData->curve_length.push_back(curve_length);
 
+					curvenum++;
+
+				}
+			}
+
+		}
+	}
+
+	return true;
+
+}
+
+bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents)
+{
+	int keyno = 0;
+
+	if(!(mesh && b_mesh && b_ob && CData))
+		return false;
+
+	Transform tfm = get_transform(b_ob->matrix_world());
+	Transform itfm = transform_quick_inverse(tfm);
+
+	BL::Object::modifiers_iterator b_mod;
+	for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
+		if ((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (b_mod->show_viewport()) && (b_mod->show_render())) {
+			BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
+
+			BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
+
+			BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
+
+			if((b_psys.settings().render_type()==BL::ParticleSettings::render_type_PATH)&&(b_psys.settings().type()==BL::ParticleSettings::type_HAIR)) {
+
+				int mi = clamp(b_psys.settings().material()-1, 0, mesh->used_shaders.size()-1);
+				int shader = mesh->used_shaders[mi];
+				int draw_step = b_psys.settings().draw_step();
+				int ren_step = (int)pow((float)2.0f,(float)draw_step);
+				/*b_psys.settings().render_step(draw_step);*/
+
+				int totparts = b_psys.particles.length();
+				int totchild = b_psys.child_particles.length() * b_psys.settings().draw_percentage() / 100;
+				int totcurves = totchild;
+				
+				if (use_parents || b_psys.settings().child_type() == 0)
+					totcurves += totparts;
+
+				if (totcurves == 0)
+					continue;
+
+				int pa_no = 0;
+				if(!use_parents && !(b_psys.settings().child_type() == 0))
+					pa_no = totparts;
+
+				BL::ParticleSystem::particles_iterator b_pa;
+				b_psys.particles.begin(b_pa);
+				for(; pa_no < totparts+totchild; pa_no++) {
+
 					/*add uvs*/
 					BL::Mesh::tessface_uv_textures_iterator l;
 					b_mesh->tessface_uv_textures.begin(l);
@@ -326,7 +385,72 @@ bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par
 					if(pa_no < totparts && b_pa != b_psys.particles.end())
 						++b_pa;
 
-					curvenum++;
+				}
+			}
+
+		}
+	}
+
+	return true;
+
+}
+
+bool ObtainCacheParticleVcol(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents, int vcol_num)
+{
+	int keyno = 0;
+
+	if(!(mesh && b_mesh && b_ob && CData))
+		return false;
+
+	Transform tfm = get_transform(b_ob->matrix_world());
+	Transform itfm = transform_quick_inverse(tfm);
+
+	BL::Object::modifiers_iterator b_mod;
+	for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
+		if ((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (b_mod->show_viewport()) && (b_mod->show_render())) {
+			BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
+
+			BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
+
+			BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
+
+			if((b_psys.settings().render_type()==BL::ParticleSettings::render_type_PATH)&&(b_psys.settings().type()==BL::ParticleSettings::type_HAIR)) {
+
+				int mi = clamp(b_psys.settings().material()-1, 0, mesh->used_shaders.size()-1);
+				int shader = mesh->used_shaders[mi];
+				int draw_step = b_psys.settings().draw_step();
+				int ren_step = (int)pow((float)2.0f,(float)draw_step);
+				/*b_psys.settings().render_step(draw_step);*/
+
+				int totparts = b_psys.particles.length();
+				int totchild = b_psys.child_particles.length() * b_psys.settings().draw_percentage() / 100;
+				int totcurves = totchild;
+				
+				if (use_parents || b_psys.settings().child_type() == 0)
+					totcurves += totparts;
+
+				if (totcurves == 0)
+					continue;
+
+				int pa_no = 0;
+				if(!use_parents && !(b_psys.settings().child_type() == 0))
+					pa_no = totparts;
+
+				BL::ParticleSystem::particles_iterator b_pa;
+				b_psys.particles.begin(b_pa);
+				for(; pa_no < totparts+totchild; pa_no++) {
+
+					/*add uvs*/
+					BL::Mesh::tessface_vertex_colors_iterator l;
+					b_mesh->tessface_vertex_colors.begin(l);
+
+					float3 vcol = make_float3(0.0f, 0.0f, 0.0f);
+					if(b_mesh->tessface_vertex_colors.length())
+						b_psys.mcol_on_emitter(psmd, *b_pa, pa_no, vcol_num, &vcol.x);
+					CData->curve_vcol.push_back(vcol);
+
+					if(pa_no < totparts && b_pa != b_psys.particles.end())
+						++b_pa;
 
 				}
 			}
@@ -355,10 +479,10 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, int interpo
 
 				if(curvekey == CData->curve_firstkey[curve]) {
 					subv = 0;
-					v1 = CData->curvekey_co[curvekey+2] - CData->curvekey_co[curvekey];
+					v1 = CData->curvekey_co[min(curvekey+2,CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)] - CData->curvekey_co[curvekey];
 				}
-				else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2)
-					v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey - 2];
+				else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)
+					v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[max(curvekey - 2, CData->curve_firstkey[curve])];
 				else 
 					v1 = CData->curvekey_co[curvekey + 1] - CData->curvekey_co[curvekey - 1];
 
@@ -375,10 +499,10 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, int interpo
 
 					float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
 
-					if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
+					if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1))
 						radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);
 
-					if((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) && (subv == segments))
+					if((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) && (subv == segments))
 						radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.95f);
 
 					xbasis = normalize(cross(v1,RotCam - ickey_loc));
@@ -404,7 +528,6 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, int interpo
 	mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
 
 	/* texture coords still needed */
-
 }
 
 void ExportCurveTriangleRibbons(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int segments)
@@ -428,12 +551,12 @@ void ExportCurveTriangleRibbons(Mesh *mesh, ParticleCurveData *CData, int interp
 				float3 v2;
 
 				if(curvekey == CData->curve_firstkey[curve]) {
-					v1 = CData->curvekey_co[curvekey+2] - CData->curvekey_co[curvekey+1];
+					v1 = CData->curvekey_co[min(curvekey+2,CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)] - CData->curvekey_co[curvekey+1];
 					v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
 				}
-				else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) {
+				else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) {
 					v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
-					v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[curvekey-2];
+					v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[max(curvekey-2,CData->curve_firstkey[curve])];
 				}
 				else {
 					v1 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
@@ -457,12 +580,12 @@ void ExportCurveTriangleRibbons(Mesh *mesh, ParticleCurveData *CData, int interp
 
 				if(curvekey == CData->curve_firstkey[curve]) {
 					subv = 0;
-					v1 = CData->curvekey_co[curvekey+2] - CData->curvekey_co[curvekey+1];
+					v1 = CData->curvekey_co[min(curvekey+2,CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)] - CData->curvekey_co[curvekey+1];
 					v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
 				}
-				else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) {
+				else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) {
 					v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
-					v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[curvekey-2];
+					v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[max(curvekey-2,CData->curve_firstkey[curve])];
 				}
 				else {
 					v1 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
@@ -490,10 +613,10 @@ void ExportCurveTriangleRibbons(Mesh *mesh, ParticleCurveData *CData, int interp
 
 					float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
 
-					if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
+					if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1))
 						radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);
 
-					if((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) && (subv == segments))
+					if((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) && (subv == segments))
 						radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.95f);
 
 					float3 ickey_loc_shfl = ickey_loc - radius * xbasis;
@@ -542,12 +665,12 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int inter
 				float3 v2;
 
 				if(curvekey == CData->curve_firstkey[curve]) {
-					v1 = CData->curvekey_co[curvekey+2] - CData->curvekey_co[curvekey+1];
+					v1 = CData->curvekey_co[min(curvekey+2,CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)] - CData->curvekey_co[curvekey+1];
 					v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
 				}
-				else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) {
+				else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) {
 					v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
-					v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[curvekey-2];
+					v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[max(curvekey-2,CData->curve_firstkey[curve])];
 				}
 				else {
 					v1 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
@@ -572,12 +695,12 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int inter
 
 				if(curvekey == CData->curve_firstkey[curve]) {
 					subv = 0;
-					v1 = CData->curvekey_co[curvekey+2] - CData->curvekey_co[curvekey+1];
+					v1 = CData->curvekey_co[min(curvekey+2,CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)] - CData->curvekey_co[curvekey+1];
 					v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
 				}
-				else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) {
+				else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) {
 					v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
-					v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[curvekey-2];
+					v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[max(curvekey-2,CData->curve_firstkey[curve])];
 				}
 				else {
 					v1 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
@@ -607,10 +730,10 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int inter
 
 					float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
 
-					if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
+					if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1))
 						radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);
 
-					if((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) && (subv == segments))
+					if((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) && (subv == segments))
 						radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.95f);
 
 					float angle = 2 * M_PI_F / (float)resolution;
@@ -717,6 +840,65 @@ static void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CDa
 	}
 }
 
+void ExportCurveTriangleUVs(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int segments, int vert_offset, int resol)
+{
+	float time = 0.0f;
+	float prevtime = 0.0f;
+
+	Attribute *attr = mesh->attributes.find(ATTR_STD_UV);
+	if (attr == NULL)
+		return;
+		
+	float3 *uvdata = attr->data_float3();
+
+	int vertexindex = vert_offset;
+
+	for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
+		for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
+
+			for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
+
+				int subv = 1;
+
+				if (curvekey == CData->curve_firstkey[curve])
+					subv = 0;
+				
+				for (; subv <= segments; subv++) {
+
+					float3 ickey_loc = make_float3(0.0f,0.0f,0.0f);
+
+					InterpolateKeySegments(subv, segments, curvekey, curve, &ickey_loc, &time, CData , interpolation);
+
+					if(subv!=0) {
+						for(int section = 0 ; section < resol; section++) {
+							uvdata[vertexindex] = CData->curve_uv[curve];
+							uvdata[vertexindex].z = prevtime;
+							vertexindex++;
+							uvdata[vertexindex] = CData->curve_uv[curve];
+							uvdata[vertexindex].z = time;
+							vertexindex++;
+							uvdata[vertexindex] = CData->curve_uv[curve];
+							uvdata[vertexindex].z = prevtime;
+							vertexindex++;
+							uvdata[vertexindex] = CData->curve_uv[curve];
+							uvdata[vertexindex].z = time;
+							vertexindex++;
+							uvdata[vertexindex] = CData->curve_uv[curve];
+							uvdata[vertexindex].z = prevtime;
+							vertexindex++;
+							uvdata[vertexindex] = CData->curve_uv[curve];
+							uvdata[vertexindex].z = time;
+							vertexindex++;
+						}
+					}
+
+					prevtime = time;
+				}
+			}
+		}
+	}
+
+}
 /* Hair Curve Sync */
 
 void BlenderSync::sync_curve_settings()
@@ -846,8 +1028,10 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool
 
 	ParticleCurveData CData;
 
-	if(use_cache)
+	if(use_cache) {
 		ObtainCacheParticleData(mesh, &b_mesh, &b_ob, &CData, use_parents);
+		ObtainCacheParticleUV(mesh, &b_mesh, &b_ob, &CData, use_parents);
+	}
 	else
 		ObtainParticleData(mesh, &b_mesh, &b_ob, &CData);
 
@@ -862,12 +1046,20 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool
 	}
 
 	if(primitive == CURVE_TRIANGLES){
-		if(triangle_method == CURVE_CAMERA)
+		int vert_num = mesh->triangles.size() * 3;
+		if(triangle_method == CURVE_CAMERA) {
 			ExportCurveTrianglePlanes(mesh, &CData, interpolation, use_smooth, segments, RotCam);
-		else if(triangle_method == CURVE_RIBBONS)
+			ExportCurveTriangleUVs(mesh, &CData, interpolation, use_smooth, segments, vert_num, 1);
+		}
+		else if(triangle_method == CURVE_RIBBONS) {
 			ExportCurveTriangleRibbons(mesh, &CData, interpolation, use_smooth, segments);
-		else
+			ExportCurveTriangleUVs(mesh, &CData, interpolation, use_smooth, segments, vert_num, 1);
+		}
+		else {
 			ExportCurveTriangleGeometry(mesh, &CData, interpolation, use_smooth, resolution, segments);
+			ExportCurveTriangleUVs(mesh, &CData, interpolation, use_smooth, segments, vert_num, resolution);
+		}
+
 	}
 	else {
 		ExportCurveSegments(scene, mesh, &CData, interpolation, segments);
@@ -901,6 +1093,33 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool
 				generated[i++] = co*size - loc;
 			}
 		}
+
+		/* create vertex color attributes */
+		BL::Mesh::tessface_vertex_colors_iterator l;
+		int vcol_num = 0;
+
+		for(b_mesh.tessface_vertex_colors.begin(l); l != b_mesh.tessface_vertex_colors.end(); ++l, vcol_num++) {
+			if(!mesh->need_attribute(scene, ustring(l->name().c_str())))
+				continue;
+
+			/*error occurs with more than one vertex colour attribute so avoided*/
+			if(vcol_num!=0)
+				break;
+
+			Attribute *attr_vcol = mesh->curve_attributes.add(
+				ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CURVE);
+
+			ObtainCacheParticleVcol(mesh, &b_mesh, &b_ob, &CData, use_parents, 0);
+
+			float3 *vcol = attr_vcol->data_float3();
+
+			if(vcol) {
+				for(size_t curve = 0; curve < CData.curve_vcol.size() ;curve++)
+					vcol[curve] = color_srgb_to_scene_linear(CData.curve_vcol[curve]);
+			}
+
+		}
+
 	}
 
 	mesh->compute_bounds();
diff --git a/intern/cycles/kernel/kernel_bvh.h b/intern/cycles/kernel/kernel_bvh.h
index c73d9328c74..2cb29207b05 100644
--- a/intern/cycles/kernel/kernel_bvh.h
+++ b/intern/cycles/kernel/kernel_bvh.h
@@ -231,13 +231,14 @@ __device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect,
 	float3 dif = P - p1;
 	float3 dir = 1.0f/idir;
 
-	/* test bounding sphere intersection (introduce circular artifacts)*/
-	/*float3 bvector = 0.5f * (p1 + p2) - P;
-	float bvectorl_sq = len_squared(bvector);
-	float dot_bv_dir = dot(bvector,dir);
-	float maxdist = l * 0.5f + mr;
-	if(bvectorl_sq - dot_bv_dir * dot_bv_dir > maxdist * maxdist)
-		return;*/
+	float sp_r = mr + 0.5f * l;
+	float3 sphere_dif = P - ((p1 + p2) * 0.5f);
+	float sphere_b = dot(dir,sphere_dif);
+	sphere_dif = sphere_dif - sphere_b * dir;
+	sphere_b = dot(dir,sphere_dif);
+	float sdisc = sphere_b * sphere_b - len_squared(sphere_dif) + sp_r * sp_r;
+	if(sdisc < 0.0f)
+		return;
 
 	/* obtain parameters and test midpoint distance for suitable modes*/
 	float3 tg = (p2 - p1) / l;
@@ -278,7 +279,7 @@ __device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect,
 	float tc = dot(tdif,tdif) - tdifz * tdifz * (1 + gd*gd) - r1*r1 - 2*r1*tdifz*gd;
 	float td = tb*tb - 4*a*tc;
 
-	if (td<0)
+	if (td < 0.0f)
 		return;
 
 	float rootd = 0.0f;
@@ -321,14 +322,6 @@ __device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect,
 				}
 			}
 
-			/*remove overlap - not functional yet*/
-			/*if (flags & CURVE_KN_CURVEDATA) {
-				float3 tg1 = float4_to_float3(kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+0));
-				float3 tg2 = float4_to_float3(kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+1));
-				if((dot(P + t * dir - p1, tg1) < 0.0f) || (dot(P + t * dir - p2, tg2) > 0.0f))
-					return;
-			}*/
-
 #ifdef __VISIBILITY_FLAG__
 			/* visibility flag test. we do it here under the assumption
 			 * that most triangles are culled by node flags */
diff --git a/intern/cycles/render/curves.h b/intern/cycles/render/curves.h
index 85a549082f2..bb9ef6d99cf 100644
--- a/intern/cycles/render/curves.h
+++ b/intern/cycles/render/curves.h
@@ -81,6 +81,7 @@ public:
 	vector curve_keynum;
 	vector curve_length;
 	vector curve_uv;
+	vector curve_vcol;
 
 	vector curvekey_co;
 	vector curvekey_time;
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(-)

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(-)

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(-)

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(-)

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(-)

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 0e676bf50bd961c86b48af2c0baf10136cdb60a9 Mon Sep 17 00:00:00 2001
From: Bastien Montagne 
Date: Fri, 4 Jan 2013 18:19:07 +0000
Subject: Adding Uzbek language

---
 release/scripts/modules/bl_i18n_utils/settings.py | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/release/scripts/modules/bl_i18n_utils/settings.py b/release/scripts/modules/bl_i18n_utils/settings.py
index df87a288cfe..0f09e8238ab 100644
--- a/release/scripts/modules/bl_i18n_utils/settings.py
+++ b/release/scripts/modules/bl_i18n_utils/settings.py
@@ -81,6 +81,8 @@ LANGUAGES = (
     (35, "Esperanto (Esperanto)", "eo"),
     (36, "Spanish from Spain (Español de España)", "es_ES"),
     (37, "Amharic (አማርኛ)", "am_ET"),
+    (38, "Uzbek (Oʻzbek)", "uz_UZ"),
+    (39, "Uzbek Cyrillic (Ўзбек)", "uz_UZ@cyrillic"),
 )
 
 # Name of language file used by Blender to generate translations' menu.
@@ -91,7 +93,7 @@ LANGUAGES_FILE = "languages"
 IMPORT_MIN_LEVEL = -1
 
 # Languages in /branches we do not want to import in /trunk currently...
-IMPORT_LANGUAGES_SKIP = {'am', 'bg', 'fi', 'el', 'et', 'ko', 'ne', 'pl', 'ro'}
+IMPORT_LANGUAGES_SKIP = {'am', 'bg', 'fi', 'el', 'et', 'ko', 'ne', 'pl', 'ro', 'uz', 'uz@cyrillic'}
 
 # The comment prefix used in generated messages.txt file.
 COMMENT_PREFIX = "#~ "
-- 
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(-)

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(+)

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(-)

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(-)

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(-)

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(+)

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(+)

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(-)

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(-)

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 9b9da2820bc68e11e7ccbc1941b038863cbb4e62 Mon Sep 17 00:00:00 2001
From: Bastien Montagne 
Date: Sat, 5 Jan 2013 11:14:35 +0000
Subject: Adding some example for new UIList...

---
 doc/python_api/examples/bpy.types.UIList.py | 89 +++++++++++++++++++++++++++++
 release/scripts/templates_py/ui_list.py     | 78 +++++++++++++++++++++++++
 2 files changed, 167 insertions(+)
 create mode 100644 doc/python_api/examples/bpy.types.UIList.py
 create mode 100644 release/scripts/templates_py/ui_list.py

diff --git a/doc/python_api/examples/bpy.types.UIList.py b/doc/python_api/examples/bpy.types.UIList.py
new file mode 100644
index 00000000000..f2017e3883d
--- /dev/null
+++ b/doc/python_api/examples/bpy.types.UIList.py
@@ -0,0 +1,89 @@
+"""
+Basic UIList Example
++++++++++++++++++++
+This script is the UIList subclass used to show material slots, with a bunch of additional commentaries.
+
+Notice the name of the class, this naming convention is similar as the one for panels or menus.
+
+.. note::
+
+   UIList subclasses must be registered for blender to use them.
+"""
+import bpy
+
+
+class MATERIAL_UL_matslots_example(bpy.types.UIList):
+    # The draw_item function is called for each item of the collection that is visible in the list.
+    #   data is the RNA object containing the collection,
+    #   item is the current drawn item of the collection,
+    #   icon is the "computed" icon for the item (as an integer, because some objects like materials or textures
+    #   have custom icons ID, which are not available as enum items).
+    #   active_data is the RNA object containing the active property for the collection (i.e. integer pointing to the
+    #   active item of the collection).
+    #   active_propname is the name of the active property (use 'getattr(active_data, active_propname)').
+    #   index is index of the current item in the collection.
+    def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+        ob = data
+        slot = item
+        ma = slot.material
+        # draw_item must handle the three layout types... Usually 'DEFAULT' and 'COMPACT' can share the same code.
+        if self.layout_type in {'DEFAULT', 'COMPACT'}:
+            # You should always start your row layout by a label (icon + text), this will also make the row easily
+            # selectable in the list!
+            # We use icon_value of label, as our given icon is an integer value, not an enum ID.
+            layout.label(ma.name if ma else "", icon_value=icon)
+            # And now we can add other UI stuff...
+            # Here, we add nodes info if this material uses (old!) shading nodes.
+            if ma and not context.scene.render.use_shading_nodes:
+                manode = ma.active_node_material
+                if manode:
+                    # The static method UILayout.icon returns the integer value of the icon ID "computed" for the given
+                    # RNA object.
+                    layout.label("Node %s" % manode.name, icon_value=layout.icon(manode))
+                elif ma.use_nodes:
+                    layout.label("Node ")
+                else:
+                    layout.label("")
+        # 'GRID' layout type should be as compact as possible (typically a single icon!).
+        elif self.layout_type in {'GRID'}:
+            layout.alignment = 'CENTER'
+            layout.label("", icon_value=icon)
+
+
+# And now we can use this list everywhere in Blender. Here is a small example panel.
+class UIListPanelExample(bpy.types.Panel):
+    """Creates a Panel in the Object properties window"""
+    bl_label = "UIList Panel"
+    bl_idname = "OBJECT_PT_ui_list_example"
+    bl_space_type = 'PROPERTIES'
+    bl_region_type = 'WINDOW'
+    bl_context = "object"
+
+    def draw(self, context):
+        layout = self.layout
+
+        obj = context.object
+
+        # template_list now takes two new args.
+        # The first one is the identifier of the registered UIList to use (if you want only the default list,
+        # with no custom draw code, use "UI_UL_list").
+        layout.template_list("MATERIAL_UL_matslots_example", "", obj, "material_slots", obj, "active_material_index")
+
+        # The second one can usually be left as an empty string. It's an additional ID used to distinguish lists in case you
+        # use the same list several times in a given area.
+        layout.template_list("MATERIAL_UL_matslots_example", "compact", obj, "material_slots",
+                             obj, "active_material_index", type='COMPACT')
+
+
+def register():
+    bpy.utils.register_class(MATERIAL_UL_matslots_example)
+    bpy.utils.register_class(UIListPanelExample)
+
+
+def unregister():
+    bpy.utils.unregister_class(MATERIAL_UL_matslots_example)
+    bpy.utils.unregister_class(UIListPanelExample)
+
+
+if __name__ == "__main__":
+    register()
\ No newline at end of file
diff --git a/release/scripts/templates_py/ui_list.py b/release/scripts/templates_py/ui_list.py
new file mode 100644
index 00000000000..18861f7d801
--- /dev/null
+++ b/release/scripts/templates_py/ui_list.py
@@ -0,0 +1,78 @@
+import bpy
+
+
+class MATERIAL_UL_matslots_example(bpy.types.UIList):
+    # The draw_item function is called for each item of the collection that is visible in the list.
+    #   data is the RNA object containing the collection,
+    #   item is the current drawn item of the collection,
+    #   icon is the "computed" icon for the item (as an integer, because some objects like materials or textures
+    #   have custom icons ID, which are not available as enum items).
+    #   active_data is the RNA object containing the active property for the collection (i.e. integer pointing to the
+    #   active item of the collection).
+    #   active_propname is the name of the active property (use 'getattr(active_data, active_propname)').
+    #   index is index of the current item in the collection.
+    def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+        ob = data
+        slot = item
+        ma = slot.material
+        # draw_item must handle the three layout types... Usually 'DEFAULT' and 'COMPACT' can share the same code.
+        if self.layout_type in {'DEFAULT', 'COMPACT'}:
+            # You should always start your row layout by a label (icon + text), this will also make the row easily
+            # selectable in the list!
+            # We use icon_value of label, as our given icon is an integer value, not an enum ID.
+            layout.label(ma.name if ma else "", icon_value=icon)
+            # And now we can add other UI stuff...
+            # Here, we add nodes info if this material uses (old!) shading nodes.
+            if ma and not context.scene.render.use_shading_nodes:
+                manode = ma.active_node_material
+                if manode:
+                    # The static method UILayout.icon returns the integer value of the icon ID "computed" for the given
+                    # RNA object.
+                    layout.label("Node %s" % manode.name, icon_value=layout.icon(manode))
+                elif ma.use_nodes:
+                    layout.label("Node ")
+                else:
+                    layout.label("")
+        # 'GRID' layout type should be as compact as possible (typically a single icon!).
+        elif self.layout_type in {'GRID'}:
+            layout.alignment = 'CENTER'
+            layout.label("", icon_value=icon)
+
+
+# And now we can use this list everywhere in Blender. Here is a small example panel.
+class UIListPanelExample(bpy.types.Panel):
+    """Creates a Panel in the Object properties window"""
+    bl_label = "UIList Panel"
+    bl_idname = "OBJECT_PT_ui_list_example"
+    bl_space_type = 'PROPERTIES'
+    bl_region_type = 'WINDOW'
+    bl_context = "object"
+
+    def draw(self, context):
+        layout = self.layout
+
+        obj = context.object
+
+        # template_list now takes two new args.
+        # The first one is the identifier of the registered UIList to use (if you want only the default list,
+        # with no custom draw code, use "UI_UL_list").
+        layout.template_list("MATERIAL_UL_matslots_example", "", obj, "material_slots", obj, "active_material_index")
+
+        # The second one can usually be left as an empty string. It's an additional ID used to distinguish lists in case you
+        # use the same list several times in a given area.
+        layout.template_list("MATERIAL_UL_matslots_example", "compact", obj, "material_slots",
+                             obj, "active_material_index", type='COMPACT')
+
+
+def register():
+    bpy.utils.register_class(MATERIAL_UL_matslots_example)
+    bpy.utils.register_class(UIListPanelExample)
+
+
+def unregister():
+    bpy.utils.unregister_class(MATERIAL_UL_matslots_example)
+    bpy.utils.unregister_class(UIListPanelExample)
+
+
+if __name__ == "__main__":
+    register()
\ No newline at end of file
-- 
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(-)

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(-)

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(-)

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(-)

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