// Description:
//	This script has been tried on Adobe Photoshop CC 2014.
//	The script runs on both Windows or Mac-OS versions of Photoshop.
//	The script should work with all color spaces and pixel depths
//	To use, have an image open and run the script from Photoshop's "File->Scripts" menu.
//      This script converts Layered cube maps with layer names -X,+X,-Z,+Z,-Y,+Y, to horizontal single layer format.
//      Or horizontal/vertical cube map fomated documents to Layered cube map documents.
//       The original image reamins unatered, a new image is always created.
//       Any additional layer like Adjustment layers etc, will get duplicated into  the new image.
//       
//       Use this script to export a cubemap in split faces (into layers) format when color operating layers like adjustment layers 
//       are situates ontop of it. Then export the new file with the Intel Texture Works dds file format. 
//       This circumvents photoshops limitation to apply these color operation adjustment layers onto the inidividual layers and then
//        save out the dds preserving the layers and not flattening it.
//
// Installation:
//	Place this script in your Photoshop Presets\Scripts directory and re-start Photoshop.
//	The script will then appear in your "File->Scripts..." menu items.
//	For more info on Photoshop scripting, see
//		http://partners.Adobe.com/public/developer/photoshop/devcenter.html
//

var gSquare = new UnitValue(256,"px");
var gZero = new UnitValue(0,"px");

function main_body()
{
    if (!app.documents.length > 0) 
    {   
        // stop if no document is opened.
        alert("Sorry, No Current Document");
    } 
    else 
    {
        var strtRulerUnits = app.preferences.rulerUnits;
        if (strtRulerUnits != Units.PIXELS) 
        {
            app.preferences.rulerUnits = Units.PIXELS; // selections are always in pixels
        }

        var origDoc = app.activeDocument;
        var w = origDoc.width;
        var h = origDoc.height;
        var bits = origDoc.bitsPerChannel;
        var layerName = new Array("+Y","-X","+Z","+X","-Z","-Y");
        var orgCorners;  //image cubemap face coords into original Doc
        var orgRot;
        var newCornrner; //image cubemap face coords into new Doc
        var newDoc;
        
        //Determine cube map format
        if (origDoc.artLayers.length >= 6) //copy layered to horizontal cubemap format ----------------------------------------------------------------------------------
        {
            //-----------------Preparation-----------------------------------------------------------------
            //store tile width
            gSquare = w;
            
            //get coordinates to copy tioles from old to new document
            orgCorners = square_corners();
            newCorners =  horizontal_corners();

            orgRot = new Array(0,0,0,0,0,0); //no rotations by default

            //create new document ready for horizoal cube map aligment
            newDoc = app.documents.add(gSquare*4,gSquare*3, origDoc.resolution,"cubeMapHorizontal",NewDocumentMode.RGB,DocumentFill.TRANSPARENT);
            newDoc.bitsPerChannel = bits;
                        
            newDoc.info.source = "Generated by IntelTextureTools from '" + origDoc.name + "'";
            newDoc.info.category = "cubemap";
        
            // duplicate  original document to be safe
            var tempDoc;
            activeDocument = origDoc;
            tempDoc = origDoc.duplicate();
            activeDocument = tempDoc;
        
            //force rgb mode
            if (tempDoc.mode != DocumentMode.RGB) 
            {
                tempDoc.changeMode(ChangeMode.RGB);
            }
            
            //-----------------------face copy------------------------------------------------------
            //copy faces from 'tempDoc' to 'newDoc'. Search for the 6 faces by name
            var i;
            for (i=0; i<6; i++)
            {
                //get layer
                var layerRef = app.activeDocument.artLayers.getByName(layerName[i]);
                
                //if layer exists copy it into new document
                if (layerRef != null)
                {
                    CopyTile(tempDoc, newDoc, orgCorners[i], newCorners[i], orgRot[i], layerRef);
                }
            }
        
           app.activeDocument = newDoc;
           app.activeDocument.mergeVisibleLayers();            

            //----------------------rest layers copy--------------------------------------------------------
            //Now copy over using duplication the rest of the layers from temDoc to newDoc
            var layerNameStr = layerName.toString(); //create a string array for searching
            
            //for all layers in the document
            app.activeDocument = tempDoc;
            
            for (i=activeDocument.artLayers.length-1; i>=0; i--)
            {
                //Ommit the already processed cubemap faces. Search by name if the selected layer is a cubemap face
                if (layerNameStr.indexOf(activeDocument.artLayers[i].name) == -1)
               {
                   //Duplicate form src doc into dst doc
                    activeDocument.artLayers[i].duplicate(newDoc, ElementPlacement.INSIDE);
                }
            }
            
            //------------------------clean up------------------------------------------------------------
            //close it without saving
            tempDoc.close(SaveOptions.DONOTSAVECHANGES);
        }
        else if (w/4 == h/3) //copy horizontal cubemap format to layered ----------------------------------------------------------------------------------
        {
             //-----------------Preparation-----------------------------------------------------------------
            //store tile width
            gSquare = w/4;
            
            //get coordinates to copy tioles from old to new document
            orgCorners = horizontal_corners();
            newCorners = square_corners();

            //create new document ready for horizoal cube map aligment
            newDoc = app.documents.add(gSquare,gSquare, origDoc.resolution,"cubeMapLayered",NewDocumentMode.RGB,DocumentFill.TRANSPARENT);
            newDoc.bitsPerChannel = bits;
            newDoc.info.source = "Generated by IntelTextureTools from '" + origDoc.name + "'";
            newDoc.info.category = "cubemap";

            app.activeDocument = origDoc;
            
            //-----------------------face copy------------------------------------------------------
            //get first layer where the cubemap is assumed and copy tiles into new doc as layers
            var layerRef = app.activeDocument.artLayers[app.activeDocument.artLayers.length-1];
            app.activeDocument.activeLayer = layerRef;
            for (var i=0; i<layerName.length; i++)
            {
                CopyTilesToLayeredFormat(origDoc, newDoc, orgCorners[i], newCorners[i],  layerRef, layerName[i]);
            }
        
            //----------------------rest layers copy--------------------------------------------------------
            app.activeDocument = origDoc;
            for (var i1=app.activeDocument.artLayers.length-2; i1>=0; i1--)
            {
                //Duplicate from src doc into dst doc
                app.activeDocument.artLayers[i1].duplicate(newDoc, ElementPlacement.INSIDE);
            }
        
            app.activeDocument = newDoc;
        }
        else if (w/3 == h/4) //copy vertical cubemap format to layered----------------------------------------------------------------------------------
        {
             //-----------------Preparation-----------------------------------------------------------------
            //store tile width
            gSquare = w/3;
            
            //get coordinates to copy tioles from old to new document
            orgCorners = vertical_corners();
            newCorners = square_corners();

            //create new document ready for horizoal cube map aligment
            newDoc = app.documents.add(gSquare,gSquare, origDoc.resolution,"cubeMapLayered",NewDocumentMode.RGB,DocumentFill.TRANSPARENT);
            newDoc.bitsPerChannel = bits;
            newDoc.info.source = "Generated by IntelTextureTools from '" + origDoc.name + "'";
            newDoc.info.category = "cubemap";

            app.activeDocument = origDoc;
            
            //-----------------------face copy------------------------------------------------------
            //get first layer where the cubemap is assumed and copy tiles into new doc as layers
            var layerRef = app.activeDocument.artLayers[app.activeDocument.artLayers.length-1];
            app.activeDocument.activeLayer = layerRef;
            for (var i=0; i<layerName.length; i++)
            {
                CopyTilesToLayeredFormat(origDoc, newDoc, orgCorners[i], newCorners[i],  layerRef, layerName[i]);
            }
        
            //----------------------rest layers copy--------------------------------------------------------
            app.activeDocument = origDoc;
            for (var i1=app.activeDocument.artLayers.length-2; i1>=0; i1--)
            {
                //Duplicate from src doc into dst doc
                app.activeDocument.artLayers[i1].duplicate(newDoc, ElementPlacement.INSIDE);
            }
        
            app.activeDocument = newDoc;
        }
        else
        {
            alert("Document has not the right format. This script converts Layered cube maps with layer names -X,+X,-Z,+Z,-Y,+Y, to horizontal single layer format. Or horizontal/vertical cube map fomated documents to Layered cube map documents.");
        }
        

    
        if (strtRulerUnits != Units.PIXELS) 
            app.preferences.rulerUnits = strtRulerUnits;
    }
}

main_body();

//The target doc is layed out in a  horizontal cubemap format
//       +Y
//-X  +Z   +X   -Z
//      -Y
function horizontal_corners()
{
    var pyCorner = new Array(gSquare,gZero);
    var pzCorner = step_down(pyCorner,gSquare);
    var nyCorner = step_down(pzCorner,gSquare);
    var nxCorner = step_right(pzCorner,-gSquare);
    var pxCorner = step_right(pzCorner,gSquare);
    var nzCorner = step_right(pxCorner,gSquare);
    return new Array(pyCorner,nxCorner,pzCorner,pxCorner,nzCorner,nyCorner);
}

//The target doc is layed out in a  vertical cubemap format
//       +Y
//-X  +Z   +X  
//      -Y
//      -Z
function vertical_corners()
{
    var pyCorner = new Array(gSquare,gZero);
    var pzCorner = step_down(pyCorner,gSquare);
    var nyCorner = step_down(pzCorner,gSquare);
    var nxCorner = step_right(pzCorner,-gSquare);
    var pxCorner = step_right(pzCorner,gSquare);
    var nzCorner = step_down(nyCorner,gSquare);
    return new Array(pyCorner,nxCorner,pzCorner,pxCorner,nzCorner,nyCorner);
}

//The original doc has one face per layer so the coords are at 0,0
function square_corners()
{
    var origin = new Array(gZero,gZero);
    return new Array(origin,origin,origin,origin,origin,origin);
}

function step_right(corner,size) { return new Array(corner[0]+size,corner[1]); }

function step_down(corner,size) { return new Array(corner[0],corner[1]+size); }


function CopyTilesToLayeredFormat(oDoc, nDoc, oCorner, nCorner,  srcLayer, layerName)
{
    var s = gSquare; 
    
    //src coordinates of the copy rectangle corers
    var oX  = new Array(oCorner[0]+s, oCorner[1]);
    var oY  = new Array(oCorner[0],   oCorner[1]+s);
    var oXY = new Array(oCorner[0]+s, oCorner[1]+s);
    
    //destination coordinates of the copy rectangle corners
    var nX  = new Array(nCorner[0]+s, nCorner[1]);
    var nY  = new Array(nCorner[0],   nCorner[1]+s);
    var nXY = new Array(nCorner[0]+s, nCorner[1]+s);
   
    // store full copy coordinated
    var oBound = new Array(oCorner,oX,oXY,oY);
    var nBound = new Array(nCorner,nX,nXY,nY);
   
    //start form src document and activate layer, select and copy
    activeDocument = oDoc;
    activeDocument.activeLayer = srcLayer;
    oDoc.selection.select(oBound);
    oDoc.selection.copy();
    oDoc.selection.deselect();

    //activate dst document, select and past into selection
    activeDocument = nDoc;
    nDoc.selection.select(nBound);
    var newLayer = nDoc.paste();
    newLayer.name = layerName;
    nDoc.selection.deselect();
    
    //revert to active src documetn
    activeDocument = oDoc;
}

//Copy from srcLayer from oDoc to nDoc. The coordinates for copy selection are also passed.
function CopyTile(oDoc, nDoc, oCorner, nCorner, angle, srcLayer)
{
    var s = gSquare; 
    
    //src coordinates of the copy rectangle corers
    var oX  = new Array(oCorner[0]+s, oCorner[1]);
    var oY  = new Array(oCorner[0],   oCorner[1]+s);
    var oXY = new Array(oCorner[0]+s, oCorner[1]+s);
    
    //destination coordinates of the copy rectangle corners
    var nX  = new Array(nCorner[0]+s, nCorner[1]);
    var nY  = new Array(nCorner[0],   nCorner[1]+s);
    var nXY = new Array(nCorner[0]+s, nCorner[1]+s);
   
    // store full copy coordinated
    var oBound = new Array(oCorner,oX,oXY,oY);
    var nBound = new Array(nCorner,nX,nXY,nY);
   
    //start form src document and activate layer, select and copy
    activeDocument = oDoc;
    activeDocument.activeLayer = srcLayer;
    oDoc.selection.select(oBound);
    oDoc.selection.copy();
    oDoc.selection.deselect();

    //activate dst document, select and past into selection
    activeDocument = nDoc;
    nDoc.selection.select(nBound);
    var newLayer = nDoc.paste();
    
    //rotate dst copy selection if needed
    if (nDoc.bitsPerChannel == BitsPerChannelType.THIRTYTWO) 
    {
        nDoc.selection.rotate(angle);
    } 
    else 
    {
        if (angle != 0) 
        {
            newLayer.rotate(angle);
        }
    }
    nDoc.selection.deselect();
    
    //revert to active src documetn
    activeDocument = oDoc;
}

// eof

