// FacePalmer v3.0 // http://forums.qhimm.com/index.php?topic=11933.0 // A Final Fantasy VII Texture Resizing Batch Script for Photoshop CS5.1 // by Omzy // Credits to yarLson for resize() function // Requires Aali's Palmer 0.7 for input and conversion // Requires Adobe Photoshop CS5.1 (untested on other versions) // Recommended ExtendScript Toolkit for script editing // Requires Perfect Resize 7.0 Professional Edition (PS Plug-in) // Requires Perfectum Filter v1.4 (PS Plug-in) // Requires Aali's OpenGL Driver to play in-game // Tested under Windows 7 32-bit //========Adjustment Parameters========= //General var resizeFactor = 4 //Only put 2 or 4 //Perfect Resize var textureControlAmount = 1 var textureControlThreshold = 10 var textureControlSmoothness = 0 var sharpen = true var sharpenMethod = 0 var sharpenRadius = 2 var sharpenAmount = 25 var sharpenHighlights = 20 var sharpenShadows = 20 //Reduce noise filter var rdfStrength = 2 var rdfPresDetail = 100 var rdfRemColNoise = 50 var rdfSharpDetail = 25 //Film Grain var fgIntensity = 15 var fgContrast = 50 //Perfectum Smoothing var perfSmoothPercent = 20 //Doesn't work, always 20 unless recorded again //========Adjustment Parameters========= //Resizes activeDocument //May be modified to support other resizing methods / programs function resize () { perfectResize(sharpen, sharpenMethod, sharpenRadius, sharpenAmount, sharpenHighlights, sharpenShadows, textureControlAmount, textureControlThreshold, textureControlSmoothness) reduceNoise(rdfRemColNoise, rdfSharpDetail, rdfStrength, rdfPresDetail) //applyFilmGrain(fgIntensity, fgContrast) perfectum(/*perfSmoothPercent*/) } //GLOBALS var textureFolder = null var fileList = null var layerGroup = null //layerGroup Structure //LayerType 0 (Standard) //Group 0 = BG (0, 0-128) //child = 0 //child = file id << 8 + file index //Group 1 = FG (0, 128-147) //child = 0 //child = file id << 8 + file index //Group 2 = Anims (0, 148-65535) //child = anim group //child = file id << 8 + file index //Group 3 = Alpha Anims (0, 65536>) //child = anim group //child = file id << 8 + file index //Group 4 = missingBlock //child = 0 //child = file id << 8 + file index //Group 5 = RequiredAnims //child = file id << 8 + file index //LayerType 1 (Parallax 1) //Same (no Group 5) //LayerType 2 (Parallax 2) //Same (no Group 5) //MAIN SECTION //Save original preferences var originalUnit = preferences.rulerUnits var originalType = preferences.typeUnits preferences.rulerUnits = Units.PIXELS preferences.typeUnits = TypeUnits.PIXELS //Get all folders and resize their contents var inputFolder = new Folder(app.path + "\\ff7TexturesIN") //Texture input folder var outputFolder = new Folder(app.path + "\\ff7TexturesOUT") //Texture output folder outputFolder.create() var folderList = inputFolder.getFiles() //List of all folders (one folder per texture) var i = 0 for (i = 0; i < folderList.length; i++) //For every texture { textureFolder = new Folder(outputFolder.path + "\\" + outputFolder.name+ "\\" + folderList[i].name) //Texture output folder textureFolder.create() fileList = folderList[i].getFiles("*.png") //List of all layers in texture analyzeFiles() //printTree() //printRequiredAnims() //printParallaxAnims() //printLightingTextures() if (layerGroup != null) { var j = 0 for (j = 0; j < layerGroup.length; j++) { //For all types if (layerGroup[j] != null) { var k = 0 for (k = 0; k < layerGroup[j].length; k++) { //For all groups if (layerGroup[j][k] != null) { var l = 0 for (l = 0; l < layerGroup[j][k].length; l++) { //For all subgroups if (layerGroup[j][k][l] != null) { var m = 0 for (m = 0; m < layerGroup[j][k][l].length; m++) { //For all images if (k != 1 && k != 4 && !(k == 2 && m > 0)) buildComposite (j, k, l, m) //Condition ensures only required composites are generated (efficiency) facepalm (j, k, l, m) }m = null} }l = null} }k = null} }j = null} //Delete all composite files var compList = textureFolder.getFiles("*_c.png") //List of all composites var p = 0 for (p = 0; p < compList.length; p++) { compList[p].remove() } //Release references p = null compList = null } //Restore original preferences preferences.rulerUnits = originalUnit preferences.typeUnits = originalType //Release references i = null originalUnit = null originalType = null inputFolder = null outputFolder = null folderList = null resizeFactor = null textureControlAmount = null textureControlThreshold = null textureControlSmoothness = null sharpen = null sharpenMethod = null sharpenRadius = null sharpenAmount = null sharpenHighlights = null sharpenShadows = null rdfStrength = null rdfPresDetail = null rdfRemColNoise = null rdfSharpDetail = null fgIntensity = null fgContrast = null perfSmoothPercent = null textureFolder = null fileList = null layerGroup = null //ESSENTIAL FUNCTIONS function analyzeFiles () { layerGroup = new Array(3); layerGroup[0] = new Array(6); layerGroup[1] = new Array(5); layerGroup[2] = new Array(5); //Required Anims cases var name = fileList[0].name.substring(0, fileList[0].name.length - 15) if (name == "anfrst_4") { layerGroup[0][5] = new Array(4) //Length of this array specifies number of requiredAnims layerGroup[0][5][0] = (644 << 8) + 4 layerGroup[0][5][1] = (648 << 8) + 4 layerGroup[0][5][2] = (652 << 8) + 4 layerGroup[0][5][3] = (656 << 8) + 4 } else if (name == "blin66_1") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (644 << 8) + 1 } else if (name == "blin66_2") { layerGroup[0][5] = new Array(2) layerGroup[0][5][0] = (644 << 8) + 1 layerGroup[0][5][1] = (648 << 8) + 1 } else if (name == "blin66_6") { layerGroup[0][5] = new Array(2) layerGroup[0][5][0] = (644 << 8) + 1 layerGroup[0][5][1] = (648 << 8) + 1 } else if (name == "bonevil2") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (644 << 8) + 1 } else if (name == "bonevil") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (644 << 8) + 1 } else if (name == "bugin1a") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (644 << 8) + 0 } else if (name == "bugin2") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (648 << 8) + 1 } else if (name == "colne_1") { layerGroup[0][5] = new Array(2) layerGroup[0][5][0] = (908 << 8) + 2 layerGroup[0][5][1] = (912 << 8) + 1 } else if (name == "colne_3") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (900 << 8) + 3 } else if (name == "colne_5") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (1412 << 8) + 0 } else if (name == "condor2") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (644 << 8) + 1 } else if (name== "ealin_2") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (644 << 8) + 1 } else if (name == "gidun_1") { layerGroup[0][5] = new Array(4) layerGroup[0][5][0] = (644 << 8) + 1 layerGroup[0][5][1] = (648 << 8) + 1 layerGroup[0][5][2] = (652 << 8) + 1 layerGroup[0][5][3] = (656 << 8) + 1 } else if (name == "hyou4") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (644 << 8) + 5 } else if (name == "itown12") { layerGroup[0][5] = new Array(2) layerGroup[0][5][0] = (644 << 8) + 7 } else if (name == "itown1a") { layerGroup[0][5] = new Array(2) layerGroup[0][5][0] = (644 << 8) + 7 } else if (name == "itown2") { layerGroup[0][5] = new Array(4) layerGroup[0][5][0] = (644 << 8) + 7 layerGroup[0][5][2] = (652 << 8) + 7 } else if (name == "junbin4") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (648 << 8) + 1 } else if (name == "junonr3") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (644 << 8) + 1 } else if (name == "md8_52") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (644 << 8) + 4 } else if (name == "mkt_s3") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (900<< 8) + 1 } else if (name == "move_f") { layerGroup[0][5] = new Array(2) layerGroup[0][5][0] = (644 << 8) + 1 layerGroup[0][5][1] = (648 << 8) + 1 } else if (name == "mrkt1") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (644 << 8) + 5 } else if (name == "nivinn_1") { layerGroup[0][5] = new Array(2) layerGroup[0][5][0] = (900 << 8) + 1 layerGroup[0][5][1] = (904 << 8) + 1 } else if (name == "nivinn_2") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (904 << 8) + 1 } else if (name == "nivl_2") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (648 << 8) + 4 } else if (name == "nivl_4") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (648 << 8) + 4 } else if (name == "nivl") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (648 << 8) + 4 } else if (name == "nvmkin1") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (644 << 8) + 3 } else if (name == "sbwy4_1") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (644 << 8) + 1 } else if (name == "ship_1") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (644 << 8) + 7 } else if (name == "sininb41") { layerGroup[0][5] = new Array(4) layerGroup[0][5][0] = (900 << 8) + 0 layerGroup[0][5][1] = (904 << 8) + 0 layerGroup[0][5][2] = (908 << 8) + 0 layerGroup[0][5][3] = (912 << 8) + 0 } else if (name == "southmk2") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (644 << 8) + 1 } else if (name == "subin_2a") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (644 << 8) + 1 } else if (name == "subin_2b") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (644 << 8) + 1 } else if (name == "tin_1") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (920 << 8) + 3 } else if (name == "tin_2") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (920 << 8) + 3 } else if (name == "tin_3") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (920 << 8) + 3 } else if (name == "tin_4") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (920 << 8) + 3 } else if (name == "tower5") { layerGroup[0][5] = new Array(2) layerGroup[0][5][0] = (644 << 8) + 4 layerGroup[0][5][1] = (656 << 8) + 1 } else if (name == "uttmpin4") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (648 << 8) + 1 } else if (name == "uutai2") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (652 << 8) + 1 } else if (name == "zcoal_1") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (764 << 8) + 0 } else if (name == "zcoal_2") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (644 << 8) + 1 } else if (name == "zcoal_3") { layerGroup[0][5] = new Array(1) layerGroup[0][5][0] = (648 << 8) + 1 } var type = 0 var gid = 0 var sgid = 0 var i = 0 for (i = 0; i < fileList.length; i++) { var tempType = parseInt(fileList[i].name.charAt(fileList[i].name.indexOf("000") - 2), 10) var newType = false if (type != tempType) { newType = true } type = tempType var idIndex = fileList[i].name.indexOf("000") var id = parseInt(fileList[i].name.substring(idIndex, fileList[i].name.length - 4), 10) if ( (type == 0) && (name != "hyou5_2") && ( //Missing block exceptions (id == 260) || (id == 304) || (id == 516) || (id == 520) || (id == 772) || (id == 776) || (id == 1020) || (id == 1284) || (id == 1296) || (id == 1816) || (id == 2308) || (id == 5712) || (id == 6504) || (id == 8456) || (id == 12816) || (id == 16660) || (id == 65632) || (id == 65732) )) { gid = 4 sgid = 0 } else if (id < 128) { gid = 0 sgid = 0 } else if (id >= 128 && id < 148) { gid = 1 sgid = 0 } else if (id >= 148 && id < 65536) { if ((layerGroup[0][4] != null) && (layerGroup[0][2] != null)) //Bugfix { if ((layerGroup[0][4][0][0] & 255) == (i - 1)) { gid = 2 sgid = layerGroup[0][2].length - 1 } } if (gid != 2 || newType) {sgid = -1} gid = 2 if (id % 4 == 0) //New SubGroup { sgid++ } } else if (id >= 65536) { if (gid != 3 || newType) {sgid = -1} gid = 3 if (id % 4 == 0) //New SubGroup { sgid++ } } if (layerGroup[type][gid] == null) //Open Group { layerGroup[type][gid] = new Array(); } if (layerGroup[type][gid][sgid] == null) //Open SubGroup { layerGroup[type][gid][sgid] = new Array(); layerGroup[type][gid][sgid][0] = (id << 8) + i; } else { layerGroup[type][gid][sgid][layerGroup[type][gid][sgid].length] = (id << 8) + i; //Add layer } //Release references idIndex = null id = null tempType = null newType = null } //Release references i = null type = null gid = null sgid = null name = null } function buildComposite (type, gid, sgid, id) { //Open layer var file = fileList[layerGroup[type][gid][sgid][id] & 255] app.open(file) //If has consecutive animation layers, place all on bottom if (gid == 2 || gid == 3) { moveGroup(type, gid, sgid, id, gid, false) } //If no required anims, use background composite if (gid == 2 && layerGroup[0][5] == null) { var c_file = new File(textureFolder.path + "\\" + textureFolder.name+ "\\" + fileList[0].name.substring(0, fileList[0].name.length - 15) + "_" + type + "_" + "00000000" + "_c.png") var master = activeDocument try { app.open(c_file) var foreLayer = activeDocument.activeLayer.duplicate(master) activeDocument.close(SaveOptions.DONOTSAVECHANGES) foreLayer.move(master.artLayers[master.artLayers.length - 1], ElementPlacement.PLACEAFTER) //Release references foreLayer = null } catch (err) {} //Release references c_file = null master = null } //If has required anims, place all on bottom if (type == 0 && ((gid == 0 || gid == 2) && layerGroup[0][5] != null)) //RequiredAnims Flag = true { //Move req anims moveGroup(type, gid, sgid, id, 2, true) } //If has foreground layers, place all on bottom if (gid == 0 || (type == 0 && gid == 2 && layerGroup[0][5] != null)) { moveGroup(type, gid, sgid, id, 1, false) } //If has bg layer, place it on bottom if (gid == 0 || (type == 0 && gid == 2 && layerGroup[0][5] != null)) { moveGroup(type, gid, sgid, id, 0, false) } //If missingBlock, place it on bottom if (type == 0 && (gid == 0 || (gid == 2 && layerGroup[0][5] != null))) { if (type == 0) moveGroup(type, gid, sgid, id, 4, false) } //If needed, place black layer on bottom if ((type == 0 && (gid == 0 || (gid == 2 && layerGroup[0][5] != null))) || (gid == 3)) { var prevLayer = activeDocument.activeLayer var blackLayer = activeDocument.artLayers.add() activeDocument.activeLayer = blackLayer activeDocument.selection.selectAll() var blackColor = new SolidColor blackColor.rgb.red = 0 blackColor.rgb.green = 0 blackColor.rgb.blue = 0 activeDocument.selection.fill(blackColor) if (gid == 3 && (id > 0)) { blackLayer.move(activeDocument.artLayers[0], ElementPlacement.PLACEBEFORE) } else { blackLayer.move(activeDocument.artLayers[activeDocument.artLayers.length - 1], ElementPlacement.PLACEAFTER) } activeDocument.activeLayer = prevLayer //Release references prevLayer = null blackLayer = null blackColor = null } //Merge layers try { activeDocument.mergeVisibleLayers() } catch (err) {} //Save composite var saveOptions = new PNGSaveOptions() saveOptions.interlaced = false var compositeFile = new File(textureFolder.path + "\\" + textureFolder.name+ "\\" + file.name.substring(0, file.name.length - 4) + "_c.png") activeDocument.saveAs(compositeFile, saveOptions, false, Extension.LOWERCASE) activeDocument.close(SaveOptions.DONOTSAVECHANGES) //Release references file = null saveOptions = null compositeFile = null } function moveGroup (type, gid, sgid, id, move_gid, reqAnims) { if (layerGroup[type][move_gid] != null) { var i = 0 for (i = 0; i < layerGroup[type][move_gid].length; i++) { if (layerGroup[type][move_gid][i] != null) { var j = 0 for (j = 0; j < layerGroup[type][move_gid][i].length; j++) { var foreLayer = null var master = null if (layerGroup[type][move_gid][i][j] != layerGroup[type][gid][sgid][id]) //Layers in order { if (reqAnims) { var this_id = layerGroup[type][gid][sgid][id] >> 8 this_id = this_id - (this_id % 4) var move_id = layerGroup[type][move_gid][i][j] >> 8 move_id = move_id - (move_id % 4) var move_req_anim = false var p = 0 for (p = 0; p < layerGroup[0][5].length; p++) { var reqAnim = layerGroup[0][5][p] >> 8 var numAnims = layerGroup[0][5][p] & 255 if (move_id == reqAnim) move_req_anim = true var nextAnim = reqAnim var q = 0 if (reqAnim >= 900) q = q + 1 if (reqAnim >= 1412) q = q + 1 var r = 0 for (r = 0; r < numAnims; r++) { nextAnim = nextAnim + (256 << (r + q)) if (this_id == nextAnim) move_req_anim = false } if (move_req_anim == true) { master = activeDocument app.open(fileList[layerGroup[type][move_gid][i][j] & 255]) foreLayer = activeDocument.activeLayer.duplicate(master) activeDocument.close(SaveOptions.DONOTSAVECHANGES) foreLayer.move(master.artLayers[master.artLayers.length - 1], ElementPlacement.PLACEAFTER) } //Release references r = null reqAnim = null numAnims = null nextAnim = null q = null } //Release references p = null this_id = null move_id = null move_req_anim = null } else if (gid != move_gid || i == sgid) { master = activeDocument app.open(fileList[layerGroup[type][move_gid][i][j] & 255]) foreLayer = activeDocument.activeLayer.duplicate(master) activeDocument.close(SaveOptions.DONOTSAVECHANGES) foreLayer.move(master.artLayers[master.artLayers.length - 1], ElementPlacement.PLACEAFTER) } } else { master = activeDocument foreLayer = master.artLayers[0] foreLayer.move(master.artLayers[master.artLayers.length - 1], ElementPlacement.PLACEAFTER) } if (gid == 3 && layerGroup[type][move_gid][i].length > 1 && foreLayer != null) { foreLayer.blendMode = BlendMode.LINEARDODGE } //Release references master = null foreLayer = null }j = null} }i = null} } function facepalm (type, gid, sgid, id) { //For any given image, the correct composite is: //Background -> Background (00000000) //Foreground -> Background (00000000) //Anims -> Anim - (Anim % 4) //Missing block -> Background (00000000) //Parallax -> Parallax var compositeFile = null if (type == 0 && (gid == 0 || gid == 1 || gid == 4)) { compositeFile = new File(textureFolder.path + "\\" + textureFolder.name + "\\" + fileList[0].name.substring(0, fileList[0].name.length - 4) + "_c.png") } else { var anim_id = layerGroup[type][gid][sgid][id] >> 8 if (!(gid == 3 && id > 0)) { anim_id = anim_id - (anim_id % 4) } var anim_string = "" + anim_id while (anim_string.length < 8) { anim_string = "0" + anim_string } compositeFile = new File(textureFolder.path + "\\" + textureFolder.name + "\\" + fileList[0].name.substring(0, fileList[0].name.length - 15) + "_" + type + "_" + anim_string + "_c.png") //Release references anim_id = null anim_string = null } if (compositeFile != null) { app.open(compositeFile) var compDoc = activeDocument var cutDoc = null var origLayer = null //Combine if (gid == 1 || gid == 2 || gid == 4) { app.open(fileList[layerGroup[type][gid][sgid][id] & 255]) cutDoc = activeDocument origLayer = cutDoc.activeLayer var cutState = cutDoc.activeHistoryState /*origLayer.duplicate() //origLayer.applyMedianNoise(1) //cutDoc.mergeVisibleLayers()*/ if (gid != 4) { cutDoc.activeLayer.duplicate(compDoc) cutDoc.activeHistoryState = cutState activeDocument = compDoc compDoc.mergeVisibleLayers() } activeDocument = compDoc //Release references cutState = null } //------------------------------------------------- resize() //------------------------------------------------- //If white border, give edge smoothing via median noise //ToDo //Cut if (gid == 1 || gid == 2 || gid == 4) { activeDocument = cutDoc cutDoc.resizeImage(cutDoc.width * 2, cutDoc.height * 2, cutDoc.resolution, ResampleMethod.NEARESTNEIGHBOR) origLayer = cutDoc.activeLayer origLayer.duplicate() origLayer.applyMedianNoise(1) cutDoc.mergeVisibleLayers() if (resizeFactor == 4) { cutDoc.resizeImage(cutDoc.width * 2, cutDoc.height * 2, cutDoc.resolution, ResampleMethod.NEARESTNEIGHBOR) origLayer = cutDoc.activeLayer origLayer.duplicate() origLayer.applyMedianNoise(1) cutDoc.mergeVisibleLayers() } selectTransparency() maskRevealSelection() showMaskChannel() cutDoc.selection.selectAll() cutDoc.selection.copy() cutDoc.close(SaveOptions.DONOTSAVECHANGES) activeDocument = compDoc maskRevealAll() showMaskChannel() compDoc.selection.selectAll() compDoc.paste() applyMask() } //Save Options var saveOptions = new PNGSaveOptions() saveOptions.interlaced = false //Save resized layer //alert(fileList[layerGroup[type][gid][sgid][id] & 255].name) var layerFile = new File(textureFolder.path + "\\" + textureFolder.name+ "\\" + fileList[layerGroup[type][gid][sgid][id] & 255].name) compDoc.saveAs(layerFile, saveOptions, false, Extension.LOWERCASE) compDoc.close(SaveOptions.DONOTSAVECHANGES) //Release references compDoc = null cutDoc = null origLayer = null saveOptions = null layerFile = null } //Release references compositeFile = null } //DEBUG FUNCTIONS function printTree () { if (layerGroup != null) { var treeString = "" for (var j = 0; j < layerGroup.length; j++) { //For all types treeString = treeString + "Type " + j + "\n" if (layerGroup[j] != null) { for (var k = 0; k < layerGroup[j].length; k++) { //For all groups treeString = treeString + " Group " + k + "\n" if (layerGroup[j][k] != null) { for (var l = 0; l < layerGroup[j][k].length; l++) { //For all subgroups treeString = treeString + " SubGroup " + l + "\n" if (layerGroup[j][k][l] != null) { for (var m = 0; m < layerGroup[j][k][l].length; m++) { //For all images treeString = treeString + " " + (layerGroup[j][k][l][m] >> 8) + " : " + (layerGroup[j][k][l][m] & 255) + "\n" }} }} }} }alert(treeString)} } function printRequiredAnims () { var animString = "" if (layerGroup[0][5] != null) { for (var i = 0; i < layerGroup[0][5].length; i++) { animString = animString + (layerGroup[0][5][i] >> 8) + " : " + (layerGroup[0][5][i] & 255) + "\n" } } alert (animString) } function printParallaxAnims () //Must put blank ParallaxAnims.txt inside ff7TexturesOUT folder, restart photoshop each execution { if (layerGroup[1][2] != null) { for (var i = 0; i < layerGroup[1][2].length; i++) { if (layerGroup[1][2][i].length > 1) { var f = File(outputFolder.name + "\\ParallaxAnims.txt") f.open ("a") f.writeln(fileList[0].name.substring(0, fileList[0].name.length - 15)) f.close() break; } } } else if (layerGroup[1][3] != null) { for (var i = 0; i < layerGroup[1][3].length; i++) { if (layerGroup[1][3][i].length > 1) { var f = File(outputFolder.name + "\\ParallaxAnims.txt") f.open ("a") f.writeln(fileList[0].name.substring(0, fileList[0].name.length - 15)) f.close() break; } } } else if (layerGroup[2][2] != null) { for (var i = 0; i < layerGroup[2][2].length; i++) { if (layerGroup[2][2][i].length > 1) { var f = File(outputFolder.name + "\\ParallaxAnims.txt") f.open ("a") f.writeln(fileList[0].name.substring(0, fileList[0].name.length - 15)) f.close() break; } } } else if (layerGroup[2][3] != null) { for (var i = 0; i < layerGroup[2][3].length; i++) { if (layerGroup[2][3][i].length > 1) { var f = File(outputFolder.name + "\\ParallaxAnims.txt") f.open ("a") f.writeln(fileList[0].name.substring(0, fileList[0].name.length - 15)) f.close() break; } } } } function printLightingTextures () //Must put blank LightingTextures.txt inside ff7TexturesOUT folder, restart photoshop each execution { if (layerGroup[0][3] != null) { for (var i = 0; i < layerGroup[0][3].length; i++) { if (layerGroup[0][3][i].length > 1) { var f = File(outputFolder.name + "\\LightingTextures.txt") f.open ("a") f.writeln(fileList[0].name.substring(0, fileList[0].name.length - 15)) f.close() break; } } } } //RECORDED FUNCTIONS //Perfect Resize function function perfectResize (se, sm, sr, sa, st, ss, bs, td, ts) { var resizeWidth = activeDocument.width * resizeFactor var resizeHeight = activeDocument.height * resizeFactor if ((resizeWidth % 2) > 0) resizeWidth = resizeWidth + 1 //Sometimes math is off and will calculate 1 less than the desired size if ((resizeHeight % 2) > 0) resizeHeight = resizeHeight + 1 var idonOnePerfectResizesevenzeroProfessionalEdition = stringIDToTypeID( "onOne Perfect Resize 7.0 Professional Edition" ); var desc2 = new ActionDescriptor(); var idgfBP = charIDToTypeID( "gfBP" ); var idtyBP = charIDToTypeID( "tyBP" ); var idbpPD = charIDToTypeID( "bpPD" ); desc2.putEnumerated( idgfBP, idtyBP, idbpPD ); var idgfPW = charIDToTypeID( "gfPW" ); //Width in pixels desc2.putInteger( idgfPW, resizeWidth ); var idgfPH = charIDToTypeID( "gfPH" ); //Height in pixels desc2.putInteger( idgfPH, resizeHeight ); var idgfCP = charIDToTypeID( "gfCP" ); //Constrain proportions desc2.putBoolean( idgfCP, true ); var idgfSE = charIDToTypeID( "gfSE" ); //Sharpen ON/OFF desc2.putBoolean( idgfSE, se ); var idgfSM = charIDToTypeID( "gfSM" ); //Sharpen method desc2.putInteger( idgfSM, sm ); var idgfSR = charIDToTypeID( "gfSR" ); //Sharpen radius desc2.putInteger( idgfSR, sr ); var idgfSA = charIDToTypeID( "gfSA" ); //Sharpen amount desc2.putInteger( idgfSA, sa ); var idgfST = charIDToTypeID( "gfST" ); //Sharpen highlights desc2.putInteger( idgfST, st ); var idgfSS = charIDToTypeID( "gfSS" ); //Sharpen shadows desc2.putInteger( idgfSS, ss ); var idgfBS = charIDToTypeID( "gfBS" ); //Texture control amount desc2.putInteger( idgfBS, bs ); var idgfTD = charIDToTypeID( "gfTD" ); //Texture control threshold desc2.putInteger( idgfTD, td ); var idgfTS = charIDToTypeID( "gfTS" ); //Texture control smoothness desc2.putInteger( idgfTS, ts ); executeAction( idonOnePerfectResizesevenzeroProfessionalEdition, desc2, DialogModes.NO ); //Release references resizeWidth = null resizeHeight = null idonOnePerfectResizesevenzeroProfessionalEdition = null desc2 = null idgfBP = null idtyBP = null idbpPD = null idgfPW = null idgfPH = null idgfCP = null idgfSE = null idgfSM = null idgfSR = null idgfSA = null idgfST = null idgfSS = null idgfBS = null idgfTD = null idgfTS = null se = null sm = null sr = null sa = null st = null ss = null bs = null td = null ts = null } //Reduce noise function reduceNoise (clnsprc, shrpprc, amnt, edgf ) { var iddenoise = stringIDToTypeID( "denoise" ); var desc2 = new ActionDescriptor(); var idClNs = charIDToTypeID( "ClNs" ); var idPrc = charIDToTypeID( "#Prc" ); desc2.putUnitDouble( idClNs, idPrc, clnsprc ); var idShrp = charIDToTypeID( "Shrp" ); var idPrc = charIDToTypeID( "#Prc" ); desc2.putUnitDouble( idShrp, idPrc, shrpprc ); var idremoveJPEGArtifact = stringIDToTypeID( "removeJPEGArtifact" ); desc2.putBoolean( idremoveJPEGArtifact, false ); var idchannelDenoise = stringIDToTypeID( "channelDenoise" ); var list1 = new ActionList(); var desc3 = new ActionDescriptor(); var idChnl = charIDToTypeID( "Chnl" ); var ref1 = new ActionReference(); var idChnl = charIDToTypeID( "Chnl" ); var idChnl = charIDToTypeID( "Chnl" ); var idCmps = charIDToTypeID( "Cmps" ); ref1.putEnumerated( idChnl, idChnl, idCmps ); desc3.putReference( idChnl, ref1 ); var idAmnt = charIDToTypeID( "Amnt" ); desc3.putInteger( idAmnt, amnt ); var idEdgF = charIDToTypeID( "EdgF" ); desc3.putInteger( idEdgF, edgf ); var idchannelDenoiseParams = stringIDToTypeID( "channelDenoiseParams" ); list1.putObject( idchannelDenoiseParams, desc3 ); var desc4 = new ActionDescriptor(); var idChnl = charIDToTypeID( "Chnl" ); var ref2 = new ActionReference(); var idChnl = charIDToTypeID( "Chnl" ); var idChnl = charIDToTypeID( "Chnl" ); var idRd = charIDToTypeID( "Rd " ); ref2.putEnumerated( idChnl, idChnl, idRd ); desc4.putReference( idChnl, ref2 ); var idAmnt = charIDToTypeID( "Amnt" ); desc4.putInteger( idAmnt, 0 ); var idchannelDenoiseParams = stringIDToTypeID( "channelDenoiseParams" ); list1.putObject( idchannelDenoiseParams, desc4 ); var desc5 = new ActionDescriptor(); var idChnl = charIDToTypeID( "Chnl" ); var ref3 = new ActionReference(); var idChnl = charIDToTypeID( "Chnl" ); var idChnl = charIDToTypeID( "Chnl" ); var idGrn = charIDToTypeID( "Grn " ); ref3.putEnumerated( idChnl, idChnl, idGrn ); desc5.putReference( idChnl, ref3 ); var idAmnt = charIDToTypeID( "Amnt" ); desc5.putInteger( idAmnt, 0 ); var idchannelDenoiseParams = stringIDToTypeID( "channelDenoiseParams" ); list1.putObject( idchannelDenoiseParams, desc5 ); var desc6 = new ActionDescriptor(); var idChnl = charIDToTypeID( "Chnl" ); var ref4 = new ActionReference(); var idChnl = charIDToTypeID( "Chnl" ); var idChnl = charIDToTypeID( "Chnl" ); var idBl = charIDToTypeID( "Bl " ); ref4.putEnumerated( idChnl, idChnl, idBl ); desc6.putReference( idChnl, ref4 ); var idAmnt = charIDToTypeID( "Amnt" ); desc6.putInteger( idAmnt, 0 ); var idchannelDenoiseParams = stringIDToTypeID( "channelDenoiseParams" ); list1.putObject( idchannelDenoiseParams, desc6 ); desc2.putList( idchannelDenoise, list1 ); var idpreset = stringIDToTypeID( "preset" ); desc2.putString( idpreset, "Default" ); executeAction( iddenoise, desc2, DialogModes.NO ); //Release references iddenoise = null desc2 = null idClNs = null idPrc = null idShrp = null idremoveJPEGArtifact = null idchannelDenoise = null list1 = null desc3 = null idChnl = null ref1 = null idCmps = null idAmnt = null idEdgF = null idchannelDenoiseParams = null desc4 = null ref2 = null idRd = null desc5 = null ref3 = null idGrn = null desc6 = null ref4 = null idBl = null idpreset = null } //Apply film grain function applyFilmGrain(intn, cntr) { selectNonBlack() var idGrn = charIDToTypeID( "Grn " ); var desc2 = new ActionDescriptor(); var idGEfk = charIDToTypeID( "GEfk" ); var idGEft = charIDToTypeID( "GEft" ); var idGrn = charIDToTypeID( "Grn " ); desc2.putEnumerated( idGEfk, idGEft, idGrn ); var idIntn = charIDToTypeID( "Intn" ); desc2.putInteger( idIntn, intn ); var idCntr = charIDToTypeID( "Cntr" ); desc2.putInteger( idCntr, cntr ); var idGrnt = charIDToTypeID( "Grnt" ); var idGrnt = charIDToTypeID( "Grnt" ); var idGrSf = charIDToTypeID( "GrSf" ); desc2.putEnumerated( idGrnt, idGrnt, idGrSf ); executeAction( idGrn, desc2, DialogModes.NO ); deselect() //Release references idGrn = null desc2 = null idGEfk = null idGEft = null idGrn = null idIntn = null idCntr = null idGrnt = null idGrSf = null } //Select all non-black function selectNonBlack () { var idClrR = charIDToTypeID( "ClrR" ); var desc11 = new ActionDescriptor(); var idFzns = charIDToTypeID( "Fzns" ); desc11.putInteger( idFzns, 0 ); var idMnm = charIDToTypeID( "Mnm " ); var desc12 = new ActionDescriptor(); var idLmnc = charIDToTypeID( "Lmnc" ); desc12.putDouble( idLmnc, 0.000000 ); var idA = charIDToTypeID( "A " ); desc12.putDouble( idA, 0.000000 ); var idB = charIDToTypeID( "B " ); desc12.putDouble( idB, 0.000000 ); var idLbCl = charIDToTypeID( "LbCl" ); desc11.putObject( idMnm, idLbCl, desc12 ); var idMxm = charIDToTypeID( "Mxm " ); var desc13 = new ActionDescriptor(); var idLmnc = charIDToTypeID( "Lmnc" ); desc13.putDouble( idLmnc, 0.000000 ); var idA = charIDToTypeID( "A " ); desc13.putDouble( idA, 0.000000 ); var idB = charIDToTypeID( "B " ); desc13.putDouble( idB, 0.000000 ); var idLbCl = charIDToTypeID( "LbCl" ); desc11.putObject( idMxm, idLbCl, desc13 ); var idInvr = charIDToTypeID( "Invr" ); desc11.putBoolean( idInvr, true ); var idcolorModel = stringIDToTypeID( "colorModel" ); desc11.putInteger( idcolorModel, 0 ); executeAction( idClrR, desc11, DialogModes.NO ); //Release references idClrR = null desc11 = null idFzns = null idMnm = null desc12 = null idLmnc = null idA = null idB = null idLbCl = null idMxm = null desc13 = null idA = null idB = null idInvr = null idcolorModel = null } //Deselect function deselect() { var idsetd = charIDToTypeID( "setd" ); var desc14 = new ActionDescriptor(); var idnull = charIDToTypeID( "null" ); var ref3 = new ActionReference(); var idChnl = charIDToTypeID( "Chnl" ); var idfsel = charIDToTypeID( "fsel" ); ref3.putProperty( idChnl, idfsel ); desc14.putReference( idnull, ref3 ); var idT = charIDToTypeID( "T " ); var idOrdn = charIDToTypeID( "Ordn" ); var idNone = charIDToTypeID( "None" ); desc14.putEnumerated( idT, idOrdn, idNone ); executeAction( idsetd, desc14, DialogModes.NO ); //Release references idsetd = null desc14 = null idnull = null ref3 = null idChnl = null idfsel = null idT = null idOrdn = null idNone = null } //Perfectum smoothing function perfectum (/*percent*/) { var Perfectumonezerozero = stringIDToTypeID( "redfieldplugins.com/Perfectum1.00" ); var desc3 = new ActionDescriptor(); var idkkzerozero = charIDToTypeID( "kk00" ); desc3.putInteger( idkkzerozero, 88915769 ); //These two seemingly random numbers somehow control % var idkkzeroone = charIDToTypeID( "kk01" ); desc3.putInteger( idkkzeroone, -1607991020 ); var idkkzerotwo = charIDToTypeID( "kk02" ); desc3.putInteger( idkkzerotwo, 2064 ); var idkkzerothree = charIDToTypeID( "kk03" ); desc3.putInteger( idkkzerothree, 0 ); var idkkzerofour = charIDToTypeID( "kk04" ); desc3.putInteger( idkkzerofour, 0 ); var idkkzerofive = charIDToTypeID( "kk05" ); desc3.putInteger( idkkzerofive, 0 ); var idkkzerosix = charIDToTypeID( "kk06" ); desc3.putInteger( idkkzerosix, 0 ); var idkkzeroseven = charIDToTypeID( "kk07" ); desc3.putInteger( idkkzeroseven, 0 ); var idkkzeroeight = charIDToTypeID( "kk08" ); desc3.putInteger( idkkzeroeight, 0 ); var idkkzeronine = charIDToTypeID( "kk09" ); desc3.putInteger( idkkzeronine, 0 ); var idkkzerocolon = charIDToTypeID( "kk0:" ); desc3.putInteger( idkkzerocolon, 0 ); var idkkzerosemi = charIDToTypeID( "kk0;" ); desc3.putInteger( idkkzerosemi, 0 ); var idkkzeroless = charIDToTypeID( "kk0<" ); desc3.putInteger( idkkzeroless, 0 ); var idkkzeroequal = charIDToTypeID( "kk0=" ); desc3.putInteger( idkkzeroequal, 0 ); var idkkzerogreater = charIDToTypeID( "kk0>" ); desc3.putInteger( idkkzerogreater, 0 ); var idkkzeroquestion = charIDToTypeID( "kk0?" ); desc3.putInteger( idkkzeroquestion, 0 ); executeAction( Perfectumonezerozero, desc3, DialogModes.NO ); //Release references Perfectumonezerozero = null desc3 = null idkkzerozero = null idkkzeroone = null idkkzerotwo = null idkkzerothree = null idkkzerofour = null idkkzerofive = null idkkzerosix = null idkkzeroseven = null idkkzeroeight = null idkkzeronine = null idkkzerocolon = null idkkzerosemi = null idkkzeroless = null idkkzeroequal = null idkkzerogreater = null idkkzeroquestion = null } //Select layer transparency only function selectTransparency () { if(app.activeDocument.activeLayer.isBackgroundLayer) { return; // background doesn't have a transparency mask } var selection = charIDToTypeID( "setd" ); var desc = new ActionDescriptor(); var ref = new ActionReference(); ref.putProperty( charIDToTypeID( "Chnl" ), charIDToTypeID( "fsel" ) ); desc.putReference( charIDToTypeID( "null" ), ref ); var ref1 = new ActionReference(); ref1.putEnumerated( charIDToTypeID( "Chnl" ), charIDToTypeID( "Chnl" ), charIDToTypeID( "Trsp" ) ); desc.putReference( charIDToTypeID( "T " ), ref1 ); executeAction( selection, desc, DialogModes.NO ); //Release references selection = null desc = null ref = null ref1 = null } function maskRevealSelection () { var idMk = charIDToTypeID( "Mk " ); var desc3 = new ActionDescriptor(); var idNw = charIDToTypeID( "Nw " ); var idChnl = charIDToTypeID( "Chnl" ); desc3.putClass( idNw, idChnl ); var idAt = charIDToTypeID( "At " ); var ref3 = new ActionReference(); var idChnl = charIDToTypeID( "Chnl" ); var idChnl = charIDToTypeID( "Chnl" ); var idMsk = charIDToTypeID( "Msk " ); ref3.putEnumerated( idChnl, idChnl, idMsk ); desc3.putReference( idAt, ref3 ); var idUsng = charIDToTypeID( "Usng" ); var idUsrM = charIDToTypeID( "UsrM" ); var idRvlS = charIDToTypeID( "RvlS" ); desc3.putEnumerated( idUsng, idUsrM, idRvlS ); executeAction( idMk, desc3, DialogModes.NO ); //Release references idMk = null desc3 = null idNw = null idChnl = null idAt = null ref3 = null idMsk = null idUsng = null idUsrM = null idRvlS = null } function maskRevealAll () { var idMk = charIDToTypeID( "Mk " ); var desc17 = new ActionDescriptor(); var idNw = charIDToTypeID( "Nw " ); var idChnl = charIDToTypeID( "Chnl" ); desc17.putClass( idNw, idChnl ); var idAt = charIDToTypeID( "At " ); var ref12 = new ActionReference(); var idChnl = charIDToTypeID( "Chnl" ); var idChnl = charIDToTypeID( "Chnl" ); var idMsk = charIDToTypeID( "Msk " ); ref12.putEnumerated( idChnl, idChnl, idMsk ); desc17.putReference( idAt, ref12 ); var idUsng = charIDToTypeID( "Usng" ); var idUsrM = charIDToTypeID( "UsrM" ); var idRvlA = charIDToTypeID( "RvlA" ); desc17.putEnumerated( idUsng, idUsrM, idRvlA ); executeAction( idMk, desc17, DialogModes.NO ); //Release references idMk = null desc17 = null idNw = null idChnl = null idAt = null ref12 = null idMsk = null idUsng = null idUsrM = null idRvlA = null } function showMaskChannel () { var idShw = charIDToTypeID( "Shw " ); var desc4 = new ActionDescriptor(); var idnull = charIDToTypeID( "null" ); var list1 = new ActionList(); var ref4 = new ActionReference(); var idChnl = charIDToTypeID( "Chnl" ); var idOrdn = charIDToTypeID( "Ordn" ); var idTrgt = charIDToTypeID( "Trgt" ); ref4.putEnumerated( idChnl, idOrdn, idTrgt ); list1.putReference( ref4 ); desc4.putList( idnull, list1 ); executeAction( idShw, desc4, DialogModes.NO ); var idHd = charIDToTypeID( "Hd " ); var desc5 = new ActionDescriptor(); var idnull = charIDToTypeID( "null" ); var list2 = new ActionList(); var ref5 = new ActionReference(); var idChnl = charIDToTypeID( "Chnl" ); var idChnl = charIDToTypeID( "Chnl" ); var idRd = charIDToTypeID( "Rd " ); ref5.putEnumerated( idChnl, idChnl, idRd ); list2.putReference( ref5 ); var ref6 = new ActionReference(); var idChnl = charIDToTypeID( "Chnl" ); var idChnl = charIDToTypeID( "Chnl" ); var idGrn = charIDToTypeID( "Grn " ); ref6.putEnumerated( idChnl, idChnl, idGrn ); list2.putReference( ref6 ); var ref7 = new ActionReference(); var idChnl = charIDToTypeID( "Chnl" ); var idChnl = charIDToTypeID( "Chnl" ); var idBl = charIDToTypeID( "Bl " ); ref7.putEnumerated( idChnl, idChnl, idBl ); list2.putReference( ref7 ); desc5.putList( idnull, list2 ); executeAction( idHd, desc5, DialogModes.NO ); //Release references idShw = null desc4 = null idnull = null list1 = null ref4 = null idChnl = null idOrdn = null idTrgt = null idHd = null desc5 = null list2 = null ref5 = null idRd = null ref6 = null idGrn = null ref7 = null idBl = null } function applyMask () { var idDlt = charIDToTypeID( "Dlt " ); var desc21 = new ActionDescriptor(); var idnull = charIDToTypeID( "null" ); var ref17 = new ActionReference(); var idChnl = charIDToTypeID( "Chnl" ); var idOrdn = charIDToTypeID( "Ordn" ); var idTrgt = charIDToTypeID( "Trgt" ); ref17.putEnumerated( idChnl, idOrdn, idTrgt ); desc21.putReference( idnull, ref17 ); var idAply = charIDToTypeID( "Aply" ); desc21.putBoolean( idAply, true ); executeAction( idDlt, desc21, DialogModes.NO ); //Release references idDlt = null desc21 = null idnull = null ref17 = null idChnl = null idOrdn = null idTrgt = null idAply = null } function pasteInPlace () { var idpast = charIDToTypeID( "past" ); var desc6 = new ActionDescriptor(); var idinPlace = stringIDToTypeID( "inPlace" ); desc6.putBoolean( idinPlace, true ); var idAntA = charIDToTypeID( "AntA" ); var idAnnt = charIDToTypeID( "Annt" ); var idAnno = charIDToTypeID( "Anno" ); desc6.putEnumerated( idAntA, idAnnt, idAnno ); executeAction( idpast, desc6, DialogModes.NO ); //Release references idpast = null desc6 = null idinPlace = null idAntA = null idAnnt = null idAnno = null }