If the necessary items are not selected, the script uses the queryYesNo dialog to remind the user that they need to select them. The dialog has a Yes/No choice, but the result is not used so you can click either of the buttons.
Here is a simple example, using two line fixtures. The fixture on the left is selected to remain: ...and the two closest vertices are selected to be the join position. The order of the vertices (shown in red) is important! This is the result: The script works by adding all the vertices from the to-be-deleted fixture, to the fixture that will remain, starting from the selected points, so the vertex winding of the two fixtures is important. For example, if we had selected the fixture on the right, we would get this result: It can be a bit confusing when this happens, but you can usually reverse the winding of one of the fixtures to get the result you intended.
This script does not care what type of shape the fixture has, so you can also use it to merge fixtures of different types. Keep in mind that the fixture which remains will dictate the shape type of the result. For example, we can merge the two shapes here into one polygon fixture by selecting the polygon to be the fixture that remains: Result: Hey... that's not what we wanted
![Confused :?](./images/smilies/icon_e_confused.gif)
In this case, we need to reverse the winding on one of the fixtures (best to keep polygons wound counter-clockwise so I will change the line fixture): ... and also select the vertices that give a clean line sequence that does not self-intersect: Result: Unfortunately, it's not very intuitive to know how to get the arrangement you want, but this is about as good as the script can do. I humbly suggest a little trial and error, since there are only four possibilities in total. In particular I think the most typical cases where this will be used are:
1) to connect lines end-to-end as in the first example above, for which you should select the last vertex of the fixture to remain, and the first vertex of the fixture to be deleted. Because the vertices to choose are not optional, you will need to reverse the windings of the fixtures as necessary.
2) to connect two polygons. Both polygons will typically be wound counter-clockwise, so the problem shown above will not occur. It's best to leave the windings alone, and select the pair of vertices as necessary. There are usually only two possibilities that make sense, for example to join the two sections of ground below, you would choose either the top pair, or the bottom pair, depending on which of the fixtures was selected to remain: Here is the script:
Code: Select all
void main() {
//check that one fixture is selected
if ( sf().length != 1 ) {
queryYesNo("Please select a single fixture to be the destination for the merged result");
return;
}
fixture destinationFixture = sf()[0];
//check that two vertices are selected
if ( sv().length != 2 ) {
queryYesNo("Please select one vertex from each of the fixtures to merge");
return;
}
vertex[] vs = sv();
vertex v0 = vs[0];
vertex v1 = vs[1];
fixture f0 = v0.getFixture();
fixture f1 = v1.getFixture();
//check that one (and only one) of the vertices belongs to the selected fixture
if ( ! (f0 != f1 && (f0 == destinationFixture || f1 == destinationFixture)) ) {
queryYesNo("Please select one vertex from each of the fixtures to merge");
return;
}
//make sure 0 is the destination, and 1 is the source
if ( f1 == destinationFixture ) {
vertex tmpv = v1;
v1 = v0;
v0 = tmpv;
fixture tmpf = f1;
f1 = f0;
f0 = tmpf;
}
//add all vertices from f1 to f0
uint dstIndex = v0.index+1;
uint srcIndex = v1.index;
for (int i = 0; i < f1.getNumVertices(); i++) {
f0.addVertex( dstIndex++, f0.getBody().getLocalPoint(f1.getVertex(srcIndex).wpos) );
srcIndex = (srcIndex + 1) % f1.getNumVertices();
}
body b1 = f1.getBody();
//delete the source fixture (the body will remain)
f1.delete();
//delete body if it now has no fixtures
if ( b1.getFixtures().length == 0 )
b1.delete();
}