@nexrender/core 1.44.1 → 1.45.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/package.json +2 -2
  2. package/src/helpers/analytics.js +71 -4
  3. package/src/index.js +1 -0
  4. package/src/tasks/cleanup.js +2 -0
  5. package/src/tasks/download.js +3 -2
  6. package/src/tasks/render.js +10 -1
  7. package/src/tasks/script.js +1 -1
  8. package/test/index-mock.js +28 -0
  9. package/test/index.js +2 -28
  10. package/test/result.mp4 +0 -0
  11. package/test/workpath/7LyC6arUCXaJkBo7IORV-/aerender.log +4 -0
  12. package/test/workpath/7LyC6arUCXaJkBo7IORV-/nexrender-7LyC6arUCXaJkBo7IORV--script.jsx +259 -0
  13. package/test/workpath/7LyC6arUCXaJkBo7IORV-/shuo3xcefe8.txt +1 -0
  14. package/test/workpath/7LyC6arUCXaJkBo7IORV-/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==.png +0 -0
  15. package/test/workpath/8jeh3u9dpLHjoGpI6rjx2/aerender.log +4 -0
  16. package/test/workpath/8jeh3u9dpLHjoGpI6rjx2/nexrender-8jeh3u9dpLHjoGpI6rjx2-script.jsx +259 -0
  17. package/test/workpath/8jeh3u9dpLHjoGpI6rjx2/o5qw6b68qb.txt +1 -0
  18. package/test/workpath/8jeh3u9dpLHjoGpI6rjx2/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==.png +0 -0
  19. package/test/workpath/VknW4c3v2iqxn2oCwwn6h/22whbptmoco.txt +1 -0
  20. package/test/workpath/VknW4c3v2iqxn2oCwwn6h/nexrender-VknW4c3v2iqxn2oCwwn6h-script.jsx +259 -0
  21. package/test/workpath/VknW4c3v2iqxn2oCwwn6h/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==.png +0 -0
  22. package/test/workpath/WWZPunE4et5DRshfZExi3/aerender.log +4 -0
  23. package/test/workpath/WWZPunE4et5DRshfZExi3/ayw72a2jxmu.txt +1 -0
  24. package/test/workpath/WWZPunE4et5DRshfZExi3/nexrender-WWZPunE4et5DRshfZExi3-script.jsx +259 -0
  25. package/test/workpath/WWZPunE4et5DRshfZExi3/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==.png +0 -0
  26. package/test/workpath/aerender-VknW4c3v2iqxn2oCwwn6h.log +4 -0
  27. package/test/workpath/aerender-gEX4BWRLMuK1mfa7YsWSO.log +4 -0
  28. package/test/workpath/aerender-lIMz7U9rMGkTk_2ui_7LM.log +4 -0
  29. package/test/workpath/aerender-uiy_a4azTwe5XOC8r4qlX.log +4 -0
  30. package/test/workpath/aerender-umMNXjDQlXv8l1hayySwW.log +4 -0
  31. package/test/workpath/aerender-yV_jes3eq34uZi-1eyBYp.log +4 -0
  32. package/test/workpath/aerender-zOn54c0S90bFqVAhSLZlt.log +4 -0
  33. package/test/workpath/ffmpeg-b5.0.1 +0 -0
  34. package/test/workpath/gEX4BWRLMuK1mfa7YsWSO/5es7lulklvl.txt +1 -0
  35. package/test/workpath/gEX4BWRLMuK1mfa7YsWSO/nexrender-gEX4BWRLMuK1mfa7YsWSO-script.jsx +259 -0
  36. package/test/workpath/gEX4BWRLMuK1mfa7YsWSO/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==.png +0 -0
  37. package/test/workpath/lIMz7U9rMGkTk_2ui_7LM/6krza0kzkvy.txt +1 -0
  38. package/test/workpath/lIMz7U9rMGkTk_2ui_7LM/nexrender-lIMz7U9rMGkTk_2ui_7LM-script.jsx +259 -0
  39. package/test/workpath/lIMz7U9rMGkTk_2ui_7LM/output.gif +0 -0
  40. package/test/workpath/lIMz7U9rMGkTk_2ui_7LM/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==.png +0 -0
  41. package/test/workpath/lkYw_qyYMwB3waoIh7CaR/ReelsBot.aep +0 -0
  42. package/test/workpath/lkYw_qyYMwB3waoIh7CaR/_DSR8473-HIGH +0 -0
  43. package/test/workpath/lkYw_qyYMwB3waoIh7CaR/_DSR8586-HIGH.jpg +0 -0
  44. package/test/workpath/lkYw_qyYMwB3waoIh7CaR/_DSR8954-HIGH__.jpg +0 -0
  45. package/test/workpath/lkYw_qyYMwB3waoIh7CaR/_DSR8959-HIGH__.jpg +0 -0
  46. package/test/workpath/lkYw_qyYMwB3waoIh7CaR/_DSR8964-HIGH__.jpg +0 -0
  47. package/test/workpath/lkYw_qyYMwB3waoIh7CaR/_DSR8969-HIGH__.jpg +0 -0
  48. package/test/workpath/lkYw_qyYMwB3waoIh7CaR/_DSR8974-HIGH__.jpg +0 -0
  49. package/test/workpath/lkYw_qyYMwB3waoIh7CaR/_DSR8989-HIGH__.jpg +0 -0
  50. package/test/workpath/lkYw_qyYMwB3waoIh7CaR/_DSR8994-HIGH__.jpg +0 -0
  51. package/test/workpath/lkYw_qyYMwB3waoIh7CaR/_DSR9000-HIGH__.jpg +0 -0
  52. package/test/workpath/lkYw_qyYMwB3waoIh7CaR/_DSR9004-HIGH__.jpg +0 -0
  53. package/test/workpath/lkYw_qyYMwB3waoIh7CaR/_DSR9009-HIGH__.jpg +0 -0
  54. package/test/workpath/uiy_a4azTwe5XOC8r4qlX/dw9kq81pala.txt +1 -0
  55. package/test/workpath/uiy_a4azTwe5XOC8r4qlX/nexrender-uiy_a4azTwe5XOC8r4qlX-script.jsx +259 -0
  56. package/test/workpath/uiy_a4azTwe5XOC8r4qlX/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==.png +0 -0
  57. package/test/workpath/umMNXjDQlXv8l1hayySwW/nexrender-umMNXjDQlXv8l1hayySwW-script.jsx +259 -0
  58. package/test/workpath/umMNXjDQlXv8l1hayySwW/vkp2ixck7yk.txt +1 -0
  59. package/test/workpath/umMNXjDQlXv8l1hayySwW/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==.png +0 -0
  60. package/test/workpath/yV_jes3eq34uZi-1eyBYp/ci6z16bpfum.txt +1 -0
  61. package/test/workpath/yV_jes3eq34uZi-1eyBYp/nexrender-yV_jes3eq34uZi-1eyBYp-script.jsx +259 -0
  62. package/test/workpath/yV_jes3eq34uZi-1eyBYp/output.gif +0 -0
  63. package/test/workpath/yV_jes3eq34uZi-1eyBYp/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==.png +0 -0
  64. package/test/workpath/zOn54c0S90bFqVAhSLZlt/ncxvpalkvc.txt +1 -0
  65. package/test/workpath/zOn54c0S90bFqVAhSLZlt/nexrender-zOn54c0S90bFqVAhSLZlt-script.jsx +259 -0
  66. package/test/workpath/zOn54c0S90bFqVAhSLZlt/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==.png +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nexrender/core",
3
- "version": "1.44.1",
3
+ "version": "1.45.5",
4
4
  "main": "src/index.js",
5
5
  "author": "Inlife",
6
6
  "homepage": "https://github.com/inlife/nexrender",
@@ -36,5 +36,5 @@
36
36
  "publishConfig": {
37
37
  "access": "public"
38
38
  },
39
- "gitHead": "db4b6d36c4f0daa85b022538ca654539d2ddce96"
39
+ "gitHead": "45cf9d9c1ba6f343474348fcbf6a7d81ac7f244d"
40
40
  }
@@ -37,6 +37,12 @@ const forceSyncRequest = (settings, event, properties) => {
37
37
  })
38
38
  }
39
39
 
40
+ // cache for combined events
41
+ let cache = {
42
+ job_id: null,
43
+ data: {},
44
+ }
45
+
40
46
  /**
41
47
  * Tracking function for analytics
42
48
  *
@@ -75,9 +81,32 @@ const track = async (settings, event, properties = {}, isRemote) => {
75
81
  return forceSyncRequest(settings, event, properties)
76
82
  }
77
83
 
84
+ // anonymize job_id (we are doing it after the forced check,
85
+ // to ensure we won't be hashing the same value twice)
86
+ if (properties.job_id) {
87
+ properties.job_id = hash(properties.job_id, settings.analyticsId)
88
+ }
89
+
90
+ // we are not sending the event itself, but rather combining it with other events of the same type
91
+ // and sending it as a single event when flush is triggered
92
+ if (properties.combined === true) {
93
+ delete properties.combined
94
+
95
+ // remove any data from previous jobs
96
+ if (cache.job_id != properties.job_id) {
97
+ cache.job_id = properties.job_id
98
+ cache.data = {}
99
+ }
100
+
101
+ cache.data[event] = cache.data[event] || []
102
+ cache.data[event].push(properties)
103
+
104
+ return;
105
+ }
106
+
78
107
  // collect system info
79
108
  if (!settings.systemInfo) {
80
- if (isRemote) console.log('collectiing systeminfo')
109
+ // if (isRemote) console.log('collecting systeminfo')
81
110
 
82
111
  settings.systemInfo = await si.get({
83
112
  cpu: 'manufacturer,brand,cores',
@@ -102,9 +131,45 @@ const track = async (settings, event, properties = {}, isRemote) => {
102
131
  }
103
132
  }
104
133
 
105
- // anonymize job_id
106
- if (properties.job_id) {
107
- properties.job_id = hash(properties.job_id, settings.analyticsId)
134
+ if (event == 'Job Cleanup') {
135
+ const events = Object.keys(cache.data)
136
+
137
+ for (let i = 0; i < events.length; i++) {
138
+ const combinedEvent = events[i]
139
+ const combinedProperties = cache.data[combinedEvent]
140
+
141
+ switch (combinedEvent) {
142
+ case 'Asset Download':
143
+ properties.assets_total = combinedProperties.length
144
+
145
+ for (let j = 0; j < combinedProperties.length; j++) {
146
+ const asset = combinedProperties[j]
147
+ const byProtocol = `assets_by_protocol_${asset.asset_protocol}`
148
+ const byExtension = `assets_by_extension_${asset.asset_extension}`
149
+ properties[byProtocol] = (properties[byProtocol] || 0) + 1
150
+ properties[byExtension] = (properties[byExtension] || 0) + 1
151
+ }
152
+
153
+ break;
154
+
155
+ case 'Asset Script Wraps':
156
+ properties.assets_script_wraps = combinedProperties.length
157
+
158
+ for (let j = 0; j < combinedProperties.length; j++) {
159
+ const script = combinedProperties[j]
160
+ const byType = `assets_by_type_${script.script_type}`
161
+ const byComposition = `assets_by_composition_set_${script.script_composition_set ? 'true' : 'false'}`
162
+ const byLayerStrategy = `assets_by_layer_strategy_${script.script_layer_strat || 'none'}`
163
+ const byValueStrategy = `assets_by_value_strategy_${script.script_value_strat || 'none'}`
164
+ properties[byType] = (properties[byType] || 0) + 1
165
+ properties[byComposition] = (properties[byComposition] || 0) + 1
166
+ properties[byLayerStrategy] = (properties[byLayerStrategy] || 0) + 1
167
+ properties[byValueStrategy] = (properties[byValueStrategy] || 0) + 1
168
+ }
169
+
170
+ break;
171
+ }
172
+ }
108
173
  }
109
174
 
110
175
  const params = {
@@ -119,6 +184,8 @@ const track = async (settings, event, properties = {}, isRemote) => {
119
184
  }, properties)
120
185
  }
121
186
 
187
+ // console.log('tracking event:', params)
188
+
122
189
  analytics.capture(params);
123
190
  await analytics.flush();
124
191
  }
package/src/index.js CHANGED
@@ -41,6 +41,7 @@ const init = (settings) => {
41
41
  settings = Object.assign({}, settings);
42
42
  settings.logger = settings.logger || console;
43
43
  settings.track = (...args) => track(settings, ...args);
44
+ settings.trackCombined = (event, params) => track(settings, event, { combined: true, ...params });
44
45
  settings.trackSync = (event, params) => track(settings, event, { forced: true, ...params })
45
46
 
46
47
  // set default process name for analytics
@@ -5,6 +5,8 @@ const path = require('path')
5
5
  * Clean up all workpath files and remove folder
6
6
  */
7
7
  module.exports = function(job, settings) {
8
+ settings.track('Job Cleanup');
9
+
8
10
  if (settings.skipCleanup) {
9
11
  settings.logger.log(`[${job.uid}] skipping the clean up...`);
10
12
  return Promise.resolve(job)
@@ -48,7 +48,7 @@ const download = (job, settings, asset) => {
48
48
 
49
49
  asset.dest = path.join(job.workpath, destName);
50
50
 
51
- settings.track('Job Asset Download Started', {
51
+ settings.trackCombined('Asset Download', {
52
52
  job_id: job.uid, // anonymized internally
53
53
  asset_type: asset.type,
54
54
  asset_protocol: protocol,
@@ -95,7 +95,8 @@ const download = (job, settings, asset) => {
95
95
 
96
96
  asset.extension = fileExt
97
97
  const destHasExtension = path.extname(asset.dest) ? true : false
98
- //don't do this if asset.dest already has extension else it gives you example.jpg.jpg like file in case of assets and aep/aepx file
98
+ // don't do this if asset.dest already has extension else it gives you example.jpg.jpg
99
+ // like file in case of assets and aep/aepx file
99
100
  if (asset.extension && !destHasExtension) {
100
101
  asset.dest += `.${fileExt}`
101
102
  }
@@ -75,7 +75,16 @@ Estimated date of change to the new behavior: 2023-06-01.\n`);
75
75
 
76
76
  option(params, '-r', jobScriptFile);
77
77
 
78
- if (!settings.skipRender && settings.multiFrames) params.push('-mfr', 'ON', settings.multiFramesCPU);
78
+ if (!settings.skipRender && settings.multiFrames) {
79
+ const afterEffects = path.dirname(settings.binary)
80
+ const afterEffectsYearMatch = afterEffects.match(/(20[0-9]{2})/);
81
+
82
+ if (afterEffectsYearMatch && afterEffectsYearMatch[0] >= "2022") {
83
+ params.push('-mfr', 'ON', settings.multiFramesCPU);
84
+ } else {
85
+ params.push('-mp');
86
+ }
87
+ }
79
88
  if (settings.reuse) params.push('-reuse');
80
89
  if (job.template.continueOnMissing) params.push('-continueOnMissingFootage')
81
90
 
@@ -432,7 +432,7 @@ module.exports = (job, settings) => {
432
432
  const base = job.workpath;
433
433
 
434
434
  job.assets.map(asset => {
435
- settings.track('Job Script Asset Wrap', {
435
+ settings.trackCombined('Asset Script Wraps', {
436
436
  job_id: job.uid, // anonymized internally
437
437
  script_type: asset.type,
438
438
  script_compostion_set: asset.composition !== undefined,
@@ -0,0 +1,28 @@
1
+ // simple test code
2
+ const {render} = require('../src')
3
+
4
+ process.env.NEXRENDER_ENABLE_AELOG_PROJECT_FOLDER = true
5
+
6
+ const job = {
7
+ template: {
8
+ src: 'data:text/plain,Hello, World!',
9
+ composition: 'test',
10
+ output: __dirname + '/index.js',
11
+ },
12
+ assets: [
13
+ {
14
+ type: 'image',
15
+ src: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==',
16
+ layerName: 'test',
17
+ }
18
+ ]
19
+ }
20
+
21
+ const settings = {
22
+ binary: __dirname + '/aerender',
23
+ workpath: __dirname + '/workpath',
24
+ }
25
+
26
+ render(job, settings)
27
+ .then(() => console.log('rendered successfully'))
28
+ .catch(console.error)
package/test/index.js CHANGED
@@ -1,28 +1,2 @@
1
- // simple test code
2
- const {render} = require('../src')
3
-
4
- process.env.NEXRENDER_ENABLE_AELOG_PROJECT_FOLDER = true
5
-
6
- const job = {
7
- template: {
8
- src: 'data:text/plain,Hello, World!',
9
- composition: 'test',
10
- output: __dirname + '/index.js',
11
- },
12
- assets: [
13
- {
14
- type: 'image',
15
- src: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==',
16
- layerName: 'test',
17
- }
18
- ]
19
- }
20
-
21
- const settings = {
22
- binary: __dirname + '/aerender',
23
- workpath: __dirname + '/workpath',
24
- }
25
-
26
- render(job, settings)
27
- .then(() => console.log('rendered successfully'))
28
- .catch(console.error)
1
+ // simple syntax test
2
+ require('../src')
Binary file
@@ -0,0 +1,4 @@
1
+ imitating rendering with aerender :p
2
+ rendering... 0%
3
+ rendering... 50%
4
+ rendering... 100%
@@ -0,0 +1,259 @@
1
+
2
+ try{Object.defineProperty({},'a',{value:0})}catch(err){(function(){var defineProperty=Object.defineProperty;Object.defineProperty=function(object,property,descriptor){delete descriptor.configurable;delete descriptor.enumerable;delete descriptor.writable;try{return defineProperty(object,property,descriptor)}catch(err){object[property]=descriptor.value}}}())}Object.defineProperties||(Object.defineProperties=function defineProperties(object,descriptors){var property;for(property in descriptors){Object.defineProperty(object,property,descriptors[property])}return object});var lambda=function(l){var fn=l.match(/((.*))s*=>s*(.*)/);var p=[];var b="";if(fn.length>0){fn.shift()}if(fn.length>0){b=fn.pop()}if(fn.length>0){p=fn.pop().replace(/^s*|s(?=s)|s*$|,/g,'').split(' ')}fn=((!/s*returns+/.test(b))?"return ":"")+b;p.push(fn);try{return Function.apply({},p)}catch(e){return null}};if(typeof(Array.prototype.where)==='undefined'){Array.prototype.where=function(f){var fn=f;if(typeof f=="string"){if((fn=lambda(fn))===null){throw "Syntax error in lambda string: "+f}}var res=[];var l=this.length;var p=[0,0,res];for(var i=1;i<arguments.length;i+=1){p.push(arguments[i])}for(var j=0;j<l;j+=1){if(typeof this[j]=="undefined"){continue}p[0]=this[j];p[1]=j;if(!!fn.apply(this,p)){res.push(this[j])}}return res}}if(!Array.prototype.forEach){Array.prototype.forEach=function(callback,thisArg){var T,k;if(this===null){throw new TypeError(' this is null or not defined')}var O=Object(this);var len=O.length>>>0;if(typeof callback!=="function"){throw new TypeError(callback+' is not a function')}if(arguments.length>1){T=thisArg}k=0;while(k<len){var kValue;if(k in O){kValue=O[k];callback.call(T,kValue,k,O)}k+=1}}}if(!Array.prototype.filter){Array.prototype.filter=function(fun ){'use strict';if(this===void 0||this===null){throw new TypeError()}var t=Object(this);var len=t.length>>>0;if(typeof fun!=='function'){throw new TypeError()}var res=[];var thisArg=arguments.length>=2?arguments[1]:void 0;for(var i=0;i<len;i+=1){if(i in t){var val=t[i];if(fun.call(thisArg,val,i,t)){res.push(val)}}}return res}}if(!Array.prototype.indexOf){Array.prototype.indexOf=function(searchElement,fromIndex){var k;if(this===null){throw new TypeError('"this" is null or not defined')}var O=Object(this);var len=O.length>>>0;if(len===0){return -1}var n= +fromIndex||0;if(Math.abs(n)===Infinity){n=0}if(n>=len){return -1}k=Math.max(n>=0?n:len-Math.abs(n),0);while(k<len){var kValue;if(k in O&&O[k]===searchElement){return k}k+=1}return -1}}if(typeof(String.prototype.localeCompare)==='undefined'){String.prototype.localeCompare=function(str,locale,options){return((this==str)?0:((this>str)?1:-1))}}
3
+ (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
4
+ "use strict";
5
+
6
+ /* start of nexrender script */
7
+
8
+ var nexrender = {
9
+ renderCompositionName: 'test',
10
+ defaultCompositionName: '*',
11
+ types: [CompItem, FolderItem, FootageItem, AVLayer, ShapeLayer, TextLayer, CameraLayer, LightLayer, Property, PropertyGroup],
12
+ };
13
+
14
+ nexrender.typesMatch = function (types, layer) {
15
+ return nexrender.types.filter(function (t) {
16
+ return layer instanceof t;
17
+ }).length > 0;
18
+ };
19
+
20
+ nexrender.replaceFootage = function (layer, filepath) {
21
+ if (!layer) { return false; }
22
+
23
+ var file = new File(filepath);
24
+
25
+ if (!file.exists) {
26
+ throw new Error("nexrender: Trying to create a file replacement for an unknown file: " + filepath);
27
+ }
28
+
29
+ var importOptions = new ImportOptions(file);
30
+ //importOptions.importAs = ImportAsType.COMP; // you can do stuff like this at this point for PSDs
31
+ var theImport = app.project.importFile(importOptions);
32
+ layer.replaceSource(theImport, true);
33
+
34
+ return true;
35
+ };
36
+
37
+ /* invoke callback for every composition matching specific name */
38
+ nexrender.selectCompositionsByName = function(name, callback) {
39
+ var items = [];
40
+ var nameChain = name.split("->");
41
+ var name = nameChain.pop();
42
+
43
+ function isNestedComp(comp, name, parentChain) {
44
+ if (
45
+ name &&
46
+ comp.name === name &&
47
+ parentChain &&
48
+ parentChain.length > 0 &&
49
+ comp.usedIn.length > 0
50
+ ) {
51
+ var parentComp = null;
52
+ for (var i = 0; i < comp.usedIn.length; i++) {
53
+ if (
54
+ comp.usedIn[i] instanceof CompItem &&
55
+ comp.usedIn[i].name === parentChain[parentChain.length - 1]
56
+ ) {
57
+ parentComp = comp.usedIn[i];
58
+ break;
59
+ }
60
+ }
61
+
62
+ if (parentComp) {
63
+ if (parentChain.length === 1) {
64
+ return true;
65
+ } else {
66
+ return isNestedComp(
67
+ parentComp,
68
+ parentChain.pop(),
69
+ parentChain
70
+ );
71
+ }
72
+ }
73
+ }
74
+ return false;
75
+ }
76
+
77
+ /* step 1: collect all matching compositions */
78
+ var len = app.project.items.length;
79
+ for (var i = 1; i <= len; i++) {
80
+ var item = app.project.items[i];
81
+ if (!(item instanceof CompItem)) continue;
82
+
83
+ if (name !== "*" && item.name !== name) {
84
+ continue;
85
+ } else if (nameChain.length === 0) { // if the comp name wasn't hierarchical
86
+ items.push(item);
87
+ } else if (isNestedComp(item, name, nameChain)) { // otherwise only add the comp if it matches the hierarchical position defined in the comp name
88
+ items.push(item);
89
+ } else {
90
+ continue;
91
+ }
92
+ }
93
+
94
+ /* step 2: invoke callback for every match */
95
+ var len = items.length;
96
+ for (var i = 0; i < len; i++) {
97
+ callback(items[i]);
98
+ }
99
+
100
+ if (len == 0) {
101
+ throw new Error("nexrender: Couldn't find any compositions by provided name (" + name + ")");
102
+ }
103
+ };
104
+
105
+ /* call callback for an every layer matching specific name and composition */
106
+ nexrender.selectLayersByName = function(compositionName, name, callback, types, continueOnMissing) {
107
+ var foundOnce = false;
108
+
109
+ if (!compositionName) compositionName = nexrender.defaultCompositionName;
110
+ if (!types) types = nexrender.types;
111
+
112
+ nexrender.selectCompositionsByName(compositionName, function(comp) {
113
+ var items = [];
114
+
115
+ /* step 1: collect all matching layers */
116
+ for (var j = 1; j <= comp.numLayers; j++) {
117
+ var layer = comp.layer(j);
118
+ if (layer.name !== name) continue;
119
+
120
+ if (nexrender.typesMatch(types, layer)) {
121
+ foundOnce = true;
122
+ items.push(layer);
123
+ }
124
+ }
125
+
126
+ /* step 2: invoke callback for every match */
127
+ var len = items.length;
128
+ for (var i = 0; i < len; i++) {
129
+ callback(items[i], name);
130
+ }
131
+ });
132
+
133
+ if (!foundOnce && !continueOnMissing) {
134
+ throw new Error("nexrender: Couldn't find any layers by provided name (" + name + ") inside a composition: " + compositionName);
135
+ }
136
+ };
137
+
138
+ /* call callback for every layer matching specific type and composition */
139
+ nexrender.selectLayersByType = function(
140
+ compositionName,
141
+ type,
142
+ callback,
143
+ types,
144
+ continueOnMissing
145
+ ) {
146
+ var foundOnce = false;
147
+
148
+ if (!compositionName) compositionName = nexrender.defaultCompositionName;
149
+ if (!types) types = nexrender.types;
150
+
151
+ nexrender.selectCompositionsByName(compositionName, function(comp) {
152
+ var items = [];
153
+
154
+ /* step 1: collect all matching layers */
155
+ for (var j = 1; j <= comp.numLayers; j++) {
156
+ var layer = comp.layer(j);
157
+
158
+ if (!(layer instanceof type)) continue;
159
+
160
+ if (nexrender.typesMatch(types, layer)) {
161
+ foundOnce = true;
162
+ items.push(layer);
163
+ }
164
+ }
165
+
166
+ /* step 2: invoke callback for every match */
167
+ var len = items.length;
168
+ for (var i = 0; i < len; i++) {
169
+ callback(items[i]);
170
+ }
171
+ });
172
+
173
+ if (!foundOnce && !continueOnMissing) {
174
+ throw new Error(
175
+ "nexrender: Couldn't find any layers by provided type ("
176
+ + type +
177
+ ") inside a composition: "
178
+ + compositionName
179
+ );
180
+ }
181
+ };
182
+
183
+ /* call callback for an every layer matching specific index and composition */
184
+ nexrender.selectLayersByIndex = function(compositionName, index, callback, types, continueOnMissing) {
185
+ var foundOnce = false;
186
+
187
+ if (!compositionName) compositionName = nexrender.defaultCompositionName;
188
+ if (!types) types = nexrender.types;
189
+
190
+ nexrender.selectCompositionsByName(compositionName, function(comp) {
191
+ var layer = comp.layer(index)
192
+ if (layer) {
193
+ callback(layer, index);
194
+ foundOnce = true;
195
+ }
196
+ })
197
+
198
+ if (!foundOnce && !continueOnMissing) {
199
+ throw new Error("nexrender: Couldn't find any layers by provided index (" + index + ") inside a composition: " + compositionName);
200
+ }
201
+ };
202
+
203
+ /* ensure that eval only gets a minimal variable scope */
204
+ nexrender.evaluate = function (layer, expression) {
205
+ return eval(expression);
206
+ }
207
+
208
+ nexrender.changeValueForKeypath = function (layer, keys, val) {
209
+ function change(o, keys, val) {
210
+ if (keys.length == 0) {
211
+ val.changed = false;
212
+ return val;
213
+ } else {
214
+ var key = keys[0];
215
+ if ("property" in o && o.property(key)) {
216
+ var prop = o.property(key)
217
+ if ("value" in prop) {
218
+ var pval = prop.value;
219
+ var v = change(pval, keys.slice(1), val)
220
+ if ("value" in v) {
221
+ prop.setValue(v.value)
222
+ } else {
223
+ prop.expression = v.expression
224
+ }
225
+ } else {
226
+ change(prop, keys.slice(1), val)
227
+ }
228
+ return { "value": o, "changed": true };
229
+ } else if (key in o) {
230
+ var v = change(o[key], keys.slice(1), val)
231
+ if (!v.changed) {
232
+ if ("value" in v) {
233
+ o[key] = v.value;
234
+ } else {
235
+ o[key] = nexrender.evaluate(layer, v.expression)
236
+ }
237
+ }
238
+ return { "value": o, "changed": true };
239
+ } else {
240
+ throw new Error("nexrender: Can't find a property sequence " + keys.join('.') + " for key: " + key + "within layer: " + layer.name);
241
+ }
242
+ }
243
+ }
244
+ change(layer, keys, val);
245
+ };
246
+
247
+
248
+ /* end of nexrender script */
249
+ /* start of custom user script */
250
+
251
+ (function() {
252
+ nexrender.selectLayersByName(null, 'test', function(layer) {
253
+ nexrender.replaceFootage(layer, '/Users/inlife/Projects/nexrender/packages/nexrender-core/test/workpath/7LyC6arUCXaJkBo7IORV-/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==.png')
254
+ }, null, undefined);
255
+ })();
256
+
257
+
258
+ /* end of custom user script */
259
+ },{}]},{},[1]);
@@ -0,0 +1 @@
1
+ Hello, World!
@@ -0,0 +1,4 @@
1
+ imitating rendering with aerender :p
2
+ rendering... 0%
3
+ rendering... 50%
4
+ rendering... 100%