From 8f0e80863c343846fe31872d3d3c01fc39f39287 Mon Sep 17 00:00:00 2001 From: Unknown Date: Tue, 20 Mar 2018 13:32:43 -0400 Subject: [PATCH] Can now retrieve ArtLayers/LayerSets from Document/LayerSets by name. - Added helper methods to ArtLayer to get each boundry. - Fixed a bug in getActiveDoc.jsx --- ps_test.go | 59 ++++++++---- scripts/getActiveDoc.jsx | 4 +- scripts/getLayerSet.jsx | 4 +- structs.go | 198 +++++++++++++++++++++++++++------------ 4 files changed, 184 insertions(+), 81 deletions(-) diff --git a/ps_test.go b/ps_test.go index 55808f3..f5c579a 100644 --- a/ps_test.go +++ b/ps_test.go @@ -2,12 +2,11 @@ package ps import ( "fmt" - // "os" - // "path/filepath" + "os" + "path/filepath" "testing" ) -/* func TestPkgPath(t *testing.T) { out := filepath.Join(os.Getenv("GOPATH"), "src", "github.com", "sbrow", "ps") if filepath.Join(pkgpath) != out { @@ -23,9 +22,9 @@ func TestStart(t *testing.T) { } func TestOpen(t *testing.T) { - if testing.Short() { - t.Skip("Skipping \"TestOpen\"") - } + // if testing.Short() { + // t.Skip("Skipping \"TestOpen\"") + // } err := Open("F:\\GitLab\\dreamkeepers-psd\\Template009.1.psd") if err != nil { t.Fatal(err) @@ -82,6 +81,9 @@ func TestWait(t *testing.T) { } func TestDoAction_Crop(t *testing.T) { + if testing.Short() { + t.Skip("Skipping \"TestDoAction_Crop\"") + } err := Open("F:\\GitLab\\dreamkeepers-psd\\Template009.1.psd") if err != nil { t.Fatal(err) @@ -93,6 +95,9 @@ func TestDoAction_Crop(t *testing.T) { } func TestDoAction_Undo(t *testing.T) { + if testing.Short() { + t.Skip("Skipping \"TestDoAction_Undo\"") + } err := DoAction("DK", "Undo") if err != nil { t.Fatal(err) @@ -104,8 +109,10 @@ func TestSaveAs(t *testing.T) { if err != nil { t.Fatal(err) } + os.Remove("F:\\TEMP\\test.png") } +/* func TestLayerSet(t *testing.T) { _, err := NewLayerSet("Areas/TitleBackground/") if err != nil { @@ -120,7 +127,6 @@ func TestLayer(t *testing.T) { } } - func TestMove(t *testing.T) { lyr, err := Layer("Group 1/Layer 1") if err != nil { @@ -137,27 +143,27 @@ func TestActiveDocument(t *testing.T) { if err != nil { t.Fatal(err) } - if d != d.ArtLayers[0].Parent() { + if d != d.artLayers[0].Parent() { fmt.Println(d) - fmt.Println(d.ArtLayers[0].Parent()) + fmt.Println(d.artLayers[0].Parent()) t.Fatal("ArtLayers do not have doc as parent.") } - if d != d.LayerSets[0].Parent() { + if d != d.layerSets[0].Parent() { fmt.Println(d) - fmt.Println(d.LayerSets[0].Parent()) + fmt.Println(d.layerSets[0].Parent()) t.Fatal("LayerSets do not have doc as parent.") } - if d.LayerSets[0] != d.LayerSets[0].ArtLayers[0].Parent() { - fmt.Println(d.LayerSets[0]) - fmt.Println(d.LayerSets[0].ArtLayers[0]) - fmt.Println(d.LayerSets[0].ArtLayers[0].Parent()) + if d.layerSets[0] != d.layerSets[0].artLayers[0].Parent() { + fmt.Println(d.layerSets[0]) + fmt.Println(d.layerSets[0].artLayers[0]) + fmt.Println(d.layerSets[0].artLayers[0].Parent()) t.Fatal("Layerset's ArtLayers do not have correct parents") } } func TestApplyDataset(t *testing.T) { out := []byte("done!\r\n") - ret, err := ApplyDataset("Anger") + ret, err := ApplyDataset(" Anger") if err != nil { t.Fatal(err) } @@ -165,11 +171,28 @@ func TestApplyDataset(t *testing.T) { fail := fmt.Sprintf("TestJS failed.\ngot:\t\"%s\"\nwant:\t\"%s\"", ret, out) t.Fatal(fail) } - err = Quit(2) +} + +func TestDocumentLayerSet(t *testing.T) { + d, err := ActiveDocument() if err != nil { t.Fatal(err) } + set := d.LayerSet("Text") + fmt.Println(set) + for _, lyr := range set.ArtLayers() { + fmt.Println(lyr.name) + } + lyr := set.ArtLayer("id") + fmt.Println(lyr) + set = d.LayerSet("Indicators").LayerSet("Life") + fmt.Println(set) + for _, lyr := range set.ArtLayers() { + fmt.Println(lyr.name) + } } + +/* func TestDoJs_HideLayer(t *testing.T) { err := Open("F:\\GitLab\\dreamkeepers-psd\\Template009.1.psd") if err != nil { @@ -181,7 +204,7 @@ func TestDoJs_HideLayer(t *testing.T) { t.Fatal(err) } } - +*/ func BenchmarkDoc_Go(b *testing.B) { for i := 0; i < b.N; i++ { _, err := ActiveDocument() diff --git a/scripts/getActiveDoc.jsx b/scripts/getActiveDoc.jsx index b473248..eb14b4e 100644 --- a/scripts/getActiveDoc.jsx +++ b/scripts/getActiveDoc.jsx @@ -1,8 +1,8 @@ #include lib.js var stdout = newFile(arguments[0]); var doc = app.activeDocument; -stdout.writeln(('{"Name": "' + doc.name +'", "Height":' +doc.height + - ', "Width":' + doc.width + ', "ArtLayers": [').replace(/ px/g, "")); +stdout.writeln(('{"Name": "'+doc.name+'", "Height":'+doc.height+ + ', "Width":'+doc.width+', "ArtLayers": [').replace(/ px/g, "")); function layers(lyrs) { if (typeof lyrs === 'undefined') return; diff --git a/scripts/getLayerSet.jsx b/scripts/getLayerSet.jsx index eaed0b5..c0eae16 100644 --- a/scripts/getLayerSet.jsx +++ b/scripts/getLayerSet.jsx @@ -13,8 +13,8 @@ for (var i = 0; i < set.artLayers.length; i++) { } stdout.write('], "LayerSets": [') for (var i = 0; i < set.layerSets.length; i++) { - var set = set.layerSets[i]; - stdout.write('{"Name": "'+ set.name +'"}'); + var s = set.layerSets[i]; + stdout.write('{"Name": "'+ s.name +'"}'); if (i < set.layerSets.length - 1) stdout.writeln(","); } diff --git a/structs.go b/structs.go index c6c0e54..94e20e2 100644 --- a/structs.go +++ b/structs.go @@ -2,6 +2,7 @@ package ps import ( "encoding/json" + "flag" "fmt" "log" "strings" @@ -13,13 +14,21 @@ type Group interface { Parent() Group SetParent(Group) Path() string - GetArtLayers() []*ArtLayer - GetLayerSets() []*LayerSet + ArtLayers() []*ArtLayer + LayerSets() []*LayerSet } // Document represents a Photoshop document (PSD file). type Document struct { name string + height int + width int + artLayers []*ArtLayer + layerSets []*LayerSet +} + +type DocumentJSON struct { + Name string Height int Width int ArtLayers []*ArtLayer @@ -32,30 +41,42 @@ func (d *Document) UnmarshalJSON(b []byte) error { return err } d.name = tmp.Name - d.Height = tmp.Height - d.Width = tmp.Width - d.ArtLayers = tmp.ArtLayers - d.LayerSets = tmp.LayerSets + d.height = tmp.Height + d.width = tmp.Width + d.artLayers = tmp.ArtLayers + d.layerSets = tmp.LayerSets return nil } -type DocumentJSON struct { - Name string - Height int - Width int - ArtLayers []*ArtLayer - LayerSets []*LayerSet -} - +// Name returns the document's title. +// This fufills the Group interface. func (d *Document) Name() string { return d.name } -func (d *Document) GetArtLayers() []*ArtLayer { - return d.ArtLayers + +// The height of the document, in pixels. +func (d *Document) Height() int { + return d.height } -func (d *Document) GetLayerSets() []*LayerSet { - return d.LayerSets +func (d *Document) ArtLayers() []*ArtLayer { + return d.artLayers +} + +// LayerSets returns all the document's top level LayerSets. +func (d *Document) LayerSets() []*LayerSet { + return d.layerSets +} + +// LayerSet returns the first top level LayerSet matching +// the given name. +func (d *Document) LayerSet(name string) *LayerSet { + for _, set := range d.layerSets { + if set.name == name { + return set + } + } + return nil } func (d *Document) Parent() Group { @@ -68,29 +89,31 @@ func (d *Document) Path() string { } func ActiveDocument() (*Document, error) { + log.Println("Loading ActiveDoucment/") byt, err := DoJs("getActiveDoc.jsx") var d *Document err = json.Unmarshal(byt, &d) - for _, lyr := range d.ArtLayers { + for _, lyr := range d.artLayers { lyr.SetParent(d) } - for i, set := range d.LayerSets { - s, err := NewLayerSet(set.Path() + "/") + for i, set := range d.layerSets { + s, err := NewLayerSet(set.Path()+"/", d) if err != nil { log.Fatal(err) } - d.LayerSets[i] = s - s.SetParent(d) + d.layerSets[i] = s + // s.SetParent(d) } return d, err } +// ArtLayer represents an Art Layer in a photoshop document. type ArtLayer struct { name string // TextItem string - Bounds [2][2]int - parent Group - Visiblity bool + bounds [2][2]int + parent Group + visible bool } type ArtLayerJSON struct { @@ -106,12 +129,40 @@ func (a *ArtLayer) UnmarshalJSON(b []byte) error { return err } a.name = tmp.Name - a.Bounds = tmp.Bounds + a.bounds = tmp.Bounds a.parent = tmp.Parent - a.Visiblity = tmp.Visible + a.visible = tmp.Visible return nil } +func (a *ArtLayer) Name() string { + return a.name +} + +func (a *ArtLayer) Bounds() [2][2]int { + return a.bounds +} + +// X1 returns the layer's leftmost x value. +func (a *ArtLayer) X1() int { + return a.bounds[0][0] +} + +// X2 returns the layer's rightmost x value. +func (a *ArtLayer) X2() int { + return a.bounds[1][0] +} + +// Y1 returns the layer's topmost Y value. +func (a *ArtLayer) Y1() int { + return a.bounds[0][1] +} + +// Y2 returns the layer's bottommost y value. +func (a *ArtLayer) Y2() int { + return a.bounds[1][1] +} + func (a *ArtLayer) SetParent(c Group) { a.parent = c } @@ -137,37 +188,41 @@ func Layer(path string) (ArtLayer, error) { } // SetVisible makes the layer visible. -func (a *ArtLayer) SetVisible() { - js := JSLayer(a.Path()) + fmt.Sprintf(".visible=%s;", true) +func (a *ArtLayer) SetVisible(b bool) { + js := fmt.Sprintf("%s.visible=%v;", + strings.TrimRight(JSLayer(a.Path()), ";"), b) + log.Printf("Setting %s.Visible to %v\n", a.name, b) DoJs("compilejs.jsx", js) } -// Position moves the layer to pos(x, y), measuring from -// the top or bottom left-hand corner. +// Visible returns whether or not the layer is currently hidden. +func (a *ArtLayer) Visible() bool { + return a.visible +} + +// SetPos snaps the given layer boundry to the given point. +// Valid options for bound are: TL, TR, BL, BR // TODO: Improve -func (a *ArtLayer) Position(x, y int, align string) { +func (a *ArtLayer) SetPos(x, y int, bound string) { var lyrX, lyrY int - lyrX = a.Bounds[0][0] - if align != "bottom" { - lyrY = a.Bounds[0][1] - } else { - lyrY = a.Bounds[1][1] + lyrX = a.X1() + if bound != "TL" { + lyrY = a.Y2() + } else { // "BL" + lyrY = a.Y1() } byt, err := DoJs("moveLayer.jsx", JSLayer(a.Path()), fmt.Sprint(x-lyrX), fmt.Sprint(y-lyrY)) if err != nil { panic(err) } - fmt.Println("byte", string(byt)) - fmt.Println("bounds", a.Bounds) json.Unmarshal(byt, &a) - fmt.Println("after", a.Bounds) } type LayerSet struct { name string parent Group - ArtLayers []*ArtLayer - LayerSets []*LayerSet + artLayers []*ArtLayer + layerSets []*LayerSet } type LayerSetJSON struct { @@ -184,8 +239,8 @@ func (l *LayerSet) UnmarshalJSON(b []byte) error { } l.name = tmp.Name l.parent = tmp.Parent - l.ArtLayers = tmp.ArtLayers - l.LayerSets = tmp.LayerSets + l.artLayers = tmp.ArtLayers + l.layerSets = tmp.LayerSets return nil } @@ -193,12 +248,34 @@ func (l *LayerSet) Name() string { return l.name } -func (l *LayerSet) GetArtLayers() []*ArtLayer { - return l.ArtLayers +func (l *LayerSet) ArtLayers() []*ArtLayer { + return l.artLayers } -func (l *LayerSet) GetLayerSets() []*LayerSet { - return l.LayerSets +// ArtLayer returns the first top level ArtLayer matching +// the given name. +func (l *LayerSet) ArtLayer(name string) *ArtLayer { + for _, lyr := range l.artLayers { + if lyr.name == name { + return lyr + } + } + return nil +} + +func (l *LayerSet) LayerSets() []*LayerSet { + return l.layerSets +} + +// LayerSet returns the first top level LayerSet matching +// the given name. +func (l *LayerSet) LayerSet(name string) *LayerSet { + for _, set := range l.layerSets { + if set.name == name { + return set + } + } + return nil } func (l *LayerSet) SetParent(c Group) { @@ -216,32 +293,35 @@ func (l *LayerSet) Path() string { return fmt.Sprintf("%s%s/", l.parent.Path(), l.name) } -func NewLayerSet(path string) (*LayerSet, error) { +func NewLayerSet(path string, g Group) (*LayerSet, error) { byt, err := DoJs("getLayerSet.jsx", JSLayer(path)) - // fmt.Println(string(byt)) var out *LayerSet err = json.Unmarshal(byt, &out) + if flag.Lookup("test.v") != nil { + // log.Println(string(byt)) + } + out.SetParent(g) + log.Printf("Loading ActiveDocument/%s\n", out.Path()) if err != nil { return &LayerSet{}, err } - for _, lyr := range out.ArtLayers { + for _, lyr := range out.artLayers { lyr.SetParent(out) } - for i, set := range out.LayerSets { - s, err := NewLayerSet(fmt.Sprintf("%s%s/", path, set.Name())) + for i, set := range out.layerSets { + // log.Println("\t", set.name) + s, err := NewLayerSet(fmt.Sprintf("%s%s/", path, set.Name()), out) if err != nil { log.Fatal(err) } - out.LayerSets[i] = s + out.layerSets[i] = s s.SetParent(out) } return out, err } // SetVisible makes the LayerSet visible. -func (s *LayerSet) SetVisible(b bool) { - fmt.Println(s.Path()) - fmt.Println(JSLayer(s.Path())) - js := JSLayer(strings.TrimRight(s.Path(), ";") + fmt.Sprintf(".visible=%v;", b)) +func (l *LayerSet) SetVisible(b bool) { + js := fmt.Sprintf("%s%v", JSLayer(strings.TrimRight(l.Path(), ";")), b) DoJs("compilejs.jsx", js) }