from http://wiki.blender.org/index.php/Dev:2.5/Source/Development/Todo/Simple_Todos
This works for its intended purpose. It doesn't crash or freeze.
I knew nothing about the internals of blender. I just dove in after reading the simple todos list, and after days of coding and a rewrite, I managed to finish what "an experienced blender developer could accomplish in 4 hours or less."
This tool appears after pressing w in the uveditor in a popup that says:
Weld/Align
Weld
Straighten
Align Auto
Align X
Align Y
The submenu also appears as part of the UVs menu item on the UV/Image editor panel bar.
Only one file was changed.
To use this feature:
Select an open edge loop, press w, click on Straighten.
It finds the two endpoints, calculates a line connecting them, then moves every other point perpendicularly to the line onto the line
so that all the points lie on the "S axis."
When this tool is not used in this way, it doesn't behave in the way you might expect. It is currently only designed to straighten one line at a time.
For example,
If two lines are selected, It picks two points out of the four, maybe on the same line, maybe not, and straightens using those.
If a plus(meaning 5 points with one connected to four) is selected, it again picks two endpoints and straightens along that.
This could mean along a diagonal or along one of the lines of the plus.
When extra non-connected points are selected along with the line, they are also aligned to the line.
A closed loop(meaning circle) does not have a result as there are no endpoints to straighten on.
Similarly, it also fails to do anything if there are faces selected because I am assuming that you don't want to align faces to a line.
I(we(my brother and I)) have tested this thoroughly, and it works for normal usage.
This is a patch that does not need a review for "functional level (does this fit with Blender's design or roadmap)" as this was already done because it was in the todo list.
However, as a new coder I can't for sure tell you that I followed the coding style.
Please feel free to remove comments as those are for understanding the code before inclusion and do not need to be preserved.
I already removed print statements.
I hope this was thorough enough.
svn diff
Someone else misread the todo list and made a straighten tool for edit mode, not uvedit. I deemed that person's code unusable for my purposes for that reason.
Description
Event Timeline
I can add the patch in a comment but not as an attached file: everything below this line is from straighten.patch
Index: source/blender/editors/uvedit/uvedit_ops.c
===================================================================
--- source/blender/editors/uvedit/uvedit_ops.c (revision 38520)
+++ source/blender/editors/uvedit/uvedit_ops.c (working copy)
@@ -1057,6 +1057,129 @@
}
}
+ if(tool == 's') {
+ //pass 1&2 variables
+ int i, j;
+ int starttmpl=-1, connectedtostarttmpl, startcorner;
+ int endtmpl=-1, connectedtoendtmpl, endcorner;
+ MTFace *startface, *endface;
+ int itmpl, jtmpl;
+ EditVert *eve;
+ int pass;//first 2 passes find endpoints, 3rd pass moves middle points, 4th pass is fail-on-face-selected
+ EditFace *startefa, *endefa;
+
+ //pass 3 variables
+ double startx, starty, firstm, firstb, midx, midy;
+ double endx, endy, secondm, secondb, midmovedx, midmovedy;
+ double IsVertical_check=-1;//like my Java_Ish code?
+ double IsHorizontal_check=-1;
+
+ for(i=0, eve=em->verts.first; eve; eve=eve->next, i++)//give each point a unique name
+ eve->tmp.l = i;
+ for(pass=1; pass<=3; pass++) {//do this for each endpoint
+ if(pass==3){//calculate
+ startx=startface->uv[startcorner][0];
+ starty=startface->uv[startcorner][1];
+ endx=endface->uv[endcorner][0];
+ endy=endface->uv[endcorner][1];
+ firstm=(endy-starty)/(endx-startx);
+ firstb=starty-(firstm*startx);
+ secondm=-1/firstm;
+ if(startx==endx) { IsVertical_check=startx; }
+ if(starty==endy) { IsHorizontal_check=starty; }
+ }
+ for(efa= em->faces.first; efa; efa= efa->next) {//for each face
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);//get face
+ if(uvedit_face_visible(scene, ima, efa, tf)) {//if you can see it
+ if(uvedit_face_selected(scene, efa, tf)) {//if the face is selected, get out now!
+ pass=4;
+ break;
+ }
+ for(i=0; (i<3 || (i==3 && efa->v4)); i++) {//for each point of the face
+ itmpl=(*(&efa->v1 + i))->tmp.l;//get unique name for points
+ if(pass==3) {//move
+ if(uvedit_uv_selected(scene, efa, tf, i)) {
+ if(!(itmpl==starttmpl || itmpl==endtmpl)) {
+ if(IsVertical_check!=-1) { tf->uv[i][0]=IsVertical_check; }
+ if(IsHorizontal_check!=-1) { tf->uv[i][1]=IsHorizontal_check; }
+ if(IsVertical_check== -1&&-1 ==IsHorizontal_check) {
+ midx=tf->uv[i][0];
+ midy=tf->uv[i][1];
+ secondb=midy-(secondm*midx);
+ //y=m1x+b1
+ //y=m2x+b2
+ //m1x+b1=m2x+b2
+ //m1x-m2x+b1=b2
+ //(m1-m2)x=b2-b1
+ //x=(b2-b1)/(m1-m2)
+ //y=m1x+b1
+ midmovedx=(secondb-firstb)/(firstm-secondm);
+ midmovedy=(secondm*midmovedx)+secondb;
+ tf->uv[i][0]=midmovedx;
+ tf->uv[i][1]=midmovedy;
+ }
+ }
+ }
+ } else {
+ for(j=0; (j<3 || (j==3 && efa->v4)); j++) {//also for each point on the face
+ jtmpl=(*(&efa->v1 + j))->tmp.l;
+ if(i!=j && (!efa->v4 || abs(i-j)!=2)) {//if the points are connected
+ //quad (0,1,2,3) 0,1 0,3 1,0 1,2 2,1 2,3 3,0 3,2
+ //triangle (0,1,2) 0,1 0,2 1,0 1,2 2,0 2,1
+ if(uvedit_uv_selected(scene, efa, tf, i) && uvedit_uv_selected(scene, efa, tf, j)) {
+ //if the edge is selected
+ if(pass==1) {//if finding first endpoint
+ if(starttmpl==-1) {//if the first endpoint isn't found yet
+ starttmpl=itmpl;//set unique name for endpoint
+ connectedtostarttmpl=jtmpl;
+ //get point that endpoint is connected to
+ startface=tf;//get face it's on
+ startcorner=i;//what corner of the face?
+ startefa=efa;
+ efa= em->faces.first;
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ i=-1;
+ break;
+ }
+ if(starttmpl==itmpl && jtmpl!=connectedtostarttmpl) {
+ starttmpl=-1;//not an endpoint
+ efa=startefa;
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ i=startcorner;
+ break;
+ }
+ }
+ if(pass==2) {//if finding second endpoint
+ if(endtmpl==-1 && itmpl!=starttmpl) {
+ endtmpl=itmpl;
+ connectedtoendtmpl=jtmpl;
+ endface=tf;
+ endcorner=i;
+ endefa=efa;
+ efa= em->faces.first;
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ i=-1;
+ break;
+ }
+ if(endtmpl==itmpl && jtmpl!=connectedtoendtmpl) {
+ endtmpl=-1;
+ efa=endefa;
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ i=endcorner;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if(pass==2 && (starttmpl==-1 || endtmpl==-1)) { pass=4; }//if endpoints aren't found
+ }
+ }
+
uvedit_live_unwrap_update(sima, scene, obedit);
DAG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
@@ -1074,6 +1197,7 @@
static void UV_OT_align(wmOperatorType *ot)
{
static EnumPropertyItem axis_items[] = {
+ {'s', "ALIGN_S", 0, "Straighten", "Align UVs along the line defined by the endpoints"},
{'a', "ALIGN_AUTO", 0, "Align Auto", "Automatically choose the axis on which there is most alignment already"},
{'x', "ALIGN_X", 0, "Align X", "Align UVs on X axis"},
{'y', "ALIGN_Y", 0, "Align Y", "Align UVs on Y axis"},
straightenxy.patch adds new functionality.
Now it can straighten perpendicularly to the line,
using the X axis only, or
using the Y axis only.
Now If you have columns and want to make the top go diagonally, you won't make the column itself diagonal.