Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Convert mesh to normal paths

New Here ,
Oct 13, 2025 Oct 13, 2025

I am pretty new to using scripts in Illustrator. I have a script that I would like to run in Illustrator. However, when I go to File > Scripts > Other Script and attempt to select my plain text file named SimplifyMeshToLines_Separated.jsx, the file is greyed out. If I save this file to the folder containing the Illustrator Scripts, it fails to show up in the list of Scripts. What am I doing wrong here? Thanks.

TOPICS
Scripting
858
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Community Expert , Oct 15, 2025 Oct 15, 2025

Hi @chadulus2, I've written a script that works with the idea I mentioned earlier—saving as an Illustrator version 8 file. It works because it reads the plain text coordinates directly from the saved file and then draws them into the document. Each patch of the mesh is a path item.

 

Give it a try and let me know if it helps in your case.

- Mark

demo.gif

/**
 * @file Draw Geometry Of MeshItems.js
 *
 * Will add a path item for each patch
 * of each mesh item in the document.
 *
 * Note: document must be
...
Translate
Adobe
Community Expert ,
Oct 13, 2025 Oct 13, 2025

Can you possibly share the jsx file?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Oct 13, 2025 Oct 13, 2025

For some reason it would not let me upload the .jsx file, however, I have attached a plain text version.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Oct 13, 2025 Oct 13, 2025

I have tried a few things and seems to have gotten the script to actually work....well, whether it does what I want is another question, but at least I can get Illustrator to run the script.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 13, 2025 Oct 13, 2025

Hi @chadulus2 did you get the script to give you the meshes geometry as normal path items? I tried it and it didn't work. In fact I don't think it *can* work because it uses "Expand" menu on the mesh which isn't available from the UI (or anywhere!). So, sadly, this script seems to be AI confabulation. By the way, we don't have access to the mesh's paths via scripting either so no help there. Maybe there is a way to export in some format—I notice we can get the coordinates from an .ai version 8 file, so it would be possible to script this with a bit of work.

- Mark

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Oct 13, 2025 Oct 13, 2025

Hi Mark, thanks for giving that a try. No, I could not get it to work either. I also tried this one (see attached), but I am not sure this works either (it is actually still running on my machine after quite a bit of time). Are you aware of any method to "convert" a mesh into a simplified line drawing?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 15, 2025 Oct 15, 2025

Hi @chadulus2, I've written a script that works with the idea I mentioned earlier—saving as an Illustrator version 8 file. It works because it reads the plain text coordinates directly from the saved file and then draws them into the document. Each patch of the mesh is a path item.

 

Give it a try and let me know if it helps in your case.

- Mark

demo.gif

/**
 * @file Draw Geometry Of MeshItems.js
 *
 * Will add a path item for each patch
 * of each mesh item in the document.
 *
 * Note: document must be saved before
 * running script.
 *
 * @author m1b
 * @version 2025-10-18
 * @discussion https://community.adobe.com/t5/illustrator-discussions/greyed-out-script/m-p/15545562
 */
(function () {

    var settings = {
        drawAsPatches: false,
        layerName: 'meshes',
        showUI: true,
    };

    if (0 === app.documents.length)
        return alert('Please open a document and try again.');

    var doc = app.activeDocument;

    if (!doc.saved)
        return alert('Please save document and try again.');

    if (settings.showUI) {

        var result = ui(settings);

        if (2 === result)
            // user cancelled
            return;

    }

    // how to draw the mesh geometry
    settings.drawMesh = settings.drawAsPatches ? drawMeshAsPatches : drawMeshAsGridLines;

    // save temp document as AI version 8 (plain text)
    var original = doc.fullName;
    var so = new IllustratorSaveOptions();
    so.compatibility = Compatibility.ILLUSTRATOR8;
    so.compressed = true;
    var tempFile = File(Folder.temp + '/tmp.ai');
    doc.saveAs(tempFile, so);
    doc.close();

    // restore original document
    app.open(original);
    doc = app.activeDocument;

    // read the mesh coords
    var meshes = readMeshData(tempFile);

    // draw the meshes as path items
    var pathItems = [];

    // get a safe layer to draw to
    var layer = getThing(doc, 'name', settings.layerName) || doc.layers.add();
    layer.name = settings.layerName;
    layer.visible = true;
    layer.locked = false;

    // draw the meshes
    for (var i = 0; i < meshes.length; i++) {

        var group = layer.groupItems.add();
        group.name = 'mesh ' + (i + 1);

        pathItems = pathItems.concat(settings.drawMesh(group, meshes[i]));

    }

    if (0 === pathItems.length)
        alert('No mesh items found in document.');

})();

/**
 * Extract MeshItem coordinates from an Illustrator v8 file.
 * Will return an array containing mesh data for each mesh found.
 * @author m1b
 * @version 2025-10-18
 * @param {File} file - the file to read.
 * @returns {Array<Array<patch>>} - the mesh data objects.
 */
function readMeshData(file) {

    const MATCH_PATCH_START = /%_\[([^\]]+)\] \/P X#/;
    const MATCH_PATCH_END = /%_\/E X#/;
    const MATCH_PATCH_COORDS = /%_\[([^\]]+)\] \/N X#/;

    if (!file.exists)
        return;

    file.open('r');

    var meshes = [];
    var mesh;
    var patch;
    var line;
    var match;
    var coords;

    while (!file.eof) {

        line = file.readln();
        match = line.match(MATCH_PATCH_START);

        if (
            null !== match
            && 2 === match.length
        ) {
            // start new patch
            patch = { name: match[1], rowIndex: -1, columnIndex: -1, points: [] };

            var parts = patch.name.split(' ');

            if (2 !== parts.length)
                continue;

            patch.rowIndex = Number(parts[0]);
            patch.columnIndex = Number(parts[1]);

            if (
                isNaN(patch.rowIndex)
                || isNaN(patch.columnIndex)
            )
                continue;

            if (
                0 === patch.rowIndex
                && 0 === patch.columnIndex
            ) {
                // start new mesh
                mesh = [];
                meshes.push(mesh);
            }

            mesh.push(patch);
            continue;

        }

        if (!patch)
            // nothing
            continue;

        var match = line.match(MATCH_PATCH_COORDS);

        if (
            null === match
            || 2 > match.length
        ) {

            if (MATCH_PATCH_END.test(line))
                // end of patch
                patch = undefined;

            // part of a patch, but not geometry;
            continue;

        }

        var coords = match[1].split(' ');
        // start new point
        var numbers = [];

        for (var i = 0; i < coords.length; i++) {
            numbers.push(Number(coords[i]));
        }

        var len = numbers.length;

        patch.points.push({
            anchor: [numbers[len - 8], numbers[len - 7]],
            leftDirection: [numbers[len - 3], numbers[len - 2]],
            rightDirection: [numbers[len - 6], numbers[len - 5]],
        });

    }

    return meshes;

};

/**
 * Draws mesh patches.
 * @author m1b
 * @version 2025-10-18
 * @param {Document|Layer|GroupItem} container - the location of the new path items.
 * @param {Object} patches - patch objects { name:"", points:[] }.
 * @returns {Array<PathItem>}
 */
function drawMeshAsPatches(container, patches) {

    if (!container.hasOwnProperty('pathItems'))
        throw new Error('drawMesh: bad `container` supplied.');

    var pathItems = [];

    for (var i = 0; i < patches.length; i++) {

        var patch = patches[i];
        var pathItem = drawPath(container, patch.points, patch.name);
        pathItem.closed = true;
        pathItems.push(pathItem);

    }

    return pathItems;

};

/**
 * Draw mesh grid lines (rows and columns).
 * @author m1b
 * @version 2025-10-18
 * @param {Document|Layer|GroupItem} [container] - the container to draw in.
 * @param {Array<Object>} patches - array of patches {name: points:}.
 * @returns {Array<PathItem>}
 */
function drawMeshAsGridLines(container, patches) {

    var map = [];
    var maxRow = 0;
    var maxCol = 0;

    // parse patch names
    for (var i = 0; i < patches.length; i++) {

        var p = patches[i];

        if (!map[p.rowIndex])
            map[p.rowIndex] = [];

        map[p.rowIndex][p.columnIndex] = p;

        if (p.rowIndex > maxRow)
            maxRow = p.rowIndex;

        if (p.columnIndex > maxCol)
            maxCol = p.columnIndex;

    }

    var rowCount = maxRow + 1;
    var columnCount = maxCol + 1;

    // draw the lines
    var pathItems = [];
    var linePts = [];

    /* ------------------ *
     *  HORIZONTAL LINES  *
     * ------------------ */

    for (var r = 0; r < rowCount; r++) {

        for (var c = 0; c < columnCount; c++) {

            var patch = map[r][c];

            if (!linePts[c]) {
                linePts[c] = [];
            }

            if (!linePts[c + 1]) {
                linePts[c + 1] = [];
            }

            if (0 === c) {

                // right side of patch
                if (0 === r)
                    linePts[c][r] = {
                        anchor: patch.points[0].anchor,
                        leftDirection: patch.points[0].leftDirection,
                        rightDirection: patch.points[0].rightDirection,
                        pointType: PointType.CORNER,
                    };

                else
                    // fix join
                    linePts[c][r].rightDirection = patch.points[0].rightDirection;

                linePts[c][r + 1] = {
                    anchor: patch.points[1].anchor,
                    leftDirection: patch.points[1].leftDirection,
                    rightDirection: patch.points[1].rightDirection,
                    pointType: PointType.CORNER,
                };

            }

            // left side of patch
            if (0 === r)
                linePts[c + 1][r] = {
                    anchor: patch.points[3].anchor,
                    leftDirection: patch.points[3].rightDirection,
                    rightDirection: patch.points[3].leftDirection,
                    pointType: PointType.CORNER,
                };

            else
                // fix join
                linePts[c + 1][r].rightDirection = patch.points[3].leftDirection;

            linePts[c + 1][r + 1] = {
                anchor: patch.points[2].anchor,
                leftDirection: patch.points[2].rightDirection,
                rightDirection: patch.points[2].leftDirection,
                pointType: PointType.CORNER,
            };

        }

    }

    // draw horizontal lines
    for (var i = 0; i < linePts.length; i++)
        pathItems.push(drawPath(container, linePts[i], 'row ' + (i + 1)));


    /* ----------------- *
     *  VERTICAL LINES   *
     * ----------------- */
    var linePts = [];

    for (var c = 0; c < columnCount; c++) {

        for (var r = 0; r < rowCount; r++) {

            var patch = map[r][c];

            if (!linePts[r]) {
                linePts[r] = [];
            }

            if (!linePts[r + 1]) {
                linePts[r + 1] = [];
            }

            if (0 === r) {

                // bottom edge of patch
                if (0 === c)

                    linePts[r][c] = {
                        anchor: patch.points[0].anchor,
                        leftDirection: patch.points[0].rightDirection,
                        rightDirection: patch.points[0].leftDirection,
                        pointType: PointType.CORNER,
                    };

                else
                    // fix join
                    linePts[r][c].rightDirection = patch.points[0].leftDirection;

                linePts[r][c + 1] = {
                    anchor: patch.points[3].anchor,
                    leftDirection: patch.points[3].rightDirection,
                    rightDirection: patch.points[3].leftDirection,
                    pointType: PointType.CORNER,
                };

            }

            // top edge of patch
            if (0 === c)

                linePts[r + 1][c] = {
                    anchor: patch.points[1].anchor,
                    leftDirection: patch.points[1].leftDirection,
                    rightDirection: patch.points[1].rightDirection,
                    pointType: PointType.CORNER,
                };

            else
                // fix join
                linePts[r + 1][c].rightDirection = patch.points[1].rightDirection;

            linePts[r + 1][c + 1] = {
                anchor: patch.points[2].anchor,
                leftDirection: patch.points[2].leftDirection,
                rightDirection: patch.points[2].rightDirection,
                pointType: PointType.CORNER,
            };

        }

    }

    // draw vertical lines
    for (var i = 0; i < linePts.length; i++)
        pathItems.push(drawPath(container, linePts[i], 'column ' + (i + 1)));

    return pathItems;

};

/**
 * Draws a path of `points`;
 * @author m1b
 * @version 2025-10-18
 * @param {Document|Layer|GroupItem} [container] - the container to draw in.
 * @param {Array<PathPoints>} points - an array of points {anchor: leftDirection: rightDirection: pointType?:}.
 * @param {String} [name] - the path item name (default: none).
 * @returns {PathItem}
 */
function drawPath(container, points, name) {

    var path = newEmptyPathItem(container, name);

    for (var i = 0; i < points.length; i++) {

        var p = path.pathPoints.add();

        p.anchor = points[i].anchor;
        p.leftDirection = points[i].leftDirection;
        p.rightDirection = points[i].rightDirection;
        p.pointType = points.pointType || PointType.CORNER;

    }

    return path;

};

/**
 * Returns a new empty path item.
 * @author m1b
 * @version 2025-10-16
 * @param {Document|Layer|GroupItem} container - the location of the new path items.
 * @param {String} [name] - the name of the item (default: none).
 * @returns {PathItem}
 */
function newEmptyPathItem(container, name) {
    var item = container.pathItems.add();
    item.name = name || '';
    item.filled = false;
    item.stroked = true;
    return item;
};

/**
 * Returns a thing with matching property.
 * If `key` is undefined, evaluate the object itself.
 * @author m1b
 * @version 2024-04-21
 * @param {Array|Collection} things - the things to look through.
 * @param {String} [key] - the property name (default: undefined).
 * @param {*} value - the value to match.
 */
function getThing(things, key, value) {

    for (var i = 0, obj; i < things.length; i++)
        if ((undefined == key ? things[i] : things[i][key]) == value)
            return things[i];

};

/**
 * User interface for this script. Will update the `settings` object.
 * @author m1b
 * @version 2025-10-18
 * @param {Object} settings - the script settings.
 * @returns {1|2}
 */
function ui(settings) {

    var w = new Window("dialog { text:'Draw MeshItem Geometry' }");

    var group = w.add('group {orientation:"column", alignment:["fill","fill"], alignChildren:["left","fill"], margins:[10,10,10,10] }');

    var radioButtons = group.add('group {orientation:"row", margins:[10,10,10,10] }'),
        asPatchesRadio = radioButtons.add('radiobutton {text:"Draw mesh as patches"}'),
        asLinesRadio = radioButtons.add('radiobutton {text:"Draw mesh as lines"}');

    var bottomUI = w.add('group {orientation:"row", alignment:["fill","top"], margins: [0,20,0,0] }'),
        buttons = bottomUI.add('group {orientation:"row", alignment:["right","top"], alignChildren:"right" }'),
        cancelButton = buttons.add('button', undefined, 'Cancel', { name: 'cancel' }),
        drawButton = buttons.add('button', undefined, 'Draw', { name: 'ok' });

    (settings.drawAsPatches ? asPatchesRadio : asLinesRadio).value = true;

    drawButton.onClick = function () {
        settings.drawAsPatches = asPatchesRadio.value;
        w.close(1);
    };

    w.center();
    return w.show();

};

Edit 2025-10-18: added capability to draw geometry as grid lines, as well as patches.

demo2.gif

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 15, 2025 Oct 15, 2025

fantastic Mark!

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 15, 2025 Oct 15, 2025

Thanks! I did a bit of Carlos-style thinking outside the box! Well, except you would have done it somehow in just two lines! 😝

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Oct 17, 2025 Oct 17, 2025
Thanks Mark!
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 17, 2025 Oct 17, 2025
LATEST

@chadulus2 FYI I updated the code so it can draw as grid lines as well as patches.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines