BatchPlay, Layer Visibility, Nested Smart Objects, Bitmap Halftone, Saving & Closing, Oh my!

So, I might’ve got a bit carried away :rofl:
Here’s a full prototype, the only thing I’ve not cracked is getting the smart object edits to update the master document. The file saves, but it doesn’t update, and I’m not sure I’m using placedLayerUpdateAllModified correctly. Perhaps @Maher has some bright ideas as to what’s going on with that!

const { app, core, action } = require("photoshop");
const fs = require("uxp").storage.localFileSystem;
const batchPlay = action.batchPlay;
const executeAsModal = core.executeAsModal;

const makeDefaultDocument = async () => {
  const result = await batchPlay(
    [
      {
        _obj: "make",
        new: {
          _obj: "document",
          artboard: false,
          autoPromoteBackgroundLayer: false,
          preset: "Default Photoshop Size",
        },
      },
    ],
    {}
  );

  return result[0];
};

const makeNewLayer = async (id) => {
  const result = await batchPlay(
    [
      {
        _obj: "make",
        _target: [
          {
            _ref: "layer",
          },
        ],
        layerID: id,
      },
    ],
    {}
  );

  return result[0];
};

const convertToSmartObject = async (docId, layerId) => {
  return await batchPlay([{ _obj: "newPlacedLayer" }], {});
};

const openSmartObject = async (layerId) => {
  const result = await batchPlay(
    [
      {
        _obj: "placedLayerEditContents",
        layerID: layerId,
      },
    ],
    {}
  );

  return result[0];
};

const makeSolidColour = async (red, green, blue) => {
  const result = await batchPlay(
    [
      {
        _obj: "make",
        _target: [
          {
            _ref: "contentLayer",
          },
        ],
        using: {
          _obj: "contentLayer",
          type: {
            _obj: "solidColorLayer",
            color: {
              _obj: "RGBColor",
              red: red,
              grain: green,
              blue: blue,
            },
          },
        },
      },
    ],
    {}
  );

  return result[0];
};

const updateSmartObjectLink = async (id, layerId) => {
  const result = await batchPlay(
    [
      {
        _obj: "placedLayerUpdateAllModified",
        documentID: id,
        layerIDs: [layerId],
      },
    ],
    {}
  );

  return result;
};

const saveDocument = async (id, filename, folder) => {
  // Create file
  const file = await folder.createFile(filename, {
    overwrite: true,
  });

  // Generate token
  const token = await fs.createSessionToken(file);

  const result = await batchPlay(
    [
      {
        _obj: "save",
        in: {
          _path: token,
          _kind: "local",
        },
        saveStage: {
          _enum: "saveStageType",
          _value: "saveBegin",
        },
        documentID: id,
      },
    ],
    {}
  );

  return result;
};

const closeDocument = async (id) => {
  const result = await batchPlay(
    [
      {
        _obj: "close",
        saving: {
          _enum: "yesNo",
          _value: "no",
        },
        documentID: id,
      },
    ],
    {}
  );

  return result;
};

const activateDocument = (id) => {
  app.activeDocument = app.documents.find((doc) => doc.id === id);
};

const makeAndOpenSmartObject = async (masterDocId) => {
    // Make new layer
    const newLayer = await makeNewLayer(masterDocId);

    // Convert new layer to smart object
    await convertToSmartObject(masterDocId, newLayer.layerID);

    // Open smart object
    const smartObjectDoc = await openSmartObject(newLayer.layerID);

    return {
      newLayer,
      smartObjectDoc,
    };
};

const main = async () => {
  await executeAsModal(async () => {
    try {
      // Get folder for saving
      const saveFolder = await fs.getFolder();

      // Make master document
      const masterDoc = await makeDefaultDocument();

      // Make and open smart object
      const { newLayer, smartObjectDoc } = await makeAndOpenSmartObject(
        masterDoc.documentID
      );

      // Perform edit to smart object
      await makeSolidColour(0, 0, 255);

      // Generate filename from layer id
      const filename = `SmartObject_${newLayer.layerID}`;

      // Update master doc
      await updateSmartObjectLink(masterDoc.documentID, newLayer.layerID);

      // Save smart object
      await saveDocument(smartObjectDoc.documentID, filename, saveFolder);

      // Close smart object
      await closeDocument(smartObjectDoc.documentID);

      // Activate master document
      activateDocument(masterDoc.documentID);
    } catch (error) {
      console.log("💥", error);
    }
  });
};
1 Like