#target photoshop // $.level = 2; // debugger; var settings = new File(Folder.userData + "/.ShiftotronSettings"); var stepSize = new UnitValue(5, "px"); var stepsLeft = -10; var stepsRight = 10; var midLayerName; if (app.documents.length == 0) { Window.alert("This script requires an open Photoshop document to work on.\nPlease open one and try again.", "File not open", true); } else { main(); } function setDropDown( dd, strSet ) { var index = 0; for ( var i = 0; i < dd.items.length; i = i + 1 ) { if ( dd.items[ i ].toString() == strSet ) { index = i; break; } } if ( dd.items.length > 0 ) { dd.items[ index ].selected = true; } return index; } function multiAdd(drop, arr) { var i; for (i = 0; i < arr.length; i = i + 1) { var curr = arr[i]; if ((curr.typename == "ArtLayer") || (curr.typename == "LayerSet")) { curr = curr.name; } if (curr == "-") { drop.add("separator", ""); } else { drop.add("item", curr); } } } function readSettings(settings) { try { if (settings.open("r")) { var ss = new UnitValue(settings.readln()); var sl = settings.readln(); var sr = settings.readln(); stepSize = ss; stepsLeft = sl; stepsRight = sr; } } catch (e) { } finally { settings.close(); } } function writeSettings(settings) { try { if (settings.open("w")) { settings.writeln(stepSize); settings.writeln(stepsLeft); settings.writeln(stepsRight); app.activeDocument.activeLayer = app.activeDocument.layers.getByName(midLayerName); } } catch (e) { } finally { settings.close(); } } function updateParams(dialog) { stepsLeft = dialog.step.count.left.edit.text; stepsRight = dialog.step.count.right.edit.text; stepSize = new UnitValue(dialog.stepSize.edit.text, dialog.stepSize.unit.selection); midLayerName = dialog.centralLayer.value.selection; } function buildWindow(doc) { var dlgResource = "dialog { text:'Shiftotron', orientation: 'column', alignChildren: 'fill', \ stepSize: Panel { orientation: 'row', alignChildren: 'fill', text: 'Step Size',\ description: StaticText {text: 'Shift step size' }, \ edit: EditText {preferredSize: [30, 20]}, \ unit: DropDownList {}\ }, \ step: Panel { orientation: 'row', alignChildren: 'fill', text: 'Starting and ending steps', \ count: Group { orientation: 'column', alignChildren: 'right', \ left: Group { orientation: 'row', alignChildren: 'center', \ description: StaticText {text: 'From' }, \ edit: EditText {preferredSize: [30, 20]}, \ }, \ right: Group { orientation: 'row', alignChildren: 'center', \ description: StaticText {text: 'To' }, \ edit: EditText {preferredSize: [30, 20]}, \ } \ }, \ lock: Checkbox {text: 'Mirrored' } \ }, \ centralLayer: Group { orientation: 'row', alignChildren: 'fill', \ description: StaticText {text: 'Central layer' }, \ value: DropDownList {} \ }, \ progress: Progressbar {}, \ commands: Group { orientation: 'row', alignChildren: 'center', \ ok: Button {text: 'OK' }, \ cancel: Button {text: 'Cancel' } \ } \ }"; var dlg = new Window(dlgResource); dlg.commands.ok.onClick = function() { dlg.progress.maxvalue = stepsRight - stepsLeft + 1; if (stepsRight < stepsLeft) { var z = stepsRight; stepsRight = stepsLeft; stepsLeft = z; } doWork(doc, dlg.progress); dlg.close(); } multiAdd(dlg.stepSize.unit, ["px", "in", "cm"]); multiAdd(dlg.centralLayer.value, app.activeDocument.layers); dlg.onClose = function() { updateParams(dlg); } dlg.stepSize.edit.onChange = function() { updateParams(dlg); } dlg.stepSize.unit.onChange = function() { updateParams(dlg); } dlg.step.count.left.edit.onChange = function() { updateParams(dlg); } dlg.step.count.right.edit.onChange = function() { updateParams(dlg); } dlg.step.count.right.edit.onChanging = function() { if (dlg.step.lock.value) { dlg.step.count.left.edit.text = - (+dlg.step.count.right.edit.text); } } dlg.centralLayer.value.onChange = function() { updateParams(dlg); } dlg.stepSize.edit.text = stepSize.value; setDropDown(dlg.stepSize.unit, stepSize.type); dlg.step.count.left.edit.text = stepsLeft; dlg.step.count.right.edit.text = stepsRight; dlg.step.lock.onClick = function() { if (this.value) { dlg.step.count.left.enabled = false; dlg.step.count.left.edit.text = - (+dlg.step.count.right.edit.text); updateParams(dlg); } else { dlg.step.count.left.enabled = true; } } if (+stepsRight == -stepsLeft) { dlg.step.lock.value = true; dlg.step.count.left.enabled = false; } setDropDown(dlg.centralLayer.value, app.activeDocument.activeLayer.name); dlg.center(); dlg.show(); } function shift(x, y) { var id970 = charIDToTypeID( "move" ); var desc209 = new ActionDescriptor(); var id971 = charIDToTypeID( "null" ); var ref184 = new ActionReference(); var id972 = charIDToTypeID( "Lyr " ); var id973 = charIDToTypeID( "Ordn" ); var id974 = charIDToTypeID( "Trgt" ); ref184.putEnumerated( id972, id973, id974 ); desc209.putReference( id971, ref184 ); var id975 = charIDToTypeID( "T " ); var desc210 = new ActionDescriptor(); var id976 = charIDToTypeID( "Hrzn" ); var id977 = charIDToTypeID( "#Pxl" ); desc210.putUnitDouble( id976, id977, x.as("px")); var id978 = charIDToTypeID( "Vrtc" ); var id979 = charIDToTypeID( "#Pxl" ); desc210.putUnitDouble( id978, id979, y.as("px")); var id980 = charIDToTypeID( "Ofst" ); desc209.putObject( id975, id980, desc210 ); executeAction( id970, desc209, DialogModes.NO ); } function doWork(doc, prog) { try { var dir = new Folder(String(doc.fullName).replace(/\.[^\.]*$/, "")); } catch (e) { alert(e, "Document not saved", true); return; } if (!dir.exists && !dir.create()) { alert("Could not create a directory to place output files in:\n" + dir.fsName, "Could not create directory", true); return; } var files = dir.getFiles("!frame_?????.*"); for (var i = 0; i < files.length; i = i + 1) { if (!files[i].remove()) { alert("Could not remove old output files. Please close applications that may be using them and try again. File:\n" + dir.fsName, "Could not remove old output files", true); return; } } var n; for (var i = 0; i < doc.layers.length; i = i + 1) { if (doc.layers[i].name.toString() == midLayerName.toString()) { n = i; break; } } var opts = new JPEGSaveOptions(); var zero = new UnitValue(0, "px"); var t = doc.layerComps.getByName("!!!TEMP") opts.quality = 10; for (var j = +stepsLeft; j < +stepsRight + 1; j = j + 1) { for (var i = 0; i < doc.layers.length; i = i + 1) { curr = doc.layers[i]; if (curr.visible) { doc.activeLayer = curr; shift(j * stepSize * (n - i), zero); } } try { var file = new File(dir + "/!frame_" + (j + 50000) + ".jpg"); doc.saveAs(file, opts, true); } catch (e) { alert("Could not save file:\n" + file.fsName, "Could not create file", true); return; } t.apply(); prog.value++; } } function main() { readSettings(settings); var doc = app.activeDocument; var t = doc.layerComps.add("!!!TEMP", "", true, true, true); t = doc.layerComps.getByName("!!!TEMP"); var window = buildWindow(doc); writeSettings(settings); t.remove(); }