Photoshop API directory crawling

I’m still trying to get my feet wet with tech-artistry and I stumbled onto something that could help my efforts in deconstructing an engine/content that I’m working with…

I’m working with ArmAIII and have a tool packed with this software that can convert from the compressed paa format to tga format. I’ve found a method that can execute this converter by writing a batch script through Photoshop’s file.execute command explained here.

This sample code allows me to define the Cfile_in and Cfile_out explicitly, but I’m looking for a way to assign those variables for each time that a paa file is found throughout a vast directory structure. So I want something that will crawl from a root location and if a paa file is found at that directory layer then apply this code to it:

Cfile_in = "path/file.paa";
Cfile_out = "path/file.tga";

pal2pace = function(){};
pal2pace.execute = function(){

var bat = new File("/c/data/pal2pace.bat");
bat.open("w");
bat.writeln("p:\	ools\	ex\\Pal2PacE.exe\ " +Cfile_in + " " + Cfile_out+"");
bat.execute();
};

function main(){
alert(pal2pace.execute());
};

main();

This works good for one texture and I am learning how to build this out further, but wanted to know if anyone has experience in writing JSX scripts for Photoshop. First, is this API something that’s widely used by tech-artists given the breadth of tools that are out there?

Secondly, does anybody know if it’s possible to script crawling through directories? I want to start with a root directory and find all the paa files in this directory, then convert each file. For each directory within this, crawl it and search for paa files and then convert each of those. Is this possible or far fetched?

you can, but why are you using photoshop for this?

It seemed like it was a better option since I don’t really know Windows Batch Scripting. I’m open to suggestions, but am limited with what tools I have on my workstation and the JavaScript structure was more familiar to me. I actually do have a working script that will convert all the files in a folder, but I still don’t know how to make it crawl from a root level folder through each subfolder and I still have to define the root folder.

function main(){
var root = Folder("c:\\root");
var listFiles = root.getFiles("*.paa");
var bat = new File("/c/root/pal2pace.bat");
bat.open("w");

//format path so it's written correctly for batch file
var Cfolder = String(root).replace(/\//g, "\\").replace("\\","");

for (i = 0; i < listFiles.length; i++){
var Cfile_in = String(Cfolder).replace("c\\", "c:\\")+ "\\" + listFiles[i].name;
var Cfile_in = String(Cfolder).replace("c\\", "c:\\")+ "\\" + listFiles[i].name.replace(".paa", ".tga");

bat.writeln("p:\	ools\	ex\\Pal2PacE.exe\ " +Cfile_in+ " " +Cfile_out);
};

bat.close();
bat.execute();


};

main();

What i mean is, you’re using photoshop for what seems to actually not use photoshop for anything. Why not use python or c# or node? You wont have to fight against photoshops js implementation and limitations.

If you really want button for this script in Photoshop, just call python (cmd line call) from PS and be done with it.

As for directory crawl, I just did it last week, this is snippet from my code I modified somewhere from net, it searches in Folder tFolder for file named exactly string mask.
You will have modify it for it to not return, but do whatever you want on found pattern.

function scanSubFolders(tFolder, mask) {
	var sFolders = new Array();
    var allFiles = new Array(); 
    sFolders[0] = tFolder; 
    for (var j = 0; j < sFolders.length; j++){ // loop through folders      
        var procFiles = sFolders[j].getFiles(); 
        for (var i=0;i<procFiles.length;i++){ // loop through this folder contents 
            if (procFiles[i] instanceof File ){
                if(procFiles[i].name == mask) {
		    return procFiles[i].path + "/" + procFiles[i].name
		}
	    } else if (procFiles[i] instanceof Folder) {
		var file = scanSubFolders(procFiles[i], mask);
		if (file != "not found") {
			return file;
		}
	    }
	} 
   } 
   return "not found";
};

Thanks for your posts. I will work on something in the coming week or so, but I have to focus back on some other work for the next few days. I would really like to learn how to write and run scripts outside of Photoshop (or any other application) like @TheMaxx suggested. The machine I’m working on doesn’t have Visual Studio, but I did find the command line compiler for .NET Framework 4 so I can still write with a simple IDE and build. Thanks again guys for your help.

There’s two different issues: the back end that does the work and the front end in PS (or some other application, or just a command line).

If you’re comfortable in JavaScript you can do the back end without Photoshop using Node (https://nodejs.org/). Or you can pick up Python, which is a better general-purpose system management tool. For the front end, you will need to do a PS button in Javascript but you probably want to keep that part as simple as possible and put the hard work into the back end. That way you or other power users can do fancy stuff from the command line while the n00bs use the buttons, but the code base is shared :slight_smile:

Ok, I have spent some time working on a solution and I think I have one that should suffice. This recursively crawls a directory and if a paa file is found it will convert to a tga by starting a process (Bohemia’s Pal2PacE converter) along with the correct parameters. This is a very different solution than I was originally looking for, but after considering your comments I realized what I was doing was wrong.

to use this you need ModelConverter in p: ools
command line use: > folderpath/convert_paa_to_tga “c:\folder\root_to_crawl”

using System;
using System.IO;
using System.Diagnostics;

public class convert_paa_to_tga{
	public static void Main(string[] args){
		foreach (string path in args){
			if(File.Exists(path)){
				ProcessFile(path);
			}
			else if(Directory.Exists(path)){
				ProcessDirectory(path);
			}
			else{
				Console.WriteLine("{0} is not a valid file or directory.", path);
			}
		}
	}
	
	public static void ProcessDirectory(string targetDirectory){
		string [] fileEntries = Directory.GetFiles(targetDirectory);
		foreach (string fileName in fileEntries){
			ProcessFile(fileName);
			}
			
		string[] subdirectoryEntries = Directory.GetDirectories(targetDirectory);
		foreach(string subdirectory in subdirectoryEntries)
			ProcessDirectory(subdirectory);
	}
	
	public static void ProcessFile(string path){
		if (Path.GetExtension(path) == ".paa"){
			ExecuteBatchScript(path);
		}	
	}
	
	public static void ExecuteBatchScript(string path){
		string origin = path;
		string destin = path.Replace(".paa", ".tga");
		
		var processInfo = new ProcessStartInfo();
			processInfo.FileName = @"p:	ools	ex\Pal2PacE.exe";
			processInfo.Arguments = string.Format(" {0} {1}", origin, destin);
			processInfo.CreateNoWindow = false;
			processInfo.UseShellExecute = false;
			processInfo.RedirectStandardError = true;
			processInfo.RedirectStandardOutput = true;
				
		var process = Process.Start(processInfo);
			process.Start();
			process.WaitForExit();
	}
}

If anybody else reading this is an ArmA developer note that this tool will batch export paa to tga files (moving from proprietary format to standardized), but you can also call their other converter tool (p3d to fbx) with this same script and convert a whole project textures and models.