├── .DS_Store
├── .appcast.xml
├── .gitignore
├── Angle.playground
├── Contents.swift
├── Resources
│ └── screen.png
├── contents.xcplayground
├── playground.xcworkspace
│ └── contents.xcworkspacedata
└── timeline.xctimeline
├── Angle.sketchplugin
└── Contents
│ ├── Resources
│ ├── icon.png
│ └── logo.png
│ └── Sketch
│ ├── apply.js
│ ├── manifest.json
│ ├── reset.js
│ ├── rotate.js
│ ├── symmetry.js
│ └── symmetry.js~HEAD
├── README.md
├── assets
├── .DS_Store
├── icon.png
└── logo.png
├── package-lock.json
├── package.json
├── src
├── Angle.js
├── CompositionAngle.js
├── CompressionRatio.js
├── Error.js
├── PixelDensity.js
├── ShapeAngle.js
├── SymbolicAngle.js
├── apply.js
├── manifest.json
├── reset.js
├── rotate.js
├── shared.js
└── symmetry.js
└── workspace.code-workspace
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MengTo/Angle-Sketch-Plugin/c5145c524a2a463611fbb0aa6312943a861c6992/.DS_Store
--------------------------------------------------------------------------------
/.appcast.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 | -
8 |
9 |
10 | -
11 |
12 |
13 | -
14 |
15 |
16 | -
17 |
18 |
19 | -
20 |
21 |
22 | -
23 |
24 |
25 | -
26 |
27 |
28 | -
29 |
30 |
31 | -
32 |
33 |
34 | -
35 |
36 |
37 | -
38 |
39 |
40 | -
41 |
42 |
43 | -
44 |
45 |
46 | -
47 |
48 |
49 | -
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Created by https://www.gitignore.io/api/node
4 |
5 | ### Node ###
6 | # Logs
7 | logs
8 | *.log
9 | npm-debug.log*
10 | yarn-debug.log*
11 | yarn-error.log*
12 |
13 | # Runtime data
14 | pids
15 | *.pid
16 | *.seed
17 | *.pid.lock
18 |
19 | # Directory for instrumented libs generated by jscoverage/JSCover
20 | lib-cov
21 |
22 | # Coverage directory used by tools like istanbul
23 | coverage
24 |
25 | # nyc test coverage
26 | .nyc_output
27 |
28 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
29 | .grunt
30 |
31 | # Bower dependency directory (https://bower.io/)
32 | bower_components
33 |
34 | # node-waf configuration
35 | .lock-wscript
36 |
37 | # Compiled binary addons (http://nodejs.org/api/addons.html)
38 | build/Release
39 |
40 | # Dependency directories
41 | node_modules/
42 | jspm_packages/
43 |
44 | # Typescript v1 declaration files
45 | typings/
46 |
47 | # Optional npm cache directory
48 | .npm
49 |
50 | # Optional eslint cache
51 | .eslintcache
52 |
53 | # Optional REPL history
54 | .node_repl_history
55 |
56 | # Output of 'npm pack'
57 | *.tgz
58 |
59 | # Yarn Integrity file
60 | .yarn-integrity
61 |
62 | # dotenv environment variables file
63 | .env
64 |
65 |
66 |
67 | # End of https://www.gitignore.io/api/node
68 |
69 |
70 | # Created by https://www.gitignore.io/api/xcode
71 |
72 | ### Xcode ###
73 | # Xcode
74 | #
75 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
76 |
77 | ## Build generated
78 | build/
79 | DerivedData/
80 |
81 | ## Various settings
82 | *.pbxuser
83 | !default.pbxuser
84 | *.mode1v3
85 | !default.mode1v3
86 | *.mode2v3
87 | !default.mode2v3
88 | *.perspectivev3
89 | !default.perspectivev3
90 | xcuserdata/
91 |
92 | ## Other
93 | *.moved-aside
94 | *.xccheckout
95 | *.xcscmblueprint
96 |
97 | ### Xcode Patch ###
98 | *.xcodeproj/*
99 | !*.xcodeproj/project.pbxproj
100 | !*.xcodeproj/xcshareddata/
101 | !*.xcworkspace/contents.xcworkspacedata
102 | /*.gcno
103 |
104 |
105 | # End of https://www.gitignore.io/api/xcode
106 |
107 | Angle.sketchplugin
108 | .DS_Store
--------------------------------------------------------------------------------
/Angle.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | import CoreImage
2 | import AppKit
3 |
4 | let screenImage = #imageLiteral(resourceName: "screen.png")
5 | let screenTiff = screenImage.tiffRepresentation!
6 | let screenbitmap = NSBitmapImageRep(data: screenTiff)!
7 | let screen = CIImage(bitmapImageRep: screenbitmap)
8 |
9 | let rect = (
10 | topLeft: CGPoint(x: 1040.0, y: 1410.0 - 0.0),
11 | topRight: CGPoint(x: 1670.0, y: 1410.0 - 260.0),
12 | bottomRight: CGPoint(x: 650.0, y: 1410.0 - 1350.0),
13 | bottomLeft: CGPoint(x: 25.0, y: 1410.0 - 960.0)
14 | )
15 |
16 | let perspectiveTransform = CIFilter(name: "CIPerspectiveTransform")!
17 |
18 | perspectiveTransform.setValue(CIVector(cgPoint: rect.topLeft), forKey: "inputTopLeft")
19 | perspectiveTransform.setValue(CIVector(cgPoint: rect.topRight), forKey: "inputTopRight")
20 | perspectiveTransform.setValue(CIVector(cgPoint: rect.bottomRight), forKey: "inputBottomRight")
21 | perspectiveTransform.setValue(CIVector(cgPoint: rect.bottomLeft), forKey: "inputBottomLeft")
22 | perspectiveTransform.setValue(screen, forKey: "inputImage")
23 |
24 | perspectiveTransform.value(forKey: "outputImage")
25 |
26 | let representation = NSCIImageRep(ciImage: perspectiveTransform.outputImage!)
27 | let image = NSImage(size: representation.size)
28 | image.addRepresentation(representation)
29 |
--------------------------------------------------------------------------------
/Angle.playground/Resources/screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MengTo/Angle-Sketch-Plugin/c5145c524a2a463611fbb0aa6312943a861c6992/Angle.playground/Resources/screen.png
--------------------------------------------------------------------------------
/Angle.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Angle.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Angle.playground/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Angle.sketchplugin/Contents/Resources/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MengTo/Angle-Sketch-Plugin/c5145c524a2a463611fbb0aa6312943a861c6992/Angle.sketchplugin/Contents/Resources/icon.png
--------------------------------------------------------------------------------
/Angle.sketchplugin/Contents/Resources/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MengTo/Angle-Sketch-Plugin/c5145c524a2a463611fbb0aa6312943a861c6992/Angle.sketchplugin/Contents/Resources/logo.png
--------------------------------------------------------------------------------
/Angle.sketchplugin/Contents/Sketch/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "bundleVersion": 1,
3 | "version": "1.1.7",
4 | "icon": "icon.png",
5 | "identifier": "io.designcode.Angle",
6 | "description": "Important note: use version 1.1.7 for Sketch 86+, version 1.1.6 for Sketch 72-85, version 1.1.5 for Sketch 66-71 and version 1.1.4 for Sketch 65 and earlier. Apply perspective transforms on screen mockups. Auto-detect screens by resolution and works on shapes and symbols.",
7 | "homepage": "https://angle.sh",
8 | "author": "Design+Code",
9 | "authorEmail": "angle@designcode.io",
10 | "compatibleVersion": 50,
11 | "commands": [
12 | {
13 | "name": "Rotate Mockup",
14 | "identifier": "Angle-Rotate-Mockup",
15 | "script": "__rotate.js",
16 | "shortcut": "control \\"
17 | },
18 | {
19 | "name": "Flip Mockup",
20 | "identifier": "Angle-Rotate-Flip",
21 | "script": "__symmetry.js",
22 | "shortcut": "cmd shift \\"
23 | },
24 | {
25 | "name": "Apply Mockup",
26 | "identifier": "Angle-Apply-Mockup",
27 | "script": "__apply.js",
28 | "shortcut": "cmd \\"
29 | },
30 | {
31 | "name": "Reset Mockup",
32 | "identifier": "Angle-Reset-Metadata",
33 | "script": "__reset.js",
34 | "shortcut": "cmd control \\"
35 | }
36 | ],
37 | "menu": {
38 | "title": "Angle",
39 | "items": [
40 | "Angle-Apply-Mockup",
41 | "Angle-Rotate-Flip",
42 | "Angle-Rotate-Mockup",
43 | "Angle-Reset-Metadata"
44 | ]
45 | },
46 | "name": "Angle",
47 | "disableCocoaScriptPreprocessor": true,
48 | "appcast": "https://raw.githubusercontent.com/MengTo/Angle-Sketch-Plugin/master/.appcast.xml"
49 | }
--------------------------------------------------------------------------------
/Angle.sketchplugin/Contents/Sketch/reset.js:
--------------------------------------------------------------------------------
1 | var that = this;
2 | function __skpm_run(e, t) {
3 | that.context = t;
4 | var r = (function (e) {
5 | var t = {};
6 | function r(n) {
7 | if (t[n]) return t[n].exports;
8 | var o = (t[n] = { i: n, l: !1, exports: {} });
9 | return e[n].call(o.exports, o, o.exports, r), (o.l = !0), o.exports;
10 | }
11 | return (
12 | (r.m = e),
13 | (r.c = t),
14 | (r.d = function (e, t, n) {
15 | r.o(e, t) ||
16 | Object.defineProperty(e, t, {
17 | configurable: !1,
18 | enumerable: !0,
19 | get: n,
20 | });
21 | }),
22 | (r.n = function (e) {
23 | var t =
24 | e && e.__esModule
25 | ? function () {
26 | return e.default;
27 | }
28 | : function () {
29 | return e;
30 | };
31 | return r.d(t, "a", t), t;
32 | }),
33 | (r.o = function (e, t) {
34 | return Object.prototype.hasOwnProperty.call(e, t);
35 | }),
36 | (r.p = ""),
37 | r((r.s = 3))
38 | );
39 | })([
40 | function (e, r, n) {
41 | Object.defineProperty(r, "__esModule", { value: !0 });
42 | var o = (function () {
43 | function e(e, t) {
44 | for (var r = 0; r < t.length; r++) {
45 | var n = t[r];
46 | (n.enumerable = n.enumerable || !1),
47 | (n.configurable = !0),
48 | "value" in n && (n.writable = !0),
49 | Object.defineProperty(e, n.key, n);
50 | }
51 | }
52 | return function (t, r, n) {
53 | return r && e(t.prototype, r), n && e(t, n), t;
54 | };
55 | })(),
56 | i = n(4);
57 | function a(e) {
58 | if (Array.isArray(e)) {
59 | for (var t = 0, r = Array(e.length); t < e.length; t++) r[t] = e[t];
60 | return r;
61 | }
62 | return Array.from(e);
63 | }
64 | var s = { linear: 0, quadratic: 1, cubic: 2 };
65 | Array.prototype.rotated = function (e) {
66 | return this.slice(e, this.length).concat(this.slice(0, e));
67 | };
68 | var u = (function () {
69 | function e() {
70 | var t =
71 | arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
72 | !(function (e, t) {
73 | if (!(e instanceof t))
74 | throw new TypeError("Cannot call a class as a function");
75 | })(this, e),
76 | (this.context = t.context),
77 | (this.selectedLayer = t.selectedLayer);
78 | }
79 | return (
80 | o(e, [
81 | {
82 | key: "imprintValue_forKey",
83 | value: (function () {
84 | return function (e, t) {
85 | null != this.selectedLayer
86 | ? this.context.command.setValue_forKey_onLayer(
87 | e,
88 | t,
89 | this.selectedLayer
90 | )
91 | : print(
92 | "🛑 Imprinting value before selected layer assignment"
93 | );
94 | };
95 | })(),
96 | },
97 | {
98 | key: "loadValueForKey",
99 | value: (function () {
100 | return function (e) {
101 | return null == this.selectedLayer
102 | ? (print(
103 | "🛑 Loading value before selected layer assignment"
104 | ),
105 | null)
106 | : this.context.command.valueForKey_onLayer(
107 | e,
108 | this.selectedLayer
109 | );
110 | };
111 | })(),
112 | },
113 | {
114 | key: "artboardID",
115 | get: (function () {
116 | return function () {
117 | return void 0 != this._artboardID
118 | ? this._artboardID
119 | : ((this._artboardID =
120 | this.loadValueForKey("artboard-id") + ""),
121 | this._artboardID);
122 | };
123 | })(),
124 | set: (function () {
125 | return function (e) {};
126 | })(),
127 | },
128 | {
129 | key: "artboard",
130 | get: (function () {
131 | return function () {
132 | if (void 0 != this._artboard) return this._artboard;
133 | if (void 0 != this.artboardID) {
134 | for (
135 | var e = this.context.document.artboards(), t = 0;
136 | t < e.count();
137 | t++
138 | )
139 | e[t].objectID() == this.artboardID &&
140 | (this._artboard = e[t]);
141 | if (void 0 != this._artboard) return this._artboard;
142 | print(
143 | "🛑 Not able to retrieve artboard from id in document"
144 | );
145 | } else print("🛑 No artboard ID registered");
146 | };
147 | })(),
148 | set: (function () {
149 | return function (e) {
150 | (this._artboard = e),
151 | this.imprintValue_forKey(e.objectID(), "artboard-id");
152 | };
153 | })(),
154 | },
155 | {
156 | key: "rotation",
157 | get: (function () {
158 | return function () {
159 | return (
160 | void 0 == this._rotation &&
161 | (this._rotation = this.loadValueForKey("rotation")),
162 | this._rotation
163 | );
164 | };
165 | })(),
166 | set: (function () {
167 | return function (e) {
168 | (this._rotation = e), this.imprintValue_forKey(e, "rotation");
169 | };
170 | })(),
171 | },
172 | {
173 | key: "pixelDensity",
174 | get: (function () {
175 | return function () {
176 | if (
177 | (void 0 == this._pixelDensity &&
178 | (this._pixelDensity =
179 | this.loadValueForKey("pixel-density") + 0),
180 | 0 == this._pixelDensity)
181 | ) {
182 | var e = Math.round(2 * this.estimatePixelDensity() + 0.5);
183 | return 0 == e ? 1 : e;
184 | }
185 | return this._pixelDensity;
186 | };
187 | })(),
188 | set: (function () {
189 | return function (e) {
190 | (this._pixelDensity = e),
191 | this.imprintValue_forKey(e, "pixel-density");
192 | };
193 | })(),
194 | },
195 | {
196 | key: "compressionRatio",
197 | get: (function () {
198 | return function () {
199 | return (
200 | void 0 == this._compressionRatio &&
201 | (this._compressionRatio =
202 | this.loadValueForKey("compression-ratio") + 0),
203 | this._compressionRatio
204 | );
205 | };
206 | })(),
207 | set: (function () {
208 | return function (e) {
209 | (this._compressionRatio = e),
210 | this.imprintValue_forKey(e, "compression-ratio");
211 | };
212 | })(),
213 | },
214 | {
215 | key: "reversed",
216 | get: (function () {
217 | return function () {
218 | return (
219 | void 0 == this._reversed &&
220 | (this._reversed = 1 == this.loadValueForKey("reversed")),
221 | this._reversed
222 | );
223 | };
224 | })(),
225 | set: (function () {
226 | return function (e) {
227 | (this._reversed = e), this.imprintValue_forKey(e, "reversed");
228 | };
229 | })(),
230 | },
231 | ]),
232 | o(e, [
233 | {
234 | key: "exportRequest_lessThan52",
235 | value: (function () {
236 | return function () {
237 | var e = NSClassFromString(
238 | "SketchModel.MSImmutableLayerAncestry"
239 | )
240 | .alloc()
241 | .initWithMutableLayer(t.selection[0]),
242 | r = MSExportFormat.formatWithScale_name_fileFormat(
243 | this.pixelDensity,
244 | "Angle",
245 | "png"
246 | );
247 | return MSExportRequest.exportRequestsFromLayerAncestry_exportFormats(
248 | e,
249 | [r]
250 | ).firstObject();
251 | };
252 | })(),
253 | },
254 | {
255 | key: "exporter",
256 | value: (function () {
257 | return function () {
258 | var e = this.context.document.colorSpace();
259 | if (BCSketchInfo.shared().metadata().appVersion < 52)
260 | return MSExporter.exporterForRequest_colorSpace(
261 | this.exportRequest_lessThan52(),
262 | e
263 | );
264 | var t = MSExportFormat.alloc().init();
265 | (t.fileFormat = "png"), (t.scale = this.pixelDensity);
266 | var r =
267 | MSExportRequest.exportRequestsFromExportableLayer_exportFormats_useIDForName(
268 | this.artboard,
269 | [t],
270 | !0
271 | ).firstObject();
272 | return MSExporter.exporterForRequest_colorSpace(r, e);
273 | };
274 | })(),
275 | },
276 | {
277 | key: "ciImage",
278 | value: (function () {
279 | return function () {
280 | var e = this.exporter().bitmapImageRep();
281 | return CIImage.alloc().initWithCGImage(e.CGImage());
282 | };
283 | })(),
284 | },
285 | {
286 | key: "guessRotationAndReversion",
287 | value: (function () {
288 | return function () {
289 | if (1 === this.loadValueForKey("guessed-rotation"))
290 | print(
291 | "⚠️ Angle has already guessed rotation and symmetry for this shape"
292 | );
293 | else {
294 | var e = this.verticesLengths,
295 | t = void 0;
296 | if (this.artboard.class() != MSSymbolMaster) {
297 | t = this.artboard.frame();
298 | var r = e[0] > e[1],
299 | n = t.width() > t.height();
300 | r && (print("🛑 HORIZONTAL"), this.rotate()),
301 | n &&
302 | (print("🛑 HAS HORIZONTAL ARTBOARD"), this.rotate());
303 | var o = this.pointsFromBezierPath,
304 | i = Math.min.apply(
305 | Math,
306 | a(
307 | o.map(function (e) {
308 | return e.y;
309 | })
310 | )
311 | ),
312 | s = o[this.mappedIndexFor(0)],
313 | u = o[this.mappedIndexFor(1)];
314 | s.y != i &&
315 | u.y != i &&
316 | (print("🛑 UPSIDE DOWN"), this.rotate(), this.rotate());
317 | var l = BCSketchInfo.shared().metadata().appVersion;
318 | if (l < 50 || l >= 52) {
319 | var c = this.shorlaceSum();
320 | c < 0
321 | ? (print("🛑 COUNTERCLOCKWISE"),
322 | this.reverseSymmetry())
323 | : c > 0
324 | ? print("🛑 CLOCKWISE")
325 | : print("🛑 UNDEFINED CHIRALITY");
326 | } else
327 | l < 52 &&
328 | (1 ===
329 | this.targetPath.contours().firstObject().isClockwise()
330 | ? (this.reverseSymmetry(), print("🛑 CLOCKWISE"))
331 | : print("🛑 COUNTERCLOCKWISE"),
332 | print("🛑 UNDEFINED CHIRALITY"));
333 | print(
334 | "🔄↔️ Angle has just guessed rotation and symmetry for this shape"
335 | ),
336 | this.imprintValue_forKey(!0, "guessed-rotation");
337 | }
338 | }
339 | };
340 | })(),
341 | },
342 | {
343 | key: "shorlaceSum",
344 | value: (function () {
345 | return function () {
346 | var e = this.pointsFromBezierPath,
347 | t = Math.max.apply(
348 | Math,
349 | a(
350 | e.map(function (e) {
351 | return e.y;
352 | })
353 | )
354 | );
355 | return Array.from({ length: 4 }, function (e, t) {
356 | return t;
357 | }).reduce(function (r, n) {
358 | return (
359 | r +
360 | (-e[n].x + e[(n + 1) % 4].x) *
361 | (2 * t - e[n].y - e[(n + 1) % 4].y)
362 | );
363 | }, 0);
364 | };
365 | })(),
366 | },
367 | {
368 | key: "maximumVerticesWidthAndHeight",
369 | value: (function () {
370 | return function () {
371 | var e = this.verticesLengths.rotated(this.rotation % 2);
372 | return [Math.max(e[0], e[2]), Math.max(e[1], e[3])];
373 | };
374 | })(),
375 | },
376 | {
377 | key: "rotate",
378 | value: (function () {
379 | return function () {
380 | this.rotation = (this.rotation + (this.reversed ? 1 : 3)) % 4;
381 | };
382 | })(),
383 | },
384 | {
385 | key: "reverseSymmetry",
386 | value: (function () {
387 | return function () {
388 | this.rotate(), (this.reversed = !this.reversed);
389 | };
390 | })(),
391 | },
392 | {
393 | key: "mappedIndexFor",
394 | value: (function () {
395 | return function (e) {
396 | return this.reversed
397 | ? [0, 3, 2, 1][(e + this.rotation) % 4]
398 | : (e + this.rotation) % 4;
399 | };
400 | })(),
401 | },
402 | {
403 | key: "lossyCompressionOfImage_atRate",
404 | value: (function () {
405 | return function (e, t) {
406 | var r = NSBitmapImageRep.alloc().initWithCIImage(e),
407 | n = NSMutableDictionary.dictionary();
408 | n.setObject_forKey(
409 | NSTIFFCompressionJPEG,
410 | NSImageCompressionMethod
411 | ),
412 | n.setObject_forKey(t, NSImageCompressionFactor),
413 | n.setObject_forKey(
414 | NSColor.whiteColor(),
415 | NSImageFallbackBackgroundColor
416 | );
417 | var o = r.representationUsingType_properties(
418 | NSJPEGFileType,
419 | n
420 | );
421 | return NSImage.alloc().initWithData(o);
422 | };
423 | })(),
424 | },
425 | {
426 | key: "pixelAccurateRepresentationOfImage",
427 | value: (function () {
428 | return function (e) {
429 | var t = NSCIImageRep.alloc().initWithCIImage(e),
430 | r = NSImage.alloc().initWithSize(t.size());
431 | return r.addRepresentation(t), r;
432 | };
433 | })(),
434 | },
435 | {
436 | key: "pointsAreValid_lessThan50",
437 | get: (function () {
438 | return function () {
439 | var e = this.pointsFromBezierPath;
440 | return null !== e && 7 === e.length;
441 | };
442 | })(),
443 | },
444 | {
445 | key: "pointsAreValid_lessThan52",
446 | get: (function () {
447 | return function () {
448 | var e = this.targetPath.contours().firstObject(),
449 | t = Array.fromNSArray(e.segments());
450 | return (
451 | null !== t &&
452 | 4 === t.length &&
453 | !t.some(function (e) {
454 | return e.segmentType() != s.linear;
455 | })
456 | );
457 | };
458 | })(),
459 | },
460 | {
461 | key: "pointsAreValid",
462 | get: (function () {
463 | return function () {
464 | var e = BCSketchInfo.shared().metadata().appVersion;
465 | if (e < 50) return this.pointsAreValid_lessThan50;
466 | if (e < 52) return this.pointsAreValid_lessThan52;
467 | var t = this.targetLayer.points();
468 | return (
469 | null !== t &&
470 | 4 === t.length &&
471 | !t.some(function (e) {
472 | return !e.isStraight();
473 | })
474 | );
475 | };
476 | })(),
477 | },
478 | {
479 | key: "pointsFromBezierPath",
480 | get: (function () {
481 | return function () {
482 | var e = this,
483 | t = BCSketchInfo.shared().metadata().appVersion;
484 | if (t < 50) {
485 | var r = this.targetPath.elementCount();
486 | return 7 != r
487 | ? null
488 | : Array.from({ length: r }, function (e, t) {
489 | return t;
490 | }).map(function (t) {
491 | var r = MOPointer.alloc().initWithValue_(
492 | CGPointMake(0, 0)
493 | );
494 | return (
495 | e.targetPath.elementAtIndex_associatedPoints_(t, r),
496 | r.value()
497 | );
498 | });
499 | }
500 | if (t < 52) {
501 | var n = this.targetPath.contours().firstObject();
502 | return Array.fromNSArray(n.segments()).map(function (e) {
503 | return e.endPoint1();
504 | });
505 | }
506 | var o = this.targetLayer.rect().size;
507 | return Array.fromNSArray(this.targetLayer.points())
508 | .map(function (e) {
509 | return e.point();
510 | })
511 | .map(function (e) {
512 | return {
513 | x: Number(e.x) * Number(o.width),
514 | y: Number(e.y) * Number(o.height),
515 | };
516 | });
517 | };
518 | })(),
519 | },
520 | {
521 | key: "verticesLengths",
522 | get: (function () {
523 | return function () {
524 | var e = this.pointsFromBezierPath;
525 | return Array.from({ length: 4 }, function (e, t) {
526 | return t;
527 | }).map(function (t) {
528 | var r = (t + 1) % 4,
529 | n = e[t].x - e[r].x,
530 | o = e[t].y - e[r].y;
531 | return Math.sqrt(Math.pow(n, 2) + Math.pow(o, 2));
532 | });
533 | };
534 | })(),
535 | },
536 | {
537 | key: "normalizedCIVectors",
538 | get: (function () {
539 | return function () {
540 | var e = this.pointsFromBezierPath,
541 | t = Math.max.apply(
542 | Math,
543 | a(
544 | e.map(function (e) {
545 | return e.y;
546 | })
547 | )
548 | ),
549 | r = this.pixelDensity;
550 | return e.map(function (e) {
551 | return CIVector.vectorWithX_Y(e.x * r, (t - e.y) * r);
552 | });
553 | };
554 | })(),
555 | },
556 | {
557 | key: "transformedImage",
558 | get: (function () {
559 | return function () {
560 | var e = this.normalizedCIVectors,
561 | t = CIFilter.filterWithName("CIPerspectiveTransform");
562 | t.setValue_forKey(e[this.mappedIndexFor(0)], "inputTopLeft"),
563 | t.setValue_forKey(
564 | e[this.mappedIndexFor(1)],
565 | "inputTopRight"
566 | ),
567 | t.setValue_forKey(
568 | e[this.mappedIndexFor(2)],
569 | "inputBottomRight"
570 | ),
571 | t.setValue_forKey(
572 | e[this.mappedIndexFor(3)],
573 | "inputBottomLeft"
574 | );
575 | var r = this.ciImage();
576 | t.setValue_forKey(r, "inputImage");
577 | var n = t.valueForKey("outputImage");
578 | if (n) {
579 | var o = void 0,
580 | a = i.CompressionRatio[this.compressionRatio].ratio;
581 | return (
582 | (o =
583 | 1 != a
584 | ? this.lossyCompressionOfImage_atRate(n, a)
585 | : this.pixelAccurateRepresentationOfImage(n)),
586 | BCSketchInfo.shared().metadata().appVersion < 47
587 | ? MSImageData.alloc().initWithImage_convertColorSpace(
588 | o,
589 | !0
590 | )
591 | : MSImageData.alloc().initWithImage_(o)
592 | );
593 | }
594 | print("🛑 Unable to form perspective image");
595 | };
596 | })(),
597 | },
598 | ]),
599 | e
600 | );
601 | })();
602 | r.default = u;
603 | },
604 | function (e, t) {
605 | Object.defineProperty(t, "__esModule", { value: !0 });
606 | t.Error = {
607 | unsupportedSymbol: {
608 | message: "This does not seem to be a supported symbol.",
609 | },
610 | unsupportedShapePath: {
611 | message:
612 | "There seems to be an issue with the shape we are trying to apply.",
613 | },
614 | emptySelection: {
615 | message: "Please, select a Shape, Angle Mockup or Angle Composition",
616 | },
617 | unsupportedElement: {
618 | message: "Please, select a Shape, Angle Mockup or Angle Composition",
619 | },
620 | noImageOverrideOnSymbol: {
621 | message: "There is no image override for the selected symbol",
622 | },
623 | symbolWithBitMapLayer: {
624 | message: "Bitmat overrides are not supported",
625 | },
626 | };
627 | },
628 | function (e, t, r) {
629 | Object.defineProperty(t, "__esModule", { value: !0 });
630 | var n,
631 | o = (function () {
632 | return function (e, t) {
633 | if (Array.isArray(e)) return e;
634 | if (Symbol.iterator in Object(e))
635 | return (function (e, t) {
636 | var r = [],
637 | n = !0,
638 | o = !1,
639 | i = void 0;
640 | try {
641 | for (
642 | var a, s = e[Symbol.iterator]();
643 | !(n = (a = s.next()).done) &&
644 | (r.push(a.value), !t || r.length !== t);
645 | n = !0
646 | );
647 | } catch (e) {
648 | (o = !0), (i = e);
649 | } finally {
650 | try {
651 | !n && s.return && s.return();
652 | } finally {
653 | if (o) throw i;
654 | }
655 | }
656 | return r;
657 | })(e, t);
658 | throw new TypeError(
659 | "Invalid attempt to destructure non-iterable instance"
660 | );
661 | };
662 | })(),
663 | i = (function () {
664 | function e(e, t) {
665 | for (var r = 0; r < t.length; r++) {
666 | var n = t[r];
667 | (n.enumerable = n.enumerable || !1),
668 | (n.configurable = !0),
669 | "value" in n && (n.writable = !0),
670 | Object.defineProperty(e, n.key, n);
671 | }
672 | }
673 | return function (t, r, n) {
674 | return r && e(t.prototype, r), n && e(t, n), t;
675 | };
676 | })(),
677 | a = r(0),
678 | s = (n = a) && n.__esModule ? n : { default: n },
679 | u = r(1);
680 | function l(e, t) {
681 | if (!e)
682 | throw new ReferenceError(
683 | "this hasn't been initialised - super() hasn't been called"
684 | );
685 | return !t || ("object" != typeof t && "function" != typeof t) ? e : t;
686 | }
687 | var c = (function (e) {
688 | function t() {
689 | var e =
690 | arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
691 | !(function (e, t) {
692 | if (!(e instanceof t))
693 | throw new TypeError("Cannot call a class as a function");
694 | })(this, t);
695 | var r = l(
696 | this,
697 | (t.__proto__ || Object.getPrototypeOf(t)).call(this, e)
698 | );
699 | if (
700 | ((r.targetLayer = e.override.affectedLayer()),
701 | r.targetLayer.class() === MSImmutableBitmapLayer)
702 | )
703 | return l(r, u.Error.symbolWithBitMapLayer);
704 | var n = BCSketchInfo.shared().metadata().appVersion;
705 | n < 50
706 | ? (r.targetPath = e.override.affectedLayer().bezierPath())
707 | : n < 52 &&
708 | (r.targetPath = e.override
709 | .affectedLayer()
710 | .pathInFrameWithTransforms());
711 | var o = e.override.overridePoint().parent();
712 | return (
713 | null !== o && (r.overrideLayer = o),
714 | r.pointsAreValid ? r : l(r, u.Error.unsupportedShapePath)
715 | );
716 | }
717 | return (
718 | (function (e, t) {
719 | if ("function" != typeof t && null !== t)
720 | throw new TypeError(
721 | "Super expression must either be null or a function, not " +
722 | typeof t
723 | );
724 | (e.prototype = Object.create(t && t.prototype, {
725 | constructor: {
726 | value: e,
727 | enumerable: !1,
728 | writable: !0,
729 | configurable: !0,
730 | },
731 | })),
732 | t &&
733 | (Object.setPrototypeOf
734 | ? Object.setPrototypeOf(e, t)
735 | : (e.__proto__ = t));
736 | })(t, s["default"]),
737 | i(t, [
738 | {
739 | key: "applyImage",
740 | value: (function () {
741 | return function () {
742 | var e = this.targetLayer.objectID(),
743 | t =
744 | this.selectedLayer.overrides() ||
745 | NSDictionary.dictionary(),
746 | r = NSMutableDictionary.dictionaryWithDictionary(t);
747 | r.setObject_forKey(this.transformedImage, e),
748 | (this.selectedLayer.overrides = r);
749 | };
750 | })(),
751 | },
752 | {
753 | key: "estimatePixelDensity",
754 | value: (function () {
755 | return function () {
756 | var e = this.maximumVerticesWidthAndHeight(),
757 | t = o(e, 2),
758 | r = t[0],
759 | n = t[1],
760 | i =
761 | (this.selectedLayer.rect().size.width * r) /
762 | (this.selectedLayer.naturalSize().width *
763 | this.artboard.rect().size.width),
764 | a =
765 | (this.selectedLayer.rect().size.height * n) /
766 | (this.selectedLayer.naturalSize().height *
767 | this.artboard.rect().size.height);
768 | return i > a ? i : a;
769 | };
770 | })(),
771 | },
772 | {
773 | key: "description",
774 | value: (function () {
775 | return function () {
776 | return (
777 | this.selectedLayer.name() + " " + this.targetLayer.name()
778 | );
779 | };
780 | })(),
781 | },
782 | ]),
783 | t
784 | );
785 | })();
786 | t.default = c;
787 | },
788 | function (e, r, n) {
789 | Object.defineProperty(r, "__esModule", { value: !0 }),
790 | (r.default = function (e) {
791 | var r = e.document,
792 | n = e.selection,
793 | o = e.command;
794 | if (void 0 != n && 1 == n.count()) {
795 | var i = n.firstObject();
796 | a.default.tryCreating({
797 | for: [i],
798 | in: { document: r, selection: n, command: o },
799 | }) instanceof a.default
800 | ? (t.command.setValue_forKey_onLayer(null, "pixel-density", i),
801 | t.command.setValue_forKey_onLayer(null, "rotation", i),
802 | t.command.setValue_forKey_onLayer(null, "artboard-id", i),
803 | t.command.setValue_forKey_onLayer(null, "compression-ratio", i),
804 | t.command.setValue_forKey_onLayer(null, "reversed", i),
805 | t.command.setValue_forKey_onLayer(null, "guessed-rotation", i),
806 | s.show({
807 | message: "Angle Mockup metadata reset.",
808 | inDocument: r,
809 | }))
810 | : s.show({
811 | message: "Reset only works on shapes and symbols.",
812 | inDocument: r,
813 | });
814 | } else
815 | s.show({
816 | message: "Please, select 1️⃣ element to reset",
817 | inDocument: r,
818 | });
819 | });
820 | var o,
821 | i = n(0),
822 | a = (o = i) && o.__esModule ? o : { default: o },
823 | s = (function (e) {
824 | if (e && e.__esModule) return e;
825 | var t = {};
826 | if (null != e)
827 | for (var r in e)
828 | Object.prototype.hasOwnProperty.call(e, r) && (t[r] = e[r]);
829 | return (t.default = e), t;
830 | })(n(5));
831 | },
832 | function (e, t) {
833 | Object.defineProperty(t, "__esModule", { value: !0 });
834 | t.CompressionRatio = [
835 | { selectionLabel: "Best", ratio: 1 },
836 | { selectionLabel: "Better", ratio: 0.9 },
837 | { selectionLabel: "Good", ratio: 0.8 },
838 | { selectionLabel: "Average", ratio: 0.7 },
839 | ];
840 | },
841 | function (e, t, r) {
842 | Object.defineProperty(t, "__esModule", { value: !0 }),
843 | (t.show = function (e) {
844 | var t = e.message,
845 | r = e.inDocument;
846 | void 0 != r && void 0 != r.showMessage && r.showMessage(t);
847 | print(t);
848 | }),
849 | (t.filterPossibleArtboards = function (e) {
850 | var t = e.class();
851 | switch (t) {
852 | case MSArtboardGroup:
853 | var r = e,
854 | n = r.frame();
855 | if (n.width() < 250 || n.height() < 250) return !1;
856 | var o = n.width() / n.height();
857 | if ((o > 1 && (o = 1 / o), o < 0.4)) return !1;
858 | break;
859 | case MSSymbolMaster:
860 | return !1;
861 | default:
862 | return print(t), !1;
863 | }
864 | return !0;
865 | }),
866 | (t.compareByRatioAndAlphabet = function (e, t) {
867 | var r = e.frame(),
868 | n = t.frame(),
869 | o = r.width() / r.height();
870 | o > 1 && (o = 1 / o);
871 | var i = o > 0.4 && o < 0.8,
872 | a = n.width() / n.height();
873 | a > 1 && (a = 1 / a);
874 | var s = a > 0.4 && a < 0.8;
875 | if (i && !s) return !1;
876 | if (s && !i) return !0;
877 | if (o == a) return e.name() > t.name();
878 | return o > a;
879 | }),
880 | (t.introspect = function (e) {
881 | var t = e.class().mocha();
882 | print("-----------------------------------------------"),
883 | print("PROPERTIES-------------------------------------"),
884 | print("-----------------------------------------------"),
885 | print(t.properties()),
886 | print(t.propertiesWithAncestors()),
887 | print("-----------------------------------------------"),
888 | print("INSTANCE METHODS-------------------------------"),
889 | print("-----------------------------------------------"),
890 | print(t.instanceMethods()),
891 | print(t.instanceMethodsWithAncestors()),
892 | print("-----------------------------------------------"),
893 | print("CLASS METHODS----------------------------------"),
894 | print("-----------------------------------------------"),
895 | print(t.classMethods()),
896 | print(t.classMethodsWithAncestors()),
897 | print("-----------------------------------------------"),
898 | print("PROTOCOLS--------------------------------------"),
899 | print("-----------------------------------------------"),
900 | print(t.protocols()),
901 | print(t.protocolsWithAncestors());
902 | }),
903 | (t.createLabel = function (e, t, r) {
904 | var n = NSTextField.alloc().initWithFrame(r);
905 | return (
906 | n.setStringValue(e),
907 | n.setFont(NSFont.boldSystemFontOfSize(t)),
908 | n.setBezeled(!1),
909 | n.setDrawsBackground(!1),
910 | n.setEditable(!1),
911 | n.setSelectable(!1),
912 | n
913 | );
914 | }),
915 | (t.popUpButtonsforRectangleIndexer_withTitleIndexer_andImageIndexer_defaultSelected_onIndex =
916 | function (e, t, r, n) {
917 | var o = NSPopUpButton.alloc().initWithFrame(e(n));
918 | o.addItemsWithTitles(t),
919 | null != r &&
920 | ((o.imageScaling = NSImageScaleProportionallyUpOrDown),
921 | Array.fromNSArray(o.itemArray()).forEach(function (e, t, n) {
922 | e.image = r[t];
923 | }));
924 | return o;
925 | }),
926 | (t.smallImagesFromArtboard = function (e) {
927 | if (e.class() == MSSymbolMaster) return print(e), null;
928 | void 0 == e.frame && print(e);
929 | var t = e.frame().width(),
930 | r = e.frame().height(),
931 | n = t / r;
932 | n > 1 && (n = 1 / n);
933 | if (n > 0.8 || n < 0.4) return null;
934 | var o = NSClassFromString("SketchModel.MSImmutableLayerAncestry")
935 | .alloc()
936 | .initWithMutableLayer(e),
937 | i = 48 / (t > r ? t : r),
938 | a = MSExportFormat.formatWithScale_name_fileFormat(i, "", "png"),
939 | s = MSExportRequest.exportRequestsFromLayerAncestry_exportFormats(
940 | o,
941 | [a]
942 | ).firstObject();
943 | return MSExporter.exporterForRequest_colorSpace(
944 | s,
945 | NSColorSpace.sRGBColorSpace()
946 | ).previewImage();
947 | });
948 | var n = u(r(0)),
949 | o = u(r(6)),
950 | i = u(r(2)),
951 | a = u(r(7)),
952 | s = r(1);
953 | function u(e) {
954 | return e && e.__esModule ? e : { default: e };
955 | }
956 | (n.default.tryCreating = function (e) {
957 | var t = e.for,
958 | r = e.in;
959 | return t
960 | .map(function (e) {
961 | switch (e.class()) {
962 | case MSSymbolInstance:
963 | var t = Array.fromNSArray(e.availableOverrides()) || [],
964 | n = t
965 | .filter(function (e) {
966 | return e.currentValue().class() == MSImageData;
967 | })
968 | .map(function (t) {
969 | return new i.default({
970 | selectedLayer: e,
971 | context: r,
972 | override: t,
973 | });
974 | }),
975 | u = t
976 | .map(function (e) {
977 | return e.children();
978 | })
979 | .filter(function (e) {
980 | return null != e;
981 | })
982 | .map(Array.fromNSArray)
983 | .reduce(function (e, t) {
984 | return e.concat(t);
985 | }, [])
986 | .filter(function (e) {
987 | return e.class() == MSAvailableOverride;
988 | })
989 | .map(function (t) {
990 | return new o.default({
991 | override: t,
992 | selectedLayer: e,
993 | context: r,
994 | });
995 | });
996 | return n.concat(u);
997 | case MSShapeGroup:
998 | case MSShapePathLayer:
999 | case MSRectangleShape:
1000 | return new a.default({ selectedLayer: e, context: r });
1001 | default:
1002 | return s.Error.unsupportedElement;
1003 | }
1004 | })
1005 | .reduce(function (e, t, r, n) {
1006 | return e.concat(t);
1007 | }, []);
1008 | }),
1009 | (Array.fromNSArray = function (e) {
1010 | for (var t = [], r = 0; r < e.length; r++) t.push(e[r]);
1011 | return t;
1012 | }),
1013 | (Array.prototype.print = function () {
1014 | return this.map(function (e) {
1015 | return print(e), e;
1016 | });
1017 | });
1018 | },
1019 | function (e, t, r) {
1020 | Object.defineProperty(t, "__esModule", { value: !0 });
1021 | var n,
1022 | o = (function () {
1023 | function e(e, t) {
1024 | for (var r = 0; r < t.length; r++) {
1025 | var n = t[r];
1026 | (n.enumerable = n.enumerable || !1),
1027 | (n.configurable = !0),
1028 | "value" in n && (n.writable = !0),
1029 | Object.defineProperty(e, n.key, n);
1030 | }
1031 | }
1032 | return function (t, r, n) {
1033 | return r && e(t.prototype, r), n && e(t, n), t;
1034 | };
1035 | })(),
1036 | i = (function () {
1037 | return function e(t, r, n) {
1038 | null === t && (t = Function.prototype);
1039 | var o = Object.getOwnPropertyDescriptor(t, r);
1040 | if (void 0 === o) {
1041 | var i = Object.getPrototypeOf(t);
1042 | return null === i ? void 0 : e(i, r, n);
1043 | }
1044 | if ("value" in o) return o.value;
1045 | var a = o.get;
1046 | return void 0 !== a ? a.call(n) : void 0;
1047 | };
1048 | })(),
1049 | a = r(2),
1050 | s = (n = a) && n.__esModule ? n : { default: n };
1051 | r(1);
1052 | var u = (function (e) {
1053 | function t() {
1054 | var e =
1055 | arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
1056 | !(function (e, t) {
1057 | if (!(e instanceof t))
1058 | throw new TypeError("Cannot call a class as a function");
1059 | })(this, t);
1060 | var r = (function (e, t) {
1061 | if (!e)
1062 | throw new ReferenceError(
1063 | "this hasn't been initialised - super() hasn't been called"
1064 | );
1065 | return !t || ("object" != typeof t && "function" != typeof t)
1066 | ? e
1067 | : t;
1068 | })(this, (t.__proto__ || Object.getPrototypeOf(t)).call(this, e));
1069 | return (r.override = e.override), r;
1070 | }
1071 | return (
1072 | (function (e, t) {
1073 | if ("function" != typeof t && null !== t)
1074 | throw new TypeError(
1075 | "Super expression must either be null or a function, not " +
1076 | typeof t
1077 | );
1078 | (e.prototype = Object.create(t && t.prototype, {
1079 | constructor: {
1080 | value: e,
1081 | enumerable: !1,
1082 | writable: !0,
1083 | configurable: !0,
1084 | },
1085 | })),
1086 | t &&
1087 | (Object.setPrototypeOf
1088 | ? Object.setPrototypeOf(e, t)
1089 | : (e.__proto__ = t));
1090 | })(t, s["default"]),
1091 | o(t, [
1092 | {
1093 | key: "loadValueForKey",
1094 | value: (function () {
1095 | return function (e) {
1096 | return i(
1097 | t.prototype.__proto__ || Object.getPrototypeOf(t.prototype),
1098 | "loadValueForKey",
1099 | this
1100 | ).call(this, this.targetLayer.objectID() + "-" + e);
1101 | };
1102 | })(),
1103 | },
1104 | {
1105 | key: "imprintValue_forKey",
1106 | value: (function () {
1107 | return function (e, r) {
1108 | i(
1109 | t.prototype.__proto__ || Object.getPrototypeOf(t.prototype),
1110 | "imprintValue_forKey",
1111 | this
1112 | ).call(this, e, this.targetLayer.objectID() + "-" + r);
1113 | };
1114 | })(),
1115 | },
1116 | {
1117 | key: "applyImage",
1118 | value: (function () {
1119 | return function () {
1120 | var e =
1121 | this.selectedLayer.overrides() ||
1122 | NSDictionary.dictionary(),
1123 | t = NSMutableDictionary.dictionaryWithDictionary(e),
1124 | r = (this.overrideLayer + "").replace("_symbolID", ""),
1125 | n = t.objectForKey(r) || NSMutableDictionary.dictionary(),
1126 | o = NSMutableDictionary.dictionaryWithDictionary(n),
1127 | i = this.targetLayer.objectID();
1128 | o.setObject_forKey(this.transformedImage, i),
1129 | t.setObject_forKey(o, r),
1130 | (this.selectedLayer.overrides = t);
1131 | };
1132 | })(),
1133 | },
1134 | {
1135 | key: "description",
1136 | value: (function () {
1137 | return function () {
1138 | return (
1139 | this.override.parent().affectedLayer().name() +
1140 | " " +
1141 | this.targetLayer.name()
1142 | );
1143 | };
1144 | })(),
1145 | },
1146 | ]),
1147 | t
1148 | );
1149 | })();
1150 | t.default = u;
1151 | },
1152 | function (e, t, r) {
1153 | Object.defineProperty(t, "__esModule", { value: !0 });
1154 | var n,
1155 | o = (function () {
1156 | return function (e, t) {
1157 | if (Array.isArray(e)) return e;
1158 | if (Symbol.iterator in Object(e))
1159 | return (function (e, t) {
1160 | var r = [],
1161 | n = !0,
1162 | o = !1,
1163 | i = void 0;
1164 | try {
1165 | for (
1166 | var a, s = e[Symbol.iterator]();
1167 | !(n = (a = s.next()).done) &&
1168 | (r.push(a.value), !t || r.length !== t);
1169 | n = !0
1170 | );
1171 | } catch (e) {
1172 | (o = !0), (i = e);
1173 | } finally {
1174 | try {
1175 | !n && s.return && s.return();
1176 | } finally {
1177 | if (o) throw i;
1178 | }
1179 | }
1180 | return r;
1181 | })(e, t);
1182 | throw new TypeError(
1183 | "Invalid attempt to destructure non-iterable instance"
1184 | );
1185 | };
1186 | })(),
1187 | i = (function () {
1188 | function e(e, t) {
1189 | for (var r = 0; r < t.length; r++) {
1190 | var n = t[r];
1191 | (n.enumerable = n.enumerable || !1),
1192 | (n.configurable = !0),
1193 | "value" in n && (n.writable = !0),
1194 | Object.defineProperty(e, n.key, n);
1195 | }
1196 | }
1197 | return function (t, r, n) {
1198 | return r && e(t.prototype, r), n && e(t, n), t;
1199 | };
1200 | })(),
1201 | a = r(0),
1202 | s = (n = a) && n.__esModule ? n : { default: n },
1203 | u = r(1);
1204 | function l(e, t) {
1205 | if (!e)
1206 | throw new ReferenceError(
1207 | "this hasn't been initialised - super() hasn't been called"
1208 | );
1209 | return !t || ("object" != typeof t && "function" != typeof t) ? e : t;
1210 | }
1211 | var c = { solid: 0, gradient: 1, pattern: 4, noise: 5 },
1212 | f = (function (e) {
1213 | function t() {
1214 | var e =
1215 | arguments.length > 0 && void 0 !== arguments[0]
1216 | ? arguments[0]
1217 | : {};
1218 | !(function (e, t) {
1219 | if (!(e instanceof t))
1220 | throw new TypeError("Cannot call a class as a function");
1221 | })(this, t);
1222 | var r = l(
1223 | this,
1224 | (t.__proto__ || Object.getPrototypeOf(t)).call(this, e)
1225 | );
1226 | r.targetLayer = r.selectedLayer;
1227 | var n = BCSketchInfo.shared().metadata().appVersion;
1228 | return (
1229 | n < 50
1230 | ? (r.targetPath = r.selectedLayer.bezierPath())
1231 | : n < 52 &&
1232 | (r.targetPath = r.selectedLayer.pathInFrameWithTransforms()),
1233 | r.pointsAreValid ? r : l(r, u.Error.unsupportedShapePath)
1234 | );
1235 | }
1236 | return (
1237 | (function (e, t) {
1238 | if ("function" != typeof t && null !== t)
1239 | throw new TypeError(
1240 | "Super expression must either be null or a function, not " +
1241 | typeof t
1242 | );
1243 | (e.prototype = Object.create(t && t.prototype, {
1244 | constructor: {
1245 | value: e,
1246 | enumerable: !1,
1247 | writable: !0,
1248 | configurable: !0,
1249 | },
1250 | })),
1251 | t &&
1252 | (Object.setPrototypeOf
1253 | ? Object.setPrototypeOf(e, t)
1254 | : (e.__proto__ = t));
1255 | })(t, s["default"]),
1256 | i(t, [
1257 | {
1258 | key: "applyImage",
1259 | value: (function () {
1260 | return function () {
1261 | var e = MSStyleFill.alloc().init();
1262 | e.setImage(this.transformedImage),
1263 | (e.fillType = c.pattern),
1264 | this.targetLayer.style().removeAllStyleFills(),
1265 | this.targetLayer.style().addStyleFill(e);
1266 | };
1267 | })(),
1268 | },
1269 | {
1270 | key: "estimatePixelDensity",
1271 | value: (function () {
1272 | return function () {
1273 | var e = this.maximumVerticesWidthAndHeight(),
1274 | t = o(e, 2),
1275 | r = t[0],
1276 | n = t[1],
1277 | i = r / this.artboard.rect().size.width,
1278 | a = n / this.artboard.rect().size.height;
1279 | return i > a ? i : a;
1280 | };
1281 | })(),
1282 | },
1283 | {
1284 | key: "description",
1285 | value: (function () {
1286 | return function () {
1287 | return this.targetLayer.name();
1288 | };
1289 | })(),
1290 | },
1291 | ]),
1292 | t
1293 | );
1294 | })();
1295 | t.default = f;
1296 | },
1297 | ]);
1298 | "default" === e && "function" == typeof r ? r(t) : r[e](t);
1299 | }
1300 | that.onRun = __skpm_run.bind(this, "default");
1301 |
--------------------------------------------------------------------------------
/Angle.sketchplugin/Contents/Sketch/rotate.js:
--------------------------------------------------------------------------------
1 | var that = this;
2 | function __skpm_run(e, t) {
3 | that.context = t;
4 | var r = (function (e) {
5 | var t = {};
6 | function r(n) {
7 | if (t[n]) return t[n].exports;
8 | var i = (t[n] = { i: n, l: !1, exports: {} });
9 | return e[n].call(i.exports, i, i.exports, r), (i.l = !0), i.exports;
10 | }
11 | return (
12 | (r.m = e),
13 | (r.c = t),
14 | (r.d = function (e, t, n) {
15 | r.o(e, t) ||
16 | Object.defineProperty(e, t, {
17 | configurable: !1,
18 | enumerable: !0,
19 | get: n,
20 | });
21 | }),
22 | (r.n = function (e) {
23 | var t =
24 | e && e.__esModule
25 | ? function () {
26 | return e.default;
27 | }
28 | : function () {
29 | return e;
30 | };
31 | return r.d(t, "a", t), t;
32 | }),
33 | (r.o = function (e, t) {
34 | return Object.prototype.hasOwnProperty.call(e, t);
35 | }),
36 | (r.p = ""),
37 | r((r.s = 3))
38 | );
39 | })([
40 | function (e, t) {
41 | Object.defineProperty(t, "__esModule", { value: !0 });
42 | t.Error = {
43 | unsupportedSymbol: {
44 | message: "This does not seem to be a supported symbol.",
45 | },
46 | unsupportedShapePath: {
47 | message:
48 | "There seems to be an issue with the shape we are trying to apply.",
49 | },
50 | emptySelection: {
51 | message: "Please, select a Shape, Angle Mockup or Angle Composition",
52 | },
53 | unsupportedElement: {
54 | message: "Please, select a Shape, Angle Mockup or Angle Composition",
55 | },
56 | noImageOverrideOnSymbol: {
57 | message: "There is no image override for the selected symbol",
58 | },
59 | symbolWithBitMapLayer: {
60 | message: "Bitmat overrides are not supported",
61 | },
62 | };
63 | },
64 | function (e, r, n) {
65 | Object.defineProperty(r, "__esModule", { value: !0 });
66 | var i = (function () {
67 | function e(e, t) {
68 | for (var r = 0; r < t.length; r++) {
69 | var n = t[r];
70 | (n.enumerable = n.enumerable || !1),
71 | (n.configurable = !0),
72 | "value" in n && (n.writable = !0),
73 | Object.defineProperty(e, n.key, n);
74 | }
75 | }
76 | return function (t, r, n) {
77 | return r && e(t.prototype, r), n && e(t, n), t;
78 | };
79 | })(),
80 | o = n(4);
81 | function a(e) {
82 | if (Array.isArray(e)) {
83 | for (var t = 0, r = Array(e.length); t < e.length; t++) r[t] = e[t];
84 | return r;
85 | }
86 | return Array.from(e);
87 | }
88 | var s = { linear: 0, quadratic: 1, cubic: 2 };
89 | Array.prototype.rotated = function (e) {
90 | return this.slice(e, this.length).concat(this.slice(0, e));
91 | };
92 | var u = (function () {
93 | function e() {
94 | var t =
95 | arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
96 | !(function (e, t) {
97 | if (!(e instanceof t))
98 | throw new TypeError("Cannot call a class as a function");
99 | })(this, e),
100 | (this.context = t.context),
101 | (this.selectedLayer = t.selectedLayer);
102 | }
103 | return (
104 | i(e, [
105 | {
106 | key: "imprintValue_forKey",
107 | value: (function () {
108 | return function (e, t) {
109 | null != this.selectedLayer
110 | ? this.context.command.setValue_forKey_onLayer(
111 | e,
112 | t,
113 | this.selectedLayer
114 | )
115 | : print(
116 | "🛑 Imprinting value before selected layer assignment"
117 | );
118 | };
119 | })(),
120 | },
121 | {
122 | key: "loadValueForKey",
123 | value: (function () {
124 | return function (e) {
125 | return null == this.selectedLayer
126 | ? (print(
127 | "🛑 Loading value before selected layer assignment"
128 | ),
129 | null)
130 | : this.context.command.valueForKey_onLayer(
131 | e,
132 | this.selectedLayer
133 | );
134 | };
135 | })(),
136 | },
137 | {
138 | key: "artboardID",
139 | get: (function () {
140 | return function () {
141 | return void 0 != this._artboardID
142 | ? this._artboardID
143 | : ((this._artboardID =
144 | this.loadValueForKey("artboard-id") + ""),
145 | this._artboardID);
146 | };
147 | })(),
148 | set: (function () {
149 | return function (e) {};
150 | })(),
151 | },
152 | {
153 | key: "artboard",
154 | get: (function () {
155 | return function () {
156 | if (void 0 != this._artboard) return this._artboard;
157 | if (void 0 != this.artboardID) {
158 | for (
159 | var e = this.context.document.artboards(), t = 0;
160 | t < e.count();
161 | t++
162 | )
163 | e[t].objectID() == this.artboardID &&
164 | (this._artboard = e[t]);
165 | if (void 0 != this._artboard) return this._artboard;
166 | print(
167 | "🛑 Not able to retrieve artboard from id in document"
168 | );
169 | } else print("🛑 No artboard ID registered");
170 | };
171 | })(),
172 | set: (function () {
173 | return function (e) {
174 | (this._artboard = e),
175 | this.imprintValue_forKey(e.objectID(), "artboard-id");
176 | };
177 | })(),
178 | },
179 | {
180 | key: "rotation",
181 | get: (function () {
182 | return function () {
183 | return (
184 | void 0 == this._rotation &&
185 | (this._rotation = this.loadValueForKey("rotation")),
186 | this._rotation
187 | );
188 | };
189 | })(),
190 | set: (function () {
191 | return function (e) {
192 | (this._rotation = e), this.imprintValue_forKey(e, "rotation");
193 | };
194 | })(),
195 | },
196 | {
197 | key: "pixelDensity",
198 | get: (function () {
199 | return function () {
200 | if (
201 | (void 0 == this._pixelDensity &&
202 | (this._pixelDensity =
203 | this.loadValueForKey("pixel-density") + 0),
204 | 0 == this._pixelDensity)
205 | ) {
206 | var e = Math.round(2 * this.estimatePixelDensity() + 0.5);
207 | return 0 == e ? 1 : e;
208 | }
209 | return this._pixelDensity;
210 | };
211 | })(),
212 | set: (function () {
213 | return function (e) {
214 | (this._pixelDensity = e),
215 | this.imprintValue_forKey(e, "pixel-density");
216 | };
217 | })(),
218 | },
219 | {
220 | key: "compressionRatio",
221 | get: (function () {
222 | return function () {
223 | return (
224 | void 0 == this._compressionRatio &&
225 | (this._compressionRatio =
226 | this.loadValueForKey("compression-ratio") + 0),
227 | this._compressionRatio
228 | );
229 | };
230 | })(),
231 | set: (function () {
232 | return function (e) {
233 | (this._compressionRatio = e),
234 | this.imprintValue_forKey(e, "compression-ratio");
235 | };
236 | })(),
237 | },
238 | {
239 | key: "reversed",
240 | get: (function () {
241 | return function () {
242 | return (
243 | void 0 == this._reversed &&
244 | (this._reversed = 1 == this.loadValueForKey("reversed")),
245 | this._reversed
246 | );
247 | };
248 | })(),
249 | set: (function () {
250 | return function (e) {
251 | (this._reversed = e), this.imprintValue_forKey(e, "reversed");
252 | };
253 | })(),
254 | },
255 | ]),
256 | i(e, [
257 | {
258 | key: "exportRequest_lessThan52",
259 | value: (function () {
260 | return function () {
261 | var e = NSClassFromString(
262 | "SketchModel.MSImmutableLayerAncestry"
263 | )
264 | .alloc()
265 | .initWithMutableLayer(t.selection[0]),
266 | r = MSExportFormat.formatWithScale_name_fileFormat(
267 | this.pixelDensity,
268 | "Angle",
269 | "png"
270 | );
271 | return MSExportRequest.exportRequestsFromLayerAncestry_exportFormats(
272 | e,
273 | [r]
274 | ).firstObject();
275 | };
276 | })(),
277 | },
278 | {
279 | key: "exporter",
280 | value: (function () {
281 | return function () {
282 | var e = this.context.document.colorSpace();
283 | if (BCSketchInfo.shared().metadata().appVersion < 52)
284 | return MSExporter.exporterForRequest_colorSpace(
285 | this.exportRequest_lessThan52(),
286 | e
287 | );
288 | var t = MSExportFormat.alloc().init();
289 | (t.fileFormat = "png"), (t.scale = this.pixelDensity);
290 | var r =
291 | MSExportRequest.exportRequestsFromExportableLayer_exportFormats_useIDForName(
292 | this.artboard,
293 | [t],
294 | !0
295 | ).firstObject();
296 | return MSExporter.exporterForRequest_colorSpace(r, e);
297 | };
298 | })(),
299 | },
300 | {
301 | key: "ciImage",
302 | value: (function () {
303 | return function () {
304 | var e = this.exporter().bitmapImageRep();
305 | return CIImage.alloc().initWithCGImage(e.CGImage());
306 | };
307 | })(),
308 | },
309 | {
310 | key: "guessRotationAndReversion",
311 | value: (function () {
312 | return function () {
313 | if (1 === this.loadValueForKey("guessed-rotation"))
314 | print(
315 | "⚠️ Angle has already guessed rotation and symmetry for this shape"
316 | );
317 | else {
318 | var e = this.verticesLengths,
319 | t = void 0;
320 | if (this.artboard.class() != MSSymbolMaster) {
321 | t = this.artboard.frame();
322 | var r = e[0] > e[1],
323 | n = t.width() > t.height();
324 | r && (print("🛑 HORIZONTAL"), this.rotate()),
325 | n &&
326 | (print("🛑 HAS HORIZONTAL ARTBOARD"), this.rotate());
327 | var i = this.pointsFromBezierPath,
328 | o = Math.min.apply(
329 | Math,
330 | a(
331 | i.map(function (e) {
332 | return e.y;
333 | })
334 | )
335 | ),
336 | s = i[this.mappedIndexFor(0)],
337 | u = i[this.mappedIndexFor(1)];
338 | s.y != o &&
339 | u.y != o &&
340 | (print("🛑 UPSIDE DOWN"), this.rotate(), this.rotate());
341 | var c = BCSketchInfo.shared().metadata().appVersion;
342 | if (c < 50 || c >= 52) {
343 | var l = this.shorlaceSum();
344 | l < 0
345 | ? (print("🛑 COUNTERCLOCKWISE"),
346 | this.reverseSymmetry())
347 | : l > 0
348 | ? print("🛑 CLOCKWISE")
349 | : print("🛑 UNDEFINED CHIRALITY");
350 | } else
351 | c < 52 &&
352 | (1 ===
353 | this.targetPath.contours().firstObject().isClockwise()
354 | ? (this.reverseSymmetry(), print("🛑 CLOCKWISE"))
355 | : print("🛑 COUNTERCLOCKWISE"),
356 | print("🛑 UNDEFINED CHIRALITY"));
357 | print(
358 | "🔄↔️ Angle has just guessed rotation and symmetry for this shape"
359 | ),
360 | this.imprintValue_forKey(!0, "guessed-rotation");
361 | }
362 | }
363 | };
364 | })(),
365 | },
366 | {
367 | key: "shorlaceSum",
368 | value: (function () {
369 | return function () {
370 | var e = this.pointsFromBezierPath,
371 | t = Math.max.apply(
372 | Math,
373 | a(
374 | e.map(function (e) {
375 | return e.y;
376 | })
377 | )
378 | );
379 | return Array.from({ length: 4 }, function (e, t) {
380 | return t;
381 | }).reduce(function (r, n) {
382 | return (
383 | r +
384 | (-e[n].x + e[(n + 1) % 4].x) *
385 | (2 * t - e[n].y - e[(n + 1) % 4].y)
386 | );
387 | }, 0);
388 | };
389 | })(),
390 | },
391 | {
392 | key: "maximumVerticesWidthAndHeight",
393 | value: (function () {
394 | return function () {
395 | var e = this.verticesLengths.rotated(this.rotation % 2);
396 | return [Math.max(e[0], e[2]), Math.max(e[1], e[3])];
397 | };
398 | })(),
399 | },
400 | {
401 | key: "rotate",
402 | value: (function () {
403 | return function () {
404 | this.rotation = (this.rotation + (this.reversed ? 1 : 3)) % 4;
405 | };
406 | })(),
407 | },
408 | {
409 | key: "reverseSymmetry",
410 | value: (function () {
411 | return function () {
412 | this.rotate(), (this.reversed = !this.reversed);
413 | };
414 | })(),
415 | },
416 | {
417 | key: "mappedIndexFor",
418 | value: (function () {
419 | return function (e) {
420 | return this.reversed
421 | ? [0, 3, 2, 1][(e + this.rotation) % 4]
422 | : (e + this.rotation) % 4;
423 | };
424 | })(),
425 | },
426 | {
427 | key: "lossyCompressionOfImage_atRate",
428 | value: (function () {
429 | return function (e, t) {
430 | var r = NSBitmapImageRep.alloc().initWithCIImage(e),
431 | n = NSMutableDictionary.dictionary();
432 | n.setObject_forKey(
433 | NSTIFFCompressionJPEG,
434 | NSImageCompressionMethod
435 | ),
436 | n.setObject_forKey(t, NSImageCompressionFactor),
437 | n.setObject_forKey(
438 | NSColor.whiteColor(),
439 | NSImageFallbackBackgroundColor
440 | );
441 | var i = r.representationUsingType_properties(
442 | NSJPEGFileType,
443 | n
444 | );
445 | return NSImage.alloc().initWithData(i);
446 | };
447 | })(),
448 | },
449 | {
450 | key: "pixelAccurateRepresentationOfImage",
451 | value: (function () {
452 | return function (e) {
453 | var t = NSCIImageRep.alloc().initWithCIImage(e),
454 | r = NSImage.alloc().initWithSize(t.size());
455 | return r.addRepresentation(t), r;
456 | };
457 | })(),
458 | },
459 | {
460 | key: "pointsAreValid_lessThan50",
461 | get: (function () {
462 | return function () {
463 | var e = this.pointsFromBezierPath;
464 | return null !== e && 7 === e.length;
465 | };
466 | })(),
467 | },
468 | {
469 | key: "pointsAreValid_lessThan52",
470 | get: (function () {
471 | return function () {
472 | var e = this.targetPath.contours().firstObject(),
473 | t = Array.fromNSArray(e.segments());
474 | return (
475 | null !== t &&
476 | 4 === t.length &&
477 | !t.some(function (e) {
478 | return e.segmentType() != s.linear;
479 | })
480 | );
481 | };
482 | })(),
483 | },
484 | {
485 | key: "pointsAreValid",
486 | get: (function () {
487 | return function () {
488 | var e = BCSketchInfo.shared().metadata().appVersion;
489 | if (e < 50) return this.pointsAreValid_lessThan50;
490 | if (e < 52) return this.pointsAreValid_lessThan52;
491 | var t = this.targetLayer.points();
492 | return (
493 | null !== t &&
494 | 4 === t.length &&
495 | !t.some(function (e) {
496 | return !e.isStraight();
497 | })
498 | );
499 | };
500 | })(),
501 | },
502 | {
503 | key: "pointsFromBezierPath",
504 | get: (function () {
505 | return function () {
506 | var e = this,
507 | t = BCSketchInfo.shared().metadata().appVersion;
508 | if (t < 50) {
509 | var r = this.targetPath.elementCount();
510 | return 7 != r
511 | ? null
512 | : Array.from({ length: r }, function (e, t) {
513 | return t;
514 | }).map(function (t) {
515 | var r = MOPointer.alloc().initWithValue_(
516 | CGPointMake(0, 0)
517 | );
518 | return (
519 | e.targetPath.elementAtIndex_associatedPoints_(t, r),
520 | r.value()
521 | );
522 | });
523 | }
524 | if (t < 52) {
525 | var n = this.targetPath.contours().firstObject();
526 | return Array.fromNSArray(n.segments()).map(function (e) {
527 | return e.endPoint1();
528 | });
529 | }
530 | var i = this.targetLayer.rect().size;
531 | return Array.fromNSArray(this.targetLayer.points())
532 | .map(function (e) {
533 | return e.point();
534 | })
535 | .map(function (e) {
536 | return {
537 | x: Number(e.x) * Number(i.width),
538 | y: Number(e.y) * Number(i.height),
539 | };
540 | });
541 | };
542 | })(),
543 | },
544 | {
545 | key: "verticesLengths",
546 | get: (function () {
547 | return function () {
548 | var e = this.pointsFromBezierPath;
549 | return Array.from({ length: 4 }, function (e, t) {
550 | return t;
551 | }).map(function (t) {
552 | var r = (t + 1) % 4,
553 | n = e[t].x - e[r].x,
554 | i = e[t].y - e[r].y;
555 | return Math.sqrt(Math.pow(n, 2) + Math.pow(i, 2));
556 | });
557 | };
558 | })(),
559 | },
560 | {
561 | key: "normalizedCIVectors",
562 | get: (function () {
563 | return function () {
564 | var e = this.pointsFromBezierPath,
565 | t = Math.max.apply(
566 | Math,
567 | a(
568 | e.map(function (e) {
569 | return e.y;
570 | })
571 | )
572 | ),
573 | r = this.pixelDensity;
574 | return e.map(function (e) {
575 | return CIVector.vectorWithX_Y(e.x * r, (t - e.y) * r);
576 | });
577 | };
578 | })(),
579 | },
580 | {
581 | key: "transformedImage",
582 | get: (function () {
583 | return function () {
584 | var e = this.normalizedCIVectors,
585 | t = CIFilter.filterWithName("CIPerspectiveTransform");
586 | t.setValue_forKey(e[this.mappedIndexFor(0)], "inputTopLeft"),
587 | t.setValue_forKey(
588 | e[this.mappedIndexFor(1)],
589 | "inputTopRight"
590 | ),
591 | t.setValue_forKey(
592 | e[this.mappedIndexFor(2)],
593 | "inputBottomRight"
594 | ),
595 | t.setValue_forKey(
596 | e[this.mappedIndexFor(3)],
597 | "inputBottomLeft"
598 | );
599 | var r = this.ciImage();
600 | t.setValue_forKey(r, "inputImage");
601 | var n = t.valueForKey("outputImage");
602 | if (n) {
603 | var i = void 0,
604 | a = o.CompressionRatio[this.compressionRatio].ratio;
605 | return (
606 | (i =
607 | 1 != a
608 | ? this.lossyCompressionOfImage_atRate(n, a)
609 | : this.pixelAccurateRepresentationOfImage(n)),
610 | BCSketchInfo.shared().metadata().appVersion < 47
611 | ? MSImageData.alloc().initWithImage_convertColorSpace(
612 | i,
613 | !0
614 | )
615 | : MSImageData.alloc().initWithImage_(i)
616 | );
617 | }
618 | print("🛑 Unable to form perspective image");
619 | };
620 | })(),
621 | },
622 | ]),
623 | e
624 | );
625 | })();
626 | r.default = u;
627 | },
628 | function (e, t, r) {
629 | Object.defineProperty(t, "__esModule", { value: !0 });
630 | var n,
631 | i = (function () {
632 | return function (e, t) {
633 | if (Array.isArray(e)) return e;
634 | if (Symbol.iterator in Object(e))
635 | return (function (e, t) {
636 | var r = [],
637 | n = !0,
638 | i = !1,
639 | o = void 0;
640 | try {
641 | for (
642 | var a, s = e[Symbol.iterator]();
643 | !(n = (a = s.next()).done) &&
644 | (r.push(a.value), !t || r.length !== t);
645 | n = !0
646 | );
647 | } catch (e) {
648 | (i = !0), (o = e);
649 | } finally {
650 | try {
651 | !n && s.return && s.return();
652 | } finally {
653 | if (i) throw o;
654 | }
655 | }
656 | return r;
657 | })(e, t);
658 | throw new TypeError(
659 | "Invalid attempt to destructure non-iterable instance"
660 | );
661 | };
662 | })(),
663 | o = (function () {
664 | function e(e, t) {
665 | for (var r = 0; r < t.length; r++) {
666 | var n = t[r];
667 | (n.enumerable = n.enumerable || !1),
668 | (n.configurable = !0),
669 | "value" in n && (n.writable = !0),
670 | Object.defineProperty(e, n.key, n);
671 | }
672 | }
673 | return function (t, r, n) {
674 | return r && e(t.prototype, r), n && e(t, n), t;
675 | };
676 | })(),
677 | a = r(1),
678 | s = (n = a) && n.__esModule ? n : { default: n },
679 | u = r(0);
680 | function c(e, t) {
681 | if (!e)
682 | throw new ReferenceError(
683 | "this hasn't been initialised - super() hasn't been called"
684 | );
685 | return !t || ("object" != typeof t && "function" != typeof t) ? e : t;
686 | }
687 | var l = (function (e) {
688 | function t() {
689 | var e =
690 | arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
691 | !(function (e, t) {
692 | if (!(e instanceof t))
693 | throw new TypeError("Cannot call a class as a function");
694 | })(this, t);
695 | var r = c(
696 | this,
697 | (t.__proto__ || Object.getPrototypeOf(t)).call(this, e)
698 | );
699 | if (
700 | ((r.targetLayer = e.override.affectedLayer()),
701 | r.targetLayer.class() === MSImmutableBitmapLayer)
702 | )
703 | return c(r, u.Error.symbolWithBitMapLayer);
704 | var n = BCSketchInfo.shared().metadata().appVersion;
705 | n < 50
706 | ? (r.targetPath = e.override.affectedLayer().bezierPath())
707 | : n < 52 &&
708 | (r.targetPath = e.override
709 | .affectedLayer()
710 | .pathInFrameWithTransforms());
711 | var i = e.override.overridePoint().parent();
712 | return (
713 | null !== i && (r.overrideLayer = i),
714 | r.pointsAreValid ? r : c(r, u.Error.unsupportedShapePath)
715 | );
716 | }
717 | return (
718 | (function (e, t) {
719 | if ("function" != typeof t && null !== t)
720 | throw new TypeError(
721 | "Super expression must either be null or a function, not " +
722 | typeof t
723 | );
724 | (e.prototype = Object.create(t && t.prototype, {
725 | constructor: {
726 | value: e,
727 | enumerable: !1,
728 | writable: !0,
729 | configurable: !0,
730 | },
731 | })),
732 | t &&
733 | (Object.setPrototypeOf
734 | ? Object.setPrototypeOf(e, t)
735 | : (e.__proto__ = t));
736 | })(t, s["default"]),
737 | o(t, [
738 | {
739 | key: "applyImage",
740 | value: (function () {
741 | return function () {
742 | var e = this.targetLayer.objectID(),
743 | t =
744 | this.selectedLayer.overrides() ||
745 | NSDictionary.dictionary(),
746 | r = NSMutableDictionary.dictionaryWithDictionary(t);
747 | r.setObject_forKey(this.transformedImage, e),
748 | (this.selectedLayer.overrides = r);
749 | };
750 | })(),
751 | },
752 | {
753 | key: "estimatePixelDensity",
754 | value: (function () {
755 | return function () {
756 | var e = this.maximumVerticesWidthAndHeight(),
757 | t = i(e, 2),
758 | r = t[0],
759 | n = t[1],
760 | o =
761 | (this.selectedLayer.rect().size.width * r) /
762 | (this.selectedLayer.naturalSize().width *
763 | this.artboard.rect().size.width),
764 | a =
765 | (this.selectedLayer.rect().size.height * n) /
766 | (this.selectedLayer.naturalSize().height *
767 | this.artboard.rect().size.height);
768 | return o > a ? o : a;
769 | };
770 | })(),
771 | },
772 | {
773 | key: "description",
774 | value: (function () {
775 | return function () {
776 | return (
777 | this.selectedLayer.name() + " " + this.targetLayer.name()
778 | );
779 | };
780 | })(),
781 | },
782 | ]),
783 | t
784 | );
785 | })();
786 | t.default = l;
787 | },
788 | function (e, t, r) {
789 | Object.defineProperty(t, "__esModule", { value: !0 }),
790 | (t.default = function (e) {
791 | var t = e.selection[0];
792 | if (null != t) {
793 | var r = Array.fromNSArray(t);
794 | if (0 != r.length) {
795 | var n = o.default.tryCreating({ for: r, in: e }),
796 | i = n.filter(function (e) {
797 | return e instanceof o.default;
798 | }),
799 | u = n.filter(function (e) {
800 | return !(e instanceof o.default);
801 | });
802 | if (0 != i.length)
803 | i.forEach(function (e) {
804 | e.rotate(), e.applyImage();
805 | }),
806 | a.show({
807 | message: "Angle rotated! 🔄",
808 | inDocument: e.document,
809 | });
810 | else {
811 | var c = u[0];
812 | a.show({ message: c.message, inDocument: e.document });
813 | }
814 | } else
815 | a.show({
816 | message: s.Error.emptySelection.message,
817 | inDocument: e.document,
818 | });
819 | } else
820 | a.show({
821 | message: s.Error.emptySelection.message,
822 | inDocument: e.document,
823 | });
824 | });
825 | var n,
826 | i = r(1),
827 | o = (n = i) && n.__esModule ? n : { default: n },
828 | a = (function (e) {
829 | if (e && e.__esModule) return e;
830 | var t = {};
831 | if (null != e)
832 | for (var r in e)
833 | Object.prototype.hasOwnProperty.call(e, r) && (t[r] = e[r]);
834 | return (t.default = e), t;
835 | })(r(5)),
836 | s = r(0);
837 | },
838 | function (e, t) {
839 | Object.defineProperty(t, "__esModule", { value: !0 });
840 | t.CompressionRatio = [
841 | { selectionLabel: "Best", ratio: 1 },
842 | { selectionLabel: "Better", ratio: 0.9 },
843 | { selectionLabel: "Good", ratio: 0.8 },
844 | { selectionLabel: "Average", ratio: 0.7 },
845 | ];
846 | },
847 | function (e, t, r) {
848 | Object.defineProperty(t, "__esModule", { value: !0 }),
849 | (t.show = function (e) {
850 | var t = e.message,
851 | r = e.inDocument;
852 | void 0 != r && void 0 != r.showMessage && r.showMessage(t);
853 | print(t);
854 | }),
855 | (t.filterPossibleArtboards = function (e) {
856 | var t = e.class();
857 | switch (t) {
858 | case MSArtboardGroup:
859 | var r = e,
860 | n = r.frame();
861 | if (n.width() < 250 || n.height() < 250) return !1;
862 | var i = n.width() / n.height();
863 | if ((i > 1 && (i = 1 / i), i < 0.4)) return !1;
864 | break;
865 | case MSSymbolMaster:
866 | return !1;
867 | default:
868 | return print(t), !1;
869 | }
870 | return !0;
871 | }),
872 | (t.compareByRatioAndAlphabet = function (e, t) {
873 | var r = e.frame(),
874 | n = t.frame(),
875 | i = r.width() / r.height();
876 | i > 1 && (i = 1 / i);
877 | var o = i > 0.4 && i < 0.8,
878 | a = n.width() / n.height();
879 | a > 1 && (a = 1 / a);
880 | var s = a > 0.4 && a < 0.8;
881 | if (o && !s) return !1;
882 | if (s && !o) return !0;
883 | if (i == a) return e.name() > t.name();
884 | return i > a;
885 | }),
886 | (t.introspect = function (e) {
887 | var t = e.class().mocha();
888 | print("-----------------------------------------------"),
889 | print("PROPERTIES-------------------------------------"),
890 | print("-----------------------------------------------"),
891 | print(t.properties()),
892 | print(t.propertiesWithAncestors()),
893 | print("-----------------------------------------------"),
894 | print("INSTANCE METHODS-------------------------------"),
895 | print("-----------------------------------------------"),
896 | print(t.instanceMethods()),
897 | print(t.instanceMethodsWithAncestors()),
898 | print("-----------------------------------------------"),
899 | print("CLASS METHODS----------------------------------"),
900 | print("-----------------------------------------------"),
901 | print(t.classMethods()),
902 | print(t.classMethodsWithAncestors()),
903 | print("-----------------------------------------------"),
904 | print("PROTOCOLS--------------------------------------"),
905 | print("-----------------------------------------------"),
906 | print(t.protocols()),
907 | print(t.protocolsWithAncestors());
908 | }),
909 | (t.createLabel = function (e, t, r) {
910 | var n = NSTextField.alloc().initWithFrame(r);
911 | return (
912 | n.setStringValue(e),
913 | n.setFont(NSFont.boldSystemFontOfSize(t)),
914 | n.setBezeled(!1),
915 | n.setDrawsBackground(!1),
916 | n.setEditable(!1),
917 | n.setSelectable(!1),
918 | n
919 | );
920 | }),
921 | (t.popUpButtonsforRectangleIndexer_withTitleIndexer_andImageIndexer_defaultSelected_onIndex =
922 | function (e, t, r, n) {
923 | var i = NSPopUpButton.alloc().initWithFrame(e(n));
924 | i.addItemsWithTitles(t),
925 | null != r &&
926 | ((i.imageScaling = NSImageScaleProportionallyUpOrDown),
927 | Array.fromNSArray(i.itemArray()).forEach(function (e, t, n) {
928 | e.image = r[t];
929 | }));
930 | return i;
931 | }),
932 | (t.smallImagesFromArtboard = function (e) {
933 | if (e.class() == MSSymbolMaster) return print(e), null;
934 | void 0 == e.frame && print(e);
935 | var t = e.frame().width(),
936 | r = e.frame().height(),
937 | n = t / r;
938 | n > 1 && (n = 1 / n);
939 | if (n > 0.8 || n < 0.4) return null;
940 | var i = NSClassFromString("SketchModel.MSImmutableLayerAncestry")
941 | .alloc()
942 | .initWithMutableLayer(e),
943 | o = 48 / (t > r ? t : r),
944 | a = MSExportFormat.formatWithScale_name_fileFormat(o, "", "png"),
945 | s = MSExportRequest.exportRequestsFromLayerAncestry_exportFormats(
946 | i,
947 | [a]
948 | ).firstObject();
949 | return MSExporter.exporterForRequest_colorSpace(
950 | s,
951 | NSColorSpace.sRGBColorSpace()
952 | ).previewImage();
953 | });
954 | var n = u(r(1)),
955 | i = u(r(6)),
956 | o = u(r(2)),
957 | a = u(r(7)),
958 | s = r(0);
959 | function u(e) {
960 | return e && e.__esModule ? e : { default: e };
961 | }
962 | (n.default.tryCreating = function (e) {
963 | var t = e.for,
964 | r = e.in;
965 | return t
966 | .map(function (e) {
967 | switch (e.class()) {
968 | case MSSymbolInstance:
969 | var t = Array.fromNSArray(e.availableOverrides()) || [],
970 | n = t
971 | .filter(function (e) {
972 | return e.currentValue().class() == MSImageData;
973 | })
974 | .map(function (t) {
975 | return new o.default({
976 | selectedLayer: e,
977 | context: r,
978 | override: t,
979 | });
980 | }),
981 | u = t
982 | .map(function (e) {
983 | return e.children();
984 | })
985 | .filter(function (e) {
986 | return null != e;
987 | })
988 | .map(Array.fromNSArray)
989 | .reduce(function (e, t) {
990 | return e.concat(t);
991 | }, [])
992 | .filter(function (e) {
993 | return e.class() == MSAvailableOverride;
994 | })
995 | .map(function (t) {
996 | return new i.default({
997 | override: t,
998 | selectedLayer: e,
999 | context: r,
1000 | });
1001 | });
1002 | return n.concat(u);
1003 | case MSShapeGroup:
1004 | case MSShapePathLayer:
1005 | case MSRectangleShape:
1006 | return new a.default({ selectedLayer: e, context: r });
1007 | default:
1008 | return s.Error.unsupportedElement;
1009 | }
1010 | })
1011 | .reduce(function (e, t, r, n) {
1012 | return e.concat(t);
1013 | }, []);
1014 | }),
1015 | (Array.fromNSArray = function (e) {
1016 | for (var t = [], r = 0; r < e.length; r++) t.push(e[r]);
1017 | return t;
1018 | }),
1019 | (Array.prototype.print = function () {
1020 | return this.map(function (e) {
1021 | return print(e), e;
1022 | });
1023 | });
1024 | },
1025 | function (e, t, r) {
1026 | Object.defineProperty(t, "__esModule", { value: !0 });
1027 | var n,
1028 | i = (function () {
1029 | function e(e, t) {
1030 | for (var r = 0; r < t.length; r++) {
1031 | var n = t[r];
1032 | (n.enumerable = n.enumerable || !1),
1033 | (n.configurable = !0),
1034 | "value" in n && (n.writable = !0),
1035 | Object.defineProperty(e, n.key, n);
1036 | }
1037 | }
1038 | return function (t, r, n) {
1039 | return r && e(t.prototype, r), n && e(t, n), t;
1040 | };
1041 | })(),
1042 | o = (function () {
1043 | return function e(t, r, n) {
1044 | null === t && (t = Function.prototype);
1045 | var i = Object.getOwnPropertyDescriptor(t, r);
1046 | if (void 0 === i) {
1047 | var o = Object.getPrototypeOf(t);
1048 | return null === o ? void 0 : e(o, r, n);
1049 | }
1050 | if ("value" in i) return i.value;
1051 | var a = i.get;
1052 | return void 0 !== a ? a.call(n) : void 0;
1053 | };
1054 | })(),
1055 | a = r(2),
1056 | s = (n = a) && n.__esModule ? n : { default: n };
1057 | r(0);
1058 | var u = (function (e) {
1059 | function t() {
1060 | var e =
1061 | arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
1062 | !(function (e, t) {
1063 | if (!(e instanceof t))
1064 | throw new TypeError("Cannot call a class as a function");
1065 | })(this, t);
1066 | var r = (function (e, t) {
1067 | if (!e)
1068 | throw new ReferenceError(
1069 | "this hasn't been initialised - super() hasn't been called"
1070 | );
1071 | return !t || ("object" != typeof t && "function" != typeof t)
1072 | ? e
1073 | : t;
1074 | })(this, (t.__proto__ || Object.getPrototypeOf(t)).call(this, e));
1075 | return (r.override = e.override), r;
1076 | }
1077 | return (
1078 | (function (e, t) {
1079 | if ("function" != typeof t && null !== t)
1080 | throw new TypeError(
1081 | "Super expression must either be null or a function, not " +
1082 | typeof t
1083 | );
1084 | (e.prototype = Object.create(t && t.prototype, {
1085 | constructor: {
1086 | value: e,
1087 | enumerable: !1,
1088 | writable: !0,
1089 | configurable: !0,
1090 | },
1091 | })),
1092 | t &&
1093 | (Object.setPrototypeOf
1094 | ? Object.setPrototypeOf(e, t)
1095 | : (e.__proto__ = t));
1096 | })(t, s["default"]),
1097 | i(t, [
1098 | {
1099 | key: "loadValueForKey",
1100 | value: (function () {
1101 | return function (e) {
1102 | return o(
1103 | t.prototype.__proto__ || Object.getPrototypeOf(t.prototype),
1104 | "loadValueForKey",
1105 | this
1106 | ).call(this, this.targetLayer.objectID() + "-" + e);
1107 | };
1108 | })(),
1109 | },
1110 | {
1111 | key: "imprintValue_forKey",
1112 | value: (function () {
1113 | return function (e, r) {
1114 | o(
1115 | t.prototype.__proto__ || Object.getPrototypeOf(t.prototype),
1116 | "imprintValue_forKey",
1117 | this
1118 | ).call(this, e, this.targetLayer.objectID() + "-" + r);
1119 | };
1120 | })(),
1121 | },
1122 | {
1123 | key: "applyImage",
1124 | value: (function () {
1125 | return function () {
1126 | var e =
1127 | this.selectedLayer.overrides() ||
1128 | NSDictionary.dictionary(),
1129 | t = NSMutableDictionary.dictionaryWithDictionary(e),
1130 | r = (this.overrideLayer + "").replace("_symbolID", ""),
1131 | n = t.objectForKey(r) || NSMutableDictionary.dictionary(),
1132 | i = NSMutableDictionary.dictionaryWithDictionary(n),
1133 | o = this.targetLayer.objectID();
1134 | i.setObject_forKey(this.transformedImage, o),
1135 | t.setObject_forKey(i, r),
1136 | (this.selectedLayer.overrides = t);
1137 | };
1138 | })(),
1139 | },
1140 | {
1141 | key: "description",
1142 | value: (function () {
1143 | return function () {
1144 | return (
1145 | this.override.parent().affectedLayer().name() +
1146 | " " +
1147 | this.targetLayer.name()
1148 | );
1149 | };
1150 | })(),
1151 | },
1152 | ]),
1153 | t
1154 | );
1155 | })();
1156 | t.default = u;
1157 | },
1158 | function (e, t, r) {
1159 | Object.defineProperty(t, "__esModule", { value: !0 });
1160 | var n,
1161 | i = (function () {
1162 | return function (e, t) {
1163 | if (Array.isArray(e)) return e;
1164 | if (Symbol.iterator in Object(e))
1165 | return (function (e, t) {
1166 | var r = [],
1167 | n = !0,
1168 | i = !1,
1169 | o = void 0;
1170 | try {
1171 | for (
1172 | var a, s = e[Symbol.iterator]();
1173 | !(n = (a = s.next()).done) &&
1174 | (r.push(a.value), !t || r.length !== t);
1175 | n = !0
1176 | );
1177 | } catch (e) {
1178 | (i = !0), (o = e);
1179 | } finally {
1180 | try {
1181 | !n && s.return && s.return();
1182 | } finally {
1183 | if (i) throw o;
1184 | }
1185 | }
1186 | return r;
1187 | })(e, t);
1188 | throw new TypeError(
1189 | "Invalid attempt to destructure non-iterable instance"
1190 | );
1191 | };
1192 | })(),
1193 | o = (function () {
1194 | function e(e, t) {
1195 | for (var r = 0; r < t.length; r++) {
1196 | var n = t[r];
1197 | (n.enumerable = n.enumerable || !1),
1198 | (n.configurable = !0),
1199 | "value" in n && (n.writable = !0),
1200 | Object.defineProperty(e, n.key, n);
1201 | }
1202 | }
1203 | return function (t, r, n) {
1204 | return r && e(t.prototype, r), n && e(t, n), t;
1205 | };
1206 | })(),
1207 | a = r(1),
1208 | s = (n = a) && n.__esModule ? n : { default: n },
1209 | u = r(0);
1210 | function c(e, t) {
1211 | if (!e)
1212 | throw new ReferenceError(
1213 | "this hasn't been initialised - super() hasn't been called"
1214 | );
1215 | return !t || ("object" != typeof t && "function" != typeof t) ? e : t;
1216 | }
1217 | var l = { solid: 0, gradient: 1, pattern: 4, noise: 5 },
1218 | f = (function (e) {
1219 | function t() {
1220 | var e =
1221 | arguments.length > 0 && void 0 !== arguments[0]
1222 | ? arguments[0]
1223 | : {};
1224 | !(function (e, t) {
1225 | if (!(e instanceof t))
1226 | throw new TypeError("Cannot call a class as a function");
1227 | })(this, t);
1228 | var r = c(
1229 | this,
1230 | (t.__proto__ || Object.getPrototypeOf(t)).call(this, e)
1231 | );
1232 | r.targetLayer = r.selectedLayer;
1233 | var n = BCSketchInfo.shared().metadata().appVersion;
1234 | return (
1235 | n < 50
1236 | ? (r.targetPath = r.selectedLayer.bezierPath())
1237 | : n < 52 &&
1238 | (r.targetPath = r.selectedLayer.pathInFrameWithTransforms()),
1239 | r.pointsAreValid ? r : c(r, u.Error.unsupportedShapePath)
1240 | );
1241 | }
1242 | return (
1243 | (function (e, t) {
1244 | if ("function" != typeof t && null !== t)
1245 | throw new TypeError(
1246 | "Super expression must either be null or a function, not " +
1247 | typeof t
1248 | );
1249 | (e.prototype = Object.create(t && t.prototype, {
1250 | constructor: {
1251 | value: e,
1252 | enumerable: !1,
1253 | writable: !0,
1254 | configurable: !0,
1255 | },
1256 | })),
1257 | t &&
1258 | (Object.setPrototypeOf
1259 | ? Object.setPrototypeOf(e, t)
1260 | : (e.__proto__ = t));
1261 | })(t, s["default"]),
1262 | o(t, [
1263 | {
1264 | key: "applyImage",
1265 | value: (function () {
1266 | return function () {
1267 | var e = MSStyleFill.alloc().init();
1268 | e.setImage(this.transformedImage),
1269 | (e.fillType = l.pattern),
1270 | this.targetLayer.style().removeAllStyleFills(),
1271 | this.targetLayer.style().addStyleFill(e);
1272 | };
1273 | })(),
1274 | },
1275 | {
1276 | key: "estimatePixelDensity",
1277 | value: (function () {
1278 | return function () {
1279 | var e = this.maximumVerticesWidthAndHeight(),
1280 | t = i(e, 2),
1281 | r = t[0],
1282 | n = t[1],
1283 | o = r / this.artboard.rect().size.width,
1284 | a = n / this.artboard.rect().size.height;
1285 | return o > a ? o : a;
1286 | };
1287 | })(),
1288 | },
1289 | {
1290 | key: "description",
1291 | value: (function () {
1292 | return function () {
1293 | return this.targetLayer.name();
1294 | };
1295 | })(),
1296 | },
1297 | ]),
1298 | t
1299 | );
1300 | })();
1301 | t.default = f;
1302 | },
1303 | ]);
1304 | "default" === e && "function" == typeof r ? r(t) : r[e](t);
1305 | }
1306 | that.onRun = __skpm_run.bind(this, "default");
1307 |
--------------------------------------------------------------------------------
/Angle.sketchplugin/Contents/Sketch/symmetry.js:
--------------------------------------------------------------------------------
1 | var that = this;
2 | function __skpm_run(e, t) {
3 | that.context = t;
4 | var r = (function (e) {
5 | var t = {};
6 | function r(n) {
7 | if (t[n]) return t[n].exports;
8 | var i = (t[n] = { i: n, l: !1, exports: {} });
9 | return e[n].call(i.exports, i, i.exports, r), (i.l = !0), i.exports;
10 | }
11 | return (
12 | (r.m = e),
13 | (r.c = t),
14 | (r.d = function (e, t, n) {
15 | r.o(e, t) ||
16 | Object.defineProperty(e, t, {
17 | configurable: !1,
18 | enumerable: !0,
19 | get: n,
20 | });
21 | }),
22 | (r.n = function (e) {
23 | var t =
24 | e && e.__esModule
25 | ? function () {
26 | return e.default;
27 | }
28 | : function () {
29 | return e;
30 | };
31 | return r.d(t, "a", t), t;
32 | }),
33 | (r.o = function (e, t) {
34 | return Object.prototype.hasOwnProperty.call(e, t);
35 | }),
36 | (r.p = ""),
37 | r((r.s = 3))
38 | );
39 | })([
40 | function (e, t) {
41 | Object.defineProperty(t, "__esModule", { value: !0 });
42 | t.Error = {
43 | unsupportedSymbol: {
44 | message: "This does not seem to be a supported symbol.",
45 | },
46 | unsupportedShapePath: {
47 | message:
48 | "There seems to be an issue with the shape we are trying to apply.",
49 | },
50 | emptySelection: {
51 | message: "Please, select a Shape, Angle Mockup or Angle Composition",
52 | },
53 | unsupportedElement: {
54 | message: "Please, select a Shape, Angle Mockup or Angle Composition",
55 | },
56 | noImageOverrideOnSymbol: {
57 | message: "There is no image override for the selected symbol",
58 | },
59 | symbolWithBitMapLayer: {
60 | message: "Bitmat overrides are not supported",
61 | },
62 | };
63 | },
64 | function (e, r, n) {
65 | Object.defineProperty(r, "__esModule", { value: !0 });
66 | var i = (function () {
67 | function e(e, t) {
68 | for (var r = 0; r < t.length; r++) {
69 | var n = t[r];
70 | (n.enumerable = n.enumerable || !1),
71 | (n.configurable = !0),
72 | "value" in n && (n.writable = !0),
73 | Object.defineProperty(e, n.key, n);
74 | }
75 | }
76 | return function (t, r, n) {
77 | return r && e(t.prototype, r), n && e(t, n), t;
78 | };
79 | })(),
80 | o = n(4);
81 | function a(e) {
82 | if (Array.isArray(e)) {
83 | for (var t = 0, r = Array(e.length); t < e.length; t++) r[t] = e[t];
84 | return r;
85 | }
86 | return Array.from(e);
87 | }
88 | var s = { linear: 0, quadratic: 1, cubic: 2 };
89 | Array.prototype.rotated = function (e) {
90 | return this.slice(e, this.length).concat(this.slice(0, e));
91 | };
92 | var u = (function () {
93 | function e() {
94 | var t =
95 | arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
96 | !(function (e, t) {
97 | if (!(e instanceof t))
98 | throw new TypeError("Cannot call a class as a function");
99 | })(this, e),
100 | (this.context = t.context),
101 | (this.selectedLayer = t.selectedLayer);
102 | }
103 | return (
104 | i(e, [
105 | {
106 | key: "imprintValue_forKey",
107 | value: (function () {
108 | return function (e, t) {
109 | null != this.selectedLayer
110 | ? this.context.command.setValue_forKey_onLayer(
111 | e,
112 | t,
113 | this.selectedLayer
114 | )
115 | : print(
116 | "🛑 Imprinting value before selected layer assignment"
117 | );
118 | };
119 | })(),
120 | },
121 | {
122 | key: "loadValueForKey",
123 | value: (function () {
124 | return function (e) {
125 | return null == this.selectedLayer
126 | ? (print(
127 | "🛑 Loading value before selected layer assignment"
128 | ),
129 | null)
130 | : this.context.command.valueForKey_onLayer(
131 | e,
132 | this.selectedLayer
133 | );
134 | };
135 | })(),
136 | },
137 | {
138 | key: "artboardID",
139 | get: (function () {
140 | return function () {
141 | return void 0 != this._artboardID
142 | ? this._artboardID
143 | : ((this._artboardID =
144 | this.loadValueForKey("artboard-id") + ""),
145 | this._artboardID);
146 | };
147 | })(),
148 | set: (function () {
149 | return function (e) {};
150 | })(),
151 | },
152 | {
153 | key: "artboard",
154 | get: (function () {
155 | return function () {
156 | if (void 0 != this._artboard) return this._artboard;
157 | if (void 0 != this.artboardID) {
158 | for (
159 | var e = this.context.document.artboards(), t = 0;
160 | t < e.count();
161 | t++
162 | )
163 | e[t].objectID() == this.artboardID &&
164 | (this._artboard = e[t]);
165 | if (void 0 != this._artboard) return this._artboard;
166 | print(
167 | "🛑 Not able to retrieve artboard from id in document"
168 | );
169 | } else print("🛑 No artboard ID registered");
170 | };
171 | })(),
172 | set: (function () {
173 | return function (e) {
174 | (this._artboard = e),
175 | this.imprintValue_forKey(e.objectID(), "artboard-id");
176 | };
177 | })(),
178 | },
179 | {
180 | key: "rotation",
181 | get: (function () {
182 | return function () {
183 | return (
184 | void 0 == this._rotation &&
185 | (this._rotation = this.loadValueForKey("rotation")),
186 | this._rotation
187 | );
188 | };
189 | })(),
190 | set: (function () {
191 | return function (e) {
192 | (this._rotation = e), this.imprintValue_forKey(e, "rotation");
193 | };
194 | })(),
195 | },
196 | {
197 | key: "pixelDensity",
198 | get: (function () {
199 | return function () {
200 | if (
201 | (void 0 == this._pixelDensity &&
202 | (this._pixelDensity =
203 | this.loadValueForKey("pixel-density") + 0),
204 | 0 == this._pixelDensity)
205 | ) {
206 | var e = Math.round(2 * this.estimatePixelDensity() + 0.5);
207 | return 0 == e ? 1 : e;
208 | }
209 | return this._pixelDensity;
210 | };
211 | })(),
212 | set: (function () {
213 | return function (e) {
214 | (this._pixelDensity = e),
215 | this.imprintValue_forKey(e, "pixel-density");
216 | };
217 | })(),
218 | },
219 | {
220 | key: "compressionRatio",
221 | get: (function () {
222 | return function () {
223 | return (
224 | void 0 == this._compressionRatio &&
225 | (this._compressionRatio =
226 | this.loadValueForKey("compression-ratio") + 0),
227 | this._compressionRatio
228 | );
229 | };
230 | })(),
231 | set: (function () {
232 | return function (e) {
233 | (this._compressionRatio = e),
234 | this.imprintValue_forKey(e, "compression-ratio");
235 | };
236 | })(),
237 | },
238 | {
239 | key: "reversed",
240 | get: (function () {
241 | return function () {
242 | return (
243 | void 0 == this._reversed &&
244 | (this._reversed = 1 == this.loadValueForKey("reversed")),
245 | this._reversed
246 | );
247 | };
248 | })(),
249 | set: (function () {
250 | return function (e) {
251 | (this._reversed = e), this.imprintValue_forKey(e, "reversed");
252 | };
253 | })(),
254 | },
255 | ]),
256 | i(e, [
257 | {
258 | key: "exportRequest_lessThan52",
259 | value: (function () {
260 | return function () {
261 | var e = NSClassFromString(
262 | "SketchModel.MSImmutableLayerAncestry"
263 | )
264 | .alloc()
265 | .initWithMutableLayer(t.selection[0]),
266 | r = MSExportFormat.formatWithScale_name_fileFormat(
267 | this.pixelDensity,
268 | "Angle",
269 | "png"
270 | );
271 | return MSExportRequest.exportRequestsFromLayerAncestry_exportFormats(
272 | e,
273 | [r]
274 | ).firstObject();
275 | };
276 | })(),
277 | },
278 | {
279 | key: "exporter",
280 | value: (function () {
281 | return function () {
282 | var e = this.context.document.colorSpace();
283 | if (BCSketchInfo.shared().metadata().appVersion < 52)
284 | return MSExporter.exporterForRequest_colorSpace(
285 | this.exportRequest_lessThan52(),
286 | e
287 | );
288 | var t = MSExportFormat.alloc().init();
289 | (t.fileFormat = "png"), (t.scale = this.pixelDensity);
290 | var r =
291 | MSExportRequest.exportRequestsFromExportableLayer_exportFormats_useIDForName(
292 | this.artboard,
293 | [t],
294 | !0
295 | ).firstObject();
296 | return MSExporter.exporterForRequest_colorSpace(r, e);
297 | };
298 | })(),
299 | },
300 | {
301 | key: "ciImage",
302 | value: (function () {
303 | return function () {
304 | var e = this.exporter().bitmapImageRep();
305 | return CIImage.alloc().initWithCGImage(e.CGImage());
306 | };
307 | })(),
308 | },
309 | {
310 | key: "guessRotationAndReversion",
311 | value: (function () {
312 | return function () {
313 | if (1 === this.loadValueForKey("guessed-rotation"))
314 | print(
315 | "⚠️ Angle has already guessed rotation and symmetry for this shape"
316 | );
317 | else {
318 | var e = this.verticesLengths,
319 | t = void 0;
320 | if (this.artboard.class() != MSSymbolMaster) {
321 | t = this.artboard.frame();
322 | var r = e[0] > e[1],
323 | n = t.width() > t.height();
324 | r && (print("🛑 HORIZONTAL"), this.rotate()),
325 | n &&
326 | (print("🛑 HAS HORIZONTAL ARTBOARD"), this.rotate());
327 | var i = this.pointsFromBezierPath,
328 | o = Math.min.apply(
329 | Math,
330 | a(
331 | i.map(function (e) {
332 | return e.y;
333 | })
334 | )
335 | ),
336 | s = i[this.mappedIndexFor(0)],
337 | u = i[this.mappedIndexFor(1)];
338 | s.y != o &&
339 | u.y != o &&
340 | (print("🛑 UPSIDE DOWN"), this.rotate(), this.rotate());
341 | var c = BCSketchInfo.shared().metadata().appVersion;
342 | if (c < 50 || c >= 52) {
343 | var l = this.shorlaceSum();
344 | l < 0
345 | ? (print("🛑 COUNTERCLOCKWISE"),
346 | this.reverseSymmetry())
347 | : l > 0
348 | ? print("🛑 CLOCKWISE")
349 | : print("🛑 UNDEFINED CHIRALITY");
350 | } else
351 | c < 52 &&
352 | (1 ===
353 | this.targetPath.contours().firstObject().isClockwise()
354 | ? (this.reverseSymmetry(), print("🛑 CLOCKWISE"))
355 | : print("🛑 COUNTERCLOCKWISE"),
356 | print("🛑 UNDEFINED CHIRALITY"));
357 | print(
358 | "🔄↔️ Angle has just guessed rotation and symmetry for this shape"
359 | ),
360 | this.imprintValue_forKey(!0, "guessed-rotation");
361 | }
362 | }
363 | };
364 | })(),
365 | },
366 | {
367 | key: "shorlaceSum",
368 | value: (function () {
369 | return function () {
370 | var e = this.pointsFromBezierPath,
371 | t = Math.max.apply(
372 | Math,
373 | a(
374 | e.map(function (e) {
375 | return e.y;
376 | })
377 | )
378 | );
379 | return Array.from({ length: 4 }, function (e, t) {
380 | return t;
381 | }).reduce(function (r, n) {
382 | return (
383 | r +
384 | (-e[n].x + e[(n + 1) % 4].x) *
385 | (2 * t - e[n].y - e[(n + 1) % 4].y)
386 | );
387 | }, 0);
388 | };
389 | })(),
390 | },
391 | {
392 | key: "maximumVerticesWidthAndHeight",
393 | value: (function () {
394 | return function () {
395 | var e = this.verticesLengths.rotated(this.rotation % 2);
396 | return [Math.max(e[0], e[2]), Math.max(e[1], e[3])];
397 | };
398 | })(),
399 | },
400 | {
401 | key: "rotate",
402 | value: (function () {
403 | return function () {
404 | this.rotation = (this.rotation + (this.reversed ? 1 : 3)) % 4;
405 | };
406 | })(),
407 | },
408 | {
409 | key: "reverseSymmetry",
410 | value: (function () {
411 | return function () {
412 | this.rotate(), (this.reversed = !this.reversed);
413 | };
414 | })(),
415 | },
416 | {
417 | key: "mappedIndexFor",
418 | value: (function () {
419 | return function (e) {
420 | return this.reversed
421 | ? [0, 3, 2, 1][(e + this.rotation) % 4]
422 | : (e + this.rotation) % 4;
423 | };
424 | })(),
425 | },
426 | {
427 | key: "lossyCompressionOfImage_atRate",
428 | value: (function () {
429 | return function (e, t) {
430 | var r = NSBitmapImageRep.alloc().initWithCIImage(e),
431 | n = NSMutableDictionary.dictionary();
432 | n.setObject_forKey(
433 | NSTIFFCompressionJPEG,
434 | NSImageCompressionMethod
435 | ),
436 | n.setObject_forKey(t, NSImageCompressionFactor),
437 | n.setObject_forKey(
438 | NSColor.whiteColor(),
439 | NSImageFallbackBackgroundColor
440 | );
441 | var i = r.representationUsingType_properties(
442 | NSJPEGFileType,
443 | n
444 | );
445 | return NSImage.alloc().initWithData(i);
446 | };
447 | })(),
448 | },
449 | {
450 | key: "pixelAccurateRepresentationOfImage",
451 | value: (function () {
452 | return function (e) {
453 | var t = NSCIImageRep.alloc().initWithCIImage(e),
454 | r = NSImage.alloc().initWithSize(t.size());
455 | return r.addRepresentation(t), r;
456 | };
457 | })(),
458 | },
459 | {
460 | key: "pointsAreValid_lessThan50",
461 | get: (function () {
462 | return function () {
463 | var e = this.pointsFromBezierPath;
464 | return null !== e && 7 === e.length;
465 | };
466 | })(),
467 | },
468 | {
469 | key: "pointsAreValid_lessThan52",
470 | get: (function () {
471 | return function () {
472 | var e = this.targetPath.contours().firstObject(),
473 | t = Array.fromNSArray(e.segments());
474 | return (
475 | null !== t &&
476 | 4 === t.length &&
477 | !t.some(function (e) {
478 | return e.segmentType() != s.linear;
479 | })
480 | );
481 | };
482 | })(),
483 | },
484 | {
485 | key: "pointsAreValid",
486 | get: (function () {
487 | return function () {
488 | var e = BCSketchInfo.shared().metadata().appVersion;
489 | if (e < 50) return this.pointsAreValid_lessThan50;
490 | if (e < 52) return this.pointsAreValid_lessThan52;
491 | var t = this.targetLayer.points();
492 | return (
493 | null !== t &&
494 | 4 === t.length &&
495 | !t.some(function (e) {
496 | return !e.isStraight();
497 | })
498 | );
499 | };
500 | })(),
501 | },
502 | {
503 | key: "pointsFromBezierPath",
504 | get: (function () {
505 | return function () {
506 | var e = this,
507 | t = BCSketchInfo.shared().metadata().appVersion;
508 | if (t < 50) {
509 | var r = this.targetPath.elementCount();
510 | return 7 != r
511 | ? null
512 | : Array.from({ length: r }, function (e, t) {
513 | return t;
514 | }).map(function (t) {
515 | var r = MOPointer.alloc().initWithValue_(
516 | CGPointMake(0, 0)
517 | );
518 | return (
519 | e.targetPath.elementAtIndex_associatedPoints_(t, r),
520 | r.value()
521 | );
522 | });
523 | }
524 | if (t < 52) {
525 | var n = this.targetPath.contours().firstObject();
526 | return Array.fromNSArray(n.segments()).map(function (e) {
527 | return e.endPoint1();
528 | });
529 | }
530 | var i = this.targetLayer.rect().size;
531 | return Array.fromNSArray(this.targetLayer.points())
532 | .map(function (e) {
533 | return e.point();
534 | })
535 | .map(function (e) {
536 | return {
537 | x: Number(e.x) * Number(i.width),
538 | y: Number(e.y) * Number(i.height),
539 | };
540 | });
541 | };
542 | })(),
543 | },
544 | {
545 | key: "verticesLengths",
546 | get: (function () {
547 | return function () {
548 | var e = this.pointsFromBezierPath;
549 | return Array.from({ length: 4 }, function (e, t) {
550 | return t;
551 | }).map(function (t) {
552 | var r = (t + 1) % 4,
553 | n = e[t].x - e[r].x,
554 | i = e[t].y - e[r].y;
555 | return Math.sqrt(Math.pow(n, 2) + Math.pow(i, 2));
556 | });
557 | };
558 | })(),
559 | },
560 | {
561 | key: "normalizedCIVectors",
562 | get: (function () {
563 | return function () {
564 | var e = this.pointsFromBezierPath,
565 | t = Math.max.apply(
566 | Math,
567 | a(
568 | e.map(function (e) {
569 | return e.y;
570 | })
571 | )
572 | ),
573 | r = this.pixelDensity;
574 | return e.map(function (e) {
575 | return CIVector.vectorWithX_Y(e.x * r, (t - e.y) * r);
576 | });
577 | };
578 | })(),
579 | },
580 | {
581 | key: "transformedImage",
582 | get: (function () {
583 | return function () {
584 | var e = this.normalizedCIVectors,
585 | t = CIFilter.filterWithName("CIPerspectiveTransform");
586 | t.setValue_forKey(e[this.mappedIndexFor(0)], "inputTopLeft"),
587 | t.setValue_forKey(
588 | e[this.mappedIndexFor(1)],
589 | "inputTopRight"
590 | ),
591 | t.setValue_forKey(
592 | e[this.mappedIndexFor(2)],
593 | "inputBottomRight"
594 | ),
595 | t.setValue_forKey(
596 | e[this.mappedIndexFor(3)],
597 | "inputBottomLeft"
598 | );
599 | var r = this.ciImage();
600 | t.setValue_forKey(r, "inputImage");
601 | var n = t.valueForKey("outputImage");
602 | if (n) {
603 | var i = void 0,
604 | a = o.CompressionRatio[this.compressionRatio].ratio;
605 | return (
606 | (i =
607 | 1 != a
608 | ? this.lossyCompressionOfImage_atRate(n, a)
609 | : this.pixelAccurateRepresentationOfImage(n)),
610 | BCSketchInfo.shared().metadata().appVersion < 47
611 | ? MSImageData.alloc().initWithImage_convertColorSpace(
612 | i,
613 | !0
614 | )
615 | : MSImageData.alloc().initWithImage_(i)
616 | );
617 | }
618 | print("🛑 Unable to form perspective image");
619 | };
620 | })(),
621 | },
622 | ]),
623 | e
624 | );
625 | })();
626 | r.default = u;
627 | },
628 | function (e, t, r) {
629 | Object.defineProperty(t, "__esModule", { value: !0 });
630 | var n,
631 | i = (function () {
632 | return function (e, t) {
633 | if (Array.isArray(e)) return e;
634 | if (Symbol.iterator in Object(e))
635 | return (function (e, t) {
636 | var r = [],
637 | n = !0,
638 | i = !1,
639 | o = void 0;
640 | try {
641 | for (
642 | var a, s = e[Symbol.iterator]();
643 | !(n = (a = s.next()).done) &&
644 | (r.push(a.value), !t || r.length !== t);
645 | n = !0
646 | );
647 | } catch (e) {
648 | (i = !0), (o = e);
649 | } finally {
650 | try {
651 | !n && s.return && s.return();
652 | } finally {
653 | if (i) throw o;
654 | }
655 | }
656 | return r;
657 | })(e, t);
658 | throw new TypeError(
659 | "Invalid attempt to destructure non-iterable instance"
660 | );
661 | };
662 | })(),
663 | o = (function () {
664 | function e(e, t) {
665 | for (var r = 0; r < t.length; r++) {
666 | var n = t[r];
667 | (n.enumerable = n.enumerable || !1),
668 | (n.configurable = !0),
669 | "value" in n && (n.writable = !0),
670 | Object.defineProperty(e, n.key, n);
671 | }
672 | }
673 | return function (t, r, n) {
674 | return r && e(t.prototype, r), n && e(t, n), t;
675 | };
676 | })(),
677 | a = r(1),
678 | s = (n = a) && n.__esModule ? n : { default: n },
679 | u = r(0);
680 | function c(e, t) {
681 | if (!e)
682 | throw new ReferenceError(
683 | "this hasn't been initialised - super() hasn't been called"
684 | );
685 | return !t || ("object" != typeof t && "function" != typeof t) ? e : t;
686 | }
687 | var l = (function (e) {
688 | function t() {
689 | var e =
690 | arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
691 | !(function (e, t) {
692 | if (!(e instanceof t))
693 | throw new TypeError("Cannot call a class as a function");
694 | })(this, t);
695 | var r = c(
696 | this,
697 | (t.__proto__ || Object.getPrototypeOf(t)).call(this, e)
698 | );
699 | if (
700 | ((r.targetLayer = e.override.affectedLayer()),
701 | r.targetLayer.class() === MSImmutableBitmapLayer)
702 | )
703 | return c(r, u.Error.symbolWithBitMapLayer);
704 | var n = BCSketchInfo.shared().metadata().appVersion;
705 | n < 50
706 | ? (r.targetPath = e.override.affectedLayer().bezierPath())
707 | : n < 52 &&
708 | (r.targetPath = e.override
709 | .affectedLayer()
710 | .pathInFrameWithTransforms());
711 | var i = e.override.overridePoint().parent();
712 | return (
713 | null !== i && (r.overrideLayer = i),
714 | r.pointsAreValid ? r : c(r, u.Error.unsupportedShapePath)
715 | );
716 | }
717 | return (
718 | (function (e, t) {
719 | if ("function" != typeof t && null !== t)
720 | throw new TypeError(
721 | "Super expression must either be null or a function, not " +
722 | typeof t
723 | );
724 | (e.prototype = Object.create(t && t.prototype, {
725 | constructor: {
726 | value: e,
727 | enumerable: !1,
728 | writable: !0,
729 | configurable: !0,
730 | },
731 | })),
732 | t &&
733 | (Object.setPrototypeOf
734 | ? Object.setPrototypeOf(e, t)
735 | : (e.__proto__ = t));
736 | })(t, s["default"]),
737 | o(t, [
738 | {
739 | key: "applyImage",
740 | value: (function () {
741 | return function () {
742 | var e = this.targetLayer.objectID(),
743 | t =
744 | this.selectedLayer.overrides() ||
745 | NSDictionary.dictionary(),
746 | r = NSMutableDictionary.dictionaryWithDictionary(t);
747 | r.setObject_forKey(this.transformedImage, e),
748 | (this.selectedLayer.overrides = r);
749 | };
750 | })(),
751 | },
752 | {
753 | key: "estimatePixelDensity",
754 | value: (function () {
755 | return function () {
756 | var e = this.maximumVerticesWidthAndHeight(),
757 | t = i(e, 2),
758 | r = t[0],
759 | n = t[1],
760 | o =
761 | (this.selectedLayer.rect().size.width * r) /
762 | (this.selectedLayer.naturalSize().width *
763 | this.artboard.rect().size.width),
764 | a =
765 | (this.selectedLayer.rect().size.height * n) /
766 | (this.selectedLayer.naturalSize().height *
767 | this.artboard.rect().size.height);
768 | return o > a ? o : a;
769 | };
770 | })(),
771 | },
772 | {
773 | key: "description",
774 | value: (function () {
775 | return function () {
776 | return (
777 | this.selectedLayer.name() + " " + this.targetLayer.name()
778 | );
779 | };
780 | })(),
781 | },
782 | ]),
783 | t
784 | );
785 | })();
786 | t.default = l;
787 | },
788 | function (e, t, r) {
789 | Object.defineProperty(t, "__esModule", { value: !0 }),
790 | (t.default = function (e) {
791 | var t = e.selection[0];
792 | if (null != t) {
793 | var r = Array.fromNSArray(t);
794 | if (0 != r.length) {
795 | var n = o.default.tryCreating({ for: r, in: e }),
796 | i = n.filter(function (e) {
797 | return e instanceof o.default;
798 | }),
799 | u = n.filter(function (e) {
800 | return !(e instanceof o.default);
801 | });
802 | 0 != i.length
803 | ? (i.forEach(function (e) {
804 | e.reverseSymmetry(), e.applyImage();
805 | }),
806 | a.show({
807 | message: "Angle flipped! ↔️",
808 | inDocument: e.document,
809 | }))
810 | : a.show({ message: u[0].message, inDocument: e.document });
811 | } else
812 | a.show({
813 | message: s.Error.emptySelection.message,
814 | inDocument: e.document,
815 | });
816 | } else
817 | a.show({
818 | message: s.Error.emptySelection.message,
819 | inDocument: e.document,
820 | });
821 | });
822 | var n,
823 | i = r(1),
824 | o = (n = i) && n.__esModule ? n : { default: n },
825 | a = (function (e) {
826 | if (e && e.__esModule) return e;
827 | var t = {};
828 | if (null != e)
829 | for (var r in e)
830 | Object.prototype.hasOwnProperty.call(e, r) && (t[r] = e[r]);
831 | return (t.default = e), t;
832 | })(r(5)),
833 | s = r(0);
834 | },
835 | function (e, t) {
836 | Object.defineProperty(t, "__esModule", { value: !0 });
837 | t.CompressionRatio = [
838 | { selectionLabel: "Best", ratio: 1 },
839 | { selectionLabel: "Better", ratio: 0.9 },
840 | { selectionLabel: "Good", ratio: 0.8 },
841 | { selectionLabel: "Average", ratio: 0.7 },
842 | ];
843 | },
844 | function (e, t, r) {
845 | Object.defineProperty(t, "__esModule", { value: !0 }),
846 | (t.show = function (e) {
847 | var t = e.message,
848 | r = e.inDocument;
849 | void 0 != r && void 0 != r.showMessage && r.showMessage(t);
850 | print(t);
851 | }),
852 | (t.filterPossibleArtboards = function (e) {
853 | var t = e.class();
854 | switch (t) {
855 | case MSArtboardGroup:
856 | var r = e,
857 | n = r.frame();
858 | if (n.width() < 250 || n.height() < 250) return !1;
859 | var i = n.width() / n.height();
860 | if ((i > 1 && (i = 1 / i), i < 0.4)) return !1;
861 | break;
862 | case MSSymbolMaster:
863 | return !1;
864 | default:
865 | return print(t), !1;
866 | }
867 | return !0;
868 | }),
869 | (t.compareByRatioAndAlphabet = function (e, t) {
870 | var r = e.frame(),
871 | n = t.frame(),
872 | i = r.width() / r.height();
873 | i > 1 && (i = 1 / i);
874 | var o = i > 0.4 && i < 0.8,
875 | a = n.width() / n.height();
876 | a > 1 && (a = 1 / a);
877 | var s = a > 0.4 && a < 0.8;
878 | if (o && !s) return !1;
879 | if (s && !o) return !0;
880 | if (i == a) return e.name() > t.name();
881 | return i > a;
882 | }),
883 | (t.introspect = function (e) {
884 | var t = e.class().mocha();
885 | print("-----------------------------------------------"),
886 | print("PROPERTIES-------------------------------------"),
887 | print("-----------------------------------------------"),
888 | print(t.properties()),
889 | print(t.propertiesWithAncestors()),
890 | print("-----------------------------------------------"),
891 | print("INSTANCE METHODS-------------------------------"),
892 | print("-----------------------------------------------"),
893 | print(t.instanceMethods()),
894 | print(t.instanceMethodsWithAncestors()),
895 | print("-----------------------------------------------"),
896 | print("CLASS METHODS----------------------------------"),
897 | print("-----------------------------------------------"),
898 | print(t.classMethods()),
899 | print(t.classMethodsWithAncestors()),
900 | print("-----------------------------------------------"),
901 | print("PROTOCOLS--------------------------------------"),
902 | print("-----------------------------------------------"),
903 | print(t.protocols()),
904 | print(t.protocolsWithAncestors());
905 | }),
906 | (t.createLabel = function (e, t, r) {
907 | var n = NSTextField.alloc().initWithFrame(r);
908 | return (
909 | n.setStringValue(e),
910 | n.setFont(NSFont.boldSystemFontOfSize(t)),
911 | n.setBezeled(!1),
912 | n.setDrawsBackground(!1),
913 | n.setEditable(!1),
914 | n.setSelectable(!1),
915 | n
916 | );
917 | }),
918 | (t.popUpButtonsforRectangleIndexer_withTitleIndexer_andImageIndexer_defaultSelected_onIndex =
919 | function (e, t, r, n) {
920 | var i = NSPopUpButton.alloc().initWithFrame(e(n));
921 | i.addItemsWithTitles(t),
922 | null != r &&
923 | ((i.imageScaling = NSImageScaleProportionallyUpOrDown),
924 | Array.fromNSArray(i.itemArray()).forEach(function (e, t, n) {
925 | e.image = r[t];
926 | }));
927 | return i;
928 | }),
929 | (t.smallImagesFromArtboard = function (e) {
930 | if (e.class() == MSSymbolMaster) return print(e), null;
931 | void 0 == e.frame && print(e);
932 | var t = e.frame().width(),
933 | r = e.frame().height(),
934 | n = t / r;
935 | n > 1 && (n = 1 / n);
936 | if (n > 0.8 || n < 0.4) return null;
937 | var i = NSClassFromString("SketchModel.MSImmutableLayerAncestry")
938 | .alloc()
939 | .initWithMutableLayer(e),
940 | o = 48 / (t > r ? t : r),
941 | a = MSExportFormat.formatWithScale_name_fileFormat(o, "", "png"),
942 | s = MSExportRequest.exportRequestsFromLayerAncestry_exportFormats(
943 | i,
944 | [a]
945 | ).firstObject();
946 | return MSExporter.exporterForRequest_colorSpace(
947 | s,
948 | NSColorSpace.sRGBColorSpace()
949 | ).previewImage();
950 | });
951 | var n = u(r(1)),
952 | i = u(r(6)),
953 | o = u(r(2)),
954 | a = u(r(7)),
955 | s = r(0);
956 | function u(e) {
957 | return e && e.__esModule ? e : { default: e };
958 | }
959 | (n.default.tryCreating = function (e) {
960 | var t = e.for,
961 | r = e.in;
962 | return t
963 | .map(function (e) {
964 | switch (e.class()) {
965 | case MSSymbolInstance:
966 | var t = Array.fromNSArray(e.availableOverrides()) || [],
967 | n = t
968 | .filter(function (e) {
969 | return e.currentValue().class() == MSImageData;
970 | })
971 | .map(function (t) {
972 | return new o.default({
973 | selectedLayer: e,
974 | context: r,
975 | override: t,
976 | });
977 | }),
978 | u = t
979 | .map(function (e) {
980 | return e.children();
981 | })
982 | .filter(function (e) {
983 | return null != e;
984 | })
985 | .map(Array.fromNSArray)
986 | .reduce(function (e, t) {
987 | return e.concat(t);
988 | }, [])
989 | .filter(function (e) {
990 | return e.class() == MSAvailableOverride;
991 | })
992 | .map(function (t) {
993 | return new i.default({
994 | override: t,
995 | selectedLayer: e,
996 | context: r,
997 | });
998 | });
999 | return n.concat(u);
1000 | case MSShapeGroup:
1001 | case MSShapePathLayer:
1002 | case MSRectangleShape:
1003 | return new a.default({ selectedLayer: e, context: r });
1004 | default:
1005 | return s.Error.unsupportedElement;
1006 | }
1007 | })
1008 | .reduce(function (e, t, r, n) {
1009 | return e.concat(t);
1010 | }, []);
1011 | }),
1012 | (Array.fromNSArray = function (e) {
1013 | for (var t = [], r = 0; r < e.length; r++) t.push(e[r]);
1014 | return t;
1015 | }),
1016 | (Array.prototype.print = function () {
1017 | return this.map(function (e) {
1018 | return print(e), e;
1019 | });
1020 | });
1021 | },
1022 | function (e, t, r) {
1023 | Object.defineProperty(t, "__esModule", { value: !0 });
1024 | var n,
1025 | i = (function () {
1026 | function e(e, t) {
1027 | for (var r = 0; r < t.length; r++) {
1028 | var n = t[r];
1029 | (n.enumerable = n.enumerable || !1),
1030 | (n.configurable = !0),
1031 | "value" in n && (n.writable = !0),
1032 | Object.defineProperty(e, n.key, n);
1033 | }
1034 | }
1035 | return function (t, r, n) {
1036 | return r && e(t.prototype, r), n && e(t, n), t;
1037 | };
1038 | })(),
1039 | o = (function () {
1040 | return function e(t, r, n) {
1041 | null === t && (t = Function.prototype);
1042 | var i = Object.getOwnPropertyDescriptor(t, r);
1043 | if (void 0 === i) {
1044 | var o = Object.getPrototypeOf(t);
1045 | return null === o ? void 0 : e(o, r, n);
1046 | }
1047 | if ("value" in i) return i.value;
1048 | var a = i.get;
1049 | return void 0 !== a ? a.call(n) : void 0;
1050 | };
1051 | })(),
1052 | a = r(2),
1053 | s = (n = a) && n.__esModule ? n : { default: n };
1054 | r(0);
1055 | var u = (function (e) {
1056 | function t() {
1057 | var e =
1058 | arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
1059 | !(function (e, t) {
1060 | if (!(e instanceof t))
1061 | throw new TypeError("Cannot call a class as a function");
1062 | })(this, t);
1063 | var r = (function (e, t) {
1064 | if (!e)
1065 | throw new ReferenceError(
1066 | "this hasn't been initialised - super() hasn't been called"
1067 | );
1068 | return !t || ("object" != typeof t && "function" != typeof t)
1069 | ? e
1070 | : t;
1071 | })(this, (t.__proto__ || Object.getPrototypeOf(t)).call(this, e));
1072 | return (r.override = e.override), r;
1073 | }
1074 | return (
1075 | (function (e, t) {
1076 | if ("function" != typeof t && null !== t)
1077 | throw new TypeError(
1078 | "Super expression must either be null or a function, not " +
1079 | typeof t
1080 | );
1081 | (e.prototype = Object.create(t && t.prototype, {
1082 | constructor: {
1083 | value: e,
1084 | enumerable: !1,
1085 | writable: !0,
1086 | configurable: !0,
1087 | },
1088 | })),
1089 | t &&
1090 | (Object.setPrototypeOf
1091 | ? Object.setPrototypeOf(e, t)
1092 | : (e.__proto__ = t));
1093 | })(t, s["default"]),
1094 | i(t, [
1095 | {
1096 | key: "loadValueForKey",
1097 | value: (function () {
1098 | return function (e) {
1099 | return o(
1100 | t.prototype.__proto__ || Object.getPrototypeOf(t.prototype),
1101 | "loadValueForKey",
1102 | this
1103 | ).call(this, this.targetLayer.objectID() + "-" + e);
1104 | };
1105 | })(),
1106 | },
1107 | {
1108 | key: "imprintValue_forKey",
1109 | value: (function () {
1110 | return function (e, r) {
1111 | o(
1112 | t.prototype.__proto__ || Object.getPrototypeOf(t.prototype),
1113 | "imprintValue_forKey",
1114 | this
1115 | ).call(this, e, this.targetLayer.objectID() + "-" + r);
1116 | };
1117 | })(),
1118 | },
1119 | {
1120 | key: "applyImage",
1121 | value: (function () {
1122 | return function () {
1123 | var e =
1124 | this.selectedLayer.overrides() ||
1125 | NSDictionary.dictionary(),
1126 | t = NSMutableDictionary.dictionaryWithDictionary(e),
1127 | r = (this.overrideLayer + "").replace("_symbolID", ""),
1128 | n = t.objectForKey(r) || NSMutableDictionary.dictionary(),
1129 | i = NSMutableDictionary.dictionaryWithDictionary(n),
1130 | o = this.targetLayer.objectID();
1131 | i.setObject_forKey(this.transformedImage, o),
1132 | t.setObject_forKey(i, r),
1133 | (this.selectedLayer.overrides = t);
1134 | };
1135 | })(),
1136 | },
1137 | {
1138 | key: "description",
1139 | value: (function () {
1140 | return function () {
1141 | return (
1142 | this.override.parent().affectedLayer().name() +
1143 | " " +
1144 | this.targetLayer.name()
1145 | );
1146 | };
1147 | })(),
1148 | },
1149 | ]),
1150 | t
1151 | );
1152 | })();
1153 | t.default = u;
1154 | },
1155 | function (e, t, r) {
1156 | Object.defineProperty(t, "__esModule", { value: !0 });
1157 | var n,
1158 | i = (function () {
1159 | return function (e, t) {
1160 | if (Array.isArray(e)) return e;
1161 | if (Symbol.iterator in Object(e))
1162 | return (function (e, t) {
1163 | var r = [],
1164 | n = !0,
1165 | i = !1,
1166 | o = void 0;
1167 | try {
1168 | for (
1169 | var a, s = e[Symbol.iterator]();
1170 | !(n = (a = s.next()).done) &&
1171 | (r.push(a.value), !t || r.length !== t);
1172 | n = !0
1173 | );
1174 | } catch (e) {
1175 | (i = !0), (o = e);
1176 | } finally {
1177 | try {
1178 | !n && s.return && s.return();
1179 | } finally {
1180 | if (i) throw o;
1181 | }
1182 | }
1183 | return r;
1184 | })(e, t);
1185 | throw new TypeError(
1186 | "Invalid attempt to destructure non-iterable instance"
1187 | );
1188 | };
1189 | })(),
1190 | o = (function () {
1191 | function e(e, t) {
1192 | for (var r = 0; r < t.length; r++) {
1193 | var n = t[r];
1194 | (n.enumerable = n.enumerable || !1),
1195 | (n.configurable = !0),
1196 | "value" in n && (n.writable = !0),
1197 | Object.defineProperty(e, n.key, n);
1198 | }
1199 | }
1200 | return function (t, r, n) {
1201 | return r && e(t.prototype, r), n && e(t, n), t;
1202 | };
1203 | })(),
1204 | a = r(1),
1205 | s = (n = a) && n.__esModule ? n : { default: n },
1206 | u = r(0);
1207 | function c(e, t) {
1208 | if (!e)
1209 | throw new ReferenceError(
1210 | "this hasn't been initialised - super() hasn't been called"
1211 | );
1212 | return !t || ("object" != typeof t && "function" != typeof t) ? e : t;
1213 | }
1214 | var l = { solid: 0, gradient: 1, pattern: 4, noise: 5 },
1215 | f = (function (e) {
1216 | function t() {
1217 | var e =
1218 | arguments.length > 0 && void 0 !== arguments[0]
1219 | ? arguments[0]
1220 | : {};
1221 | !(function (e, t) {
1222 | if (!(e instanceof t))
1223 | throw new TypeError("Cannot call a class as a function");
1224 | })(this, t);
1225 | var r = c(
1226 | this,
1227 | (t.__proto__ || Object.getPrototypeOf(t)).call(this, e)
1228 | );
1229 | r.targetLayer = r.selectedLayer;
1230 | var n = BCSketchInfo.shared().metadata().appVersion;
1231 | return (
1232 | n < 50
1233 | ? (r.targetPath = r.selectedLayer.bezierPath())
1234 | : n < 52 &&
1235 | (r.targetPath = r.selectedLayer.pathInFrameWithTransforms()),
1236 | r.pointsAreValid ? r : c(r, u.Error.unsupportedShapePath)
1237 | );
1238 | }
1239 | return (
1240 | (function (e, t) {
1241 | if ("function" != typeof t && null !== t)
1242 | throw new TypeError(
1243 | "Super expression must either be null or a function, not " +
1244 | typeof t
1245 | );
1246 | (e.prototype = Object.create(t && t.prototype, {
1247 | constructor: {
1248 | value: e,
1249 | enumerable: !1,
1250 | writable: !0,
1251 | configurable: !0,
1252 | },
1253 | })),
1254 | t &&
1255 | (Object.setPrototypeOf
1256 | ? Object.setPrototypeOf(e, t)
1257 | : (e.__proto__ = t));
1258 | })(t, s["default"]),
1259 | o(t, [
1260 | {
1261 | key: "applyImage",
1262 | value: (function () {
1263 | return function () {
1264 | var e = MSStyleFill.alloc().init();
1265 | e.setImage(this.transformedImage),
1266 | (e.fillType = l.pattern),
1267 | this.targetLayer.style().removeAllStyleFills(),
1268 | this.targetLayer.style().addStyleFill(e);
1269 | };
1270 | })(),
1271 | },
1272 | {
1273 | key: "estimatePixelDensity",
1274 | value: (function () {
1275 | return function () {
1276 | var e = this.maximumVerticesWidthAndHeight(),
1277 | t = i(e, 2),
1278 | r = t[0],
1279 | n = t[1],
1280 | o = r / this.artboard.rect().size.width,
1281 | a = n / this.artboard.rect().size.height;
1282 | return o > a ? o : a;
1283 | };
1284 | })(),
1285 | },
1286 | {
1287 | key: "description",
1288 | value: (function () {
1289 | return function () {
1290 | return this.targetLayer.name();
1291 | };
1292 | })(),
1293 | },
1294 | ]),
1295 | t
1296 | );
1297 | })();
1298 | t.default = f;
1299 | },
1300 | ]);
1301 | "default" === e && "function" == typeof r ? r(t) : r[e](t);
1302 | }
1303 | that.onRun = __skpm_run.bind(this, "default");
1304 |
--------------------------------------------------------------------------------
/Angle.sketchplugin/Contents/Sketch/symmetry.js~HEAD:
--------------------------------------------------------------------------------
1 | var that = this;
2 | function __skpm_run (key, context) {
3 | that.context = context;
4 |
5 | var exports =
6 | /******/ (function(modules) { // webpackBootstrap
7 | /******/ // The module cache
8 | /******/ var installedModules = {};
9 | /******/
10 | /******/ // The require function
11 | /******/ function __webpack_require__(moduleId) {
12 | /******/
13 | /******/ // Check if module is in cache
14 | /******/ if(installedModules[moduleId]) {
15 | /******/ return installedModules[moduleId].exports;
16 | /******/ }
17 | /******/ // Create a new module (and put it into the cache)
18 | /******/ var module = installedModules[moduleId] = {
19 | /******/ i: moduleId,
20 | /******/ l: false,
21 | /******/ exports: {}
22 | /******/ };
23 | /******/
24 | /******/ // Execute the module function
25 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
26 | /******/
27 | /******/ // Flag the module as loaded
28 | /******/ module.l = true;
29 | /******/
30 | /******/ // Return the exports of the module
31 | /******/ return module.exports;
32 | /******/ }
33 | /******/
34 | /******/
35 | /******/ // expose the modules object (__webpack_modules__)
36 | /******/ __webpack_require__.m = modules;
37 | /******/
38 | /******/ // expose the module cache
39 | /******/ __webpack_require__.c = installedModules;
40 | /******/
41 | /******/ // define getter function for harmony exports
42 | /******/ __webpack_require__.d = function(exports, name, getter) {
43 | /******/ if(!__webpack_require__.o(exports, name)) {
44 | /******/ Object.defineProperty(exports, name, {
45 | /******/ configurable: false,
46 | /******/ enumerable: true,
47 | /******/ get: getter
48 | /******/ });
49 | /******/ }
50 | /******/ };
51 | /******/
52 | /******/ // getDefaultExport function for compatibility with non-harmony modules
53 | /******/ __webpack_require__.n = function(module) {
54 | /******/ var getter = module && module.__esModule ?
55 | /******/ function getDefault() { return module['default']; } :
56 | /******/ function getModuleExports() { return module; };
57 | /******/ __webpack_require__.d(getter, 'a', getter);
58 | /******/ return getter;
59 | /******/ };
60 | /******/
61 | /******/ // Object.prototype.hasOwnProperty.call
62 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
63 | /******/
64 | /******/ // __webpack_public_path__
65 | /******/ __webpack_require__.p = "";
66 | /******/
67 | /******/ // Load entry module and return exports
68 | /******/ return __webpack_require__(__webpack_require__.s = 3);
69 | /******/ })
70 | /************************************************************************/
71 | /******/ ({
72 |
73 | /***/ 3:
74 | /***/ (function(module, exports) {
75 |
76 | throw new Error("Module build failed: Error: ENOENT: no such file or directory, open '/Users/tmergulhao/Source/Angle for Sketch/src/symmetry.js'");
77 |
78 | /***/ })
79 |
80 | /******/ });
81 | if (key === 'default' && typeof exports === 'function') {
82 | exports(context);
83 | } else {
84 | exports[key](context);
85 | }
86 | }
87 | that['onRun'] = __skpm_run.bind(this, 'default')
88 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 | Angle is a free and lightweight Sketch plugin for applying perspective transforms for your mockups. You can get the **[starting template](https://angle.sh)** to help you design beautiful mockups from scratch. Check out the **[full tutorial](https://www.youtube.com/watch?v=5uffgI-J29I)**.
3 |
4 | # Getting Started
5 |
6 | The only thing that Angle needs to work is an Artboard containing your Screen. That's it!
7 | 
8 |
9 | ## Installation
10 |
11 | Make sure you have the latest version of Sketch (72+) running on macOS Catalina (10.15.0) or newer.
12 |
13 | - [Download the zip file](https://github.com/MengTo/Angle-Sketch-Plugin/archive/master.zip).
14 | - Double-click on Angle.sketchplugin
15 |
16 | #### Important note:
17 | - This plugin may not work for Sketch 93+. You can use [Mockup](https://github.com/ruslanlatypov/Mockup-Plugin-for-Sketch) (make sure to Detach from Symbol and once applied, rotate 3 times). This will work with Angle mockups.
18 | - use version [1.1.7](https://github.com/MengTo/Angle-Sketch-Plugin/releases/download/v1.1.7/Angle.sketchplugin.zip) for Sketch 86+
19 | - use version [1.1.6](https://github.com/MengTo/Angle-Sketch-Plugin/releases/download/v1.1.6/Angle.sketchplugin.zip) for Sketch 72 to Sketch 85.1
20 | - use version [1.1.5](https://github.com/MengTo/Angle-Sketch-Plugin/releases/download/v1.1.5/Angle.sketchplugin.zip) for Sketch 66 to Sketch 71.2
21 | - use version [1.1.4](https://github.com/MengTo/Angle-Sketch-Plugin/releases/download/v1.1.4/Angle.sketchplugin.zip) for Sketch 65 and earlier.
22 |
23 | Apply perspective transforms on screen mockups. Auto-detect screens by resolution and works on shapes and symbols.
24 |
25 | ## Usage
26 |
27 | Select a shape layer and do **Apply Mockup** `Command + \`.
28 | 
29 |
30 | - **Apply Mockup** `Command + \`: this will apply an Artboard to your selected shape.
31 |
32 | ## Auto-Detect
33 |
34 | When applying a mockup, Angle automatically detects all the Artboards, except the current Artboard. No expensive operations while you're designing, as this only happens when you run one of Angle's commands.
35 | 
36 |
37 | ## Single Artboard
38 |
39 | If you have a single Artboard with your screen, Angle will skip the modal and apply right away. Boom!
40 |
41 | ## Working with Symbols
42 |
43 | If you have a Symbol that contains your Mockup, make sure to have an **Image Fill**. That's how Angle knows that your Symbol contains a mockup.
44 | 
45 |
46 | ## Multiple Shapes and Nested Symbols
47 |
48 | If you have multiple shapes or a Nested Symbols, you can apply the mockups to multiple destinations.
49 |
50 | ## Pixel Density
51 |
52 | By default, it's set to **Auto**, which will detect the size of selected shape and apply a **2x** pixel density. You can set to **1x**, **2x**, **3x** or **4x**.
53 |
54 | ## Image Quality
55 |
56 | By default, it's set the **Best**. While you'll get the highest quality possible, this will increase your filesize dramatically. By setting to **Better**, **Good** or **Average**, you will make the file smaller.
57 |
58 | ## Credit
59 |
60 | This plugin was made by the team at [Design+Code](https://designcode.io), including [Tiago Mergulhao](https://github.com/tmergulhao), [Meng To](https://twitter.com/mengto) and [Kwan Yip Yap](http://twitter.com/pizza0502).
61 |
--------------------------------------------------------------------------------
/assets/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MengTo/Angle-Sketch-Plugin/c5145c524a2a463611fbb0aa6312943a861c6992/assets/.DS_Store
--------------------------------------------------------------------------------
/assets/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MengTo/Angle-Sketch-Plugin/c5145c524a2a463611fbb0aa6312943a861c6992/assets/icon.png
--------------------------------------------------------------------------------
/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MengTo/Angle-Sketch-Plugin/c5145c524a2a463611fbb0aa6312943a861c6992/assets/logo.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angle",
3 | "version": "1.1.7",
4 | "repository": "https://github.com/MengTo/Angle-Sketch-Plugin",
5 | "description": "Important note: use version 1.1.7 for Sketch 86+, version 1.1.6 for Sketch 72-85, version 1.1.5 for Sketch 66-71 and version 1.1.4 for Sketch 65 and earlier. Apply perspective transforms on screen mockups. Auto-detect screens by resolution and works on shapes and symbols.",
6 | "engines": {
7 | "sketch": ">=3.0"
8 | },
9 | "skpm": {
10 | "name": "Angle",
11 | "manifest": "src/manifest.json",
12 | "main": "Angle.sketchplugin",
13 | "assets": [
14 | "assets/**/*"
15 | ]
16 | },
17 | "scripts": {
18 | "build": "skpm-build",
19 | "watch": "skpm-build --watch",
20 | "start": "skpm-build --watch --run",
21 | "postinstall": "npm run build && skpm-link"
22 | },
23 | "devDependencies": {
24 | "@skpm/builder": "^0.8.0"
25 | },
26 | "dependencies": {
27 | "npm": "^6.14.16",
28 | "skpm": "^1.3.2"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/Angle.js:
--------------------------------------------------------------------------------
1 | import { CompressionRatio } from './CompressionRatio';
2 |
3 | const SegmentType = { linear: 0, quadratic: 1, cubic: 2 };
4 |
5 | Array.prototype.rotated = function (n) {
6 | return this.slice(n, this.length).concat(this.slice(0, n));
7 | };
8 | export default class Angle {
9 | // ---------------------------------
10 | // PERSISTENT PROPERTIES
11 | // ---------------------------------
12 |
13 | get artboardID() {
14 | if (this._artboardID != undefined) {
15 | return this._artboardID;
16 | }
17 |
18 | // Javascript string cohersion
19 | this._artboardID = this.loadValueForKey('artboard-id') + '';
20 |
21 | return this._artboardID;
22 | }
23 | set artboardID(value) {
24 | return;
25 | }
26 |
27 | get artboard() {
28 | if (this._artboard != undefined) {
29 | return this._artboard;
30 | }
31 |
32 | if (this.artboardID == undefined) {
33 | print('🛑 No artboard ID registered');
34 | return;
35 | }
36 |
37 | let artboards = this.context.document.artboards();
38 |
39 | for (let index = 0; index < artboards.count(); index++) {
40 | if (artboards[index].objectID() == this.artboardID) {
41 | this._artboard = artboards[index];
42 | }
43 | }
44 |
45 | if (this._artboard == undefined) {
46 | print('🛑 Not able to retrieve artboard from id in document');
47 | return;
48 | }
49 |
50 | return this._artboard;
51 | }
52 |
53 | set artboard(value) {
54 | this._artboard = value;
55 | this.imprintValue_forKey(value.objectID(), 'artboard-id');
56 | }
57 |
58 | get rotation() {
59 | if (this._rotation == undefined) {
60 | this._rotation = this.loadValueForKey('rotation');
61 | }
62 | return this._rotation;
63 | }
64 | set rotation(value) {
65 | this._rotation = value;
66 | this.imprintValue_forKey(value, 'rotation');
67 | }
68 |
69 | get pixelDensity() {
70 | if (this._pixelDensity == undefined) {
71 | this._pixelDensity = this.loadValueForKey('pixel-density') + 0;
72 | }
73 |
74 | if (this._pixelDensity == 0) {
75 | let roundedEstimate = Math.round(2 * this.estimatePixelDensity() + 0.5);
76 | return roundedEstimate == 0 ? 1 : roundedEstimate;
77 | }
78 |
79 | return this._pixelDensity;
80 | }
81 | set pixelDensity(value) {
82 | this._pixelDensity = value;
83 | this.imprintValue_forKey(value, 'pixel-density');
84 | }
85 |
86 | get compressionRatio() {
87 | if (this._compressionRatio == undefined) {
88 | this._compressionRatio = this.loadValueForKey('compression-ratio') + 0;
89 | }
90 |
91 | return this._compressionRatio;
92 | }
93 | set compressionRatio(value) {
94 | this._compressionRatio = value;
95 | this.imprintValue_forKey(value, 'compression-ratio');
96 | }
97 |
98 | get reversed() {
99 | if (this._reversed == undefined) {
100 | // Javascript boolean cohersion
101 | this._reversed = this.loadValueForKey('reversed') == 1 ? true : false;
102 | }
103 | return this._reversed;
104 | }
105 | set reversed(value) {
106 | this._reversed = value;
107 | this.imprintValue_forKey(value, 'reversed');
108 | }
109 |
110 | // ---------------------------------
111 | // PERSISTENCY METHODS
112 | // ---------------------------------
113 |
114 | imprintValue_forKey(value, key) {
115 | if (this.selectedLayer == null) {
116 | print('🛑 Imprinting value before selected layer assignment');
117 | return;
118 | }
119 |
120 | this.context.command.setValue_forKey_onLayer(
121 | value,
122 | key,
123 | this.selectedLayer
124 | );
125 | }
126 |
127 | loadValueForKey(key) {
128 | if (this.selectedLayer == null) {
129 | print('🛑 Loading value before selected layer assignment');
130 | return null;
131 | }
132 |
133 | let value = this.context.command.valueForKey_onLayer(
134 | key,
135 | this.selectedLayer
136 | );
137 |
138 | return value;
139 | }
140 |
141 | // ---------------------------------
142 | // CONSTRUCTOR
143 | // ---------------------------------
144 |
145 | constructor(options = {}) {
146 | this.context = options.context;
147 | this.selectedLayer = options.selectedLayer;
148 | }
149 |
150 | // ---------------------------------
151 | // IMAGE DATA
152 | // ---------------------------------
153 |
154 | exportRequest_lessThan52() {
155 | // let layerAncestry = MSImmutableLayerAncestry.alloc().initWithMSLayer(this.artboard)
156 | // let layerAncestry = this.artboard.ancestry();
157 |
158 | // MSImmutableLayerAncestry has been renamed(As of V.66.1) and must be called from the class string
159 | let cls = NSClassFromString('SketchModel.MSImmutableLayerAncestry');
160 | let layerAncestry = cls.alloc().initWithMutableLayer(context.selection[0]);
161 |
162 | let exportFormat = MSExportFormat.formatWithScale_name_fileFormat(
163 | this.pixelDensity,
164 | 'Angle',
165 | 'png'
166 | );
167 | return MSExportRequest.exportRequestsFromLayerAncestry_exportFormats(
168 | layerAncestry,
169 | [exportFormat]
170 | ).firstObject();
171 | }
172 |
173 | exporter() {
174 | const colorSpace = this.context.document.colorSpace().CGColorSpace();
175 |
176 | const sketchVersion = BCSketchInfo.shared().metadata().appVersion;
177 | if (sketchVersion < 52)
178 | return MSExporter.exporterForRequest_colorSpace(
179 | this.exportRequest_lessThan52(),
180 | colorSpace
181 | );
182 |
183 | const format = MSExportFormat.alloc().init();
184 | format.fileFormat = 'png';
185 | format.scale = this.pixelDensity;
186 | const request = MSExportRequest.exportRequestsFromExportableLayer_exportFormats_useIDForName(
187 | this.artboard,
188 | [format],
189 | true
190 | ).firstObject();
191 |
192 | return MSExporter.exporterForRequest_colorSpace(request, colorSpace);
193 | }
194 |
195 | ciImage() {
196 | const bitmapRepresentation = this.exporter().bitmapImageRep();
197 |
198 | return CIImage.alloc().initWithCGImage(bitmapRepresentation.CGImage());
199 | // Below works too
200 | // return CIImage.alloc().initWithBitmapImageRep(bitmapRepresentation);
201 | }
202 |
203 | // ---------------------------------
204 | // PATH VALIDATION AND CORRECTION
205 | // ---------------------------------
206 |
207 | get pointsAreValid_lessThan50() {
208 | let points = this.pointsFromBezierPath;
209 |
210 | if (points === null) return false;
211 |
212 | if (points.length !== 7) return false;
213 |
214 | return true;
215 | }
216 |
217 | get pointsAreValid_lessThan52() {
218 | const contour = this.targetPath.contours().firstObject();
219 | const points = Array.fromNSArray(contour.segments());
220 |
221 | if (points === null) return false;
222 |
223 | if (points.length !== 4) return false;
224 |
225 | if (points.some((a) => a.segmentType() != SegmentType.linear)) return false;
226 |
227 | return true;
228 | }
229 |
230 | get pointsAreValid() {
231 | const sketchVersion = BCSketchInfo.shared().metadata().appVersion;
232 |
233 | if (sketchVersion < 50) return this.pointsAreValid_lessThan50;
234 |
235 | if (sketchVersion < 52) return this.pointsAreValid_lessThan52;
236 |
237 | let points = this.targetLayer.points();
238 |
239 | if (points === null) return false;
240 | if (points.length !== 4) return false;
241 | if (points.some((a) => !a.isStraight())) return false;
242 |
243 | return true;
244 | }
245 |
246 | guessRotationAndReversion() {
247 | // Avoid double inference overriding user configuration
248 |
249 | let hasAlreadyGuessed =
250 | this.loadValueForKey('guessed-rotation') === 1 ? true : false;
251 |
252 | if (hasAlreadyGuessed) {
253 | print(
254 | '⚠️ Angle has already guessed rotation and symmetry for this shape'
255 | );
256 | return;
257 | }
258 |
259 | let verticesLengths = this.verticesLengths;
260 |
261 | let artboardSize;
262 |
263 | if (this.artboard.class() == MSSymbolMaster) {
264 | // artboard.frame == undefined
265 | return;
266 | artboardSize = this.artboard.optimalBoundingBox();
267 | } else {
268 | artboardSize = this.artboard.frame();
269 | }
270 |
271 | let firstVerticeLength = verticesLengths[0];
272 | let secondVerticeLength = verticesLengths[1];
273 |
274 | let isHorizontal = firstVerticeLength > secondVerticeLength;
275 | let hasHorizontalArtboard = artboardSize.width() > artboardSize.height();
276 |
277 | if (isHorizontal) {
278 | // Ensures that the first vertice is smaller
279 | print('🛑 HORIZONTAL');
280 | this.rotate();
281 | }
282 |
283 | if (hasHorizontalArtboard) {
284 | print('🛑 HAS HORIZONTAL ARTBOARD');
285 | this.rotate();
286 | }
287 |
288 | let points = this.pointsFromBezierPath;
289 |
290 | var minimumY = Math.min(...points.map((a) => a.y));
291 |
292 | let mappedFirstPoint = points[this.mappedIndexFor(0)];
293 | let mappedSecondPoint = points[this.mappedIndexFor(1)];
294 |
295 | let isUpsideDown = !(
296 | mappedFirstPoint.y == minimumY || mappedSecondPoint.y == minimumY
297 | );
298 |
299 | if (isUpsideDown) {
300 | print('🛑 UPSIDE DOWN');
301 | this.rotate();
302 | this.rotate();
303 | }
304 |
305 | const sketchVersion = BCSketchInfo.shared().metadata().appVersion;
306 | if (sketchVersion < 50 || sketchVersion >= 52) {
307 | let shoelaceSumOfPoints = this.shorlaceSum();
308 | if (shoelaceSumOfPoints < 0) {
309 | print('🛑 COUNTERCLOCKWISE');
310 | this.reverseSymmetry();
311 | } else if (shoelaceSumOfPoints > 0) {
312 | print('🛑 CLOCKWISE');
313 | } else {
314 | print('🛑 UNDEFINED CHIRALITY');
315 | }
316 | } else if (sketchVersion < 52) {
317 | const contour = this.targetPath.contours().firstObject();
318 | if (contour.isClockwise() === 1) {
319 | this.reverseSymmetry();
320 | print('🛑 CLOCKWISE');
321 | } else {
322 | print('🛑 COUNTERCLOCKWISE');
323 | }
324 | print('🛑 UNDEFINED CHIRALITY');
325 | }
326 |
327 | print('🔄↔️ Angle has just guessed rotation and symmetry for this shape');
328 | this.imprintValue_forKey(true, 'guessed-rotation');
329 | }
330 |
331 | shorlaceSum() {
332 | const points = this.pointsFromBezierPath;
333 | let maximumY = Math.max(...points.map((a) => a.y));
334 |
335 | return Array.from({ length: 4 }, (x, i) => i).reduce(function (p, i) {
336 | let edgeSum =
337 | (-points[i].x + points[(i + 1) % 4].x) *
338 | (2 * maximumY - points[i].y - points[(i + 1) % 4].y);
339 | return p + edgeSum;
340 | }, 0);
341 | }
342 |
343 | // ---------------------------------
344 | // PATH
345 | // ---------------------------------
346 |
347 | get pointsFromBezierPath() {
348 | const sketchVersion = BCSketchInfo.shared().metadata().appVersion;
349 | if (sketchVersion < 50) {
350 | let count = this.targetPath.elementCount();
351 | if (count != 7) {
352 | return null;
353 | }
354 |
355 | return Array.from({ length: count }, (x, i) => i).map((i) => {
356 | var pointsPointer = MOPointer.alloc().initWithValue_(CGPointMake(0, 0));
357 | var element = this.targetPath.elementAtIndex_associatedPoints_(
358 | i,
359 | pointsPointer
360 | );
361 | return pointsPointer.value();
362 | });
363 | } else if (sketchVersion < 52) {
364 | const contour = this.targetPath.contours().firstObject();
365 | return Array.fromNSArray(contour.segments()).map((a) => a.endPoint1());
366 | }
367 |
368 | const size = this.targetLayer.rect().size;
369 | return Array.fromNSArray(this.targetLayer.points())
370 | .map((a) => a.point())
371 | .map((a) => ({
372 | x: Number(a.x) * Number(size.width),
373 | y: Number(a.y) * Number(size.height),
374 | }));
375 | }
376 |
377 | get verticesLengths() {
378 | let points = this.pointsFromBezierPath;
379 |
380 | return Array.from({ length: 4 }, (x, i) => i).map((i) => {
381 | const j = (i + 1) % 4;
382 | const width = points[i].x - points[j].x;
383 | const height = points[i].y - points[j].y;
384 | return Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
385 | });
386 | }
387 |
388 | maximumVerticesWidthAndHeight() {
389 | let verticesLengths = this.verticesLengths.rotated(this.rotation % 2);
390 |
391 | let layerWidth = Math.max(verticesLengths[0], verticesLengths[2]);
392 | let layerHeight = Math.max(verticesLengths[1], verticesLengths[3]);
393 |
394 | return [layerWidth, layerHeight];
395 | }
396 |
397 | get normalizedCIVectors() {
398 | let points = this.pointsFromBezierPath;
399 |
400 | var maximumY = Math.max(...points.map((a) => a.y));
401 |
402 | let pixelDensity = this.pixelDensity;
403 |
404 | return points.map((a) => {
405 | return CIVector.vectorWithX_Y(
406 | a.x * pixelDensity,
407 | (maximumY - a.y) * pixelDensity
408 | );
409 | });
410 | }
411 |
412 | // ---------------------------------
413 | // INTERFACE
414 | // ---------------------------------
415 |
416 | rotate() {
417 | this.rotation = (this.rotation + (this.reversed ? 1 : 3)) % 4;
418 | }
419 |
420 | reverseSymmetry() {
421 | this.rotate();
422 |
423 | this.reversed = !this.reversed;
424 | }
425 |
426 | // ---------------------------------
427 | // DRAWING
428 | // ---------------------------------
429 |
430 | mappedIndexFor(index) {
431 | if (this.reversed) {
432 | return [0, 3, 2, 1][(index + this.rotation) % 4];
433 | }
434 | return (index + this.rotation) % 4;
435 | }
436 |
437 | lossyCompressionOfImage_atRate(image, rate) {
438 | let representation = NSBitmapImageRep.alloc().initWithCIImage(image);
439 | let properties = NSMutableDictionary.dictionary();
440 |
441 | properties.setObject_forKey(
442 | NSTIFFCompressionJPEG,
443 | NSImageCompressionMethod
444 | );
445 | properties.setObject_forKey(rate, NSImageCompressionFactor);
446 | properties.setObject_forKey(
447 | NSColor.whiteColor(),
448 | NSImageFallbackBackgroundColor
449 | );
450 |
451 | let compressed = representation.representationUsingType_properties(
452 | NSJPEGFileType,
453 | properties
454 | );
455 | let nsImage = NSImage.alloc().initWithData(compressed);
456 |
457 | return nsImage;
458 | }
459 |
460 | pixelAccurateRepresentationOfImage(image) {
461 | let representation = NSCIImageRep.alloc().initWithCIImage(image);
462 | let nsImage = NSImage.alloc().initWithSize(representation.size());
463 | nsImage.addRepresentation(representation);
464 |
465 | return nsImage;
466 | }
467 |
468 | get transformedImage() {
469 | let vectors = this.normalizedCIVectors;
470 |
471 | let perspectiveTransform = CIFilter.filterWithName(
472 | 'CIPerspectiveTransform'
473 | );
474 |
475 | perspectiveTransform.setValue_forKey(
476 | vectors[this.mappedIndexFor(0)],
477 | 'inputTopLeft'
478 | );
479 | perspectiveTransform.setValue_forKey(
480 | vectors[this.mappedIndexFor(1)],
481 | 'inputTopRight'
482 | );
483 | perspectiveTransform.setValue_forKey(
484 | vectors[this.mappedIndexFor(2)],
485 | 'inputBottomRight'
486 | );
487 | perspectiveTransform.setValue_forKey(
488 | vectors[this.mappedIndexFor(3)],
489 | 'inputBottomLeft'
490 | );
491 |
492 | let image = this.ciImage();
493 |
494 | perspectiveTransform.setValue_forKey(image, 'inputImage');
495 |
496 | let perspectiveImage = perspectiveTransform.valueForKey('outputImage');
497 |
498 | if (!perspectiveImage) {
499 | print('🛑 Unable to form perspective image');
500 | return;
501 | }
502 |
503 | let ouputNSImage;
504 |
505 | let compressionRatio = CompressionRatio[this.compressionRatio].ratio;
506 |
507 | if (compressionRatio != 1.0) {
508 | ouputNSImage = this.lossyCompressionOfImage_atRate(
509 | perspectiveImage,
510 | compressionRatio
511 | );
512 | } else {
513 | ouputNSImage = this.pixelAccurateRepresentationOfImage(perspectiveImage);
514 | }
515 |
516 | let imageData;
517 |
518 | if (BCSketchInfo.shared().metadata().appVersion < 47) {
519 | imageData = MSImageData.alloc().initWithImage_convertColorSpace(
520 | ouputNSImage,
521 | true
522 | );
523 | return imageData;
524 | }
525 |
526 | imageData = MSImageData.alloc().initWithImage_(ouputNSImage);
527 |
528 | return imageData;
529 | }
530 | }
531 |
--------------------------------------------------------------------------------
/src/CompositionAngle.js:
--------------------------------------------------------------------------------
1 | import SymbolicAngle from './SymbolicAngle'
2 | import { Error } from './Error'
3 |
4 | export default class CompositionAngle extends SymbolicAngle {
5 |
6 | constructor (options = {}) {
7 |
8 | super(options);
9 |
10 | this.override = options.override;
11 | }
12 |
13 | loadValueForKey (key) {
14 | return super.loadValueForKey(this.targetLayer.objectID() + "-" + key);
15 | }
16 |
17 | imprintValue_forKey (value, key) {
18 | super.imprintValue_forKey(value, this.targetLayer.objectID() + "-" + key);
19 | }
20 |
21 | applyImage () {
22 |
23 | const existingTopOverrides = this.selectedLayer.overrides() || NSDictionary.dictionary();
24 | const topOverrides = NSMutableDictionary.dictionaryWithDictionary(existingTopOverrides);
25 |
26 | const overrideBranchAddress = (this.overrideLayer + "").replace("_symbolID", "");
27 |
28 | const existingOverrideBranch = topOverrides.objectForKey(overrideBranchAddress) || NSMutableDictionary.dictionary();
29 | let overrideBranch = NSMutableDictionary.dictionaryWithDictionary(existingOverrideBranch);
30 |
31 | const objectID = this.targetLayer.objectID();
32 | overrideBranch.setObject_forKey(this.transformedImage, objectID);
33 | topOverrides.setObject_forKey(overrideBranch, overrideBranchAddress);
34 |
35 | this.selectedLayer.overrides = topOverrides;
36 | }
37 |
38 | description () {
39 | return this.override.parent().affectedLayer().name() + " " + this.targetLayer.name();
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/CompressionRatio.js:
--------------------------------------------------------------------------------
1 | export const CompressionRatio = [
2 | { selectionLabel: "Best", ratio: 1.0 },
3 | { selectionLabel: "Better", ratio: 0.9 },
4 | { selectionLabel: "Good", ratio: 0.8 },
5 | { selectionLabel: "Average", ratio: 0.7 }
6 | ]
7 |
--------------------------------------------------------------------------------
/src/Error.js:
--------------------------------------------------------------------------------
1 | export const Error = {
2 | unsupportedSymbol : {
3 | message : "This does not seem to be a supported symbol."
4 | },
5 | unsupportedShapePath : {
6 | message : "There seems to be an issue with the shape we are trying to apply."
7 | },
8 | emptySelection : {
9 | message : "Please, select a Shape, Angle Mockup or Angle Composition"
10 | },
11 | unsupportedElement : {
12 | message : "Please, select a Shape, Angle Mockup or Angle Composition"
13 | },
14 | noImageOverrideOnSymbol : {
15 | message : "There is no image override for the selected symbol"
16 | },
17 | symbolWithBitMapLayer : {
18 | message : "Bitmat overrides are not supported"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/PixelDensity.js:
--------------------------------------------------------------------------------
1 | export const PixelDensity = [
2 | { title: "Auto", selectionLabel: "Auto" },
3 | { title: "1x", selectionLabel: "1x" },
4 | { title: "2x", selectionLabel: "2x" },
5 | { title: "3x", selectionLabel: "3x" },
6 | { title: "4x", selectionLabel: "4x" },
7 | ]
8 |
--------------------------------------------------------------------------------
/src/ShapeAngle.js:
--------------------------------------------------------------------------------
1 | import Angle from './Angle'
2 | import { Error } from './Error'
3 |
4 | const StyleFillType = { solid: 0, gradient: 1, pattern: 4, noise: 5 };
5 | export default class ShapeAngle extends Angle {
6 | constructor (options = {}) {
7 | super(options);
8 |
9 | this.targetLayer = this.selectedLayer;
10 |
11 | const sketchVersion = BCSketchInfo.shared().metadata().appVersion
12 | if (sketchVersion < 50) {
13 | this.targetPath = this.selectedLayer.bezierPath();
14 | } else if (sketchVersion < 52) {
15 | this.targetPath = this.selectedLayer.pathInFrameWithTransforms();
16 | }
17 |
18 | if (!this.pointsAreValid) {
19 | return Error.unsupportedShapePath
20 | }
21 | }
22 |
23 | applyImage () {
24 |
25 | let imageFill = MSStyleFill.alloc().init();
26 | imageFill.setImage(this.transformedImage);
27 | imageFill.fillType = StyleFillType.pattern;
28 |
29 | this.targetLayer.style().removeAllStyleFills();
30 | this.targetLayer.style().addStyleFill(imageFill);
31 | }
32 |
33 | estimatePixelDensity () {
34 |
35 | // Best guess of a 2x sampling of the image if the mockup is in it's original scale
36 |
37 | let [layerWidth, layerHeight] = this.maximumVerticesWidthAndHeight();
38 |
39 | let widthRatio = layerWidth / this.artboard.rect().size.width;
40 | let heightRatio = layerHeight / this.artboard.rect().size.height;
41 |
42 | let estimate = widthRatio > heightRatio ? widthRatio : heightRatio;
43 |
44 | return estimate;
45 | }
46 |
47 | description () {
48 | return this.targetLayer.name();
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/SymbolicAngle.js:
--------------------------------------------------------------------------------
1 | import Angle from './Angle'
2 | import { Error } from './Error'
3 |
4 | export default class SymbolicAngle extends Angle {
5 |
6 | constructor (options = {}) {
7 |
8 | super(options);
9 |
10 | this.targetLayer = options.override.affectedLayer();
11 |
12 | if (this.targetLayer.class() === MSImmutableBitmapLayer)
13 | return Error.symbolWithBitMapLayer
14 |
15 | const sketchVersion = BCSketchInfo.shared().metadata().appVersion
16 | if (sketchVersion < 50) {
17 | this.targetPath = options.override.affectedLayer().bezierPath();
18 | } else if (sketchVersion < 52) {
19 | this.targetPath = options.override.affectedLayer().pathInFrameWithTransforms();
20 | }
21 |
22 | let parentSymbolIdentifier = options.override.overridePoint().parent()
23 | if (parentSymbolIdentifier !== null) {
24 | this.overrideLayer = parentSymbolIdentifier
25 | }
26 |
27 | if (!this.pointsAreValid) {
28 | return Error.unsupportedShapePath
29 | }
30 | }
31 |
32 | applyImage () {
33 |
34 | let objectID = this.targetLayer.objectID();
35 |
36 | const existingOverrides = this.selectedLayer.overrides() || NSDictionary.dictionary();
37 | const overrides = NSMutableDictionary.dictionaryWithDictionary(existingOverrides);
38 |
39 | overrides.setObject_forKey(this.transformedImage, objectID);
40 |
41 | this.selectedLayer.overrides = overrides;
42 | }
43 |
44 | estimatePixelDensity () {
45 |
46 | // Best guess of a 2x sampling of the image if the mockup is in it's original scale
47 |
48 | let [layerWidth, layerHeight] = this.maximumVerticesWidthAndHeight();
49 |
50 | let widthRatio = this.selectedLayer.rect().size.width * layerWidth / (this.selectedLayer.naturalSize().width * this.artboard.rect().size.width);
51 | let heightRatio = this.selectedLayer.rect().size.height * layerHeight / (this.selectedLayer.naturalSize().height * this.artboard.rect().size.height);
52 |
53 | let estimate = widthRatio > heightRatio ? widthRatio : heightRatio;
54 |
55 | return estimate;
56 | }
57 |
58 | description () {
59 | return this.selectedLayer.name() + " " + this.targetLayer.name();
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/apply.js:
--------------------------------------------------------------------------------
1 | import Angle from './Angle';
2 | import * as Shared from './Shared';
3 |
4 | import { Error } from './Error';
5 | import { PixelDensity } from './PixelDensity';
6 | import { CompressionRatio } from './CompressionRatio';
7 |
8 | String.prototype.repeat = (i) => new Array(i + 1).join(this);
9 |
10 | export function getSelectionAndOptions_forAngleInstances(options) {
11 | let { artboards, otherArtboards, alertImage, angles } = options;
12 |
13 | let array = Array.from({ length: angles.length }, (x, i) => i);
14 |
15 | if (artboards.length == 1) {
16 | return {
17 | alertOption: NSAlertFirstButtonReturn,
18 | artboardSelections: array.map((a, i, as) => {
19 | indexOfSelectedItem: () => 0;
20 | }),
21 | densitySelections: array.map((a, i, as) => {
22 | indexOfSelectedItem: () => 0;
23 | }),
24 | compressionSelections: array.map((a, i, as) => {
25 | indexOfSelectedItem: () => 0;
26 | }),
27 | };
28 | }
29 |
30 | var alert = NSAlert.alloc().init();
31 | var alertContent = NSView.alloc().init();
32 |
33 | alert.setMessageText('Apply Mockup');
34 | alert.setInformativeText(
35 | 'Choose an Artboard to apply into the selected shape.'
36 | );
37 | alert.addButtonWithTitle('Apply');
38 | alert.addButtonWithTitle('Cancel');
39 | alert.icon = alertImage;
40 |
41 | var movingYPosition = 0;
42 | var labelHeight = 16;
43 |
44 | var fisrtColumnWidth = 260;
45 | var secondColumnWidth = 90;
46 | var thirdColumnWidth = 90;
47 |
48 | const windowWidth = fisrtColumnWidth + secondColumnWidth + thirdColumnWidth;
49 |
50 | var rectangle;
51 |
52 | rectangle = NSMakeRect(0, 0, fisrtColumnWidth, labelHeight);
53 | var artboardLabel = Shared.createLabel('Artboard', 12, rectangle);
54 | alertContent.addSubview(artboardLabel);
55 |
56 | rectangle = NSMakeRect(fisrtColumnWidth, 0, secondColumnWidth, labelHeight);
57 | var densityLabel = Shared.createLabel('Pixel Density', 12, rectangle);
58 | alertContent.addSubview(densityLabel);
59 |
60 | rectangle = NSMakeRect(
61 | fisrtColumnWidth + secondColumnWidth,
62 | 0,
63 | thirdColumnWidth,
64 | labelHeight
65 | );
66 | var compressionLabel = Shared.createLabel('Quality', 12, rectangle);
67 | alertContent.addSubview(compressionLabel);
68 |
69 | let spacing = array.length > 1 ? 50 : 28;
70 |
71 | if (array.length > 1) {
72 | let targetLabels = array.map(function (a, i, as) {
73 | let rectangle = NSMakeRect(
74 | 0,
75 | labelHeight + 4 + spacing * i,
76 | fisrtColumnWidth,
77 | labelHeight
78 | );
79 | let label = Shared.createLabel(angles[i].description(), 12, rectangle);
80 |
81 | return label;
82 | });
83 | targetLabels.forEach((a) => alertContent.addSubview(a));
84 | }
85 |
86 | let allArtboards = artboards.concat(otherArtboards);
87 |
88 | let artboardNames = allArtboards
89 | .map(function (a) {
90 | if (a.name != undefined) {
91 | if (a.name instanceof String) {
92 | return a.name;
93 | }
94 | return a.name();
95 | }
96 | })
97 | .map(function (a, i, as) {
98 | let indexesWithSameName = as
99 | .map((b, j, bs) => (a == b ? j : -1))
100 | .filter((a, i, as) => a != -1);
101 |
102 | if (indexesWithSameName.length > 1) {
103 | let indexOfIndex = indexesWithSameName.indexOf(i);
104 | return a + ' '.repeat(indexOfIndex);
105 | }
106 |
107 | return a;
108 | });
109 |
110 | let artboardImages = allArtboards.map((a) =>
111 | Shared.smallImagesFromArtboard(a)
112 | );
113 |
114 | let artboardSelections = array.map((a, index, as) =>
115 | Shared.popUpButtonsforRectangleIndexer_withTitleIndexer_andImageIndexer_defaultSelected_onIndex(
116 | (i) =>
117 | NSMakeRect(0, labelHeight + 4 + spacing * i + 16, fisrtColumnWidth, 28),
118 | artboardNames,
119 | artboardImages,
120 | index
121 | )
122 | );
123 | artboardSelections.forEach((a) => alertContent.addSubview(a));
124 |
125 | let pixelDensityNames = PixelDensity.map((a) => a.selectionLabel);
126 | let pixelDensitySelections = array.map((a, index, as) =>
127 | Shared.popUpButtonsforRectangleIndexer_withTitleIndexer_andImageIndexer_defaultSelected_onIndex(
128 | (i) =>
129 | NSMakeRect(
130 | fisrtColumnWidth,
131 | labelHeight + 4 + spacing * i + 16,
132 | secondColumnWidth,
133 | 28
134 | ),
135 | pixelDensityNames,
136 | null,
137 | index
138 | )
139 | );
140 | pixelDensitySelections.forEach((a) => alertContent.addSubview(a));
141 |
142 | let compressionRatioNames = CompressionRatio.map((a) => a.selectionLabel);
143 | let compressionRatioSelections = array.map((a, index, as) =>
144 | Shared.popUpButtonsforRectangleIndexer_withTitleIndexer_andImageIndexer_defaultSelected_onIndex(
145 | (i) =>
146 | NSMakeRect(
147 | fisrtColumnWidth + secondColumnWidth,
148 | labelHeight + 4 + spacing * i + 16,
149 | thirdColumnWidth,
150 | 28
151 | ),
152 | compressionRatioNames,
153 | null,
154 | index
155 | )
156 | );
157 | compressionRatioSelections.forEach((a) => alertContent.addSubview(a));
158 |
159 | movingYPosition = labelHeight + 4 + spacing * angles.length + 28;
160 |
161 | // Render those label, dropdown etc into the Alert view
162 | alertContent.frame = NSMakeRect(0, 0, windowWidth, movingYPosition);
163 |
164 | // Reverse order of the content elements
165 | alertContent.setFlipped(true);
166 |
167 | alert.accessoryView = alertContent;
168 |
169 | // With this will run the modal and return a reference to the selection element
170 | return {
171 | alertOption: alert.runModal(),
172 | artboardSelections: artboardSelections,
173 | densitySelections: pixelDensitySelections,
174 | compressionSelections: compressionRatioSelections,
175 | };
176 | }
177 |
178 | function loadLocalImage(scriptPath, filePath) {
179 | const basePath = scriptPath
180 | .stringByDeletingLastPathComponent()
181 | .stringByDeletingLastPathComponent()
182 | .stringByDeletingLastPathComponent();
183 |
184 | return NSImage.alloc().initWithContentsOfFile(basePath + '/' + filePath);
185 | }
186 |
187 | function applyAngles(options) {
188 | let {
189 | angles,
190 | artboardsOnSelectPage: artboards,
191 | context,
192 | artboardsOnOtherPages: otherArtboards,
193 | } = options;
194 |
195 | if (artboards.length === 1) {
196 | angles.forEach(function (a) {
197 | a.artboard = artboards[0];
198 | a.pixelDensity = 0;
199 | a.selectedCompressionRatio = 0;
200 | });
201 | } else {
202 | const angleLogo = loadLocalImage(
203 | context.scriptPath,
204 | 'Contents/Resources/logo.png'
205 | );
206 |
207 | let response = getSelectionAndOptions_forAngleInstances({
208 | artboards: artboards,
209 | otherArtboards: otherArtboards,
210 | angles: angles,
211 | alertImage: angleLogo,
212 | });
213 |
214 | if (response.alertOption != NSAlertFirstButtonReturn) {
215 | return false;
216 | }
217 |
218 | angles.forEach(function (a, i, as) {
219 | let artboardSelectionIndex = response.artboardSelections[
220 | i
221 | ].indexOfSelectedItem();
222 |
223 | let allArtboards = artboards.concat(otherArtboards);
224 |
225 | a.artboard = allArtboards[artboardSelectionIndex];
226 | a.pixelDensity = response.densitySelections[i].indexOfSelectedItem();
227 | a.compressionRatio = response.compressionSelections[
228 | i
229 | ].indexOfSelectedItem();
230 | });
231 | }
232 |
233 | angles.forEach((a) => {
234 | a.guessRotationAndReversion();
235 | a.applyImage();
236 | });
237 |
238 | return true;
239 | }
240 |
241 | export default function (context) {
242 | let { document, selection } = context;
243 |
244 | const angleLogo = loadLocalImage(
245 | context.scriptPath,
246 | 'Contents/Resources/logo.png'
247 | );
248 |
249 | if (selection == null) {
250 | Shared.show({
251 | message: Error.emptySelection.message,
252 | inDocument: document,
253 | });
254 | return;
255 | }
256 |
257 | const selectedLayers = Array.fromNSArray(selection);
258 |
259 | if (selectedLayers.length == 0) {
260 | Shared.show({
261 | message: Error.emptySelection.message,
262 | inDocument: document,
263 | });
264 | return;
265 | }
266 |
267 | let parentArtboard = selectedLayers[0].parentArtboard();
268 |
269 | let artboardsOnSelectPage = Array.fromNSArray(document.artboards())
270 | .filter((a) => a != parentArtboard)
271 | .sort(Shared.compareByRatioAndAlphabet);
272 |
273 | let artboardsOnOtherPages = Array.fromNSArray(document.pages())
274 | .filter((a) => a != document.currentPage())
275 | .map((a) => a.artboards())
276 | .map((a) => Array.fromNSArray(a))
277 | .reduce((p, a) => {
278 | return p.concat(a);
279 | }, new Array())
280 | .filter(Shared.filterPossibleArtboards)
281 | .sort(Shared.compareByRatioAndAlphabet);
282 |
283 | if (artboardsOnSelectPage.length + artboardsOnOtherPages.length == 0) {
284 | var alert = NSAlert.alloc().init();
285 |
286 | alert.setMessageText('Angle needs an Artboard');
287 | alert.setInformativeText(
288 | 'To start using Angle, create a new Artboard that contains your screen.'
289 | );
290 | alert.addButtonWithTitle('OK');
291 | alert.icon = angleLogo;
292 |
293 | alert.runModal();
294 | return;
295 | }
296 |
297 | let possibleAngles = Angle.tryCreating({ for: selectedLayers, in: context });
298 |
299 | let angles = possibleAngles.filter((a) => a instanceof Angle);
300 | let errors = possibleAngles.filter((a) => !(a instanceof Angle));
301 |
302 | if (angles.length != 0) {
303 | let appliedShapeAngles = applyAngles({
304 | angles: angles,
305 | artboardsOnSelectPage: artboardsOnSelectPage,
306 | artboardsOnOtherPages: artboardsOnOtherPages,
307 | context: context,
308 | });
309 |
310 | if (appliedShapeAngles) {
311 | Shared.show({
312 | message: 'You got Angled! 📱',
313 | inDocument: document,
314 | });
315 | }
316 |
317 | return;
318 | }
319 |
320 | if (errors.length == 0) {
321 | Shared.show({
322 | message: Error.unsupportedElement.message,
323 | inDocument: document,
324 | });
325 | } else {
326 | Shared.show({
327 | message: errors[0].message,
328 | inDocument: document,
329 | });
330 | }
331 | }
332 |
--------------------------------------------------------------------------------
/src/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "bundleVersion": 1,
3 | "version": "1.1.7",
4 | "icon": "icon.png",
5 | "identifier": "io.designcode.Angle",
6 | "description": "Important note: use version 1.1.7 for Sketch 86+, version 1.1.6 for Sketch 72-85, version 1.1.5 for Sketch 66-71 and version 1.1.4 for Sketch 65 and earlier. Apply perspective transforms on screen mockups. Auto-detect screens by resolution and works on shapes and symbols.",
7 | "homepage": "https://angle.sh",
8 | "author": "Design+Code",
9 | "authorEmail": "angle@designcode.io",
10 | "compatibleVersion": 50,
11 | "commands": [
12 | {
13 | "name": "Rotate Mockup",
14 | "identifier": "Angle-Rotate-Mockup",
15 | "script": "./rotate.js",
16 | "shortcut": "control \\"
17 | },
18 | {
19 | "name": "Flip Mockup",
20 | "identifier": "Angle-Rotate-Flip",
21 | "script": "./symmetry.js",
22 | "shortcut": "cmd shift \\"
23 | },
24 | {
25 | "name": "Apply Mockup",
26 | "identifier": "Angle-Apply-Mockup",
27 | "script": "./apply.js",
28 | "shortcut": "cmd \\"
29 | },
30 | {
31 | "name": "Reset Mockup",
32 | "identifier": "Angle-Reset-Metadata",
33 | "script": "./reset.js",
34 | "shortcut": "cmd control \\"
35 | }
36 | ],
37 | "menu": {
38 | "title": "Angle",
39 | "items": [
40 | "Angle-Apply-Mockup",
41 | "Angle-Rotate-Flip",
42 | "Angle-Rotate-Mockup",
43 | "Angle-Reset-Metadata"
44 | ]
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/reset.js:
--------------------------------------------------------------------------------
1 | import Angle from './Angle'
2 | import * as Shared from './Shared'
3 |
4 | export default function ({ document, selection, command }) {
5 |
6 | if (selection == undefined || selection.count() != 1) {
7 | Shared.show({
8 | message: "Please, select 1️⃣ element to reset",
9 | inDocument: document
10 | });
11 | return
12 | }
13 |
14 | let layer = selection.firstObject();
15 | let possibleAngle = Angle.tryCreating({ for: [layer], in: { document, selection, command } });
16 |
17 | if (!(possibleAngle instanceof Angle)) {
18 |
19 | Shared.show({
20 | message: "Reset only works on shapes and symbols.",
21 | inDocument: document
22 | });
23 | return
24 | }
25 |
26 | context.command.setValue_forKey_onLayer(null, "pixel-density", layer);
27 | context.command.setValue_forKey_onLayer(null, "rotation", layer);
28 | context.command.setValue_forKey_onLayer(null, "artboard-id", layer);
29 | context.command.setValue_forKey_onLayer(null, "compression-ratio", layer);
30 | context.command.setValue_forKey_onLayer(null, "reversed", layer);
31 | context.command.setValue_forKey_onLayer(null, "guessed-rotation", layer);
32 |
33 | Shared.show({
34 | message: "Angle Mockup metadata reset.",
35 | inDocument: document
36 | });
37 | }
38 |
--------------------------------------------------------------------------------
/src/rotate.js:
--------------------------------------------------------------------------------
1 | import Angle from './Angle';
2 | import * as Shared from './Shared';
3 |
4 | import { Error } from './Error';
5 |
6 | export default function (context) {
7 | let selectedLayersNSArray = context.selection[0];
8 |
9 | if (selectedLayersNSArray == null) {
10 | Shared.show({
11 | message: Error.emptySelection.message,
12 | inDocument: context.document,
13 | });
14 | return;
15 | }
16 |
17 | let selectedLayers = Array.fromNSArray(selectedLayersNSArray);
18 | // console.log('SELECTED LAYERS', selectedLayers);
19 |
20 | if (selectedLayers.length == 0) {
21 | Shared.show({
22 | message: Error.emptySelection.message,
23 | inDocument: context.document,
24 | });
25 | return;
26 | }
27 |
28 | let possibleAngles = Angle.tryCreating({ for: selectedLayers, in: context });
29 |
30 | let angles = possibleAngles.filter((a) => a instanceof Angle);
31 | let errors = possibleAngles.filter((a) => !(a instanceof Angle));
32 |
33 | if (angles.length == 0) {
34 | let error = errors[0];
35 | Shared.show({
36 | message: error.message,
37 | inDocument: context.document,
38 | });
39 | return;
40 | }
41 |
42 | angles.forEach((a) => {
43 | a.rotate();
44 | a.applyImage();
45 | });
46 |
47 | Shared.show({
48 | message: 'Angle rotated! 🔄',
49 | inDocument: context.document,
50 | });
51 |
52 | return;
53 | }
54 |
--------------------------------------------------------------------------------
/src/shared.js:
--------------------------------------------------------------------------------
1 | import Angle from './Angle';
2 | import CompositionAngle from './CompositionAngle';
3 | import SymbolicAngle from './SymbolicAngle';
4 | import ShapeAngle from './ShapeAngle';
5 |
6 | import { Error } from './Error';
7 |
8 | Angle.tryCreating = function ({ for: selectedLayers, in: context }) {
9 | return selectedLayers
10 | .map((layer) => {
11 | switch (layer.class()) {
12 | case MSSymbolInstance:
13 | let overrides = Array.fromNSArray(layer.availableOverrides()) || [];
14 |
15 | let symbolAngles = overrides
16 | .filter(
17 | (override) => override.currentValue().class() == MSImageData
18 | )
19 | .map((override) => {
20 | return new SymbolicAngle({
21 | selectedLayer: layer,
22 | context: context,
23 | override: override,
24 | });
25 | });
26 |
27 | let nestedAngles = overrides
28 | .map((a) => a.children())
29 | .filter((a) => a != null)
30 | .map(Array.fromNSArray)
31 | .reduce((p, a) => p.concat(a), [])
32 | .filter(function (a) {
33 | return a.class() == MSAvailableOverride;
34 | })
35 | .map(function (a) {
36 | return new CompositionAngle({
37 | override: a,
38 | selectedLayer: layer,
39 | context: context,
40 | });
41 | });
42 | return symbolAngles.concat(nestedAngles);
43 | case MSShapeGroup:
44 | case MSShapePathLayer:
45 | case MSRectangleShape:
46 | return new ShapeAngle({
47 | selectedLayer: layer,
48 | context: context,
49 | });
50 | default:
51 | return Error.unsupportedElement;
52 | }
53 | })
54 | .reduce((p, a, i, as) => p.concat(a), []);
55 | };
56 |
57 | Array.fromNSArray = function (nsArray) {
58 | let array = [];
59 | for (var i = 0; i < nsArray.length; i++) {
60 | array.push(nsArray[i]);
61 | }
62 | return array;
63 | };
64 |
65 | Array.prototype.print = function () {
66 | return this.map((a) => {
67 | print(a);
68 | return a;
69 | });
70 | };
71 |
72 | export function show({ message, inDocument: document }) {
73 | if (document != undefined && document.showMessage != undefined) {
74 | document.showMessage(message);
75 | }
76 |
77 | print(message);
78 | }
79 |
80 | export function filterPossibleArtboards(artboardOrSymbol) {
81 | let upperMaring = 0.8;
82 | let lowerMargin = 0.4;
83 | let minimumDimention = 250;
84 |
85 | let elementClass = artboardOrSymbol.class();
86 |
87 | switch (elementClass) {
88 | case MSArtboardGroup:
89 | let artboard = artboardOrSymbol;
90 | let frame = artboard.frame();
91 |
92 | if (
93 | frame.width() < minimumDimention ||
94 | frame.height() < minimumDimention
95 | ) {
96 | return false;
97 | }
98 |
99 | let ratio = frame.width() / frame.height();
100 | if (ratio > 1) {
101 | ratio = 1 / ratio;
102 | }
103 |
104 | if (ratio < lowerMargin) {
105 | return false;
106 | }
107 | break;
108 | case MSSymbolMaster:
109 | // Traversion of symbols does not work properly yet.
110 | return false;
111 |
112 | default:
113 | print(elementClass);
114 | return false;
115 | }
116 |
117 | return true;
118 | }
119 |
120 | export function compareByRatioAndAlphabet(a, b) {
121 | let upperMaring = 0.8;
122 | let lowerMargin = 0.4;
123 |
124 | let artboardSizeA = a.frame();
125 | let artboardSizeB = b.frame();
126 |
127 | let artboardARatio = artboardSizeA.width() / artboardSizeA.height();
128 | if (artboardARatio > 1) {
129 | artboardARatio = 1 / artboardARatio;
130 | }
131 |
132 | let artboardARatioInsideMargin =
133 | artboardARatio > lowerMargin && artboardARatio < upperMaring;
134 |
135 | let artboardBRatio = artboardSizeB.width() / artboardSizeB.height();
136 | if (artboardBRatio > 1) {
137 | artboardBRatio = 1 / artboardBRatio;
138 | }
139 |
140 | let artboardBRatioInsideMargin =
141 | artboardBRatio > lowerMargin && artboardBRatio < upperMaring;
142 |
143 | if (artboardARatioInsideMargin && !artboardBRatioInsideMargin) {
144 | return false;
145 | }
146 |
147 | if (artboardBRatioInsideMargin && !artboardARatioInsideMargin) {
148 | return true;
149 | }
150 |
151 | if (artboardARatio == artboardBRatio) {
152 | return a.name() > b.name();
153 | }
154 |
155 | return artboardARatio > artboardBRatio;
156 | }
157 |
158 | export function introspect(type) {
159 | let mocha = type.class().mocha();
160 |
161 | print('-----------------------------------------------');
162 | print('PROPERTIES-------------------------------------');
163 | print('-----------------------------------------------');
164 |
165 | print(mocha.properties());
166 | print(mocha.propertiesWithAncestors());
167 |
168 | print('-----------------------------------------------');
169 | print('INSTANCE METHODS-------------------------------');
170 | print('-----------------------------------------------');
171 | print(mocha.instanceMethods());
172 | print(mocha.instanceMethodsWithAncestors());
173 |
174 | print('-----------------------------------------------');
175 | print('CLASS METHODS----------------------------------');
176 | print('-----------------------------------------------');
177 | print(mocha.classMethods());
178 | print(mocha.classMethodsWithAncestors());
179 |
180 | print('-----------------------------------------------');
181 | print('PROTOCOLS--------------------------------------');
182 | print('-----------------------------------------------');
183 | print(mocha.protocols());
184 | print(mocha.protocolsWithAncestors());
185 | }
186 |
187 | export function createLabel(text, size, frame) {
188 | var label = NSTextField.alloc().initWithFrame(frame);
189 |
190 | label.setStringValue(text);
191 | label.setFont(NSFont.boldSystemFontOfSize(size));
192 | label.setBezeled(false);
193 | label.setDrawsBackground(false);
194 | label.setEditable(false);
195 | label.setSelectable(false);
196 |
197 | return label;
198 | }
199 |
200 | export function popUpButtonsforRectangleIndexer_withTitleIndexer_andImageIndexer_defaultSelected_onIndex(
201 | rectangle,
202 | titles,
203 | images,
204 | index
205 | ) {
206 | let button = NSPopUpButton.alloc().initWithFrame(rectangle(index));
207 | button.addItemsWithTitles(titles);
208 |
209 | if (images != null) {
210 | button.imageScaling = NSImageScaleProportionallyUpOrDown;
211 |
212 | Array.fromNSArray(button.itemArray()).forEach((a, i, as) => {
213 | a.image = images[i];
214 | });
215 | }
216 |
217 | return button;
218 | }
219 |
220 | export function smallImagesFromArtboard(artboard) {
221 | // var sketch = require('sketch/dom');
222 | // var artboard = sketch.fromNative(msartboard);
223 |
224 | // //let image = sketch.export(artboard);
225 |
226 | // print(msartboard.unselectedPreviewImage());
227 |
228 | // return nil
229 |
230 | if (artboard.class() == MSSymbolMaster) {
231 | print(artboard);
232 | return null;
233 | }
234 |
235 | if (artboard.frame == undefined) {
236 | print(artboard);
237 | }
238 |
239 | let artboardWidth = artboard.frame().width();
240 | let artboardHeight = artboard.frame().height();
241 | var artboardRatio = artboardWidth / artboardHeight;
242 | if (artboardRatio > 1) {
243 | artboardRatio = 1 / artboardRatio;
244 | }
245 |
246 | if (artboardRatio > 0.8 || artboardRatio < 0.4) {
247 | return null;
248 | }
249 |
250 | // let layerAncestry = MSImmutableLayerAncestry.alloc().initWithMSLayer(artboard);
251 | // let layerAncestry = this.artboard.ancestry();
252 |
253 | // MSImmutableLayerAncestry has been renamed (As of V.66.1) and must be called from the class string
254 | let cls = NSClassFromString('SketchModel.MSImmutableLayerAncestry');
255 | let layerAncestry = cls.alloc().initWithMutableLayer(artboard);
256 |
257 | let biggerDimention =
258 | artboardWidth > artboardHeight ? artboardWidth : artboardHeight;
259 | let exportScale = 48 / biggerDimention;
260 | let exportFormat = MSExportFormat.formatWithScale_name_fileFormat(
261 | exportScale,
262 | '',
263 | 'png'
264 | );
265 | let exportRequest = MSExportRequest.exportRequestsFromLayerAncestry_exportFormats(
266 | layerAncestry,
267 | [exportFormat]
268 | ).firstObject();
269 | let exporter = MSExporter.exporterForRequest_colorSpace(
270 | exportRequest,
271 | NSColorSpace.sRGBColorSpace()
272 | );
273 |
274 | return exporter.previewImage();
275 | }
276 |
--------------------------------------------------------------------------------
/src/symmetry.js:
--------------------------------------------------------------------------------
1 | import Angle from './Angle';
2 | import * as Shared from './Shared';
3 |
4 | import { Error } from './Error';
5 |
6 | export default function (context) {
7 | let selectedLayersNSArray = context.selection[0];
8 |
9 | if (selectedLayersNSArray == null) {
10 | Shared.show({
11 | message: Error.emptySelection.message,
12 | inDocument: context.document,
13 | });
14 | return;
15 | }
16 |
17 | let selectedLayers = Array.fromNSArray(selectedLayersNSArray);
18 |
19 | if (selectedLayers.length == 0) {
20 | Shared.show({
21 | message: Error.emptySelection.message,
22 | inDocument: context.document,
23 | });
24 | return;
25 | }
26 |
27 | let possibleAngles = Angle.tryCreating({ for: selectedLayers, in: context });
28 |
29 | let angles = possibleAngles.filter((a) => a instanceof Angle);
30 | let errors = possibleAngles.filter((a) => !(a instanceof Angle));
31 |
32 | if (angles.length == 0) {
33 | Shared.show({
34 | message: errors[0].message,
35 | inDocument: context.document,
36 | });
37 | return;
38 | }
39 |
40 | angles.forEach((a) => {
41 | a.reverseSymmetry();
42 | a.applyImage();
43 | });
44 |
45 | Shared.show({
46 | message: 'Angle flipped! ↔️',
47 | inDocument: context.document,
48 | });
49 |
50 | return;
51 | }
52 |
--------------------------------------------------------------------------------
/workspace.code-workspace:
--------------------------------------------------------------------------------
1 | {
2 | "folders": [
3 | {
4 | "path": "."
5 | }
6 | ],
7 | "settings": {
8 | "search.exclude": {
9 | "**/Angle.sketchplugin": true,
10 | "**/Angle.xcodeproj": true
11 | }
12 | },
13 | }
14 |
--------------------------------------------------------------------------------