mirror of
https://github.com/sbrow/ps.git
synced 2025-12-29 18:47:38 -05:00
Merge branch 'release/v1.0'
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
data/
|
||||||
44
Variables.go
Normal file
44
Variables.go
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package ps
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Colors map[string]Color = map[string]Color{
|
||||||
|
"Black": &RGB{0, 0, 0},
|
||||||
|
"Gray": &RGB{128, 128, 128},
|
||||||
|
"White": &RGB{255, 255, 255},
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModeEnum determines how aggressively the package will attempt to sync with Photoshop.
|
||||||
|
type ModeEnum int
|
||||||
|
|
||||||
|
// Holds the current mode.
|
||||||
|
var Mode ModeEnum
|
||||||
|
|
||||||
|
// Fast mode never checks layers before returning.
|
||||||
|
const Fast ModeEnum = 2
|
||||||
|
|
||||||
|
// Normal Mode Always checks to see if layers are up to date
|
||||||
|
// before returning them.
|
||||||
|
const Normal ModeEnum = 0
|
||||||
|
|
||||||
|
// Safe Mode Always loads the document from scratch. (Very Slow)
|
||||||
|
const Safe ModeEnum = 1
|
||||||
|
|
||||||
|
// PSSaveOptions is an enum for options when closing a document.
|
||||||
|
type PSSaveOptions int
|
||||||
|
|
||||||
|
func (p *PSSaveOptions) String() string {
|
||||||
|
return fmt.Sprint("", *p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSSaveChanges saves changes before closing documents.
|
||||||
|
const PSSaveChanges PSSaveOptions = 1
|
||||||
|
|
||||||
|
// PSDoNotSaveChanges closes documents without saving.
|
||||||
|
const PSDoNotSaveChanges PSSaveOptions = 2
|
||||||
|
|
||||||
|
// PSPromptToSaveChanges prompts the user whether to save each
|
||||||
|
// document before closing it.
|
||||||
|
const PSPromptToSaveChanges PSSaveOptions = 3
|
||||||
71
colors.go
Normal file
71
colors.go
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
package ps
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
// "fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Color is an interface for color objects, allowing colors to be
|
||||||
|
// used in various formats.
|
||||||
|
//
|
||||||
|
// RGB is the default format for everything.
|
||||||
|
type Color interface {
|
||||||
|
RGB() [3]int // The color in RGB format.
|
||||||
|
Hex() []uint8 // The color in hexadecimal format.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare determines which of two colors is "brighter".
|
||||||
|
func Compare(a, b Color) Color {
|
||||||
|
A := a.RGB()
|
||||||
|
B := b.RGB()
|
||||||
|
Aavg := (A[0] + A[1] + A[2]) / 3
|
||||||
|
Bavg := (B[0] + B[1] + B[2]) / 3
|
||||||
|
if Aavg > Bavg {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// RGB is a color in RGB format. It fulfills the Color interface.
|
||||||
|
type RGB struct {
|
||||||
|
Red int
|
||||||
|
Green int
|
||||||
|
Blue int
|
||||||
|
}
|
||||||
|
|
||||||
|
// RGB returns the color in RGB format.
|
||||||
|
func (r RGB) RGB() [3]int {
|
||||||
|
return [3]int{r.Red, r.Green, r.Blue}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Implement RGB.Hex()
|
||||||
|
func (r RGB) Hex() []uint8 {
|
||||||
|
return make([]uint8, 6)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hex is a color in hexadecimal format. It fulfills the Color interface.
|
||||||
|
type Hex []uint8
|
||||||
|
|
||||||
|
func (h Hex) RGB() [3]int {
|
||||||
|
src := []byte(h)
|
||||||
|
dst := make([]byte, hex.DecodedLen(len(src)))
|
||||||
|
_, err := hex.Decode(dst, src)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return [3]int{int(dst[0]), int(dst[1]), int(dst[2])}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h Hex) Hex() []uint8 {
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stroke represents a layer stroke effect.
|
||||||
|
type Stroke struct {
|
||||||
|
Size float32
|
||||||
|
Color
|
||||||
|
}
|
||||||
|
|
||||||
|
// func (s *Stroke) String() string {
|
||||||
|
// return fmt.Sprintf("%vpt %v", s.Size, s.Color.RGB())
|
||||||
|
// }
|
||||||
157
ps.go
157
ps.go
@@ -1,70 +1,181 @@
|
|||||||
|
// Package ps is a rudimentary API between Adobe Photoshop CS5 and Golang.
|
||||||
|
//
|
||||||
|
// Most of the interaction between the two is implemented via
|
||||||
|
// Javascript and/or VBS/Applescript.
|
||||||
|
//
|
||||||
|
// Currently only works with CS5 on Windows.
|
||||||
package ps
|
package ps
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
// "log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
var Cmd string
|
||||||
Cmd = "cscript.exe"
|
var Opts string
|
||||||
Opts = "/nologo"
|
var pkgpath string
|
||||||
)
|
|
||||||
|
|
||||||
var PKGPATH = path.Join(os.Getenv("GOPATH"), "src", "github.com", "sbrow", "ps")
|
func init() {
|
||||||
|
_, file, _, _ := runtime.Caller(0)
|
||||||
|
pkgpath = filepath.Dir(file)
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "windows":
|
||||||
|
Cmd = "cscript.exe"
|
||||||
|
Opts = "/nologo"
|
||||||
|
case "darwin":
|
||||||
|
Cmd = "osacript"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start opens Photoshop.
|
||||||
func Start() error {
|
func Start() error {
|
||||||
_, err := run("start")
|
_, err := run("start")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func Open(path string) ([]byte, error) {
|
// Close closes the active document in Photoshop.
|
||||||
return run("open", path)
|
func Close(save PSSaveOptions) error {
|
||||||
}
|
_, err := run("close", save.String())
|
||||||
|
|
||||||
func Close() error {
|
|
||||||
_, err := run("close")
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func Quit() ([]byte, error) {
|
// Open opens a Photoshop document with the specified path.
|
||||||
return run("quit")
|
// If Photoshop is not currently running, it is started before
|
||||||
|
// opening the document
|
||||||
|
func Open(path string) error {
|
||||||
|
_, err := run("open", path)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func Js(args ...string) ([]byte, error) {
|
// Quit exits Photoshop with the given saving option.
|
||||||
return run("dojs", args...)
|
func Quit(save PSSaveOptions) error {
|
||||||
|
_, err := run("quit", save.String())
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SaveAs saves the Photoshop document to the given location.
|
||||||
|
func SaveAs(path string) error {
|
||||||
|
_, err := run("save", path)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DoJs runs a Photoshop Javascript script file (.jsx) from the specified location.
|
||||||
|
// It can't directly return output, so instead the scripts write their output to
|
||||||
|
// a temporary file, whose contents is then read and returned.
|
||||||
|
func DoJs(path string, args ...string) (out []byte, err error) {
|
||||||
|
// Temp file for js to output to.
|
||||||
|
outpath := filepath.Join(os.Getenv("TEMP"), "js_out.txt")
|
||||||
|
// defer os.Remove(outpath)
|
||||||
|
if !strings.HasSuffix(path, ".jsx") {
|
||||||
|
path += ".jsx"
|
||||||
|
}
|
||||||
|
|
||||||
|
args = append([]string{outpath}, args...)
|
||||||
|
|
||||||
|
// If passed a script by name, assume it's in the default folder.
|
||||||
|
if filepath.Dir(path) == "." {
|
||||||
|
path = filepath.Join(pkgpath, "scripts", path)
|
||||||
|
}
|
||||||
|
|
||||||
|
args = append([]string{path}, args...)
|
||||||
|
cmd, err := run("dojs", args...)
|
||||||
|
if err == nil {
|
||||||
|
file, err := ioutil.ReadFile(outpath)
|
||||||
|
if err == nil {
|
||||||
|
cmd = append(cmd, file...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cmd, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait prints a message to the console and halts operation until the user
|
||||||
|
// signals that they are ready (by pushing enter).
|
||||||
|
//
|
||||||
|
// Useful for when you need to do something by hand in the middle of an
|
||||||
|
// otherwise automated process.
|
||||||
func Wait(msg string) {
|
func Wait(msg string) {
|
||||||
fmt.Print(msg)
|
fmt.Print(msg)
|
||||||
var input string
|
var input string
|
||||||
fmt.Scanln(&input)
|
fmt.Scanln(&input)
|
||||||
|
fmt.Println()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// run handles running the script files, returning output, and displaying errors.
|
||||||
func run(name string, args ...string) ([]byte, error) {
|
func run(name string, args ...string) ([]byte, error) {
|
||||||
var ext string
|
var ext string
|
||||||
var dir string
|
|
||||||
var out bytes.Buffer
|
var out bytes.Buffer
|
||||||
var stderr bytes.Buffer
|
var errs bytes.Buffer
|
||||||
|
|
||||||
switch runtime.GOOS {
|
switch runtime.GOOS {
|
||||||
case "windows":
|
case "windows":
|
||||||
ext = ".vbs"
|
ext = ".vbs"
|
||||||
dir = "win"
|
|
||||||
case "darwin":
|
case "darwin":
|
||||||
ext = ".applescript"
|
ext = ".applescript"
|
||||||
dir = "mac"
|
|
||||||
}
|
}
|
||||||
if !strings.HasSuffix(name, ext) {
|
if !strings.HasSuffix(name, ext) {
|
||||||
name += ext
|
name += ext
|
||||||
}
|
}
|
||||||
args = append([]string{Opts, path.Join(PKGPATH, dir, name)}, args...)
|
|
||||||
|
if strings.Contains(name, "dojs") {
|
||||||
|
args = append([]string{Opts, filepath.Join(pkgpath, "scripts", name)},
|
||||||
|
args[0],
|
||||||
|
fmt.Sprintf("%s", strings.Join(args[1:], ",")),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
args = append([]string{Opts, filepath.Join(pkgpath, "scripts", name)}, args...)
|
||||||
|
}
|
||||||
cmd := exec.Command(Cmd, args...)
|
cmd := exec.Command(Cmd, args...)
|
||||||
cmd.Stdout = &out
|
cmd.Stdout = &out
|
||||||
cmd.Stderr = &stderr
|
cmd.Stderr = &errs
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
return out.Bytes(), err
|
if err != nil || len(errs.Bytes()) != 0 {
|
||||||
|
return out.Bytes(), errors.New(string(errs.Bytes()))
|
||||||
|
}
|
||||||
|
return out.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DoAction runs the Photoshop action with name from set.
|
||||||
|
func DoAction(set, name string) error {
|
||||||
|
_, err := run("action", set, name)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplyDataset fills out a template file with information
|
||||||
|
// from a given dataset (csv) file. It is important to note that running this
|
||||||
|
// function will change data in the Photoshop document, but will not update
|
||||||
|
// data in the Go Document struct (if any); you will have to implement syncing
|
||||||
|
// them yourself.
|
||||||
|
func ApplyDataset(name string) ([]byte, error) {
|
||||||
|
return DoJs("applyDataset.jsx", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// property of the layer, you'll have to trim the output before concatenating
|
||||||
|
func JSLayer(path string, art ...bool) string {
|
||||||
|
path = strings.TrimLeft(path, "/")
|
||||||
|
pth := strings.Split(path, "/")
|
||||||
|
js := "app.activeDocument"
|
||||||
|
last := len(pth) - 1
|
||||||
|
if len(art) > 0 {
|
||||||
|
pth = pth[:len(pth)-1]
|
||||||
|
last--
|
||||||
|
}
|
||||||
|
if last > 0 {
|
||||||
|
for i := 0; i < last; i++ {
|
||||||
|
js += fmt.Sprintf(".layerSets.getByName('%s')", pth[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if pth[last] != "" {
|
||||||
|
js += fmt.Sprintf(".artLayers.getByName('%s')", pth[last])
|
||||||
|
}
|
||||||
|
return js + ";"
|
||||||
}
|
}
|
||||||
|
|||||||
283
ps_test.go
283
ps_test.go
@@ -1,59 +1,296 @@
|
|||||||
package ps
|
package ps
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"path"
|
"os"
|
||||||
"strings"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: Comparison borked
|
func TestPkgPath(t *testing.T) {
|
||||||
func TestRun(t *testing.T) {
|
out := filepath.Join(os.Getenv("GOPATH"), "src", "github.com", "sbrow", "ps")
|
||||||
out := []byte("Testing...\n")
|
if filepath.Join(pkgpath) != out {
|
||||||
msg, err := run("test")
|
t.Fatal(filepath.Join(pkgpath), out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStart(t *testing.T) {
|
||||||
|
err := Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if string(msg) == string(out) {
|
|
||||||
fail := fmt.Sprintf("run(test)\ngot:\t\"%s\"\nwant:\t\"%s\"\n", msg, out)
|
|
||||||
t.Fatal(fail)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOpen(t *testing.T) {
|
func TestOpen(t *testing.T) {
|
||||||
if testing.Short() {
|
// if testing.Short() {
|
||||||
t.Skip("Skipping \"TestOpen\"")
|
// t.Skip("Skipping \"TestOpen\"")
|
||||||
|
// }
|
||||||
|
err := Open("F:\\GitLab\\dreamkeepers-psd\\Template009.1.psd")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClose(t *testing.T) {
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("Skipping \"TestClose\"")
|
||||||
|
}
|
||||||
|
err := Close(2)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
Open("F:\\GitLab\\dreamkeepers-psd\\Template009.1.psd")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestQuit(t *testing.T) {
|
func TestQuit(t *testing.T) {
|
||||||
if testing.Short() {
|
if testing.Short() {
|
||||||
t.Skip("Skipping \"TestQuit\"")
|
t.Skip("Skipping \"TestQuit\"")
|
||||||
}
|
}
|
||||||
Quit()
|
err := Quit(2)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDoJs(t *testing.T) {
|
||||||
|
out := []byte("F:\\TEMP\\js_out.txt\r\narg\r\nargs\r\n")
|
||||||
|
script := "test.jsx"
|
||||||
|
ret, err := DoJs(script, "arg", "args")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if string(ret) != string(out) {
|
||||||
|
fail := fmt.Sprintf("TestJS failed.\ngot:\t\"%s\"\nwant:\t\"%s\"", ret, out)
|
||||||
|
t.Fatal(fail)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRun(t *testing.T) {
|
||||||
|
out := []byte("hello,\r\nworld!\r\n")
|
||||||
|
msg, err := run("test", "hello,", "world!")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if string(msg) != string(out) {
|
||||||
|
fail := fmt.Sprintf("TestRun faild.\ngot:\n\"%s\"\nwant:\n\"%s\"\n", msg, out)
|
||||||
|
t.Fatal(fail)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWait(t *testing.T) {
|
func TestWait(t *testing.T) {
|
||||||
Wait("Waiting...")
|
Wait("Waiting...")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Comparison borked
|
func TestDoAction_Crop(t *testing.T) {
|
||||||
func TestJS(t *testing.T) {
|
if testing.Short() {
|
||||||
out := "Testing...\n"
|
t.Skip("Skipping \"TestDoAction_Crop\"")
|
||||||
_, err := Js(path.Join(Folder, "test.jsx"), Folder)
|
}
|
||||||
|
err := Open("F:\\GitLab\\dreamkeepers-psd\\Template009.1.psd")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
f, err := ioutil.ReadFile(path.Join(Folder, "test.txt"))
|
err = DoAction("DK", "Crop")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if strings.Compare(string(f), string(out)) != 0 {
|
}
|
||||||
fmt.Println(f)
|
|
||||||
fmt.Println([]byte(out))
|
func TestDoAction_Undo(t *testing.T) {
|
||||||
fail := fmt.Sprintf("TestJS failed.\ngot:\t\"%s\"\nwant:\t\"%s\"", f, out)
|
if testing.Short() {
|
||||||
|
t.Skip("Skipping \"TestDoAction_Undo\"")
|
||||||
|
}
|
||||||
|
err := DoAction("DK", "Undo")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSaveAs(t *testing.T) {
|
||||||
|
err := SaveAs("F:\\TEMP\\test.png")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
os.Remove("F:\\TEMP\\test.png")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLayerSet(t *testing.T) {
|
||||||
|
_, err := NewLayerSet("Areas/TitleBackground/", nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLayer(t *testing.T) {
|
||||||
|
_, err := Layer("Border/Inner Border")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMove(t *testing.T) {
|
||||||
|
lyr, err := Layer("Group 1/Layer 1")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
lyr.SetPos(100, 50, "TL")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestActiveDocument(t *testing.T) {
|
||||||
|
Mode = Safe
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("Skipping \"TestDocument\"")
|
||||||
|
}
|
||||||
|
d, err := ActiveDocument()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if d != d.artLayers[0].Parent() {
|
||||||
|
fmt.Println(d)
|
||||||
|
fmt.Println(d.artLayers[0].Parent())
|
||||||
|
t.Fatal("ArtLayers do not have doc as parent.")
|
||||||
|
}
|
||||||
|
if d != d.layerSets[0].Parent() {
|
||||||
|
fmt.Println(d)
|
||||||
|
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())
|
||||||
|
t.Fatal("Layerset's ArtLayers do not have correct parents")
|
||||||
|
}
|
||||||
|
// d.LayerSet("Areas").LayerSet("Bottom").ArtLayer("L Bar").SetColor(155, 255, 255)
|
||||||
|
lyr := d.LayerSet("Text").ArtLayer("speed")
|
||||||
|
if lyr == nil {
|
||||||
|
t.Fatal("lyr does not exist")
|
||||||
|
}
|
||||||
|
s := Stroke{Size: 4, Color: &RGB{0, 0, 0}}
|
||||||
|
lyr.SetStroke(s, &RGB{128, 128, 128})
|
||||||
|
d.Dump()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestColor(t *testing.T) {
|
||||||
|
byt, err := run("colorLayer.vbs", "255", "255", "255")
|
||||||
|
fmt.Println(string(byt))
|
||||||
|
fmt.Println(err)
|
||||||
|
if err != nil {
|
||||||
|
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestApplyDataset(t *testing.T) {
|
||||||
|
out := []byte("done!\r\n")
|
||||||
|
ret, err := ApplyDataset(" Anger")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if string(ret) != string(out) {
|
||||||
|
fail := fmt.Sprintf("TestJS failed.\ngot:\t\"%s\"\nwant:\t\"%s\"", ret, out)
|
||||||
t.Fatal(fail)
|
t.Fatal(fail)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDocumentLayerSet(t *testing.T) {
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("Skipping TestDocumentLayerSet")
|
||||||
|
}
|
||||||
|
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 TestLoadedDoc(t *testing.T) {
|
||||||
|
var d *Document
|
||||||
|
byt, err := ioutil.ReadFile("Document.txt")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(byt, &d)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if d != d.ArtLayers()[0].Parent() {
|
||||||
|
t.Fatal("Loaded document's ArtLayers do not point to doc")
|
||||||
|
}
|
||||||
|
if d != d.LayerSets()[0].Parent() {
|
||||||
|
t.Fatal("Loaded document's LayerSets do not point to doc")
|
||||||
|
}
|
||||||
|
if d.LayerSets()[0] != d.layerSets[0].artLayers[0].Parent() {
|
||||||
|
t.Fatal("Loaded document's LayerSet's ArtLayers do not point to layerSets")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDoJs_HideLayer(t *testing.T) {
|
||||||
|
err := Open("F:\\GitLab\\dreamkeepers-psd\\Template009.1.psd")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
lyr, err := NewLayerSet("Areas/TitleBackground", nil)
|
||||||
|
lyr.SetVisible(false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDoc_Go(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_, err := ActiveDocument()
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//.8s
|
||||||
|
//.15
|
||||||
|
func BenchmarkHideLayer(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
// _, err := Layers("Areas/TitleBackground/")
|
||||||
|
// if err != nil {
|
||||||
|
// b.Fatal(err)
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 59ns
|
||||||
|
func BenchmarkHelloWorld_go(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
fmt.Sprintf("Hello, world!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ~35200000ns (.0352s)
|
||||||
|
func BenchmarkHelloWorld_vbs(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_, err := run("helloworld")
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ~51700000 (0.0517)
|
||||||
|
func BenchmarkHelloWorld_js(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_, err := DoJs("test.jsx", "Hello, World!")
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
12
scripts/PsIsOpen.vbs
Normal file
12
scripts/PsIsOpen.vbs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
Function IsProcessRunning( strComputer, strProcess )
|
||||||
|
Dim Process, strObject
|
||||||
|
IsProcessRunning = False
|
||||||
|
strObject = "winmgmts://" & strComputer
|
||||||
|
For Each Process in GetObject( strObject ).InstancesOf( "win32_process" )
|
||||||
|
If UCase( Process.name ) = UCase( strProcess ) Then
|
||||||
|
IsProcessRunning = True
|
||||||
|
Exit Function
|
||||||
|
End If
|
||||||
|
Next
|
||||||
|
End Function
|
||||||
|
wScript.Echo IsProcessRunning(".", "Photoshop.exe")
|
||||||
10
scripts/action.vbs
Normal file
10
scripts/action.vbs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
set appRef = CreateObject("Photoshop.Application")
|
||||||
|
' No dialogs'
|
||||||
|
dlgMode = 3
|
||||||
|
|
||||||
|
set desc = CreateObject( "Photoshop.ActionDescriptor" )
|
||||||
|
set ref = CreateObject( "Photoshop.ActionReference" )
|
||||||
|
Call ref.PutName(appRef.CharIDToTypeID("Actn"), wScript.Arguments(1))
|
||||||
|
Call ref.PutName(appRef.CharIDToTypeID("ASet"), wScript.Arguments(0))
|
||||||
|
Call desc.PutReference(appRef.CharIDToTypeID("null"), ref)
|
||||||
|
Call appRef.ExecuteAction(appRef.CharIDToTypeID("Ply "), desc, dlgMode)
|
||||||
2
scripts/activeDocName.jsx
Normal file
2
scripts/activeDocName.jsx
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#include lib.js
|
||||||
|
var stdout = newFile(arguments[0]);stdout.writeln(app.activeDocument.name);stdout.close();
|
||||||
15
scripts/applyDataset.jsx
Normal file
15
scripts/applyDataset.jsx
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
var saveFile = File(arguments[0]);
|
||||||
|
if(saveFile.exists)
|
||||||
|
saveFile.remove();
|
||||||
|
var idAply = charIDToTypeID("Aply");
|
||||||
|
var desc1 = new ActionDescriptor();
|
||||||
|
var idnull = charIDToTypeID("null");
|
||||||
|
var ref1 = new ActionReference();
|
||||||
|
var iddataSetClass = stringIDToTypeID("dataSetClass");
|
||||||
|
ref1.putName(iddataSetClass, arguments[1]);
|
||||||
|
desc1.putReference(idnull, ref1);
|
||||||
|
executeAction(idAply, desc1, DialogModes.NO);
|
||||||
|
saveFile.encoding = "UTF8";
|
||||||
|
saveFile.open("e", "TEXT", "????");
|
||||||
|
saveFile.writeln("done!");
|
||||||
|
saveFile.close();
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
set App = CreateObject("Photoshop.Application")
|
set App = CreateObject("Photoshop.Application")
|
||||||
set Doc = App.activeDocument
|
set Doc = App.activeDocument
|
||||||
Doc.Close
|
Doc.Close(CInt(wScript.Arguments(0)))
|
||||||
76
scripts/colorLayer.vbs
Normal file
76
scripts/colorLayer.vbs
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
DIM objApp
|
||||||
|
SET objApp = CreateObject("Photoshop.Application")
|
||||||
|
DIM dialogMode
|
||||||
|
dialogMode = 3
|
||||||
|
DIM idsetd
|
||||||
|
idsetd = objApp.CharIDToTypeID("setd")
|
||||||
|
DIM desc134
|
||||||
|
SET desc134 = CreateObject("Photoshop.ActionDescriptor")
|
||||||
|
DIM idnull
|
||||||
|
idnull = objApp.CharIDToTypeID("null")
|
||||||
|
DIM ref44
|
||||||
|
SET ref44 = CreateObject("Photoshop.ActionReference")
|
||||||
|
DIM idPrpr
|
||||||
|
idPrpr = objApp.CharIDToTypeID("Prpr")
|
||||||
|
DIM idLefx
|
||||||
|
idLefx = objApp.CharIDToTypeID("Lefx")
|
||||||
|
Call ref44.PutProperty(idPrpr, idLefx)
|
||||||
|
DIM idLyr
|
||||||
|
idLyr = objApp.CharIDToTypeID("Lyr ")
|
||||||
|
DIM idOrdn
|
||||||
|
idOrdn = objApp.CharIDToTypeID("Ordn")
|
||||||
|
DIM idTrgt
|
||||||
|
idTrgt = objApp.CharIDToTypeID("Trgt")
|
||||||
|
Call ref44.PutEnumerated(idLyr, idOrdn, idTrgt)
|
||||||
|
Call desc134.PutReference(idnull, ref44)
|
||||||
|
DIM idT
|
||||||
|
idT = objApp.CharIDToTypeID("T ")
|
||||||
|
DIM desc135
|
||||||
|
SET desc135 = CreateObject("Photoshop.ActionDescriptor")
|
||||||
|
DIM idScl
|
||||||
|
idScl = objApp.CharIDToTypeID("Scl ")
|
||||||
|
DIM idPrc
|
||||||
|
idPrc = objApp.CharIDToTypeID("#Prc")
|
||||||
|
Call desc135.PutUnitDouble(idScl, idPrc, 416.666667)
|
||||||
|
DIM idSoFi
|
||||||
|
idSoFi = objApp.CharIDToTypeID("SoFi")
|
||||||
|
DIM desc136
|
||||||
|
SET desc136 = CreateObject("Photoshop.ActionDescriptor")
|
||||||
|
DIM idenab
|
||||||
|
idenab = objApp.CharIDToTypeID("enab")
|
||||||
|
Call desc136.PutBoolean(idenab, True)
|
||||||
|
DIM idMd
|
||||||
|
idMd = objApp.CharIDToTypeID("Md ")
|
||||||
|
DIM idBlnM
|
||||||
|
idBlnM = objApp.CharIDToTypeID("BlnM")
|
||||||
|
DIM idNrml
|
||||||
|
idNrml = objApp.CharIDToTypeID("Nrml")
|
||||||
|
Call desc136.PutEnumerated(idMd, idBlnM, idNrml)
|
||||||
|
DIM idOpct
|
||||||
|
idOpct = objApp.CharIDToTypeID("Opct")
|
||||||
|
idPrc = objApp.CharIDToTypeID("#Prc")
|
||||||
|
Call desc136.PutUnitDouble(idOpct, idPrc, 100.000000)
|
||||||
|
DIM idClr
|
||||||
|
idClr = objApp.CharIDToTypeID("Clr ")
|
||||||
|
DIM desc137
|
||||||
|
SET desc137 = CreateObject("Photoshop.ActionDescriptor")
|
||||||
|
DIM idRd
|
||||||
|
idRd = objApp.CharIDToTypeID("Rd ")
|
||||||
|
Call desc137.PutDouble(idRd, CInt(wScript.Arguments(0)))
|
||||||
|
' Call desc137.PutDouble(idRd, 255)
|
||||||
|
DIM idGrn
|
||||||
|
idGrn = objApp.CharIDToTypeID("Grn ")
|
||||||
|
Call desc137.PutDouble(idGrn, Cint(wScript.Arguments(1)))
|
||||||
|
' Call desc137.PutDouble(idGrn, 255)
|
||||||
|
DIM idBl
|
||||||
|
idBl = objApp.CharIDToTypeID("Bl ")
|
||||||
|
Call desc137.PutDouble(idBl, CInt(wScript.Arguments(2)))
|
||||||
|
' Call desc137.PutDouble(idBl, 255)
|
||||||
|
DIM idRGBC
|
||||||
|
idRGBC = objApp.CharIDToTypeID("RGBC")
|
||||||
|
Call desc136.PutObject(idClr, idRGBC, desc137)
|
||||||
|
idSoFi = objApp.CharIDToTypeID("SoFi")
|
||||||
|
Call desc135.PutObject(idSoFi, idSoFi, desc136)
|
||||||
|
idLefx = objApp.CharIDToTypeID("Lefx")
|
||||||
|
Call desc134.PutObject(idT, idLefx, desc135)
|
||||||
|
Call objApp.ExecuteAction(idsetd, desc134, dialogMode)
|
||||||
120
scripts/colorStroke.vbs
Normal file
120
scripts/colorStroke.vbs
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
DIM objApp
|
||||||
|
SET objApp = CreateObject("Photoshop.Application")
|
||||||
|
REM Use dialog mode 3 for show no dialogs
|
||||||
|
DIM dialogMode
|
||||||
|
dialogMode = 3
|
||||||
|
DIM idsetd
|
||||||
|
idsetd = objApp.CharIDToTypeID("setd")
|
||||||
|
DIM desc2
|
||||||
|
SET desc2 = CreateObject("Photoshop.ActionDescriptor")
|
||||||
|
DIM idnull
|
||||||
|
idnull = objApp.CharIDToTypeID("null")
|
||||||
|
DIM ref2
|
||||||
|
SET ref2 = CreateObject("Photoshop.ActionReference")
|
||||||
|
DIM idPrpr
|
||||||
|
idPrpr = objApp.CharIDToTypeID("Prpr")
|
||||||
|
DIM idLefx
|
||||||
|
idLefx = objApp.CharIDToTypeID("Lefx")
|
||||||
|
Call ref2.PutProperty(idPrpr, idLefx)
|
||||||
|
DIM idLyr
|
||||||
|
idLyr = objApp.CharIDToTypeID("Lyr ")
|
||||||
|
DIM idOrdn
|
||||||
|
idOrdn = objApp.CharIDToTypeID("Ordn")
|
||||||
|
DIM idTrgt
|
||||||
|
idTrgt = objApp.CharIDToTypeID("Trgt")
|
||||||
|
Call ref2.PutEnumerated(idLyr, idOrdn, idTrgt)
|
||||||
|
Call desc2.PutReference(idnull, ref2)
|
||||||
|
DIM idT
|
||||||
|
idT = objApp.CharIDToTypeID("T ")
|
||||||
|
DIM desc3
|
||||||
|
SET desc3 = CreateObject("Photoshop.ActionDescriptor")
|
||||||
|
DIM idScl
|
||||||
|
idScl = objApp.CharIDToTypeID("Scl ")
|
||||||
|
DIM idPrc
|
||||||
|
idPrc = objApp.CharIDToTypeID("#Prc")
|
||||||
|
Call desc3.PutUnitDouble(idScl, idPrc, 416.666667)
|
||||||
|
DIM idSoFi
|
||||||
|
idSoFi = objApp.CharIDToTypeID("SoFi")
|
||||||
|
DIM desc4
|
||||||
|
SET desc4 = CreateObject("Photoshop.ActionDescriptor")
|
||||||
|
DIM idenab
|
||||||
|
idenab = objApp.CharIDToTypeID("enab")
|
||||||
|
Call desc4.PutBoolean(idenab, True)
|
||||||
|
DIM idMd
|
||||||
|
idMd = objApp.CharIDToTypeID("Md ")
|
||||||
|
DIM idBlnM
|
||||||
|
idBlnM = objApp.CharIDToTypeID("BlnM")
|
||||||
|
DIM idNrml
|
||||||
|
idNrml = objApp.CharIDToTypeID("Nrml")
|
||||||
|
Call desc4.PutEnumerated(idMd, idBlnM, idNrml)
|
||||||
|
DIM idOpct
|
||||||
|
idOpct = objApp.CharIDToTypeID("Opct")
|
||||||
|
idPrc = objApp.CharIDToTypeID("#Prc")
|
||||||
|
Call desc4.PutUnitDouble(idOpct, idPrc, 100.000000)
|
||||||
|
DIM idClr
|
||||||
|
idClr = objApp.CharIDToTypeID("Clr ")
|
||||||
|
DIM desc5
|
||||||
|
SET desc5 = CreateObject("Photoshop.ActionDescriptor")
|
||||||
|
DIM idRd
|
||||||
|
idRd = objApp.CharIDToTypeID("Rd ")
|
||||||
|
Call desc5.PutDouble(idRd, CInt(wScript.Arguments(0)))
|
||||||
|
DIM idGrn
|
||||||
|
idGrn = objApp.CharIDToTypeID("Grn ")
|
||||||
|
Call desc5.PutDouble(idGrn,CInt(wScript.Arguments(1)))
|
||||||
|
DIM idBl
|
||||||
|
idBl = objApp.CharIDToTypeID("Bl ")
|
||||||
|
Call desc5.PutDouble(idBl, CInt(wScript.Arguments(2)))
|
||||||
|
DIM idRGBC
|
||||||
|
idRGBC = objApp.CharIDToTypeID("RGBC")
|
||||||
|
Call desc4.PutObject(idClr, idRGBC, desc5)
|
||||||
|
idSoFi = objApp.CharIDToTypeID("SoFi")
|
||||||
|
Call desc3.PutObject(idSoFi, idSoFi, desc4)
|
||||||
|
DIM idFrFX
|
||||||
|
idFrFX = objApp.CharIDToTypeID("FrFX")
|
||||||
|
DIM desc6
|
||||||
|
SET desc6 = CreateObject("Photoshop.ActionDescriptor")
|
||||||
|
idenab = objApp.CharIDToTypeID("enab")
|
||||||
|
Call desc6.PutBoolean(idenab, True)
|
||||||
|
DIM idStyl
|
||||||
|
idStyl = objApp.CharIDToTypeID("Styl")
|
||||||
|
DIM idFStl
|
||||||
|
idFStl = objApp.CharIDToTypeID("FStl")
|
||||||
|
DIM idOutF
|
||||||
|
idOutF = objApp.CharIDToTypeID("OutF")
|
||||||
|
Call desc6.PutEnumerated(idStyl, idFStl, idOutF)
|
||||||
|
DIM idPntT
|
||||||
|
idPntT = objApp.CharIDToTypeID("PntT")
|
||||||
|
DIM idFrFl
|
||||||
|
idFrFl = objApp.CharIDToTypeID("FrFl")
|
||||||
|
DIM idSClr
|
||||||
|
idSClr = objApp.CharIDToTypeID("SClr")
|
||||||
|
Call desc6.PutEnumerated(idPntT, idFrFl, idSClr)
|
||||||
|
idMd = objApp.CharIDToTypeID("Md ")
|
||||||
|
idBlnM = objApp.CharIDToTypeID("BlnM")
|
||||||
|
idNrml = objApp.CharIDToTypeID("Nrml")
|
||||||
|
Call desc6.PutEnumerated(idMd, idBlnM, idNrml)
|
||||||
|
idOpct = objApp.CharIDToTypeID("Opct")
|
||||||
|
idPrc = objApp.CharIDToTypeID("#Prc")
|
||||||
|
Call desc6.PutUnitDouble(idOpct, idPrc, 100.000000)
|
||||||
|
DIM idSz
|
||||||
|
idSz = objApp.CharIDToTypeID("Sz ")
|
||||||
|
DIM idPxl
|
||||||
|
idPxl = objApp.CharIDToTypeID("#Pxl")
|
||||||
|
Call desc6.PutUnitDouble(idSz, idPxl, CLng(wScript.Arguments(3)))
|
||||||
|
idClr = objApp.CharIDToTypeID("Clr ")
|
||||||
|
DIM desc7
|
||||||
|
SET desc7 = CreateObject("Photoshop.ActionDescriptor")
|
||||||
|
idRd = objApp.CharIDToTypeID("Rd ")
|
||||||
|
Call desc7.PutDouble(idRd, CInt(wScript.Arguments(4)))
|
||||||
|
idGrn = objApp.CharIDToTypeID("Grn ")
|
||||||
|
Call desc7.PutDouble(idGrn, CInt(wScript.Arguments(5)))
|
||||||
|
idBl = objApp.CharIDToTypeID("Bl ")
|
||||||
|
Call desc7.PutDouble(idBl, CInt(wScript.Arguments(6)))
|
||||||
|
idRGBC = objApp.CharIDToTypeID("RGBC")
|
||||||
|
Call desc6.PutObject(idClr, idRGBC, desc7)
|
||||||
|
idFrFX = objApp.CharIDToTypeID("FrFX")
|
||||||
|
Call desc3.PutObject(idFrFX, idFrFX, desc6)
|
||||||
|
idLefx = objApp.CharIDToTypeID("Lefx")
|
||||||
|
Call desc2.PutObject(idT, idLefx, desc3)
|
||||||
|
Call objApp.ExecuteAction(idsetd, desc2, dialogMode)
|
||||||
|
|
||||||
4
scripts/compilejs.jsx
Normal file
4
scripts/compilejs.jsx
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#include lib.js
|
||||||
|
var stdout = newFile(arguments[0])
|
||||||
|
eval(arguments[1]);
|
||||||
|
stdout.close()
|
||||||
13
scripts/dojs.vbs
Normal file
13
scripts/dojs.vbs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
Dim appRef
|
||||||
|
Set appRef = CreateObject("Photoshop.Application")
|
||||||
|
if wScript.Arguments.Count = 0 then
|
||||||
|
wScript.Echo "Missing parameters"
|
||||||
|
else
|
||||||
|
path = wScript.Arguments(0)
|
||||||
|
args = wScript.Arguments(1)
|
||||||
|
error = appRef.DoJavaScriptFile(path, Split(args, ","))
|
||||||
|
if Not error = "true" and Not error = "[ActionDescriptor]" and Not error = "undefined" Then
|
||||||
|
Err.raise 1, "dojs.vbs", error
|
||||||
|
end if
|
||||||
|
end if
|
||||||
54
scripts/fmtText.jsx
Normal file
54
scripts/fmtText.jsx
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
var start = parseInt(arguments[1]);
|
||||||
|
var end = parseInt(arguments[2]);
|
||||||
|
var fontName = arguments[3];
|
||||||
|
var fontStyle = arguments[4];
|
||||||
|
var colorArray = [0, 0, 0];
|
||||||
|
if(app.activeDocument.activeLayer.kind == LayerKind.TEXT){
|
||||||
|
var activeLayer = app.activeDocument.activeLayer;
|
||||||
|
var fontSize = activeLayer.textItem.size;
|
||||||
|
if(activeLayer.kind == LayerKind.TEXT){
|
||||||
|
if((activeLayer.textItem.contents != "")&&(start >= 0)&&(end <= activeLayer.textItem.contents.length)){
|
||||||
|
var idsetd = app.charIDToTypeID( "setd" );
|
||||||
|
var action = new ActionDescriptor();
|
||||||
|
var idnull = app.charIDToTypeID( "null" );
|
||||||
|
var reference = new ActionReference();
|
||||||
|
var idTxLr = app.charIDToTypeID( "TxLr" );
|
||||||
|
var idOrdn = app.charIDToTypeID( "Ordn" );
|
||||||
|
var idTrgt = app.charIDToTypeID( "Trgt" );
|
||||||
|
reference.putEnumerated( idTxLr, idOrdn, idTrgt );
|
||||||
|
action.putReference( idnull, reference );
|
||||||
|
var idT = app.charIDToTypeID( "T " );
|
||||||
|
var textAction = new ActionDescriptor();
|
||||||
|
var idTxtt = app.charIDToTypeID( "Txtt" );
|
||||||
|
var actionList = new ActionList();
|
||||||
|
var textRange = new ActionDescriptor();
|
||||||
|
var idFrom = app.charIDToTypeID( "From" );
|
||||||
|
textRange.putInteger( idFrom, start );
|
||||||
|
textRange.putInteger( idT, end );
|
||||||
|
var idTxtS = app.charIDToTypeID( "TxtS" );
|
||||||
|
var formatting = new ActionDescriptor();
|
||||||
|
var idFntN = app.charIDToTypeID( "FntN" );
|
||||||
|
formatting.putString( idFntN, fontName );
|
||||||
|
var idFntS = app.charIDToTypeID( "FntS" );
|
||||||
|
formatting.putString( idFntS, fontStyle );
|
||||||
|
var idSz = app.charIDToTypeID( "Sz " );
|
||||||
|
var idPnt = app.charIDToTypeID( "#Pnt" );
|
||||||
|
formatting.putUnitDouble( idSz, idPnt, fontSize );
|
||||||
|
var idClr = app.charIDToTypeID( "Clr " );
|
||||||
|
var colorAction = new ActionDescriptor();
|
||||||
|
var idRd = app.charIDToTypeID( "Rd " );
|
||||||
|
colorAction.putDouble( idRd, colorArray[0] );
|
||||||
|
var idGrn = app.charIDToTypeID( "Grn " );
|
||||||
|
colorAction.putDouble( idGrn, colorArray[1]);
|
||||||
|
var idBl = app.charIDToTypeID( "Bl " );
|
||||||
|
colorAction.putDouble( idBl, colorArray[2] );
|
||||||
|
var idRGBC = app.charIDToTypeID( "RGBC" );
|
||||||
|
formatting.putObject( idClr, idRGBC, colorAction );
|
||||||
|
textRange.putObject( idTxtS, idTxtS, formatting );
|
||||||
|
actionList.putObject( idTxtt, textRange );
|
||||||
|
textAction.putList( idTxtt, actionList );
|
||||||
|
action.putObject( idT, idTxLr, textAction );
|
||||||
|
app.executeAction( idsetd, action, DialogModes.NO );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
39
scripts/getActiveDoc.jsx
Normal file
39
scripts/getActiveDoc.jsx
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#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, ""));
|
||||||
|
function layers(lyrs) {
|
||||||
|
if (typeof lyrs === 'undefined')
|
||||||
|
return;
|
||||||
|
for (var i = 0; i < lyrs.length; i++) {
|
||||||
|
var lyr = lyrs[i];
|
||||||
|
stdout.write(('{"Name":"' + lyr.name + '", "Bounds": [[' + lyr.bounds[0] + ',' +
|
||||||
|
lyr.bounds[1] + '],[' + lyr.bounds[2] + ',' +
|
||||||
|
lyr.bounds[3] + ']], "Visible": ' + lyr.visible+', "Text":').replace(/ px/g, ""));
|
||||||
|
if (lyr.kind == LayerKind.TEXT)
|
||||||
|
stdout.write('"'+lyr.textItem.contents+'"');
|
||||||
|
else
|
||||||
|
stdout.write("null");
|
||||||
|
stdout.write("}")
|
||||||
|
if (i+1 != lyrs.length)
|
||||||
|
stdout.write(',');
|
||||||
|
stdout.writeln();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
layers(doc.artLayers)
|
||||||
|
stdout.writeln('], "LayerSets": [');
|
||||||
|
function lyrSets(sets, nm) {
|
||||||
|
if (typeof sets === 'undefined')
|
||||||
|
return;
|
||||||
|
for (var i = 0; i < sets.length; i++) {
|
||||||
|
var set = sets[i];
|
||||||
|
var name = nm + set.name + "/";
|
||||||
|
stdout.write('{"Name": "' + set.name + '", "Visible":'+ set.visible +'}');
|
||||||
|
if (i+1 != sets.length)
|
||||||
|
stdout.write(',');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lyrSets(doc.layerSets)
|
||||||
|
stdout.write(']}');
|
||||||
|
stdout.close();
|
||||||
14
scripts/getLayer.jsx
Normal file
14
scripts/getLayer.jsx
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#include lib.js
|
||||||
|
app.displayDialogs=DialogModes.NO
|
||||||
|
var stdout = newFile(arguments[0]);
|
||||||
|
var lyr = eval(arguments[1]);
|
||||||
|
stdout.write(('{"Name":"' + lyr.name + '","Bounds":[[' + lyr.bounds[0] + ',' +
|
||||||
|
lyr.bounds[1] + '],[' + lyr.bounds[2] + ',' +
|
||||||
|
lyr.bounds[3] + ']],"Visible":' + lyr.visible+',"Text":').replace(/ px/g, ""));
|
||||||
|
if (lyr.kind == LayerKind.TEXT) {
|
||||||
|
stdout.write('"'+lyr.textItem.contents.replace(/\r/g, "\\r")+'"');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
stdout.write(null)
|
||||||
|
stdout.writeln('}')
|
||||||
|
stdout.close();
|
||||||
39
scripts/getLayerSet.jsx
Normal file
39
scripts/getLayerSet.jsx
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#include lib.js
|
||||||
|
var stdout = newFile(arguments[0]);
|
||||||
|
var set = eval(arguments[1]);
|
||||||
|
stdout.writeln('{"Name": "'+set.name+'", "Visible": '+ set.visible +', "ArtLayers":[');
|
||||||
|
stdout.flush();
|
||||||
|
for (var i = 0; i < set.artLayers.length; i++) {
|
||||||
|
var lyr = set.artLayers[i];
|
||||||
|
stdout.write(('{"Name":"' + lyr.name + '", "Bounds": [[' + lyr.bounds[0] + ',' +
|
||||||
|
lyr.bounds[1] + '],[' + lyr.bounds[2] + ',' +
|
||||||
|
lyr.bounds[3] + ']], "Visible": ' + lyr.visible + ',"Text":').replace(/ px/g, ""));
|
||||||
|
if (lyr.kind == LayerKind.TEXT)
|
||||||
|
stdout.write('"'+lyr.textItem.contents.replace(/\r/g, "\\r")+'"');
|
||||||
|
else
|
||||||
|
stdout.write("null");
|
||||||
|
stdout.write("}")
|
||||||
|
if (i != set.artLayers.length - 1)
|
||||||
|
stdout.writeln(",");
|
||||||
|
stdout.flush();
|
||||||
|
}
|
||||||
|
stdout.writeln("]");
|
||||||
|
stdout.write(', "LayerSets": [')
|
||||||
|
for (var i = 0; i < set.layerSets.length; i++) {
|
||||||
|
var s = set.layerSets[i];
|
||||||
|
stdout.write('{"Name":"' + s.name + '", "Visible": ' + s.visible + '}');
|
||||||
|
if (i < set.layerSets.length - 1)
|
||||||
|
stdout.writeln(",");
|
||||||
|
stdout.flush()
|
||||||
|
}
|
||||||
|
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();
|
||||||
2
scripts/isVisible.jsx
Normal file
2
scripts/isVisible.jsx
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#include lib.js
|
||||||
|
var stdout = newFile(arguments[0]);stdout.writeln(eval(arguments[1]).visible);stdout.close();
|
||||||
11
scripts/layerSetBounds.jsx
Normal file
11
scripts/layerSetBounds.jsx
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#include lib.js
|
||||||
|
var stdout = newFile(arguments[0]);
|
||||||
|
var set = eval(arguments[1]);
|
||||||
|
app.activeDocument.activeLayer=set;
|
||||||
|
set.merge();
|
||||||
|
set=eval(arguments[2]);
|
||||||
|
stdout.write(('[[' + set.bounds[0] + ',' +
|
||||||
|
set.bounds[1] + '],[' + set.bounds[2] + ',' +
|
||||||
|
set.bounds[3] + ']]').replace(/ px/g, ""));
|
||||||
|
Undo();
|
||||||
|
stdout.close();
|
||||||
100
scripts/lib.js
Normal file
100
scripts/lib.js
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
// Opens and returns a file, overwriting new data.
|
||||||
|
function newFile(path) {
|
||||||
|
var f = File(path)
|
||||||
|
f.encoding = "UTF8"
|
||||||
|
f.open("w")
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
File.prototype.flush = function() {
|
||||||
|
this.close()
|
||||||
|
this.open("a")
|
||||||
|
};
|
||||||
|
function flush(file) {
|
||||||
|
file.close()
|
||||||
|
file.open("a")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Prints an error message.
|
||||||
|
function err(e) {
|
||||||
|
return 'ERROR: ' + e.message + ' at ' + e.fileName + ':' + e.line;
|
||||||
|
}
|
||||||
|
|
||||||
|
function bounds(lyr) {
|
||||||
|
return ('"Bounds": [[' + lyr.bounds[0] + ',' +
|
||||||
|
lyr.bounds[1] + '],[' + lyr.bounds[2] + ',' +
|
||||||
|
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
|
||||||
|
* characters in a Photoshop text layer.
|
||||||
|
*
|
||||||
|
* @param start (int) the index of the insertion point *before* the character you want.,
|
||||||
|
* @param end (int) the index of the insertion point following the character.
|
||||||
|
* @param fontName is a string for the font name.
|
||||||
|
* @param fontStyle is a string for the font style.
|
||||||
|
* @param fontSize (Number) the point size of the text.
|
||||||
|
* @param colorArray (Array) is the RGB color to be applied to the text.
|
||||||
|
*/
|
||||||
|
function setFormatting(start, end, fontName, fontStyle, fontSize, colorArray) {
|
||||||
|
if(app.activeDocument.activeLayer.kind == LayerKind.TEXT){
|
||||||
|
var activeLayer = app.activeDocument.activeLayer;
|
||||||
|
fontSize = activeLayer.textItem.size;
|
||||||
|
colorArray = [0, 0, 0];
|
||||||
|
if(activeLayer.kind == LayerKind.TEXT){
|
||||||
|
if((activeLayer.textItem.contents != "")&&(start >= 0)&&(end <= activeLayer.textItem.contents.length)){
|
||||||
|
var idsetd = app.charIDToTypeID( "setd" );
|
||||||
|
var action = new ActionDescriptor();
|
||||||
|
var idnull = app.charIDToTypeID( "null" );
|
||||||
|
var reference = new ActionReference();
|
||||||
|
var idTxLr = app.charIDToTypeID( "TxLr" );
|
||||||
|
var idOrdn = app.charIDToTypeID( "Ordn" );
|
||||||
|
var idTrgt = app.charIDToTypeID( "Trgt" );
|
||||||
|
reference.putEnumerated( idTxLr, idOrdn, idTrgt );
|
||||||
|
action.putReference( idnull, reference );
|
||||||
|
var idT = app.charIDToTypeID( "T " );
|
||||||
|
var textAction = new ActionDescriptor();
|
||||||
|
var idTxtt = app.charIDToTypeID( "Txtt" );
|
||||||
|
var actionList = new ActionList();
|
||||||
|
var textRange = new ActionDescriptor();
|
||||||
|
var idFrom = app.charIDToTypeID( "From" );
|
||||||
|
textRange.putInteger( idFrom, start );
|
||||||
|
textRange.putInteger( idT, end );
|
||||||
|
var idTxtS = app.charIDToTypeID( "TxtS" );
|
||||||
|
var formatting = new ActionDescriptor();
|
||||||
|
var idFntN = app.charIDToTypeID( "FntN" );
|
||||||
|
formatting.putString( idFntN, fontName );
|
||||||
|
var idFntS = app.charIDToTypeID( "FntS" );
|
||||||
|
formatting.putString( idFntS, fontStyle );
|
||||||
|
var idSz = app.charIDToTypeID( "Sz " );
|
||||||
|
var idPnt = app.charIDToTypeID( "#Pnt" );
|
||||||
|
formatting.putUnitDouble( idSz, idPnt, fontSize );
|
||||||
|
var idClr = app.charIDToTypeID( "Clr " );
|
||||||
|
var colorAction = new ActionDescriptor();
|
||||||
|
var idRd = app.charIDToTypeID( "Rd " );
|
||||||
|
colorAction.putDouble( idRd, colorArray[0] );
|
||||||
|
var idGrn = app.charIDToTypeID( "Grn " );
|
||||||
|
colorAction.putDouble( idGrn, colorArray[1]);
|
||||||
|
var idBl = app.charIDToTypeID( "Bl " );
|
||||||
|
colorAction.putDouble( idBl, colorArray[2] );
|
||||||
|
var idRGBC = app.charIDToTypeID( "RGBC" );
|
||||||
|
formatting.putObject( idClr, idRGBC, colorAction );
|
||||||
|
textRange.putObject( idTxtS, idTxtS, formatting );
|
||||||
|
actionList.putObject( idTxtt, textRange );
|
||||||
|
textAction.putList( idTxtt, actionList );
|
||||||
|
action.putObject( idT, idTxLr, textAction );
|
||||||
|
app.executeAction( idsetd, action, DialogModes.NO );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
scripts/moveLayer.jsx
Normal file
11
scripts/moveLayer.jsx
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#include lib.js
|
||||||
|
var stdout = newFile(arguments[0]);
|
||||||
|
var lyr = eval(arguments[1]);
|
||||||
|
lyr.translate((Number)(arguments[2]), (Number)(arguments[3]));
|
||||||
|
if (lyr.typename == 'LayerSet') {
|
||||||
|
lyr.merge()
|
||||||
|
lyr=eval(arguments[4])
|
||||||
|
Undo();
|
||||||
|
}
|
||||||
|
stdout.writeln('{' + bounds(lyr) + '}')
|
||||||
|
stdout.close();
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
' Close Photoshop
|
' Close Photoshop
|
||||||
Set appRef = CreateObject("Photoshop.Application")
|
Set appRef = CreateObject("Photoshop.Application")
|
||||||
|
|
||||||
wScript.echo appRef.Documents.Count
|
|
||||||
Do While appRef.Documents.Count > 0
|
Do While appRef.Documents.Count > 0
|
||||||
appRef.ActiveDocument.Close(2)
|
appRef.ActiveDocument.Close(CInt(wScript.Arguments(0)))
|
||||||
Loop
|
Loop
|
||||||
|
|
||||||
appRef.Quit()
|
appRef.Quit()
|
||||||
12
scripts/save.vbs
Normal file
12
scripts/save.vbs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
Set appRef = CreateObject("Photoshop.Application")
|
||||||
|
dlgMode = 3 'No dialog
|
||||||
|
set d = CreateObject( "Photoshop.ActionDescriptor" )
|
||||||
|
Call d.PutEnumerated(appRef.CharIDToTypeID("PGIT"), appRef.CharIDToTypeID("PGIT"), appRef.CharIDToTypeID("PGIN"))
|
||||||
|
Call d.PutEnumerated(appRef.CharIDToTypeID("PNGf"), appRef.CharIDToTypeID("PNGf"), appRef.CharIDToTypeID("PGAd"))
|
||||||
|
|
||||||
|
SET desc = CreateObject( "Photoshop.ActionDescriptor" )
|
||||||
|
Call desc.PutObject( appRef.CharIDToTypeID("As "), appRef.CharIDToTypeID("PNGF"), d)
|
||||||
|
Call desc.PutPath( appRef.CharIDToTypeID("In "), wScript.Arguments(0))
|
||||||
|
Call desc.PutBoolean( appRef.CharIDToTypeID("Cpy "), True )
|
||||||
|
|
||||||
|
Call appRef.ExecuteAction(appRef.CharIDToTypeID("save"), desc, dlgMode)
|
||||||
13
scripts/test.jsx
Normal file
13
scripts/test.jsx
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#include lib.js
|
||||||
|
|
||||||
|
// var saveFile = File(arguments[0]);
|
||||||
|
var arg = 'app.activeDocument.layerSets.getByName("ResolveGem");';
|
||||||
|
var set = eval(arg);
|
||||||
|
set.visible=false;
|
||||||
|
alert(set.visible)
|
||||||
|
// var doc=app.activeDocument
|
||||||
|
// doc.layerSets.getByName("ResolveGem").merge();
|
||||||
|
// alert(doc.artLayers.getByName("ResolveGem").bounds);
|
||||||
|
// doc.activeHistoryState=doc.historyStates[doc.historyStates.length-2]
|
||||||
|
// setFormatting(0,6, "Arial", "Bold");
|
||||||
|
// saveFile.close();
|
||||||
3
scripts/test.vbs
Normal file
3
scripts/test.vbs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
for i=0 to wScript.Arguments.length-1
|
||||||
|
wScript.echo wScript.Arguments(i)
|
||||||
|
next
|
||||||
721
structs.go
Normal file
721
structs.go
Normal file
@@ -0,0 +1,721 @@
|
|||||||
|
// TODO: Count skipped steps.
|
||||||
|
package ps
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Group represents a Document or LayerSet.
|
||||||
|
type Group interface {
|
||||||
|
Name() string
|
||||||
|
Parent() Group
|
||||||
|
SetParent(Group)
|
||||||
|
Path() string
|
||||||
|
ArtLayers() []*ArtLayer
|
||||||
|
LayerSets() []*LayerSet
|
||||||
|
MarshalJSON() ([]byte, error)
|
||||||
|
UnmarshalJSON(b []byte) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
LayerSets []*LayerSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Document) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(&DocumentJSON{Name: d.name, Height: d.height,
|
||||||
|
Width: d.width, ArtLayers: d.artLayers, LayerSets: d.layerSets})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Document) UnmarshalJSON(b []byte) error {
|
||||||
|
tmp := &DocumentJSON{}
|
||||||
|
if err := json.Unmarshal(b, &tmp); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
d.name = tmp.Name
|
||||||
|
d.height = tmp.Height
|
||||||
|
d.width = tmp.Width
|
||||||
|
d.artLayers = tmp.ArtLayers
|
||||||
|
for _, lyr := range d.artLayers {
|
||||||
|
lyr.SetParent(d)
|
||||||
|
}
|
||||||
|
d.layerSets = tmp.LayerSets
|
||||||
|
for _, set := range d.layerSets {
|
||||||
|
set.SetParent(d)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns the document's title.
|
||||||
|
// This fufills the Group interface.
|
||||||
|
func (d *Document) Name() string {
|
||||||
|
return d.name
|
||||||
|
}
|
||||||
|
|
||||||
|
// The height of the document, in pixels.
|
||||||
|
func (d *Document) Height() int {
|
||||||
|
return d.height
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
if Mode != Fast && !set.current {
|
||||||
|
set.Refresh()
|
||||||
|
}
|
||||||
|
return set
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Document) Parent() Group {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (d *Document) SetParent(g Group) {}
|
||||||
|
|
||||||
|
func (d *Document) Path() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filename returns the path to the json file for this document.
|
||||||
|
func (d *Document) Filename() string {
|
||||||
|
_, dir, _, ok := runtime.Caller(0)
|
||||||
|
if !ok {
|
||||||
|
log.Panic("No caller information")
|
||||||
|
}
|
||||||
|
return filepath.Join(filepath.Dir(dir), "data",
|
||||||
|
strings.TrimRight(string(d.name), "\r\n")+".txt")
|
||||||
|
}
|
||||||
|
|
||||||
|
func ActiveDocument() (*Document, error) {
|
||||||
|
log.Println("Loading ActiveDoucment")
|
||||||
|
d := &Document{}
|
||||||
|
|
||||||
|
byt, err := DoJs("activeDocName.jsx")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
d.name = strings.TrimRight(string(byt), "\r\n")
|
||||||
|
if Mode != Safe {
|
||||||
|
byt, err = ioutil.ReadFile(d.Filename())
|
||||||
|
if err == nil {
|
||||||
|
log.Println("Previous version found, loading")
|
||||||
|
err = json.Unmarshal(byt, &d)
|
||||||
|
if err == nil {
|
||||||
|
return d, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Println("Loading manually (This could take awhile)")
|
||||||
|
byt, err = DoJs("getActiveDoc.jsx")
|
||||||
|
if err != nil {
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(byt, &d)
|
||||||
|
if err != nil {
|
||||||
|
d.Dump()
|
||||||
|
fmt.Println(string(byt))
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
for _, lyr := range d.artLayers {
|
||||||
|
lyr.SetParent(d)
|
||||||
|
}
|
||||||
|
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.Dump()
|
||||||
|
return d, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Document) Dump() {
|
||||||
|
log.Println("Dumping to disk")
|
||||||
|
f, err := os.Create(d.Filename())
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
byt, err := json.MarshalIndent(d, "", "\t")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
f.Write(byt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ArtLayer reflects certain values from an Art Layer in a Photoshop document.
|
||||||
|
// TODO: Make TextLayer a subclass of ArtLayer
|
||||||
|
type ArtLayer struct {
|
||||||
|
name string // The layer's name.
|
||||||
|
Text *string // The contents of a text layer.
|
||||||
|
bounds [2][2]int // The layers' corners.
|
||||||
|
parent Group // The LayerSet/Document this layer is in.
|
||||||
|
visible bool // Whether or not the layer is visible.
|
||||||
|
current bool // Whether we've checked this layer since we loaded from disk.
|
||||||
|
Color // The layer's color overlay.
|
||||||
|
*Stroke // The layer's stroke.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bounds returns the furthest corners of the ArtLayer.
|
||||||
|
func (a *ArtLayer) Bounds() [2][2]int {
|
||||||
|
return a.bounds
|
||||||
|
}
|
||||||
|
|
||||||
|
// ArtLayerJSON is a bridge between the ArtLayer struct and
|
||||||
|
// the encoding/json package, allowing ArtLayer's unexported fields
|
||||||
|
// to ber written to and read from by the json package.
|
||||||
|
type ArtLayerJSON struct {
|
||||||
|
Name string
|
||||||
|
Bounds [2][2]int
|
||||||
|
Visible bool
|
||||||
|
Color [3]int
|
||||||
|
Stroke [3]int
|
||||||
|
StrokeAmt float32
|
||||||
|
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
|
||||||
|
// saved to disk in JSON format.
|
||||||
|
func (a *ArtLayer) MarshalJSON() ([]byte, error) {
|
||||||
|
// txt := strings.Replace(*a.Text, "\r", "\\r", -1)
|
||||||
|
return json.Marshal(&ArtLayerJSON{
|
||||||
|
Name: a.name,
|
||||||
|
Bounds: a.bounds,
|
||||||
|
Visible: a.visible,
|
||||||
|
Color: a.Color.RGB(),
|
||||||
|
Stroke: a.Stroke.RGB(),
|
||||||
|
StrokeAmt: a.Stroke.Size,
|
||||||
|
Text: a.Text,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ArtLayer) UnmarshalJSON(b []byte) error {
|
||||||
|
tmp := &ArtLayerJSON{}
|
||||||
|
if err := json.Unmarshal(b, &tmp); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
a.name = tmp.Name
|
||||||
|
a.bounds = tmp.Bounds
|
||||||
|
a.Color = RGB{tmp.Color[0], tmp.Color[1], tmp.Color[2]}
|
||||||
|
a.Stroke = &Stroke{tmp.StrokeAmt, RGB{tmp.Stroke[0], tmp.Stroke[1], tmp.Stroke[2]}}
|
||||||
|
a.visible = tmp.Visible
|
||||||
|
if tmp.Text != nil {
|
||||||
|
// s := strings.Replace(*tmp.Text, "\\r", "\r", -1)
|
||||||
|
a.Text = tmp.Text
|
||||||
|
}
|
||||||
|
a.current = false
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ArtLayer) Name() string {
|
||||||
|
return a.name
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetActive makes this layer active in Photoshop.
|
||||||
|
// Layers need to be active to perform certain operations
|
||||||
|
func (a *ArtLayer) SetActive() ([]byte, error) {
|
||||||
|
js := fmt.Sprintf("app.activeDocument.activeLayer=%s", JSLayer(a.Path()))
|
||||||
|
return DoJs("compilejs.jsx", js)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetColor creates a color overlay for the layer
|
||||||
|
func (a *ArtLayer) SetColor(c Color) {
|
||||||
|
if a.Color.RGB() == c.RGB() {
|
||||||
|
if Mode == 2 || (Mode == 0 && a.current) {
|
||||||
|
// log.Println("Skipping color: already set.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if a.Stroke.Size != 0 {
|
||||||
|
a.SetStroke(*a.Stroke, c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
a.Color = c
|
||||||
|
cols := a.Color.RGB()
|
||||||
|
log.Printf(`Setting layer "%s" to color %v`, a.name, cols)
|
||||||
|
r := cols[0]
|
||||||
|
g := cols[1]
|
||||||
|
b := cols[2]
|
||||||
|
byt, err := a.SetActive()
|
||||||
|
if len(byt) != 0 {
|
||||||
|
log.Println(string(byt), "err")
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Println(a.Path())
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
byt, err = run("colorLayer", fmt.Sprint(r), fmt.Sprint(g), fmt.Sprint(b))
|
||||||
|
if len(byt) != 0 {
|
||||||
|
log.Println(string(byt), "err")
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ArtLayer) SetStroke(stk Stroke, fill Color) {
|
||||||
|
if stk.Size == 0 {
|
||||||
|
a.Stroke = &stk
|
||||||
|
a.SetColor(fill)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if fill == nil {
|
||||||
|
fill = a.Color
|
||||||
|
}
|
||||||
|
if stk.Size == a.Stroke.Size && stk.Color.RGB() == a.Stroke.Color.RGB() {
|
||||||
|
if a.Color.RGB() == fill.RGB() {
|
||||||
|
if Mode == 2 || (Mode == 0 && a.current) {
|
||||||
|
// log.Println("Skipping stroke: already set.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
byt, err := a.SetActive()
|
||||||
|
if len(byt) != 0 {
|
||||||
|
log.Println(string(byt))
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
a.Stroke = &stk
|
||||||
|
a.Color = fill
|
||||||
|
stkCol := stk.Color.RGB()
|
||||||
|
col := fill.RGB()
|
||||||
|
log.Printf("Setting layer %s stroke to %.2fpt %v and color to %v\n", a.name, a.Stroke.Size,
|
||||||
|
a.Stroke.Color.RGB(), a.Color.RGB())
|
||||||
|
byt, err = run("colorStroke", fmt.Sprint(col[0]), fmt.Sprint(col[1]), fmt.Sprint(col[2]),
|
||||||
|
fmt.Sprintf("%.2f", stk.Size), fmt.Sprint(stkCol[0]), fmt.Sprint(stkCol[1]), fmt.Sprint(stkCol[2]))
|
||||||
|
if len(byt) != 0 {
|
||||||
|
log.Println(string(byt))
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ArtLayer) Parent() Group {
|
||||||
|
return a.parent
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ArtLayer) Path() string {
|
||||||
|
return fmt.Sprintf("%s%s", a.parent.Path(), a.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ArtLayer) Format(start, end int, font, style string) {
|
||||||
|
if !a.Visible() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, err := DoJs("fmtText.jsx", fmt.Sprint(start), fmt.Sprint(end),
|
||||||
|
font, style)
|
||||||
|
if err != nil {
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Layer returns an ArtLayer from the active document given a specified
|
||||||
|
// path string.
|
||||||
|
func Layer(path string) (ArtLayer, error) {
|
||||||
|
byt, err := DoJs("getLayer.jsx", JSLayer(path))
|
||||||
|
var out ArtLayer
|
||||||
|
err = json.Unmarshal(byt, &out)
|
||||||
|
if err != nil {
|
||||||
|
return ArtLayer{}, err
|
||||||
|
}
|
||||||
|
return out, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetVisible makes the layer visible.
|
||||||
|
func (a *ArtLayer) SetVisible(b bool) {
|
||||||
|
if a.visible == b {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
a.visible = b
|
||||||
|
switch b {
|
||||||
|
case true:
|
||||||
|
log.Printf("Showing %s", a.name)
|
||||||
|
case false:
|
||||||
|
log.Printf("Hiding %s", a.name)
|
||||||
|
}
|
||||||
|
js := fmt.Sprintf("%s.visible=%v;",
|
||||||
|
strings.TrimRight(JSLayer(a.Path()), ";"), b)
|
||||||
|
DoJs("compilejs.jsx", js)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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: Test TR and BR
|
||||||
|
func (a *ArtLayer) SetPos(x, y int, bound string) {
|
||||||
|
if !a.visible || (x == 0 && y == 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var lyrX, lyrY int
|
||||||
|
switch bound[:1] {
|
||||||
|
case "B":
|
||||||
|
lyrY = a.Y2()
|
||||||
|
case "T":
|
||||||
|
fallthrough
|
||||||
|
default:
|
||||||
|
lyrY = a.Y1()
|
||||||
|
}
|
||||||
|
switch bound[1:] {
|
||||||
|
case "R":
|
||||||
|
lyrX = a.X2()
|
||||||
|
case "L":
|
||||||
|
fallthrough
|
||||||
|
default:
|
||||||
|
lyrX = a.X1()
|
||||||
|
}
|
||||||
|
byt, err := DoJs("moveLayer.jsx", JSLayer(a.Path()), fmt.Sprint(x-lyrX), fmt.Sprint(y-lyrY))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
var lyr ArtLayer
|
||||||
|
err = json.Unmarshal(byt, &lyr)
|
||||||
|
if err != nil {
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
a.bounds = lyr.bounds
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ArtLayer) Refresh() error {
|
||||||
|
tmp, err := Layer(a.Path())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
tmp.SetParent(a.Parent())
|
||||||
|
a.name = tmp.name
|
||||||
|
a.bounds = tmp.bounds
|
||||||
|
a.Text = tmp.Text
|
||||||
|
a.parent = tmp.Parent()
|
||||||
|
a.visible = tmp.visible
|
||||||
|
a.current = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type LayerSet struct {
|
||||||
|
name string
|
||||||
|
bounds [2][2]int
|
||||||
|
parent Group
|
||||||
|
current bool // Whether we've checked this layer since we loaded from disk.
|
||||||
|
visible bool
|
||||||
|
artLayers []*ArtLayer
|
||||||
|
layerSets []*LayerSet
|
||||||
|
}
|
||||||
|
|
||||||
|
type LayerSetJSON struct {
|
||||||
|
Name string
|
||||||
|
Bounds [2][2]int
|
||||||
|
Visible bool
|
||||||
|
ArtLayers []*ArtLayer
|
||||||
|
LayerSets []*LayerSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LayerSet) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(&LayerSetJSON{
|
||||||
|
Name: l.name,
|
||||||
|
Bounds: l.bounds,
|
||||||
|
Visible: l.visible,
|
||||||
|
ArtLayers: l.artLayers,
|
||||||
|
LayerSets: l.layerSets,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LayerSet) UnmarshalJSON(b []byte) error {
|
||||||
|
tmp := &LayerSetJSON{}
|
||||||
|
if err := json.Unmarshal(b, &tmp); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
l.name = tmp.Name
|
||||||
|
l.bounds = tmp.Bounds
|
||||||
|
l.visible = tmp.Visible
|
||||||
|
l.artLayers = tmp.ArtLayers
|
||||||
|
for _, lyr := range l.artLayers {
|
||||||
|
lyr.SetParent(l)
|
||||||
|
}
|
||||||
|
l.layerSets = tmp.LayerSets
|
||||||
|
for _, set := range l.layerSets {
|
||||||
|
set.SetParent(l)
|
||||||
|
}
|
||||||
|
l.current = false
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LayerSet) Name() string {
|
||||||
|
return l.name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LayerSet) ArtLayers() []*ArtLayer {
|
||||||
|
if Mode != 2 {
|
||||||
|
for _, lyr := range l.artLayers {
|
||||||
|
if !lyr.current {
|
||||||
|
lyr.Refresh()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return l.artLayers
|
||||||
|
}
|
||||||
|
|
||||||
|
// ArtLayer returns the first top level ArtLayer matching
|
||||||
|
// the given name.
|
||||||
|
// TODO: Does funky things when passed invalid layername.
|
||||||
|
func (l *LayerSet) ArtLayer(name string) *ArtLayer {
|
||||||
|
for _, lyr := range l.artLayers {
|
||||||
|
if lyr.name == name {
|
||||||
|
if Mode == 0 && !lyr.current {
|
||||||
|
err := lyr.Refresh()
|
||||||
|
if err != nil {
|
||||||
|
l.Refresh()
|
||||||
|
err := lyr.Refresh()
|
||||||
|
if err != nil {
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lyr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// l.Refresh()
|
||||||
|
// for _, lyr := range l.artLayers {
|
||||||
|
// fmt.Println(lyr)
|
||||||
|
// }
|
||||||
|
lyr := l.ArtLayer(name)
|
||||||
|
fmt.Println(lyr)
|
||||||
|
if lyr == nil {
|
||||||
|
log.Panic(errors.New("Layer not found!"))
|
||||||
|
}
|
||||||
|
return lyr
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bounds returns the furthest corners of the LayerSet.
|
||||||
|
func (l *LayerSet) Bounds() [2][2]int {
|
||||||
|
return l.bounds
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LayerSet) SetParent(c Group) {
|
||||||
|
l.parent = c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LayerSet) Parent() Group {
|
||||||
|
return l.parent
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LayerSet) Path() string {
|
||||||
|
if l.parent == nil {
|
||||||
|
return l.name
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s%s/", l.parent.Path(), l.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLayerSet(path string, g Group) (*LayerSet, error) {
|
||||||
|
path = strings.Replace(path, "//", "/", -1)
|
||||||
|
byt, err := DoJs("getLayerSet.jsx", JSLayer(path))
|
||||||
|
if err != nil {
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
var out *LayerSet
|
||||||
|
err = json.Unmarshal(byt, &out)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(JSLayer(path))
|
||||||
|
log.Println(string(byt))
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
out.SetParent(g)
|
||||||
|
log.Printf("Loading ActiveDocument/%s\n", out.Path())
|
||||||
|
if err != nil {
|
||||||
|
return &LayerSet{}, err
|
||||||
|
}
|
||||||
|
for _, lyr := range out.artLayers {
|
||||||
|
lyr.SetParent(out)
|
||||||
|
}
|
||||||
|
for i, set := range out.layerSets {
|
||||||
|
s, err := NewLayerSet(fmt.Sprintf("%s%s/", path, set.Name()), out)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
out.layerSets[i] = s
|
||||||
|
s.SetParent(out)
|
||||||
|
}
|
||||||
|
out.current = true
|
||||||
|
return out, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LayerSet) Visible() bool {
|
||||||
|
return l.visible
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetVisible makes the LayerSet visible.
|
||||||
|
func (l *LayerSet) SetVisible(b bool) {
|
||||||
|
if l.visible == b {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
js := fmt.Sprintf("%s.visible=%v;", strings.TrimRight(
|
||||||
|
JSLayer(l.Path()), ";"), b)
|
||||||
|
DoJs("compilejs.jsx", js)
|
||||||
|
l.visible = b
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPos snaps the given layerset boundry to the given point.
|
||||||
|
// Valid options for bound are: "TL", "TR", "BL", "BR"
|
||||||
|
func (l *LayerSet) SetPos(x, y int, bound string) {
|
||||||
|
if !l.visible || (x == 0 && y == 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
byt, err := DoJs("LayerSetBounds.jsx", JSLayer(l.Path()),
|
||||||
|
JSLayer(l.Path(), true))
|
||||||
|
if err != nil {
|
||||||
|
log.Println(string(byt))
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
var bnds *[2][2]int
|
||||||
|
err = json.Unmarshal(byt, &bnds)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(string(byt))
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
l.bounds = *bnds
|
||||||
|
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]
|
||||||
|
}
|
||||||
|
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() {
|
||||||
|
var tmp *LayerSet
|
||||||
|
byt, err := DoJs("getLayerSet.jsx", JSLayer(l.Path()), JSLayer(l.Path(), true))
|
||||||
|
err = json.Unmarshal(byt, &tmp)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Error in LayerSet.Refresh() \"", string(byt), "\"", "for", l.Path())
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
tmp.SetParent(l.Parent())
|
||||||
|
for _, lyr := range l.artLayers {
|
||||||
|
err := lyr.Refresh()
|
||||||
|
if err != nil {
|
||||||
|
l.artLayers = tmp.artLayers
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, set := range l.layerSets {
|
||||||
|
set.Refresh()
|
||||||
|
}
|
||||||
|
l.name = tmp.name
|
||||||
|
l.bounds = tmp.bounds
|
||||||
|
l.visible = tmp.visible
|
||||||
|
l.current = true
|
||||||
|
}
|
||||||
10
win/dojs.vbs
10
win/dojs.vbs
@@ -1,10 +0,0 @@
|
|||||||
|
|
||||||
Dim app
|
|
||||||
Set app = CreateObject("Photoshop.Application")
|
|
||||||
if WScript.Arguments.Count = 0 then
|
|
||||||
WScript.Echo "Missing parameters"
|
|
||||||
else
|
|
||||||
path = wScript.Arguments(0)
|
|
||||||
folder = wScript.Arguments(1)
|
|
||||||
app.DoJavaScriptFile path, Array(Folder)
|
|
||||||
end if
|
|
||||||
11
win/test.jsx
11
win/test.jsx
@@ -1,11 +0,0 @@
|
|||||||
var Path = arguments[0];
|
|
||||||
alert(Path)
|
|
||||||
var saveFile = File(Path + "/test.txt");
|
|
||||||
|
|
||||||
if(saveFile.exists)
|
|
||||||
saveFile.remove();
|
|
||||||
|
|
||||||
saveFile.encoding = "UTF8";
|
|
||||||
saveFile.open("e", "TEXT", "????");
|
|
||||||
saveFile.writeln("Testing...");
|
|
||||||
saveFile.close();
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
Testing...
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
wScript.echo "Testing..."
|
|
||||||
Reference in New Issue
Block a user