/* */ import java.awt.font.*; import java.awt.geom.*; showInfoWindow() { warning = new BTextArea("This is an experimental tool. In particular, it doesn't work\n"+ "well with some fonts."+ "However, it works often and can be useful, and that is my intention. \n"+ "But be aware that I can't be held responsible for any damage it does to \n"+ "your work.\n"+ "In case of crash, I suggest saving your work if it wasn't and closing Art of "+ "Illusion and opening it again.\n\n"+ "Enjoy!", 10, 80); warning.setEditable(false); wrnDlg = new PanelDialog(window, "Important Information", new BScrollPane(warning)); } showHelpWindow() { helpText = new BTextArea("Text tool script.\n\n"+ "By Yokiyoki (Julio Sangrador-Pat�n), with great aid from Peter Eastman and others.\n"+ "This is a beta version, but quite usable especially on windows.\n\n"+ "Help:\n\n"+ "Tool to build the model of a string of text, in the form of simple approximating curves, tubes which follow these,\n\n"+ "flat triangle meshes or extruded solid triangle meshes. Steps:\n\n"+ "1. Choose one of the above at the top of the dialog.\n"+ "2. Choose a font face from the list. Be aware that (on linux at least) a great deal of them\n"+ "make the script crash. It seems to have to do with the font being Adobe type, but I'm not\n"+ "sure yet.\n"+ "3. Mark if you want it bold and/or italic.\n"+ "4. Write the text you want to be modelled.\n"+ "5. Enter the tolerance value, which grosso modo tells how accurate the outlines will be (the smaller\n"+ "the value, the more accurate).\n"+ "6. Enter the thickness of the mesh (for 3D meshes) or of the tube (for tubes). Useless for curves and flat surfaces.\n"+ "7. Enter the degree of subdivision you want for the meshes, which can be 0 or a positive integer. A value\n"+ "of at least 1 is recomended to avoid artifacts. You will seldom need more than 2, and might do well\n"+ "with 0.", 10, 80); helpText.setEditable(false); hlpDlg = new PanelDialog(window, "Help", new BScrollPane(helpText)); } /* Modes */ M_TUBE = -1; M_SPLINE = 0; M_2D = 1; M_3D = 2; /* Prepare to remember the user selections */ if(global.textToolwantsBold == void) { global.textToolwantsBold = false; global.textToolwantsItalic = false; global.textToolfont = "SurelyThisIsntAFontName"; global.textTooltheString = "Write some text"; global.textTooltolerance = 0.1; global.textToolmesh = M_2D; global.textToolthickness = 0.1; global.textToolsubdivideTimes = 1; } /* error message function */ errorMessage(s) { return (new MessageDialog(window, s)).getChoice(); } /* Rewrite of the solidify function, using the static methods of the Extrude Dialog Plugin */ /* Copied from a message to the forum by Peter Eastman */ solidify2(info, thickness) { extrudeDialog = ModellingApp.getClass("artofillusion.tools.ExtrudeDialog"); extrudeMesh = extrudeDialog.getMethod("extrudeMesh", new Class [] {TriangleMesh.class, CoordinateSystem.class, Vec3.class, Integer.TYPE, Double.TYPE, Boolean.TYPE}); extruded = extrudeMesh.invoke(null, new Object[] {info.object, info.coords, new Vec3(0,0,thickness), 1, 0.0, true}); return extruded; } /* Create the components of the options dialog */ meshType = new RadioButtonGroup(); meshSpline = new BRadioButton("Silhouette", global.textToolmesh==M_SPLINE,meshType); mesh2D = new BRadioButton("2D surface", global.textToolmesh==M_2D,meshType); mesh3D = new BRadioButton("3D solid", global.textToolmesh==M_3D,meshType); meshTube = new BRadioButton("Tube", global.textToolmesh==M_TUBE,meshType); kindOfMesh = new GridContainer(2, 2); kindOfMesh.setDefaultLayout(new LayoutInfo(LayoutInfo.WEST, LayoutInfo.NONE, new Insets(2, 2, 2, 2), null)); kindOfMesh.add(meshSpline, 0, 0); kindOfMesh.add(mesh2D, 0, 1); kindOfMesh.add(mesh3D, 1, 0); kindOfMesh.add(meshTube, 1, 1); fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); fontsList = new BList(fonts); fontsList.setPreferredVisibleRows(10); fontsList.setMultipleSelectionEnabled(false); theSelectedIndex = 0; for(y=0;yM_SPLINE) { // i.e, Surface or Solid // try to triangulate the curve theMesh = theCurve.subdivideCurve(subdivideTimes).convertToTriangleMesh(tolerance); if (theMesh == null) continue; currentGlyphOI = new ObjectInfo(theMesh, new CoordinateSystem(), glyphName); currentGlyphOI.setTexture(sceneDefaultTex, sceneDefaultTex.getDefaultMapping()); if(firstCurveOfGlyph) { fullLetterOI = currentGlyphOI; } else { // More curves, see if they intersect or unite what we already have meshToTestForIntersection = new ObjectInfo(solidify2(currentGlyphOI,0.2), currentGlyphOI.coords.duplicate(), glyphName); meshToTestForIntersection.setTexture(sceneDefaultTex, sceneDefaultTex.getDefaultMapping()); // for getBounds() to work coordsDiff = currentGlyphOI.getBounds().getCenter().minus(meshToTestForIntersection.getBounds().getCenter()); meshToTestForIntersection.coords.setOrigin(meshToTestForIntersection.coords.getOrigin().plus(coordsDiff)); testCSG = new CSGObject(fullLetterOI,meshToTestForIntersection,CSGObject.INTERSECTION); testCSGMesh = testCSG.convertToTriangleMesh(tolerance); if(testCSGMesh.getEdges().length > 0) { // Intersects bounds1 = fullLetterOI.getBounds(); bounds2 = currentGlyphOI.getBounds(); firstIsLarger = ((bounds1.maxx-bounds1.minx)*(bounds1.maxy-bounds1.miny) >= (bounds2.maxx-bounds2.minx)*(bounds2.maxy-bounds2.miny)); firstMesh = (firstIsLarger ? fullLetterOI : currentGlyphOI); secondMesh = (firstIsLarger ? currentGlyphOI : fullLetterOI); meshToCut = new ObjectInfo(solidify2(secondMesh,0.2), secondMesh.coords.duplicate(), glyphName); meshToCut.setTexture(sceneDefaultTex, sceneDefaultTex.getDefaultMapping()); // for getBounds() to work coordsDiff = secondMesh.getBounds().getCenter().minus(meshToCut.getBounds().getCenter()); meshToCut.coords.setOrigin(meshToCut.coords.getOrigin().plus(coordsDiff)); aCSG = new CSGObject(firstMesh, meshToCut, CSGObject.DIFFERENCE12); aCSGMesh = aCSG.convertToTriangleMesh(tolerance); fullLetterOI = new ObjectInfo(aCSGMesh,fullLetterOI.coords.duplicate(), glyphName); fullLetterOI.setTexture(sceneDefaultTex, sceneDefaultTex.getDefaultMapping()); } else { // Unites aCSG = new CSGObject(fullLetterOI, currentGlyphOI, CSGObject.UNION); aCSGMesh = aCSG.convertToTriangleMesh(tolerance); fullLetterOI = new ObjectInfo(aCSGMesh,fullLetterOI.coords.duplicate(), glyphName); fullLetterOI.setTexture(sceneDefaultTex, sceneDefaultTex.getDefaultMapping()); } try { // Optimize the mesh while we are building it fullLetterOI.object = TriangleMesh.optimizeMesh(fullLetterOI.object); fullLetterOI.clearCachedMeshes(); } catch (Exception e) {e.printStackTrace();} // Should we act? Not sure... } firstCurveOfGlyph = false; } else if(mesh==M_TUBE) { // User wants tubes nVerts = theCurve.getVertices().length; tubeThickness = new double[nVerts]; for(t=0;t