|
const { batchPlay } = require('photoshop').action |
|
const { executeAsModal } = require('photoshop').core |
|
const { |
|
cleanLayers, |
|
getLayerIndex, |
|
selectLayers, |
|
unSelectMarqueeCommand, |
|
unSelectMarqueeExe, |
|
getSelectionInfoExe, |
|
reSelectMarqueeExe, |
|
} = require('../psapi') |
|
|
|
const psapi = require('../psapi') |
|
|
|
async function createNewLayerExe(layerName, opacity = 100) { |
|
await executeAsModal(async () => { |
|
await createNewLayerCommand(layerName, opacity) |
|
}) |
|
const new_layer = await app.activeDocument.activeLayers[0] |
|
return new_layer |
|
} |
|
|
|
async function createNewLayerCommand(layerName, opacity = 100) { |
|
return await app.activeDocument.createLayer({ |
|
name: layerName, |
|
opacity: opacity, |
|
mode: 'normal', |
|
}) |
|
} |
|
|
|
async function deleteLayers(layers) { |
|
try { |
|
await cleanLayers(layers) |
|
} catch (e) { |
|
console.warn(e) |
|
} |
|
} |
|
|
|
async function getIndexCommand() { |
|
const command = { |
|
_obj: 'get', |
|
_target: [ |
|
{ |
|
_property: 'itemIndex', |
|
}, |
|
{ |
|
_ref: 'layer', |
|
_enum: 'ordinal', |
|
_value: 'targetEnum', |
|
}, |
|
], |
|
} |
|
const result = await batchPlay([command], { |
|
synchronousExecution: true, |
|
modalBehavior: 'execute', |
|
}) |
|
|
|
return result |
|
} |
|
|
|
async function getIndexExe() { |
|
let index |
|
await executeAsModal(async () => { |
|
index = await getIndexCommand() |
|
}) |
|
|
|
return index |
|
} |
|
const photoshop = require('photoshop') |
|
|
|
const collapseFolderCommand = async (expand = false, recursive = false) => { |
|
let result |
|
try { |
|
result = await batchPlay( |
|
[ |
|
{ |
|
_obj: 'set', |
|
_target: { |
|
_ref: [ |
|
{ _property: 'layerSectionExpanded' }, |
|
{ |
|
_ref: 'layer', |
|
_enum: 'ordinal', |
|
_value: 'targetEnum', |
|
}, |
|
], |
|
}, |
|
to: expand, |
|
recursive, |
|
_options: { dialogOptions: 'dontDisplay' }, |
|
}, |
|
], |
|
{ synchronousExecution: true } |
|
) |
|
} catch (e) { |
|
console.error(e.message) |
|
} |
|
return result |
|
} |
|
async function collapseFolderExe(layers, expand = false, recursive = false) { |
|
for (let layer of layers) { |
|
try { |
|
await executeAsModal(async () => { |
|
const is_visible = await layer.visible |
|
await selectLayers([layer]) |
|
await collapseFolderCommand(expand, recursive) |
|
layer.visible = is_visible |
|
}) |
|
} catch (e) { |
|
console.warn(e) |
|
} |
|
} |
|
} |
|
|
|
class Layer { |
|
static doesLayerExist(layer) { |
|
let b_exist = false |
|
try { |
|
if (typeof layer !== 'undefined' && layer && layer.name) { |
|
|
|
b_exist = true |
|
|
|
} |
|
|
|
} catch (e) { |
|
b_exist = false |
|
|
|
} |
|
return b_exist |
|
} |
|
static async getLayerInfo(layer) { |
|
const bounds = layer.bounds |
|
const height = bounds.bottom - bounds.top |
|
const width = bounds.right - bounds.left |
|
const layer_info = { |
|
height: height, |
|
width: width, |
|
left: bounds.left, |
|
right: bounds.right, |
|
top: bounds.top, |
|
bottom: bounds.bottom, |
|
} |
|
console.log('layer_info:', layer_info) |
|
return layer_info |
|
} |
|
static async scaleTo(layer, new_width, new_height) { |
|
await executeAsModal(async () => { |
|
try { |
|
const selection_info = await psapi.getSelectionInfoExe() |
|
await psapi.unSelectMarqueeExe() |
|
|
|
console.log('scaleLayer got called') |
|
|
|
|
|
|
|
const layer_info = await this.getLayerInfo(layer) |
|
const scale_x_ratio = (new_width / layer_info.width) * 100 |
|
const scale_y_ratio = (new_height / layer_info.height) * 100 |
|
console.log('scale_x_y_ratio:', scale_x_ratio, scale_y_ratio) |
|
await layer.scale(scale_x_ratio, scale_y_ratio) |
|
await psapi.reSelectMarqueeExe(selection_info) |
|
} catch (e) { |
|
console.warn(e) |
|
} |
|
}) |
|
} |
|
|
|
static async moveTo(layer, to_x, to_y) { |
|
try { |
|
await executeAsModal(async () => { |
|
try { |
|
|
|
const selection_info = await psapi.getSelectionInfoExe() |
|
await psapi.unSelectMarqueeExe() |
|
|
|
const layer_info = await this.getLayerInfo(layer) |
|
const top_dist = layer_info.top - to_y |
|
const left_dist = layer_info.left - to_x |
|
console.log('-left_dist, -top_dist', -left_dist, -top_dist) |
|
await layer.translate(-left_dist, -top_dist) |
|
|
|
await psapi.reSelectMarqueeExe(selection_info) |
|
} catch (e) { |
|
console.warn(e) |
|
} |
|
}) |
|
} catch (e) { |
|
console.warn(e) |
|
} |
|
} |
|
static resizeTo() {} |
|
static fitSelection() {} |
|
static async duplicateToDoc(layer, to_doc) { |
|
const dupLayer = await layer.duplicate(to_doc) |
|
|
|
return dupLayer |
|
} |
|
|
|
static async duplicateLayerExe(layer) { |
|
let layer_copy |
|
try { |
|
await executeAsModal(async () => { |
|
layer_copy = await layer.duplicate() |
|
}) |
|
} catch (e) { |
|
console.warn('duplication error:', e) |
|
} |
|
return layer_copy |
|
} |
|
|
|
static {} |
|
} |
|
|
|
const hasBackgroundLayerDesc = () => ({ |
|
_obj: 'get', |
|
_target: [ |
|
{ _property: 'hasBackgroundLayer' }, |
|
{ |
|
_ref: 'document', |
|
_enum: 'ordinal', |
|
_value: 'targetEnum', |
|
}, |
|
], |
|
}) |
|
async function hasBackgroundLayer() { |
|
|
|
try { |
|
const result = await batchPlay([hasBackgroundLayerDesc()], { |
|
synchronousExecution: true, |
|
modalBehavior: 'execute', |
|
}) |
|
const b_hasBackgroundLayer = result[0]?.hasBackgroundLayer |
|
return b_hasBackgroundLayer |
|
} catch (e) { |
|
console.warn(e) |
|
} |
|
} |
|
const makeBackgroundLayerDesc = () => ({ |
|
_obj: 'make', |
|
_target: [ |
|
{ |
|
_ref: 'backgroundLayer', |
|
}, |
|
], |
|
using: { |
|
_ref: 'layer', |
|
_enum: 'ordinal', |
|
_value: 'targetEnum', |
|
}, |
|
_options: { failOnMissingProperty: false, failOnMissingElement: false }, |
|
|
|
|
|
|
|
}) |
|
|
|
const createSolidLayerDesc = (r, g, b) => ({ |
|
_obj: 'make', |
|
_target: [ |
|
{ |
|
_ref: 'contentLayer', |
|
}, |
|
], |
|
using: { |
|
_obj: 'contentLayer', |
|
type: { |
|
_obj: 'solidColorLayer', |
|
color: { |
|
_obj: 'RGBColor', |
|
red: r, |
|
grain: g, |
|
blue: b, |
|
}, |
|
}, |
|
}, |
|
_options: { |
|
dialogOptions: 'dontDisplay', |
|
}, |
|
}) |
|
|
|
const toggleBackgroundLayerDesc = () => ({ |
|
_obj: 'show', |
|
null: [ |
|
{ |
|
_ref: 'layer', |
|
_property: 'background', |
|
}, |
|
], |
|
toggleOptionsPalette: true, |
|
_options: { |
|
dialogOptions: 'dontDisplay', |
|
}, |
|
}) |
|
|
|
async function toggleBackgroundLayerExe() { |
|
try { |
|
await executeAsModal(async () => { |
|
const result = await batchPlay([toggleBackgroundLayerDesc()], { |
|
synchronousExecution: true, |
|
modalBehavior: 'execute', |
|
}) |
|
console.log('toggleBackgroundLayerExe result: ', result) |
|
}) |
|
} catch (e) { |
|
console.warn(e) |
|
} |
|
} |
|
|
|
async function createBackgroundLayer(r = 255, g = 255, b = 255) { |
|
try { |
|
const has_background = await hasBackgroundLayer() |
|
if (has_background) { |
|
|
|
return null |
|
} |
|
|
|
|
|
|
|
await executeAsModal(async () => { |
|
|
|
const selectionInfo = await psapi.getSelectionInfoExe() |
|
await psapi.unSelectMarqueeExe() |
|
const active_layers = app.activeDocument.activeLayers |
|
|
|
|
|
|
|
const result = await batchPlay( |
|
[createSolidLayerDesc(r, g, b), makeBackgroundLayerDesc()], |
|
{ |
|
synchronousExecution: true, |
|
modalBehavior: 'execute', |
|
} |
|
) |
|
|
|
await psapi.reSelectMarqueeExe(selectionInfo) |
|
await psapi.selectLayersExe(active_layers) |
|
}) |
|
} catch (e) { |
|
console.warn(e) |
|
} |
|
} |
|
async function fixImageBackgroundLayer() { |
|
|
|
|
|
|
|
} |
|
module.exports = { |
|
createNewLayerExe, |
|
deleteLayers, |
|
getIndexExe, |
|
collapseFolderExe, |
|
Layer, |
|
hasBackgroundLayer, |
|
createBackgroundLayer, |
|
createSolidLayerDesc, |
|
makeBackgroundLayerDesc, |
|
toggleBackgroundLayerExe, |
|
} |
|
|