From 86f791676700dc317a12cb94b2c02fcfd972260a Mon Sep 17 00:00:00 2001 From: Sergej Reich Date: Sat, 16 Feb 2013 19:24:50 +0000 Subject: [PATCH 001/182] Code cleanup, remove redundant function wrapper --- source/blender/blenkernel/intern/scene.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index ede0925e01f..9e83c11a021 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -378,7 +378,7 @@ void BKE_scene_free(Scene *sce) BKE_color_managed_view_settings_free(&sce->view_settings); } -static Scene *scene_add(Main *bmain, const char *name) +Scene *BKE_scene_add(Main *bmain, const char *name) { Scene *sce; ParticleEditSettings *pset; @@ -613,11 +613,6 @@ static Scene *scene_add(Main *bmain, const char *name) return sce; } -Scene *BKE_scene_add(Main *bmain, const char *name) -{ - return scene_add(bmain, name); -} - Base *BKE_scene_base_find(Scene *scene, Object *ob) { return BLI_findptr(&scene->base, ob, offsetof(Base, object)); From 500bc0c5e948079bd0ab7bd2c96a78a1451964f1 Mon Sep 17 00:00:00 2001 From: Sergej Reich Date: Sat, 16 Feb 2013 19:24:52 +0000 Subject: [PATCH 002/182] rigidbody: Fix [#34277] Deleting a copied bullet scene crashes blender. Copying scenes didn't handle rigid body worlds previously. Since we use groups to keep track of objecs in the rigid body sim it's tricky to do the right thing here since groups aren't duplicated. One option would be to create new groups and add the duplicated objects into those but that has other drawbacks. So the rigid body world isn't copied for now. TODO find a better way of handling this. --- source/blender/blenkernel/intern/scene.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 9e83c11a021..6dba03ce22d 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -173,6 +173,7 @@ Scene *BKE_scene_copy(Scene *sce, int type) scen->obedit = NULL; scen->stats = NULL; scen->fps_info = NULL; + scen->rigidbody_world = NULL; /* RB_TODO figure out a way of copying the rigid body world */ BLI_duplicatelist(&(scen->markers), &(sce->markers)); BLI_duplicatelist(&(scen->transform_spaces), &(sce->transform_spaces)); From 9cd01c6a5c68543ed40bfe33d5faa564006b0717 Mon Sep 17 00:00:00 2001 From: Monique Dewanchand Date: Sat, 16 Feb 2013 20:21:41 +0000 Subject: [PATCH 003/182] Added option for group node buffering in the compositor. Justa cluster did not have enough memory to handle all Mango 4k scenes. Option is default disabled and can be enabled in the performance panel. - At Mind - --- release/scripts/startup/bl_ui/space_node.py | 1 + source/blender/compositor/intern/COM_CompositorContext.h | 3 ++- source/blender/compositor/nodes/COM_GroupNode.cpp | 3 ++- source/blender/makesdna/DNA_node_types.h | 8 +++++--- source/blender/makesrna/intern/rna_nodetree.c | 4 ++++ 5 files changed, 14 insertions(+), 5 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py index c46b1c20738..104c1500756 100644 --- a/release/scripts/startup/bl_ui/space_node.py +++ b/release/scripts/startup/bl_ui/space_node.py @@ -252,6 +252,7 @@ class NODE_PT_quality(bpy.types.Panel): col = layout.column() col.prop(tree, "use_opencl") + col.prop(tree, "use_groupnode_buffer") col.prop(tree, "two_pass") col.prop(snode, "show_highlight") col.prop(snode, "use_hidden_preview") diff --git a/source/blender/compositor/intern/COM_CompositorContext.h b/source/blender/compositor/intern/COM_CompositorContext.h index 2f5e8c0648d..840a9e59584 100644 --- a/source/blender/compositor/intern/COM_CompositorContext.h +++ b/source/blender/compositor/intern/COM_CompositorContext.h @@ -74,7 +74,7 @@ private: * @brief does this system have active opencl devices? */ bool m_hasActiveOpenCLDevices; - + /** * @brief Skip slow nodes */ @@ -178,6 +178,7 @@ public: void setFastCalculation(bool fastCalculation) {this->m_fastCalculation = fastCalculation;} bool isFastCalculation() {return this->m_fastCalculation;} + inline bool isGroupnodeBufferEnabled() {return this->getbNodeTree()->flag & NTREE_COM_GROUPNODE_BUFFER;} }; diff --git a/source/blender/compositor/nodes/COM_GroupNode.cpp b/source/blender/compositor/nodes/COM_GroupNode.cpp index 4cef337d994..05c749345d5 100644 --- a/source/blender/compositor/nodes/COM_GroupNode.cpp +++ b/source/blender/compositor/nodes/COM_GroupNode.cpp @@ -64,11 +64,12 @@ void GroupNode::ungroup(ExecutionSystem &system) } } + const bool groupnodeBuffering = system.getContext().isGroupnodeBufferEnabled(); for (index = 0; index < outputsockets.size(); index++) { OutputSocket *outputSocket = outputsockets[index]; bNodeSocket *editorOutput = outputSocket->getbNodeSocket(); if (editorOutput->groupsock) { - SocketProxyNode *proxy = new SocketProxyNode(bnode, editorOutput->groupsock, editorOutput, true); + SocketProxyNode *proxy = new SocketProxyNode(bnode, editorOutput->groupsock, editorOutput, groupnodeBuffering); outputSocket->relinkConnections(proxy->getOutputSocket(0)); ExecutionSystemHelper::addNode(system.getNodes(), proxy); } diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 7f2e388cd69..5aaf46a541f 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -309,9 +309,11 @@ typedef struct bNodeTree { #define NTREE_TYPE_INIT 1 /* ntree->flag */ -#define NTREE_DS_EXPAND 1 /* for animation editors */ -#define NTREE_COM_OPENCL 2 /* use opencl */ -#define NTREE_TWO_PASS 4 /* two pass */ +#define NTREE_DS_EXPAND 1 /* for animation editors */ +#define NTREE_COM_OPENCL 2 /* use opencl */ +#define NTREE_TWO_PASS 4 /* two pass */ +#define NTREE_COM_GROUPNODE_BUFFER 8 /* use groupnode buffers */ + /* XXX not nice, but needed as a temporary flags * for group updates after library linking. */ diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 397e05b6a97..2140f90664e 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -4971,6 +4971,10 @@ static void rna_def_composite_nodetree(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", NTREE_COM_OPENCL); RNA_def_property_ui_text(prop, "OpenCL", "Enable GPU calculations"); + prop = RNA_def_property(srna, "use_groupnode_buffer", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", NTREE_COM_GROUPNODE_BUFFER); + RNA_def_property_ui_text(prop, "Buffer Groups", "Enable buffering of group nodes"); + prop = RNA_def_property(srna, "two_pass", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NTREE_TWO_PASS); RNA_def_property_ui_text(prop, "Two Pass", "Use two pass execution during editing: first calculate fast nodes, " From 772a3b1e1e536e88ca141b404eacc1fbecb73bbf Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Sat, 16 Feb 2013 21:21:04 +0000 Subject: [PATCH 004/182] Fix for [#34182] Movie Distortion and Bilateral Blur doesn't work together * added area of interest based on a radius around the input tile. If someone can implement a correct formula (based on K1, K2 and K3) and send it to me, I will be happy to apply it! - At Mind - --- .../operations/COM_MovieDistortionOperation.cpp | 13 +++++++++++++ .../operations/COM_MovieDistortionOperation.h | 2 ++ 2 files changed, 15 insertions(+) diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp index 68a61dff801..cf379d91652 100644 --- a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp +++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp @@ -112,3 +112,16 @@ void MovieDistortionOperation::executePixel(float output[4], float x, float y, P this->m_inputOperation->read(output, x, y, COM_PS_BILINEAR); } } + +bool MovieDistortionOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +{ + const int marginX = this->m_width*0.15; + const int marginY = this->m_height*0.15; + + rcti newInput; + newInput.xmin = input->xmin - marginX; + newInput.ymin = input->ymin - marginY; + newInput.xmax = input->xmax + marginX; + newInput.ymax = input->ymax + marginY; + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); +} diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.h b/source/blender/compositor/operations/COM_MovieDistortionOperation.h index 9f8aa065e3e..4596fbd555b 100644 --- a/source/blender/compositor/operations/COM_MovieDistortionOperation.h +++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.h @@ -162,6 +162,8 @@ public: void setMovieClip(MovieClip *clip) { this->m_movieClip = clip; } void setFramenumber(int framenumber) { this->m_framenumber = framenumber; } + bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); + }; void deintializeDistortionCache(void); From ed39f334cab23347738a7b2255c4bfd8a360eb45 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sat, 16 Feb 2013 21:32:05 +0000 Subject: [PATCH 005/182] Fix performance regression with anchor brush in sculpt mode When restoring coordinates in sculpt mode (used for several brushes including anchor brush), can use sculpt_undo_get_node() for non-dyntopo sculpting instead of sculpt_undo_push_node(). This should bring speed of anchor brush back to 2.65 level for regular mesh/multires sculpting. Fixes projects.blender.org/tracker/?func=detail&atid=498&aid=34208&group_id=9 --- source/blender/editors/sculpt_paint/sculpt.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 10f4dc2aebc..f737b6ccee7 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -441,7 +441,12 @@ static void paint_mesh_restore_co(Sculpt *sd, Object *ob) SculptUndoType type = (brush->sculpt_tool == SCULPT_TOOL_MASK ? SCULPT_UNDO_MASK : SCULPT_UNDO_COORDS); - unode = sculpt_undo_push_node(ob, nodes[n], type); + if (ss->bm) { + unode = sculpt_undo_push_node(ob, nodes[n], type); + } + else { + unode = sculpt_undo_get_node(nodes[n]); + } if (unode) { PBVHVertexIter vd; SculptOrigVertData orig_data; From 39ee06421c63f52afa2a544cf090cb62be954b94 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sat, 16 Feb 2013 21:36:26 +0000 Subject: [PATCH 006/182] Fix for harmless uninitialized-variable warning --- source/blender/editors/sculpt_paint/sculpt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index f737b6ccee7..976181f837a 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -3158,7 +3158,7 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob) PBVHVertexIter vd; PBVHProxyNode *proxies; int proxy_count; - float (*orco)[3]; + float (*orco)[3] = NULL; if (use_orco && !ss->bm) orco = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS)->co; From 2e0017efd4d6858a1d4d78dc5e72fdd2f1aafaa9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 17 Feb 2013 03:57:20 +0000 Subject: [PATCH 007/182] code cleanup: change order of args in void BKE_object_where_is_calc_time_ex() so extra arg is at the end (loose convention for *_ex() funcs). also some style cleanup. --- source/blender/blenkernel/BKE_object.h | 3 +- source/blender/blenkernel/intern/object.c | 11 ++-- source/blender/blenkernel/intern/rigidbody.c | 2 +- .../COM_MovieDistortionOperation.cpp | 4 +- source/blender/editors/sculpt_paint/sculpt.c | 51 ++++++++++--------- 5 files changed, 37 insertions(+), 34 deletions(-) diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 19c04676548..8a929297acf 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -103,7 +103,8 @@ struct Object *BKE_object_pose_armature_get(struct Object *ob); void BKE_object_where_is_calc(struct Scene *scene, struct Object *ob); void BKE_object_where_is_calc_ex(struct Scene *scene, struct RigidBodyWorld *rbw, struct Object *ob); void BKE_object_where_is_calc_time(struct Scene *scene, struct Object *ob, float ctime); -void BKE_object_where_is_calc_time_ex(struct Scene *scene, struct RigidBodyWorld *rbw, struct Object *ob, float ctime); +void BKE_object_where_is_calc_time_ex(struct Scene *scene, struct Object *ob, float ctime, + struct RigidBodyWorld *rbw); void BKE_object_where_is_calc_simul(struct Scene *scene, struct Object *ob); void BKE_object_where_is_calc_mat4(struct Scene *scene, struct Object *ob, float obmat[4][4]); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 117e9fe280c..ef3c98ee3f4 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -2118,7 +2118,8 @@ static int where_is_object_parslow(Object *ob, float obmat[4][4], float slowmat[ } /* note, scene is the active scene while actual_scene is the scene the object resides in */ -void BKE_object_where_is_calc_time_ex(Scene *scene, RigidBodyWorld *rbw, Object *ob, float ctime) +void BKE_object_where_is_calc_time_ex(Scene *scene, Object *ob, float ctime, + RigidBodyWorld *rbw) { if (ob == NULL) return; @@ -2163,7 +2164,7 @@ void BKE_object_where_is_calc_time_ex(Scene *scene, RigidBodyWorld *rbw, Object void BKE_object_where_is_calc_time(Scene *scene, Object *ob, float ctime) { - BKE_object_where_is_calc_time_ex(scene, NULL, ob, ctime); + BKE_object_where_is_calc_time_ex(scene, ob, ctime, NULL); } /* get object transformation matrix without recalculating dependencies and @@ -2189,17 +2190,17 @@ void BKE_object_where_is_calc_mat4(Scene *scene, Object *ob, float obmat[4][4]) void BKE_object_where_is_calc_ex(Scene *scene, RigidBodyWorld *rbw, Object *ob) { - BKE_object_where_is_calc_time_ex(scene, rbw, ob, BKE_scene_frame_get(scene)); + BKE_object_where_is_calc_time_ex(scene, ob, BKE_scene_frame_get(scene), rbw); } void BKE_object_where_is_calc(Scene *scene, Object *ob) { - BKE_object_where_is_calc_time_ex(scene, NULL, ob, BKE_scene_frame_get(scene)); + BKE_object_where_is_calc_time_ex(scene, ob, BKE_scene_frame_get(scene), NULL); } -void BKE_object_where_is_calc_simul(Scene *scene, Object *ob) /* was written for the old game engine (until 2.04) */ /* It seems that this function is only called * for a lamp that is the child of another object */ +void BKE_object_where_is_calc_simul(Scene *scene, Object *ob) { Object *par; float *fp1, *fp2; diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 26f0c25617f..66edfe2fe15 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -1308,7 +1308,7 @@ struct RigidBodyCon *BKE_rigidbody_create_constraint(Scene *scene, Object *ob, s struct RigidBodyWorld *BKE_rigidbody_get_world(Scene *scene) { return NULL; } void BKE_rigidbody_remove_object(Scene *scene, Object *ob) {} void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob) {} -void BKE_rigidbody_sync_transforms(Scene *scene, Object *ob, float ctime) {} +void BKE_rigidbody_sync_transforms(RigidBodyWorld *rbw, Object *ob, float ctime) {} void BKE_rigidbody_aftertrans_update(Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle) {} void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) {} void BKE_rigidbody_do_simulation(Scene *scene, float ctime) {} diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp index cf379d91652..b0fc21d4d55 100644 --- a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp +++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp @@ -115,8 +115,8 @@ void MovieDistortionOperation::executePixel(float output[4], float x, float y, P bool MovieDistortionOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) { - const int marginX = this->m_width*0.15; - const int marginY = this->m_height*0.15; + const int marginX = this->m_width * 0.15; + const int marginY = this->m_height * 0.15; rcti newInput; newInput.xmin = input->xmin - marginX; diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 976181f837a..342671698d2 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -883,7 +883,7 @@ 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, - const float point[3], + const float point[3], const float len, const float sculpt_normal[3], const short vno[3], @@ -1411,8 +1411,8 @@ static float bmesh_neighbor_average_mask(BMesh *bm, BMVert *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); + v2->head.data, + CD_PAINT_MASK); avg += (*vmask); total++; } @@ -1423,8 +1423,8 @@ static float bmesh_neighbor_average_mask(BMesh *bm, BMVert *v) } else { float *vmask = CustomData_bmesh_get(&bm->vdata, - v->head.data, - CD_PAINT_MASK); + v->head.data, + CD_PAINT_MASK); return (*vmask); } } @@ -1938,11 +1938,11 @@ static void do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) if (sculpt_brush_test(&test, orig_data.co)) { const float fade = bstrength * tex_strength(ss, brush, - orig_data.co, - test.dist, + orig_data.co, + test.dist, ss->cache->sculpt_normal_symm, - orig_data.no, - NULL, vd.mask ? *vd.mask : 0.0f); + orig_data.no, + NULL, vd.mask ? *vd.mask : 0.0f); mul_v3_v3fl(proxy[vd.i], grab_delta, fade); @@ -2077,11 +2077,11 @@ static void do_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode if (sculpt_brush_test(&test, orig_data.co)) { const float fade = bstrength * tex_strength(ss, brush, - orig_data.co, - test.dist, + orig_data.co, + test.dist, ss->cache->sculpt_normal_symm, orig_data.no, - NULL, vd.mask ? *vd.mask : 0.0f); + NULL, vd.mask ? *vd.mask : 0.0f); mul_v3_v3fl(proxy[vd.i], cono, fade); @@ -2135,7 +2135,7 @@ static void do_rotate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod test.dist, ss->cache->sculpt_normal_symm, orig_data.no, - NULL, vd.mask ? *vd.mask : 0.0f); + NULL, vd.mask ? *vd.mask : 0.0f); mul_v3_m4v3(proxy[vd.i], m, orig_data.co); sub_v3_v3(proxy[vd.i], orig_data.co); @@ -3005,7 +3005,7 @@ static void sculpt_topology_update(Sculpt *sd, Object *ob, Brush *brush) if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) { BKE_pbvh_bmesh_update_topology(ss->pbvh, mode, - ss->cache->location, + ss->cache->location, ss->cache->radius); } @@ -3313,7 +3313,7 @@ static void calc_brushdata_symm(Sculpt *sd, StrokeCache *cache, const char symm, typedef void (*BrushActionFunc)(Sculpt *sd, Object *ob, Brush *brush); static void do_radial_symmetry(Sculpt *sd, Object *ob, Brush *brush, - BrushActionFunc action, + BrushActionFunc action, const char symm, const int axis, const float feather) { @@ -4077,7 +4077,7 @@ static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin) } if (BKE_pbvh_node_raycast(srd->ss->pbvh, node, origco, use_origco, - srd->ray_start, srd->ray_normal, &srd->dist)) + srd->ray_start, srd->ray_normal, &srd->dist)) { srd->hit = 1; *tmin = srd->dist; @@ -4665,24 +4665,25 @@ static int sculpt_dynamic_topology_toggle_exec(bContext *C, wmOperator *UNUSED(o } static int sculpt_dynamic_topology_toggle_invoke(bContext *C, wmOperator *op, - wmEvent *UNUSED(event)) + 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"; + "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))) { + 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); @@ -4763,8 +4764,8 @@ static int sculpt_symmetrize_exec(bContext *C, wmOperator *UNUSED(op)) /* Symmetrize and re-triangulate */ BMO_op_callf(ss->bm, BMO_FLAG_DEFAULTS, - "symmetrize input=%avef direction=%i", - sd->symmetrize_direction); + "symmetrize input=%avef direction=%i", + sd->symmetrize_direction); sculpt_dynamic_topology_triangulate(ss->bm); /* Finish undo */ From 00f48914f32f9df4266ff73550a0f80a085baa32 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 17 Feb 2013 04:35:50 +0000 Subject: [PATCH 008/182] code cleanup: missed r54603, arg reordering. --- source/blender/blenkernel/BKE_object.h | 3 ++- source/blender/blenkernel/intern/object.c | 5 +++-- source/blender/blenkernel/intern/scene.c | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 8a929297acf..89860cd0da9 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -150,7 +150,8 @@ void BKE_object_tfm_protected_restore(struct Object *ob, const short protectflag); void BKE_object_handle_update(struct Scene *scene, struct Object *ob); -void BKE_object_handle_update_ex(struct Scene *scene, struct RigidBodyWorld *rbw, struct Object *ob); +void BKE_object_handle_update_ex(struct Scene *scene, struct Object *ob, + struct RigidBodyWorld *rbw); void BKE_object_sculpt_modifiers_changed(struct Object *ob); int BKE_object_obdata_texspace_get(struct Object *ob, short **r_texflag, float **r_loc, float **r_size, float **r_rot); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index ef3c98ee3f4..b810aa89257 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -2631,7 +2631,8 @@ int BKE_object_parent_loop_check(const Object *par, const Object *ob) /* the main object update call, for object matrix, constraints, keys and displist (modifiers) */ /* requires flags to be set! */ /* Ideally we shouldn't have to pass the rigid body world, but need bigger restructuring to avoid id */ -void BKE_object_handle_update_ex(Scene *scene, RigidBodyWorld *rbw, Object *ob) +void BKE_object_handle_update_ex(Scene *scene, Object *ob, + RigidBodyWorld *rbw) { if (ob->recalc & OB_RECALC_ALL) { /* speed optimization for animation lookups */ @@ -2833,7 +2834,7 @@ void BKE_object_handle_update_ex(Scene *scene, RigidBodyWorld *rbw, Object *ob) */ void BKE_object_handle_update(Scene *scene, Object *ob) { - BKE_object_handle_update_ex(scene, NULL, ob); + BKE_object_handle_update_ex(scene, ob, NULL); } void BKE_object_sculpt_modifiers_changed(Object *ob) diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 6dba03ce22d..279c321d371 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -1125,7 +1125,7 @@ static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scen for (base = scene->base.first; base; base = base->next) { Object *ob = base->object; - BKE_object_handle_update_ex(scene_parent, scene->rigidbody_world, ob); + BKE_object_handle_update_ex(scene_parent, ob, scene->rigidbody_world); if (ob->dup_group && (ob->transflag & OB_DUPLIGROUP)) group_handle_recalc_and_update(scene_parent, ob, ob->dup_group); From 34805a4752b0ce6a66d24389b04f86b26fb7e71f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 17 Feb 2013 05:16:48 +0000 Subject: [PATCH 009/182] BLI_mempool totalloc was being used un-initialized, normally this would cause bugs but turns out its not used, ifdef'd it out but keep in the struct in BLI_mempool for now. --- source/blender/blenlib/intern/BLI_mempool.c | 14 +++++++++++--- source/blender/makesrna/intern/makesrna.c | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c index 7670b057a7f..5f0c90f234d 100644 --- a/source/blender/blenlib/intern/BLI_mempool.c +++ b/source/blender/blenlib/intern/BLI_mempool.c @@ -54,6 +54,9 @@ #define FREEWORD MAKE_ID('f', 'r', 'e', 'e') +/* currently totalloc isnt used */ +// #define USE_TOTALLOC + typedef struct BLI_freenode { struct BLI_freenode *next; int freeword; /* used to identify this as a freed node */ @@ -110,6 +113,7 @@ BLI_mempool *BLI_mempool_create(int esize, int totelem, int pchunk, int flag) pool->pchunk = pchunk; pool->csize = esize * pchunk; pool->chunks.first = pool->chunks.last = NULL; + pool->totalloc = 0; pool->totused = 0; maxchunks = totelem / pchunk + 1; @@ -159,10 +163,11 @@ BLI_mempool *BLI_mempool_create(int esize, int totelem, int pchunk, int flag) } } - /* set the end of this chunks memoryy to the new tail for next iteration */ + /* set the end of this chunks memory to the new tail for next iteration */ lasttail = curnode; - +#ifdef USE_TOTALLOC pool->totalloc += pool->pchunk; +#endif } /* terminate the list */ curnode->next = NULL; @@ -213,8 +218,9 @@ void *BLI_mempool_alloc(BLI_mempool *pool) } } curnode->next = NULL; /* terminate the list */ - +#ifdef USE_TOTALLOC pool->totalloc += pool->pchunk; +#endif } retval = pool->free; @@ -282,7 +288,9 @@ void BLI_mempool_free(BLI_mempool *pool, void *addr) } BLI_addtail(&pool->chunks, first); +#ifdef USE_TOTALLOC pool->totalloc = pool->pchunk; +#endif pool->free = first->data; /* start of the list */ for (tmpaddr = first->data, i = 0; i < pool->pchunk; i++) { diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 96ca3805d3e..95222a067af 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -1798,7 +1798,7 @@ static const char *rna_parameter_type_cpp_name(PropertyRNA *prop) } } -static void rna_def_struct_function_prototype_cpp(FILE *f, StructRNA *srna, FunctionDefRNA *dfunc, +static void rna_def_struct_function_prototype_cpp(FILE *f, StructRNA *UNUSED(srna), FunctionDefRNA *dfunc, const char *namespace, int close_prototype) { PropertyDefRNA *dp; From 18f12c3fa4196189c8c8a21c147ac3c46abac74d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 17 Feb 2013 05:39:55 +0000 Subject: [PATCH 010/182] allow alt or Ckey to toggle clamping for vertex slide. --- source/blender/editors/transform/transform.c | 14 ++++++++------ source/blender/editors/transform/transform.h | 1 - 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 8ffa04050a2..ae00f012846 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -6054,7 +6054,6 @@ static int createVertSlideVerts(TransInfo *t) } sld->is_proportional = true; - sld->is_clamp = true; sld->curr_sv_index = 0; sld->flipped_vtx = false; @@ -6252,7 +6251,7 @@ int handleEventVertSlide(struct TransInfo *t, struct wmEvent *event) { /* use like a modifier key */ if (event->val == KM_PRESS) { - sld->is_clamp = !sld->is_clamp; + t->flag ^= T_ALT_TRANSFORM; calcVertSlideCustomPoints(t); return 1; } @@ -6278,7 +6277,8 @@ int handleEventVertSlide(struct TransInfo *t, struct wmEvent *event) case MOUSEMOVE: { /* don't recalculat the best edge */ - if (sld->is_clamp) { + const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); + if (is_clamp) { calcVertSlideMouseActiveEdges(t, event->mval); } calcVertSlideCustomPoints(t); @@ -6303,6 +6303,7 @@ static void drawVertSlide(const struct bContext *C, TransInfo *t) const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f; const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f; const int alpha_shade = -30; + const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); int i; if (v3d && v3d->zbuf) @@ -6319,7 +6320,7 @@ static void drawVertSlide(const struct bContext *C, TransInfo *t) glLineWidth(line_size); UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); glBegin(GL_LINES); - if (sld->is_clamp) { + if (is_clamp) { sv = sld->sv; for (i = 0; i < sld->totsv; i++, sv++) { glVertex3fv(sv->co_orig_3d); @@ -6412,7 +6413,8 @@ int VertSlide(TransInfo *t, const int UNUSED(mval[2])) VertSlideData *sld = t->customData; const bool flipped = sld->flipped_vtx; const bool is_proportional = sld->is_proportional; - const bool is_constrained = !(sld->is_clamp == false || hasNumInput(&t->num)); + const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); + const bool is_constrained = !(is_clamp == false || hasNumInput(&t->num)); final = t->values[0]; @@ -6439,7 +6441,7 @@ int VertSlide(TransInfo *t, const int UNUSED(mval[2])) if (!is_proportional) { str_p += BLI_snprintf(str_p, sizeof(str) - (str_p - str), "(F)lipped: %s, ", flipped ? "ON" : "OFF"); } - str_p += BLI_snprintf(str_p, sizeof(str) - (str_p - str), "(C)lamp: %s", sld->is_clamp ? "ON" : "OFF"); + str_p += BLI_snprintf(str_p, sizeof(str) - (str_p - str), "Alt or (C)lamp: %s", is_clamp ? "ON" : "OFF"); /* done with header string */ if (is_constrained) { diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 78f346be2aa..4e3f2b04de0 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -239,7 +239,6 @@ typedef struct VertSlideData { float perc; bool is_proportional; - bool is_clamp; bool flipped_vtx; int curr_sv_index; From b0a7370284f076cdb0570d05d8afd955f3cdc231 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 17 Feb 2013 05:58:18 +0000 Subject: [PATCH 011/182] vertex slide: dont write clamped value back into TransInfo.values, this meant toggling clamp didn't take any effect until the mouse was moved. (annoying glitch) --- source/blender/editors/transform/transform.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index ae00f012846..e5b4a6c7bae 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -6444,15 +6444,11 @@ int VertSlide(TransInfo *t, const int UNUSED(mval[2])) str_p += BLI_snprintf(str_p, sizeof(str) - (str_p - str), "Alt or (C)lamp: %s", is_clamp ? "ON" : "OFF"); /* done with header string */ - if (is_constrained) { - CLAMP(final, 0.0f, 1.0f); - } - - t->values[0] = final; /*do stuff here*/ - if (t->customData) + if (t->customData) { doVertSlide(t, final); + } else { strcpy(str, "Invalid Vert Selection"); t->state = TRANS_CANCEL; From 6e0cedd61cba2cfcdbf470cdd89f5604ca8fe7f0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 17 Feb 2013 07:17:04 +0000 Subject: [PATCH 012/182] code cleanup: operator/function mismatch --- source/blender/editors/object/object_hook.c | 4 ++-- source/blender/editors/object/object_intern.h | 4 ++-- source/blender/editors/object/object_ops.c | 4 ++-- source/blender/editors/uvedit/uvedit_intern.h | 2 +- source/blender/editors/uvedit/uvedit_ops.c | 2 +- source/blender/editors/uvedit/uvedit_unwrap_ops.c | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c index 1387ef94091..b1612a2b9d3 100644 --- a/source/blender/editors/object/object_hook.c +++ b/source/blender/editors/object/object_hook.c @@ -558,7 +558,7 @@ static int object_add_hook_selob_exec(bContext *C, wmOperator *op) } } -void OBJECT_OT_hook_add_selobj(wmOperatorType *ot) +void OBJECT_OT_hook_add_selob(wmOperatorType *ot) { /* identifiers */ ot->name = "Hook to Selected Object"; @@ -592,7 +592,7 @@ static int object_add_hook_newob_exec(bContext *C, wmOperator *op) } } -void OBJECT_OT_hook_add_newobj(wmOperatorType *ot) +void OBJECT_OT_hook_add_newob(wmOperatorType *ot) { /* identifiers */ ot->name = "Hook to New Object"; diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index 0be9c92897e..4523ac098d6 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -127,8 +127,8 @@ void OBJECT_OT_join_shapes(struct wmOperatorType *ot); void OBJECT_OT_convert(struct wmOperatorType *ot); /* object_hook.c */ -void OBJECT_OT_hook_add_selobj(struct wmOperatorType *ot); -void OBJECT_OT_hook_add_newobj(struct wmOperatorType *ot); +void OBJECT_OT_hook_add_selob(struct wmOperatorType *ot); +void OBJECT_OT_hook_add_newob(struct wmOperatorType *ot); void OBJECT_OT_hook_remove(struct wmOperatorType *ot); void OBJECT_OT_hook_select(struct wmOperatorType *ot); void OBJECT_OT_hook_assign(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index d26ea89bd1e..bf408d6dbe4 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -217,8 +217,8 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_group_link); WM_operatortype_append(OBJECT_OT_group_remove); - WM_operatortype_append(OBJECT_OT_hook_add_selobj); - WM_operatortype_append(OBJECT_OT_hook_add_newobj); + WM_operatortype_append(OBJECT_OT_hook_add_selob); + WM_operatortype_append(OBJECT_OT_hook_add_newob); WM_operatortype_append(OBJECT_OT_hook_remove); WM_operatortype_append(OBJECT_OT_hook_select); WM_operatortype_append(OBJECT_OT_hook_assign); diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h index 7faec33ca98..d1893d639bb 100644 --- a/source/blender/editors/uvedit/uvedit_intern.h +++ b/source/blender/editors/uvedit/uvedit_intern.h @@ -79,7 +79,7 @@ void uvedit_get_aspect(struct Scene *scene, struct Object *ob, struct BMEditMesh void UV_OT_average_islands_scale(struct wmOperatorType *ot); void UV_OT_cube_project(struct wmOperatorType *ot); void UV_OT_cylinder_project(struct wmOperatorType *ot); -void UV_OT_from_view(struct wmOperatorType *ot); +void UV_OT_project_from_view(struct wmOperatorType *ot); void UV_OT_minimize_stretch(struct wmOperatorType *ot); void UV_OT_pack_islands(struct wmOperatorType *ot); void UV_OT_reset(struct wmOperatorType *ot); diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index e158f8843b7..a17d3c20c1c 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -4053,7 +4053,7 @@ void ED_operatortypes_uvedit(void) WM_operatortype_append(UV_OT_average_islands_scale); WM_operatortype_append(UV_OT_cube_project); WM_operatortype_append(UV_OT_cylinder_project); - WM_operatortype_append(UV_OT_from_view); + WM_operatortype_append(UV_OT_project_from_view); WM_operatortype_append(UV_OT_minimize_stretch); WM_operatortype_append(UV_OT_pack_islands); WM_operatortype_append(UV_OT_reset); diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index 00b82e26a05..4ddf4bd6a5c 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -1387,7 +1387,7 @@ static int uv_from_view_poll(bContext *C) return (rv3d != NULL); } -void UV_OT_from_view(wmOperatorType *ot) +void UV_OT_project_from_view(wmOperatorType *ot) { /* identifiers */ ot->name = "Project From View"; From c524b479121179fbd82c158c59c876bb06b2b999 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sun, 17 Feb 2013 13:56:49 +0000 Subject: [PATCH 013/182] =?UTF-8?q?Another=20huge=20bunch=20of=20UI=20tran?= =?UTF-8?q?slation=20fixes,=20mostly=20reported=20by=20Leon=20Cheung,=20Sv?= =?UTF-8?q?.Lockal,=20Gabriel=20Gazz=C3=A1n=20and=20Satoshi=20Yamasaki,=20?= =?UTF-8?q?thanks!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../startup/bl_ui/properties_material.py | 8 +-- source/blender/blenkernel/intern/pointcache.c | 24 ++++--- source/blender/editors/curve/editcurve.c | 13 ++-- .../editors/interface/interface_regions.c | 12 ++-- .../editors/interface/interface_templates.c | 2 +- .../blender/editors/space_clip/CMakeLists.txt | 4 ++ source/blender/editors/space_clip/SConscript | 3 + .../blender/editors/space_clip/clip_buttons.c | 67 ++++++++++--------- .../blender/editors/space_clip/clip_toolbar.c | 10 ++- .../blender/editors/space_image/image_ops.c | 2 +- source/blender/makesrna/intern/rna_nodetree.c | 3 +- .../windowmanager/intern/wm_operators.c | 24 ++++--- 12 files changed, 99 insertions(+), 73 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py index 273b2450200..a13c722ea62 100644 --- a/release/scripts/startup/bl_ui/properties_material.py +++ b/release/scripts/startup/bl_ui/properties_material.py @@ -566,7 +566,7 @@ class MATERIAL_PT_halo(MaterialButtonsPanel, Panel): row.prop(halo, toggle, text="") sub = row.column() sub.active = getattr(halo, toggle) - sub.prop(halo, number, text=name) + sub.prop(halo, number, text=name, translate=False) if not color == "": sub.prop(mat, color, text="") @@ -593,9 +593,9 @@ class MATERIAL_PT_halo(MaterialButtonsPanel, Panel): col.prop(halo, "use_soft") col = split.column() - number_but(col, "use_ring", "ring_count", "Rings", "mirror_color") - number_but(col, "use_lines", "line_count", "Lines", "specular_color") - number_but(col, "use_star", "star_tip_count", "Star tips", "") + number_but(col, "use_ring", "ring_count", iface_("Rings"), "mirror_color") + number_but(col, "use_lines", "line_count", iface_("Lines"), "specular_color") + number_but(col, "use_star", "star_tip_count", iface_("Star Tips"), "") class MATERIAL_PT_flare(MaterialButtonsPanel, Panel): diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 4302032ade1..27c5e03132e 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -52,6 +52,8 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +#include "BLF_translation.h" + #include "PIL_time.h" #include "WM_api.h" @@ -3505,11 +3507,11 @@ void BKE_ptcache_update_info(PTCacheID *pid) /* smoke doesn't use frame 0 as info frame so can't check based on totpoint */ if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN && totframes) - BLI_snprintf(cache->info, sizeof(cache->info), "%i frames found!", totframes); + BLI_snprintf(cache->info, sizeof(cache->info), IFACE_("%i frames found!"), totframes); else if (totframes && cache->totpoint) - BLI_snprintf(cache->info, sizeof(cache->info), "%i points found!", cache->totpoint); + BLI_snprintf(cache->info, sizeof(cache->info), IFACE_("%i points found!"), cache->totpoint); else - BLI_snprintf(cache->info, sizeof(cache->info), "No valid data to read!"); + BLI_snprintf(cache->info, sizeof(cache->info), IFACE_("No valid data to read!")); return; } @@ -3518,9 +3520,9 @@ void BKE_ptcache_update_info(PTCacheID *pid) int totpoint = pid->totpoint(pid->calldata, 0); if (cache->totpoint > totpoint) - BLI_snprintf(mem_info, sizeof(mem_info), "%i cells + High Resolution cached", totpoint); + BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%i cells + High Resolution cached"), totpoint); else - BLI_snprintf(mem_info, sizeof(mem_info), "%i cells cached", totpoint); + BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%i cells cached"), totpoint); } else { int cfra = cache->startframe; @@ -3530,7 +3532,7 @@ void BKE_ptcache_update_info(PTCacheID *pid) totframes++; } - BLI_snprintf(mem_info, sizeof(mem_info), "%i frames on disk", totframes); + BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%i frames on disk"), totframes); } } else { @@ -3554,17 +3556,18 @@ void BKE_ptcache_update_info(PTCacheID *pid) mb = (bytes > 1024.0f * 1024.0f); - BLI_snprintf(mem_info, sizeof(mem_info), "%i frames in memory (%.1f %s)", + BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%i frames in memory (%.1f %s)"), totframes, bytes / (mb ? 1024.0f * 1024.0f : 1024.0f), - mb ? "Mb" : "kb"); + mb ? IFACE_("Mb") : IFACE_("kb")); } if (cache->flag & PTCACHE_OUTDATED) { - BLI_snprintf(cache->info, sizeof(cache->info), "%s, cache is outdated!", mem_info); + BLI_snprintf(cache->info, sizeof(cache->info), IFACE_("%s, cache is outdated!"), mem_info); } else if (cache->flag & PTCACHE_FRAMES_SKIPPED) { - BLI_snprintf(cache->info, sizeof(cache->info), "%s, not exact since frame %i.", mem_info, cache->last_exact); + BLI_snprintf(cache->info, sizeof(cache->info), IFACE_("%s, not exact since frame %i."), + mem_info, cache->last_exact); } else { BLI_snprintf(cache->info, sizeof(cache->info), "%s.", mem_info); @@ -3586,4 +3589,3 @@ void BKE_ptcache_invalidate(PointCache *cache) cache->last_exact = MIN2(cache->startframe, 0); } } - diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index a67bf00a559..a72d3767b69 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -2481,10 +2481,11 @@ static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short /**************** select start/end operators **************/ -/* (de)selects first or last of visible part of each Nurb depending on selFirst */ -/* selFirst: defines the end of which to select */ -/* doswap: defines if selection state of each first/last control point is swapped */ -/* selstatus: selection status in case doswap is false */ +/* (de)selects first or last of visible part of each Nurb depending on selFirst + * selFirst: defines the end of which to select + * doswap: defines if selection state of each first/last control point is swapped + * selstatus: selection status in case doswap is false + */ void selectend_nurb(Object *obedit, short selfirst, short doswap, short selstatus) { ListBase *editnurb = object_editcurve_get(obedit); @@ -2558,7 +2559,7 @@ void CURVE_OT_de_select_first(wmOperatorType *ot) /* identifiers */ ot->name = "(De)select First"; ot->idname = "CURVE_OT_de_select_first"; - ot->description = "(De)select first of visible part of each Nurb"; + ot->description = "(De)select first of visible part of each NURBS"; /* api cfirstbacks */ ot->exec = de_select_first_exec; @@ -2583,7 +2584,7 @@ void CURVE_OT_de_select_last(wmOperatorType *ot) /* identifiers */ ot->name = "(De)select Last"; ot->idname = "CURVE_OT_de_select_last"; - ot->description = "(De)select last of visible part of each Nurb"; + ot->description = "(De)select last of visible part of each NURBS"; /* api clastbacks */ ot->exec = de_select_last_exec; diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 9b2ed9f0984..36717507072 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -2621,7 +2621,7 @@ void uiPupMenuOkee(bContext *C, const char *opname, const char *str, ...) va_list ap; char titlestr[256]; - BLI_snprintf(titlestr, sizeof(titlestr), "OK? %%i%d", ICON_QUESTION); + BLI_snprintf(titlestr, sizeof(titlestr), IFACE_("OK? %%i%d"), ICON_QUESTION); va_start(ap, str); vconfirm_opname(C, opname, titlestr, str, ap); @@ -2635,7 +2635,7 @@ void uiPupMenuOkee(bContext *C, const char *opname, const char *str, ...) * The operator state for this is implicitly OPERATOR_RUNNING_MODAL */ void uiPupMenuSaveOver(bContext *C, wmOperator *op, const char *filename) { - confirm_operator(C, op, "Save Over?", filename); + confirm_operator(C, op, IFACE_("Save Over?"), filename); } void uiPupMenuNotice(bContext *C, const char *str, ...) @@ -2653,7 +2653,7 @@ void uiPupMenuError(bContext *C, const char *str, ...) char nfmt[256]; char titlestr[256]; - BLI_snprintf(titlestr, sizeof(titlestr), "Error %%i%d", ICON_ERROR); + BLI_snprintf(titlestr, sizeof(titlestr), IFACE_("Error %%i%d"), ICON_ERROR); BLI_strncpy(nfmt, str, sizeof(nfmt)); @@ -2680,13 +2680,13 @@ void uiPupMenuReports(bContext *C, ReportList *reports) /* pass */ } else if (report->type >= RPT_ERROR) { - BLI_dynstr_appendf(ds, "Error %%i%d%%t|%s", ICON_ERROR, report->message); + BLI_dynstr_appendf(ds, IFACE_("Error %%i%d%%t|%s"), ICON_ERROR, report->message); } else if (report->type >= RPT_WARNING) { - BLI_dynstr_appendf(ds, "Warning %%i%d%%t|%s", ICON_ERROR, report->message); + BLI_dynstr_appendf(ds, IFACE_("Warning %%i%d%%t|%s"), ICON_ERROR, report->message); } else if (report->type >= RPT_INFO) { - BLI_dynstr_appendf(ds, "Info %%i%d%%t|%s", ICON_INFO, report->message); + BLI_dynstr_appendf(ds, IFACE_("Info %%i%d%%t|%s"), ICON_INFO, report->message); } } diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index f827da6fcc4..8dc51387db7 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -3001,7 +3001,7 @@ void uiTemplateColorspaceSettings(uiLayout *layout, PointerRNA *ptr, const char colorspace_settings_ptr = RNA_property_pointer_get(ptr, prop); - uiItemL(layout, "Input Color Space:", ICON_NONE); + uiItemL(layout, IFACE_("Input Color Space:"), ICON_NONE); uiItemR(layout, &colorspace_settings_ptr, "name", 0, "", ICON_NONE); } diff --git a/source/blender/editors/space_clip/CMakeLists.txt b/source/blender/editors/space_clip/CMakeLists.txt index 75e3d8d5685..e09a8b41262 100644 --- a/source/blender/editors/space_clip/CMakeLists.txt +++ b/source/blender/editors/space_clip/CMakeLists.txt @@ -57,4 +57,8 @@ set(SRC clip_intern.h ) +if(WITH_INTERNATIONAL) + add_definitions(-DWITH_INTERNATIONAL) +endif() + blender_add_lib(bf_editor_space_clip "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/editors/space_clip/SConscript b/source/blender/editors/space_clip/SConscript index 2cbefee0170..c65a076186f 100644 --- a/source/blender/editors/space_clip/SConscript +++ b/source/blender/editors/space_clip/SConscript @@ -32,4 +32,7 @@ defs = [] incs = '../include ../../blenkernel ../../blenloader ../../blenfont ../../blenlib ../../imbuf ../../makesdna' incs += ' ../../makesrna ../../windowmanager #/intern/guardedalloc #/extern/glew/include ../../gpu' +if env['WITH_BF_INTERNATIONAL']: + defs.append('WITH_INTERNATIONAL') + env.BlenderLib ( 'bf_editors_space_clip', sources, Split(incs), defs, libtype=['core'], priority=[95] ) diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c index 2cb6d8c9234..e442de2ba66 100644 --- a/source/blender/editors/space_clip/clip_buttons.c +++ b/source/blender/editors/space_clip/clip_buttons.c @@ -43,6 +43,8 @@ #include "BLI_listbase.h" #include "BLI_rect.h" +#include "BLF_translation.h" + #include "BKE_context.h" #include "BKE_depsgraph.h" #include "BKE_screen.h" @@ -124,7 +126,7 @@ void uiTemplateMovieClip(uiLayout *layout, bContext *C, PointerRNA *ptr, const c row = uiLayoutRow(layout, FALSE); block = uiLayoutGetBlock(row); - uiDefBut(block, LABEL, 0, "File Path:", 0, 19, 145, 19, NULL, 0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, IFACE_("File Path:"), 0, 19, 145, 19, NULL, 0, 0, 0, 0, ""); row = uiLayoutRow(layout, FALSE); split = uiLayoutSplit(row, 0.0f, FALSE); @@ -387,9 +389,9 @@ void uiTemplateMarker(uiLayout *layout, PointerRNA *ptr, const char *propname, P block = uiLayoutGetBlock(layout); if (cb->marker_flag & MARKER_DISABLED) - tip = "Marker is disabled at current frame"; + tip = TIP_("Marker is disabled at current frame"); else - tip = "Marker is enabled at current frame"; + tip = TIP_("Marker is enabled at current frame"); bt = uiDefIconButBitI(block, TOGN, MARKER_DISABLED, 0, ICON_RESTRICT_VIEW_OFF, 0, 0, 20, 20, &cb->marker_flag, 0, 0, 1, 0, tip); @@ -405,7 +407,7 @@ void uiTemplateMarker(uiLayout *layout, PointerRNA *ptr, const char *propname, P if (track->flag & TRACK_LOCKED) { uiLayoutSetActive(layout, FALSE); block = uiLayoutAbsoluteBlock(layout); - uiDefBut(block, LABEL, 0, "Track is locked", 0, 0, 300, 19, NULL, 0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, IFACE_("Track is locked"), 0, 0, 300, 19, NULL, 0, 0, 0, 0, ""); return; } @@ -434,12 +436,12 @@ void uiTemplateMarker(uiLayout *layout, PointerRNA *ptr, const char *propname, P uiBlockSetNFunc(block, marker_update_cb, cb, NULL); if (cb->marker_flag & MARKER_DISABLED) - tip = "Marker is disabled at current frame"; + tip = TIP_("Marker is disabled at current frame"); else - tip = "Marker is enabled at current frame"; + tip = TIP_("Marker is enabled at current frame"); - uiDefButBitI(block, OPTIONN, MARKER_DISABLED, B_MARKER_FLAG, "Enabled", 10, 190, 145, 19, &cb->marker_flag, - 0, 0, 0, 0, tip); + uiDefButBitI(block, OPTIONN, MARKER_DISABLED, B_MARKER_FLAG, IFACE_("Enabled"), 10, 190, 145, 19, + &cb->marker_flag, 0, 0, 0, 0, tip); col = uiLayoutColumn(layout, TRUE); uiLayoutSetActive(col, (cb->marker_flag & MARKER_DISABLED) == 0); @@ -447,33 +449,34 @@ void uiTemplateMarker(uiLayout *layout, PointerRNA *ptr, const char *propname, P block = uiLayoutAbsoluteBlock(col); uiBlockBeginAlign(block); - uiDefBut(block, LABEL, 0, "Position:", 0, 190, 300, 19, NULL, 0, 0, 0, 0, ""); - uiDefButF(block, NUM, B_MARKER_POS, "X:", 10, 171, 145, 19, &cb->marker_pos[0], - -10 * width, 10.0 * width, step, digits, "X-position of marker at frame in screen coordinates"); - uiDefButF(block, NUM, B_MARKER_POS, "Y:", 165, 171, 145, 19, &cb->marker_pos[1], - -10 * height, 10.0 * height, step, digits, "Y-position of marker at frame in screen coordinates"); + uiDefBut(block, LABEL, 0, IFACE_("Position:"), 0, 190, 300, 19, NULL, 0, 0, 0, 0, ""); + uiDefButF(block, NUM, B_MARKER_POS, IFACE_("X:"), 10, 171, 145, 19, &cb->marker_pos[0], + -10 * width, 10.0 * width, step, digits, TIP_("X-position of marker at frame in screen coordinates")); + uiDefButF(block, NUM, B_MARKER_POS, IFACE_("Y:"), 165, 171, 145, 19, &cb->marker_pos[1], + -10 * height, 10.0 * height, step, digits, + TIP_("Y-position of marker at frame in screen coordinates")); - uiDefBut(block, LABEL, 0, "Offset:", 0, 152, 300, 19, NULL, 0, 0, 0, 0, ""); - uiDefButF(block, NUM, B_MARKER_OFFSET, "X:", 10, 133, 145, 19, &cb->track_offset[0], - -10 * width, 10.0 * width, step, digits, "X-offset to parenting point"); - uiDefButF(block, NUM, B_MARKER_OFFSET, "Y:", 165, 133, 145, 19, &cb->track_offset[1], - -10 * height, 10.0 * height, step, digits, "Y-offset to parenting point"); + uiDefBut(block, LABEL, 0, IFACE_("Offset:"), 0, 152, 300, 19, NULL, 0, 0, 0, 0, ""); + uiDefButF(block, NUM, B_MARKER_OFFSET, IFACE_("X:"), 10, 133, 145, 19, &cb->track_offset[0], + -10 * width, 10.0 * width, step, digits, TIP_("X-offset to parenting point")); + uiDefButF(block, NUM, B_MARKER_OFFSET, IFACE_("Y:"), 165, 133, 145, 19, &cb->track_offset[1], + -10 * height, 10.0 * height, step, digits, TIP_("Y-offset to parenting point")); - uiDefBut(block, LABEL, 0, "Pattern Area:", 0, 114, 300, 19, NULL, 0, 0, 0, 0, ""); - uiDefButF(block, NUM, B_MARKER_PAT_DIM, "Width:", 10, 95, 300, 19, &cb->marker_pat[0], 3.0f, - 10.0 * width, step, digits, "Width of marker's pattern in screen coordinates"); - uiDefButF(block, NUM, B_MARKER_PAT_DIM, "Height:", 10, 76, 300, 19, &cb->marker_pat[1], 3.0f, - 10.0 * height, step, digits, "Height of marker's pattern in screen coordinates"); + uiDefBut(block, LABEL, 0, IFACE_("Pattern Area:"), 0, 114, 300, 19, NULL, 0, 0, 0, 0, ""); + uiDefButF(block, NUM, B_MARKER_PAT_DIM, IFACE_("Width:"), 10, 95, 300, 19, &cb->marker_pat[0], 3.0f, + 10.0 * width, step, digits, TIP_("Width of marker's pattern in screen coordinates")); + uiDefButF(block, NUM, B_MARKER_PAT_DIM, IFACE_("Height:"), 10, 76, 300, 19, &cb->marker_pat[1], 3.0f, + 10.0 * height, step, digits, TIP_("Height of marker's pattern in screen coordinates")); - uiDefBut(block, LABEL, 0, "Search Area:", 0, 57, 300, 19, NULL, 0, 0, 0, 0, ""); - uiDefButF(block, NUM, B_MARKER_SEARCH_POS, "X:", 10, 38, 145, 19, &cb->marker_search_pos[0], - -width, width, step, digits, "X-position of search at frame relative to marker's position"); - uiDefButF(block, NUM, B_MARKER_SEARCH_POS, "Y:", 165, 38, 145, 19, &cb->marker_search_pos[1], - -height, height, step, digits, "X-position of search at frame relative to marker's position"); - uiDefButF(block, NUM, B_MARKER_SEARCH_DIM, "Width:", 10, 19, 300, 19, &cb->marker_search[0], 3.0f, - 10.0 * width, step, digits, "Width of marker's search in screen soordinates"); - uiDefButF(block, NUM, B_MARKER_SEARCH_DIM, "Height:", 10, 0, 300, 19, &cb->marker_search[1], 3.0f, - 10.0 * height, step, digits, "Height of marker's search in screen soordinates"); + uiDefBut(block, LABEL, 0, IFACE_("Search Area:"), 0, 57, 300, 19, NULL, 0, 0, 0, 0, ""); + uiDefButF(block, NUM, B_MARKER_SEARCH_POS, IFACE_("X:"), 10, 38, 145, 19, &cb->marker_search_pos[0], + -width, width, step, digits, TIP_("X-position of search at frame relative to marker's position")); + uiDefButF(block, NUM, B_MARKER_SEARCH_POS, IFACE_("Y:"), 165, 38, 145, 19, &cb->marker_search_pos[1], + -height, height, step, digits, TIP_("Y-position of search at frame relative to marker's position")); + uiDefButF(block, NUM, B_MARKER_SEARCH_DIM, IFACE_("Width:"), 10, 19, 300, 19, &cb->marker_search[0], 3.0f, + 10.0 * width, step, digits, TIP_("Width of marker's search in screen coordinates")); + uiDefButF(block, NUM, B_MARKER_SEARCH_DIM, IFACE_("Height:"), 10, 0, 300, 19, &cb->marker_search[1], 3.0f, + 10.0 * height, step, digits, TIP_("Height of marker's search in screen coordinates")); uiBlockEndAlign(block); } diff --git a/source/blender/editors/space_clip/clip_toolbar.c b/source/blender/editors/space_clip/clip_toolbar.c index ad70abf5732..7543988b5aa 100644 --- a/source/blender/editors/space_clip/clip_toolbar.c +++ b/source/blender/editors/space_clip/clip_toolbar.c @@ -33,11 +33,15 @@ #include "DNA_windowmanager_types.h" +#include "RNA_access.h" + #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BLF_translation.h" + #include "BKE_context.h" #include "BKE_screen.h" @@ -197,16 +201,16 @@ static void clip_panel_operator_redo_header(const bContext *C, Panel *pa) wmOperator *op = WM_operator_last_redo(C); if (op) - BLI_strncpy(pa->drawname, op->type->name, sizeof(pa->drawname)); + BLI_strncpy(pa->drawname, RNA_struct_ui_name(op->type->srna), sizeof(pa->drawname)); else - BLI_strncpy(pa->drawname, "Operator", sizeof(pa->drawname)); + BLI_strncpy(pa->drawname, IFACE_("Operator"), sizeof(pa->drawname)); } static void clip_panel_operator_redo_operator(const bContext *C, Panel *pa, wmOperator *op) { if (op->type->flag & OPTYPE_MACRO) { for (op = op->macro.first; op; op = op->next) { - uiItemL(pa->layout, op->type->name, ICON_NONE); + uiItemL(pa->layout, RNA_struct_ui_name(op->type->srna), ICON_NONE); clip_panel_operator_redo_operator(C, pa, op); } } diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 2d2d29d9eaa..0d1156a837a 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1084,7 +1084,7 @@ void IMAGE_OT_match_movie_length(wmOperatorType *ot) { /* identifiers */ ot->name = "Match Movie Length"; - ot->description = "Set image's users length to the one of this video"; + ot->description = "Set image's user's length to the one of this video"; ot->idname = "IMAGE_OT_match_movie_length"; /* api callbacks */ diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 2140f90664e..612802c46d1 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -3800,7 +3800,8 @@ static void def_cmp_bokehblur(StructRNA *srna) /* duplicated in def_cmp_blur */ prop = RNA_def_property(srna, "use_variable_size", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom1", CMP_NODEFLAG_BLUR_VARIABLE_SIZE); - RNA_def_property_ui_text(prop, "Variable Size", "Support variable blue per-pixel when using an image for size input"); + RNA_def_property_ui_text(prop, "Variable Size", + "Support variable blur per-pixel when using an image for size input"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); #if 0 diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 41dd618caa5..f43541ec283 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1681,18 +1681,26 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar split = uiLayoutSplit(layout, 0.0f, FALSE); col = uiLayoutColumn(split, FALSE); - uiItemL(col, "Links", ICON_NONE); - uiItemStringO(col, IFACE_("Donations"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/blenderorg/blender-foundation/donation-payment"); - uiItemStringO(col, IFACE_("Credits"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/development/credits"); - uiItemStringO(col, IFACE_("Release Log"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/development/release-logs/blender-266"); - uiItemStringO(col, IFACE_("Manual"), ICON_URL, "WM_OT_url_open", "url", "http://wiki.blender.org/index.php/Doc:2.6/Manual"); + uiItemL(col, IFACE_("Links"), ICON_NONE); + uiItemStringO(col, IFACE_("Donations"), ICON_URL, "WM_OT_url_open", "url", + "http://www.blender.org/blenderorg/blender-foundation/donation-payment"); + uiItemStringO(col, IFACE_("Credits"), ICON_URL, "WM_OT_url_open", "url", + "http://www.blender.org/development/credits"); + uiItemStringO(col, IFACE_("Release Log"), ICON_URL, "WM_OT_url_open", "url", + "http://www.blender.org/development/release-logs/blender-266"); + uiItemStringO(col, IFACE_("Manual"), ICON_URL, "WM_OT_url_open", "url", + "http://wiki.blender.org/index.php/Doc:2.6/Manual"); uiItemStringO(col, IFACE_("Blender Website"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org"); - uiItemStringO(col, IFACE_("User Community"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/community/user-community"); + uiItemStringO(col, IFACE_("User Community"), ICON_URL, "WM_OT_url_open", "url", + "http://www.blender.org/community/user-community"); if (strcmp(STRINGIFY(BLENDER_VERSION_CYCLE), "release") == 0) { - BLI_snprintf(url, sizeof(url), "http://www.blender.org/documentation/blender_python_api_%d_%d" STRINGIFY(BLENDER_VERSION_CHAR) "_release", BLENDER_VERSION / 100, BLENDER_VERSION % 100); + BLI_snprintf(url, sizeof(url), "http://www.blender.org/documentation/blender_python_api_%d_%d" + STRINGIFY(BLENDER_VERSION_CHAR) "_release", + BLENDER_VERSION / 100, BLENDER_VERSION % 100); } else { - BLI_snprintf(url, sizeof(url), "http://www.blender.org/documentation/blender_python_api_%d_%d_%d", BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION); + BLI_snprintf(url, sizeof(url), "http://www.blender.org/documentation/blender_python_api_%d_%d_%d", + BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION); } uiItemStringO(col, IFACE_("Python API Reference"), ICON_URL, "WM_OT_url_open", "url", url); uiItemL(col, "", ICON_NONE); From 7cdff04f9f1b792eb99a0128189ad145f3921922 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sun, 17 Feb 2013 14:00:40 +0000 Subject: [PATCH 014/182] Fixes for BMO_error_raise extraction regex, and add hindi to "active" translations. Also enhanced the ugly py ast parsing code, so that it now can handle (up to some extent) "name" function nodes, and add bpy.app.translations.pgettext func familly to extracted ones... This ast py parsing becomes more and more ugly, should probably try to refactor it a bit. :/ --- .../modules/bl_i18n_utils/bl_process_msg.py | 142 +++++++++++------- .../scripts/modules/bl_i18n_utils/settings.py | 4 +- 2 files changed, 89 insertions(+), 57 deletions(-) diff --git a/release/scripts/modules/bl_i18n_utils/bl_process_msg.py b/release/scripts/modules/bl_i18n_utils/bl_process_msg.py index 5381af8d543..006d7170571 100644 --- a/release/scripts/modules/bl_i18n_utils/bl_process_msg.py +++ b/release/scripts/modules/bl_i18n_utils/bl_process_msg.py @@ -435,41 +435,71 @@ def dump_py_messages_from_files(messages, check_ctxt, files): # ------------------------------------------------------------------------- # Gather function names - # so far only 'text' keywords, but we may want others translated later - translate_kw = ("text", ) + # In addition of UI func, also parse pgettext ones... + # Tuples of (module name, (short names, ...)). + pgettext_variants = ( + ("pgettext", ("_",)), + ("pgettext_iface", ("iface_",)), + ("pgettext_tip", ("tip_",)) + ) + pgettext_variants_args = {"msgid": (0, {"msgctxt": 1})} - # key: func_id - # val: [(arg_kw, arg_pos), (arg_kw, arg_pos), ...] + # key: msgid keywords. + # val: tuples of ((keywords,), context_getter_func) to get a context for that msgid. + # Note: order is important, first one wins! + translate_kw = { + "text": ((("text_ctxt",), _ctxt_to_ctxt), + (("operator",), _op_to_ctxt), + ), + "msgid": ((("msgctxt",), _ctxt_to_ctxt), + ), + } + + context_kw_set = {} + for k, ctxts in translate_kw.items(): + s = set() + for c, _ in ctxts: + s |= set(c) + context_kw_set[k] = s + + # {func_id: {msgid: (arg_pos, + # {msgctxt: arg_pos, + # ... + # } + # ), + # ... + # }, + # ... + # } func_translate_args = {} - # as we only have one translate keyword, no need for complex context extraction setup for now... - # And it's already enough complex like that! - # Note: order is important, first one wins! - context_kw = ((("text_ctxt",), _ctxt_to_ctxt), - (("operator",), _op_to_ctxt), - ) - context_kw_set = set() - for c, _ in context_kw: - context_kw_set |= set(c) - - # Like func_translate_args. - func_context_args = {} + # First, functions from UILayout + # First loop is for msgid args, second one is for msgctxt args. + for func_id, func in bpy.types.UILayout.bl_rna.functions.items(): + # check it has one or more arguments as defined in translate_kw + for arg_pos, (arg_kw, arg) in enumerate(func.parameters.items()): + if ((arg_kw in translate_kw) and (not arg.is_output) and (arg.type == 'STRING')): + func_translate_args.setdefault(func_id, {})[arg_kw] = (arg_pos, {}) + for func_id, func in bpy.types.UILayout.bl_rna.functions.items(): + if func_id not in func_translate_args: + continue + for arg_pos, (arg_kw, arg) in enumerate(func.parameters.items()): + if (not arg.is_output) and (arg.type == 'STRING'): + for msgid, msgctxts in context_kw_set.items(): + if arg_kw in msgctxts: + func_translate_args[func_id][msgid][1][arg_kw] = arg_pos + # We manually add funcs from bpy.app.translations + for func_id, func_ids in pgettext_variants: + func_translate_args[func_id] = pgettext_variants_args + for func_id in func_ids: + func_translate_args[func_id] = pgettext_variants_args + #print(func_translate_args) # Break recursive nodes look up on some kind of nodes. # E.g. we don’t want to get strings inside subscripts (blah["foo"])! - stopper_nodes = {ast.Subscript, } + stopper_nodes = {ast.Subscript} # Consider strings separate: ("a" if test else "b") - separate_nodes = {ast.IfExp, } - - # For now only consider functions from UILayout... - for func_id, func in bpy.types.UILayout.bl_rna.functions.items(): - # check it has one or more arguments as defined in translate_kw - for (arg_pos, (arg_kw, arg)) in enumerate(func.parameters.items()): - if ((arg_kw in translate_kw) and (not arg.is_output) and (arg.type == 'STRING')): - func_translate_args.setdefault(func_id, []).append((arg_kw, arg_pos)) - elif ((arg_kw in context_kw_set) and (not arg.is_output) and (arg.type == 'STRING')): - func_context_args.setdefault(func_id, []).append((arg_kw, arg_pos)) - #print(func_context_args) + separate_nodes = {ast.IfExp} check_ctxt_py = None if check_ctxt: @@ -489,40 +519,42 @@ def dump_py_messages_from_files(messages, check_ctxt, files): # print("found function at") # print("%s:%d" % (fp, node.lineno)) - # lambda's + # We can't skip such situations! from blah import foo\nfoo("bar") would also be an ast.Name func! if type(node.func) == ast.Name: + func_id = node.func.id + elif hasattr(node.func, "attr"): + func_id = node.func.attr + # Ugly things like getattr(self, con.type)(context, box, con) + else: continue - # getattr(self, con.type)(context, box, con) - if not hasattr(node.func, "attr"): - continue + func_args = func_translate_args.get(func_id, {}) - # First try to get i18n context. - context_args = func_context_args.get(node.func.attr, ()) - context = "" - context_elements = {} - for arg_kw, arg_pos in context_args: - if arg_pos < len(node.args): - context_elements[arg_kw] = node.args[arg_pos] - else: - for kw in node.keywords: - if kw.arg == arg_kw: - context_elements[arg_kw] = kw.value + # First try to get i18n contexts, for every possible msgid id. + contexts = dict.fromkeys(func_args.keys(), "") + for msgid, (_, context_args) in func_args.items(): + context_elements = {} + for arg_kw, arg_pos in context_args.items(): + if arg_pos < len(node.args): + context_elements[arg_kw] = node.args[arg_pos] + else: + for kw in node.keywords: + if kw.arg == arg_kw: + context_elements[arg_kw] = kw.value + break + #print(context_elements) + for kws, proc in translate_kw[msgid]: + if set(kws) <= context_elements.keys(): + args = tuple(context_elements[k] for k in kws) + #print("running ", proc, " with ", args) + ctxt = proc(*args) + if ctxt: + contexts[msgid] = ctxt break - #print(context_elements) - for kws, proc in context_kw: - if set(kws) <= context_elements.keys(): - args = tuple(context_elements[k] for k in kws) - #print("running ", proc, " with ", args) - ctxt = proc(*args) - if ctxt: - context = ctxt - break - translate_args = func_translate_args.get(node.func.attr, ()) #print(translate_args) # do nothing if not found - for arg_kw, arg_pos in translate_args: + for arg_kw, (arg_pos, _) in func_args.items(): estr_lst = [(None, ())] if arg_pos < len(node.args): estr_lst = extract_strings_split(node.args[arg_pos]) @@ -535,7 +567,7 @@ def dump_py_messages_from_files(messages, check_ctxt, files): #print(estr, nds) for estr, nds in estr_lst: if estr: - key = (context, estr) + key = (contexts[arg_kw], estr) if nds: msgsrc = ["{}:{}".format(fp_rel, sorted({nd.lineno for nd in nds})[0])] else: diff --git a/release/scripts/modules/bl_i18n_utils/settings.py b/release/scripts/modules/bl_i18n_utils/settings.py index 01bc925cedd..232f54f5140 100644 --- a/release/scripts/modules/bl_i18n_utils/settings.py +++ b/release/scripts/modules/bl_i18n_utils/settings.py @@ -94,7 +94,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', 'hi', 'ne', 'pl', 'ro', 'uz', 'uz@cyrillic'} +IMPORT_LANGUAGES_SKIP = {'am', 'bg', 'fi', 'el', 'et', 'ne', 'pl', 'ro', 'uz', 'uz@cyrillic'} # The comment prefix used in generated messages.txt file. MSG_COMMENT_PREFIX = "#~ " @@ -229,7 +229,7 @@ PYGETTEXT_KEYWORDS = (() + tuple(("{}\\((?:[^\"',]+,){{1,2}}\\s*" + _msg_re + r"\s*(?:\)|,)").format(it) for it in ("BKE_report", "BKE_reportf", "BKE_reports_prepend", "BKE_reports_prependf")) + - tuple(("{}\\((?:[^\"',]+,){{3}}\\s*" + _msg_re + r"\s*,").format(it) + tuple(("{}\\((?:[^\"',]+,){{3}}\\s*" + _msg_re + r"\s*\)").format(it) for it in ("BMO_error_raise",)) + tuple(("{}\\((?:[^\"',]+,)\\s*" + _msg_re + r"\s*(?:\)|,)").format(it) From 4529459a07082e714b7f9c222b9a8003939a145b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 17 Feb 2013 14:38:35 +0000 Subject: [PATCH 015/182] remove stipple from console selection drawing. --- source/blender/editors/space_info/textview.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c index fc0a7b3b883..14a0aee09bd 100644 --- a/source/blender/editors/space_info/textview.c +++ b/source/blender/editors/space_info/textview.c @@ -74,15 +74,12 @@ static void console_draw_sel(const int sel[2], const int xy[2], const int str_le const int sta = max_ii(sel[0], 0); const int end = min_ii(sel[1], str_len_draw); - glEnable(GL_POLYGON_STIPPLE); - glPolygonStipple(stipple_halftone); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor4ub(255, 255, 255, 48); glRecti(xy[0] + (cwidth * sta), xy[1] - 2 + lheight, xy[0] + (cwidth * end), xy[1] - 2); - glDisable(GL_POLYGON_STIPPLE); glDisable(GL_BLEND); } } From 0aabcaca2844ce1bc0f702c20c60a7cef53eef44 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sun, 17 Feb 2013 14:53:29 +0000 Subject: [PATCH 016/182] Fix #34285: sculpt/paint radial control F key operators did not adjust brush size to retina pixel size correctly. --- source/blender/windowmanager/intern/wm_operators.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index f43541ec283..9939e6b69ba 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -3391,6 +3391,11 @@ static void radial_control_paint_cursor(bContext *C, int x, int y, void *customd break; } + /* adjust for DPI, like BKE_brush_size_get */ + r1 *= U.pixelsize; + r2 *= U.pixelsize; + tex_radius *= U.pixelsize; + /* Keep cursor in the original place */ x = rc->initial_mouse[0] - ar->winrct.xmin; y = rc->initial_mouse[1] - ar->winrct.ymin; From 3de87ebf649fbe4adddc281e1b6fa5473508e6b8 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sun, 17 Feb 2013 15:04:56 +0000 Subject: [PATCH 017/182] Minor fix... --- 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 f2d777d22f1..6adf3213b56 100644 --- a/release/scripts/modules/bl_i18n_utils/spell_check_utils.py +++ b/release/scripts/modules/bl_i18n_utils/spell_check_utils.py @@ -220,7 +220,7 @@ dict_uimsgs = { "grless", "http", "init", - "kbit", + "kbit", "kb", "lensdist", "loc", "rot", "pos", "lorem", From 85b6bbe6cd0dd7cc7b9bb403c42aaa6399dea710 Mon Sep 17 00:00:00 2001 From: Sergej Reich Date: Sun, 17 Feb 2013 18:13:22 +0000 Subject: [PATCH 018/182] ribidbody: Fix setting "Bake to Keyframes" start frame above 2 Simulation needs to run from the beginning to work properly. --- release/scripts/startup/bl_operators/rigidbody.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/release/scripts/startup/bl_operators/rigidbody.py b/release/scripts/startup/bl_operators/rigidbody.py index bb3a9a6330f..652ad4bf784 100644 --- a/release/scripts/startup/bl_operators/rigidbody.py +++ b/release/scripts/startup/bl_operators/rigidbody.py @@ -120,7 +120,8 @@ class BakeToKeyframes(Operator): if objects: # store transformation data - for f in list(range(self.frame_start, self.frame_end + 1)): + # need to start at scene start frame so simulation is run from the beginning + for f in list(range(scene.frame_start, self.frame_end + 1)): scene.frame_set(f) if f in frames: mat = {} From ee64cbaf3916002845af17e153855ca125f67bd7 Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Sun, 17 Feb 2013 18:33:10 +0000 Subject: [PATCH 019/182] fix #34284 Collada: update problem for vertex weights directly after import. --- source/blender/collada/ArmatureImporter.cpp | 75 +++++++++++++-------- source/blender/collada/DocumentImporter.cpp | 19 +++--- 2 files changed, 58 insertions(+), 36 deletions(-) diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp index fefad7dd8ec..c270a1e6b20 100644 --- a/source/blender/collada/ArmatureImporter.cpp +++ b/source/blender/collada/ArmatureImporter.cpp @@ -415,10 +415,23 @@ void ArmatureImporter::create_armature_bones(SkinInfo& skin) break; } - if (shared) + if (!shared && this->joint_parent_map.size() > 0) { + // All armatures have been created while creating the Node tree. + // The Collada exporter currently does not create a + // strict relationship between geometries and armatures + // So when we reimport a Blender collada file, then we have + // to guess what is meant. + // XXX This is not safe when we have more than one armatures + // in the import. + shared = this->joint_parent_map.begin()->second; + } + + if (shared) { ob_arm = skin.set_armature(shared); - else + } + else { ob_arm = skin.create_armature(scene); //once for every armature + } // enter armature edit mode ED_armature_to_edit(ob_arm); @@ -659,38 +672,44 @@ void ArmatureImporter::make_shape_keys() //Prereq: all the geometries must be imported and mesh objects must be made Object *source_ob = this->mesh_importer->get_object_by_geom_uid((*mc)->getSource()); - Mesh *source_me = (Mesh*) source_ob->data; - //insert key to source mesh - Key *key = source_me->key = BKE_key_add((ID *)source_me); - key->type = KEY_RELATIVE; - KeyBlock *kb; - - //insert basis key - kb = BKE_keyblock_add_ctime(key, "Basis", FALSE); - BKE_key_convert_from_mesh(source_me, kb); + if (source_ob) { - //insert other shape keys - for (int i = 0 ; i < morphTargetIds.getCount() ; i++ ) { - //better to have a seperate map of morph objects, - //This'll do for now since only mesh morphing is imported - - Mesh *me = this->mesh_importer->get_mesh_by_geom_uid(morphTargetIds[i]); + Mesh *source_me = (Mesh*) source_ob->data; + //insert key to source mesh + Key *key = source_me->key = BKE_key_add((ID *)source_me); + key->type = KEY_RELATIVE; + KeyBlock *kb; - if (me) { - me->key = key; - std::string morph_name = *this->mesh_importer->get_geometry_name(me->id.name); + //insert basis key + kb = BKE_keyblock_add_ctime(key, "Basis", FALSE); + BKE_key_convert_from_mesh(source_me, kb); - kb = BKE_keyblock_add_ctime(key, morph_name.c_str(), FALSE); - BKE_key_convert_from_mesh(me, kb); + //insert other shape keys + for (int i = 0 ; i < morphTargetIds.getCount() ; i++ ) { + //better to have a seperate map of morph objects, + //This'll do for now since only mesh morphing is imported + + Mesh *me = this->mesh_importer->get_mesh_by_geom_uid(morphTargetIds[i]); - //apply weights - weight = morphWeights.getFloatValues()->getData()[i]; - kb->curval = weight; - } - else { - fprintf(stderr, "Morph target geometry not found.\n"); + if (me) { + me->key = key; + std::string morph_name = *this->mesh_importer->get_geometry_name(me->id.name); + + kb = BKE_keyblock_add_ctime(key, morph_name.c_str(), FALSE); + BKE_key_convert_from_mesh(me, kb); + + //apply weights + weight = morphWeights.getFloatValues()->getData()[i]; + kb->curval = weight; + } + else { + fprintf(stderr, "Morph target geometry not found.\n"); + } } } + else { + fprintf(stderr, "Morph target object not found.\n"); + } } } diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index 8af4d0652d9..b1103d78394 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -180,14 +180,16 @@ void DocumentImporter::finish() { if (mImportStage != General) return; - + + Main *bmain = CTX_data_main(mContext); + // TODO: create a new scene except the selected - use current blender scene for it + Scene *sce = CTX_data_scene(mContext); + /** TODO Break up and put into 2-pass parsing of DAE */ std::vector::iterator it; for (it = vscenes.begin(); it != vscenes.end(); it++) { PointerRNA sceneptr, unit_settings; PropertyRNA *system, *scale; - // TODO: create a new scene except the selected - use current blender scene for it - Scene *sce = CTX_data_scene(mContext); // for scene unit settings: system, scale_length @@ -228,7 +230,6 @@ void DocumentImporter::finish() } // update scene - Main *bmain = CTX_data_main(mContext); DAG_scene_sort(bmain, sce); DAG_ids_flush_update(bmain, 0); WM_event_add_notifier(mContext, NC_OBJECT | ND_TRANSFORM, NULL); @@ -241,6 +242,8 @@ void DocumentImporter::finish() armature_importer.set_tags_map(this->uid_tags_map); armature_importer.make_armatures(mContext); armature_importer.make_shape_keys(); + DAG_scene_sort(bmain, sce); + DAG_ids_flush_update(bmain, 0); #if 0 armature_importer.fix_animation(); @@ -273,8 +276,8 @@ void DocumentImporter::finish() } libnode_ob.clear(); - DAG_scene_sort(CTX_data_main(mContext), sce); - DAG_ids_flush_update(CTX_data_main(mContext), 0); + DAG_scene_sort(bmain, sce); + DAG_ids_flush_update(bmain, 0); } } @@ -541,13 +544,13 @@ std::vector *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA if ( (geom_done + camera_done + lamp_done + controller_done + inst_done) < 1) { //Check if Object is armature, by checking if immediate child is a JOINT node. if (is_armature(node)) { - ob = bc_add_object(sce, OB_ARMATURE, NULL); + ob = bc_add_object(sce, OB_ARMATURE, name.c_str()); } else { ob = bc_add_object(sce, OB_EMPTY, NULL); } - objects_done->push_back(ob); + } // XXX: if there're multiple instances, only one is stored From 029686a2fd7819ef0047dc4dc566d4f08d647624 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Sun, 17 Feb 2013 18:46:50 +0000 Subject: [PATCH 020/182] Bug fix #34281 The RNA path interpretor code was using a function to get the portion between quotes, this function was not even checking if there *are* quotes at all! Causing bad memory allocs or crashes. --- source/blender/blenlib/intern/string.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index 28fdf7b61db..3500f3f1805 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -199,12 +199,15 @@ char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict /* get the starting point (i.e. where prefix starts, and add prefixLen+1 to it to get be after the first " */ startMatch = strstr(str, prefix) + prefixLen + 1; - - /* get the end point (i.e. where the next occurance of " is after the starting point) */ - endMatch = strchr(startMatch, '"'); /* " NOTE: this comment here is just so that my text editor still shows the functions ok... */ - - /* return the slice indicated */ - return BLI_strdupn(startMatch, (size_t)(endMatch - startMatch)); + if (startMatch) { + /* get the end point (i.e. where the next occurance of " is after the starting point) */ + endMatch = strchr(startMatch, '"'); /* " NOTE: this comment here is just so that my text editor still shows the functions ok... */ + + if (endMatch) + /* return the slice indicated */ + return BLI_strdupn(startMatch, (size_t)(endMatch - startMatch)); + } + return BLI_strdupn("", 0); } /* Replaces all occurrences of oldText with newText in str, returning a new string that doesn't From 3e0725854c091c48695bf89da66e927aad611574 Mon Sep 17 00:00:00 2001 From: Sergej Reich Date: Sun, 17 Feb 2013 19:38:08 +0000 Subject: [PATCH 021/182] rigidbody: Fix regression in background scene fix Since BKE_object_where_is_calc() might be called outside of scene_update_tagged_recursive(), we need to fall back to the scene's rigid body world. --- source/blender/blenkernel/intern/object.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index b810aa89257..58b47398a7d 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -2145,6 +2145,8 @@ void BKE_object_where_is_calc_time_ex(Scene *scene, Object *ob, float ctime, BKE_object_to_mat4(ob, ob->obmat); } + /* try to fall back to the scene rigid body world if none given */ + rbw = rbw ? rbw : scene->rigidbody_world; /* read values pushed into RBO from sim/cache... */ BKE_rigidbody_sync_transforms(rbw, ob, ctime); From aefa6261c324b8117c25041c285b6cb1eaab31f8 Mon Sep 17 00:00:00 2001 From: Peter Schlaile Date: Sun, 17 Feb 2013 21:44:13 +0000 Subject: [PATCH 022/182] == Sequencer == This fixes a bug in sequencer cut tool: * if you cut two strips of the same name class (MVI_XXXX.MOV and MVI_XXXX.001) the two new generated strips will end up with the same name. (easy test case: add a MOV file with it's accompanying audio track to the timeline and then cut both strips at once into two pieces) * visible problem: your animation data will get messed up on the way, since the animation system doesn't know, which strip it should assign the animation. Problem was caused by generating a new list of sequences within the cut_seq_list() function: Since dupli_seq() can't see the members of the new list of sequences, it won't be able to assign unique names in all cases. --- .../editors/space_sequencer/sequencer_edit.c | 50 ++++++++++++------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 97943f7e6ac..cec9373ebd7 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -817,40 +817,56 @@ static Sequence *cut_seq_soft(Scene *scene, Sequence *seq, int cutframe) /* like duplicate, but only duplicate and cut overlapping strips, - * strips to the left of the cutframe are ignored and strips to the right are moved into the new list */ -static int cut_seq_list(Scene *scene, ListBase *old, ListBase *new, int cutframe, + * strips to the left of the cutframe are ignored and strips to the right + * are moved to the end of slist + * we have to work on the same slist (not using a seperate list), since + * otherwise dupli_seq can't check for duplicate names properly and + * may generate strips with the same name (which will mess up animdata) + */ + +static int cut_seq_list(Scene *scene, ListBase *slist, int cutframe, Sequence * (*cut_seq)(Scene *, Sequence *, int)) { int did_something = FALSE; Sequence *seq, *seq_next_iter; - seq = old->first; - - while (seq) { - seq_next_iter = seq->next; /* we need this because we may remove seq */ - + for (seq = slist->first; seq; seq = seq->next) { seq->tmp = NULL; + } + + seq = slist->first; + + while (seq && !seq->tmp) { + seq_next_iter = seq->next; /* we need this because we may remove seq */ + /* only handle strips not marked as new */ if (seq->flag & SELECT) { if (cutframe > seq->startdisp && cutframe < seq->enddisp) { Sequence *seqn = cut_seq(scene, seq, cutframe); if (seqn) { - BLI_addtail(new, seqn); + BLI_addtail(slist, seqn); + seqn->tmp = seq; /* mark as new */ + did_something = TRUE; } - did_something = TRUE; } else if (seq->enddisp <= cutframe) { /* do nothing */ } else if (seq->startdisp >= cutframe) { - /* move into new list */ - BLI_remlink(old, seq); - BLI_addtail(new, seq); + /* move to tail and mark as new */ + BLI_remlink(slist, seq); + BLI_addtail(slist, seq); + seq->tmp = seq; } } seq = seq_next_iter; } + + for (; seq; seq = seq->next) { + seq->tmp = NULL; + } + return did_something; } @@ -1488,25 +1504,21 @@ static int sequencer_cut_exec(bContext *C, wmOperator *op) Editing *ed = BKE_sequencer_editing_get(scene, FALSE); int cut_side, cut_hard, cut_frame; - ListBase newlist; int changed; cut_frame = RNA_int_get(op->ptr, "frame"); cut_hard = RNA_enum_get(op->ptr, "type"); cut_side = RNA_enum_get(op->ptr, "side"); - newlist.first = newlist.last = NULL; - if (cut_hard == SEQ_CUT_HARD) { - changed = cut_seq_list(scene, ed->seqbasep, &newlist, cut_frame, cut_seq_hard); + changed = cut_seq_list(scene, ed->seqbasep, cut_frame, cut_seq_hard); } else { - changed = cut_seq_list(scene, ed->seqbasep, &newlist, cut_frame, cut_seq_soft); + changed = cut_seq_list(scene, ed->seqbasep, cut_frame, cut_seq_soft); } - if (newlist.first) { /* got new strips ? */ + if (changed) { /* got new strips ? */ Sequence *seq; - BLI_movelisttolist(ed->seqbasep, &newlist); if (cut_side != SEQ_SIDE_BOTH) { SEQP_BEGIN (ed, seq) From 42a81550f9b1ab4af7945580922c897425becf7f Mon Sep 17 00:00:00 2001 From: Peter Schlaile Date: Sun, 17 Feb 2013 22:13:00 +0000 Subject: [PATCH 023/182] == Sequencer == Made my last fix a little bit faster and more elegant by not playing around with seq->tmp (only reseting it to NULL, like the old code). --- .../editors/space_sequencer/sequencer_edit.c | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index cec9373ebd7..ab7a2f38744 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -827,18 +827,14 @@ static Sequence *cut_seq_soft(Scene *scene, Sequence *seq, int cutframe) static int cut_seq_list(Scene *scene, ListBase *slist, int cutframe, Sequence * (*cut_seq)(Scene *, Sequence *, int)) { - int did_something = FALSE; Sequence *seq, *seq_next_iter; - - for (seq = slist->first; seq; seq = seq->next) { - seq->tmp = NULL; - } + Sequence *seq_first_new = NULL; seq = slist->first; - while (seq && !seq->tmp) { + while (seq && seq != seq_first_new) { seq_next_iter = seq->next; /* we need this because we may remove seq */ - /* only handle strips not marked as new */ + seq->tmp = NULL; if (seq->flag & SELECT) { if (cutframe > seq->startdisp && cutframe < seq->enddisp) @@ -846,28 +842,24 @@ static int cut_seq_list(Scene *scene, ListBase *slist, int cutframe, Sequence *seqn = cut_seq(scene, seq, cutframe); if (seqn) { BLI_addtail(slist, seqn); - seqn->tmp = seq; /* mark as new */ - did_something = TRUE; + seq_first_new = seq_first_new ?: seqn; } } else if (seq->enddisp <= cutframe) { /* do nothing */ } else if (seq->startdisp >= cutframe) { - /* move to tail and mark as new */ + /* move to tail */ BLI_remlink(slist, seq); BLI_addtail(slist, seq); - seq->tmp = seq; + + seq_first_new = seq_first_new ?: seq; } } seq = seq_next_iter; } - for (; seq; seq = seq->next) { - seq->tmp = NULL; - } - - return did_something; + return (seq_first_new != NULL); } static int insert_gap(Scene *scene, int gap, int cfra) From d45612aa412798d5529027afd068adc79b8465f1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 18 Feb 2013 02:36:36 +0000 Subject: [PATCH 024/182] fix [#34279] Python console: Selected region is not highlighted when using white background color --- .../presets/interface_theme/back_to_black.xml | 3 +- .../presets/interface_theme/blender_24x.xml | 3 +- .../presets/interface_theme/elsyiun.xml | 3 +- .../presets/interface_theme/hexagon.xml | 3 +- .../interface_theme/ubuntu_ambiance.xml | 3 +- .../blenlib/intern/math_color_inline.c | 3 +- source/blender/editors/include/UI_resources.h | 1 + source/blender/editors/interface/resources.c | 10 +++++++ .../editors/space_console/console_draw.c | 5 ++++ source/blender/editors/space_info/info_draw.c | 4 ++- source/blender/editors/space_info/textview.c | 28 +++++++++++++------ source/blender/editors/space_info/textview.h | 1 + source/blender/makesdna/DNA_userdef_types.h | 2 +- source/blender/makesrna/intern/rna_userdef.c | 7 +++++ 14 files changed, 59 insertions(+), 17 deletions(-) diff --git a/release/scripts/presets/interface_theme/back_to_black.xml b/release/scripts/presets/interface_theme/back_to_black.xml index bb625c6452c..05216841cbd 100644 --- a/release/scripts/presets/interface_theme/back_to_black.xml +++ b/release/scripts/presets/interface_theme/back_to_black.xml @@ -800,7 +800,8 @@ line_input="#cecece" line_info="#00aa00" line_error="#dc6060" - cursor="#dc6060"> + cursor="#dc6060" + select="#ffffff30"> + cursor="#dc6060" + select="#c6777799"> + cursor="#dc6060" + select="#4e4e8f80"> + cursor="#dc6060" + select="#ffffff30"> + cursor="#f47421" + select="#641f4480"> console_error; break; case TH_CONSOLE_CURSOR: cp = ts->console_cursor; break; + case TH_CONSOLE_SELECT: + cp = ts->console_select; break; case TH_HANDLE_VERTEX: cp = ts->handle_vertex; @@ -937,6 +939,7 @@ void ui_theme_init_default(void) rgba_char_args_set(btheme->tconsole.console_info, 0, 170, 0, 255); rgba_char_args_set(btheme->tconsole.console_error, 220, 96, 96, 255); rgba_char_args_set(btheme->tconsole.console_cursor, 220, 96, 96, 255); + rgba_char_args_set(btheme->tconsole.console_select, 255, 255, 255, 48); /* space time */ btheme->ttime = btheme->tv3d; @@ -2135,6 +2138,13 @@ void init_userdef_do_versions(void) } } + if (U.versionfile < 265 || (U.versionfile == 265 && U.subversionfile < 11)) { + bTheme *btheme; + for (btheme = U.themes.first; btheme; btheme = btheme->next) { + rgba_char_args_test_set(btheme->tconsole.console_select, 255, 255, 255, 48); + } + } + /* NOTE!! from now on use U.versionfile and U.subversionfile */ diff --git a/source/blender/editors/space_console/console_draw.c b/source/blender/editors/space_console/console_draw.c index c195cb39157..73747239255 100644 --- a/source/blender/editors/space_console/console_draw.c +++ b/source/blender/editors/space_console/console_draw.c @@ -193,6 +193,10 @@ static int console_textview_line_color(struct TextViewContext *tvc, unsigned cha return TVC_LINE_FG; } +static void console_textview_const_colors(TextViewContext *UNUSED(tvc), unsigned char bg_sel[4]) +{ + UI_GetThemeColor4ubv(TH_CONSOLE_SELECT, bg_sel); +} static int console_textview_main__internal(struct SpaceConsole *sc, ARegion *ar, int draw, int mval[2], void **mouse_pick, int *pos_pick) @@ -210,6 +214,7 @@ static int console_textview_main__internal(struct SpaceConsole *sc, ARegion *ar, tvc.step = console_textview_step; tvc.line_get = console_textview_line_get; tvc.line_color = console_textview_line_color; + tvc.const_colors = console_textview_const_colors; tvc.arg1 = sc; tvc.arg2 = NULL; diff --git a/source/blender/editors/space_info/info_draw.c b/source/blender/editors/space_info/info_draw.c index 54afc9a0849..a748c303b5d 100644 --- a/source/blender/editors/space_info/info_draw.c +++ b/source/blender/editors/space_info/info_draw.c @@ -251,7 +251,8 @@ static int report_textview_line_color(struct TextViewContext *tvc, unsigned char #undef USE_INFO_NEWLINE -static int info_textview_main__internal(struct SpaceInfo *sinfo, ARegion *ar, ReportList *reports, int draw, int mval[2], void **mouse_pick, int *pos_pick) +static int info_textview_main__internal(struct SpaceInfo *sinfo, ARegion *ar, ReportList *reports, + int draw, int mval[2], void **mouse_pick, int *pos_pick) { int ret = 0; @@ -264,6 +265,7 @@ static int info_textview_main__internal(struct SpaceInfo *sinfo, ARegion *ar, Re tvc.step = report_textview_step; tvc.line_get = report_textview_line_get; tvc.line_color = report_textview_line_color; + tvc.const_colors = NULL; tvc.arg1 = sinfo; tvc.arg2 = reports; diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c index 14a0aee09bd..66f4904c340 100644 --- a/source/blender/editors/space_info/textview.c +++ b/source/blender/editors/space_info/textview.c @@ -68,7 +68,8 @@ BLI_INLINE void console_step_sel(ConsoleDrawContext *cdc, const int step) cdc->sel[1] += step; } -static void console_draw_sel(const int sel[2], const int xy[2], const int str_len_draw, int cwidth, int lheight) +static void console_draw_sel(const int sel[2], const int xy[2], const int str_len_draw, int cwidth, int lheight, + const unsigned char bg_sel[4]) { if (sel[0] <= str_len_draw && sel[1] >= 0) { const int sta = max_ii(sel[0], 0); @@ -76,7 +77,7 @@ static void console_draw_sel(const int sel[2], const int xy[2], const int str_le glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glColor4ub(255, 255, 255, 48); + glColor4ubv(bg_sel); glRecti(xy[0] + (cwidth * sta), xy[1] - 2 + lheight, xy[0] + (cwidth * end), xy[1] - 2); @@ -84,12 +85,11 @@ static void console_draw_sel(const int sel[2], const int xy[2], const int str_le } } - /* return 0 if the last line is off the screen * should be able to use this for any string type */ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, const int str_len, - const unsigned char *fg, const unsigned char *bg) + const unsigned char fg[3], const unsigned char bg[3], const unsigned char bg_sel[4]) { int rct_ofs = cdc->lheight / 4; int tot_lines = (str_len / cdc->console_width) + 1; /* total number of lines for wrapping */ @@ -105,7 +105,8 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, const i /* wrap */ if (str_len > cdc->console_width) - ofs += (cdc->console_width * ((int)((((float)(y_next - cdc->mval[1]) / (float)(y_next - cdc->xy[1])) * tot_lines)))); + ofs += cdc->console_width * ((int)((((float)(y_next - cdc->mval[1]) / + (float)(y_next - cdc->xy[1])) * tot_lines))); CLAMP(ofs, 0, str_len); *cdc->pos_pick += str_len - ofs; @@ -155,7 +156,7 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, const i if (cdc->sel[0] != cdc->sel[1]) { console_step_sel(cdc, -initial_offset); // glColor4ub(255, 0, 0, 96); // debug - console_draw_sel(cdc->sel, cdc->xy, str_len % cdc->console_width, cdc->cwidth, cdc->lheight); + console_draw_sel(cdc->sel, cdc->xy, str_len % cdc->console_width, cdc->cwidth, cdc->lheight, bg_sel); console_step_sel(cdc, cdc->console_width); glColor3ubv(fg); } @@ -170,7 +171,7 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, const i if (cdc->sel[0] != cdc->sel[1]) { // glColor4ub(0, 255, 0, 96); // debug - console_draw_sel(cdc->sel, cdc->xy, cdc->console_width, cdc->cwidth, cdc->lheight); + console_draw_sel(cdc->sel, cdc->xy, cdc->console_width, cdc->cwidth, cdc->lheight, bg_sel); console_step_sel(cdc, cdc->console_width); glColor3ubv(fg); } @@ -204,7 +205,7 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, const i isel[1] = str_len - cdc->sel[0]; // glColor4ub(255, 255, 0, 96); // debug - console_draw_sel(isel, cdc->xy, str_len, cdc->cwidth, cdc->lheight); + console_draw_sel(isel, cdc->xy, str_len, cdc->cwidth, cdc->lheight, bg_sel); console_step_sel(cdc, -(str_len + 1)); } @@ -266,6 +267,11 @@ int textview_draw(TextViewContext *tvc, const int draw, int mval[2], void **mous } if (tvc->begin(tvc)) { + unsigned char bg_sel[4] = {0}; + + if (draw && tvc->const_colors) { + tvc->const_colors(tvc, bg_sel); + } do { const char *ext_line; @@ -279,7 +285,11 @@ int textview_draw(TextViewContext *tvc, const int draw, int mval[2], void **mous tvc->line_get(tvc, &ext_line, &ext_len); - if (!console_draw_string(&cdc, ext_line, ext_len, (color_flag & TVC_LINE_FG) ? fg : NULL, (color_flag & TVC_LINE_BG) ? bg : NULL)) { + if (!console_draw_string(&cdc, ext_line, ext_len, + (color_flag & TVC_LINE_FG) ? fg : NULL, + (color_flag & TVC_LINE_BG) ? bg : NULL, + bg_sel)) + { /* when drawing, if we pass v2d->cur.ymax, then quit */ if (draw) { break; /* past the y limits */ diff --git a/source/blender/editors/space_info/textview.h b/source/blender/editors/space_info/textview.h index d0fab880dc3..653c9b83a50 100644 --- a/source/blender/editors/space_info/textview.h +++ b/source/blender/editors/space_info/textview.h @@ -46,6 +46,7 @@ typedef struct TextViewContext { int (*step)(struct TextViewContext *tvc); int (*line_get)(struct TextViewContext *tvc, const char **, int *); int (*line_color)(struct TextViewContext *tvc, unsigned char fg[3], unsigned char bg[3]); + void (*const_colors)(struct TextViewContext *tvc, unsigned char bg_sel[4]); /* constant theme colors */ void *iter; int iter_index; int iter_char; /* char intex, used for multi-line report display */ diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index cc53caa4c20..26b33783535 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -250,7 +250,7 @@ typedef struct ThemeSpace { char ds_channel[4], ds_subchannel[4]; /* dopesheet */ char console_output[4], console_input[4], console_info[4], console_error[4]; - char console_cursor[4]; + char console_cursor[4], console_select[4], pad1[4]; char vertex_size, outline_width, facedot_size; char noodle_curving; diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 2b2f1a2469b..9d5a0024c0a 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -1689,6 +1689,13 @@ static void rna_def_userdef_theme_space_console(BlenderRNA *brna) RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Cursor", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "select", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "console_select"); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Selection", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + } static void rna_def_userdef_theme_space_info(BlenderRNA *brna) From a0ede5be1de91beaf4bc23d4aea201a35845c6c0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 18 Feb 2013 03:36:10 +0000 Subject: [PATCH 025/182] resolve build error in MSVC, was using a GNU C extension for ternary conditional. --- source/blender/editors/space_sequencer/sequencer_edit.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index ab7a2f38744..7be2d51a3c0 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -842,7 +842,9 @@ static int cut_seq_list(Scene *scene, ListBase *slist, int cutframe, Sequence *seqn = cut_seq(scene, seq, cutframe); if (seqn) { BLI_addtail(slist, seqn); - seq_first_new = seq_first_new ?: seqn; + if (seq_first_new == NULL) { + seq_first_new = seqn; + } } } else if (seq->enddisp <= cutframe) { @@ -853,7 +855,9 @@ static int cut_seq_list(Scene *scene, ListBase *slist, int cutframe, BLI_remlink(slist, seq); BLI_addtail(slist, seq); - seq_first_new = seq_first_new ?: seq; + if (seq_first_new == NULL) { + seq_first_new = seq; + } } } seq = seq_next_iter; From 5cc377022b810cb2ab291a0064e5749b976e185a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 18 Feb 2013 10:12:44 +0000 Subject: [PATCH 026/182] Correction to r54600 Calculate dependent area based on distortion model rather than using 15% of image resolution for this. Some assumptions here: - We're assuming real-life camera calibration is used here - Maximal undistortion delta would be achieved on frame boundary - Distortion fully goes inside frame This makes it possible to approximate margin for distortion by checking undistortion delta across frame boundary and use it for dependent area of interest. We do not use any formula-based equation here because we're likely support other distortion models and in that case it'll be stupid to try detecting formula here. --- source/blender/blenkernel/BKE_tracking.h | 3 + source/blender/blenkernel/intern/tracking.c | 61 +++++++++++++++++++ .../COM_MovieDistortionOperation.cpp | 33 +++++++--- .../operations/COM_MovieDistortionOperation.h | 1 + 4 files changed, 91 insertions(+), 7 deletions(-) diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index eb7004b1ced..9bdc96e187d 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -46,6 +46,7 @@ struct MovieDistortion; struct Camera; struct Object; struct Scene; +struct rcti; /* **** Common functions **** */ @@ -156,6 +157,8 @@ struct ImBuf *BKE_tracking_undistort_frame(struct MovieTracking *tracking, struc struct ImBuf *BKE_tracking_distort_frame(struct MovieTracking *tracking, struct ImBuf *ibuf, int calibration_width, int calibration_height, float overscan); +void BKE_tracking_max_undistortion_delta_across_bound(struct MovieTracking *tracking, struct rcti *rect, float delta[2]); + /* **** Image sampling **** */ struct ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height, struct ImBuf *struct_ibuf, struct MovieTrackingTrack *track, diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 8b81e474e76..a6519f8005c 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -1605,6 +1605,67 @@ ImBuf *BKE_tracking_distort_frame(MovieTracking *tracking, ImBuf *ibuf, int cali calibration_height, overscan, FALSE); } +void BKE_tracking_max_undistortion_delta_across_bound(MovieTracking *tracking, rcti *rect, float delta[2]) +{ + int a; + float pos[2], warped_pos[2]; + const int coord_delta = 5; + + delta[0] = delta[1] = -FLT_MAX; + + for (a = rect->xmin; a <= rect->xmax + coord_delta; a += coord_delta) { + if (a > rect->xmax) + a = rect->xmax; + + /* bottom edge */ + pos[0] = a; + pos[1] = rect->ymin; + + BKE_tracking_undistort_v2(tracking, pos, warped_pos); + + delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0])); + delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1])); + + /* top edge */ + pos[0] = a; + pos[1] = rect->ymax; + + BKE_tracking_undistort_v2(tracking, pos, warped_pos); + + delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0])); + delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1])); + + if (a >= rect->xmax) + break; + } + + for (a = rect->ymin; a <= rect->ymax + coord_delta; a += coord_delta) { + if (a > rect->ymax) + a = rect->ymax; + + /* left edge */ + pos[0] = rect->xmin; + pos[1] = a; + + BKE_tracking_undistort_v2(tracking, pos, warped_pos); + + delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0])); + delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1])); + + /* right edge */ + pos[0] = rect->xmax; + pos[1] = a; + + BKE_tracking_undistort_v2(tracking, pos, warped_pos); + + delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0])); + delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1])); + + if (a >= rect->ymax) + break; + } +} + /*********************** Image sampling *************************/ static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int grayscale) diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp index b0fc21d4d55..863a404ba67 100644 --- a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp +++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp @@ -75,9 +75,31 @@ void MovieDistortionOperation::initExecution() calibration_width, calibration_height, this->m_distortion); s_cache.push_back(newC); this->m_cache = newC; + + if (this->m_distortion) { + float delta[2]; + rcti full_frame; + full_frame.xmin = full_frame.ymin = 0; + full_frame.xmax = this->m_width; + full_frame.ymax = this->m_height; + BKE_tracking_max_undistortion_delta_across_bound(&this->m_movieClip->tracking, &full_frame, delta); + + /* 5 is just in case we didn't hit real max of distortion in + * BKE_tracking_max_undistortion_delta_across_bound + */ + m_margin[0] = delta[0] + 5; + m_margin[1] = delta[1] + 5; + } + else { + /* undistortion with sane distortion coefficients would be mapped inside + * of each tile, should be no need in margin in this case + */ + m_margin[0] = m_margin[1] = 0; + } } else { this->m_cache = NULL; + m_margin[0] = m_margin[1] = 0; } } @@ -115,13 +137,10 @@ void MovieDistortionOperation::executePixel(float output[4], float x, float y, P bool MovieDistortionOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) { - const int marginX = this->m_width * 0.15; - const int marginY = this->m_height * 0.15; - rcti newInput; - newInput.xmin = input->xmin - marginX; - newInput.ymin = input->ymin - marginY; - newInput.xmax = input->xmax + marginX; - newInput.ymax = input->ymax + marginY; + newInput.xmin = input->xmin - m_margin[0]; + newInput.ymin = input->ymin - m_margin[1]; + newInput.xmax = input->xmax + m_margin[0]; + newInput.ymax = input->ymax + m_margin[1]; return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.h b/source/blender/compositor/operations/COM_MovieDistortionOperation.h index 4596fbd555b..c9629451992 100644 --- a/source/blender/compositor/operations/COM_MovieDistortionOperation.h +++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.h @@ -148,6 +148,7 @@ private: DistortionCache *m_cache; SocketReader *m_inputOperation; MovieClip *m_movieClip; + int m_margin[2]; protected: bool m_distortion; From 971b0f1ed63c5d82c8e2956573affa663837543d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 18 Feb 2013 10:45:46 +0000 Subject: [PATCH 027/182] Correction to cmake rules for libmv/ceres libmv still requires optimization switched off because of some incompatibility of SSBA and MSVC optimizer which makes bundle adjustment work just wrong. This shall not be an issue for Ceres and no need to disable optimization for extern_ceres --- extern/libmv/CMakeLists.txt | 4 ++-- extern/libmv/bundle.sh | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/extern/libmv/CMakeLists.txt b/extern/libmv/CMakeLists.txt index a51f576d965..6b5a9a3b67a 100644 --- a/extern/libmv/CMakeLists.txt +++ b/extern/libmv/CMakeLists.txt @@ -26,6 +26,8 @@ # If you're doing changes in this file, please update template # in that script too +add_subdirectory(third_party) + set(INC . ../colamd/Include @@ -243,5 +245,3 @@ add_definitions( ) blender_add_lib(extern_libmv "${SRC}" "${INC}" "${INC_SYS}") - -add_subdirectory(third_party) diff --git a/extern/libmv/bundle.sh b/extern/libmv/bundle.sh index 23e90fc8f7d..27f964ad5b3 100755 --- a/extern/libmv/bundle.sh +++ b/extern/libmv/bundle.sh @@ -122,6 +122,8 @@ cat > CMakeLists.txt << EOF # If you're doing changes in this file, please update template # in that script too +add_subdirectory(third_party) + set(INC . ../colamd/Include From de23a9bfd5f693ac2e45f015ab0c9dc28782aee3 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 18 Feb 2013 11:50:03 +0000 Subject: [PATCH 028/182] Correction to previous commit, needed to tweak some include directories after shuffling order of subdirectories and compiler flags tweaks. --- extern/libmv/third_party/ceres/CMakeLists.txt | 1 + extern/libmv/third_party/ceres/bundle.sh | 1 + 2 files changed, 2 insertions(+) diff --git a/extern/libmv/third_party/ceres/CMakeLists.txt b/extern/libmv/third_party/ceres/CMakeLists.txt index e2f06d74646..f0c0a4b269f 100644 --- a/extern/libmv/third_party/ceres/CMakeLists.txt +++ b/extern/libmv/third_party/ceres/CMakeLists.txt @@ -31,6 +31,7 @@ set(INC include internal ../gflags + ../../ ) set(INC_SYS diff --git a/extern/libmv/third_party/ceres/bundle.sh b/extern/libmv/third_party/ceres/bundle.sh index ccf6d0aca16..76630bc0626 100755 --- a/extern/libmv/third_party/ceres/bundle.sh +++ b/extern/libmv/third_party/ceres/bundle.sh @@ -120,6 +120,7 @@ set(INC include internal ../gflags + ../.. ) set(INC_SYS From 1c216337f08af38fbba0f60b9dc6036491a6ab2a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 18 Feb 2013 12:00:17 +0000 Subject: [PATCH 029/182] make autocomplete use unicode character stepping (needed for bugfix). --- .../editors/space_text/text_autocomplete.c | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c index 94977fc5f0f..62e5728bd3c 100644 --- a/source/blender/editors/space_text/text_autocomplete.c +++ b/source/blender/editors/space_text/text_autocomplete.c @@ -162,23 +162,28 @@ static GHash *text_autocomplete_build(Text *text) gh = BLI_ghash_str_new(__func__); for (linep = text->lines.first; linep; linep = linep->next) { - int i_start = 0; - int i_end = 0; + size_t i_start = 0; + size_t i_end = 0; + size_t i_step = 0; while (i_start < linep->len) { /* seek identifier beginning */ - while (i_start < linep->len && !text_check_identifier_nodigit(linep->line[i_start])) { - i_start++; + while ((i_start < linep->len) && + (!text_check_identifier_nodigit(BLI_str_utf8_as_unicode_step(&linep->line[i_start], &i_step)))) + { + i_start = i_step; } i_end = i_start; - while (i_end < linep->len && text_check_identifier(linep->line[i_end])) { - i_end++; + while ((i_end < linep->len) && + (!text_check_identifier(BLI_str_utf8_as_unicode_step(&linep->line[i_end], &i_step)))) + { + i_end = i_step; } if ((i_start != i_end) && /* check we're at the beginning of a line or that the previous char is not an identifier - * this prevents digits from being added */ - ((i_start < 1) || !text_check_identifier(linep->line[i_start - 1]))) + * this prevents digits from being added */ + ((i_start < 1) || !text_check_identifier(BLI_str_utf8_as_unicode(&linep->line[i_start - 1])))) { char *str_sub = &linep->line[i_start]; const int choice_len = i_end - i_start; From 5c5b7537798554cf7981a913ec3d248b6959893f Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 18 Feb 2013 13:30:40 +0000 Subject: [PATCH 030/182] Fix [#34300] Slider for list of particle systems (keyed particles) is not doing anything. Navigating a list of more than 5 elements requires keyboard. Systematically adding some custom id to template_list using default UI_UL_list class, this one is commoly used more than once in an area, yielding collision issues if they do not have a custom id... --- .../startup/bl_ui/properties_data_armature.py | 3 ++- .../scripts/startup/bl_ui/properties_particle.py | 13 ++++++++----- .../startup/bl_ui/properties_physics_common.py | 3 ++- release/scripts/startup/bl_ui/properties_scene.py | 2 +- release/scripts/startup/bl_ui/space_clip.py | 2 +- .../scripts/startup/bl_ui/space_view3d_toolbar.py | 6 +++--- 6 files changed, 17 insertions(+), 12 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_data_armature.py b/release/scripts/startup/bl_ui/properties_data_armature.py index 0f9d525f168..74f33170384 100644 --- a/release/scripts/startup/bl_ui/properties_data_armature.py +++ b/release/scripts/startup/bl_ui/properties_data_armature.py @@ -184,7 +184,8 @@ class DATA_PT_pose_library(ArmatureButtonsPanel, Panel): if poselib: # list of poses in pose library row = layout.row() - row.template_list("UI_UL_list", "", poselib, "pose_markers", poselib.pose_markers, "active_index", rows=5) + row.template_list("UI_UL_list", "pose_markers", 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_particle.py b/release/scripts/startup/bl_ui/properties_particle.py index 0aa2c14a0c7..f6784cbbaa3 100644 --- a/release/scripts/startup/bl_ui/properties_particle.py +++ b/release/scripts/startup/bl_ui/properties_particle.py @@ -97,7 +97,8 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, Panel): if ob: row = layout.row() - row.template_list("UI_UL_list", "", ob, "particle_systems", ob.particle_systems, "active_index", rows=2) + row.template_list("UI_UL_list", "particle_systems", ob, "particle_systems", + ob.particle_systems, "active_index", rows=2) col = row.column(align=True) col.operator("object.particle_system_add", icon='ZOOMIN', text="") @@ -637,7 +638,7 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, Panel): layout.label(text="Fluid interaction:") row = layout.row() - row.template_list("UI_UL_list", "", psys, "targets", psys, "active_particle_target_index") + row.template_list("UI_UL_list", "particle_targets", psys, "targets", psys, "active_particle_target_index") col = row.column() sub = col.row() @@ -703,7 +704,8 @@ 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("UI_UL_list", "", boids, "states", boids, "active_boid_state_index", compact="True") + #row.template_list("UI_UL_list", "particle_boids", 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="") @@ -724,7 +726,7 @@ class PARTICLE_PT_boidbrain(ParticleButtonsPanel, Panel): row.label(text="") row = layout.row() - row.template_list("UI_UL_list", "", state, "rules", state, "active_boid_rule_index") + row.template_list("UI_UL_list", "particle_boids_rules", state, "rules", state, "active_boid_rule_index") col = row.column() sub = col.row() @@ -887,7 +889,8 @@ class PARTICLE_PT_render(ParticleButtonsPanel, Panel): if part.use_group_count and not part.use_whole_group: row = layout.row() - row.template_list("UI_UL_list", "", part, "dupli_weights", part, "active_dupliweight_index") + row.template_list("UI_UL_list", "particle_dupli_weights", 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 90cf397f526..2d9d4649e28 100644 --- a/release/scripts/startup/bl_ui/properties_physics_common.py +++ b/release/scripts/startup/bl_ui/properties_physics_common.py @@ -108,7 +108,8 @@ def point_cache_ui(self, context, cache, enabled, cachetype): if not cachetype == 'RIGID_BODY': row = layout.row() - row.template_list("UI_UL_list", "", cache, "point_caches", cache.point_caches, "active_index", rows=2) + row.template_list("UI_UL_list", "point_caches", 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_scene.py b/release/scripts/startup/bl_ui/properties_scene.py index 68a097e6188..519f9ca47fa 100644 --- a/release/scripts/startup/bl_ui/properties_scene.py +++ b/release/scripts/startup/bl_ui/properties_scene.py @@ -94,7 +94,7 @@ class SCENE_PT_keying_sets(SceneButtonsPanel, Panel): row = layout.row() col = row.column() - col.template_list("UI_UL_list", "", scene, "keying_sets", scene.keying_sets, "active_index", rows=2) + col.template_list("UI_UL_list", "keying_sets", scene, "keying_sets", scene.keying_sets, "active_index", rows=2) col = row.column(align=True) col.operator("anim.keying_set_add", icon='ZOOMIN', text="") diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index bc5d89fd45b..e32db805a29 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -746,7 +746,7 @@ class CLIP_PT_stabilization(CLIP_PT_reconstruction_panel, Panel): layout.active = stab.use_2d_stabilization row = layout.row() - row.template_list("UI_UL_list", "", stab, "tracks", + row.template_list("UI_UL_list", "stabilization_tracks", 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 2fb420dabea..d64920625f7 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -1222,7 +1222,7 @@ class VIEW3D_PT_tools_particlemode(View3DPanel, Panel): if pe.type == 'PARTICLES': if ob.particle_systems: if len(ob.particle_systems) > 1: - layout.template_list("UI_UL_list", "", ob, "particle_systems", + layout.template_list("UI_UL_list", "particle_systems", ob, "particle_systems", ob.particle_systems, "active_index", rows=2, maxrows=3) ptcache = ob.particle_systems.active.point_cache @@ -1232,8 +1232,8 @@ class VIEW3D_PT_tools_particlemode(View3DPanel, Panel): ptcache = md.point_cache if ptcache and len(ptcache.point_caches) > 1: - layout.template_list("UI_UL_list", "", ptcache, "point_caches", ptcache.point_caches, "active_index", - rows=2, maxrows=3) + layout.template_list("UI_UL_list", "particles_point_caches", 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") From b99dcf3b51ac2b4d3b44521fcdc83b017b11a026 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 18 Feb 2013 13:34:26 +0000 Subject: [PATCH 031/182] Minor precision in template_list doc, to always use a custom list_id when using default UI_UL_list class. --- source/blender/makesrna/intern/rna_ui_api.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index 2043832a3f8..d0b21948a41 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -771,7 +771,8 @@ void RNA_api_ui_layout(StructRNA *srna) 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. " + "Identifier of this list widget (should be systematically used with default UI_UL_list " + "class). " "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 " From 21ab95c7d15b5bb8909aa2d624c8ecda9bb8c9f7 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 18 Feb 2013 13:43:18 +0000 Subject: [PATCH 032/182] Fix #34289: Wrong grid color on light background Grid was blending with wrong theme color. Since r53636 TH_HIGH_GRAD is used as a background and this color shall be used for blending. This is possible other usages of TH_BACK are wrong here as well, but would want Antony to check on this. --- source/blender/editors/space_view3d/view3d_draw.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 2b28b958248..c41fb926ab0 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -345,7 +345,7 @@ static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char ** CLAMP(blend_fac, 0.3f, 1.0f); - UI_ThemeColorBlend(TH_BACK, TH_GRID, blend_fac); + UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, blend_fac); drawgrid_draw(ar, wx, wy, x, y, dx_scalar); } @@ -374,7 +374,7 @@ static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char ** } } else { /* start blending out */ - UI_ThemeColorBlend(TH_BACK, TH_GRID, dx / (GRID_MIN_PX_D * 6.0)); + UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0)); drawgrid_draw(ar, wx, wy, x, y, dx); UI_ThemeColor(TH_GRID); @@ -382,7 +382,7 @@ static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char ** } } else { /* start blending out (GRID_MIN_PX < dx < (GRID_MIN_PX * 10)) */ - UI_ThemeColorBlend(TH_BACK, TH_GRID, dx / (GRID_MIN_PX_D * 6.0)); + UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0)); drawgrid_draw(ar, wx, wy, x, y, dx); UI_ThemeColor(TH_GRID); @@ -401,21 +401,21 @@ static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char ** drawgrid_draw(ar, wx, wy, x, y, dx); } else { - UI_ThemeColorBlend(TH_BACK, TH_GRID, dx / (GRID_MIN_PX_D * 6.0)); + UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0)); drawgrid_draw(ar, wx, wy, x, y, dx); UI_ThemeColor(TH_GRID); drawgrid_draw(ar, wx, wy, x, y, dx * sublines); } } else { - UI_ThemeColorBlend(TH_BACK, TH_GRID, dx / (GRID_MIN_PX_D * 6.0)); + UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0)); drawgrid_draw(ar, wx, wy, x, y, dx); UI_ThemeColor(TH_GRID); drawgrid_draw(ar, wx, wy, x, y, dx * sublines); } } else { - UI_ThemeColorBlend(TH_BACK, TH_GRID, dx / (GRID_MIN_PX_D * 6.0)); + UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0)); drawgrid_draw(ar, wx, wy, x, y, dx); UI_ThemeColor(TH_GRID); drawgrid_draw(ar, wx, wy, x, y, dx * sublines); From b187d3375161ee6a0583f0c05181929a6d1f1774 Mon Sep 17 00:00:00 2001 From: Sergej Reich Date: Mon, 18 Feb 2013 13:51:01 +0000 Subject: [PATCH 033/182] pointcache: Set start frame soft limit to 1 Right now most simulations can't handle cache start frame < 1 unfortunately. There are two main problems: 1. frame 0 is a special case so some simulations will just pop back to their initial state on frame 0. 2. blender doesn't allow playing the animation starting from negative start frames, so most simulations only work when baked and not during regular playback. Just change soft limit since sart frame < 1 can work in some cases, but this needs to be fixed properly in the individual simulations if we really want to allow it. --- source/blender/makesrna/intern/rna_object_force.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index 873ea49824c..dcb288a6f32 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -764,7 +764,7 @@ 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_ui_range(prop, 1, 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); From d7058f12e5f4eeecf32e16e73e08ec3f142729f9 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 18 Feb 2013 14:03:26 +0000 Subject: [PATCH 034/182] Make list_id mandatory when using default UI_UL_list class for a template_list. --- release/scripts/startup/bl_ui/__init__.py | 1 + source/blender/editors/include/UI_interface.h | 2 ++ source/blender/editors/interface/interface_templates.c | 7 +++++++ source/blender/makesrna/intern/rna_ui_api.c | 4 ++-- 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py index 982c723f08e..09813d8b1c2 100644 --- a/release/scripts/startup/bl_ui/__init__.py +++ b/release/scripts/startup/bl_ui/__init__.py @@ -137,6 +137,7 @@ def unregister(): # Define a default UIList, when a list does not need any custom drawing... +# Keep in sync with its #defined name in UI_interface.h class UI_UL_list(bpy.types.UIList): pass diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 434fb58184f..eb74dd1e274 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -832,6 +832,8 @@ void uiTemplateTextureImage(uiLayout *layout, struct bContext *C, struct Tex *te void uiTemplateReportsBanner(uiLayout *layout, struct bContext *C); void uiTemplateKeymapItemProperties(uiLayout *layout, struct PointerRNA *ptr); +/* Default UIList class name, keep in sync with its declaration in bl_ui/__init__.py */ +#define UI_UL_DEFAULT_CLASS_NAME "UI_UL_list" 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); diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 8dc51387db7..5805806a9a9 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -2478,6 +2478,13 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co int min, max; /* validate arguments */ + /* Forbid default UI_UL_DEFAULT_CLASS_NAME list class without a custom list_id! */ + if (!strcmp(UI_UL_DEFAULT_CLASS_NAME, listtype_name) && !(list_id && list_id[0])) { + RNA_warning("template_list using default '" UI_UL_DEFAULT_CLASS_NAME + "' UIList class must provide a custom list_id"); + return; + } + block = uiLayoutGetBlock(layout); if (!active_dataptr->data) { diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index d0b21948a41..0ce98e0b364 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -771,8 +771,8 @@ void RNA_api_ui_layout(StructRNA *srna) 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 (should be systematically used with default UI_UL_list " - "class). " + "Identifier of this list widget (mandatory when using default \"" UI_UL_DEFAULT_CLASS_NAME + "\" class). " "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 " From 98c5da4a819c72efa1b94523553c97438dadb798 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 18 Feb 2013 14:03:50 +0000 Subject: [PATCH 035/182] Fix #34276: OpenGL render not doing color space conversion to linear correctly with transparency, would show as too dark colors on edges. Found a strange issue here though, the alpha value in the OpenGL render result is not the same as the one specified in the material. It's not clear to me why this happens, color space conversions should not influence the alpha channel. --- source/blender/editors/render/render_opengl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index 7ba6a92e4be..ea18f2c8fbb 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -264,7 +264,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender) /* sequencer has got tricker ocnversion happened above */ IMB_buffer_float_from_float(rr->rectf, rr->rectf, - 4, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, FALSE, + 4, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, TRUE, oglrender->sizex, oglrender->sizey, oglrender->sizex, oglrender->sizex); } From 4ae3a28fcb0a53b634205fc54a2fc7869ab54f36 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 18 Feb 2013 14:52:49 +0000 Subject: [PATCH 036/182] fix bpy_extras.mesh_utils.edge_face_count_dict() helper api function. it was using tessfaces when theres no need to. --- release/scripts/modules/bpy_extras/mesh_utils.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/release/scripts/modules/bpy_extras/mesh_utils.py b/release/scripts/modules/bpy_extras/mesh_utils.py index 8b93b5922e9..d02fd6e34dc 100644 --- a/release/scripts/modules/bpy_extras/mesh_utils.py +++ b/release/scripts/modules/bpy_extras/mesh_utils.py @@ -152,10 +152,14 @@ def edge_face_count_dict(mesh): faces using each edge. :rtype: dict """ - face_edge_keys = [face.edge_keys for face in mesh.tessfaces] + + #face_edge_keys = [face.edge_keys for face in ] face_edge_count = {} - for face_keys in face_edge_keys: - for key in face_keys: + loops = mesh.loops + edges = mesh.edges + for poly in mesh.polygons: + for i in poly.loop_indices: + key = edges[loops[i].edge_index].key try: face_edge_count[key] += 1 except: From b0c6f87e2d31207b8046d809f0b384265c4ad903 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 18 Feb 2013 15:08:23 +0000 Subject: [PATCH 037/182] Fix #34290: backface culling option in 3d view was not interacting well with the option in the material in texture draw mode, now it always overrides the material. --- source/blender/editors/space_view3d/drawmesh.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index 35a0111e575..2cef10e1981 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -236,8 +236,9 @@ static struct TextureDrawState { Object *ob; int is_lit, is_tex; int color_profile; + bool use_backface_culling; unsigned char obcol[4]; -} Gtexdraw = {NULL, 0, 0, 0, {0, 0, 0, 0}}; +} Gtexdraw = {NULL, 0, 0, 0, false, {0, 0, 0, 0}}; static int set_draw_settings_cached(int clearcache, MTFace *texface, Material *ma, struct TextureDrawState gtexdraw) { @@ -250,7 +251,7 @@ static int set_draw_settings_cached(int clearcache, MTFace *texface, Material *m static int c_has_texface; Object *litob = NULL; /* to get mode to turn off mipmap in painting mode */ - int backculled = GEMAT_BACKCULL; + int backculled = GEMAT_BACKCULL || gtexdraw.use_backface_culling; int alphablend = 0; int textured = 0; int lit = 0; @@ -274,7 +275,7 @@ static int set_draw_settings_cached(int clearcache, MTFace *texface, Material *m if (ma) { alphablend = ma->game.alpha_blend; if (ma->mode & MA_SHLESS) lit = 0; - backculled = ma->game.flag & GEMAT_BACKCULL; + backculled = (ma->game.flag & GEMAT_BACKCULL) || gtexdraw.use_backface_culling; } if (texface) { @@ -375,17 +376,12 @@ static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, O Gtexdraw.is_tex = is_tex; Gtexdraw.color_profile = BKE_scene_check_color_management_enabled(scene); + Gtexdraw.use_backface_culling = (v3d->flag2 & V3D_BACKFACE_CULLING) != 0; memcpy(Gtexdraw.obcol, obcol, sizeof(obcol)); set_draw_settings_cached(1, NULL, NULL, Gtexdraw); glShadeModel(GL_SMOOTH); - if (v3d->flag2 & V3D_BACKFACE_CULLING) { - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - } - else { - glDisable(GL_CULL_FACE); - } + glCullFace(GL_BACK); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, (me->flag & ME_TWOSIDED) ? GL_TRUE : GL_FALSE); } From 5ba0eb0ae50bedd5026239f10937c1a2db11cf79 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 18 Feb 2013 15:08:27 +0000 Subject: [PATCH 038/182] Fix some popups being too small on retina display, among them the new image dialog. --- source/blender/editors/armature/poseobject.c | 2 +- source/blender/editors/object/object_edit.c | 2 +- source/blender/editors/space_image/image_ops.c | 2 +- source/blender/editors/space_text/text_ops.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c index 38924105316..55b344bfd62 100644 --- a/source/blender/editors/armature/poseobject.c +++ b/source/blender/editors/armature/poseobject.c @@ -238,7 +238,7 @@ static int pose_calculate_paths_invoke(bContext *C, wmOperator *op, wmEvent *UNU /* show popup dialog to allow editing of range... */ // FIXME: hardcoded dimensions here are just arbitrary - return WM_operator_props_dialog_popup(C, op, 200, 200); + return WM_operator_props_dialog_popup(C, op, 10*UI_UNIT_X, 10*UI_UNIT_Y); } /* For the object with pose/action: create path curves for selected bones diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 4807e7364ea..f03bc8b5afa 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -1151,7 +1151,7 @@ static int object_calculate_paths_invoke(bContext *C, wmOperator *op, wmEvent *U /* show popup dialog to allow editing of range... */ /* FIXME: hardcoded dimensions here are just arbitrary */ - return WM_operator_props_dialog_popup(C, op, 200, 200); + return WM_operator_props_dialog_popup(C, op, 10*UI_UNIT_X, 10*UI_UNIT_Y); } /* Calculate/recalculate whole paths (avs.path_sf to avs.path_ef) */ diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 0d1156a837a..40a98c5ebfe 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1777,7 +1777,7 @@ static int image_new_exec(bContext *C, wmOperator *op) /* XXX Note: the WM_operator_props_dialog_popup() doesn't work for uiIDContextProperty(), image is not being that way */ static int image_new_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { - return WM_operator_props_dialog_popup(C, op, 300, 100); + return WM_operator_props_dialog_popup(C, op, 15*UI_UNIT_X, 5*UI_UNIT_Y); } diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index b60528bcee8..514ac0a4d63 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -1929,7 +1929,7 @@ static int text_jump_exec(bContext *C, wmOperator *op) static int text_jump_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { - return WM_operator_props_dialog_popup(C, op, 200, 100); + return WM_operator_props_dialog_popup(C, op, 10*UI_UNIT_X, 5*UI_UNIT_Y); } From bd7648b2d2835143a3af748608bb87219e994d62 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Mon, 18 Feb 2013 15:14:34 +0000 Subject: [PATCH 039/182] Bug fix #34292 CTRL + MMB zoom in 2d editors now depends on 'max zoom' level. This makes zooms in UI (very limited) go smoother, but for fcurve or timeline it's same. --- source/blender/editors/interface/view2d_ops.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index fbbcb650e68..7f1140501b5 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -1034,14 +1034,17 @@ static int view_zoomdrag_modal(bContext *C, wmOperator *op, wmEvent *event) } else { /* 'continuous' or 'dolly' */ - float fac; + float fac, zoomfac = 0.001f * v2d->maxzoom; + + /* some view2d's (graph) don't have min/max zoom, or extreme ones */ + CLAMP (zoomfac, 0.001f, 0.01f); /* x-axis transform */ - fac = 0.01f * (event->x - vzd->lastx); + fac = zoomfac * (event->x - vzd->lastx); dx = fac * BLI_rctf_size_x(&v2d->cur); /* y-axis transform */ - fac = 0.01f * (event->y - vzd->lasty); + fac = zoomfac * (event->y - vzd->lasty); dy = fac * BLI_rctf_size_y(&v2d->cur); } From 4cd487d731a69b1f6c4144eebec56a28e25cd201 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 18 Feb 2013 15:47:13 +0000 Subject: [PATCH 040/182] checking for V3D_LOCAL was duplicated in transform.c, and both checks not quite correct. - When checking edimode, make sure its mesh editmode. - Graph editor supports this option but wasn't being checked. --- .../scripts/modules/bpy_extras/mesh_utils.py | 3 +- source/blender/editors/transform/transform.c | 37 ++++++++++--------- source/blender/makesrna/intern/rna_space.c | 2 +- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/release/scripts/modules/bpy_extras/mesh_utils.py b/release/scripts/modules/bpy_extras/mesh_utils.py index d02fd6e34dc..f4fdfece947 100644 --- a/release/scripts/modules/bpy_extras/mesh_utils.py +++ b/release/scripts/modules/bpy_extras/mesh_utils.py @@ -152,8 +152,7 @@ def edge_face_count_dict(mesh): faces using each edge. :rtype: dict """ - - #face_edge_keys = [face.edge_keys for face in ] + face_edge_count = {} loops = mesh.loops edges = mesh.edges diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index e5b4a6c7bae..a8efd998583 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -104,6 +104,16 @@ static int doVertSlide(TransInfo *t, float perc); static void drawEdgeSlide(const struct bContext *C, TransInfo *t); static void drawVertSlide(const struct bContext *C, TransInfo *t); +static bool transdata_check_local_center(TransInfo *t) +{ + return ((t->around == V3D_LOCAL) && ( + (t->flag & (T_OBJECT | T_POSE)) || + (t->obedit && t->obedit->type == OB_MESH && (t->settings->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_FACE))) || + (t->obedit && t->obedit->type == OB_ARMATURE) || + (t->spacetype == SPACE_IPO)) + ); +} + /* ************************** SPACE DEPENDANT CODE **************************** */ void setTransformViewMatrices(TransInfo *t) @@ -3005,12 +3015,7 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) } /* local constraint shouldn't alter center */ - if ((t->around == V3D_LOCAL) && - ( (t->flag & (T_OBJECT | T_POSE)) || - ((t->flag & T_EDIT) && (t->settings->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_FACE))) || - (t->obedit && t->obedit->type == OB_ARMATURE)) - ) - { + if (transdata_check_local_center(t)) { copy_v3_v3(center, td->center); } else if (t->options & CTX_MOVIECLIP) { @@ -3387,20 +3392,16 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short { float vec[3], totmat[3][3], smat[3][3]; float eul[3], fmat[3][3], quat[4]; - float *center = t->center; + const float *center; /* local constraint shouldn't alter center */ - if (around == V3D_LOCAL) { - if ( (t->flag & (T_OBJECT | T_POSE)) || - (t->settings->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_FACE)) || - (t->obedit && t->obedit->type == OB_ARMATURE)) - { - center = td->center; - } - - if (t->options & CTX_MOVIECLIP) { - center = td->center; - } + if (transdata_check_local_center(t) || + ((around == V3D_LOCAL) && (t->options & CTX_MOVIECLIP))) + { + center = td->center; + } + else { + center = t->center; } if (t->flag & T_POINTS) { diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index a742e6d4a1a..0ab74fb617f 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2548,7 +2548,7 @@ static void rna_def_space_graph(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; - /* this is basically the same as the one for the 3D-View, but with some entries ommitted */ + /* this is basically the same as the one for the 3D-View, but with some entries omitted */ static EnumPropertyItem gpivot_items[] = { {V3D_CENTER, "BOUNDING_BOX_CENTER", ICON_ROTATE, "Bounding Box Center", ""}, {V3D_CURSOR, "CURSOR", ICON_CURSOR, "2D Cursor", ""}, From 9ab3d4ff1eaacb8156043ac33bca7e9ac07806e6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 18 Feb 2013 16:35:13 +0000 Subject: [PATCH 041/182] fix [#34303] Rotation fcurves don't work with transforming with individual centers --- source/blender/editors/animation/anim_draw.c | 17 ++++++++++------- source/blender/editors/include/ED_anim_api.h | 3 ++- source/blender/editors/transform/transform.c | 7 +++++++ source/blender/editors/transform/transform.h | 4 ++++ .../editors/transform/transform_conversions.c | 16 +++++++++++++--- .../editors/transform/transform_generics.c | 5 ++++- 6 files changed, 40 insertions(+), 12 deletions(-) diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index d83d1805f0e..eb1f5ef1043 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -399,20 +399,23 @@ float ANIM_unit_mapping_get_factor(Scene *scene, ID *id, FCurve *fcu, short rest static short bezt_unit_mapping_apply(KeyframeEditData *ked, BezTriple *bezt) { /* mapping factor is stored in f1, flags are stored in i1 */ - short only_keys = (ked->i1 & ANIM_UNITCONV_ONLYKEYS); - short sel_vs = (ked->i1 & ANIM_UNITCONV_SELVERTS); + const bool only_keys = (ked->i1 & ANIM_UNITCONV_ONLYKEYS); + const bool sel_vs = (ked->i1 & ANIM_UNITCONV_SELVERTS); + const bool skip_knot = (ked->i1 & ANIM_UNITCONV_SKIPKNOTS); float fac = ked->f1; /* adjust BezTriple handles only if allowed to */ - if (only_keys == 0) { - if ((sel_vs == 0) || (bezt->f1 & SELECT)) + if (only_keys == false) { + if ((sel_vs == false) || (bezt->f1 & SELECT)) bezt->vec[0][1] *= fac; - if ((sel_vs == 0) || (bezt->f3 & SELECT)) + if ((sel_vs == false) || (bezt->f3 & SELECT)) bezt->vec[2][1] *= fac; } - if ((sel_vs == 0) || (bezt->f2 & SELECT)) - bezt->vec[1][1] *= fac; + if (skip_knot == false) { + if ((sel_vs == false) || (bezt->f2 & SELECT)) + bezt->vec[1][1] *= fac; + } return 0; } diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 551d3041398..20f568a3642 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -552,7 +552,8 @@ typedef enum eAnimUnitConv_Flags { /* only touch selected BezTriples */ ANIM_UNITCONV_ONLYSEL = (1 << 2), /* only touch selected vertices */ - ANIM_UNITCONV_SELVERTS = (1 << 3) + ANIM_UNITCONV_SELVERTS = (1 << 3), + ANIM_UNITCONV_SKIPKNOTS = (1 << 4), } eAnimUnitConv_Flags; /* Get unit conversion factor for given ID + F-Curve */ diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index a8efd998583..befeb2bce25 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -7388,3 +7388,10 @@ void BIF_TransformSetUndo(const char *UNUSED(str)) // TRANSFORM_FIX_ME //Trans.undostr = str; } + + +/* TODO, move to: transform_queries.c */ +bool checkUseLocalCenter_GraphEdit(TransInfo *t) +{ + return ((t->around == V3D_LOCAL) && !ELEM3(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE)); +} diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 4e3f2b04de0..9c57c74a26d 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -745,4 +745,8 @@ void projectEdgeSlideData(TransInfo *t, bool is_final); void freeVertSlideVerts(TransInfo *t); + +/* TODO. transform_queries.c */ +bool checkUseLocalCenter_GraphEdit(TransInfo *t); + #endif diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 7d62775ae58..32ceaf97331 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -123,6 +123,7 @@ #include "BLO_sys_types.h" // for intptr_t support + /* local function prototype - for Object/Bone Constraints */ static short constraints_list_needinv(TransInfo *t, ListBase *list); @@ -3530,7 +3531,9 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) int count = 0, i; float cfra; float mtx[3][3], smtx[3][3]; - const short use_handle = !(sipo->flag & SIPO_NOHANDLES); + const bool use_handle = !(sipo->flag & SIPO_NOHANDLES); + const bool use_local_center = checkUseLocalCenter_GraphEdit(t); + const short anim_map_flag = ANIM_UNITCONV_ONLYSEL | ANIM_UNITCONV_SELVERTS; /* determine what type of data we are operating on */ if (ANIM_animdata_get_context(C, &ac) == 0) @@ -3662,7 +3665,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) if (fcu->bezt == NULL) continue; - ANIM_unit_mapping_apply_fcurve(ac.scene, ale->id, ale->key_data, ANIM_UNITCONV_ONLYSEL | ANIM_UNITCONV_SELVERTS); + ANIM_unit_mapping_apply_fcurve(ac.scene, ale->id, ale->key_data, anim_map_flag); /* only include BezTriples whose 'keyframe' occurs on the same side of the current frame as mouse (if applicable) */ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { @@ -3697,7 +3700,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) } /* only include main vert if selected */ - if (sel2 && (sipo->around != V3D_LOCAL || ELEM3(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE))) { + if (sel2 && (use_local_center == false)) { /* move handles relative to center */ if (ELEM3(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE)) { @@ -3733,6 +3736,13 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) /* Sets handles based on the selection */ testhandles_fcurve(fcu, use_handle); + + /* even though transform values are written back right after during transform, + * using individual center's with rotation means the center point wont + * be touched again see: [#34303] */ + if (use_local_center) { + ANIM_unit_mapping_apply_fcurve(ac.scene, ale->id, ale->key_data, anim_map_flag | ANIM_UNITCONV_RESTORE); + } } /* cleanup temp list */ diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index ef775ae3128..da761365671 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -130,6 +130,7 @@ void getViewVector(TransInfo *t, float coord[3], float vec[3]) /* ************************** GENERICS **************************** */ + static void clipMirrorModifier(TransInfo *t, Object *ob) { ModifierData *md = ob->modifiers.first; @@ -407,7 +408,9 @@ static void recalcData_graphedit(TransInfo *t) continue; // fixme: only do this for selected verts... - ANIM_unit_mapping_apply_fcurve(ac.scene, ale->id, ale->key_data, ANIM_UNITCONV_ONLYSEL | ANIM_UNITCONV_SELVERTS | ANIM_UNITCONV_RESTORE); + ANIM_unit_mapping_apply_fcurve(ac.scene, ale->id, ale->key_data, + ANIM_UNITCONV_ONLYSEL | ANIM_UNITCONV_SELVERTS | ANIM_UNITCONV_RESTORE | + (checkUseLocalCenter_GraphEdit(t) ? ANIM_UNITCONV_SKIPKNOTS : 0)); /* watch it: if the time is wrong: do not correct handles yet */ From 525da1f872a79a212e56f0692472d7831ddaf442 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 18 Feb 2013 17:39:44 +0000 Subject: [PATCH 042/182] Fix wrong alpha channel for OpenGL render results with transparent textures or materials, the typical glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); blend function does not give correct destination alpha. --- source/blender/gpu/intern/gpu_draw.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 80f35d531cd..c631f7efbe9 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -395,7 +395,12 @@ static void gpu_set_alpha_blend(GPUBlendMode alphablend) } else if (ELEM(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ALPHA_SORT)) { glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + /* for OpenGL render we use the alpha channel, this makes alpha blend correct */ + if (GLEW_VERSION_1_4) + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + else + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* if U.glalphaclip == 1.0, some cards go bonkers... * turn off alpha test in this case */ From 58c9691d19ef0b1b60b84f4c0fcc8f1d4721171a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 18 Feb 2013 17:51:07 +0000 Subject: [PATCH 043/182] Correction to own r44749 -- layers from view were always used, shall use active layer now for real. --- release/scripts/modules/bpy_extras/object_utils.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/release/scripts/modules/bpy_extras/object_utils.py b/release/scripts/modules/bpy_extras/object_utils.py index 5797b8b7bf3..ab5dc3e6aee 100644 --- a/release/scripts/modules/bpy_extras/object_utils.py +++ b/release/scripts/modules/bpy_extras/object_utils.py @@ -124,8 +124,9 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True): else: base.layers = [True if i == scene.active_layer else False for i in range(len(scene.layers))] - if v3d: - base.layers_from_view(context.space_data) + else: + if v3d: + base.layers_from_view(context.space_data) obj_new.matrix_world = add_object_align_init(context, operator) From 167dcc88c78b68540ecdd1abc3e26ade73d2d27c Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 18 Feb 2013 19:34:14 +0000 Subject: [PATCH 044/182] Force movie clips always use default alpha mode, before this straight alpha was used for them which doesn't work for cleaned footage stored in EXR file format. Perhaps we need to support configurable alpha mode for clips, but that's for later (maybe even after release), --- source/blender/blenkernel/intern/movieclip.c | 2 +- source/blender/imbuf/intern/readimage.c | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 943d9e9452a..eceac61ddb6 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -216,7 +216,7 @@ static ImBuf *movieclip_load_sequence_file(MovieClip *clip, MovieClipUser *user, colorspace = clip->colorspace_settings.name; } - loadflag = IB_rect | IB_multilayer; + loadflag = IB_rect | IB_multilayer | IB_alphamode_detect; /* read ibuf */ ibuf = IMB_loadiffname(name, loadflag, colorspace); diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c index 00bc78ee488..4d47d883444 100644 --- a/source/blender/imbuf/intern/readimage.c +++ b/source/blender/imbuf/intern/readimage.c @@ -75,6 +75,8 @@ ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, char co if (type->load) { ibuf = type->load(mem, size, flags, effective_colorspace); if (ibuf) { + int alpha_flags; + if (colorspace) { if (ibuf->rect) { /* byte buffer is never internally converted to some standard space, @@ -86,11 +88,16 @@ ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, char co BLI_strncpy(colorspace, effective_colorspace, IM_MAX_SPACE); } + if (flags & IB_alphamode_detect) + alpha_flags = ibuf->flags & IB_alphamode_premul; + else + alpha_flags = flags & IB_alphamode_premul; + if (flags & IB_ignore_alpha) { IMB_rectfill_alpha(ibuf, 1.0f); } else { - if (flags & IB_alphamode_premul) { + if (alpha_flags & IB_alphamode_premul) { if (ibuf->rect) { IMB_unpremultiply_alpha(ibuf); } From 47c29c1c2ed43f98f64e9e3a5d06e74aec34a072 Mon Sep 17 00:00:00 2001 From: Pablo Vazquez Date: Mon, 18 Feb 2013 21:19:43 +0000 Subject: [PATCH 045/182] Themes: disabled items on menus were using a color mix of text and text_selected, this didn't work nice with dark themes and text shadows and overall didn't make much sense. Now, disabled items use a mix of text and menu item background (inner) color. Same results, but allows dark themes with bright selected text to use shadows. Example case: http://pasteall.org/pic/show.php?id=45697 --- 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 6735c8b173c..68df8e29957 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1804,7 +1804,7 @@ static void widget_state_menu_item(uiWidgetType *wt, int state) } /* regular disabled */ else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) { - widget_state_blend(wt->wcol.text, wt->wcol.text_sel, 0.5f); + widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f); } /* regular active */ else if (state & UI_ACTIVE) { From 442d16b46879f9109f4536d48553aa36824b17b1 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Mon, 18 Feb 2013 23:41:28 +0000 Subject: [PATCH 046/182] Fix for [#34308] only half width of material list row is used for material name. * Issue was caused in r54393. --- release/scripts/startup/bl_ui/properties_material.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py index a13c722ea62..9a3957fe353 100644 --- a/release/scripts/startup/bl_ui/properties_material.py +++ b/release/scripts/startup/bl_ui/properties_material.py @@ -84,8 +84,6 @@ class MATERIAL_UL_matslots(UIList): layout.label(text=iface_("Node %s") % manode.name, translate=False, icon_value=layout.icon(manode)) elif ma.use_nodes: layout.label(text="Node ") - else: - layout.label(text="") elif self.layout_type in {'GRID'}: layout.alignment = 'CENTER' layout.label(text="", icon_value=icon) From 4e73ff0d637772950f1f54c0259edbc60027cfba Mon Sep 17 00:00:00 2001 From: Alex Fraser Date: Tue, 19 Feb 2013 02:24:52 +0000 Subject: [PATCH 047/182] Fix for [#34099] Particles leaking from moving meshes This was caused by a floating point precision error. During collision detection, Newton-Raphson iteration is used to find the exact time of the collision. But when using subframes, the initial Newton step was too small. Now the initial step is given in absolute units. When subframes = 0, this should behave almost the same as before. Thanks to Janne Karhu, Lukas Toenne and Ton Roosendaal for their help with this patch, and to AutoCRC for funding. --- source/blender/blenkernel/BKE_particle.h | 5 +- .../blenkernel/intern/particle_system.c | 52 ++++++++++++++----- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index a9a8bc32064..6c207675cb1 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -220,7 +220,10 @@ typedef struct ParticleCollision { ParticleCollisionElement pce; - float total_time, inv_timestep; + /* total_time is the amount of time in this subframe + * inv_total_time is the opposite + * inv_timestep is the inverse of the amount of time in this frame */ + float total_time, inv_total_time, inv_timestep; float radius; float co1[3], co2[3]; diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 6e4937d11ec..3efe25794e1 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -3028,13 +3028,20 @@ static void basic_rotate(ParticleSettings *part, ParticleData *pa, float dfra, f normalize_qt(pa->state.rot); } -/************************************************/ -/* Collisions */ -/************************************************/ +/************************************************ + * Collisions + * + * The algorithm is roughly: + * 1. Use a BVH tree to search for faces that a particle may collide with. + * 2. Use Newton's method to find the exact time at which the collision occurs. + * http://en.wikipedia.org/wiki/Newton's_method + * + ************************************************/ #define COLLISION_MAX_COLLISIONS 10 #define COLLISION_MIN_RADIUS 0.001f #define COLLISION_MIN_DISTANCE 0.0001f #define COLLISION_ZERO 0.00001f +#define COLLISION_INIT_STEP 0.00008f typedef float (*NRDistanceFunc)(float *p, float radius, ParticleCollisionElement *pce, float *nor); static float nr_signed_distance_to_plane(float *p, float radius, ParticleCollisionElement *pce, float *nor) { @@ -3189,16 +3196,20 @@ static void collision_point_on_surface(float p[3], ParticleCollisionElement *pce /* find first root in range [0-1] starting from 0 */ static float collision_newton_rhapson(ParticleCollision *col, float radius, ParticleCollisionElement *pce, NRDistanceFunc distance_func) { - float t0, t1, d0, d1, dd, n[3]; + float t0, t1, dt_init, d0, d1, dd, n[3]; int iter; pce->inv_nor = -1; + /* Initial step size should be small, but not too small or floating point + * precision errors will appear. - z0r */ + dt_init = COLLISION_INIT_STEP * col->inv_total_time; + /* start from the beginning */ t0 = 0.f; collision_interpolate_element(pce, t0, col->f, col); d0 = distance_func(col->co1, radius, pce, n); - t1 = 0.001f; + t1 = dt_init; d1 = 0.f; for (iter=0; iter<10; iter++) {//, itersum++) { @@ -3208,11 +3219,6 @@ static float collision_newton_rhapson(ParticleCollision *col, float radius, Part d1 = distance_func(pce->p, radius, pce, n); - /* no movement, so no collision */ - if (d1 == d0) { - return -1.f; - } - /* particle already inside face, so report collision */ if (iter == 0 && d0 < 0.f && d0 > -radius) { copy_v3_v3(pce->p, col->co1); @@ -3220,7 +3226,24 @@ static float collision_newton_rhapson(ParticleCollision *col, float radius, Part pce->inside = 1; return 0.f; } - + + /* Zero gradient (no movement relative to element). Can't step from + * here. */ + if (d1 == d0) { + /* If first iteration, try from other end where the gradient may be + * greater. Note: code duplicated below. */ + if (iter == 0) { + t0 = 1.f; + collision_interpolate_element(pce, t0, col->f, col); + d0 = distance_func(col->co2, radius, pce, n); + t1 = 1.0f - dt_init; + d1 = 0.f; + continue; + } + else + return -1.f; + } + dd = (t1-t0)/(d1-d0); t0 = t1; @@ -3228,14 +3251,14 @@ static float collision_newton_rhapson(ParticleCollision *col, float radius, Part t1 -= d1*dd; - /* particle movin away from plane could also mean a strangely rotating face, so check from end */ + /* Particle moving away from plane could also mean a strangely rotating + * face, so check from end. Note: code duplicated above. */ if (iter == 0 && t1 < 0.f) { t0 = 1.f; collision_interpolate_element(pce, t0, col->f, col); d0 = distance_func(col->co2, radius, pce, n); - t1 = 0.999f; + t1 = 1.0f - dt_init; d1 = 0.f; - continue; } else if (iter == 1 && (t1 < -COLLISION_ZERO || t1 > 1.f)) @@ -3683,6 +3706,7 @@ static void collision_check(ParticleSimulationData *sim, int p, float dfra, floa memset(&col, 0, sizeof(ParticleCollision)); col.total_time = timestep * dfra; + col.inv_total_time = 1.0f/col.total_time; col.inv_timestep = 1.0f/timestep; col.cfra = cfra; From 098e4234b113fdff9804ef76b6f0bdb12a6bac3b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 19 Feb 2013 02:30:02 +0000 Subject: [PATCH 048/182] minor change to own recent commit with transform fcurve centers and some style edits and typo corrections. --- source/blender/blenfont/BLF_translation.h | 2 +- source/blender/bmesh/intern/bmesh_polygon.c | 5 +++-- source/blender/editors/armature/poseobject.c | 2 +- source/blender/editors/object/object_edit.c | 2 +- source/blender/editors/space_clip/clip_editor.c | 2 +- source/blender/editors/space_image/image_ops.c | 2 +- source/blender/editors/space_text/text_ops.c | 2 +- source/blender/editors/transform/transform_generics.c | 7 ++++--- source/blender/imbuf/intern/dds/dds_api.cpp | 2 +- source/blender/imbuf/intern/iris.c | 2 +- source/blender/python/generic/bpy_internal_import.c | 2 +- 11 files changed, 16 insertions(+), 14 deletions(-) diff --git a/source/blender/blenfont/BLF_translation.h b/source/blender/blenfont/BLF_translation.h index fd8b30d1d1b..cbfc7c28d8d 100644 --- a/source/blender/blenfont/BLF_translation.h +++ b/source/blender/blenfont/BLF_translation.h @@ -112,7 +112,7 @@ const char *BLF_translate_do_tooltip(const char *msgctxt, const char *msgid); /* Default, void context. * WARNING! The "" context is not the same as no (NULL) context at mo/boost::locale level! - * NOTE: We translate BLF_I18NCONTEXT_DEFAULT as BLF_I18NCONTEXT_DEFAULT_BPY in Python, as we can’t use "natural" + * NOTE: We translate BLF_I18NCONTEXT_DEFAULT as BLF_I18NCONTEXT_DEFAULT_BPY in Python, as we can't use "natural" * None value in rna string properties... :/ * For perf reason, we only use the first char to detect this context, so other contexts should never start * with the same char! diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index 1aa4d7c5e00..9592c34fc75 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -674,7 +674,7 @@ static BMLoop *poly_find_ear(BMFace *f, float (*projectverts)[2], const bool use i = (((len_squared_v3v3(larr[0]->v->co, larr[2]->v->co) > len_squared_v3v3(larr[1]->v->co, larr[3]->v->co) * bias)) != use_beauty); i4 = (i + 3) % 4; - /* Check produced tris aren’t too flat/narrow... + /* Check produced tris aren't too flat/narrow... * Probably not the best test, but is quite efficient and should at least avoid null-area faces! */ cos1 = fabsf(cos_v3v3v3(larr[i4]->v->co, larr[i]->v->co, larr[i + 1]->v->co)); cos2 = fabsf(cos_v3v3v3(larr[i4]->v->co, larr[i + 2]->v->co, larr[i + 1]->v->co)); @@ -741,7 +741,8 @@ static BMLoop *poly_find_ear(BMFace *f, float (*projectverts)[2], const bool use /* Compare to prev best (i.e. lowest) cos. */ if (cos < bestcos) { /* We must check this tri would not leave a (too much) degenerated remaining face! */ - /* For now just assume if the average of cos of all "remaining face"'s corners is below a given threshold, it’s OK. */ + /* For now just assume if the average of cos of all + * "remaining face"'s corners is below a given threshold, it's OK. */ float avgcos = fabsf(cos_v3v3v3(v1->co, v3->co, l_iter->next->next->v->co)); const int i_limit = (i - 1 + len) % len; avgcos += fabsf(cos_v3v3v3(l_iter->prev->prev->v->co, v1->co, v3->co)); diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c index 55b344bfd62..c7d1e428355 100644 --- a/source/blender/editors/armature/poseobject.c +++ b/source/blender/editors/armature/poseobject.c @@ -238,7 +238,7 @@ static int pose_calculate_paths_invoke(bContext *C, wmOperator *op, wmEvent *UNU /* show popup dialog to allow editing of range... */ // FIXME: hardcoded dimensions here are just arbitrary - return WM_operator_props_dialog_popup(C, op, 10*UI_UNIT_X, 10*UI_UNIT_Y); + return WM_operator_props_dialog_popup(C, op, 10 * UI_UNIT_X, 10 * UI_UNIT_Y); } /* For the object with pose/action: create path curves for selected bones diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index f03bc8b5afa..a13c0509824 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -1151,7 +1151,7 @@ static int object_calculate_paths_invoke(bContext *C, wmOperator *op, wmEvent *U /* show popup dialog to allow editing of range... */ /* FIXME: hardcoded dimensions here are just arbitrary */ - return WM_operator_props_dialog_popup(C, op, 10*UI_UNIT_X, 10*UI_UNIT_Y); + return WM_operator_props_dialog_popup(C, op, 10 * UI_UNIT_X, 10 * UI_UNIT_Y); } /* Calculate/recalculate whole paths (avs.path_sf to avs.path_ef) */ diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 927834a8924..728110dfeee 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -618,7 +618,7 @@ int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf, const unsign context->last_texture = glaGetOneInteger(GL_TEXTURE_2D); /* image texture need to be rebinded if displaying another image buffer - * assuming displaying happens of footage frames only on which painting doesn't heppen. + * assuming displaying happens of footage frames only on which painting doesn't happen. * so not changed image buffer pointer means unchanged image content */ need_rebind |= context->texture_ibuf != ibuf; need_rebind |= context->display_buffer != display_buffer; diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 40a98c5ebfe..dc834d88323 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1777,7 +1777,7 @@ static int image_new_exec(bContext *C, wmOperator *op) /* XXX Note: the WM_operator_props_dialog_popup() doesn't work for uiIDContextProperty(), image is not being that way */ static int image_new_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { - return WM_operator_props_dialog_popup(C, op, 15*UI_UNIT_X, 5*UI_UNIT_Y); + return WM_operator_props_dialog_popup(C, op, 15 * UI_UNIT_X, 5 * UI_UNIT_Y); } diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index 514ac0a4d63..9b5d453d8a3 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -1929,7 +1929,7 @@ static int text_jump_exec(bContext *C, wmOperator *op) static int text_jump_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { - return WM_operator_props_dialog_popup(C, op, 10*UI_UNIT_X, 5*UI_UNIT_Y); + return WM_operator_props_dialog_popup(C, op, 10 * UI_UNIT_X, 5 * UI_UNIT_Y); } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index da761365671..f97a8175101 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -378,6 +378,8 @@ static void recalcData_graphedit(TransInfo *t) bAnimListElem *ale; int dosort = 0; + + const bool use_local_center = checkUseLocalCenter_GraphEdit(t); /* initialize relevant anim-context 'context' data from TransInfo data */ @@ -406,11 +408,10 @@ static void recalcData_graphedit(TransInfo *t) /* ignore unselected fcurves */ if (!fcu_test_selected(fcu)) continue; - - // fixme: only do this for selected verts... + ANIM_unit_mapping_apply_fcurve(ac.scene, ale->id, ale->key_data, ANIM_UNITCONV_ONLYSEL | ANIM_UNITCONV_SELVERTS | ANIM_UNITCONV_RESTORE | - (checkUseLocalCenter_GraphEdit(t) ? ANIM_UNITCONV_SKIPKNOTS : 0)); + (use_local_center ? ANIM_UNITCONV_SKIPKNOTS : 0)); /* watch it: if the time is wrong: do not correct handles yet */ diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp index 4098b466377..0c240f16227 100644 --- a/source/blender/imbuf/intern/dds/dds_api.cpp +++ b/source/blender/imbuf/intern/dds/dds_api.cpp @@ -96,7 +96,7 @@ struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags, char colo Color32 pixel; Color32 *pixels = 0; - /* OCIO_TODO: never was able to save DDS, so can'ttest loading + /* OCIO_TODO: never was able to save DDS, so can't test loading * but profile used to be set to sRGB and can't see rect_float here, so * default byte space should work fine */ diff --git a/source/blender/imbuf/intern/iris.c b/source/blender/imbuf/intern/iris.c index dec5f6fb39e..47bd3e54a6f 100644 --- a/source/blender/imbuf/intern/iris.c +++ b/source/blender/imbuf/intern/iris.c @@ -672,7 +672,7 @@ static void expandrow(unsigned char *optr, unsigned char *iptr, int z) * represents one pixel. xsize and ysize specify the dimensions of * the pixel array. zsize specifies what kind of image file to * write out. if zsize is 1, the luminance of the pixels are - * calculated, and a sinlge channel black and white image is saved. + * calculated, and a single channel black and white image is saved. * If zsize is 3, an RGB image file is saved. If zsize is 4, an * RGBA image file is saved. * diff --git a/source/blender/python/generic/bpy_internal_import.c b/source/blender/python/generic/bpy_internal_import.c index 8d146bedb48..0c0ad50ebe4 100644 --- a/source/blender/python/generic/bpy_internal_import.c +++ b/source/blender/python/generic/bpy_internal_import.c @@ -66,7 +66,7 @@ static PyObject *imp_reload_orig = NULL; * * However Python's alternative is to use import hooks, * which are implemented in a way that we can't use our own importer as a - * fall-back (instead we must try and fail - raise an exception evert time). + * fall-back (instead we must try and fail - raise an exception every time). * Since importing from blenders text-blocks is not the common case * I prefer to use Pythons import by default and fall-back to * Blenders - which we can only do by intercepting import calls I'm afraid. From 6550fb8452da5cdb1f913a1e57e13354b4ea6f5f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 19 Feb 2013 02:48:14 +0000 Subject: [PATCH 049/182] bpy.props.RemoveProperty() had incorrect docstring. --- source/blender/python/intern/bpy_props.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index b42fdbd0ca4..7ffce0e9a93 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -2796,12 +2796,17 @@ static PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject } PyDoc_STRVAR(BPy_RemoveProperty_doc, -".. function:: RemoveProperty(attr)\n" +".. function:: RemoveProperty(cls, attr)\n" "\n" " Removes a dynamically defined property.\n" "\n" +" :arg cls: The class containing the property.\n" +" :type cls: type\n" " :arg attr: Property name.\n" " :type attr: string\n" +"\n" +".. note:: Typically this function doesn't need to be accessed directly.\n" +" Instead use ``del cls.attr``\n" ); static PyObject *BPy_RemoveProperty(PyObject *self, PyObject *args, PyObject *kw) { From 926e0e7eb71726fdd1be3f9d299bf3d9c3ad0a7a Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 19 Feb 2013 03:26:18 +0000 Subject: [PATCH 050/182] Bugfix [#34283] armature bones losing their roll setting upon translation in edit mode My earlier fix for [#33974] (in r.54061) was causing some problems where manually specified roll values on horizontal or angled bones were getting reset. This could be nasty as you might not notice the changes for a while (especially when using stick bones without axes displayed). I've now put in place a hacky compromise solution which should catch both of these situations nicely. For z-axis (i.e. vertical) movements, the r.54061 fix is used, while for everything else (moving or just touch-n-go), the old setting is used. --- .../editors/transform/transform_generics.c | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index f97a8175101..76ca9d8959a 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -809,6 +809,7 @@ static void recalcData_view3d(TransInfo *t) if (td->extra) { float vec[3], up_axis[3]; float qrot[4]; + bool ztrans_hack = false; ebo = td->extra; copy_v3_v3(up_axis, td->axismtx[2]); @@ -823,7 +824,25 @@ static void recalcData_view3d(TransInfo *t) mul_m3_v3(t->mat, up_axis); } - ebo->roll = ED_rollBoneToVector(ebo, up_axis, TRUE); + /* "ztrans_hack" is a hacky compromise fix for two bug reports + * - [#33974] : When extruding/translating bones vertically, + * the roll of each bone in such vertical chains would + * flip between z-axis forward and z-axis backwards + * - [#34283] : For "normal" transforms, the original fix for [#33974] + * would cause manually-set roll values on horizontal and + * diagonal bones to constantly get reset to values the system + * deems "correct" (usually 180 degree flips of the manual version) + */ + if (t->mode == TFM_TRANSLATION) { + const float ZAXIS_REF[3] = {0.0f, 0.0f, 1.0f}; + float tdelta[3]; + + /* tdelta is the translation - enable this hack when it is z-axis movement */ + normalize_v3_v3(tdelta, t->values); + ztrans_hack = compare_v3v3(tdelta, ZAXIS_REF, 0.1f); + } + + ebo->roll = ED_rollBoneToVector(ebo, up_axis, ztrans_hack); } } } From c68d5325d0706305937372e42bd981197440de24 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 19 Feb 2013 04:37:28 +0000 Subject: [PATCH 051/182] fix for [#34283] wasn't working in my tests (attached to original report), made bone roll get compatible angle values with the original roll. --- source/blender/blenlib/BLI_math_rotation.h | 2 ++ source/blender/blenlib/intern/math_rotation.c | 6 ++++++ source/blender/editors/transform/transform_generics.c | 4 +++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/source/blender/blenlib/BLI_math_rotation.h b/source/blender/blenlib/BLI_math_rotation.h index e349a05ac23..5ba37d70ca5 100644 --- a/source/blender/blenlib/BLI_math_rotation.h +++ b/source/blender/blenlib/BLI_math_rotation.h @@ -186,6 +186,8 @@ float fov_to_focallength(float fov, float sensor); float angle_wrap_rad(float angle); float angle_wrap_deg(float angle); +float angle_compat_rad(float angle, float angle_compat); + int mat3_from_axis_conversion(int from_forward, int from_up, int to_forward, int to_up, float r_mat[3][3]); diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c index c0ea817ae4a..26576b2dcb2 100644 --- a/source/blender/blenlib/intern/math_rotation.c +++ b/source/blender/blenlib/intern/math_rotation.c @@ -1740,6 +1740,12 @@ float angle_wrap_deg(float angle) return mod_inline(angle + 180.0f, 360.0f) - 180.0f; } +/* returns an angle compatible with angle_compat */ +float angle_compat_rad(float angle, float angle_compat) +{ + return angle + (floorf(((angle_compat - angle) / (float)M_PI) + 0.5f)) * (float)M_PI; +} + /* axis conversion */ static float _axis_convert_matrix[23][3][3] = { {{-1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}}, diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 76ca9d8959a..aa32518b489 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -809,6 +809,7 @@ static void recalcData_view3d(TransInfo *t) if (td->extra) { float vec[3], up_axis[3]; float qrot[4]; + float roll; bool ztrans_hack = false; ebo = td->extra; @@ -842,7 +843,8 @@ static void recalcData_view3d(TransInfo *t) ztrans_hack = compare_v3v3(tdelta, ZAXIS_REF, 0.1f); } - ebo->roll = ED_rollBoneToVector(ebo, up_axis, ztrans_hack); + roll = ED_rollBoneToVector(ebo, up_axis, ztrans_hack); + ebo->roll = angle_compat_rad(roll, ebo->roll); } } } From e5a135e0b26d7a268e7507ffb1be2f2fcc1b0b9c Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 19 Feb 2013 08:37:08 +0000 Subject: [PATCH 052/182] Fixes for alpha mode do_versions code Before this change only old flag "Premultiply" was used to detect alpha mode, which is not enough actually. Now the logic here is: - If "Premultiply" was enabled it is likely float image with straight alpha, which shall be premultiplied before usage. In this case image/sequence Alpha Mode is set to Straight. - Otherwise use default alpha mode for image format based on an extension. This could fail in some cases like TIFF, but this wasn't handled fully correct in older blender anyway. Initial discovered issue was that EXR images saved in older Blender versions were set to Straight alpha mode, which is obviously a straight way to lots of headache. --- source/blender/blenkernel/BKE_image.h | 3 +++ source/blender/blenkernel/BKE_sequencer.h | 2 ++ source/blender/blenkernel/intern/image.c | 14 ++++++++++++++ source/blender/blenkernel/intern/sequencer.c | 18 ++++++++++++++++++ source/blender/blenloader/intern/readfile.c | 12 ++++++++++-- 5 files changed, 47 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index d12b048bc96..dd7e06259bd 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -152,6 +152,9 @@ void BKE_image_pool_free(struct ImagePool *pool); struct ImBuf *BKE_image_pool_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, struct ImagePool *pool); void BKE_image_pool_release_ibuf(struct Image *ima, struct ImBuf *ibuf, struct ImagePool *pool); +/* set an alpha mode based on file extension */ +void BKE_image_alpha_mode_from_extension(struct Image *image); + /* returns a new image or NULL if it can't load */ struct Image *BKE_image_load(struct Main *bmain, const char *filepath); /* returns existing Image when filename/type is same (frame optional) */ diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index e3d9c513c5c..eef134a6872 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -356,6 +356,8 @@ typedef struct SeqLoadInfo { typedef struct Sequence *(*SeqLoadFunc)(struct bContext *, ListBase *, struct SeqLoadInfo *); struct Sequence *BKE_sequence_alloc(ListBase *lb, int cfra, int machine); + +void BKE_sequence_alpha_mode_from_extension(struct Sequence *seq); void BKE_sequence_init_colorspace(struct Sequence *seq); struct Sequence *BKE_sequencer_add_image_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load); diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index de85cb54cfd..3655afdf088 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -571,6 +571,20 @@ static void image_init_color_management(Image *ima) } } +void BKE_image_alpha_mode_from_extension(Image *image) +{ + if (BLI_testextensie(image->name, ".exr") || + BLI_testextensie(image->name, ".cin") || + BLI_testextensie(image->name, ".dpx") || + BLI_testextensie(image->name, ".hdr")) + { + image->alpha_mode = IMA_ALPHA_PREMUL; + } + else { + image->alpha_mode = IMA_ALPHA_STRAIGHT; + } +} + Image *BKE_image_load(Main *bmain, const char *filepath) { Image *ima; diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 45393726add..68618287546 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -3955,6 +3955,24 @@ Sequence *BKE_sequence_alloc(ListBase *lb, int cfra, int machine) return seq; } +void BKE_sequence_alpha_mode_from_extension(Sequence *seq) +{ + if (seq->strip && seq->strip->stripdata) { + char *name = seq->strip->stripdata->name; + + if (BLI_testextensie(name, ".exr") || + BLI_testextensie(name, ".cin") || + BLI_testextensie(name, ".dpx") || + BLI_testextensie(name, ".hdr")) + { + seq->alpha_mode = IMA_ALPHA_PREMUL; + } + else { + seq->alpha_mode = IMA_ALPHA_STRAIGHT; + } + } +} + void BKE_sequence_init_colorspace(Sequence *seq) { if (seq->strip && seq->strip->stripdata) { diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 94dfb0cf399..4471e45be1d 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -8653,8 +8653,12 @@ static void do_versions(FileData *fd, Library *lib, Main *main) SEQ_BEGIN (scene->ed, seq) { - if (seq->flag & SEQ_MAKE_PREMUL) + if (seq->flag & SEQ_MAKE_PREMUL) { seq->alpha_mode = SEQ_ALPHA_STRAIGHT; + } + else { + BKE_sequence_alpha_mode_from_extension(seq); + } } SEQ_END @@ -8680,8 +8684,12 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } for (image = main->image.first; image; image = image->id.next) { - if (image->flag & IMA_DO_PREMUL) + if (image->flag & IMA_DO_PREMUL) { image->alpha_mode = IMA_ALPHA_STRAIGHT; + } + else { + BKE_image_alpha_mode_from_extension(image); + } image->flag &= ~IMA_DONE_TAG; } From 2d2164f10bffec1e523c95b4243f6cdf9560d1cf Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 19 Feb 2013 09:41:48 +0000 Subject: [PATCH 053/182] fix [#34295] Color picker brightness to infinity simply clamp the color to the buttons softrange since color conversion can cause the value to scale outside the intended button limits. --- .../editors/interface/interface_handlers.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index b166e532f84..7e2d79262fc 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -3404,6 +3404,19 @@ static int ui_do_but_NORMAL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut return WM_UI_HANDLER_CONTINUE; } +/* scales a vector so no axis exceeds max + * (could become BLI_math func) */ +static void clamp_axis_max_v3(float v[3], const float max) +{ + const float v_max = max_fff(v[0], v[1], v[2]); + if (v_max > max) { + mul_v3_fl(v, max / v_max); + if (v[0] > max) v[0] = max; + if (v[1] > max) v[1] = max; + if (v[2] > max) v[2] = max; + } +} + static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx, int my, const short shift) { float rgb[3]; @@ -3480,6 +3493,11 @@ static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx, if (color_profile && ((int)but->a1 != UI_GRAD_SV)) ui_block_to_scene_linear_v3(but->block, rgb); + /* clamp because with color conversion we can exceed range [#34295] */ + if ((int)but->a1 == UI_GRAD_V_ALT) { + clamp_axis_max_v3(rgb, but->softmax); + } + copy_v3_v3(data->vec, rgb); data->draglastx = mx; From fdb25a1d272633c32e32432499802d4793d37825 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 19 Feb 2013 09:51:32 +0000 Subject: [PATCH 054/182] Fix #34249: collapse edges crash blender with a specific mesh OpenMP block was using shared variable, which for sure leads to threading issues. --- source/blender/bmesh/intern/bmesh_operators.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index 98958596324..00f8dbe06bf 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -595,13 +595,13 @@ void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *UNUSED(op), const char hty const char flag_types[3] = {BM_VERT, BM_EDGE, BM_FACE}; - BMIter iter; BMElemF *ele; int i; #pragma omp parallel for schedule(dynamic) if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT) for (i = 0; i < 3; i++) { if (htype & flag_types[i]) { + BMIter iter; BM_ITER_MESH (ele, &iter, bm, iter_types[i]) { BMO_elem_flag_disable(bm, ele, oflag); } From c5e6a35e856ee9a4e459a863e8165cff5d969368 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 19 Feb 2013 10:10:09 +0000 Subject: [PATCH 055/182] Remove ztrans_hack. Looks like just keeping the angles compatible works well enough. --- .../editors/transform/transform_generics.c | 22 ++----------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index aa32518b489..9ee1d11a036 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -810,7 +810,6 @@ static void recalcData_view3d(TransInfo *t) float vec[3], up_axis[3]; float qrot[4]; float roll; - bool ztrans_hack = false; ebo = td->extra; copy_v3_v3(up_axis, td->axismtx[2]); @@ -825,25 +824,8 @@ static void recalcData_view3d(TransInfo *t) mul_m3_v3(t->mat, up_axis); } - /* "ztrans_hack" is a hacky compromise fix for two bug reports - * - [#33974] : When extruding/translating bones vertically, - * the roll of each bone in such vertical chains would - * flip between z-axis forward and z-axis backwards - * - [#34283] : For "normal" transforms, the original fix for [#33974] - * would cause manually-set roll values on horizontal and - * diagonal bones to constantly get reset to values the system - * deems "correct" (usually 180 degree flips of the manual version) - */ - if (t->mode == TFM_TRANSLATION) { - const float ZAXIS_REF[3] = {0.0f, 0.0f, 1.0f}; - float tdelta[3]; - - /* tdelta is the translation - enable this hack when it is z-axis movement */ - normalize_v3_v3(tdelta, t->values); - ztrans_hack = compare_v3v3(tdelta, ZAXIS_REF, 0.1f); - } - - roll = ED_rollBoneToVector(ebo, up_axis, ztrans_hack); + /* roll has a tendency to flip in certain orientations - [#34283], [#33974] */ + roll = ED_rollBoneToVector(ebo, up_axis, false); ebo->roll = angle_compat_rad(roll, ebo->roll); } } From 0f359c41ead3d1724b8b6e53bcff067137b219a6 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 19 Feb 2013 10:31:29 +0000 Subject: [PATCH 056/182] Style tweak - missing braces --- source/blender/editors/curve/editcurve.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index a72d3767b69..e736c494add 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -2034,11 +2034,12 @@ static int switch_direction_exec(bContext *C, wmOperator *UNUSED(op)) EditNurb *editnurb = cu->editnurb; Nurb *nu; - for (nu = editnurb->nurbs.first; nu; nu = nu->next) + for (nu = editnurb->nurbs.first; nu; nu = nu->next) { if (isNurbsel(nu)) { BKE_nurb_direction_switch(nu); keyData_switchDirectionNurb(cu, nu); } + } if (ED_curve_updateAnimPaths(obedit->data)) WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); From 0528162eb691e9d0de39b5f72c427a4d96542f64 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 19 Feb 2013 12:05:38 +0000 Subject: [PATCH 057/182] patch [#34320] Cross compiling with mingw-w64 on ubuntu from Martijn Berger (juicyfruit) applying since this is only corrects header case which is ignored on windows anyway. --- intern/cycles/util/util_dynlib.cpp | 2 +- intern/ghost/intern/GHOST_DropTargetWin32.cpp | 2 +- intern/utfconv/utf_winfunc.c | 2 +- source/blender/windowmanager/intern/wm_init_exit.c | 2 +- source/creator/creator.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/intern/cycles/util/util_dynlib.cpp b/intern/cycles/util/util_dynlib.cpp index 5836073a07a..3eaa16ab37d 100644 --- a/intern/cycles/util/util_dynlib.cpp +++ b/intern/cycles/util/util_dynlib.cpp @@ -22,7 +22,7 @@ #ifdef _WIN32 -#include +#include CCL_NAMESPACE_BEGIN diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.cpp b/intern/ghost/intern/GHOST_DropTargetWin32.cpp index 89e9a91b34c..5288b77a3c6 100644 --- a/intern/ghost/intern/GHOST_DropTargetWin32.cpp +++ b/intern/ghost/intern/GHOST_DropTargetWin32.cpp @@ -32,7 +32,7 @@ #include "GHOST_Debug.h" #include "GHOST_DropTargetWin32.h" -#include +#include #include "utf_winfunc.h" #include "utfconv.h" diff --git a/intern/utfconv/utf_winfunc.c b/intern/utfconv/utf_winfunc.c index 18f0e808562..77209313926 100644 --- a/intern/utfconv/utf_winfunc.c +++ b/intern/utfconv/utf_winfunc.c @@ -29,7 +29,7 @@ #include "utf_winfunc.h" #include -#include +#include #include diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index de0da3df868..da0c6dd2a63 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -33,7 +33,7 @@ #include #ifdef WIN32 -# include +# include #endif #include "MEM_guardedalloc.h" diff --git a/source/creator/creator.c b/source/creator/creator.c index 4b74e225ec4..d7b2d87ffe8 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -48,7 +48,7 @@ #endif #ifdef WIN32 -# include +# include # include "utfconv.h" #endif From f7848569063386b5925cb692652b584ea8765572 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 19 Feb 2013 13:15:34 +0000 Subject: [PATCH 058/182] make asserts that check for unit length vectors into a macro. this was really not nice logic to try to fit into an assert. --- source/blender/blenlib/BLI_math_base.h | 22 ++++++++++++++++++++- source/blender/blenlib/intern/math_geom.c | 5 +---- source/blender/blenlib/intern/math_vector.c | 19 +++++------------- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h index 94063c9a40a..639512f7433 100644 --- a/source/blender/blenlib/BLI_math_base.h +++ b/source/blender/blenlib/BLI_math_base.h @@ -217,5 +217,25 @@ extern double round(double x); double double_round(double x, int ndigits); -#endif /* __BLI_MATH_BASE_H__ */ +/* asserts, some math functions expect normalized inputs + * check the vector is unit length, or zero length (which can't be helped in some cases). + */ +#ifdef DEBUG +# define BLI_ASSERT_UNIT_EPSILON 0.0001f +# define BLI_ASSERT_UNIT_V3(v) { \ + const float _test_unit = len_squared_v3(v); \ + BLI_assert((fabsf(_test_unit - 1.0f) < BLI_ASSERT_UNIT_EPSILON) || \ + (fabsf(_test_unit) < BLI_ASSERT_UNIT_EPSILON)); \ +} (void)0 +# define BLI_ASSERT_UNIT_V2(v) { \ + const float _test_unit = len_squared_v2(v); \ + BLI_assert((fabsf(_test_unit - 1.0f) < BLI_ASSERT_UNIT_EPSILON) || \ + (fabsf(_test_unit) < BLI_ASSERT_UNIT_EPSILON)); \ +} (void)0 +#else +# define BLI_ASSERT_UNIT_V2(v) (void)0 +# define BLI_ASSERT_UNIT_V3(v) (void)0 +#endif + +#endif /* __BLI_MATH_BASE_H__ */ diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 810c15437dc..baca7bb8f8a 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -2001,10 +2001,7 @@ bool axis_dominant_v3_to_m3(float r_mat[3][3], const float normal[3]) float angle; /* double check they are normalized */ -#ifdef DEBUG - float test; - BLI_assert(fabsf((test = len_squared_v3(normal)) - 1.0f) < 0.0001f || fabsf(test) < 0.0001f); -#endif + BLI_ASSERT_UNIT_V3(normal); cross_v3_v3v3(axis, normal, up); angle = saacos(dot_v3v3(normal, up)); diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c index 490ed2a99fb..58d444f5794 100644 --- a/source/blender/blenlib/intern/math_vector.c +++ b/source/blender/blenlib/intern/math_vector.c @@ -235,11 +235,8 @@ float angle_signed_v2v2(const float v1[2], const float v2[2]) float angle_normalized_v3v3(const float v1[3], const float v2[3]) { /* double check they are normalized */ -#ifdef DEBUG - float test; - BLI_assert(fabsf((test = len_squared_v3(v1)) - 1.0f) < 0.0001f || fabsf(test) < 0.0001f); - BLI_assert(fabsf((test = len_squared_v3(v2)) - 1.0f) < 0.0001f || fabsf(test) < 0.0001f); -#endif + BLI_ASSERT_UNIT_V3(v1); + BLI_ASSERT_UNIT_V3(v2); /* this is the same as acos(dot_v3v3(v1, v2)), but more accurate */ if (dot_v3v3(v1, v2) < 0.0f) { @@ -258,11 +255,8 @@ float angle_normalized_v3v3(const float v1[3], const float v2[3]) float angle_normalized_v2v2(const float v1[2], const float v2[2]) { /* double check they are normalized */ -#ifdef DEBUG - float test; - BLI_assert(fabsf((test = len_squared_v2(v1)) - 1.0f) < 0.0001f || fabsf(test) < 0.0001f); - BLI_assert(fabsf((test = len_squared_v2(v2)) - 1.0f) < 0.0001f || fabsf(test) < 0.0001f); -#endif + BLI_ASSERT_UNIT_V2(v1); + BLI_ASSERT_UNIT_V2(v2); /* this is the same as acos(dot_v3v3(v1, v2)), but more accurate */ if (dot_v2v2(v1, v2) < 0.0f) { @@ -449,10 +443,7 @@ void rotate_normalized_v3_v3v3fl(float r[3], const float p[3], const float axis[ const float sintheta = sin(angle); /* double check they are normalized */ -#ifdef DEBUG - float test; - BLI_assert(fabsf((test = len_squared_v3(axis)) - 1.0f) < 0.0001f || fabsf(test) < 0.0001f); -#endif + BLI_ASSERT_UNIT_V3(axis); r[0] = ((costheta + (1 - costheta) * axis[0] * axis[0]) * p[0]) + (((1 - costheta) * axis[0] * axis[1] - axis[2] * sintheta) * p[1]) + From e3b2df5806037d5c466dd01c54ffb3fb53d2ab1c Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 19 Feb 2013 13:37:48 +0000 Subject: [PATCH 059/182] Fix #34315: memory leak cancelling move to layer operator, after change to make it not execute immediately when opening the popup. --- source/blender/editors/include/UI_interface.h | 2 +- .../editors/interface/interface_handlers.c | 2 +- .../blender/editors/interface/interface_intern.h | 2 +- .../blender/editors/interface/interface_regions.c | 2 +- .../blender/windowmanager/intern/wm_operators.c | 15 ++++++++++++--- 5 files changed, 16 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index eb74dd1e274..648f8bfd8dd 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -361,7 +361,7 @@ void uiPupMenuInvoke(struct bContext *C, const char *idname); /* popup registere * but allow using all button types and creating an own layout. */ typedef uiBlock * (*uiBlockCreateFunc)(struct bContext *C, struct ARegion *ar, void *arg1); -typedef void (*uiBlockCancelFunc)(void *arg1); +typedef void (*uiBlockCancelFunc)(struct bContext *C, void *arg1); void uiPupBlock(struct bContext *C, uiBlockCreateFunc func, void *arg); void uiPupBlockO(struct bContext *C, uiBlockCreateFunc func, void *arg, const char *opname, int opcontext); diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 7e2d79262fc..017ab559911 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -7159,7 +7159,7 @@ static int ui_handler_popup(bContext *C, const wmEvent *event, void *userdata) WM_operator_name_call(C, temp.optype->idname, temp.opcontext, NULL); } else if (temp.cancel_func) - temp.cancel_func(temp.popup_arg); + temp.cancel_func(C, temp.popup_arg); } else { /* re-enable tooltips */ diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index eb7f09c7b34..b1e8b7b001e 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -429,7 +429,7 @@ struct uiPopupBlockHandle { int popup; void (*popup_func)(struct bContext *C, void *arg, int event); - void (*cancel_func)(void *arg); + void (*cancel_func)(struct bContext *C, void *arg); void *popup_arg; struct wmTimer *scrolltimer; diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 36717507072..03c127f33c8 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -2574,7 +2574,7 @@ static void operator_cb(bContext *C, void *arg, int retval) WM_operator_free(op); } -static void confirm_cancel_operator(void *opv) +static void confirm_cancel_operator(bContext *UNUSED(C), void *opv) { WM_operator_free(opv); } diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 9939e6b69ba..357da5c8f4b 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1243,7 +1243,7 @@ wmOperator *WM_operator_last_redo(const bContext *C) return op; } -static void wm_block_redo_cb(bContext *C, void *arg_op, int UNUSED(arg_event)) +static void wm_block_redo_cb(bContext *C, void *arg_op, int arg_event) { wmOperator *op = arg_op; @@ -1260,6 +1260,15 @@ static void wm_block_redo_cb(bContext *C, void *arg_op, int UNUSED(arg_event)) } } +static void wm_block_redo_cancel_cb(bContext *C, void *arg_op) +{ + wmOperator *op = arg_op; + + /* if operator never got executed, free it */ + if (op != WM_operator_last_redo(C)) + WM_operator_free(op); +} + static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op) { wmOperator *op = arg_op; @@ -1402,7 +1411,7 @@ static uiBlock *wm_operator_ui_create(bContext *C, ARegion *ar, void *userData) return block; } -static void wm_operator_ui_popup_cancel(void *userData) +static void wm_operator_ui_popup_cancel(struct bContext *UNUSED(C), void *userData) { wmOpPopUp *data = userData; if (data->free_op && data->op) { @@ -1452,7 +1461,7 @@ static int wm_operator_props_popup_ex(bContext *C, wmOperator *op, const int do_ if (!(U.uiflag & USER_GLOBALUNDO)) return WM_operator_props_dialog_popup(C, op, 15 * UI_UNIT_X, UI_UNIT_Y); - uiPupBlock(C, wm_block_create_redo, op); + uiPupBlockEx(C, wm_block_create_redo, NULL, wm_block_redo_cancel_cb, op); if (do_call) wm_block_redo_cb(C, op, 0); From f5bdd591e989b7c99509473cdff1053e456f78b3 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 19 Feb 2013 13:38:36 +0000 Subject: [PATCH 060/182] Remove define which is not actually needed and could have been conflicted with one from IMB_colormanagement.h --- source/blender/imbuf/intern/IMB_colormanagement_intern.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/blender/imbuf/intern/IMB_colormanagement_intern.h b/source/blender/imbuf/intern/IMB_colormanagement_intern.h index ba9e20ac411..e2a8e1e3442 100644 --- a/source/blender/imbuf/intern/IMB_colormanagement_intern.h +++ b/source/blender/imbuf/intern/IMB_colormanagement_intern.h @@ -33,8 +33,6 @@ #include "DNA_listBase.h" -#define BCM_CONFIG_FILE "config.ocio" - struct OCIO_ConstProcessorRcPtr; struct ImBuf; From 54311fde29aef9494a6b752786a8d5476867a174 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 19 Feb 2013 13:41:53 +0000 Subject: [PATCH 061/182] revert own commit r54625, broke autocomplete. --- .../editors/space_text/text_autocomplete.c | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c index 62e5728bd3c..94977fc5f0f 100644 --- a/source/blender/editors/space_text/text_autocomplete.c +++ b/source/blender/editors/space_text/text_autocomplete.c @@ -162,28 +162,23 @@ static GHash *text_autocomplete_build(Text *text) gh = BLI_ghash_str_new(__func__); for (linep = text->lines.first; linep; linep = linep->next) { - size_t i_start = 0; - size_t i_end = 0; - size_t i_step = 0; + int i_start = 0; + int i_end = 0; while (i_start < linep->len) { /* seek identifier beginning */ - while ((i_start < linep->len) && - (!text_check_identifier_nodigit(BLI_str_utf8_as_unicode_step(&linep->line[i_start], &i_step)))) - { - i_start = i_step; + while (i_start < linep->len && !text_check_identifier_nodigit(linep->line[i_start])) { + i_start++; } i_end = i_start; - while ((i_end < linep->len) && - (!text_check_identifier(BLI_str_utf8_as_unicode_step(&linep->line[i_end], &i_step)))) - { - i_end = i_step; + while (i_end < linep->len && text_check_identifier(linep->line[i_end])) { + i_end++; } if ((i_start != i_end) && /* check we're at the beginning of a line or that the previous char is not an identifier - * this prevents digits from being added */ - ((i_start < 1) || !text_check_identifier(BLI_str_utf8_as_unicode(&linep->line[i_start - 1])))) + * this prevents digits from being added */ + ((i_start < 1) || !text_check_identifier(linep->line[i_start - 1]))) { char *str_sub = &linep->line[i_start]; const int choice_len = i_end - i_start; From ba375ae699b9f58b0e82276790471a68e438311e Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 19 Feb 2013 13:41:58 +0000 Subject: [PATCH 062/182] Small correction to make strict compiler setup be happy --- source/blender/windowmanager/intern/wm_operators.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 357da5c8f4b..9562f6d698f 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1243,7 +1243,7 @@ wmOperator *WM_operator_last_redo(const bContext *C) return op; } -static void wm_block_redo_cb(bContext *C, void *arg_op, int arg_event) +static void wm_block_redo_cb(bContext *C, void *arg_op, int UNUSED(arg_event)) { wmOperator *op = arg_op; From 917252175dce5d4425de76763b2b4d4c88391283 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 19 Feb 2013 14:14:37 +0000 Subject: [PATCH 063/182] internal: increase error threshold for normalize assert since normals converted from shorts are not always exactly unit length. --- source/blender/blenlib/BLI_math_base.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h index 639512f7433..aa4e697b48b 100644 --- a/source/blender/blenlib/BLI_math_base.h +++ b/source/blender/blenlib/BLI_math_base.h @@ -221,7 +221,8 @@ double double_round(double x, int ndigits); * check the vector is unit length, or zero length (which can't be helped in some cases). */ #ifdef DEBUG -# define BLI_ASSERT_UNIT_EPSILON 0.0001f +/* note: 0.0001 is too small becaues normals may be converted from short's: see [#34322] */ +# define BLI_ASSERT_UNIT_EPSILON 0.0002f # define BLI_ASSERT_UNIT_V3(v) { \ const float _test_unit = len_squared_v3(v); \ BLI_assert((fabsf(_test_unit - 1.0f) < BLI_ASSERT_UNIT_EPSILON) || \ From bc52cb1be305998ca93d3a344963727b5ad2c979 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 19 Feb 2013 14:19:53 +0000 Subject: [PATCH 064/182] fix for apply rotation/location failing for surface object types (were recognized as 2d curves). --- source/blender/editors/object/object_transform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 9dd34623739..13523154d62 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -424,7 +424,7 @@ static int apply_objects_internal(bContext *C, ReportList *reports, int apply_lo cu = ob->data; - if (!(cu->flag & CU_3D) && (apply_rot || apply_loc)) { + if (((ob->type == OB_CURVE) && !(cu->flag & CU_3D)) && (apply_rot || apply_loc)) { BKE_report(reports, RPT_ERROR, "Neither rotation nor location could be applied to a 2D curve, doing nothing"); change = 0; From 9f0dffb202c2db3476199ce27865541cf218931e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 19 Feb 2013 14:36:26 +0000 Subject: [PATCH 065/182] fix [#34033] Mesh customdata settings are missing Mesh edge number buttons were removed when the custom-data layers weren't present. More of a usability regression than a bug. --- .../editors/space_view3d/view3d_buttons.c | 39 ++++++++----------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index ec716284bf3..65fe9dba258 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -222,6 +222,9 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float } } } + else { + totedgedata = bm->totedgesel; + } /* check for defgroups */ if (evedef) @@ -427,26 +430,16 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float /* Meshes... */ if (meshdata) { if (totedgedata) { - Mesh *me = ob->data; - BMEditMesh *em = me->edit_btmesh; - BMesh *bm = em->bm; - - const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT); - const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE); - - if (cd_edge_crease_offset != -1) { - uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, - totedgedata == 1 ? IFACE_("Crease:") : IFACE_("Mean Crease:"), - 0, yi -= buth + but_margin, 200, buth, - &(tfp->ve_median[M_CREASE]), 0.0, 1.0, 1, 3, TIP_("Weight used by SubSurf modifier")); - } - - if (cd_edge_bweight_offset != -1) { - uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, - totedgedata == 1 ? IFACE_("Bevel Weight:") : IFACE_("Mean Bevel Weight:"), - 0, yi -= buth + but_margin, 200, buth, - &(tfp->ve_median[M_WEIGHT]), 0.0, 1.0, 1, 3, TIP_("Weight used by Bevel modifier")); - } + /* customdata layer added on demand */ + uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, + totedgedata == 1 ? IFACE_("Crease:") : IFACE_("Mean Crease:"), + 0, yi -= buth + but_margin, 200, buth, + &(tfp->ve_median[M_CREASE]), 0.0, 1.0, 1, 3, TIP_("Weight used by SubSurf modifier")); + /* customdata layer added on demand */ + uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, + totedgedata == 1 ? IFACE_("Bevel Weight:") : IFACE_("Mean Bevel Weight:"), + 0, yi -= buth + but_margin, 200, buth, + &(tfp->ve_median[M_WEIGHT]), 0.0, 1.0, 1, 3, TIP_("Weight used by Bevel modifier")); } if (totskinradius) { uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, @@ -529,7 +522,8 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float } if (median[M_CREASE] != 0.0f) { - const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE); + const int cd_edge_crease_offset = (BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_CREASE), + CustomData_get_offset(&bm->edata, CD_CREASE)); const float sca = compute_scale_factor(ve_median[M_CREASE], median[M_CREASE]); BMEdge *eed; @@ -561,7 +555,8 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float } if (median[M_WEIGHT] != 0.0f) { - const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT); + const int cd_edge_bweight_offset = (BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_BWEIGHT), + CustomData_get_offset(&bm->edata, CD_BWEIGHT)); const float sca = compute_scale_factor(ve_median[M_WEIGHT], median[M_WEIGHT]); BMEdge *eed; From c3b96f33af3d5325b9475b07ef8204e1aa4fcd43 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 19 Feb 2013 15:15:34 +0000 Subject: [PATCH 066/182] internal: add include so blender builds against libpng1.6 --- intern/smoke/intern/WAVELET_NOISE.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/intern/smoke/intern/WAVELET_NOISE.h b/intern/smoke/intern/WAVELET_NOISE.h index fce901b68aa..1b2fbfab58c 100644 --- a/intern/smoke/intern/WAVELET_NOISE.h +++ b/intern/smoke/intern/WAVELET_NOISE.h @@ -45,6 +45,8 @@ #include +#include + #ifdef WIN32 #include #define isnan _isnan From 1a620ac9c331cd9a9eb5a378a22818163fd61ab4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 19 Feb 2013 15:21:12 +0000 Subject: [PATCH 067/182] bpy.props.RemoveProperty() py api docs were still incorrect. --- source/blender/python/intern/bpy_props.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index 7ffce0e9a93..830c2c8de3a 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -2796,13 +2796,13 @@ static PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject } PyDoc_STRVAR(BPy_RemoveProperty_doc, -".. function:: RemoveProperty(cls, attr)\n" +".. function:: RemoveProperty(cls, attr="")\n" "\n" " Removes a dynamically defined property.\n" "\n" -" :arg cls: The class containing the property.\n" +" :arg cls: The class containing the property (must be a positional argument).\n" " :type cls: type\n" -" :arg attr: Property name.\n" +" :arg attr: Property name (must be passed as a keyword).\n" " :type attr: string\n" "\n" ".. note:: Typically this function doesn't need to be accessed directly.\n" @@ -2821,7 +2821,7 @@ static PyObject *BPy_RemoveProperty(PyObject *self, PyObject *args, PyObject *kw return ret; } else if (PyTuple_GET_SIZE(args) > 1) { - PyErr_SetString(PyExc_ValueError, "all args must be keywords"); + PyErr_SetString(PyExc_ValueError, "expected one positional arg, one keyword arg"); return NULL; } From 04d628a5b510e3e8f0c8cf67f07af021aa3f46cf Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Tue, 19 Feb 2013 15:45:56 +0000 Subject: [PATCH 068/182] Another huge bunch of new UI translations (some reported by Leon Cheung, thanks!)... --- source/blender/blenkernel/intern/context.c | 4 +- .../blender/editors/gpencil/gpencil_paint.c | 19 +- .../editors/interface/interface_templates.c | 41 ++-- source/blender/editors/mesh/editface.c | 4 +- source/blender/editors/mesh/editmesh_knife.c | 15 +- .../blender/editors/mesh/editmesh_loopcut.c | 10 +- source/blender/editors/mesh/editmesh_tools.c | 25 ++- .../editors/space_buttons/buttons_context.c | 7 +- .../editors/space_view3d/view3d_buttons.c | 26 +-- .../editors/space_view3d/view3d_draw.c | 40 ++-- source/blender/editors/transform/transform.c | 191 +++++++++--------- .../editors/transform/transform_constraints.c | 28 +-- .../editors/transform/transform_generics.c | 16 +- .../transform/transform_orientations.c | 10 +- source/blender/editors/uvedit/CMakeLists.txt | 5 + source/blender/editors/uvedit/SConscript | 9 +- .../blender/editors/uvedit/uvedit_buttons.c | 10 +- 17 files changed, 251 insertions(+), 209 deletions(-) diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index a45afa5e69a..a9e3d52f223 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -48,6 +48,8 @@ #include "BLI_threads.h" #include "BLI_utildefines.h" +#include "BLF_translation.h" + #include "BKE_context.h" #include "BKE_main.h" #include "BKE_screen.h" @@ -851,7 +853,7 @@ void CTX_wm_operator_poll_msg_set(bContext *C, const char *msg) const char *CTX_wm_operator_poll_msg_get(bContext *C) { - return C->wm.operator_poll_msg; + return IFACE_(C->wm.operator_poll_msg); } /* data context */ diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 41ef4bd0b95..8cd2bd861bc 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -39,6 +39,8 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +#include "BLF_translation.h" + #include "PIL_time.h" #include "BKE_gpencil.h" @@ -1457,28 +1459,27 @@ static void gpencil_draw_status_indicators(tGPsdata *p) case GP_STATUS_PAINTING: /* only print this for paint-sessions, otherwise it gets annoying */ if (GPENCIL_SKETCH_SESSIONS_ON(p->scene)) - ED_area_headerprint(p->sa, "Grease Pencil: Drawing/erasing stroke... Release to end stroke"); + ED_area_headerprint(p->sa, IFACE_("Grease Pencil: Drawing/erasing stroke... Release to end stroke")); break; case GP_STATUS_IDLING: /* print status info */ switch (p->paintmode) { case GP_PAINTMODE_ERASER: - ED_area_headerprint(p->sa, - "Grease Pencil Erase Session: Hold and drag LMB or RMB to erase |" - " ESC/Enter to end"); + ED_area_headerprint(p->sa, IFACE_("Grease Pencil Erase Session: Hold and drag LMB or RMB to erase |" + " ESC/Enter to end")); break; case GP_PAINTMODE_DRAW_STRAIGHT: - ED_area_headerprint(p->sa, "Grease Pencil Line Session: Hold and drag LMB to draw | " - "ESC/Enter to end"); + ED_area_headerprint(p->sa, IFACE_("Grease Pencil Line Session: Hold and drag LMB to draw | " + "ESC/Enter to end")); break; case GP_PAINTMODE_DRAW: - ED_area_headerprint(p->sa, "Grease Pencil Freehand Session: Hold and drag LMB to draw | " - "ESC/Enter to end"); + ED_area_headerprint(p->sa, IFACE_("Grease Pencil Freehand Session: Hold and drag LMB to draw | " + "ESC/Enter to end")); break; default: /* unhandled future cases */ - ED_area_headerprint(p->sa, "Grease Pencil Session: ESC/Enter to end"); + ED_area_headerprint(p->sa, IFACE_("Grease Pencil Session: ESC/Enter to end")); break; } break; diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 5805806a9a9..a9227158a20 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -542,8 +542,8 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str /* Due to space limit in UI - skip the "open" icon for packed data, and allow to unpack. Only for images, sound and fonts */ if (id && BKE_pack_check(id)) { - - but = uiDefIconButO(block, BUT, "FILE_OT_unpack_item", WM_OP_INVOKE_REGION_WIN, ICON_PACKAGE, 0, 0, UI_UNIT_X, UI_UNIT_Y, "Packed File"); + but = uiDefIconButO(block, BUT, "FILE_OT_unpack_item", WM_OP_INVOKE_REGION_WIN, ICON_PACKAGE, 0, 0, + UI_UNIT_X, UI_UNIT_Y, TIP_("Packed File, click to unpack")); uiButGetOperatorPtrRNA(but); RNA_string_set(but->opptr, "id_name", id->name + 2); @@ -691,7 +691,7 @@ void uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, co uiItemL(row, text, ICON_NONE); } else - uiItemL(row, "ID-Block:", ICON_NONE); + uiItemL(row, IFACE_("ID-Block:"), ICON_NONE); /* ID-Type Selector - just have a menu of icons */ /* FIXME: the icon-only setting doesn't work when we supply a blank name */ @@ -735,7 +735,7 @@ void uiTemplatePathBuilder(uiLayout *layout, PointerRNA *ptr, const char *propna /************************ Modifier Template *************************/ -#define ERROR_LIBDATA_MESSAGE "Can't edit external libdata" +#define ERROR_LIBDATA_MESSAGE IFACE_("Can't edit external libdata") static void modifiers_setOnCage(bContext *C, void *ob_v, void *md_v) { @@ -835,8 +835,8 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob, block = uiLayoutGetBlock(row); /* VIRTUAL MODIFIER */ /* XXX this is not used now, since these cannot be accessed via RNA */ - BLI_snprintf(str, sizeof(str), "%s parent deform", md->name); - uiDefBut(block, LABEL, 0, str, 0, 0, 185, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "Modifier name"); + BLI_snprintf(str, sizeof(str), IFACE_("%s parent deform"), md->name); + uiDefBut(block, LABEL, 0, str, 0, 0, 185, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Modifier name")); but = uiDefBut(block, BUT, 0, IFACE_("Make Real"), 0, 0, 80, 16, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Convert virtual modifier to a real modifier")); @@ -943,18 +943,22 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob, if (!(ob->mode & OB_MODE_PARTICLE_EDIT) && psys->pathcache) { if (ELEM(psys->part->ren_as, PART_DRAW_GR, PART_DRAW_OB)) - uiItemO(row, "Convert", ICON_NONE, "OBJECT_OT_duplicates_make_real"); + uiItemO(row, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Convert"), ICON_NONE, + "OBJECT_OT_duplicates_make_real"); else if (psys->part->ren_as == PART_DRAW_PATH) - uiItemO(row, "Convert", ICON_NONE, "OBJECT_OT_modifier_convert"); + uiItemO(row, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Convert"), ICON_NONE, + "OBJECT_OT_modifier_convert"); } } else { uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT); - uiItemEnumO(row, "OBJECT_OT_modifier_apply", IFACE_("Apply"), 0, "apply_as", MODIFIER_APPLY_DATA); + uiItemEnumO(row, "OBJECT_OT_modifier_apply", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Apply"), + 0, "apply_as", MODIFIER_APPLY_DATA); if (modifier_isSameTopology(md) && !modifier_isNonGeometrical(md)) { - uiItemEnumO(row, "OBJECT_OT_modifier_apply", IFACE_("Apply as Shape Key"), 0, - "apply_as", MODIFIER_APPLY_SHAPE); + uiItemEnumO(row, "OBJECT_OT_modifier_apply", + CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Apply as Shape Key"), + 0, "apply_as", MODIFIER_APPLY_SHAPE); } } @@ -964,7 +968,8 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob, if (!ELEM5(md->type, eModifierType_Fluidsim, eModifierType_Softbody, eModifierType_ParticleSystem, eModifierType_Cloth, eModifierType_Smoke)) { - uiItemO(row, IFACE_("Copy"), ICON_NONE, "OBJECT_OT_modifier_copy"); + uiItemO(row, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Copy"), ICON_NONE, + "OBJECT_OT_modifier_copy"); } } @@ -1086,10 +1091,10 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *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)); + BLI_strncpy(typestr, (con->type == CONSTRAINT_TYPE_NULL) ? IFACE_("Null") : IFACE_("Unknown"), sizeof(typestr)); } else - BLI_strncpy(typestr, cti->name, sizeof(typestr)); + BLI_strncpy(typestr, IFACE_(cti->name), sizeof(typestr)); /* determine whether constraint is proxy protected or not */ if (BKE_proxylocked_constraints_owner(ob, pchan)) @@ -1194,7 +1199,7 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con) /* Set but-locks for protected settings (magic numbers are used here!) */ if (proxy_protected) - uiBlockSetButLock(block, 1, "Cannot edit Proxy-Protected Constraint"); + uiBlockSetButLock(block, 1, IFACE_("Cannot edit Proxy-Protected Constraint")); /* Draw constraint data */ if ((con->flag & CONSTRAINT_EXPAND) == 0) { @@ -1478,7 +1483,7 @@ static void colorband_buttons_large(uiLayout *layout, uiBlock *block, ColorBand RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRampElement, cbd, &ptr); row = uiLayoutRow(layout, FALSE); - uiItemR(row, &ptr, "position", 0, "Pos", ICON_NONE); + uiItemR(row, &ptr, "position", 0, IFACE_("Pos"), ICON_NONE); bt = block->buttons.last; uiButSetFunc(bt, colorband_update_cb, bt, coba); @@ -2480,8 +2485,8 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co /* validate arguments */ /* Forbid default UI_UL_DEFAULT_CLASS_NAME list class without a custom list_id! */ if (!strcmp(UI_UL_DEFAULT_CLASS_NAME, listtype_name) && !(list_id && list_id[0])) { - RNA_warning("template_list using default '" UI_UL_DEFAULT_CLASS_NAME - "' UIList class must provide a custom list_id"); + RNA_warning("template_list using default '%s' UIList class must provide a custom list_id", + UI_UL_DEFAULT_CLASS_NAME); return; } diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index 3fbfaabbc0d..7ac27e038a4 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -34,6 +34,8 @@ #include "BLI_math.h" #include "BLI_edgehash.h" +#include "BLF_translation.h" + #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -429,7 +431,7 @@ void seam_mark_clear_tface(Scene *scene, short mode) if (me == 0 || me->totpoly == 0) return; if (mode == 0) - mode = pupmenu("Seams %t|Mark Border Seam %x1|Clear Seam %x2"); + mode = pupmenu(IFACE_("Seams %t|Mark Border Seam %x1|Clear Seam %x2")); if (mode != 1 && mode != 2) return; diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index bc7fe783e78..98fa9d10ab9 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -41,6 +41,8 @@ #include "BLI_smallhash.h" #include "BLI_memarena.h" +#include "BLF_translation.h" + #include "BKE_DerivedMesh.h" #include "BKE_context.h" @@ -215,12 +217,13 @@ static void knife_update_header(bContext *C, KnifeTool_OpData *kcd) #define HEADER_LENGTH 190 char header[HEADER_LENGTH]; - BLI_snprintf(header, HEADER_LENGTH, "LMB: define cut lines, Return/Spacebar: confirm, Esc or RMB: cancel, E: new cut, Ctrl: midpoint snap (%s), " - "Shift: ignore snap (%s), C: angle constrain (%s), Z: cut through (%s)", - kcd->snap_midpoints ? "On" : "Off", - kcd->ignore_edge_snapping ? "On" : "Off", - kcd->angle_snapping ? "On" : "Off", - kcd->cut_through ? "On" : "Off"); + BLI_snprintf(header, HEADER_LENGTH, IFACE_("LMB: define cut lines, Return/Spacebar: confirm, Esc or RMB: cancel, " + "E: new cut, Ctrl: midpoint snap (%s), Shift: ignore snap (%s), " + "C: angle constrain (%s), Z: cut through (%s)"), + kcd->snap_midpoints ? IFACE_("On") : IFACE_("Off"), + kcd->ignore_edge_snapping ? IFACE_("On") : IFACE_("Off"), + kcd->angle_snapping ? IFACE_("On") : IFACE_("Off"), + kcd->cut_through ? IFACE_("On") : IFACE_("Off")); ED_area_headerprint(CTX_wm_area(C), header); } diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index d1373363992..83542915ec2 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -37,6 +37,8 @@ #include "BLI_blenlib.h" #include "BLI_math.h" +#include "BLF_translation.h" + #include "BKE_context.h" #include "BKE_modifier.h" #include "BKE_report.h" @@ -411,10 +413,8 @@ static int ringcut_invoke(bContext *C, wmOperator *op, wmEvent *evt) lcd->eed = edge; ringsel_find_edge(lcd, 1); } - ED_area_headerprint(sa, - "Select a ring to be cut, " - "use mouse-wheel or page-up/down for number of cuts, " - "Hold Alt for smooth"); + ED_area_headerprint(sa, IFACE_("Select a ring to be cut, use mouse-wheel or page-up/down for number of cuts, " + "hold Alt for smooth")); return OPERATOR_RUNNING_MODAL; } @@ -543,7 +543,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, wmEvent *event) if (show_cuts) { char buf[64]; - BLI_snprintf(buf, sizeof(buf), "Number of Cuts: %d, Smooth: %.2f (Alt)", cuts, smoothness); + BLI_snprintf(buf, sizeof(buf), IFACE_("Number of Cuts: %d, Smooth: %.2f (Alt)"), cuts, smoothness); ED_area_headerprint(CTX_wm_area(C), buf); } diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 4957d498e98..3dd9adc264b 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -47,6 +47,8 @@ #include "BLI_math.h" #include "BLI_rand.h" +#include "BLF_translation.h" + #include "BKE_material.h" #include "BKE_context.h" #include "BKE_depsgraph.h" @@ -4673,9 +4675,10 @@ typedef struct { static void edbm_bevel_update_header(wmOperator *op, bContext *C) { #ifdef NEW_BEVEL - static char str[] = "Confirm: Enter/LClick, Cancel: (Esc/RMB), offset: %s, segments: %d"; + const char *str = IFACE_("Confirm: Enter/LClick, Cancel: (Esc/RMB), Offset: %s, Segments: %d"); #else - static char str[] = "Confirm: Enter/LClick, Cancel: (Esc/RMB), factor: %s, Use Dist (D): %s: Use Even (E): %s"; + const char *str = IFACE_("Confirm: Enter/LClick, Cancel: (Esc/RMB), Factor: %s, Use Dist (D): %s, " + "Use Even (E): %s"); BevelData *opdata = op->customdata; #endif @@ -4698,8 +4701,8 @@ static void edbm_bevel_update_header(wmOperator *op, bContext *C) BLI_snprintf(factor_str, NUM_STR_REP_LEN, "%f", RNA_float_get(op->ptr, "percent")); BLI_snprintf(msg, HEADER_LENGTH, str, factor_str, - RNA_boolean_get(op->ptr, "use_dist") ? "On" : "Off", - RNA_boolean_get(op->ptr, "use_even") ? "On" : "Off" + RNA_boolean_get(op->ptr, "use_dist") ? IFACE_("On") : IFACE_("Off"), + RNA_boolean_get(op->ptr, "use_even") ? IFACE_("On") : IFACE_("Off") ); #endif @@ -5212,12 +5215,8 @@ static void edbm_inset_update_header(wmOperator *op, bContext *C) { InsetData *opdata = op->customdata; - static const char str[] = "Confirm: Enter/LClick, " - "Cancel: (Esc/RClick), " - "thickness: %s, " - "depth (Ctrl to tweak): %s (%s), " - "Outset (O): (%s), " - "Boundary (B): (%s)"; + const char *str = IFACE_("Confirm: Enter/LClick, Cancel: (Esc/RClick), Thickness: %s, " + "Depth (Ctrl to tweak): %s (%s), Outset (O): (%s), Boundary (B): (%s)"); char msg[HEADER_LENGTH]; ScrArea *sa = CTX_wm_area(C); @@ -5233,9 +5232,9 @@ static void edbm_inset_update_header(wmOperator *op, bContext *C) BLI_snprintf(msg, HEADER_LENGTH, str, flts_str, flts_str + NUM_STR_REP_LEN, - opdata->modify_depth ? "On" : "Off", - RNA_boolean_get(op->ptr, "use_outset") ? "On" : "Off", - RNA_boolean_get(op->ptr, "use_boundary") ? "On" : "Off" + opdata->modify_depth ? IFACE_("On") : IFACE_("Off"), + RNA_boolean_get(op->ptr, "use_outset") ? IFACE_("On") : IFACE_("Off"), + RNA_boolean_get(op->ptr, "use_boundary") ? IFACE_("On") : IFACE_("Off") ); ED_area_headerprint(sa, msg); diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index 2a5b64cd6ed..0bdae9e32f4 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -36,6 +36,8 @@ #include "BLI_listbase.h" #include "BLI_utildefines.h" +#include "BLF_translation.h" + #include "DNA_armature_types.h" #include "DNA_lamp_types.h" #include "DNA_material_types.h" @@ -1028,7 +1030,8 @@ void buttons_context_draw(const bContext *C, uiLayout *layout) block = uiLayoutGetBlock(row); uiBlockSetEmboss(block, UI_EMBOSSN); - but = uiDefIconButBitC(block, ICONTOG, SB_PIN_CONTEXT, 0, ICON_UNPINNED, 0, 0, UI_UNIT_X, UI_UNIT_Y, &sbuts->flag, 0, 0, 0, 0, "Follow context or keep fixed datablock displayed"); + but = uiDefIconButBitC(block, ICONTOG, SB_PIN_CONTEXT, 0, ICON_UNPINNED, 0, 0, UI_UNIT_X, UI_UNIT_Y, &sbuts->flag, + 0, 0, 0, 0, IFACE_("Follow context or keep fixed datablock displayed")); uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */ uiButSetFunc(but, pin_cb, NULL, NULL); @@ -1068,7 +1071,7 @@ void buttons_context_register(ARegionType *art) pt = MEM_callocN(sizeof(PanelType), "spacetype buttons panel context"); strcpy(pt->idname, "BUTTONS_PT_context"); - strcpy(pt->label, "Context"); + strcpy(pt->label, N_("Context")); /* XXX C panels are not available through RNA (bpy.types)! */ pt->draw = buttons_panel_context; pt->flag = PNL_NO_HEADER; BLI_addtail(&art->paneltypes, pt); diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 65fe9dba258..bb286194992 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -403,28 +403,28 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float uiBlockBeginAlign(block); /* Should be no need to translate these. */ - but = uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "X:", 0, yi -= buth, 200, buth, + but = uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, IFACE_("X:"), 0, yi -= buth, 200, buth, &(tfp->ve_median[LOC_X]), -lim, lim, 10, RNA_TRANSLATION_PREC_DEFAULT, ""); uiButSetUnitType(but, PROP_UNIT_LENGTH); - but = uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Y:", 0, yi -= buth, 200, buth, + but = uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, IFACE_("Y:"), 0, yi -= buth, 200, buth, &(tfp->ve_median[LOC_Y]), -lim, lim, 10, RNA_TRANSLATION_PREC_DEFAULT, ""); uiButSetUnitType(but, PROP_UNIT_LENGTH); - but = uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Z:", 0, yi -= buth, 200, buth, + but = uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, IFACE_("Z:"), 0, yi -= buth, 200, buth, &(tfp->ve_median[LOC_Z]), -lim, lim, 10, RNA_TRANSLATION_PREC_DEFAULT, ""); uiButSetUnitType(but, PROP_UNIT_LENGTH); if (totcurvebweight == tot) { - uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "W:", 0, yi -= buth, 200, buth, + uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, IFACE_("W:"), 0, yi -= buth, 200, buth, &(tfp->ve_median[C_BWEIGHT]), 0.01, 100.0, 1, 3, ""); } uiBlockBeginAlign(block); uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, IFACE_("Global"), 0, yi -= buth + but_margin, 100, buth, - &v3d->flag, 0, 0, 0, 0, "Displays global values"); + &v3d->flag, 0, 0, 0, 0, TIP_("Displays global values")); uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, IFACE_("Local"), 100, yi, 100, buth, - &v3d->flag, 0, 0, 0, 0, "Displays local values"); + &v3d->flag, 0, 0, 0, 0, TIP_("Displays local values")); uiBlockEndAlign(block); /* Meshes... */ @@ -454,11 +454,11 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float } /* Curve... */ else if (totcurvedata == 1) { - uiDefButR(block, NUM, 0, "Weight", 0, yi -= buth + but_margin, 200, buth, + uiDefButR(block, NUM, 0, IFACE_("Weight"), 0, yi -= buth + but_margin, 200, buth, &data_ptr, "weight_softbody", 0, 0.0, 1.0, 1, 3, NULL); - uiDefButR(block, NUM, 0, "Radius", 0, yi -= buth + but_margin, 200, buth, + uiDefButR(block, NUM, 0, IFACE_("Radius"), 0, yi -= buth + but_margin, 200, buth, &data_ptr, "radius", 0, 0.0, 100.0, 1, 3, NULL); - uiDefButR(block, NUM, 0, "Tilt", 0, yi -= buth + but_margin, 200, buth, + uiDefButR(block, NUM, 0, IFACE_("Tilt"), 0, yi -= buth + but_margin, 200, buth, &data_ptr, "tilt", 0, -FLT_MAX, FLT_MAX, 1, 3, NULL); } else if (totcurvedata > 1) { @@ -476,7 +476,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float } /* Lattice... */ else if (totlattdata == 1) { - uiDefButR(block, NUM, 0, "Weight", 0, yi -= buth + but_margin, 200, buth, + uiDefButR(block, NUM, 0, IFACE_("Weight"), 0, yi -= buth + but_margin, 200, buth, &data_ptr, "weight_softbody", 0, 0.0, 1.0, 1, 3, NULL); } else if (totlattdata > 1) { @@ -1269,20 +1269,20 @@ void view3d_buttons_register(ARegionType *art) pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel object"); strcpy(pt->idname, "VIEW3D_PT_object"); - strcpy(pt->label, "Transform"); + strcpy(pt->label, N_("Transform")); /* XXX C panels not available through RNA (bpy.types)! */ pt->draw = view3d_panel_object; BLI_addtail(&art->paneltypes, pt); pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel gpencil"); strcpy(pt->idname, "VIEW3D_PT_gpencil"); - strcpy(pt->label, "Grease Pencil"); + strcpy(pt->label, N_("Grease Pencil")); /* XXX C panels are not available through RNA (bpy.types)! */ pt->draw_header = gpencil_panel_standard_header; pt->draw = gpencil_panel_standard; BLI_addtail(&art->paneltypes, pt); pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel vgroup"); strcpy(pt->idname, "VIEW3D_PT_vgroup"); - strcpy(pt->label, "Vertex Groups"); + strcpy(pt->label, N_("Vertex Groups")); /* XXX C panels are not available through RNA (bpy.types)! */ pt->draw = view3d_panel_vgroup; pt->poll = view3d_panel_vgroup_poll; BLI_addtail(&art->paneltypes, pt); diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index c41fb926ab0..a34b4c5157b 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -75,7 +75,9 @@ #include "BIF_glutil.h" #include "WM_api.h" + #include "BLF_api.h" +#include "BLF_translation.h" #include "ED_armature.h" #include "ED_keyframing.h" @@ -804,28 +806,28 @@ static const char *view3d_get_name(View3D *v3d, RegionView3D *rv3d) switch (rv3d->view) { case RV3D_VIEW_FRONT: - if (rv3d->persp == RV3D_ORTHO) name = "Front Ortho"; - else name = "Front Persp"; + if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Front Ortho"); + else name = IFACE_("Front Persp"); break; case RV3D_VIEW_BACK: - if (rv3d->persp == RV3D_ORTHO) name = "Back Ortho"; - else name = "Back Persp"; + if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Back Ortho"); + else name = IFACE_("Back Persp"); break; case RV3D_VIEW_TOP: - if (rv3d->persp == RV3D_ORTHO) name = "Top Ortho"; - else name = "Top Persp"; + if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Top Ortho"); + else name = IFACE_("Top Persp"); break; case RV3D_VIEW_BOTTOM: - if (rv3d->persp == RV3D_ORTHO) name = "Bottom Ortho"; - else name = "Bottom Persp"; + if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Bottom Ortho"); + else name = IFACE_("Bottom Persp"); break; case RV3D_VIEW_RIGHT: - if (rv3d->persp == RV3D_ORTHO) name = "Right Ortho"; - else name = "Right Persp"; + if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Right Ortho"); + else name = IFACE_("Right Persp"); break; case RV3D_VIEW_LEFT: - if (rv3d->persp == RV3D_ORTHO) name = "Left Ortho"; - else name = "Left Persp"; + if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Left Ortho"); + else name = IFACE_("Left Persp"); break; default: @@ -833,14 +835,14 @@ static const char *view3d_get_name(View3D *v3d, RegionView3D *rv3d) if ((v3d->camera) && (v3d->camera->type == OB_CAMERA)) { Camera *cam; cam = v3d->camera->data; - name = (cam->type != CAM_ORTHO) ? "Camera Persp" : "Camera Ortho"; + name = (cam->type != CAM_ORTHO) ? IFACE_("Camera Persp") : IFACE_("Camera Ortho"); } else { - name = "Object as Camera"; + name = IFACE_("Object as Camera"); } } else { - name = (rv3d->persp == RV3D_ORTHO) ? "User Ortho" : "User Persp"; + name = (rv3d->persp == RV3D_ORTHO) ? IFACE_("User Ortho") : IFACE_("User Persp"); } break; } @@ -855,7 +857,7 @@ static void draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect) char tmpstr[24]; if (v3d->localvd) { - BLI_snprintf(tmpstr, sizeof(tmpstr), "%s (Local)", name); + BLI_snprintf(tmpstr, sizeof(tmpstr), IFACE_("%s (Local)"), name); name = tmpstr; } @@ -918,7 +920,7 @@ static void draw_selected_name(Scene *scene, Object *ob, rcti *rect) if (kb) { BLI_snprintf(shapes, sizeof(shapes), ": %s ", kb->name); if (ob->shapeflag == OB_SHAPE_LOCK) { - strcat(shapes, " (Pinned)"); + strcat(shapes, IFACE_(" (Pinned)")); } } } @@ -2846,11 +2848,11 @@ static void draw_viewport_fps(Scene *scene, rcti *rect) /* is this more then half a frame behind? */ if (fps + 0.5f < (float)(FPS)) { UI_ThemeColor(TH_REDALERT); - BLI_snprintf(printable, sizeof(printable), "fps: %.2f", fps); + BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %.2f"), fps); } else { UI_ThemeColor(TH_TEXT_HI); - BLI_snprintf(printable, sizeof(printable), "fps: %i", (int)(fps + 0.5f)); + BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %i"), (int)(fps + 0.5f)); } BLF_draw_default_ascii(rect->xmin + U.widget_unit, rect->ymax - U.widget_unit, 0.0f, printable, sizeof(printable)); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index befeb2bce25..1a7a425fbc9 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -94,6 +94,7 @@ #include "RNA_access.h" #include "BLF_api.h" +#include "BLF_translation.h" #include "transform.h" @@ -790,22 +791,29 @@ static void transform_event_xyz_constraint(TransInfo *t, short key_type, char cm if (!(t->flag & T_NO_CONSTRAINT)) { int constraint_axis, constraint_plane; int edit_2d = (t->flag & T_2D_EDIT); - char msg1[] = "along _"; - char msg2[] = "along %s _"; - char msg3[] = "locking %s _"; + const char *msg1 = "", *msg2 = "", *msg3 = ""; char axis; /* Initialize */ switch (key_type) { case XKEY: + msg1 = IFACE_("along X"); + msg2 = IFACE_("along %s X"); + msg3 = IFACE_("locking %s X"); axis = 'X'; constraint_axis = CON_AXIS0; break; case YKEY: + msg1 = IFACE_("along Y"); + msg2 = IFACE_("along %s Y"); + msg3 = IFACE_("locking %s Y"); axis = 'Y'; constraint_axis = CON_AXIS1; break; case ZKEY: + msg1 = IFACE_("along Z"); + msg2 = IFACE_("along %s Z"); + msg3 = IFACE_("locking %s Z"); axis = 'Z'; constraint_axis = CON_AXIS2; break; @@ -813,9 +821,6 @@ static void transform_event_xyz_constraint(TransInfo *t, short key_type, char cm /* Invalid key */ return; } - msg1[sizeof(msg1) - 2] = axis; - msg2[sizeof(msg2) - 2] = axis; - msg3[sizeof(msg3) - 2] = axis; constraint_plane = ((CON_AXIS0 | CON_AXIS1 | CON_AXIS2) & (~constraint_axis)); if (edit_2d && (key_type != ZKEY)) { @@ -1005,10 +1010,10 @@ int transformEvent(TransInfo *t, wmEvent *event) } else { if (t->flag & T_2D_EDIT) { - setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS0), "along X"); + setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS0), IFACE_("along X")); } else { - setUserConstraint(t, t->current_orientation, (CON_AXIS0), "along %s X"); + setUserConstraint(t, t->current_orientation, (CON_AXIS0), IFACE_("along %s X")); } } t->redraw |= TREDRAW_HARD; @@ -1021,10 +1026,10 @@ int transformEvent(TransInfo *t, wmEvent *event) } else { if (t->flag & T_2D_EDIT) { - setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS1), "along Y"); + setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS1), IFACE_("along Y")); } else { - setUserConstraint(t, t->current_orientation, (CON_AXIS1), "along %s Y"); + setUserConstraint(t, t->current_orientation, (CON_AXIS1), IFACE_("along %s Y")); } } t->redraw |= TREDRAW_HARD; @@ -1036,7 +1041,7 @@ int transformEvent(TransInfo *t, wmEvent *event) stopConstraint(t); } else { - setUserConstraint(t, t->current_orientation, (CON_AXIS2), "along %s Z"); + setUserConstraint(t, t->current_orientation, (CON_AXIS2), IFACE_("along %s Z")); } t->redraw |= TREDRAW_HARD; } @@ -1047,7 +1052,7 @@ int transformEvent(TransInfo *t, wmEvent *event) stopConstraint(t); } else { - setUserConstraint(t, t->current_orientation, (CON_AXIS1 | CON_AXIS2), "locking %s X"); + setUserConstraint(t, t->current_orientation, (CON_AXIS1 | CON_AXIS2), IFACE_("locking %s X")); } t->redraw |= TREDRAW_HARD; } @@ -1058,7 +1063,7 @@ int transformEvent(TransInfo *t, wmEvent *event) stopConstraint(t); } else { - setUserConstraint(t, t->current_orientation, (CON_AXIS0 | CON_AXIS2), "locking %s Y"); + setUserConstraint(t, t->current_orientation, (CON_AXIS0 | CON_AXIS2), IFACE_("locking %s Y")); } t->redraw |= TREDRAW_HARD; } @@ -1069,7 +1074,7 @@ int transformEvent(TransInfo *t, wmEvent *event) stopConstraint(t); } else { - setUserConstraint(t, t->current_orientation, (CON_AXIS0 | CON_AXIS1), "locking %s Z"); + setUserConstraint(t, t->current_orientation, (CON_AXIS0 | CON_AXIS1), IFACE_("locking %s Z")); } t->redraw |= TREDRAW_HARD; } @@ -1174,7 +1179,7 @@ int transformEvent(TransInfo *t, wmEvent *event) /* exception for switching to dolly, or trackball, in camera view */ if (t->flag & T_CAMERA) { if (t->mode == TFM_TRANSLATION) - setLocalConstraint(t, (CON_AXIS2), "along local Z"); + setLocalConstraint(t, (CON_AXIS2), IFACE_("along local Z")); else if (t->mode == TFM_ROTATION) { restoreTransObjects(t); initTrackball(t); @@ -1666,7 +1671,7 @@ static void drawTransformView(const struct bContext *C, ARegion *UNUSED(ar), voi static void drawAutoKeyWarning(TransInfo *UNUSED(t), ARegion *ar) { rcti rect; - const char printable[] = "Auto Keying On"; + const char *printable = IFACE_("Auto Keying On"); float printable_size[2]; int xco, yco; @@ -2699,13 +2704,13 @@ int Warp(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - sprintf(str, "Warp: %s", c); + sprintf(str, IFACE_("Warp: %s"), c); circumfac = DEG2RADF(circumfac); } else { /* default header print */ - sprintf(str, "Warp: %.3f", RAD2DEGF(circumfac)); + sprintf(str, IFACE_("Warp: %.3f"), RAD2DEGF(circumfac)); } t->values[0] = circumfac; @@ -2840,11 +2845,11 @@ int Shear(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - sprintf(str, "Shear: %s %s", c, t->proptext); + sprintf(str, IFACE_("Shear: %s %s"), c, t->proptext); } else { /* default header print */ - sprintf(str, "Shear: %.3f %s (Press X or Y to set shear axis)", value, t->proptext); + sprintf(str, IFACE_("Shear: %.3f %s (Press X or Y to set shear axis)"), value, t->proptext); } t->values[0] = value; @@ -2936,30 +2941,30 @@ static void headerResize(TransInfo *t, float vec[3], char *str) if (t->con.mode & CON_APPLY) { switch (t->num.idx_max) { case 0: - spos += sprintf(spos, "Scale: %s%s %s", &tvec[0], t->con.text, t->proptext); + spos += sprintf(spos, IFACE_("Scale: %s%s %s"), &tvec[0], t->con.text, t->proptext); break; case 1: - spos += sprintf(spos, "Scale: %s : %s%s %s", &tvec[0], &tvec[NUM_STR_REP_LEN], + spos += sprintf(spos, IFACE_("Scale: %s : %s%s %s"), &tvec[0], &tvec[NUM_STR_REP_LEN], t->con.text, t->proptext); break; case 2: - spos += sprintf(spos, "Scale: %s : %s : %s%s %s", &tvec[0], &tvec[NUM_STR_REP_LEN], + spos += sprintf(spos, IFACE_("Scale: %s : %s : %s%s %s"), &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext); } } else { if (t->flag & T_2D_EDIT) { - spos += sprintf(spos, "Scale X: %s Y: %s%s %s", &tvec[0], &tvec[NUM_STR_REP_LEN], + spos += sprintf(spos, IFACE_("Scale X: %s Y: %s%s %s"), &tvec[0], &tvec[NUM_STR_REP_LEN], t->con.text, t->proptext); } else { - spos += sprintf(spos, "Scale X: %s Y: %s Z: %s%s %s", &tvec[0], &tvec[NUM_STR_REP_LEN], + spos += sprintf(spos, IFACE_("Scale X: %s Y: %s Z: %s%s %s"), &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext); } } if (t->flag & (T_PROP_EDIT | T_PROP_CONNECTED)) { - spos += sprintf(spos, " Proportional size: %.2f", t->prop_size); + spos += sprintf(spos, IFACE_(" Proportional size: %.2f"), t->prop_size); } (void)spos; @@ -3318,11 +3323,11 @@ int ToSphere(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - sprintf(str, "To Sphere: %s %s", c, t->proptext); + sprintf(str, IFACE_("To Sphere: %s %s"), c, t->proptext); } else { /* default header print */ - sprintf(str, "To Sphere: %.4f %s", ratio, t->proptext); + sprintf(str, IFACE_("To Sphere: %.4f %s"), ratio, t->proptext); } @@ -3662,17 +3667,17 @@ int Rotation(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - spos += sprintf(spos, "Rot: %s %s %s", &c[0], t->con.text, t->proptext); + spos += sprintf(spos, IFACE_("Rot: %s %s %s"), &c[0], t->con.text, t->proptext); /* Clamp between -180 and 180 */ final = angle_wrap_rad(DEG2RADF(final)); } else { - spos += sprintf(spos, "Rot: %.2f%s %s", RAD2DEGF(final), t->con.text, t->proptext); + spos += sprintf(spos, IFACE_("Rot: %.2f%s %s"), RAD2DEGF(final), t->con.text, t->proptext); } if (t->flag & (T_PROP_EDIT | T_PROP_CONNECTED)) { - spos += sprintf(spos, " Proportional size: %.2f", t->prop_size); + spos += sprintf(spos, IFACE_(" Proportional size: %.2f"), t->prop_size); } (void)spos; @@ -3761,17 +3766,17 @@ int Trackball(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - spos += sprintf(spos, "Trackball: %s %s %s", &c[0], &c[NUM_STR_REP_LEN], t->proptext); + spos += sprintf(spos, IFACE_("Trackball: %s %s %s"), &c[0], &c[NUM_STR_REP_LEN], t->proptext); phi[0] = DEG2RADF(phi[0]); phi[1] = DEG2RADF(phi[1]); } else { - spos += sprintf(spos, "Trackball: %.2f %.2f %s", RAD2DEGF(phi[0]), RAD2DEGF(phi[1]), t->proptext); + spos += sprintf(spos, IFACE_("Trackball: %.2f %.2f %s"), RAD2DEGF(phi[0]), RAD2DEGF(phi[1]), t->proptext); } if (t->flag & (T_PROP_EDIT | T_PROP_CONNECTED)) { - spos += sprintf(spos, " Proportional size: %.2f", t->prop_size); + spos += sprintf(spos, IFACE_(" Proportional size: %.2f"), t->prop_size); } (void)spos; @@ -3882,7 +3887,7 @@ static void headerTranslation(TransInfo *t, float vec[3], char *str) short chainlen = t->settings->autoik_chainlen; if (chainlen) - sprintf(autoik, "AutoIK-Len: %d", chainlen); + sprintf(autoik, IFACE_("AutoIK-Len: %d"), chainlen); else autoik[0] = '\0'; } @@ -3915,7 +3920,7 @@ static void headerTranslation(TransInfo *t, float vec[3], char *str) } if (t->flag & (T_PROP_EDIT | T_PROP_CONNECTED)) { - spos += sprintf(spos, " Proportional size: %.2f", t->prop_size); + spos += sprintf(spos, IFACE_(" Proportional size: %.2f"), t->prop_size); } (void)spos; } @@ -4077,7 +4082,7 @@ int ShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) /* header print for NumInput */ str_p = str; - str_p += BLI_snprintf(str_p, sizeof(str), "Shrink/Fatten:"); + str_p += BLI_snprintf(str_p, sizeof(str), IFACE_("Shrink/Fatten:")); if (hasNumInput(&t->num)) { char c[NUM_STR_REP_LEN]; outputNumInput(&(t->num), c); @@ -4099,8 +4104,8 @@ int ShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) str_p += WM_keymap_item_to_string(kmi, str_p, sizeof(str) - (str_p - str)); } } - str_p += BLI_snprintf(str_p, sizeof(str) - (str_p - str), " or Alt) Even Thickness %s", - (t->flag & T_ALT_TRANSFORM) ? "ON" : "OFF"); + str_p += BLI_snprintf(str_p, sizeof(str) - (str_p - str), IFACE_(" or Alt) Even Thickness %s"), + (t->flag & T_ALT_TRANSFORM) ? IFACE_("ON") : IFACE_("OFF")); /* done with header string */ @@ -4171,7 +4176,7 @@ int Tilt(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - sprintf(str, "Tilt: %s° %s", &c[0], t->proptext); + sprintf(str, IFACE_("Tilt: %s° %s"), &c[0], t->proptext); final = DEG2RADF(final); @@ -4179,7 +4184,7 @@ int Tilt(TransInfo *t, const int UNUSED(mval[2])) t->values[0] = final; } else { - sprintf(str, "Tilt: %.2f° %s", RAD2DEGF(final), t->proptext); + sprintf(str, IFACE_("Tilt: %.2f° %s"), RAD2DEGF(final), t->proptext); } for (i = 0; i < t->total; i++, td++) { @@ -4243,10 +4248,10 @@ int CurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) char c[NUM_STR_REP_LEN]; outputNumInput(&(t->num), c); - sprintf(str, "Shrink/Fatten: %s", c); + sprintf(str, IFACE_("Shrink/Fatten: %s"), c); } else { - sprintf(str, "Shrink/Fatten: %3f", ratio); + sprintf(str, IFACE_("Shrink/Fatten: %3f"), ratio); } for (i = 0; i < t->total; i++, td++) { @@ -4311,10 +4316,10 @@ int MaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) char c[NUM_STR_REP_LEN]; outputNumInput(&(t->num), c); - sprintf(str, "Feather Shrink/Fatten: %s", c); + sprintf(str, IFACE_("Feather Shrink/Fatten: %s"), c); } else { - sprintf(str, "Feather Shrink/Fatten: %3f", ratio); + sprintf(str, IFACE_("Feather Shrink/Fatten: %3f"), ratio); } /* detect if no points have feather yet */ @@ -4399,11 +4404,11 @@ int PushPull(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - sprintf(str, "Push/Pull: %s%s %s", c, t->con.text, t->proptext); + sprintf(str, IFACE_("Push/Pull: %s%s %s"), c, t->con.text, t->proptext); } else { /* default header print */ - sprintf(str, "Push/Pull: %.4f%s %s", distance, t->con.text, t->proptext); + sprintf(str, IFACE_("Push/Pull: %.4f%s %s"), distance, t->con.text, t->proptext); } t->values[0] = distance; @@ -4520,7 +4525,7 @@ int Bevel(TransInfo *t, const int UNUSED(mval[2])) const char *mode; TransData *td = t->data; - mode = (G.editBMesh->options & BME_BEVEL_VERT) ? "verts only" : "normal"; + mode = (G.editBMesh->options & BME_BEVEL_VERT) ? IFACE_("verts only") : IFACE_("normal"); distance = t->values[0] / 4; /* 4 just seemed a nice value to me, nothing special */ distance = fabs(distance); @@ -4535,11 +4540,11 @@ int Bevel(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - sprintf(str, "Bevel - Dist: %s, Mode: %s (MMB to toggle))", c, mode); + sprintf(str, IFACE_("Bevel - Dist: %s, Mode: %s (MMB to toggle))"), c, mode); } else { /* default header print */ - sprintf(str, "Bevel - Dist: %.4f, Mode: %s (MMB to toggle))", distance, mode); + sprintf(str, IFACE_("Bevel - Dist: %.4f, Mode: %s (MMB to toggle))"), distance, mode); } if (distance < 0) distance = -distance; @@ -4603,16 +4608,16 @@ int BevelWeight(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); if (weight >= 0.0f) - sprintf(str, "Bevel Weight: +%s %s", c, t->proptext); + sprintf(str, IFACE_("Bevel Weight: +%s %s"), c, t->proptext); else - sprintf(str, "Bevel Weight: %s %s", c, t->proptext); + sprintf(str, IFACE_("Bevel Weight: %s %s"), c, t->proptext); } else { /* default header print */ if (weight >= 0.0f) - sprintf(str, "Bevel Weight: +%.3f %s", weight, t->proptext); + sprintf(str, IFACE_("Bevel Weight: +%.3f %s"), weight, t->proptext); else - sprintf(str, "Bevel Weight: %.3f %s", weight, t->proptext); + sprintf(str, IFACE_("Bevel Weight: %.3f %s"), weight, t->proptext); } for (i = 0; i < t->total; i++, td++) { @@ -4676,16 +4681,16 @@ int Crease(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); if (crease >= 0.0f) - sprintf(str, "Crease: +%s %s", c, t->proptext); + sprintf(str, IFACE_("Crease: +%s %s"), c, t->proptext); else - sprintf(str, "Crease: %s %s", c, t->proptext); + sprintf(str, IFACE_("Crease: %s %s"), c, t->proptext); } else { /* default header print */ if (crease >= 0.0f) - sprintf(str, "Crease: +%.3f %s", crease, t->proptext); + sprintf(str, IFACE_("Crease: +%.3f %s"), crease, t->proptext); else - sprintf(str, "Crease: %.3f %s", crease, t->proptext); + sprintf(str, IFACE_("Crease: %.3f %s"), crease, t->proptext); } for (i = 0; i < t->total; i++, td++) { @@ -4744,14 +4749,14 @@ static void headerBoneSize(TransInfo *t, float vec[3], char *str) /* hmm... perhaps the y-axis values don't need to be shown? */ if (t->con.mode & CON_APPLY) { if (t->num.idx_max == 0) - sprintf(str, "ScaleB: %s%s %s", &tvec[0], t->con.text, t->proptext); + sprintf(str, IFACE_("ScaleB: %s%s %s"), &tvec[0], t->con.text, t->proptext); else - sprintf(str, "ScaleB: %s : %s : %s%s %s", &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], - t->con.text, t->proptext); + sprintf(str, IFACE_("ScaleB: %s : %s : %s%s %s"), &tvec[0], &tvec[NUM_STR_REP_LEN], + &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext); } else { - sprintf(str, "ScaleB X: %s Y: %s Z: %s%s %s", &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], - t->con.text, t->proptext); + sprintf(str, IFACE_("ScaleB X: %s Y: %s Z: %s%s %s"), &tvec[0], &tvec[NUM_STR_REP_LEN], + &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext); } } @@ -4867,10 +4872,10 @@ int BoneEnvelope(TransInfo *t, const int UNUSED(mval[2])) char c[NUM_STR_REP_LEN]; outputNumInput(&(t->num), c); - sprintf(str, "Envelope: %s", c); + sprintf(str, IFACE_("Envelope: %s"), c); } else { - sprintf(str, "Envelope: %3f", ratio); + sprintf(str, IFACE_("Envelope: %3f"), ratio); } for (i = 0; i < t->total; i++, td++) { @@ -5923,12 +5928,12 @@ int EdgeSlide(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - BLI_snprintf(str, sizeof(str), "Edge Slide: %s (E)ven: %s, (F)lipped: %s", - &c[0], !is_proportional ? "ON" : "OFF", flipped ? "ON" : "OFF"); + BLI_snprintf(str, sizeof(str), IFACE_("Edge Slide: %s (E)ven: %s, (F)lipped: %s"), + &c[0], !is_proportional ? IFACE_("ON") : IFACE_("OFF"), flipped ? IFACE_("ON") : IFACE_("OFF")); } else { - BLI_snprintf(str, sizeof(str), "Edge Slide: %.4f (E)ven: %s, (F)lipped: %s", - final, !is_proportional ? "ON" : "OFF", flipped ? "ON" : "OFF"); + BLI_snprintf(str, sizeof(str), IFACE_("Edge Slide: %.4f (E)ven: %s, (F)lipped: %s"), + final, !is_proportional ? IFACE_("ON") : IFACE_("OFF"), flipped ? IFACE_("ON") : IFACE_("OFF")); } CLAMP(final, -1.0f, 1.0f); @@ -5939,7 +5944,7 @@ int EdgeSlide(TransInfo *t, const int UNUSED(mval[2])) if (t->customData) doEdgeSlide(t, final); else { - strcpy(str, "Invalid Edge Selection"); + strcpy(str, IFACE_("Invalid Edge Selection")); t->state = TRANS_CANCEL; } @@ -6428,7 +6433,7 @@ int VertSlide(TransInfo *t, const int UNUSED(mval[2])) /* header string */ str_p = str; - str_p += BLI_snprintf(str_p, sizeof(str), "Vert Slide: "); + str_p += BLI_snprintf(str_p, sizeof(str), IFACE_("Vert Slide: ")); if (hasNumInput(&t->num)) { char c[NUM_STR_REP_LEN]; applyNumInput(&t->num, &final); @@ -6438,20 +6443,22 @@ int VertSlide(TransInfo *t, const int UNUSED(mval[2])) else { str_p += BLI_snprintf(str_p, sizeof(str) - (str_p - str), "%.4f ", final); } - str_p += BLI_snprintf(str_p, sizeof(str) - (str_p - str), "(E)ven: %s, ", !is_proportional ? "ON" : "OFF"); + str_p += BLI_snprintf(str_p, sizeof(str) - (str_p - str), IFACE_("(E)ven: %s, "), + !is_proportional ? IFACE_("ON") : IFACE_("OFF")); if (!is_proportional) { - str_p += BLI_snprintf(str_p, sizeof(str) - (str_p - str), "(F)lipped: %s, ", flipped ? "ON" : "OFF"); + str_p += BLI_snprintf(str_p, sizeof(str) - (str_p - str), IFACE_("(F)lipped: %s, "), + flipped ? IFACE_("ON") : IFACE_("OFF")); } - str_p += BLI_snprintf(str_p, sizeof(str) - (str_p - str), "Alt or (C)lamp: %s", is_clamp ? "ON" : "OFF"); + str_p += BLI_snprintf(str_p, sizeof(str) - (str_p - str), IFACE_("Alt or (C)lamp: %s"), + is_clamp ? IFACE_("ON") : IFACE_("OFF")); /* done with header string */ - /*do stuff here*/ if (t->customData) { doVertSlide(t, final); } else { - strcpy(str, "Invalid Vert Selection"); + strcpy(str, IFACE_("Invalid Vert Selection")); t->state = TRANS_CANCEL; } @@ -6502,12 +6509,12 @@ int BoneRoll(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - sprintf(str, "Roll: %s", &c[0]); + sprintf(str, IFACE_("Roll: %s"), &c[0]); final = DEG2RADF(final); } else { - sprintf(str, "Roll: %.2f", RAD2DEGF(final)); + sprintf(str, IFACE_("Roll: %.2f"), RAD2DEGF(final)); } /* set roll values */ @@ -6573,16 +6580,16 @@ int BakeTime(TransInfo *t, const int mval[2]) outputNumInput(&(t->num), c); if (time >= 0.0f) - sprintf(str, "Time: +%s %s", c, t->proptext); + sprintf(str, IFACE_("Time: +%s %s"), c, t->proptext); else - sprintf(str, "Time: %s %s", c, t->proptext); + sprintf(str, IFACE_("Time: %s %s"), c, t->proptext); } else { /* default header print */ if (time >= 0.0f) - sprintf(str, "Time: +%.3f %s", time, t->proptext); + sprintf(str, IFACE_("Time: +%.3f %s"), time, t->proptext); else - sprintf(str, "Time: %.3f %s", time, t->proptext); + sprintf(str, IFACE_("Time: %.3f %s"), time, t->proptext); } for (i = 0; i < t->total; i++, td++) { @@ -6642,7 +6649,7 @@ int Mirror(TransInfo *t, const int UNUSED(mval[2])) t->con.applySize(t, NULL, mat); } - sprintf(str, "Mirror%s", t->con.text); + sprintf(str, IFACE_("Mirror%s"), t->con.text); for (i = 0, td = t->data; i < t->total; i++, td++) { if (td->flag & TD_NOACTION) @@ -6676,9 +6683,9 @@ int Mirror(TransInfo *t, const int UNUSED(mval[2])) recalcData(t); if (t->flag & T_2D_EDIT) - ED_area_headerprint(t->sa, "Select a mirror axis (X, Y)"); + ED_area_headerprint(t->sa, IFACE_("Select a mirror axis (X, Y)")); else - ED_area_headerprint(t->sa, "Select a mirror axis (X, Y, Z)"); + ED_area_headerprint(t->sa, IFACE_("Select a mirror axis (X, Y, Z)")); } return 1; @@ -6735,7 +6742,7 @@ int Align(TransInfo *t, const int UNUSED(mval[2])) recalcData(t); - ED_area_headerprint(t->sa, "Align"); + ED_area_headerprint(t->sa, IFACE_("Align")); return 1; } @@ -6772,7 +6779,7 @@ static void headerSeqSlide(TransInfo *t, float val[2], char *str, size_t str_len } str_p = str; - str_p += BLI_snprintf(str, str_len, "Sequence Slide: %s%s, (", &tvec[0], t->con.text); + str_p += BLI_snprintf(str, str_len, IFACE_("Sequence Slide: %s%s, ("), &tvec[0], t->con.text); { wmKeyMapItem *kmi = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_TRANSLATE); @@ -6780,8 +6787,8 @@ static void headerSeqSlide(TransInfo *t, float val[2], char *str, size_t str_len str_p += WM_keymap_item_to_string(kmi, str_p, str_len - (str_p - str)); } } - str_p += BLI_snprintf(str_p, str_len - (str_p - str), " or Alt) Expand to fit %s", - (t->flag & T_ALT_TRANSFORM) ? "ON" : "OFF"); + str_p += BLI_snprintf(str_p, str_len - (str_p - str), IFACE_(" or Alt) Expand to fit %s"), + (t->flag & T_ALT_TRANSFORM) ? IFACE_("ON") : IFACE_("OFF")); } static void applySeqSlide(TransInfo *t, float val[2]) @@ -7046,7 +7053,7 @@ static void headerTimeTranslate(TransInfo *t, char *str) sprintf(&tvec[0], "%.4f", val); } - sprintf(str, "DeltaX: %s", &tvec[0]); + sprintf(str, IFACE_("DeltaX: %s"), &tvec[0]); } static void applyTimeTranslate(TransInfo *t, float UNUSED(sval)) @@ -7187,7 +7194,7 @@ static void headerTimeSlide(TransInfo *t, float sval, char *str) sprintf(&tvec[0], "%.4f", val); } - sprintf(str, "TimeSlide: %s", &tvec[0]); + sprintf(str, IFACE_("TimeSlide: %s"), &tvec[0]); } static void applyTimeSlide(TransInfo *t, float sval) @@ -7319,7 +7326,7 @@ static void headerTimeScale(TransInfo *t, char *str) else sprintf(&tvec[0], "%.4f", t->values[0]); - sprintf(str, "ScaleX: %s", &tvec[0]); + sprintf(str, IFACE_("ScaleX: %s"), &tvec[0]); } static void applyTimeScale(TransInfo *t) diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index 097e4592933..c4d61472f18 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -60,6 +60,8 @@ #include "BLI_utildefines.h" #include "BLI_string.h" +#include "BLF_translation.h" + #include "UI_resources.h" #include "transform.h" @@ -598,24 +600,24 @@ void setUserConstraint(TransInfo *t, short orientation, int mode, const char fte case V3D_MANIP_GLOBAL: { float mtx[3][3] = MAT3_UNITY; - BLI_snprintf(text, sizeof(text), ftext, "global"); + BLI_snprintf(text, sizeof(text), ftext, IFACE_("global")); setConstraint(t, mtx, mode, text); } break; case V3D_MANIP_LOCAL: - BLI_snprintf(text, sizeof(text), ftext, "local"); + BLI_snprintf(text, sizeof(text), ftext, IFACE_("local")); setLocalConstraint(t, mode, text); break; case V3D_MANIP_NORMAL: - BLI_snprintf(text, sizeof(text), ftext, "normal"); + BLI_snprintf(text, sizeof(text), ftext, IFACE_("normal")); setConstraint(t, t->spacemtx, mode, text); break; case V3D_MANIP_VIEW: - BLI_snprintf(text, sizeof(text), ftext, "view"); + BLI_snprintf(text, sizeof(text), ftext, IFACE_("view")); setConstraint(t, t->spacemtx, mode, text); break; case V3D_MANIP_GIMBAL: - BLI_snprintf(text, sizeof(text), ftext, "gimbal"); + BLI_snprintf(text, sizeof(text), ftext, IFACE_("gimbal")); setConstraint(t, t->spacemtx, mode, text); break; default: /* V3D_MANIP_CUSTOM */ @@ -865,11 +867,11 @@ static void setNearestAxis2d(TransInfo *t) /* no correction needed... just use whichever one is lower */ if (abs(t->mval[0] - t->con.imval[0]) < abs(t->mval[1] - t->con.imval[1]) ) { t->con.mode |= CON_AXIS1; - BLI_snprintf(t->con.text, sizeof(t->con.text), " along Y axis"); + BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" along Y axis")); } else { t->con.mode |= CON_AXIS0; - BLI_snprintf(t->con.text, sizeof(t->con.text), " along X axis"); + BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" along X axis")); } } @@ -920,31 +922,31 @@ static void setNearestAxis3d(TransInfo *t) if (len[0] <= len[1] && len[0] <= len[2]) { if (t->modifiers & MOD_CONSTRAINT_PLANE) { t->con.mode |= (CON_AXIS1 | CON_AXIS2); - BLI_snprintf(t->con.text, sizeof(t->con.text), " locking %s X axis", t->spacename); + BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" locking %s X axis"), t->spacename); } else { t->con.mode |= CON_AXIS0; - BLI_snprintf(t->con.text, sizeof(t->con.text), " along %s X axis", t->spacename); + BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" along %s X axis"), t->spacename); } } else if (len[1] <= len[0] && len[1] <= len[2]) { if (t->modifiers & MOD_CONSTRAINT_PLANE) { t->con.mode |= (CON_AXIS0 | CON_AXIS2); - BLI_snprintf(t->con.text, sizeof(t->con.text), " locking %s Y axis", t->spacename); + BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" locking %s Y axis"), t->spacename); } else { t->con.mode |= CON_AXIS1; - BLI_snprintf(t->con.text, sizeof(t->con.text), " along %s Y axis", t->spacename); + BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" along %s Y axis"), t->spacename); } } else if (len[2] <= len[1] && len[2] <= len[0]) { if (t->modifiers & MOD_CONSTRAINT_PLANE) { t->con.mode |= (CON_AXIS0 | CON_AXIS1); - BLI_snprintf(t->con.text, sizeof(t->con.text), " locking %s Z axis", t->spacename); + BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" locking %s Z axis"), t->spacename); } else { t->con.mode |= CON_AXIS2; - BLI_snprintf(t->con.text, sizeof(t->con.text), " along %s Z axis", t->spacename); + BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" along %s Z axis"), t->spacename); } } } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 9ee1d11a036..c2a331f5249 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -56,6 +56,8 @@ #include "BLI_rand.h" #include "BLI_utildefines.h" +#include "BLF_translation.h" + #include "RNA_access.h" #include "BIF_gl.h" @@ -1768,25 +1770,25 @@ void calculatePropRatio(TransInfo *t) } switch (t->prop_mode) { case PROP_SHARP: - strcpy(t->proptext, "(Sharp)"); + strcpy(t->proptext, IFACE_("(Sharp)")); break; case PROP_SMOOTH: - strcpy(t->proptext, "(Smooth)"); + strcpy(t->proptext, IFACE_("(Smooth)")); break; case PROP_ROOT: - strcpy(t->proptext, "(Root)"); + strcpy(t->proptext, IFACE_("(Root)")); break; case PROP_LIN: - strcpy(t->proptext, "(Linear)"); + strcpy(t->proptext, IFACE_("(Linear)")); break; case PROP_CONST: - strcpy(t->proptext, "(Constant)"); + strcpy(t->proptext, IFACE_("(Constant)")); break; case PROP_SPHERE: - strcpy(t->proptext, "(Sphere)"); + strcpy(t->proptext, IFACE_("(Sphere)")); break; case PROP_RANDOM: - strcpy(t->proptext, "(Random)"); + strcpy(t->proptext, IFACE_("(Random)")); break; default: t->proptext[0] = '\0'; diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index 4bd6496e083..e507d062b0e 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -493,25 +493,25 @@ void initTransformOrientation(bContext *C, TransInfo *t) switch (t->current_orientation) { case V3D_MANIP_GLOBAL: unit_m3(t->spacemtx); - strcpy(t->spacename, "global"); + strcpy(t->spacename, IFACE_("global")); break; case V3D_MANIP_GIMBAL: unit_m3(t->spacemtx); if (gimbal_axis(ob, t->spacemtx)) { - strcpy(t->spacename, "gimbal"); + strcpy(t->spacename, IFACE_("gimbal")); break; } /* no gimbal fallthrough to normal */ case V3D_MANIP_NORMAL: if (obedit || (ob && ob->mode & OB_MODE_POSE)) { - strcpy(t->spacename, "normal"); + strcpy(t->spacename, IFACE_("normal")); ED_getTransformOrientationMatrix(C, t->spacemtx, (v3d->around == V3D_ACTIVE)); break; } /* no break we define 'normal' as 'local' in Object mode */ case V3D_MANIP_LOCAL: - strcpy(t->spacename, "local"); + strcpy(t->spacename, IFACE_("local")); if (ob) { copy_m3_m4(t->spacemtx, ob->obmat); @@ -528,7 +528,7 @@ void initTransformOrientation(bContext *C, TransInfo *t) RegionView3D *rv3d = t->ar->regiondata; float mat[3][3]; - strcpy(t->spacename, "view"); + strcpy(t->spacename, IFACE_("view")); copy_m3_m4(mat, rv3d->viewinv); normalize_m3(mat); copy_m3_m3(t->spacemtx, mat); diff --git a/source/blender/editors/uvedit/CMakeLists.txt b/source/blender/editors/uvedit/CMakeLists.txt index 1c69e569aa6..695a7cdd0f6 100644 --- a/source/blender/editors/uvedit/CMakeLists.txt +++ b/source/blender/editors/uvedit/CMakeLists.txt @@ -22,6 +22,7 @@ set(INC ../include ../../blenkernel ../../blenlib + ../../blenfont ../../blenloader ../../bmesh ../../makesdna @@ -47,4 +48,8 @@ set(SRC uvedit_parametrizer.h ) +if(WITH_INTERNATIONAL) + add_definitions(-DWITH_INTERNATIONAL) +endif() + blender_add_lib(bf_editor_uvedit "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/editors/uvedit/SConscript b/source/blender/editors/uvedit/SConscript index 01316680d5d..dfa15d2de4f 100644 --- a/source/blender/editors/uvedit/SConscript +++ b/source/blender/editors/uvedit/SConscript @@ -27,10 +27,15 @@ Import ('env') +defs = [] + sources = env.Glob('*.c') -incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' +incs = '../include ../../blenlib ../../blenfont ../../blenkernel ../../makesdna ../../imbuf' incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' incs += ' ../../bmesh ../../makesrna #/intern/opennl/extern ../../gpu ../../blenloader' -env.BlenderLib ( 'bf_editors_uvedit', sources, Split(incs), [], libtype=['core'], priority=[45] ) +if env['WITH_BF_INTERNATIONAL']: + defs.append('WITH_INTERNATIONAL') + +env.BlenderLib ( 'bf_editors_uvedit', sources, Split(incs), defs, libtype=['core'], priority=[45] ) diff --git a/source/blender/editors/uvedit/uvedit_buttons.c b/source/blender/editors/uvedit/uvedit_buttons.c index 1c32c01b8f0..5c188628978 100644 --- a/source/blender/editors/uvedit/uvedit_buttons.c +++ b/source/blender/editors/uvedit/uvedit_buttons.c @@ -43,6 +43,8 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +#include "BLF_translation.h" + #include "BKE_context.h" #include "BKE_customdata.h" #include "BKE_mesh.h" @@ -152,8 +154,10 @@ static void uvedit_vertex_buttons(const bContext *C, uiBlock *block) } uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_UVEDIT_VERTEX, "X:", 10, 10, 145, 19, &uvedit_old_center[0], -10 * imx, 10.0 * imx, step, digits, ""); - uiDefButF(block, NUM, B_UVEDIT_VERTEX, "Y:", 165, 10, 145, 19, &uvedit_old_center[1], -10 * imy, 10.0 * imy, step, digits, ""); + uiDefButF(block, NUM, B_UVEDIT_VERTEX, IFACE_("X:"), 10, 10, 145, 19, &uvedit_old_center[0], + -10 * imx, 10.0 * imx, step, digits, ""); + uiDefButF(block, NUM, B_UVEDIT_VERTEX, IFACE_("Y:"), 165, 10, 145, 19, &uvedit_old_center[1], + -10 * imy, 10.0 * imy, step, digits, ""); uiBlockEndAlign(block); } } @@ -214,7 +218,7 @@ void ED_uvedit_buttons_register(ARegionType *art) pt = MEM_callocN(sizeof(PanelType), "spacetype image panel uv"); strcpy(pt->idname, "IMAGE_PT_uv"); - strcpy(pt->label, "UV Vertex"); + strcpy(pt->label, N_("UV Vertex")); /* XXX C panels are not available through RNA (bpy.types)! */ pt->draw = image_panel_uv; pt->poll = image_panel_uv_poll; BLI_addtail(&art->paneltypes, pt); From de26f5922022abb341b1a66b1d700ded259b9265 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Tue, 19 Feb 2013 15:47:30 +0000 Subject: [PATCH 069/182] Add CTX_wm_operator_poll_msg_set as auto-detected func for translations. --- release/scripts/modules/bl_i18n_utils/settings.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/release/scripts/modules/bl_i18n_utils/settings.py b/release/scripts/modules/bl_i18n_utils/settings.py index 232f54f5140..7e37dffbf10 100644 --- a/release/scripts/modules/bl_i18n_utils/settings.py +++ b/release/scripts/modules/bl_i18n_utils/settings.py @@ -227,7 +227,8 @@ PYGETTEXT_KEYWORDS = (() + for it in ("CTX_IFACE_", "CTX_TIP_", "CTX_N_")) + tuple(("{}\\((?:[^\"',]+,){{1,2}}\\s*" + _msg_re + r"\s*(?:\)|,)").format(it) - for it in ("BKE_report", "BKE_reportf", "BKE_reports_prepend", "BKE_reports_prependf")) + + for it in ("BKE_report", "BKE_reportf", "BKE_reports_prepend", "BKE_reports_prependf", + "CTX_wm_operator_poll_msg_set")) + tuple(("{}\\((?:[^\"',]+,){{3}}\\s*" + _msg_re + r"\s*\)").format(it) for it in ("BMO_error_raise",)) + From cd3b98c4faf7e4f7e54138bfbc2616aeeadc86af Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 19 Feb 2013 15:56:49 +0000 Subject: [PATCH 070/182] step over unicode characters with autocomplete (correctly this time). --- source/blender/blenlib/BLI_string_utf8.h | 1 + source/blender/blenlib/intern/string_utf8.c | 16 ++++++++++ .../editors/space_text/text_autocomplete.c | 32 +++++++++++++------ 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/source/blender/blenlib/BLI_string_utf8.h b/source/blender/blenlib/BLI_string_utf8.h index ecbc4cb1cd4..30d5c28bf98 100644 --- a/source/blender/blenlib/BLI_string_utf8.h +++ b/source/blender/blenlib/BLI_string_utf8.h @@ -41,6 +41,7 @@ int BLI_str_utf8_size_safe(const char *p); /* copied from glib */ unsigned int BLI_str_utf8_as_unicode(const char *p); unsigned int BLI_str_utf8_as_unicode_and_size(const char *__restrict p, size_t *__restrict index); +unsigned int BLI_str_utf8_as_unicode_and_size_safe(const char *__restrict p, size_t *__restrict index); unsigned int BLI_str_utf8_as_unicode_step(const char *__restrict p, size_t *__restrict index); size_t BLI_str_utf8_from_unicode(unsigned int c, char *outbuf); diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c index 9e0f9197ca3..d802ad53e6a 100644 --- a/source/blender/blenlib/intern/string_utf8.c +++ b/source/blender/blenlib/intern/string_utf8.c @@ -433,6 +433,22 @@ unsigned int BLI_str_utf8_as_unicode_and_size(const char *__restrict p, size_t * return result; } +unsigned int BLI_str_utf8_as_unicode_and_size_safe(const char *__restrict p, size_t *__restrict index) +{ + int i, mask = 0, len; + unsigned int result; + const unsigned char c = (unsigned char) *p; + + UTF8_COMPUTE (c, mask, len, -1); + if (len == -1) { + *index += 1; + return c; + } + UTF8_GET (result, p, i, mask, len, BLI_UTF8_ERR); + *index += len; + return result; +} + /* another variant that steps over the index, * note, currently this also falls back to latin1 for text drawing. */ unsigned int BLI_str_utf8_as_unicode_step(const char *__restrict p, size_t *__restrict index) diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c index 94977fc5f0f..0c16208c2a7 100644 --- a/source/blender/editors/space_text/text_autocomplete.c +++ b/source/blender/editors/space_text/text_autocomplete.c @@ -162,23 +162,29 @@ static GHash *text_autocomplete_build(Text *text) gh = BLI_ghash_str_new(__func__); for (linep = text->lines.first; linep; linep = linep->next) { - int i_start = 0; - int i_end = 0; + size_t i_start = 0; + size_t i_end = 0; + size_t i_pos = 0; while (i_start < linep->len) { /* seek identifier beginning */ - while (i_start < linep->len && !text_check_identifier_nodigit(linep->line[i_start])) { - i_start++; + i_pos = i_start; + while ((i_start < linep->len) && + (!text_check_identifier_nodigit(BLI_str_utf8_as_unicode_and_size_safe(&linep->line[i_start], &i_pos)))) + { + i_start = i_pos; } - i_end = i_start; - while (i_end < linep->len && text_check_identifier(linep->line[i_end])) { - i_end++; + i_pos = i_end = i_start; + while ((i_end < linep->len) && + (text_check_identifier(BLI_str_utf8_as_unicode_and_size_safe(&linep->line[i_end], &i_pos)))) + { + i_end = i_pos; } if ((i_start != i_end) && /* check we're at the beginning of a line or that the previous char is not an identifier - * this prevents digits from being added */ - ((i_start < 1) || !text_check_identifier(linep->line[i_start - 1]))) + * this prevents digits from being added */ + ((i_start < 1) || !text_check_identifier(BLI_str_utf8_as_unicode(&linep->line[i_start - 1])))) { char *str_sub = &linep->line[i_start]; const int choice_len = i_end - i_start; @@ -197,7 +203,13 @@ static GHash *text_autocomplete_build(Text *text) str_sub[choice_len] = str_sub_last; } } - i_start = i_end; + if (i_end != i_start) { + i_start = i_end; + } + else { + /* highly unlikely, but prevent eternal loop */ + i_start++; + } } } From 91a63e347d3a0909786bc0f39cb0ccf53da9d92d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 19 Feb 2013 15:58:38 +0000 Subject: [PATCH 071/182] set unicode conversion errors as UNLIKELY --- source/blender/blenlib/intern/string_utf8.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c index d802ad53e6a..26235de4dd2 100644 --- a/source/blender/blenlib/intern/string_utf8.c +++ b/source/blender/blenlib/intern/string_utf8.c @@ -369,7 +369,7 @@ size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst_w, const char *__rest int BLI_str_utf8_size(const char *p) { int mask = 0, len; - unsigned char c = (unsigned char) *p; + const unsigned char c = (unsigned char) *p; UTF8_COMPUTE (c, mask, len, -1); @@ -382,7 +382,7 @@ int BLI_str_utf8_size(const char *p) int BLI_str_utf8_size_safe(const char *p) { int mask = 0, len; - unsigned char c = (unsigned char) *p; + const unsigned char c = (unsigned char) *p; UTF8_COMPUTE (c, mask, len, 1); @@ -408,10 +408,10 @@ unsigned int BLI_str_utf8_as_unicode(const char *p) { int i, mask = 0, len; unsigned int result; - unsigned char c = (unsigned char) *p; + const unsigned char c = (unsigned char) *p; UTF8_COMPUTE (c, mask, len, -1); - if (len == -1) + if (UNLIKELY(len == -1)) return BLI_UTF8_ERR; UTF8_GET (result, p, i, mask, len, BLI_UTF8_ERR); @@ -423,10 +423,10 @@ unsigned int BLI_str_utf8_as_unicode_and_size(const char *__restrict p, size_t * { int i, mask = 0, len; unsigned int result; - unsigned char c = (unsigned char) *p; + const unsigned char c = (unsigned char) *p; UTF8_COMPUTE (c, mask, len, -1); - if (len == -1) + if (UNLIKELY(len == -1)) return BLI_UTF8_ERR; UTF8_GET (result, p, i, mask, len, BLI_UTF8_ERR); *index += len; @@ -440,7 +440,7 @@ unsigned int BLI_str_utf8_as_unicode_and_size_safe(const char *__restrict p, siz const unsigned char c = (unsigned char) *p; UTF8_COMPUTE (c, mask, len, -1); - if (len == -1) { + if (UNLIKELY(len == -1)) { *index += 1; return c; } @@ -461,7 +461,7 @@ unsigned int BLI_str_utf8_as_unicode_step(const char *__restrict p, size_t *__re c = (unsigned char) *p; UTF8_COMPUTE (c, mask, len, -1); - if (len == -1) { + if (UNLIKELY(len == -1)) { /* when called with NULL end, result will never be NULL, * checks for a NULL character */ char *p_next = BLI_str_find_next_char_utf8(p, NULL); From 7f1ae2497b01dfc026564420605b492944d685a6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 19 Feb 2013 16:13:41 +0000 Subject: [PATCH 072/182] fix [#34275] Text autocomplete cuts words with accents or special characters autocomplete is now unicode aware, using python api's checks for now. eventually we should have our own. --- source/blender/blenkernel/BKE_text.h | 4 ++++ source/blender/blenkernel/intern/text.c | 12 ++++++++++++ .../editors/space_text/text_autocomplete.c | 6 +++--- source/blender/python/intern/bpy_interface.c | 17 +++++++++++++++++ 4 files changed, 36 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h index 3e882a048eb..3d7b5d1c8e4 100644 --- a/source/blender/blenkernel/BKE_text.h +++ b/source/blender/blenkernel/BKE_text.h @@ -109,6 +109,10 @@ int text_check_identifier_nodigit(const char ch); int text_check_whitespace(const char ch); int text_find_identifier_start(const char *str, int i); +/* defined in bpy_interface.c */ +extern int text_check_identifier_unicode(const unsigned int ch); +extern int text_check_identifier_nodigit_unicode(const unsigned int ch); + enum { TXT_MOVE_LINE_UP = -1, TXT_MOVE_LINE_DOWN = 1 diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 86e7a152a4a..74c0a76f82d 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -2938,6 +2938,18 @@ int text_check_identifier_nodigit(const char ch) return 0; } +#ifndef WITH_PYTHON +int text_check_identifier_unicode(const unsigned int ch) +{ + return (ch < 255 && text_check_identifier((char)ch)); +} + +int text_check_identifier_nodigit_unicode(const unsigned int ch) +{ + return (ch < 255 && text_check_identifier_nodigit((char)ch)); +} +#endif /* WITH_PYTHON */ + int text_check_whitespace(const char ch) { if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c index 0c16208c2a7..7c18b5c283a 100644 --- a/source/blender/editors/space_text/text_autocomplete.c +++ b/source/blender/editors/space_text/text_autocomplete.c @@ -170,13 +170,13 @@ static GHash *text_autocomplete_build(Text *text) /* seek identifier beginning */ i_pos = i_start; while ((i_start < linep->len) && - (!text_check_identifier_nodigit(BLI_str_utf8_as_unicode_and_size_safe(&linep->line[i_start], &i_pos)))) + (!text_check_identifier_nodigit_unicode(BLI_str_utf8_as_unicode_and_size_safe(&linep->line[i_start], &i_pos)))) { i_start = i_pos; } i_pos = i_end = i_start; while ((i_end < linep->len) && - (text_check_identifier(BLI_str_utf8_as_unicode_and_size_safe(&linep->line[i_end], &i_pos)))) + (text_check_identifier_unicode(BLI_str_utf8_as_unicode_and_size_safe(&linep->line[i_end], &i_pos)))) { i_end = i_pos; } @@ -184,7 +184,7 @@ static GHash *text_autocomplete_build(Text *text) if ((i_start != i_end) && /* check we're at the beginning of a line or that the previous char is not an identifier * this prevents digits from being added */ - ((i_start < 1) || !text_check_identifier(BLI_str_utf8_as_unicode(&linep->line[i_start - 1])))) + ((i_start < 1) || !text_check_identifier_unicode(BLI_str_utf8_as_unicode(&linep->line[i_start - 1])))) { char *str_sub = &linep->line[i_start]; const int choice_len = i_end - i_start; diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 632018f2bf0..90199a403dc 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -928,3 +928,20 @@ static void bpy_module_free(void *UNUSED(mod)) } #endif + + +/* EVIL, define text.c functions here... */ +extern int text_check_identifier_unicode(const unsigned int ch); +extern int text_check_identifier_nodigit_unicode(const unsigned int ch); +extern int text_check_identifier(const char ch); +extern int text_check_identifier_nodigit(const char ch); + +int text_check_identifier_unicode(const unsigned int ch) +{ + return (ch < 255 && text_check_identifier((char)ch)) || Py_UNICODE_ISALNUM(ch); +} + +int text_check_identifier_nodigit_unicode(const unsigned int ch) +{ + return (ch < 255 && text_check_identifier_nodigit((char)ch)) || Py_UNICODE_ISALPHA(ch); +} From 3d415325542730b610be0d1337c0f5ba13189e9c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 19 Feb 2013 16:57:04 +0000 Subject: [PATCH 073/182] fix [#34244] Snap to face projection - Entire mesh is affected by projection when Proportional Editing mode is active, regardless of influence radius --- source/blender/editors/transform/transform_snap.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 5577619901a..e95fc6d7bb9 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -303,6 +303,9 @@ void applyProject(TransInfo *t) if (td->flag & TD_SKIP) continue; + + if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f)) + continue; copy_v3_v3(iloc, td->loc); if (t->flag & (T_EDIT | T_POSE)) { @@ -325,7 +328,14 @@ void applyProject(TransInfo *t) mul_m3_v3(td->smtx, tvec); - add_v3_v3(td->loc, tvec); + if ((t->flag & T_PROP_EDIT) == 0) { + add_v3_v3(td->loc, tvec); + } + else { + add_v3_v3(tvec, td->loc); + interp_v3_v3v3(td->loc, td->loc, tvec, td->factor); + } + } } From 3e5f6293b6f73531d9765c0156ec762470a44fc2 Mon Sep 17 00:00:00 2001 From: Sergej Reich Date: Tue, 19 Feb 2013 20:04:08 +0000 Subject: [PATCH 074/182] rigidbody: Don't run simulation if cache is baked In rare cases this would allow the simulation to run before being initialized (if cache is baked and reading cache fails after undo or loading a file). --- source/blender/blenkernel/intern/rigidbody.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 66edfe2fe15..caa344f862e 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -1259,7 +1259,7 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime) } /* advance simulation, we can only step one frame forward */ - if (ctime == rbw->ltime + 1) { + if (ctime == rbw->ltime + 1 && !(cache->flag & PTCACHE_BAKED)) { /* write cache for first frame when on second frame */ if (rbw->ltime == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact == 0)) { BKE_ptcache_write(&pid, startframe); From 134537b65baf7fead290f37ae875801fe0784b34 Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Wed, 20 Feb 2013 00:06:31 +0000 Subject: [PATCH 075/182] fix #34049: Collada importer doesn't import armature. Added support for 'rootless' armature similar to Maya. --- source/blender/collada/DocumentImporter.cpp | 26 +++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index b1103d78394..1b726192079 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -252,8 +252,9 @@ void DocumentImporter::finish() for (std::vector::iterator it = vscenes.begin(); it != vscenes.end(); it++) { const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes(); - for (unsigned int i = 0; i < roots.getCount(); i++) + for (unsigned int i = 0; i < roots.getCount(); i++) { translate_anim_recursive(roots[i], NULL, NULL); + } } if (libnode_ob.size()) { @@ -312,13 +313,19 @@ void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW #endif unsigned int i; + //for (i = 0; i < 4; i++) // ob = anim_importer.translate_Animations(node, root_map, object_map, FW_object_map); - COLLADAFW::NodePointerArray &children = node->getChildNodes(); - for (i = 0; i < children.getCount(); i++) { - translate_anim_recursive(children[i], node, NULL); + if (node->getType() == COLLADAFW::Node::JOINT && par == NULL) { + translate_anim_recursive(node, node, parob); + } + else { + COLLADAFW::NodePointerArray &children = node->getChildNodes(); + for (i = 0; i < children.getCount(); i++) { + translate_anim_recursive(children[i], node, NULL); + } } } @@ -465,7 +472,18 @@ std::vector *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA name.c_str()); if (is_joint) { + if (parent_node == NULL) { + par = bc_add_object(sce, OB_ARMATURE, std::string("Armature").c_str()); + //anim_importer.read_node_transform(node, par); + objects_done->push_back(par); + object_map.insert(std::make_pair(node->getUniqueId(), par)); + node_map[node->getUniqueId()] = node; + } armature_importer.add_joint(node, parent_node == NULL || parent_node->getType() != COLLADAFW::Node::JOINT, par, sce); + + if (parent_node == NULL) { + return objects_done; + } } else { COLLADAFW::InstanceGeometryPointerArray &geom = node->getInstanceGeometries(); From 7337c2d4c2a84b7a0b3e212d76aa2e3b6fca8f9a Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Wed, 20 Feb 2013 00:13:34 +0000 Subject: [PATCH 076/182] fix #34049: Collada importer doesn't import armature. Added some comments to the program code for better understanding. --- source/blender/collada/DocumentImporter.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index 1b726192079..17a1c7f1e18 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -319,6 +319,9 @@ void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW anim_importer.translate_Animations(node, root_map, object_map, FW_object_map); if (node->getType() == COLLADAFW::Node::JOINT && par == NULL) { + // For Skeletons without root node we have to simulate the + // root node here and recursively enter the same function + // XXX: maybe this can be made more elegant. translate_anim_recursive(node, node, parob); } else { @@ -473,8 +476,9 @@ std::vector *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA if (is_joint) { if (parent_node == NULL) { + // A Joint on root level is a skeleton without root node. + // Here we add the armature "on the fly": par = bc_add_object(sce, OB_ARMATURE, std::string("Armature").c_str()); - //anim_importer.read_node_transform(node, par); objects_done->push_back(par); object_map.insert(std::make_pair(node->getUniqueId(), par)); node_map[node->getUniqueId()] = node; @@ -482,6 +486,8 @@ std::vector *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA armature_importer.add_joint(node, parent_node == NULL || parent_node->getType() != COLLADAFW::Node::JOINT, par, sce); if (parent_node == NULL) { + // for skeletons without root node all has been done above. + // Skeletons with root node are handled further down. return objects_done; } } From 6adb526f31fb14d800861a85ea5e565932fae162 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 20 Feb 2013 00:44:18 +0000 Subject: [PATCH 077/182] change to proportional editing suggested by Jeroen Hoolmans, don't interpolate projection, just project all points within the PET radius. --- source/blender/editors/transform/transform_snap.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index e95fc6d7bb9..2efd35327c7 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -328,14 +328,7 @@ void applyProject(TransInfo *t) mul_m3_v3(td->smtx, tvec); - if ((t->flag & T_PROP_EDIT) == 0) { - add_v3_v3(td->loc, tvec); - } - else { - add_v3_v3(tvec, td->loc); - interp_v3_v3v3(td->loc, td->loc, tvec, td->factor); - } - + add_v3_v3(td->loc, tvec); } } From 2f0eec488c7c634a843aaaa0abdd33a4e131422b Mon Sep 17 00:00:00 2001 From: Sergej Reich Date: Wed, 20 Feb 2013 00:45:53 +0000 Subject: [PATCH 078/182] rigidbody: Properly handle constrained objects not having rigid bodies This is a pretty rare case that can be triggered by switching rigid body and constraint groups before simulation was validated. Code checked for existing physics objects but was missing else block. --- source/blender/blenkernel/intern/rigidbody.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index caa344f862e..c2fd6a9f54a 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -635,6 +635,9 @@ void BKE_rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, shor break; } } + else { /* can't create constraint without both rigid bodies */ + return; + } RB_constraint_set_enabled(rbc->physics_constraint, rbc->flag & RBC_FLAG_ENABLED); From c22e52f4090943e0149924b5d370cac863c8700a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 20 Feb 2013 01:23:34 +0000 Subject: [PATCH 079/182] remove unneeded call to RNA_property_enum_get(), the icon was always overwritten after. --- source/blender/editors/interface/interface_templates.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index a9227158a20..8e4d0289f78 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -1581,7 +1581,8 @@ static uiBlock *icon_view_menu(bContext *C, ARegion *ar, void *arg_litem) /* arg_litem is malloced, can be freed by parent button */ cb = *((RNAUpdateCb *)arg_litem); - icon = RNA_property_enum_get(&cb.ptr, cb.prop); + /* unused */ + // icon = RNA_property_enum_get(&cb.ptr, cb.prop); block = uiBeginBlock(C, ar, "_popup", UI_EMBOSS); uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_REDRAW); From 7f8d597c7983ed9d196402fc441ba510414e0c0f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 20 Feb 2013 01:36:35 +0000 Subject: [PATCH 080/182] fix [#32294] Navmesh crashed if on creation navmesh is also selected thanks to Sv. Lockal for investigating and providing the fix. --- source/blender/editors/mesh/editmesh_utils.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index d62eba9728c..fd90246f791 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -136,8 +136,10 @@ void EDBM_mesh_clear(BMEditMesh *em) /* free tessellation data */ em->tottri = 0; - if (em->looptris) + if (em->looptris) { MEM_freeN(em->looptris); + em->looptris = NULL; + } } void EDBM_stats_update(BMEditMesh *em) From 5d04d06d76f0f48c0bc42c223b204b062938df04 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 20 Feb 2013 08:39:31 +0000 Subject: [PATCH 081/182] Fix drawing of translated strings (can't use _ascii version of BLF_draw in these cases, when WITH_INTERNATIONAL is defined we need unicode support). --- .../blender/editors/space_view3d/view3d_draw.c | 17 +++++++++++++++-- source/blender/editors/transform/transform.c | 4 ++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index a34b4c5157b..4aaa3332252 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -854,8 +854,13 @@ static void draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect) { RegionView3D *rv3d = ar->regiondata; const char *name = view3d_get_name(v3d, rv3d); + /* XXX 24 may be a bit small for unicode languages (Chinese in utf-8...) */ +#ifdef WITH_INTERNATIONAL + char tmpstr[32]; +#else char tmpstr[24]; - +#endif + if (v3d->localvd) { BLI_snprintf(tmpstr, sizeof(tmpstr), IFACE_("%s (Local)"), name); name = tmpstr; @@ -863,7 +868,11 @@ static void draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect) if (name) { UI_ThemeColor(TH_TEXT_HI); +#ifdef WITH_INTERNATIONAL + BLF_draw_default(U.widget_unit + rect->xmin, rect->ymax - U.widget_unit, 0.0f, name, sizeof(tmpstr)); +#else BLF_draw_default_ascii(U.widget_unit + rect->xmin, rect->ymax - U.widget_unit, 0.0f, name, sizeof(tmpstr)); +#endif } } @@ -2854,8 +2863,12 @@ static void draw_viewport_fps(Scene *scene, rcti *rect) UI_ThemeColor(TH_TEXT_HI); BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %i"), (int)(fps + 0.5f)); } - + +#ifdef WITH_INTERNATIONAL + BLF_draw_default(rect->xmin + U.widget_unit, rect->ymax - U.widget_unit, 0.0f, printable, sizeof(printable)); +#else BLF_draw_default_ascii(rect->xmin + U.widget_unit, rect->ymax - U.widget_unit, 0.0f, printable, sizeof(printable)); +#endif } static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const char **grid_unit); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 1a7a425fbc9..ea82ebb9234 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1686,7 +1686,11 @@ static void drawAutoKeyWarning(TransInfo *UNUSED(t), ARegion *ar) * - original color was red to match the icon, but that clashes badly with a less nasty border */ UI_ThemeColorShade(TH_TEXT_HI, -50); +#ifdef WITH_INTERNATIONAL + BLF_draw_default(xco, ar->winy - 17, 0.0f, printable, sizeof(printable)); +#else BLF_draw_default_ascii(xco, ar->winy - 17, 0.0f, printable, sizeof(printable)); +#endif /* autokey recording icon... */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); From 1f88ee6213ed5e8b60597034d52188256448b104 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 20 Feb 2013 11:29:43 +0000 Subject: [PATCH 082/182] Fix #34299: Motion Tracking 20x slower under Windows Root of the issue goes to SSBA library which didn't work properly when using optimization in MSVC. It was worked around by disabling optimization for libmv, which is in fact shame and shouldn't have been done. It seems after some changes optimization does not affect on SSBA code, but enabling optimization could be risky so close to release. For now solved by splitting SSBA to separate CMake/SCons library, disabling optimization only for this particular library and enabling optimization for rest of libmv. Tested on all files which used to fail with optimization enabled in SSBA and all of them works the same as before. Tracking speed is significantly higher now. After release we'll enable optimization for SSBA as well, so there'll be no crappy build setup. Later we'll replace old SSBA library with new BA code based on Ceres. Bundle script would be broken for until then, so better not to use it. --- extern/libmv/CMakeLists.txt | 21 +------ extern/libmv/SConscript | 21 +------ extern/libmv/third_party/CMakeLists.txt | 1 + extern/libmv/third_party/SConscript | 1 + extern/libmv/third_party/ssba/CMakeLists.txt | 61 +++++++++++++++++++ extern/libmv/third_party/ssba/SConscript | 35 +++++++++++ .../blender/editors/space_clip/tracking_ops.c | 4 +- source/creator/CMakeLists.txt | 1 + 8 files changed, 104 insertions(+), 41 deletions(-) create mode 100644 extern/libmv/third_party/ssba/CMakeLists.txt create mode 100644 extern/libmv/third_party/ssba/SConscript diff --git a/extern/libmv/CMakeLists.txt b/extern/libmv/CMakeLists.txt index 6b5a9a3b67a..aabf2324372 100644 --- a/extern/libmv/CMakeLists.txt +++ b/extern/libmv/CMakeLists.txt @@ -26,8 +26,6 @@ # If you're doing changes in this file, please update template # in that script too -add_subdirectory(third_party) - set(INC . ../colamd/Include @@ -86,8 +84,6 @@ set(SRC third_party/gflags/gflags_completions.cc third_party/gflags/gflags_reporting.cc third_party/ldl/Source/ldl.c - third_party/ssba/Geometry/v3d_metricbundle.cpp - third_party/ssba/Math/v3d_optimization.cpp libmv-capi.h libmv/base/id_generator.h @@ -148,13 +144,6 @@ set(SRC third_party/ldl/Include/ldl.h third_party/msinttypes/inttypes.h third_party/msinttypes/stdint.h - third_party/ssba/Geometry/v3d_cameramatrix.h - third_party/ssba/Geometry/v3d_distortion.h - third_party/ssba/Geometry/v3d_metricbundle.h - third_party/ssba/Math/v3d_linear.h - third_party/ssba/Math/v3d_linear_utils.h - third_party/ssba/Math/v3d_mathutilities.h - third_party/ssba/Math/v3d_optimization.h ) if(WIN32) @@ -193,14 +182,6 @@ if(WIN32) third_party/msinttypes ) endif() - - if(MSVC) - set(MSVC_OFLAGS O1 O2 Ox) - foreach(FLAG ${MSVC_OFLAGS}) - string(REPLACE "${FLAG}" "Od" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") - string(REPLACE "${FLAG}" "Od" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}") - endforeach() - endif() else() list(APPEND SRC third_party/glog/src/demangle.cc @@ -245,3 +226,5 @@ add_definitions( ) blender_add_lib(extern_libmv "${SRC}" "${INC}" "${INC_SYS}") + +add_subdirectory(third_party) diff --git a/extern/libmv/SConscript b/extern/libmv/SConscript index b47086f3e91..5f790ab3ae6 100644 --- a/extern/libmv/SConscript +++ b/extern/libmv/SConscript @@ -11,10 +11,6 @@ Import('env') defs = [] -cflags_libmv = Split(env['CFLAGS']) -ccflags_libmv = Split(env['CCFLAGS']) -cxxflags_libmv = Split(env['CXXFLAGS']) - defs.append('V3DLIB_ENABLE_SUITESPARSE') defs.append('GOOGLE_GLOG_DLL_DECL=') @@ -27,8 +23,6 @@ src += env.Glob('libmv/tracking/*.cc') src += env.Glob('third_party/fast/*.c') src += env.Glob('third_party/gflags/*.cc') src += env.Glob('third_party/ldl/Source/*.c') -src += env.Glob('third_party/ssba/Geometry/*.cpp') -src += env.Glob('third_party/ssba/Math/*.cpp') incs = '. ../Eigen3 third_party/ceres/include' incs += ' ' + env['BF_PNG_INC'] @@ -41,19 +35,6 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', ' src += ['./third_party/glog/src/logging.cc', './third_party/glog/src/raw_logging.cc', './third_party/glog/src/utilities.cc', './third_party/glog/src/vlog_is_on.cc'] src += ['./third_party/glog/src/windows/port.cc'] - - if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): - cflags_libmv.append('/Od') - ccflags_libmv.append('/Od') - cxxflags_libmv.append('/Od') - - if not env['BF_DEBUG']: - defs.append('NDEBUG') - else: - if not env['BF_DEBUG']: - cflags_libmv += Split(env['REL_CFLAGS']) - ccflags_libmv += Split(env['REL_CCFLAGS']) - cxxflags_libmv += Split(env['REL_CXXFLAGS']) else: src += env.Glob("third_party/glog/src/*.cc") incs += ' ./third_party/glog/src' @@ -64,6 +45,6 @@ else: incs += ' ./third_party/ssba ./third_party/ldl/Include ../colamd/Include' -env.BlenderLib ( libname = 'extern_libmv', sources=src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137], compileflags=cflags_libmv, cc_compileflags=ccflags_libmv, cxx_compileflags=cxxflags_libmv ) +env.BlenderLib ( libname = 'extern_libmv', sources=src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137] ) SConscript(['third_party/SConscript']) diff --git a/extern/libmv/third_party/CMakeLists.txt b/extern/libmv/third_party/CMakeLists.txt index 6212fe480b1..7989d97345c 100644 --- a/extern/libmv/third_party/CMakeLists.txt +++ b/extern/libmv/third_party/CMakeLists.txt @@ -1,2 +1,3 @@ +add_subdirectory(ssba) add_subdirectory(ceres) diff --git a/extern/libmv/third_party/SConscript b/extern/libmv/third_party/SConscript index b05692e385f..2e30650f656 100644 --- a/extern/libmv/third_party/SConscript +++ b/extern/libmv/third_party/SConscript @@ -1,3 +1,4 @@ #!/usr/bin/python +SConscript(['ssba/SConscript']) SConscript(['ceres/SConscript']) diff --git a/extern/libmv/third_party/ssba/CMakeLists.txt b/extern/libmv/third_party/ssba/CMakeLists.txt new file mode 100644 index 00000000000..f73a6137d6f --- /dev/null +++ b/extern/libmv/third_party/ssba/CMakeLists.txt @@ -0,0 +1,61 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2013, Blender Foundation +# All rights reserved. +# +# Contributor(s): Blender Foundation, +# Sergey Sharybin +# +# ***** END GPL LICENSE BLOCK ***** + +set(INC + . + ../ldl/Include + ../../../colamd/Include +) + +set(INC_SYS +) + +set(SRC + Geometry/v3d_metricbundle.cpp + Math/v3d_optimization.cpp + + Geometry/v3d_cameramatrix.h + Geometry/v3d_distortion.h + Geometry/v3d_metricbundle.h + Math/v3d_linear.h + Math/v3d_linear_utils.h + Math/v3d_mathutilities.h + Math/v3d_optimization.h +) + +if(WIN32) + if(MSVC) + set(MSVC_OFLAGS O1 O2 Ox) + foreach(FLAG ${MSVC_OFLAGS}) + string(REPLACE "${FLAG}" "Od" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") + string(REPLACE "${FLAG}" "Od" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}") + endforeach() + endif() +endif() + +add_definitions( + -DV3DLIB_ENABLE_SUITESPARSE +) + +blender_add_lib(extern_ssba "${SRC}" "${INC}" "${INC_SYS}") diff --git a/extern/libmv/third_party/ssba/SConscript b/extern/libmv/third_party/ssba/SConscript new file mode 100644 index 00000000000..598415d0039 --- /dev/null +++ b/extern/libmv/third_party/ssba/SConscript @@ -0,0 +1,35 @@ +#!/usr/bin/python + +import sys +import os + +Import('env') + +defs = [] + +cflags_ssba = Split(env['CFLAGS']) +ccflags_ssba = Split(env['CCFLAGS']) +cxxflags_ssba = Split(env['CXXFLAGS']) + +defs.append('V3DLIB_ENABLE_SUITESPARSE') + +src = env.Glob('Geometry/*.cpp') +src += env.Glob('Math/*.cpp') + +incs = '. ../ldl/Include ../../../colamd/Include' + +if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): + if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): + cflags_ssba.append('/Od') + ccflags_ssba.append('/Od') + cxxflags_ssba.append('/Od') + + if not env['BF_DEBUG']: + defs.append('NDEBUG') + else: + if not env['BF_DEBUG']: + cflags_ssba += Split(env['REL_CFLAGS']) + ccflags_ssba += Split(env['REL_CCFLAGS']) + cxxflags_ssba += Split(env['REL_CXXFLAGS']) + +env.BlenderLib ( libname = 'extern_ssba', sources=src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137], compileflags=cflags_ssba, cc_compileflags=ccflags_ssba, cxx_compileflags=cxxflags_ssba ) diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index 56a890c714a..77ed197c1d7 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -1105,7 +1105,7 @@ static void track_markers_startjob(void *tmv, short *stop, short *do_update, flo { TrackMarkersJob *tmj = (TrackMarkersJob *)tmv; int framenr = tmj->sfra; - //double t = PIL_check_seconds_timer(); + // double t = PIL_check_seconds_timer(); while (framenr != tmj->efra) { if (tmj->delay > 0) { @@ -1141,7 +1141,7 @@ static void track_markers_startjob(void *tmv, short *stop, short *do_update, flo break; } - //printf("Tracking time: %lf\n", PIL_check_seconds_timer()-t); + // printf("Tracking time: %lf\n", PIL_check_seconds_timer()-t); } static void track_markers_updatejob(void *tmv) diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index bb5f34167bc..a5d7763487f 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -924,6 +924,7 @@ endif() if(WITH_LIBMV) list(APPEND BLENDER_SORTED_LIBS extern_libmv) list(APPEND BLENDER_SORTED_LIBS extern_ceres) + list(APPEND BLENDER_SORTED_LIBS extern_ssba) endif() if(WITH_MOD_CLOTH_ELTOPO) From 705d2ab417688976a50897d098ad25ab3ef3e6c8 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 20 Feb 2013 11:41:33 +0000 Subject: [PATCH 083/182] Correction to previous release -- scons on linux was broken --- extern/libmv/SConscript | 4 ---- 1 file changed, 4 deletions(-) diff --git a/extern/libmv/SConscript b/extern/libmv/SConscript index 5f790ab3ae6..42e96e230ea 100644 --- a/extern/libmv/SConscript +++ b/extern/libmv/SConscript @@ -38,10 +38,6 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', ' else: src += env.Glob("third_party/glog/src/*.cc") incs += ' ./third_party/glog/src' - if not env['BF_DEBUG']: - cflags_libmv += Split(env['REL_CFLAGS']) - ccflags_libmv += Split(env['REL_CCFLAGS']) - cxxflags_libmv += Split(env['REL_CXXFLAGS']) incs += ' ./third_party/ssba ./third_party/ldl/Include ../colamd/Include' From ea99b9a392bddec4ea58b816b1fb66f78c77ff6e Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 20 Feb 2013 12:07:27 +0000 Subject: [PATCH 084/182] Made ldl code a part of extern_ssba library, otherwise gcc fails to find ldl symbols because order of libraries seems to be critical for gcc linker. A bit stupid, but that's how linker works.. Both CMake and SCons shall work fine on linux now. --- extern/libmv/CMakeLists.txt | 3 --- extern/libmv/SConscript | 3 +-- extern/libmv/third_party/ssba/CMakeLists.txt | 3 +++ extern/libmv/third_party/ssba/SConscript | 1 + source/creator/CMakeLists.txt | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/extern/libmv/CMakeLists.txt b/extern/libmv/CMakeLists.txt index aabf2324372..0cf2211fe88 100644 --- a/extern/libmv/CMakeLists.txt +++ b/extern/libmv/CMakeLists.txt @@ -35,7 +35,6 @@ set(INC set(INC_SYS ../Eigen3 third_party/ssba - third_party/ldl/Include ${PNG_INCLUDE_DIR} ${ZLIB_INCLUDE_DIRS} ) @@ -83,7 +82,6 @@ set(SRC third_party/gflags/gflags.cc third_party/gflags/gflags_completions.cc third_party/gflags/gflags_reporting.cc - third_party/ldl/Source/ldl.c libmv-capi.h libmv/base/id_generator.h @@ -141,7 +139,6 @@ set(SRC third_party/gflags/gflags/gflags.h third_party/gflags/mutex.h third_party/gflags/util.h - third_party/ldl/Include/ldl.h third_party/msinttypes/inttypes.h third_party/msinttypes/stdint.h ) diff --git a/extern/libmv/SConscript b/extern/libmv/SConscript index 42e96e230ea..a0ab5bd61d7 100644 --- a/extern/libmv/SConscript +++ b/extern/libmv/SConscript @@ -22,7 +22,6 @@ src += env.Glob('libmv/simple_pipeline/*.cc') src += env.Glob('libmv/tracking/*.cc') src += env.Glob('third_party/fast/*.c') src += env.Glob('third_party/gflags/*.cc') -src += env.Glob('third_party/ldl/Source/*.c') incs = '. ../Eigen3 third_party/ceres/include' incs += ' ' + env['BF_PNG_INC'] @@ -39,7 +38,7 @@ else: src += env.Glob("third_party/glog/src/*.cc") incs += ' ./third_party/glog/src' -incs += ' ./third_party/ssba ./third_party/ldl/Include ../colamd/Include' +incs += ' ./third_party/ssba ../colamd/Include' env.BlenderLib ( libname = 'extern_libmv', sources=src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137] ) diff --git a/extern/libmv/third_party/ssba/CMakeLists.txt b/extern/libmv/third_party/ssba/CMakeLists.txt index f73a6137d6f..72379625396 100644 --- a/extern/libmv/third_party/ssba/CMakeLists.txt +++ b/extern/libmv/third_party/ssba/CMakeLists.txt @@ -42,6 +42,9 @@ set(SRC Math/v3d_linear_utils.h Math/v3d_mathutilities.h Math/v3d_optimization.h + + ../ldl/Source/ldl.c + ../ldl/Include/ldl.h ) if(WIN32) diff --git a/extern/libmv/third_party/ssba/SConscript b/extern/libmv/third_party/ssba/SConscript index 598415d0039..667b40f929b 100644 --- a/extern/libmv/third_party/ssba/SConscript +++ b/extern/libmv/third_party/ssba/SConscript @@ -15,6 +15,7 @@ defs.append('V3DLIB_ENABLE_SUITESPARSE') src = env.Glob('Geometry/*.cpp') src += env.Glob('Math/*.cpp') +src += env.Glob('../ldl/Source/*.c') incs = '. ../ldl/Include ../../../colamd/Include' diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index a5d7763487f..bb10bdd0bae 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -923,8 +923,8 @@ endif() if(WITH_LIBMV) list(APPEND BLENDER_SORTED_LIBS extern_libmv) - list(APPEND BLENDER_SORTED_LIBS extern_ceres) list(APPEND BLENDER_SORTED_LIBS extern_ssba) + list(APPEND BLENDER_SORTED_LIBS extern_ceres) endif() if(WITH_MOD_CLOTH_ELTOPO) From 4c287f1d4dcdef959368de4dca9b1e5d7244b5f7 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 20 Feb 2013 12:10:05 +0000 Subject: [PATCH 085/182] Fix shadow pass issue with non-progressive render shadow pass with emitting meshes and world MIS. --- intern/cycles/render/light.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index ccc6c5142bd..47e9dd8e7f5 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -360,10 +360,10 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen /* bit of an ugly hack to compensate for emitting triangles influencing * amount of samples we get for this pass */ - if(scene->integrator->progressive && kintegrator->pdf_triangles != 0.0f) - kfilm->pass_shadow_scale = 0.5f; - else - kfilm->pass_shadow_scale = 1.0f; + kfilm->pass_shadow_scale = 1.0f; + + if(kintegrator->pdf_triangles != 0.0f) + kfilm->pass_shadow_scale *= 0.5f; if(num_background_lights < num_lights) kfilm->pass_shadow_scale *= (float)(num_lights - num_background_lights)/(float)num_lights; From e55848179aa7d79b0bbacf89e7f3737a857923cd Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 20 Feb 2013 13:03:14 +0000 Subject: [PATCH 086/182] Fix for blenderplayer build after recent motrack changes --- source/blenderplayer/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt index fb06c5e4477..cd3edc11c46 100644 --- a/source/blenderplayer/CMakeLists.txt +++ b/source/blenderplayer/CMakeLists.txt @@ -167,6 +167,7 @@ endif() if(WITH_LIBMV) list(APPEND BLENDER_SORTED_LIBS extern_libmv) + list(APPEND BLENDER_SORTED_LIBS extern_ssba) list(APPEND BLENDER_SORTED_LIBS extern_ceres) endif() From d9d1f8e58febe60fdd5974ad46dc299c617f1782 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 20 Feb 2013 13:07:28 +0000 Subject: [PATCH 087/182] Raise a bit Header string fixed length, else some translations (e.g. Japanese) have not enough room! --- source/blender/editors/mesh/editmesh_knife.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 98fa9d10ab9..d7dbe3506b1 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -214,7 +214,7 @@ static void knife_input_ray_segment(KnifeTool_OpData *kcd, const float mval[2], static void knife_update_header(bContext *C, KnifeTool_OpData *kcd) { - #define HEADER_LENGTH 190 + #define HEADER_LENGTH 256 char header[HEADER_LENGTH]; BLI_snprintf(header, HEADER_LENGTH, IFACE_("LMB: define cut lines, Return/Spacebar: confirm, Esc or RMB: cancel, " From f844b79577961544d585750f15f6bc7bc88ab031 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 20 Feb 2013 13:41:29 +0000 Subject: [PATCH 088/182] Quick fix: translating header's string with some languages (complex scripts, like Japanese or Hindi) generates a very odd segfault! Have really no time to fix now, will try in a few hours, but safer to do this for now! --- source/blender/editors/space_info/info_stats.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c index 976769752f9..5a8a77f7350 100644 --- a/source/blender/editors/space_info/info_stats.c +++ b/source/blender/editors/space_info/info_stats.c @@ -367,9 +367,9 @@ static void stats_string(Scene *scene) mmap_in_use = MEM_get_mapped_memory_in_use(); /* get memory statistics */ - s = memstr + sprintf(memstr, IFACE_(" | Mem:%.2fM"), (double)((mem_in_use - mmap_in_use) >> 10) / 1024.0); + s = memstr + sprintf(memstr, " | Mem:%.2fM", (double)((mem_in_use - mmap_in_use) >> 10) / 1024.0); if (mmap_in_use) - sprintf(s, IFACE_(" (%.2fM)"), (double)((mmap_in_use) >> 10) / 1024.0); + sprintf(s, " (%.2fM)", (double)((mmap_in_use) >> 10) / 1024.0); s = stats->infostr; @@ -377,32 +377,32 @@ static void stats_string(Scene *scene) if (scene->obedit) { if (BKE_keyblock_from_object(scene->obedit)) - s += sprintf(s, IFACE_("(Key) ")); + s += sprintf(s, "(Key) "); if (scene->obedit->type == OB_MESH) { - s += sprintf(s, IFACE_("Verts:%d/%d | Edges:%d/%d | Faces:%d/%d | Tris:%d"), + s += sprintf(s, "Verts:%d/%d | Edges:%d/%d | Faces:%d/%d | Tris:%d", stats->totvertsel, stats->totvert, stats->totedgesel, stats->totedge, stats->totfacesel, stats->totface, stats->tottri); } else if (scene->obedit->type == OB_ARMATURE) { - s += sprintf(s, IFACE_("Verts:%d/%d | Bones:%d/%d"), stats->totvertsel, stats->totvert, stats->totbonesel, + s += sprintf(s, "Verts:%d/%d | Bones:%d/%d", stats->totvertsel, stats->totvert, stats->totbonesel, stats->totbone); } else { - s += sprintf(s, IFACE_("Verts:%d/%d"), stats->totvertsel, stats->totvert); + s += sprintf(s, "Verts:%d/%d", stats->totvertsel, stats->totvert); } strcat(s, memstr); } else if (ob && (ob->mode & OB_MODE_POSE)) { - s += sprintf(s, IFACE_("Bones:%d/%d %s"), + s += sprintf(s, "Bones:%d/%d %s", stats->totbonesel, stats->totbone, memstr); } else if (stats_is_object_dynamic_topology_sculpt(ob)) { - s += sprintf(s, IFACE_("Verts:%d | Tris:%d"), stats->totvert, stats->tottri); + s += sprintf(s, "Verts:%d | Tris:%d", stats->totvert, stats->tottri); } else { - s += sprintf(s, IFACE_("Verts:%d | Faces:%d | Tris:%d | Objects:%d/%d | Lamps:%d/%d%s"), + 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); } From a8ebc1b2de13c0f473b8cb22036f54dee8e1f393 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 20 Feb 2013 14:22:36 +0000 Subject: [PATCH 089/182] edits to document uploading script so the latest release docs can always be found at: http://www.blender.org/documentation/blender_python_api Easier for linking wiki docs. --- doc/python_api/sphinx_doc_gen.py | 4 +++- doc/python_api/sphinx_doc_gen.sh | 8 ++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py index 3170a2ef469..09e844adae3 100644 --- a/doc/python_api/sphinx_doc_gen.py +++ b/doc/python_api/sphinx_doc_gen.py @@ -1483,7 +1483,9 @@ def write_sphinx_conf_py(basepath): def execfile(filepath): global_namespace = {"__file__": filepath, "__name__": "__main__"} - exec(compile(open(filepath).read(), filepath, 'exec'), global_namespace) + file_handle = open(filepath) + exec(compile(file_handle.read(), filepath, 'exec'), global_namespace) + file_handle.close() def write_rst_contents(basepath): diff --git a/doc/python_api/sphinx_doc_gen.sh b/doc/python_api/sphinx_doc_gen.sh index 92461961920..14919f678be 100755 --- a/doc/python_api/sphinx_doc_gen.sh +++ b/doc/python_api/sphinx_doc_gen.sh @@ -32,8 +32,7 @@ blender_version_char=$(grep BLENDER_VERSION_CHAR $blender_srcdir/source/blender/ blender_version_cycle=$(grep BLENDER_VERSION_CYCLE $blender_srcdir/source/blender/blenkernel/BKE_blender.h | awk '{print $3}') blender_subversion=$(grep BLENDER_SUBVERSION $blender_srcdir/source/blender/blenkernel/BKE_blender.h | awk '{print $3}') -if [ "$blender_version_cycle" == "release" ] -then +if [ "$blender_version_cycle" == "release" ] ; then BLENDER_VERSION=$(expr $blender_version / 100)_$(expr $blender_version % 100)$blender_version_char"_release" else BLENDER_VERSION=$(expr $blender_version / 100)_$(expr $blender_version % 100)_$blender_subversion @@ -109,6 +108,11 @@ if $DO_UPLOAD ; then # better redirect ssh $SSH_USER@emo.blender.org 'echo "Redirecting...Redirecting..." > '$SSH_UPLOAD'/250PythonDoc/index.html' + # redirect for release only so wiki can point here + if [ "$blender_version_cycle" == "release" ] ; then + ssh $SSH_USER@emo.blender.org 'echo "Redirecting...Redirecting..." > '$SSH_UPLOAD'/blender_python_api/index.html' + fi + if $DO_OUT_PDF ; then # rename so local PDF has matching name. rsync --progress -avze "ssh -p 22" $SPHINXBASE/sphinx-out/blender_python_reference_$BLENDER_VERSION.pdf $SSH_HOST:$SSH_UPLOAD_FULL/blender_python_reference_$BLENDER_VERSION.pdf From 7175549de618a88b8f08678b7003a2a6565b3370 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 20 Feb 2013 14:53:31 +0000 Subject: [PATCH 090/182] Fix DPI not taken into account for header text (e.g. during transform). --- 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 8afe07b4689..63232b8c455 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -446,7 +446,7 @@ void ED_region_do_draw(bContext *C, ARegion *ar) glClear(GL_COLOR_BUFFER_BIT); UI_ThemeColor(TH_TEXT); - BLF_draw_default(20, 8, 0.0f, ar->headerstr, BLF_DRAW_STR_DUMMY_MAX); + BLF_draw_default(UI_UNIT_X, 0.4f*UI_UNIT_Y, 0.0f, ar->headerstr, BLF_DRAW_STR_DUMMY_MAX); } else if (at->draw) { at->draw(C, ar); From b9333b304ca78cc7abccfd84222b022e214ada41 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 20 Feb 2013 15:06:13 +0000 Subject: [PATCH 091/182] Fix visible seams on normal map bake due to clear colour being black: This is a special case, tangent space normal maps should be cleared to 0.5, 0.5, 1.0. This is good practice but there's no reason why not to automate this (for artists whose bump map fu may be a bit shallow). Thanks to Morten Mikkelsen for reporting. --- source/blender/editors/object/object_bake.c | 25 +++++++++++++++++---- source/blender/render/intern/source/bake.c | 11 ++++++--- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index 322ba99593e..a680230fb32 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -257,11 +257,18 @@ static DerivedMesh *multiresbake_create_hiresdm(Scene *scene, Object *ob, int *l return dm; } -static void clear_images(MTFace *mtface, int totface) +typedef enum ClearFlag { + CLEAR_NORMAL = 1 +} ClearFlag; + + +static void clear_images(MTFace *mtface, int totface, ClearFlag flag) { int a; 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}; + const float nor_alpha[4] = {0.5f, 0.5f, 1.0f, 0.0f}; + const float nor_solid[4] = {0.5f, 0.5f, 1.0f, 1.0f}; for (a = 0; a < totface; a++) mtface[a].tpage->id.flag &= ~LIB_DOIT; @@ -272,7 +279,11 @@ static void clear_images(MTFace *mtface, int totface) if ((ima->id.flag & LIB_DOIT) == 0) { ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); - IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid); + if (flag == CLEAR_NORMAL) + IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? nor_alpha : nor_solid); + else + IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid); + ima->id.flag |= LIB_DOIT; BKE_image_release_ibuf(ima, ibuf, NULL); @@ -300,7 +311,10 @@ static int multiresbake_image_exec_locked(bContext *C, wmOperator *op) ob = base->object; me = (Mesh *)ob->data; - clear_images(me->mtface, me->totface); + if (scene->r.bake_mode == RE_BAKE_NORMALS && scene->r.bake_normal_space == R_BAKE_SPACE_TANGENT) + clear_images(me->mtface, me->totface, CLEAR_NORMAL); + else + clear_images(me->mtface, me->totface, 0); } CTX_DATA_END; } @@ -395,7 +409,10 @@ static void multiresbake_startjob(void *bkv, short *stop, short *do_update, floa DerivedMesh *dm = data->lores_dm; MTFace *mtface = CustomData_get_layer(&dm->faceData, CD_MTFACE); - clear_images(mtface, dm->getNumTessFaces(dm)); + if (bkj->mode == RE_BAKE_NORMALS) + clear_images(mtface, dm->getNumTessFaces(dm), CLEAR_NORMAL); + else + clear_images(mtface, dm->getNumTessFaces(dm), 0); } } diff --git a/source/blender/render/intern/source/bake.c b/source/blender/render/intern/source/bake.c index cb6f9611bfd..7c5d6038e0a 100644 --- a/source/blender/render/intern/source/bake.c +++ b/source/blender/render/intern/source/bake.c @@ -648,6 +648,8 @@ static int get_next_bake_face(BakeShade *bs) 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}; + const float nor_alpha[4] = {0.5f, 0.5f, 1.0f, 0.0f}; + const float nor_solid[4] = {0.5f, 0.5f, 1.0f, 1.0f}; tface = RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0); @@ -684,9 +686,12 @@ static int get_next_bake_face(BakeShade *bs) if (ibuf->rect_float) imb_freerectImBuf(ibuf); /* clear image */ - if (R.r.bake_flag & R_BAKE_CLEAR) - IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid); - + if (R.r.bake_flag & R_BAKE_CLEAR) { + if (R.r.bake_mode == RE_BAKE_NORMALS && R.r.bake_normal_space == R_BAKE_SPACE_TANGENT) + IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? nor_alpha : nor_solid); + else + IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid); + } /* might be read by UI to set active image for display */ R.bakebuf = ima; } From f6f0ec6dfc56e201ae5490baecc7c913e9467a6f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 20 Feb 2013 15:34:31 +0000 Subject: [PATCH 092/182] increase openmp limit for release so low poly meshes don't use openmp threads (which can be slow) --- source/blender/blenkernel/BKE_DerivedMesh.h | 2 +- source/blender/bmesh/bmesh_class.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 5f504df5628..486834f9540 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -95,7 +95,7 @@ struct BMEditMesh; struct ListBase; struct PBVH; -#define DM_OMP_LIMIT 0 /* setting zero so we can catch bugs in OpenMP/BMesh */ +#define DM_OMP_LIMIT 10000 /* setting zero so we can catch bugs in OpenMP/BMesh */ /* number of sub-elements each mesh element has (for interpolation) */ #define SUB_ELEMS_VERT 0 diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h index e851a642b32..6dc0218da93 100644 --- a/source/blender/bmesh/bmesh_class.h +++ b/source/blender/bmesh/bmesh_class.h @@ -288,6 +288,6 @@ enum { * but should not error on valid cases */ #define BM_LOOP_RADIAL_MAX 10000 #define BM_NGON_MAX 100000 -#define BM_OMP_LIMIT 0 /* setting zero so we can catch bugs in OpenMP/BMesh */ +#define BM_OMP_LIMIT 10000 /* setting zero so we can catch bugs in OpenMP/BMesh */ #endif /* __BMESH_CLASS_H__ */ From 2605dd231f38cd07fb8029c74423528d42d23807 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Wed, 20 Feb 2013 16:05:29 +0000 Subject: [PATCH 093/182] Getting ready for the 2.66 release! - Version bump to 2.66 - Splash image by Lucas Falcao, selected by Jonathan Williamson, Andrew Price and Bart Veldhuizen. --- release/datafiles/splash.png | Bin 330539 -> 128911 bytes source/blender/blenkernel/BKE_blender.h | 8 ++++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/release/datafiles/splash.png b/release/datafiles/splash.png index 41284eff9c19c1920f9c68a24ebca19662df0cb3..7affcab8a820007502fd144ac412643fae11904c 100644 GIT binary patch literal 128911 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