Various updates

* Layersets now have bounds.
* TextItem is now writeable
* Added flush function to writing, for faster debugging.
This commit is contained in:
Unknown
2018-04-18 23:58:38 -04:00
parent e90c491450
commit c54b196f6a
6 changed files with 125 additions and 21 deletions

8
ps.go
View File

@@ -73,7 +73,7 @@ func SaveAs(path string) error {
func DoJs(path string, args ...string) (out []byte, err error) { func DoJs(path string, args ...string) (out []byte, err error) {
// Temp file for js to output to. // Temp file for js to output to.
outpath := filepath.Join(os.Getenv("TEMP"), "js_out.txt") outpath := filepath.Join(os.Getenv("TEMP"), "js_out.txt")
defer os.Remove(outpath) // defer os.Remove(outpath)
if !strings.HasSuffix(path, ".jsx") { if !strings.HasSuffix(path, ".jsx") {
path += ".jsx" path += ".jsx"
} }
@@ -160,11 +160,15 @@ func ApplyDataset(name string) ([]byte, error) {
// JSLayer "compiles" Javascript code to get an ArtLayer with the given path. // JSLayer "compiles" Javascript code to get an ArtLayer with the given path.
// The output always ends with a semicolon, so if you want to access a specific // The output always ends with a semicolon, so if you want to access a specific
// property of the layer, you'll have to trim the output before concatenating // property of the layer, you'll have to trim the output before concatenating
func JSLayer(path string) string { func JSLayer(path string, art ...bool) string {
path = strings.TrimLeft(path, "/") path = strings.TrimLeft(path, "/")
pth := strings.Split(path, "/") pth := strings.Split(path, "/")
js := "app.activeDocument" js := "app.activeDocument"
last := len(pth) - 1 last := len(pth) - 1
if len(art) > 0 {
pth = pth[:len(pth)-1]
last--
}
if last > 0 { if last > 0 {
for i := 0; i < last; i++ { for i := 0; i < last; i++ {
js += fmt.Sprintf(".layerSets.getByName('%s')", pth[i]) js += fmt.Sprintf(".layerSets.getByName('%s')", pth[i])

View File

@@ -1,8 +1,8 @@
#include lib.js #include lib.js
var stdout = newFile(arguments[0]); var stdout = newFile(arguments[0]);
var set = eval(arguments[1]); var set = eval(arguments[1]);
stdout.writeln('{"Name": "'+set.name+'", "ArtLayers":['); stdout.writeln('{"Name": "'+set.name+'", "ArtLayers":[');
stdout.flush();
for (var i = 0; i < set.artLayers.length; i++) { for (var i = 0; i < set.artLayers.length; i++) {
var lyr = set.artLayers[i]; var lyr = set.artLayers[i];
stdout.write(('{"Name":"' + lyr.name + '", "Bounds": [[' + lyr.bounds[0] + ',' + stdout.write(('{"Name":"' + lyr.name + '", "Bounds": [[' + lyr.bounds[0] + ',' +
@@ -15,13 +15,25 @@ for (var i = 0; i < set.artLayers.length; i++) {
stdout.write("}") stdout.write("}")
if (i != set.artLayers.length - 1) if (i != set.artLayers.length - 1)
stdout.writeln(","); stdout.writeln(",");
stdout.flush();
} }
stdout.write('], "LayerSets": [') stdout.writeln("]");
stdout.write(', "LayerSets": [')
for (var i = 0; i < set.layerSets.length; i++) { for (var i = 0; i < set.layerSets.length; i++) {
var s = set.layerSets[i]; var s = set.layerSets[i];
stdout.write('{"Name":"' + s.name + '", "Visible": ' + s.visible + '}'); stdout.write('{"Name":"' + s.name + '", "Visible": ' + s.visible + '}');
if (i < set.layerSets.length - 1) if (i < set.layerSets.length - 1)
stdout.writeln(","); stdout.writeln(",");
stdout.flush()
} }
stdout.write("]}") stdout.writeln(']')
// app.activeDocument.activeLayer=set;
// set.merge();
// set=eval(arguments[2]);
stdout.write(', "Bounds": [[],[]]');
// stdout.write((', "Bounds": [[' + set.bounds[0] + ',' +
// set.bounds[1] + '],[' + set.bounds[2] + ',' +
// set.bounds[3] + ']]').replace(/ px/g, ""));
stdout.write("}");
// Undo();
stdout.close(); stdout.close();

View File

@@ -1,13 +1,21 @@
// Opens and returns a file, overwriting new data. // Opens and returns a file, overwriting new data.
function newFile(path) { function newFile(path) {
var f = File(path) var f = File(path)
if(f.exists)
f.remove()
f.encoding = "UTF8" f.encoding = "UTF8"
f.open("e", "TEXT", "????") f.open("w")
return f return f
} }
File.prototype.flush = function() {
this.close()
this.open("a")
};
function flush(file) {
file.close()
file.open("a")
}
// Prints an error message. // Prints an error message.
function err(e) { function err(e) {
return 'ERROR: ' + e.message + ' at ' + e.fileName + ':' + e.line; return 'ERROR: ' + e.message + ' at ' + e.fileName + ':' + e.line;
@@ -19,6 +27,14 @@ function bounds(lyr) {
lyr.bounds[3] + ']]').replace(/ px/g, ""); lyr.bounds[3] + ']]').replace(/ px/g, "");
} }
function Undo() {
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID( "HstS" ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Prvs" ));
desc.putReference(charIDToTypeID( "null" ), ref);
executeAction( charIDToTypeID( "slct" ), desc, DialogModes.NO );
}
/** /**
* The setFormatting function sets the font, font style, point size, and RGB color of specified * The setFormatting function sets the font, font style, point size, and RGB color of specified
* characters in a Photoshop text layer. * characters in a Photoshop text layer.

View File

@@ -2,5 +2,12 @@
var stdout = newFile(arguments[0]); var stdout = newFile(arguments[0]);
var lyr = eval(arguments[1]); var lyr = eval(arguments[1]);
lyr.translate((Number)(arguments[2]), (Number)(arguments[3])); lyr.translate((Number)(arguments[2]), (Number)(arguments[3]));
if (lyr.typename == 'LayerSet') {
alert(lyr.name + "\n" + lyr.typename)
alert(lyr)
// lyr.merge()
// lyr=eval(arguments[4])
// Undo();
}
stdout.writeln('{' + bounds(lyr) + '}') stdout.writeln('{' + bounds(lyr) + '}')
stdout.close(); stdout.close();

View File

@@ -1,12 +1,11 @@
#include lib.js #include lib.js
var saveFile = File(arguments[0]);
if(saveFile.exists)
saveFile.remove();
saveFile.encoding = "UTF8"; // var saveFile = File(arguments[0]);
saveFile.open("e", "TEXT", "????"); var arg = 'app.activeDocument.layerSets.getByName("Indicators").layerSets.getByName("Deck")';
for (var i = 0; i < arguments.length; i++) { alert(arg.replace(/[^(?:layerSets)]*(layerSets)/, "artLayers"))
saveFile.writeln(arguments[i]) // var doc=app.activeDocument
} // doc.layerSets.getByName("ResolveGem").merge();
setFormatting(0,6, "Arial", "Bold"); // alert(doc.artLayers.getByName("ResolveGem").bounds);
saveFile.close(); // doc.activeHistoryState=doc.historyStates[doc.historyStates.length-2]
// setFormatting(0,6, "Arial", "Bold");
// saveFile.close();

View File

@@ -168,6 +168,7 @@ func (d *Document) Dump() {
} }
// ArtLayer reflects certain values from an Art Layer in a Photoshop document. // ArtLayer reflects certain values from an Art Layer in a Photoshop document.
// TODO: Make TextLayer a subclass of ArtLayer
type ArtLayer struct { type ArtLayer struct {
name string // The layer's name. name string // The layer's name.
Text *string // The contents of a text layer. Text *string // The contents of a text layer.
@@ -197,6 +198,16 @@ type ArtLayerJSON struct {
Text *string Text *string
} }
func (a *ArtLayer) SetText(txt string) {
lyr := strings.TrimRight(JSLayer(a.Path()), ";")
js := fmt.Sprintf("%s.textItem.contents='%s';", lyr, txt)
_, err := DoJs("compilejs.jsx", js)
if err != nil {
a.Text = &txt
}
a.Refresh()
}
// MarshalJSON fulfills the json.Marshaler interface, allowing the ArtLayer to be // MarshalJSON fulfills the json.Marshaler interface, allowing the ArtLayer to be
// saved to disk in JSON format. // saved to disk in JSON format.
func (a *ArtLayer) MarshalJSON() ([]byte, error) { func (a *ArtLayer) MarshalJSON() ([]byte, error) {
@@ -444,6 +455,7 @@ func (a *ArtLayer) Refresh() error {
type LayerSet struct { type LayerSet struct {
name string name string
bounds [2][2]int
parent Group parent Group
current bool // Whether we've checked this layer since we loaded from disk. current bool // Whether we've checked this layer since we loaded from disk.
visible bool visible bool
@@ -453,6 +465,7 @@ type LayerSet struct {
type LayerSetJSON struct { type LayerSetJSON struct {
Name string Name string
Bounds [2][2]int
ArtLayers []*ArtLayer ArtLayers []*ArtLayer
LayerSets []*LayerSet LayerSets []*LayerSet
} }
@@ -460,6 +473,7 @@ type LayerSetJSON struct {
func (l *LayerSet) MarshalJSON() ([]byte, error) { func (l *LayerSet) MarshalJSON() ([]byte, error) {
return json.Marshal(&LayerSetJSON{ return json.Marshal(&LayerSetJSON{
Name: l.name, Name: l.name,
Bounds: l.bounds,
ArtLayers: l.artLayers, ArtLayers: l.artLayers,
LayerSets: l.layerSets, LayerSets: l.layerSets,
}) })
@@ -471,6 +485,7 @@ func (l *LayerSet) UnmarshalJSON(b []byte) error {
return err return err
} }
l.name = tmp.Name l.name = tmp.Name
l.bounds = tmp.Bounds
l.artLayers = tmp.ArtLayers l.artLayers = tmp.ArtLayers
for _, lyr := range l.artLayers { for _, lyr := range l.artLayers {
lyr.SetParent(l) lyr.SetParent(l)
@@ -544,6 +559,11 @@ func (l *LayerSet) LayerSet(name string) *LayerSet {
return nil return nil
} }
// Bounds returns the furthest corners of the LayerSet.
func (l *LayerSet) Bounds() [2][2]int {
return l.bounds
}
func (l *LayerSet) SetParent(c Group) { func (l *LayerSet) SetParent(c Group) {
l.parent = c l.parent = c
} }
@@ -562,9 +582,13 @@ func (l *LayerSet) Path() string {
func NewLayerSet(path string, g Group) (*LayerSet, error) { func NewLayerSet(path string, g Group) (*LayerSet, error) {
path = strings.Replace(path, "//", "/", -1) path = strings.Replace(path, "//", "/", -1)
byt, err := DoJs("getLayerSet.jsx", JSLayer(path)) byt, err := DoJs("getLayerSet.jsx", JSLayer(path))
if err != nil {
log.Panic(err)
}
var out *LayerSet var out *LayerSet
err = json.Unmarshal(byt, &out) err = json.Unmarshal(byt, &out)
if err != nil { if err != nil {
log.Println(JSLayer(path))
log.Println(string(byt)) log.Println(string(byt))
log.Panic(err) log.Panic(err)
} }
@@ -597,12 +621,53 @@ func (l *LayerSet) SetVisible(b bool) {
DoJs("compilejs.jsx", js) DoJs("compilejs.jsx", js)
} }
// SetPos snaps the given layerset boundry to the given point.
// Valid options for bound are: "TL", "TR", "BL", "BR"
//
// TODO: Test TR and BR
func (l *LayerSet) SetPos(x, y int, bound string) {
// if !l.visible || (x == 0 && y == 0) {
// return
// }
var lyrX, lyrY int
switch bound[:1] {
case "B":
lyrY = l.bounds[1][1]
case "T":
fallthrough
default:
lyrY = l.bounds[0][1]
}
switch bound[1:] {
case "R":
lyrX = l.bounds[1][0]
case "L":
fallthrough
default:
lyrX = l.bounds[0][0]
}
fmt.Println(JSLayer(l.Path()), fmt.Sprint(x-lyrX), fmt.Sprint(y-lyrY))
byt, err := DoJs("moveLayer.jsx", JSLayer(l.Path()), fmt.Sprint(x-lyrX),
fmt.Sprint(y-lyrY), JSLayer(l.Path(), true))
if err != nil {
fmt.Println("byte:", string(byt))
panic(err)
}
var lyr LayerSet
err = json.Unmarshal(byt, &lyr)
if err != nil {
fmt.Println("byte:", string(byt))
log.Panic(err)
}
l.bounds = lyr.bounds
}
func (l *LayerSet) Refresh() { func (l *LayerSet) Refresh() {
var tmp *LayerSet var tmp *LayerSet
byt, err := DoJs("getLayerSet.jsx", JSLayer(l.Path())) byt, err := DoJs("getLayerSet.jsx", JSLayer(l.Path()), JSLayer(l.Path(), true))
err = json.Unmarshal(byt, &tmp) err = json.Unmarshal(byt, &tmp)
if err != nil { if err != nil {
log.Println("Error in LayerSet.Refresh()", string(byt)) log.Println("Error in LayerSet.Refresh() \"", string(byt), "\"", "for", l.Path())
log.Panic(err) log.Panic(err)
} }
tmp.SetParent(l.Parent()) tmp.SetParent(l.Parent())
@@ -617,6 +682,7 @@ func (l *LayerSet) Refresh() {
set.Refresh() set.Refresh()
} }
l.name = tmp.name l.name = tmp.name
l.bounds = tmp.bounds
l.visible = tmp.visible l.visible = tmp.visible
l.current = true l.current = true
} }