├── .gitmodules ├── README.md ├── ScriptUI ├── CustomGlow │ ├── CustomGlow.jsx │ ├── README.md │ └── ui.png ├── DimensionConverter │ ├── DimensionConverter.jsx │ ├── README.md │ └── ui.png ├── FrameSplitter │ ├── FrameSplitter.jsx │ ├── README.md │ └── ui.png ├── LayerTrimmer │ ├── LayerTrimmer.jsx │ ├── README.md │ └── ui.png ├── MakeItStill │ ├── MakeItStill.jsx │ ├── README.md │ └── ui.png ├── MinimalMemo │ ├── MinimalMemo.jsx │ ├── README.md │ └── ui.png ├── MinimalTodo │ ├── MinimalTodo.jsx │ ├── README.md │ └── ui.png ├── PartialAdjustment │ ├── PartialAdjustment.jsx │ ├── README.md │ └── ui.png ├── README.md ├── SimpleMemo │ ├── README.md │ ├── SimpleMemo.jsx │ └── ui.png └── TimeRemap │ ├── README.md │ ├── TimeRemap.jsx │ └── ui.png ├── Startup ├── KikakuEventDispatcher │ ├── KikakuEventDispatcher.jsx │ └── README.md ├── KikakuFileManager │ ├── KikakuFileManager.jsx │ └── README.md ├── KikakuJSON │ ├── KikakuJSON.jsx │ └── README.md ├── KikakuSettingManager │ ├── KikakuSettingManager.jsx │ └── README.md ├── KikakuUIBuilder │ ├── KikakuUIBuilder.jsx │ ├── README.md │ ├── ui_example1.png │ └── ui_example2.png ├── KikakuUnit │ ├── KikakuUnit.jsx │ └── README.md ├── KikakuUtils │ ├── KikakuUtils.jsx │ └── README.md └── README.md └── typings └── kikaku ├── kikaku.d.ts ├── kikaku.event_dispatcher.d.ts ├── kikaku.file_manager.d.ts ├── kikaku.json.d.ts ├── kikaku.setting_manager.d.ts ├── kikaku.ui_builder.d.ts ├── kikaku.unit.d.ts └── kikaku.utils.d.ts /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "typings/aftereffects"] 2 | path = typings/aftereffects 3 | url = https://github.com/atarabi/aftereffects.d.ts.git 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AfterEffects-Scripts 2 | 3 | Adobe After Effects向けスクリプト集。 4 | 5 | ## Startup 6 | 7 | Startup向けスクリプト。 8 | 9 | ## ScriptUI 10 | 11 | ScriptUI向けスクリプト。 -------------------------------------------------------------------------------- /ScriptUI/CustomGlow/CustomGlow.jsx: -------------------------------------------------------------------------------- 1 | /* 2 | * CustomGlow v0.0.0 / ScriptUI 3 | * 4 | * Author: Kareobana(http://atarabi.com/) 5 | * License: MIT 6 | * Dependencies : 7 | * KIKAKU.Utils 0.0.0 8 | * KIKAKU.UIBuilder 2.0.0 9 | */ 10 | 11 | (function (global) { 12 | 13 | var Utils = KIKAKU.Utils, 14 | builder = new KIKAKU.UIBuilder(global, 'CustomGlow', {version: '0.0.0', author: 'Kareobana', url: 'http://atarabi.com/'}); 15 | 16 | builder 17 | .add('popup', 'Keying', {value: 'Extract', items: ['None', 'Extract']}) 18 | .add('popup', 'Blur', ['Fast Blur', 'Box Blur', 'Directional Blur', 'Radial Blur', 'Camera Lens Blur', 'Channel Blur', 'CC Radial Fast Blur', 'CC Radial Blur', 'CC Cross Blur', 'FL Out Of Focus']) 19 | .add('popup', 'Toner', {value: 'KikakuToner', items: ['None', 'KikakuToner', 'CC Toner', 'Tritone', 'Colorama', 'Tint', 'VC Color Vibrance']}) 20 | .add('popup', 'Intensity', {value: 'KikakuExposure', items: ['None', 'KikakuExposure', 'Exposure', 'Levels', 'Curves']}) 21 | .add('script', 'Execute', function () { 22 | function addEffect(name) { 23 | if (layer.Effects.canAddProperty(name)) { 24 | return layer.Effects.addProperty(name); 25 | } else { 26 | alert('Not Found: ' + name); 27 | return null; 28 | } 29 | } 30 | 31 | var layer = Utils.getSelectedLayer(); 32 | if (layer === null) { 33 | return; 34 | } 35 | 36 | switch (this.get('Keying')) { 37 | case 'Extract': 38 | addEffect('ADBE Extract'); 39 | break; 40 | } 41 | 42 | switch (this.get('Blur')) { 43 | case 'Fast Blur': 44 | addEffect('ADBE Fast Blur'); 45 | break; 46 | case 'Box Blur': 47 | addEffect('ADBE Box Blur2'); 48 | break; 49 | case 'Directional Blur': 50 | addEffect('ADBE Motion Blur'); 51 | break; 52 | case 'Radial Blur': 53 | addEffect('ADBE Radial Blur'); 54 | break; 55 | case 'Camera Lens Blur': 56 | addEffect('ADBE Camera Lens Blur'); 57 | break; 58 | case 'Channel Blur': 59 | addEffect('ADBE Channel Blur'); 60 | break; 61 | case 'CC Radial Fast Blur': 62 | addEffect('CC Radial Fast Blur'); 63 | break; 64 | case 'CC Radial Blur': 65 | addEffect('CC Radial Blur'); 66 | break; 67 | case 'CC Cross Blur': 68 | addEffect('CS CrossBlur'); 69 | break; 70 | case 'FL Out Of Focus': 71 | addEffect('DRFL Out of Focus'); 72 | break; 73 | } 74 | 75 | switch (this.get('Toner')) { 76 | case 'KikakuToner': 77 | addEffect('KikakuToner'); 78 | break; 79 | case 'CC Toner': 80 | addEffect('CC Toner'); 81 | break; 82 | case 'Tritone': 83 | addEffect('ADBE Tritone'); 84 | break; 85 | case 'Colorama': 86 | addEffect('APC Colorama'); 87 | break; 88 | case 'VC Color Vibrance': 89 | addEffect('VIDEOCOPILOT VIBRANCE'); 90 | break; 91 | } 92 | 93 | switch (this.get('Intensity')) { 94 | case 'KikakuExposure': 95 | addEffect('KikakuExposure'); 96 | break; 97 | case 'Exposure': 98 | addEffect('ADBE Exposure2'); 99 | break; 100 | case 'Levels': 101 | addEffect('ADBE Pro Levels2'); 102 | break; 103 | case 'Curves': 104 | addEffect('ADBE CurvesCustom'); 105 | break; 106 | } 107 | 108 | var composite = addEffect('KikakuComposite'); 109 | if (composite) { 110 | composite.property(2).setValue(13); 111 | composite.property(3).setValue(2); 112 | } 113 | }) 114 | .build(); 115 | 116 | })(this); 117 | -------------------------------------------------------------------------------- /ScriptUI/CustomGlow/README.md: -------------------------------------------------------------------------------- 1 | # CustomGlow 2 | 3 | エフェクトを組み合わせて自作グローを作る。 4 | 5 | ## 使い方 6 | 7 | ![UI](ui.png) 8 | 9 | 1. **Keying**, **Blur**, **Toner**, **Intensity**を色々選択し、適当に組み合わせる。 10 | 11 | 1. **Execute**をクリックすると選択レイヤーにエフェクトが追加される。 12 | 13 | ## Dependencies 14 | 15 | - [KIKAKU.Utils 1.0.0](https://github.com/atarabi/AfterEffects-Scripts/tree/master/Startup/KikakuUtils) 16 | - [KIKAKU.UIBuilder 2.0.0](https://github.com/atarabi/AfterEffects-Scripts/tree/master/Startup/KikakuUIBuilder) 17 | 18 | ## Version 19 | 20 | - v0.0.0 -------------------------------------------------------------------------------- /ScriptUI/CustomGlow/ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atarabi/AfterEffects-Scripts/108cc5f5abdafa751d2dc9081f374af881cc6500/ScriptUI/CustomGlow/ui.png -------------------------------------------------------------------------------- /ScriptUI/DimensionConverter/DimensionConverter.jsx: -------------------------------------------------------------------------------- 1 | /* 2 | * DimensionConverter v0.0.0 / ScriptUI 3 | * 4 | * Author: Kareobana(http://atarabi.com/) 5 | * License: MIT 6 | * Dependencies : 7 | * KIKAKU.Utils 0.2.0 8 | * KIKAKU.UIBuilder 1.0.0 9 | */ 10 | 11 | (function (global) { 12 | 13 | //Lib 14 | var Utils = KIKAKU.Utils, 15 | UIBuilder = KIKAKU.UIBuilder; 16 | 17 | //functions 18 | function trim(str) { 19 | return str.replace(/^\s+|\s+$/g, ''); 20 | } 21 | 22 | function escapeRegExp(str) { 23 | return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); 24 | } 25 | 26 | function getPropertyDimensions(property) { 27 | switch (property.propertyValueType) { 28 | case PropertyValueType.ThreeD_SPATIAL: 29 | case PropertyValueType.ThreeD: 30 | return 3; 31 | case PropertyValueType.TwoD_SPATIAL: 32 | case PropertyValueType.TwoD: 33 | return 2; 34 | case PropertyValueType.OneD: 35 | return 1; 36 | case PropertyValueType.COLOR: 37 | return 4; 38 | default: 39 | return -1; 40 | } 41 | } 42 | 43 | //Main 44 | var builder = new UIBuilder(global, 'DimensionConverter', { version: '0.0.0', author: 'Kareobana', url: 'http://atarabi.com/' }); 45 | 46 | builder 47 | .add('popup', 'Unite Type', ['Controls', 'Null'], function () { 48 | var unite_type = this.get('Unite Type'); 49 | switch (unite_type) { 50 | case 'Controls': 51 | this.enable('Separate'); 52 | break; 53 | case 'Null': 54 | this.disable('Separate'); 55 | break; 56 | } 57 | }) 58 | .add('script', 'Separate', function () { 59 | var layer = Utils.getSelectedLayer(); 60 | if (layer === null) { 61 | return; 62 | } 63 | 64 | var properties = layer.selectedProperties.slice(); 65 | for (var i = 0, l = properties.length; i < l; i++) { 66 | var property = properties[i]; 67 | if (Utils.isProperty(property)) { 68 | var dimensions = getPropertyDimensions(property); 69 | if (dimensions > 1) { 70 | var property_value = property.value, 71 | property_name = property.name, 72 | property_path = Utils.getPathOfProperty(property), 73 | parent_property = property.parentProperty; 74 | $.writeln(property_path); 75 | 76 | property_name = parent_property.name + ' - ' + property_name; 77 | 78 | if (dimensions === 2) { 79 | var x_slider = layer.Effects.addProperty('ADBE Slider Control'), 80 | x_slider_name = property_name + ' X'; 81 | 82 | x_slider.enabled = false; 83 | x_slider.name = x_slider_name; 84 | x_slider.property(1).setValue(property_value[0]); 85 | 86 | var y_slider = layer.Effects.addProperty('ADBE Slider Control'), 87 | y_slider_name = property_name + ' Y'; 88 | 89 | y_slider.enabled = false; 90 | y_slider.name = y_slider_name; 91 | y_slider.property(1).setValue(property_value[1]); 92 | 93 | property = Utils.getPropertyFromPath(layer, property_path); 94 | property.expression = 'x = effect("' + x_slider_name + '")(1); y = effect("' + y_slider_name + '")(1); [x, y];'; 95 | break; 96 | } else if (dimensions === 3) { 97 | var x_slider = layer.Effects.addProperty('ADBE Slider Control'), 98 | x_slider_name = property_name + ' X'; 99 | 100 | x_slider.enabled = false; 101 | x_slider.name = x_slider_name; 102 | x_slider.property(1).setValue(property_value[0]); 103 | 104 | var y_slider = layer.Effects.addProperty('ADBE Slider Control'), 105 | y_slider_name = property_name + ' Y'; 106 | 107 | y_slider.enabled = false; 108 | y_slider.name = y_slider_name; 109 | y_slider.property(1).setValue(property_value[1]); 110 | 111 | var z_slider = layer.Effects.addProperty('ADBE Slider Control'), 112 | z_slider_name = property_name + ' Z'; 113 | 114 | z_slider.enabled = false; 115 | z_slider.name = z_slider_name; 116 | z_slider.property(1).setValue(property_value[2]); 117 | 118 | property = Utils.getPropertyFromPath(layer, property_path); 119 | property.expression = 'x = effect("' + x_slider_name + '")(1); y = effect("' + y_slider_name + '")(1); z = effect("' + z_slider_name + '")(1); [x, y, z];'; 120 | break; 121 | } else if (dimensions === 4) { 122 | var hsl = Utils.rgbToHsl(property_value); 123 | 124 | var h_slider = layer.Effects.addProperty('ADBE Angle Control'), 125 | h_slider_name = property_name + ' H'; 126 | 127 | h_slider.enabled = false; 128 | h_slider.name = h_slider_name; 129 | h_slider.property(1).setValue(hsl[0] * 360); 130 | 131 | var s_slider = layer.Effects.addProperty('ADBE Slider Control'), 132 | s_slider_name = property_name + ' S'; 133 | 134 | s_slider.enabled = false; 135 | s_slider.name = s_slider_name; 136 | s_slider.property(1).setValue(hsl[1] * 100); 137 | 138 | var l_slider = layer.Effects.addProperty('ADBE Slider Control'), 139 | l_slider_name = property_name + ' L'; 140 | 141 | l_slider.enabled = false; 142 | l_slider.name = l_slider_name; 143 | l_slider.property(1).setValue(hsl[2] * 100); 144 | 145 | property = Utils.getPropertyFromPath(layer, property_path); 146 | property.expression = 'h = (effect("' + h_slider_name + '")(1) / 360) % 1; if (h < 0) h += 1; s = effect("' + s_slider_name + '")(1) / 100; l = effect("' + l_slider_name + '")(1) / 100; hslToRgb([h, s, l, 1]);'; 147 | break; 148 | } 149 | } 150 | } 151 | } 152 | }) 153 | .add('script', 'Unite', function () { 154 | function uniteNames(name1, name2) { 155 | if (name1 === null || name1 === name2) { 156 | return name2; 157 | } 158 | return ''; 159 | } 160 | 161 | function getPrefix(name1, name2) { 162 | if (name1 === null) { 163 | return name2; 164 | } 165 | var name = ''; 166 | for (var i = 0, l = Math.min(name1.length, name2.length); i < l; i++) { 167 | if (name1[i] === name2[i]) { 168 | name += name1[i]; 169 | } else { 170 | break; 171 | } 172 | } 173 | return name; 174 | } 175 | 176 | function getSuffix(name1, name2) { 177 | if (name1 === null) { 178 | return name2; 179 | } 180 | var name = ''; 181 | for (var i = 0, l = Math.min(name1.length, name2.length); i < l; i++) { 182 | if (name1[name1.length - (i + 1)] === name2[name2.length - (i + 1)]) { 183 | name = name1[name1.length - (i + 1)] + name; 184 | } else { 185 | break; 186 | } 187 | } 188 | return name; 189 | } 190 | 191 | function getControlName(parent_name, prefix, suffix, property_infos, default_dimensions_name) { 192 | function getDimensionsName() { 193 | if (prefix === '' && suffix === '') { 194 | return ''; 195 | } 196 | var name = ''; 197 | for (var i = 0, l = property_infos.length; i < l; i++) { 198 | var property_name = property_infos[i].name; 199 | name += trim(property_name.replace(new RegExp('(^' + escapeRegExp(prefix) + ')|(' + escapeRegExp(suffix) + '$)', 'g'), '')); 200 | } 201 | return name; 202 | } 203 | 204 | function getExistingNames() { 205 | var names = {}; 206 | 207 | if (unite_type === 'Controls') { 208 | for (var i = 1, l = layer.Effects.numProperties; i <= l; i++) { 209 | names[layer.Effects.property(i).name] = true; 210 | } 211 | } else if (unite_type === 'Null') { 212 | for (var i = 1, l = comp.numLayers; i <= l; i++) { 213 | names[comp.layer(i).name] = true; 214 | } 215 | } 216 | 217 | return names; 218 | } 219 | 220 | var dimensions_name = getDimensionsName() || default_dimensions_name; 221 | 222 | if (prefix !== '') { 223 | prefix = prefix + ' '; 224 | } 225 | if (suffix !== '') { 226 | suffix = ' ' + suffix; 227 | } 228 | if (parent_name !== '') { 229 | parent_name += ' - '; 230 | } 231 | 232 | var existing_names = getExistingNames(), 233 | name = parent_name + prefix + dimensions_name + suffix; 234 | 235 | if (unite_type === 'Null') { 236 | name = layer.name + ' / ' + name; 237 | } 238 | 239 | if (existing_names[name]) { 240 | var n = 2; 241 | while (existing_names[name + ' ' + n]) { 242 | n++; 243 | } 244 | name += ' ' + n; 245 | } 246 | return name; 247 | } 248 | 249 | var comp = Utils.getActiveComp(), 250 | layer = Utils.getSelectedLayer(); 251 | if (layer === null) { 252 | return; 253 | } 254 | 255 | var properties = layer.selectedProperties.slice(), 256 | property_value = [], 257 | property_prefix = null, 258 | property_suffix = null, 259 | parent_name = null, 260 | property_infos = [], 261 | total_dimensions = 0; 262 | for (var i = 0, l = properties.length; i < l; i++) { 263 | var property = properties[i]; 264 | if (Utils.isProperty(property)) { 265 | var dimensions = getPropertyDimensions(property); 266 | if (dimensions > 0) { 267 | property_prefix = getPrefix(property_prefix, property.name); 268 | property_suffix = getSuffix(property_suffix, property.name); 269 | parent_name = uniteNames(parent_name, property.parentProperty.name); 270 | if (dimensions === 1) { 271 | property_value.push(property.value); 272 | } else { 273 | property_value = property_value.concat(property.value); 274 | } 275 | property_infos.push({ 276 | dimensions: dimensions, 277 | name: property.name, 278 | path: Utils.getPathOfProperty(property), 279 | }); 280 | total_dimensions += dimensions; 281 | } 282 | } 283 | } 284 | 285 | if (property_infos.length > 1 && (total_dimensions === 2 || total_dimensions === 3)) { 286 | property_prefix = trim(property_prefix); 287 | property_suffix = trim(property_suffix); 288 | 289 | var unite_type = this.get('Unite Type'), 290 | name = getControlName(parent_name, property_prefix, property_suffix, property_infos, total_dimensions === 2 ? 'XY' : 'XYZ'); 291 | 292 | if (unite_type === 'Controls') { 293 | try { 294 | var point_control = total_dimensions === 2 ? layer.Effects.addProperty('ADBE Point Control') : layer.Effects.addProperty('ADBE Point3D Control'); 295 | 296 | point_control.enabled = false; 297 | point_control.name = name; 298 | point_control.property(1).setValue(property_value); 299 | 300 | var offset = 0; 301 | for (var i = 0, l = property_infos.length; i < l; i++) { 302 | var property_info = property_infos[i], 303 | dimensions = property_info.dimensions, 304 | property = Utils.getPropertyFromPath(layer, property_info.path); 305 | 306 | if (dimensions === 1) { 307 | if (property.canSetExpression) { 308 | property.expression = 'effect("' + name + '")(1)[' + offset + ']'; 309 | } 310 | } else if (dimensions === 2) { 311 | if (property.canSetExpression) { 312 | property.expression = 'prop = effect("' + name + '")(1); [prop[' + offset + '], prop[' + (offset + 1) + ']]'; 313 | } 314 | } 315 | offset += dimensions; 316 | } 317 | } catch (e) { 318 | } 319 | } else if (unite_type === 'Null') { 320 | try { 321 | var null_layer = comp.layers.addNull(), 322 | null_layer_name = name; 323 | null_layer.threeDLayer = total_dimensions === 3; 324 | null_layer.name = null_layer_name; 325 | null_layer.transform.position.setValue(property_value); 326 | null_layer.moveBefore(layer); 327 | 328 | var offset = 0; 329 | for (var i = 0, l = property_infos.length; i < l; i++) { 330 | var property_info = property_infos[i], 331 | dimensions = property_info.dimensions, 332 | property = Utils.getPropertyFromPath(layer, property_info.path); 333 | 334 | if (dimensions === 1) { 335 | if (property.canSetExpression) { 336 | property.expression = 'thisComp.layer("' + null_layer_name + '").transform.position[' + offset + ']'; 337 | } 338 | } else if (dimensions === 2) { 339 | if (property.canSetExpression) { 340 | property.expression = 'prop = thisComp.layer("' + null_layer_name + '").transform.position; [prop[' + offset + '], prop[' + (offset + 1) + ']]'; 341 | } 342 | } 343 | offset += dimensions; 344 | } 345 | } catch (e) { 346 | } 347 | } 348 | } 349 | }) 350 | .build(); 351 | 352 | })(this); 353 | -------------------------------------------------------------------------------- /ScriptUI/DimensionConverter/README.md: -------------------------------------------------------------------------------- 1 | # DimensionConverter 2 | 3 | プロパティの次元を変換する。 4 | 5 | - 3(2)次元パラメータを1次元パラメータ3(2)つに分割する。 6 | 7 | - 2次元パラメータと1次元パラメータを3次元パラメータ1つに結合する。 8 | 9 | - 1次元パラメータ3(2)つを3(2)次元パラメータ1つに結合する。 10 | 11 | ## 使い方 12 | 13 | ![UI](ui.png) 14 | 15 | - Unite Type 16 | 17 | - Controls 18 | 19 | エクスプレッション制御エフェクトを用いる。 20 | 21 | - Null 22 | 23 | エクスプレッション制御エフェクトの代わりにヌルを使う。 24 | 25 | - Separate 26 | 27 | 2,3次元パラメータから複数の1次元パラメータに分割する。 28 | 29 | - Unite 30 | 31 | 複数の1次元パラメータから2,3次元パラメータ(またはヌルの位置)に結合する。 32 | 33 | ## Dependencies 34 | 35 | - [KIKAKU.Utils 1.0.0](https://github.com/atarabi/AfterEffects-Scripts/tree/master/Startup/KikakuUtils) 36 | - [KIKAKU.UIBuilder 2.0.0](https://github.com/atarabi/AfterEffects-Scripts/tree/master/Startup/KikakuUIBuilder) 37 | 38 | ## Version 39 | 40 | - v0.1.0 -------------------------------------------------------------------------------- /ScriptUI/DimensionConverter/ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atarabi/AfterEffects-Scripts/108cc5f5abdafa751d2dc9081f374af881cc6500/ScriptUI/DimensionConverter/ui.png -------------------------------------------------------------------------------- /ScriptUI/FrameSplitter/FrameSplitter.jsx: -------------------------------------------------------------------------------- 1 | /* 2 | * FrameSplitter v0.0.0 / ScriptUI 3 | * 4 | * Author: Kareobana(http://atarabi.com/) 5 | * License: MIT 6 | * Dependencies: 7 | * KIKAKU.Utils 1.0.0 8 | * KIKAKU.UIBuilder 2.0.0 9 | */ 10 | 11 | (function (global) { 12 | 13 | var Utils = KIKAKU.Utils, 14 | builder = new KIKAKU.UIBuilder(global, 'FrameSplitter', {version: '0.0.0', author: 'Kareobana', url: 'http://atarabi.com/'}); 15 | 16 | builder 17 | .add('number', 'Frame', {value: 1, minvalue: 1}) 18 | .add('checkbox', 'Remove', true) 19 | .add('script', 'Split', function () { 20 | var comp = Utils.getActiveComp(), 21 | layer = Utils.getSelectedLayer(); 22 | if (layer === null) { 23 | return; 24 | } 25 | 26 | var frame = this.get('Frame'), 27 | frame_duration = comp.frameDuration, 28 | delta = frame * frame_duration, 29 | prev_layer = layer; 30 | for (var t = layer.inPoint; t <= layer.outPoint - frame_duration; t += delta) { 31 | var duplicated_layer = layer.duplicate(); 32 | duplicated_layer.inPoint = t; 33 | duplicated_layer.outPoint = t + delta > layer.outPoint ? layer.outPoint : t + delta; 34 | duplicated_layer.moveBefore(prev_layer); 35 | prev_layer = duplicated_layer; 36 | } 37 | if (this.get('Remove')) { 38 | layer.remove(); 39 | } 40 | }) 41 | .build(); 42 | 43 | })(this); 44 | -------------------------------------------------------------------------------- /ScriptUI/FrameSplitter/README.md: -------------------------------------------------------------------------------- 1 | # FrameSplitter 2 | 3 | nフレームごとにレイヤーを分割。 4 | 5 | ## 使い方 6 | 7 | ![UI](ui.png) 8 | 9 | 1. **Frame**で何フレームごとに分割するかを決める。 10 | 11 | 1. **Split**をクリックで実行。**Remove**がチェックされている場合、元の動画は取り除かれる。 12 | 13 | ## Dependencies 14 | 15 | - [KIKAKU.Utils 1.0.0](https://github.com/atarabi/AfterEffects-Scripts/tree/master/Startup/KikakuUtils) 16 | - [KIKAKU.UIBuilder 2.0.0](https://github.com/atarabi/AfterEffects-Scripts/tree/master/Startup/KikakuUIBuilder) 17 | 18 | ## Version 19 | 20 | - v0.0.0 -------------------------------------------------------------------------------- /ScriptUI/FrameSplitter/ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atarabi/AfterEffects-Scripts/108cc5f5abdafa751d2dc9081f374af881cc6500/ScriptUI/FrameSplitter/ui.png -------------------------------------------------------------------------------- /ScriptUI/LayerTrimmer/LayerTrimmer.jsx: -------------------------------------------------------------------------------- 1 | /* 2 | * LayerTrimmer v0.0.0 / ScriptUI 3 | * 4 | * Author: Kareobana(http://atarabi.com/) 5 | * License: MIT 6 | * Dependencies: 7 | * KIKAKU.JSON 8 | * KIKAKU.Utils 1.0.0 9 | * KIKAKU.UIBuilder 2.0.0 10 | */ 11 | 12 | (function (global) { 13 | //Lib 14 | var JSON = KIKAKU.JSON, 15 | Utils = KIKAKU.Utils, 16 | UIBuilder = KIKAKU.UIBuilder; 17 | 18 | //Utility 19 | var assign = Utils.assign, 20 | forEach = Utils.forEach, 21 | isTextLayer = Utils.isTextLayer, 22 | isShapeLayer = Utils.isShapeLayer, 23 | isCompLayer = Utils.isCompLayer, 24 | getActiveComp = Utils.getActiveComp, 25 | getCompByName = Utils.getCompByName, 26 | getSelectedLayer = Utils.getSelectedLayer, 27 | getLayer = Utils.getLayer, 28 | getLayers = Utils.getLayers; 29 | 30 | //Constants 31 | var SCAN = { 32 | CURRENT_FRAME: 'Current Frame', 33 | ALL_FRAMES: 'All Frames', 34 | }; 35 | 36 | var CENTER = { 37 | COMPOSITION: 'Composition', 38 | CONTENTS: 'Contents', 39 | }; 40 | 41 | //Functions 42 | function getValues(obj) { 43 | var values = []; 44 | for (var key in obj) { 45 | values.push(obj[key]); 46 | } 47 | return values; 48 | } 49 | 50 | function setValue(property, value, time) { 51 | if (property.numKeys) { 52 | property.setValueAtTime(time, value); 53 | } else { 54 | property.setValue(value); 55 | } 56 | } 57 | 58 | function setComment(layer, obj) { 59 | var comment = layer.comment; 60 | try { 61 | comment = JSON.parse(comment); 62 | } catch (e) { 63 | comment = comment ? {comment: comment} : {}; 64 | } 65 | assign(comment, obj); 66 | 67 | layer.comment = JSON.stringify(comment); 68 | } 69 | 70 | function getComment(layer) { 71 | var comment = layer.comment; 72 | try { 73 | comment = JSON.parse(comment); 74 | } catch (e) { 75 | comment = { 76 | comment: comment 77 | }; 78 | } 79 | return comment; 80 | } 81 | 82 | function removeComment(layer, key) { 83 | var comment = layer.comment; 84 | try { 85 | comment = JSON.parse(comment); 86 | } catch (e) { 87 | return; 88 | } 89 | 90 | delete comment[key]; 91 | 92 | var has_key = false, 93 | only_comment = true; 94 | for (var k in comment) { 95 | has_key = true; 96 | if (k !== 'comment') { 97 | only_comment = false; 98 | break; 99 | } 100 | } 101 | 102 | if (!has_key) { 103 | layer.comment = ''; 104 | } else { 105 | layer.comment = only_comment ? comment.comment : JSON.stringify(comment); 106 | } 107 | } 108 | 109 | function getRect(comp, layer, scan, extents) { 110 | var rect = { 111 | left: Infinity, 112 | top: Infinity, 113 | right: -Infinity, 114 | bottom: -Infinity, 115 | }; 116 | 117 | if (scan === SCAN.CURRENT_FRAME) { 118 | var _rect = layer.sourceRectAtTime(layer.time, extents); 119 | rect.left = _rect.left; 120 | rect.top = _rect.top; 121 | rect.right = _rect.left + _rect.width; 122 | rect.bottom = _rect.top + _rect.height; 123 | } else if (scan === SCAN.ALL_FRAMES) { 124 | var in_point = layer.inPoint, 125 | out_point = layer.outPoint, 126 | frame_duration = comp.frameDuration; 127 | 128 | if (in_point > out_point) { 129 | var temp = in_point; 130 | in_point = out_point; 131 | out_point = temp; 132 | } 133 | 134 | for (var t = in_point; t < out_point; t += frame_duration) { 135 | var _rect = layer.sourceRectAtTime(t, extents); 136 | rect.left = Math.min(rect.left, _rect.left); 137 | rect.top = Math.min(rect.top, _rect.top); 138 | rect.right = Math.max(rect.right, _rect.left + _rect.width); 139 | rect.bottom = Math.max(rect.bottom, _rect.top + _rect.height); 140 | } 141 | } 142 | 143 | return rect; 144 | } 145 | 146 | function createPrecomp(script_name, comp, layer, name, rect, center, padding, precomp) { 147 | var width, 148 | height, 149 | position, 150 | pixel_aspect = comp.pixelAspect, 151 | duration = Math.abs(layer.inPoint - layer.outPoint), 152 | frame_rate = comp.frameRate; 153 | 154 | if (center === CENTER.COMPOSITION) { 155 | width = 2 * (Math.ceil(Math.max(Math.abs(rect.left), Math.abs(rect.right))) + padding); 156 | height = 2 * (Math.ceil(Math.max(Math.abs(rect.top), Math.abs(rect.bottom))) + padding); 157 | position = [width / 2, height / 2]; 158 | } else if (center === CENTER.CONTENTS) { 159 | width = Math.ceil(rect.right - rect.left) + 2 * padding; 160 | height = Math.ceil(rect.bottom - rect.top) + 2 * padding; 161 | position = [width / 2 - (rect.left + rect.right) / 2, height / 2 - (rect.top + rect.bottom) / 2]; 162 | } 163 | 164 | if (precomp) { 165 | forEach(getLayers('all', precomp), function (layer) { 166 | layer.remove(); 167 | }); 168 | precomp.name = name; 169 | precomp.width = width; 170 | precomp.height = height; 171 | precomp.pixelAspect = pixel_aspect; 172 | precomp.duration = duration; 173 | precomp.frameRate = frame_rate; 174 | } else { 175 | precomp = app.project.items.addComp(name, width, height, pixel_aspect, duration, frame_rate); 176 | } 177 | layer.copyToComp(precomp); 178 | 179 | var copied_layer = precomp.layer(1); 180 | removeComment(copied_layer, script_name); 181 | copied_layer.enabled = true; 182 | if (layer.inPoint < layer.outPoint) { 183 | copied_layer.startTime = 0; 184 | } else { 185 | copied_layer.startTime = comp.duration; 186 | } 187 | setValue(copied_layer.transform.position, position, 0); 188 | 189 | return precomp; 190 | } 191 | 192 | //Main 193 | var builder = new UIBuilder(global, 'LayerTrimmer', { 194 | version: '0.0.0', 195 | author: 'Kareobana', 196 | url: 'http://atarabi.com/', 197 | titleWidth: 60, 198 | }); 199 | 200 | builder 201 | .add('popup', 'Scan', {value: SCAN.ALL_FRAMES, items: getValues(SCAN)}) 202 | .add('checkbox', 'Extents', true) 203 | .add('popup', 'Center', {value: CENTER.CONTENTS, items: getValues(CENTER)}) 204 | .add('number', 'Padding', {value: 0, minvalue: 0}, function () { 205 | this.set('Padding', ~~this.get('Padding')); 206 | }) 207 | .add('script', 'Execute', function () { 208 | var layer = getSelectedLayer(); 209 | if (!layer) { 210 | return alert('Select a layer.'); 211 | } else if (!(isTextLayer(layer) || isShapeLayer(layer))) { 212 | return alert('Select a text layer or shape layer.'); 213 | } 214 | 215 | var comp = getActiveComp(), 216 | comment = getComment(layer)[this.getName()], 217 | update = false; 218 | 219 | if (comment && comment.comp) { 220 | update = true; 221 | } 222 | 223 | if (!update) { 224 | var rect = getRect(comp, layer, this.get('Scan'), this.get('Extents')); 225 | var precomp_name = prompt('Input a composition\'s name', ''); 226 | if (!precomp_name) { 227 | return; 228 | } else if (getCompByName(precomp_name)) { 229 | removeComment(layer, this.getName()); 230 | return alert(precomp_name + ' already exists.'); 231 | } 232 | 233 | var precomp = createPrecomp(this.getName(), comp, layer, precomp_name, rect, isTextLayer(layer) ? CENTER.CONTENTS : this.get('Center'), this.get('Padding')), 234 | precomp_layer = comp.layers.add(precomp); 235 | precomp_layer.moveBefore(layer); 236 | precomp_layer.startTime = Math.min(layer.inPoint, layer.outPoint); 237 | 238 | comment = {}; 239 | comment[this.getName()] = { 240 | comp: precomp_name 241 | }; 242 | setComment(layer, comment); 243 | 244 | layer.enabled = false; 245 | } else { 246 | var precomp = getCompByName(comment.comp); 247 | if (!precomp) { 248 | return alert(comment.comp + ' is not found.'); 249 | } 250 | var rect = getRect(comp, layer, this.get('Scan'), this.get('Extents')); 251 | 252 | createPrecomp(this.getName(), comp, layer, precomp.name, rect, isTextLayer(layer) ? CENTER.CONTENTS : this.get('Center'), this.get('Padding'), precomp); 253 | 254 | var precomp_layer = getLayer(function (layer) { 255 | return isCompLayer(layer) && layer.source === precomp; 256 | }, comp); 257 | precomp_layer.moveBefore(layer); 258 | precomp_layer.startTime = Math.min(layer.inPoint, layer.outPoint); 259 | precomp_layer.inPoint = precomp_layer.startTime; 260 | precomp_layer.outPoint = precomp_layer.startTime + precomp.duration; 261 | 262 | layer.enabled = false; 263 | } 264 | }) 265 | .build(); 266 | 267 | })(this); 268 | -------------------------------------------------------------------------------- /ScriptUI/LayerTrimmer/README.md: -------------------------------------------------------------------------------- 1 | # LayerTrimmer 2 | 3 | シェイプレイヤー、テキストレイヤーをコンテンツに応じてトリミングする。 4 | 5 | ## 使い方 6 | 7 | ![UI](ui.png) 8 | 9 | ### 基本 10 | 11 | 1. **Scan**で現在のフレームの境界のみをチェックするか、全フレームの境界をチェックするかを決める。また、シェイプレイヤーの場合は**Extents**でストローク等による描写範囲の拡大を考慮するかを決める。 12 | 13 | 1. **Center**で、コンポジションの中心とコンテンツの中心のどちらを基準にするか決める(テキストレイヤーはコンテンツ中心のみ)。 14 | 15 | 1. **Execute**をクリックで実行。 16 | 17 | ### 更新 18 | 19 | 1. 更新したいシェイプレイヤーまたはテキストレイヤーを選択(一度実行したレイヤーにはコメントに情報が付加されるのでそれを参照)。 20 | 21 | 1. **Execute**をクリックで更新。 22 | 23 | ## Dependencies 24 | 25 | - [KIKAKU.JSON](https://github.com/atarabi/AfterEffects-Scripts/tree/master/Startup/KikakuJSON) 26 | - [KIKAKU.Utils 1.0.0](https://github.com/atarabi/AfterEffects-Scripts/tree/master/Startup/KikakuUtils) 27 | - [KIKAKU.UIBuilder 2.0.0](https://github.com/atarabi/AfterEffects-Scripts/tree/master/Startup/KikakuUIBuilder) 28 | 29 | ## Version 30 | 31 | - v0.0.0 -------------------------------------------------------------------------------- /ScriptUI/LayerTrimmer/ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atarabi/AfterEffects-Scripts/108cc5f5abdafa751d2dc9081f374af881cc6500/ScriptUI/LayerTrimmer/ui.png -------------------------------------------------------------------------------- /ScriptUI/MakeItStill/MakeItStill.jsx: -------------------------------------------------------------------------------- 1 | /* 2 | * MakeItStill v0.0.0 / ScriptUI 3 | * 4 | * Author: Kareobana(http://atarabi.com/) 5 | * License: MIT 6 | * Dependencies: 7 | * KIKAKU.Utils 1.0.0 8 | * KIKAKU.UIBuilder 2.0.0 9 | */ 10 | 11 | (function(global) { 12 | //Lib 13 | var Utils = KIKAKU.Utils, 14 | UIBuilder = KIKAKU.UIBuilder; 15 | 16 | //Utility 17 | var isAVLayer = Utils.isAVLayer, 18 | getSelectedLayer = Utils.getSelectedLayer; 19 | 20 | //Main 21 | var TIME_MODE = { 22 | CURRENT: 'Current', 23 | IN_POINT: 'inPoint' 24 | }; 25 | 26 | var builder = new KIKAKU.UIBuilder(global, 'MakeItStill', { 27 | version: '0.0.0', 28 | author: 'Kareobana', 29 | url: 'http://atarabi.com/' 30 | }); 31 | 32 | builder 33 | .add('popup', 'Time', [TIME_MODE.CURRENT, TIME_MODE.IN_POINT]) 34 | .add('script', 'Execute', function() { 35 | var layer = getSelectedLayer(); 36 | if (!(layer && isAVLayer(layer) && layer.canSetTimeRemapEnabled)) { 37 | return; 38 | } 39 | var type = this.get('Time'), 40 | start_time = layer.startTime, 41 | in_point = layer.inPoint, 42 | out_point = layer.outPoint, 43 | timeremap_enabled = layer.timeRemapEnabled, 44 | time; 45 | 46 | switch (type) { 47 | case TIME_MODE.CURRENT: 48 | if (timeremap_enabled) { 49 | time = layer.timeRemap.value; 50 | } else { 51 | time = layer.time - start_time; 52 | } 53 | break; 54 | case TIME_MODE.IN_POINT: 55 | if (timeremap_enabled) { 56 | time = layer.timeRemap.valueAtTime(in_point, false); 57 | } else { 58 | time = in_point - start_time; 59 | } 60 | break; 61 | } 62 | 63 | layer.timeRemapEnabled = false; 64 | layer.timeRemapEnabled = true; 65 | layer.timeRemap.setValueAtKey(1, time); 66 | layer.timeRemap.setValueAtKey(2, time); 67 | layer.inPoint = in_point; 68 | layer.outPoint = out_point; 69 | }) 70 | .build(); 71 | 72 | })(this); 73 | -------------------------------------------------------------------------------- /ScriptUI/MakeItStill/README.md: -------------------------------------------------------------------------------- 1 | # MakeItStill 2 | 3 | 動画(タイムリマップ可能なレイヤー)を止める。 4 | 5 | ## 使い方 6 | 7 | ![UI](ui.png) 8 | 9 | *Current*を選択し、**Execute**を押すと現在のレイヤー時間で停止。*inPoint*を選択すると、インポイントで停止。 10 | 11 | ## Dependencies 12 | 13 | - [KIKAKU.Utils 1.0.0](https://github.com/atarabi/AfterEffects-Scripts/tree/master/Startup/KikakuUtils) 14 | - [KIKAKU.UIBuilder 2.0.0](https://github.com/atarabi/AfterEffects-Scripts/tree/master/Startup/KikakuUIBuilder) 15 | 16 | ## Version 17 | 18 | - v0.0.0 -------------------------------------------------------------------------------- /ScriptUI/MakeItStill/ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atarabi/AfterEffects-Scripts/108cc5f5abdafa751d2dc9081f374af881cc6500/ScriptUI/MakeItStill/ui.png -------------------------------------------------------------------------------- /ScriptUI/MinimalMemo/MinimalMemo.jsx: -------------------------------------------------------------------------------- 1 | /* 2 | * MinimalMemo v0.0.0 / ScriptUI 3 | * 4 | * Author: Kareobana(http://atarabi.com/) 5 | * License: MIT 6 | * Dependencies: 7 | * KIKAKU.UIBuilder 2.0.0 8 | */ 9 | 10 | (function (global) { 11 | 12 | new KIKAKU.UIBuilder(global, 'MinimalMemo', {version: '0.0.0', author: 'Kareobana', url: 'http://atarabi.com/', autoSave: true, help: false}) 13 | .add('textarea', 'Memo', '', {title: false, height: 150}) 14 | .api('write', function (text) { 15 | if (typeof text === 'string') { 16 | this.set('Memo', text); 17 | } 18 | }) 19 | .api('append', function (text) { 20 | if (typeof text === 'string') { 21 | this.set('Memo', this.get('Memo') + text); 22 | } 23 | }) 24 | .build(); 25 | 26 | })(this); 27 | -------------------------------------------------------------------------------- /ScriptUI/MinimalMemo/README.md: -------------------------------------------------------------------------------- 1 | # MinimalMemo 2 | 3 | ミニマルなメモ。テキストは設定ファイルに保存される。 4 | 5 | ![UI](ui.png) 6 | 7 | ## Dependencies 8 | 9 | - [KIKAKU.UIBuilder 2.0.0](https://github.com/atarabi/AfterEffects-Scripts/tree/master/Startup/KikakuUIBuilder) 10 | 11 | ## Version 12 | 13 | - v0.0.0 -------------------------------------------------------------------------------- /ScriptUI/MinimalMemo/ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atarabi/AfterEffects-Scripts/108cc5f5abdafa751d2dc9081f374af881cc6500/ScriptUI/MinimalMemo/ui.png -------------------------------------------------------------------------------- /ScriptUI/MinimalTodo/MinimalTodo.jsx: -------------------------------------------------------------------------------- 1 | /* 2 | * MinimalTodo v0.0.0 / ScriptUI 3 | * 4 | * Author: Kareobana(http://atarabi.com/) 5 | * License: MIT 6 | * Dependencies: 7 | * KIKAKU.UIBuilder 1.0.0 8 | */ 9 | 10 | (function (global) { 11 | 12 | new KIKAKU.UIBuilder(global, 'MinimalTodo', {version: '0.0.0', author: 'Kareobana', url: 'http://atarabi.com/', width: 250, help: false, autoSave: true}) 13 | .add('checkbox', 'Unlock', true, { 14 | title: false 15 | }) 16 | .add('listbox', 'Todos', '', { 17 | title: false, 18 | height: 150, 19 | onDoubleClick: function () { 20 | if (this.get('Unlock')) { 21 | var todo = this.get('Todos'); 22 | if (todo !== null) { 23 | this.removeItem('Todos', todo); 24 | } 25 | } 26 | } 27 | }) 28 | .add('text', 'Text', '', {title: false}) 29 | .add('script', 'Add', function () { 30 | var text = this.get('Text'); 31 | if (text !== '') { 32 | this.set('Text', ''); 33 | this.addItems('Todos', text); 34 | this.set('Todos', text); 35 | } 36 | }) 37 | .build(); 38 | 39 | })(this); 40 | -------------------------------------------------------------------------------- /ScriptUI/MinimalTodo/README.md: -------------------------------------------------------------------------------- 1 | # MinimalTodo 2 | 3 | ミニマルなTodo。 4 | 5 | # 使い方 6 | 7 | ![UI](ui.png) 8 | 9 | 1. 下のテキストボックスに内容を入力して、**Add**で追加。 10 | 11 | 1. 左上のチェックボックスをチェック時に項目をダブルクリックで削除。 12 | 13 | ## Dependencies 14 | 15 | - [KIKAKU.UIBuilder 2.0.0](https://github.com/atarabi/AfterEffects-Scripts/tree/master/Startup/KikakuUIBuilder) 16 | 17 | ## Version 18 | 19 | - v0.0.0 -------------------------------------------------------------------------------- /ScriptUI/MinimalTodo/ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atarabi/AfterEffects-Scripts/108cc5f5abdafa751d2dc9081f374af881cc6500/ScriptUI/MinimalTodo/ui.png -------------------------------------------------------------------------------- /ScriptUI/PartialAdjustment/PartialAdjustment.jsx: -------------------------------------------------------------------------------- 1 | /* 2 | * PartialAdjustment v0.0.1 / ScriptUI 3 | * 4 | * Author: Kareobana(http://atarabi.com/) 5 | * License: MIT 6 | * Dependencies: 7 | * KIKAKU.JSON 8 | * KIKAKU.Utils 1.0.0 9 | * KIKAKU.UIBuilder 2.0.0 10 | */ 11 | 12 | (function (global) { 13 | //Lib 14 | var JSON = KIKAKU.JSON, 15 | Utils = KIKAKU.Utils, 16 | UIBuilder = KIKAKU.UIBuilder; 17 | 18 | //Utility 19 | var assign = Utils.assign, 20 | forEach = Utils.forEach, 21 | filter = Utils.filter, 22 | isString = Utils.isString, 23 | isAVLayer = Utils.isAVLayer, 24 | forEachPropertyGroup = Utils.forEachPropertyGroup, 25 | forEachEffect = Utils.forEachEffect, 26 | getActiveComp = Utils.getActiveComp, 27 | getCompByName = Utils.getCompByName, 28 | isCompLayer = Utils.isCompLayer, 29 | getLayers = Utils.getLayers, 30 | getSelectedLayers = Utils.getSelectedLayers, 31 | getSelectedLayer = Utils.getSelectedLayer, 32 | isHiddenProperty = Utils.isHiddenProperty; 33 | 34 | //constants 35 | var Expression = { 36 | Transform: 0, 37 | Effect: 1, 38 | }; 39 | 40 | //functions 41 | function setComment(layer, obj) { 42 | var comment = layer.comment; 43 | try { 44 | comment = JSON.parse(comment); 45 | } catch (e) { 46 | comment = comment ? {comment: comment} : {}; 47 | } 48 | assign(comment, obj); 49 | 50 | layer.comment = JSON.stringify(comment); 51 | } 52 | 53 | function getComment(layer) { 54 | var comment = layer.comment; 55 | try { 56 | comment = JSON.parse(comment); 57 | } catch (e) { 58 | comment = { 59 | comment: comment 60 | }; 61 | } 62 | return comment; 63 | } 64 | 65 | function removeComment(layer, key) { 66 | var comment = layer.comment; 67 | try { 68 | comment = JSON.parse(comment); 69 | } catch (e) { 70 | return; 71 | } 72 | 73 | delete comment[key]; 74 | 75 | var has_key = false, 76 | only_comment = true; 77 | for (var k in comment) { 78 | has_key = true; 79 | if (k !== 'comment') { 80 | only_comment = false; 81 | break; 82 | } 83 | } 84 | 85 | if (!has_key) { 86 | layer.comment = ''; 87 | } else { 88 | layer.comment = only_comment ? comment.comment : JSON.stringify(comment); 89 | } 90 | } 91 | 92 | //Main 93 | var builder = new UIBuilder(global, 'PartialAdjustment', { 94 | version: '0.0.1', 95 | author: 'Kareobana', 96 | url: 'http://atarabi.com/' 97 | }); 98 | 99 | builder 100 | .add('checkboxes', 'Expression', [{ text: 'Transform', value: true }, { text: 'Effect', value: true }], { title: false }) 101 | .add('script', 'Execute', function () { 102 | var comp = getActiveComp(), 103 | layers = getSelectedLayers(); 104 | if (!layers.length) { 105 | return; 106 | } 107 | 108 | layers.sort(function (lhs, rhs) { 109 | return lhs.index < rhs.index; 110 | }); 111 | 112 | for (var i = 0, l = layers.length - 1; i < l; i++) { 113 | if (layers[i].index - layers[i + 1].index !== 1) { 114 | throw new Error('Select successive layers'); 115 | } 116 | } 117 | 118 | var precomp_name = prompt('Give a precomp name', ''); 119 | if (!precomp_name) { 120 | return; 121 | } else if (getCompByName(precomp_name)) { 122 | return alert('"' + precomp_name + '"' + ' already exists'); 123 | } 124 | 125 | var precomp = app.project.items.addComp(precomp_name, comp.width, comp.height, comp.pixelAspect, comp.duration, comp.frameRate), 126 | comp_layer = comp.layers.add(precomp); 127 | comp_layer.moveBefore(layers[layers.length - 1]); 128 | 129 | var obj = {}; 130 | obj[this.getName()] = { 131 | comp: precomp_name, 132 | }; 133 | forEach(layers, function (layer) { 134 | setComment(layer, obj); 135 | }); 136 | 137 | this.trigger('copy', layers, comp, precomp); 138 | }) 139 | .add('script', 'Refresh', function () { 140 | var script_name = this.getName(), 141 | comp = getActiveComp(), 142 | comp_layer = getSelectedLayer(), 143 | target_comp; 144 | if (!comp_layer) { 145 | return; 146 | } else if (isCompLayer(comp_layer)) { 147 | target_comp = comp_layer.source; 148 | } else { 149 | var comment = getComment(comp_layer); 150 | if (comment[script_name] && isString(comment[script_name].comp)) { 151 | target_comp = getCompByName(comment[script_name].comp); 152 | } 153 | if (!target_comp) { 154 | return alert('Select a comp layer'); 155 | } 156 | } 157 | 158 | var precomp_name = target_comp.name, 159 | layers = filter(getLayers('all', comp), function (layer) { 160 | var comment = getComment(layer); 161 | return comment[script_name] && comment[script_name].comp === precomp_name; 162 | }); 163 | 164 | if (!layers.length) { 165 | return; 166 | } 167 | 168 | this.trigger('copy', layers, comp, target_comp); 169 | }) 170 | .on('copy', function (layers, source_comp, target_comp) { 171 | function removeAllKeys(property) { 172 | var num_keys = property.numKeys; 173 | if (!num_keys) { 174 | return; 175 | } 176 | for (var i = num_keys; i >= 1; i--) { 177 | property.removeKey(i); 178 | } 179 | } 180 | 181 | target_comp.displayStartTime = source_comp.displayStartTime; 182 | 183 | //desc 184 | layers.sort(function (lhs, rhs) { 185 | return lhs.index < rhs.index; 186 | }); 187 | 188 | //remove layers 189 | forEach(getLayers('all', target_comp), function (layer) { 190 | layer.remove(); 191 | }); 192 | 193 | //copy 194 | forEach(layers, function (layer) { 195 | layer.locked = false; 196 | layer.enabled = true; 197 | layer.solo = false; 198 | layer.copyToComp(target_comp); 199 | layer.enabled = false; 200 | }); 201 | 202 | //asc 203 | layers.sort(function (lhs, rhs) { 204 | return lhs.index > rhs.index; 205 | }); 206 | 207 | //set expression 208 | var do_transform = this.get('Expression', Expression.Transform), 209 | do_effect = this.get('Expression', Expression.Effect); 210 | 211 | var expression_template = 'comp("' + source_comp.name + '").layer("#{LayerName}").', 212 | script_name = this.getName(); 213 | forEach(layers, function (layer, i) { 214 | var expression = expression_template.replace('#{LayerName}', layer.name); 215 | var target_layer = target_comp.layer(i + 1); 216 | removeComment(target_layer, script_name); 217 | if (do_transform) { 218 | forEachPropertyGroup(target_layer.transform, function (property) { 219 | if (isHiddenProperty(property) || !property.canSetExpression) { 220 | return; 221 | } 222 | removeAllKeys(property); 223 | property.expression = expression + 'transform("' + property.matchName + '");'; 224 | }); 225 | } 226 | if (do_effect && isAVLayer(target_layer)) { 227 | forEachEffect(target_layer, function (effect) { 228 | forEachPropertyGroup(effect, function (property, i) { 229 | if (isHiddenProperty(property) || !property.canSetExpression) { 230 | return; 231 | } 232 | removeAllKeys(property); 233 | property.expression = expression + 'effect("' + effect.name + '")(' + i + ');'; 234 | }); 235 | }); 236 | } 237 | }); 238 | }) 239 | .build(); 240 | 241 | })(this); 242 | -------------------------------------------------------------------------------- /ScriptUI/PartialAdjustment/README.md: -------------------------------------------------------------------------------- 1 | # PartialAdjustment 2 | 3 | 部分的調整レイヤー。 4 | 5 | ## 説明 6 | 7 | 調整レイヤーは、その調整レイヤー以下のレイヤー群をプリコンポしそのプリコンポしたものにエフェクトを掛けることと基本的には変わらない。 8 | したがってレイヤー以下の全てを対象にするのではなく、ある一部分だけに調整レイヤーを掛けたい場合、その箇所だけをプリコンポすれば基本的には同じ効果が得られる。 9 | しかし、当然その対象となったレイヤー群を弄りたい場合は、わざわざプリコンポ内にもぐる必要性があり手間となる。この手間の有無が、プリコンポではなく調整レイヤーを用いたい理由の一つであろう。 10 | そこで、通常の調整レイヤーと同じように、わざわざプリコンポ内に移動することなく透過的に扱えるような仕組みを考える必要がある。 11 | 12 | ## 使い方 13 | 14 | ![UI](ui.png) 15 | 16 | 1. 対象となる連続したレイヤー群を選択し**Execute**ボタンをクリックすると、プリコンポの名前を求められるので入力する。すると、その名前のコンポジションが作られその中に対象レイヤーがコピーされる。この際に**Transform**がチェックされているとトランスフォームのプロパティが、**Effect**がチェックされているとエフェクトのプロパティが、元のレイヤーとピックウィップで繋がれる(よって、レイヤーの名前はユニークである必要がある)。この際、レイヤーのコメントにどのコンポにコピーされたかの情報が書き加えられる。 17 | 18 | 1. レイヤーに新たにエフェクトを追加する等々の既存のピックウィップだけでは整合性のとれない変化があった場合は、**Refresh**ボタンをクリックすると対象レイヤー群を再びコピーすることによって整合性を保つことが出来る。 19 | 20 | ## Dependencies 21 | 22 | - [KIKAKU.JSON](https://github.com/atarabi/AfterEffects-Scripts/tree/master/Startup/KikakuJSON) 23 | - [KIKAKU.Utils 1.0.0](https://github.com/atarabi/AfterEffects-Scripts/tree/master/Startup/KikakuUtils) 24 | - [KIKAKU.UIBuilder 2.0.0](https://github.com/atarabi/AfterEffects-Scripts/tree/master/Startup/KikakuUIBuilder) 25 | 26 | ## Version 27 | 28 | - v0.0.1(2015/06/18) comment関連のバグフィクス。 29 | - v0.0.0 -------------------------------------------------------------------------------- /ScriptUI/PartialAdjustment/ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atarabi/AfterEffects-Scripts/108cc5f5abdafa751d2dc9081f374af881cc6500/ScriptUI/PartialAdjustment/ui.png -------------------------------------------------------------------------------- /ScriptUI/README.md: -------------------------------------------------------------------------------- 1 | # ScriptUI Scripts 2 | 3 | ScriptUI向けスクリプト。 4 | 5 | ## CustomGlow 6 | 7 | 自作グロー。 8 | 9 | ## DimensionConverter 10 | 11 | パラメータの次元を変える。 12 | 13 | ## FrameSplitter 14 | 15 | nフレームごとに分割。 16 | 17 | ## LayerTrimmer 18 | 19 | シェイプレイヤー、テキストレイヤーをトリミングする。 20 | 21 | ## MakeItStill 22 | 23 | 動画をそのフレームで静止させる。 24 | 25 | ## MinimalMemo 26 | 27 | ミニマルなメモ。 28 | 29 | ## MinimalTodo 30 | 31 | ミニマルなTODO。 32 | 33 | ## PartialAdjustment 34 | 35 | 部分的調整レイヤー。 36 | 37 | ## SimpleMemo 38 | 39 | シンプルなメモ。 40 | 41 | ## TimeRemap 42 | 43 | タイムリマップで遊ぶ。 -------------------------------------------------------------------------------- /ScriptUI/SimpleMemo/README.md: -------------------------------------------------------------------------------- 1 | # SimpleMemo 2 | 3 | シンプルなメモ。 4 | 5 | ![UI](ui.png) 6 | 7 | ## Dependencies 8 | 9 | - [KIKAKU.UIBuilder 2.0.0](https://github.com/atarabi/AfterEffects-Scripts/tree/master/Startup/KikakuUIBuilder) 10 | 11 | ## Version 12 | 13 | - v0.1.0 -------------------------------------------------------------------------------- /ScriptUI/SimpleMemo/SimpleMemo.jsx: -------------------------------------------------------------------------------- 1 | /* 2 | * SimpleMemo v0.1.0 / ScriptUI 3 | * 4 | * Author: Kareobana(http://atarabi.com/) 5 | * License: MIT 6 | * Dependencies: 7 | * KIKAKU.UIBuilder 2.0.0 8 | */ 9 | 10 | (function (global) { 11 | 12 | var titles = []; 13 | 14 | new KIKAKU.UIBuilder(global, 'SimpleMemo', {version: '0.1.0', author: 'Kareobana', url: 'http://atarabi.com/', width: 250, resizeable: true}) 15 | .add('textarea', 'Memo', '', { 16 | title: false, 17 | height: 150, 18 | callback: function () { 19 | var title = this.get('Title'); 20 | if (title !== null) { 21 | var memo = this.get('Memo'); 22 | try { 23 | this.saveFile(title, memo); 24 | } catch (e) { 25 | alert(e); 26 | } 27 | } 28 | } 29 | }) 30 | .add('popup', 'Title', undefined, function () { 31 | var title = this.get('Title'); 32 | if (title !== null) { 33 | try { 34 | var memo = this.getFile(title); 35 | this.set('Memo', memo); 36 | } catch (e) { 37 | alert(e); 38 | } 39 | } 40 | }) 41 | .add('script', 'Add', function () { 42 | var title = prompt('Input a title', ''); 43 | if (title === null || title === '') { 44 | return; 45 | } 46 | 47 | for (var i = 0, l = titles.length; i < l; i++) { 48 | if (title === titles[i]) { 49 | alert(title + ' has exists'); 50 | return; 51 | } 52 | } 53 | 54 | try { 55 | if (titles.length === 0) { 56 | this.saveFile(title, this.get('Memo')); 57 | } else { 58 | this.saveFile(title, ''); 59 | } 60 | titles.push(title); 61 | this.replaceItems('Title', titles); 62 | this.set('Title', title); 63 | this.trigger('refresh'); 64 | } catch (e) { 65 | alert(e); 66 | } 67 | }) 68 | .add('script', 'Remove', function () { 69 | var title = this.get('Title'); 70 | if (title === null) { 71 | return; 72 | } 73 | 74 | var do_remove = confirm('Remove ' + title + '?'); 75 | if (do_remove) { 76 | try { 77 | this.deleteFile(title); 78 | 79 | for (var i = 0, l = titles.length; i < l; i++) { 80 | if (title === titles[i]) { 81 | titles.splice(i, 1); 82 | break; 83 | } 84 | } 85 | this.replaceItems('Title', titles); 86 | this.trigger('refresh'); 87 | } catch (e) { 88 | alert(e); 89 | } 90 | } 91 | }) 92 | .on('refresh', function () { 93 | var title = this.get('Title'); 94 | if (title !== null) { 95 | try { 96 | var text = this.getFile(title); 97 | this.set('Memo', text); 98 | } catch (e) { 99 | alert(e); 100 | } 101 | } 102 | }) 103 | .on('init', function () { 104 | try { 105 | titles = this.getFileNames(); 106 | this.replaceItems('Title', titles); 107 | this.trigger('refresh'); 108 | } catch (e) { 109 | alert(e); 110 | } 111 | }) 112 | .build(); 113 | 114 | })(this); 115 | -------------------------------------------------------------------------------- /ScriptUI/SimpleMemo/ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atarabi/AfterEffects-Scripts/108cc5f5abdafa751d2dc9081f374af881cc6500/ScriptUI/SimpleMemo/ui.png -------------------------------------------------------------------------------- /ScriptUI/TimeRemap/README.md: -------------------------------------------------------------------------------- 1 | # TimeRemap 2 | 3 | タイムリマップとエクスプレッション制御エフェクトで遊ぶ。 4 | 5 | ## 使い方 6 | 7 | ![UI](ui.png) 8 | 9 | - Mode 10 | 11 | - OneShot 12 | 13 | 角度制御エフェクトを用いてタイムリマップを弄る。0-360°の範囲のみ有効でそれ以外はクランプされる。 14 | 15 | - Loop 16 | 17 | 角度制御エフェクトを用いてタイムリマップを弄る。360°ごとにループ。 18 | 19 | - Pingpong 20 | 21 | 角度制御エフェクトを用いてタイムリマップを弄る。360°ごとにピンポン再生。 22 | 23 | - Stop 24 | 25 | チェックボックス制御エフェクトでタイムリマップを制御。チェックされたキーフレームで停止。 26 | 27 | - Shuffle 28 | 29 | チェックボックス制御エフェクトとスライダー制御エフェクトでタイムリマップを制御。チェックボックスで有効かを設定、スライダー制御エフェクトで何フレームを一塊にするかを決める。 30 | 31 | - Inverse 32 | 33 | 一塊ごとに逆再生。 34 | 35 | - Random 36 | 37 | 一塊ごとにランダム再生。 38 | 39 | - Execute 40 | 41 | 実行。 42 | 43 | 44 | 45 | ## Dependencies 46 | 47 | - [KIKAKU.Utils 1.0.0](https://github.com/atarabi/AfterEffects-Scripts/tree/master/Startup/KikakuUtils) 48 | - [KIKAKU.UIBuilder 2.0.0](https://github.com/atarabi/AfterEffects-Scripts/tree/master/Startup/KikakuUIBuilder) 49 | 50 | ## Version 51 | 52 | - v0.1.0 -------------------------------------------------------------------------------- /ScriptUI/TimeRemap/TimeRemap.jsx: -------------------------------------------------------------------------------- 1 | /* 2 | * TimeRemap v0.1.0 / ScriptUI 3 | * 4 | * Author: Kareobana(http://atarabi.com/) 5 | * License: MIT 6 | * Dependencies: 7 | * KIKAKU.Utils 1.0.0 8 | * KIKAKU.UIBuilder 2.0.0 9 | */ 10 | 11 | (function (global) { 12 | var Utils = KIKAKU.Utils, 13 | builder = new KIKAKU.UIBuilder(global, 'TimeRemap', {version: '0.1.0', author: 'Kareobana', url: 'http://atarabi.com/'}); 14 | 15 | builder 16 | .add('popup', 'Mode', ['OneShot', 'Loop', 'Pingpong', 'Stop', 'Shuffle'], function () { 17 | var mode = this.get('Mode'); 18 | if (mode === 'Shuffle') { 19 | this.enable('Shuffle Type'); 20 | } else { 21 | this.disable('Shuffle Type'); 22 | } 23 | }) 24 | .add('popup', 'Shuffle Type', ['Inverse', 'Random']) 25 | .add('script', 'Execute', function () { 26 | function isAVLayer(layer) { 27 | return layer instanceof AVLayer || layer instanceof TextLayer|| layer instanceof ShapeLayer; 28 | } 29 | 30 | var layer = Utils.getSelectedLayer(); 31 | if (layer === null || !isAVLayer(layer) || !layer.canSetTimeRemapEnabled) { 32 | return; 33 | } 34 | 35 | var mode = this.get('Mode'); 36 | if (mode === 'OneShot' || mode === 'Loop' || mode === 'Pingpong') { 37 | var timeramp = layer.Effects.addProperty('ADBE Angle Control'), 38 | expression = ''; 39 | 40 | layer.timeRemapEnabled = true; 41 | timeramp.enabled = false; 42 | timeramp.name = 'Time Remap'; 43 | 44 | switch (mode) { 45 | case 'OneShot': 46 | expression = 'duration = thisLayer.source.duration - thisComp.frameDuration;\nphase = effect("' + timeramp.name + '")(1) / 360;\nphase = phase < 0 ? 0 : phase > 1 ? 1: phase;\nduration * phase;'; 47 | break; 48 | case 'Loop': 49 | expression = 'duration = thisLayer.source.duration - thisComp.frameDuration;\nphase = (effect("' + timeramp.name + '")(1) / 360) % 1;\nif (phase < 0) {\n phase += 1;\n}\nduration * phase;'; 50 | break; 51 | case 'Pingpong': 52 | expression = 'duration = thisLayer.source.duration - thisComp.frameDuration;\nphase = (effect("' + timeramp.name + '")(1) / 360) % 2;\nif (phase < 0) {\n phase += 2;\n}\nif (phase < 1) {\n duration * phase;\n} else {\n duration * (2 - phase);\n}'; 53 | break; 54 | } 55 | 56 | layer.timeRemap.expression = expression; 57 | } else if (mode === 'Stop') { 58 | var stop = layer.Effects.addProperty('ADBE Checkbox Control'), 59 | expression = """function findPrevKey(property) { 60 | if (property.numKeys === 0) { 61 | return null; 62 | } 63 | var prev_key = property.nearestKey(time); 64 | if (prev_key.time > time) { 65 | if (prev_key.index === 1) { 66 | return null; 67 | } 68 | prev_key = property.key(prev_key.index - 1); 69 | } 70 | return prev_key; 71 | } 72 | var stop = effect("Stop")(1), 73 | prev_key = findPrevKey(stop); 74 | if (stop.value && prev_key !== null) { 75 | thisProperty.valueAtTime(prev_key.time); 76 | } else { 77 | value; 78 | }"""; 79 | 80 | stop.enabled = false; 81 | stop.name = 'Stop'; 82 | 83 | layer.timeRemapEnabled = true; 84 | layer.timeRemap.expression = expression; 85 | } else if (mode === 'Shuffle') { 86 | var shuffle_type = this.get('Shuffle Type'); 87 | 88 | var shuffle = layer.Effects.addProperty('ADBE Checkbox Control'); 89 | shuffle.enabled = false; 90 | shuffle.name = 'Shuffle'; 91 | shuffle(1).setValue(1); 92 | 93 | var frames = layer.Effects.addProperty('ADBE Slider Control'); 94 | frames.enabled = false; 95 | frames.name = 'Frames'; 96 | frames(1).setValue(5); 97 | 98 | if (shuffle_type === 'Random') { 99 | var shuffle_seed = layer.Effects.addProperty('ADBE Slider Control'); 100 | shuffle_seed.enabled = false; 101 | shuffle_seed.name = 'Shuffle Seed'; 102 | } 103 | 104 | var expression = ''; 105 | 106 | if (shuffle_type === 'Inverse') { 107 | expression = """var do_shuffle = effect("Shuffle")(1).value, 108 | frames = ~~effect("Frames")(1).value; 109 | if (do_shuffle && frames > 2) { 110 | var mapping = (function (n) { 111 | var arr = []; 112 | for (var i = 0; i < n; i++) { 113 | arr.push(n - 1 - i); 114 | } 115 | return arr; 116 | })(frames); 117 | 118 | var frame_duration = thisComp.frameDuration, 119 | fps = 1 / frame_duration, 120 | current_frame = ~~(thisProperty.value * fps), 121 | bar = ~~(current_frame / frames), 122 | beat = current_frame % frames; 123 | if (beat < 0) { 124 | beat += frames; 125 | } 126 | (bar * frames + mapping[beat]) * frame_duration; 127 | } else { 128 | value; 129 | }"""; 130 | } else if (shuffle_type === 'Random') { 131 | expression = """function shuffle(arr) { 132 | for (var i = 0, l = arr.length; i < l; i++) { 133 | var j = ~~random(l); 134 | arr[j] = [arr[i], arr[i] = arr[j]][0]; 135 | } 136 | } 137 | var do_shuffle = effect("Shuffle")(1).value, 138 | frames = ~~effect("Frames")(1).value, 139 | shuffle_seed = effect("Shuffle Seed")(1).value; 140 | if (do_shuffle && frames > 2) { 141 | seedRandom(shuffle_seed, true); 142 | var mapping = (function (n) { 143 | var arr = []; 144 | for (var i = 0; i < n; i++) { 145 | arr.push(i); 146 | } 147 | shuffle(arr); 148 | return arr; 149 | })(frames); 150 | 151 | var frame_duration = thisComp.frameDuration, 152 | fps = 1 / frame_duration, 153 | current_frame = ~~(thisProperty.value * fps), 154 | bar = ~~(current_frame / frames), 155 | beat = current_frame % frames; 156 | if (beat < 0) { 157 | beat += frames; 158 | } 159 | (bar * frames + mapping[beat]) * frame_duration; 160 | } else { 161 | value; 162 | }"""; 163 | } 164 | 165 | layer.timeRemapEnabled = true; 166 | layer.timeRemap.expression = expression; 167 | } 168 | 169 | }) 170 | .on('init', function () { 171 | var mode = this.get('Mode'); 172 | if (mode === 'Shuffle') { 173 | this.enable('Shuffle Type'); 174 | } else { 175 | this.disable('Shuffle Type'); 176 | } 177 | }) 178 | .build(); 179 | 180 | })(this); 181 | -------------------------------------------------------------------------------- /ScriptUI/TimeRemap/ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atarabi/AfterEffects-Scripts/108cc5f5abdafa751d2dc9081f374af881cc6500/ScriptUI/TimeRemap/ui.png -------------------------------------------------------------------------------- /Startup/KikakuEventDispatcher/KikakuEventDispatcher.jsx: -------------------------------------------------------------------------------- 1 | /* 2 | * KikakuEventDispatcher v0.0.0 3 | * 4 | * Author: Kareobana (http://atarabi.com/) 5 | * License: MIT 6 | */ 7 | 8 | var KIKAKU = KIKAKU || function(fn) { 9 | app.beginUndoGroup('KIKAKU'); 10 | try { 11 | fn(); 12 | } catch (e) { 13 | alert(e); 14 | } 15 | app.endUndoGroup(); 16 | }; 17 | 18 | (function(root) { 19 | /* 20 | * Declaration 21 | */ 22 | function EventDispatcher() {} 23 | 24 | EventDispatcher.VERSION = '0.0.0'; 25 | 26 | EventDispatcher.AUTHOR = 'Kareobana'; 27 | 28 | EventDispatcher.prototype.addEventListener = addEventListener; 29 | 30 | EventDispatcher.prototype.removeEventListener = removeEventListener; 31 | 32 | EventDispatcher.prototype.dispatchEvent = dispatchEvent; 33 | 34 | /* 35 | * Implementation 36 | */ 37 | function addEventListener(type, fn, ctx) { 38 | this._listeners = this._listeners || {}; 39 | 40 | fn = typeof fn === 'function' ? fn : ctx[fn]; 41 | 42 | if (typeof this._listeners[type] === 'undefined') { 43 | this._listeners[type] = []; 44 | } 45 | 46 | this._listeners[type].push({ 47 | fn: fn, 48 | ctx: ctx || this 49 | }); 50 | } 51 | 52 | function removeEventListener(type, fn, ctx) { 53 | this._listeners = this._listeners || {}; 54 | 55 | ctx = ctx || this; 56 | 57 | var listeners = this._listeners[type], 58 | mx = listeners ? listeners.length : 0; 59 | 60 | for (var i = 0; i < mx; i++) { 61 | if (listeners[i].fn === fn && listeners[i].ctx === ctx) { 62 | listeners.splice(i, 1); 63 | break; 64 | } 65 | } 66 | } 67 | 68 | function dispatchEvent(type) { 69 | this._listeners = this._listeners || {}; 70 | 71 | var listeners = this._listeners[type], 72 | mx = listeners ? listeners.length : 0, 73 | args = Array.prototype.slice.call(arguments, 1); 74 | 75 | for (var i = 0; i < mx; i++) { 76 | listeners[i].fn.apply(listeners[i].ctx, args); 77 | } 78 | } 79 | 80 | /* 81 | * Exports 82 | */ 83 | root.EventDispatcher = EventDispatcher; 84 | 85 | })(KIKAKU); 86 | -------------------------------------------------------------------------------- /Startup/KikakuEventDispatcher/README.md: -------------------------------------------------------------------------------- 1 | # KikakuEventDispatcher 2 | 3 | 単純なイベントディスパッチャークラス。 4 | 5 | ## Usage 6 | 7 | ``` 8 | var event_dispatcher = new KIKAKU.EventDispatcher(); 9 | event_dispatcher.addEventListener('custom event', function () { 10 | alert('Custom Event is fired.'); 11 | }); 12 | event_dispatcher.dispatchEvent('custom event'); 13 | ``` 14 | 15 | ## Version 16 | 17 | - v0.0.0 -------------------------------------------------------------------------------- /Startup/KikakuFileManager/KikakuFileManager.jsx: -------------------------------------------------------------------------------- 1 | /* 2 | * KikakuFileManager v0.0.0 3 | * 4 | * Author: Kareobana (http://atarabi.com/) 5 | * License: MIT 6 | */ 7 | 8 | var KIKAKU = KIKAKU || function(fn) { 9 | app.beginUndoGroup('KIKAKU'); 10 | try { 11 | fn(); 12 | } catch (e) { 13 | alert(e); 14 | } 15 | app.endUndoGroup(); 16 | }; 17 | 18 | (function(root) { 19 | /* 20 | * Declaration 21 | */ 22 | function FileManager(path, type) { 23 | this._initialize.apply(this, arguments); 24 | } 25 | 26 | FileManager.VERSION = '0.0.0'; 27 | 28 | FileManager.AUTHOR = 'Kareobana'; 29 | 30 | FileManager.validateFileName = validateFileName; 31 | 32 | FileManager.prototype.getFiles = getFiles; 33 | 34 | FileManager.prototype.getFile = getFile; 35 | 36 | FileManager.prototype.getFileNames = getFileNames; 37 | 38 | FileManager.prototype.exists = exists; 39 | 40 | FileManager.prototype.get = get_; 41 | 42 | FileManager.prototype.save = save; 43 | 44 | FileManager.prototype.delete = delete_; 45 | 46 | /* 47 | * Implementation 48 | */ 49 | //utility 50 | function isObject(arg) { 51 | return Object.prototype.toString.call(arg) === '[object Object]'; 52 | } 53 | 54 | function isArray(arg) { 55 | return Object.prototype.toString.call(arg) === '[object Array]'; 56 | } 57 | 58 | function isString(arg) { 59 | return Object.prototype.toString.call(arg) === '[object String]'; 60 | } 61 | 62 | function forEach(obj, fn) { 63 | if (isArray(obj)) { 64 | for (var i = 0, l = obj.length; i < l; i++) { 65 | fn(obj[i], i); 66 | } 67 | } else if (isObject(obj)) { 68 | for (var key in obj) { 69 | fn(obj[key], key); 70 | } 71 | } 72 | } 73 | 74 | function filter(arr, fn) { 75 | var result = []; 76 | forEach(arr, function(v, i) { 77 | if (fn(v, i)) { 78 | result.push(v); 79 | } 80 | }); 81 | return result; 82 | } 83 | 84 | function assign() { 85 | var args = Array.prototype.slice.call(arguments); 86 | if (args.length === 0) { 87 | return {}; 88 | } 89 | var obj1 = isObject(args[0]) ? args[0] : {}; 90 | for (var i = 1, l = args.length; i < l; i++) { 91 | var obj2 = args[i]; 92 | if (isObject(obj2)) { 93 | for (var key in obj2) { 94 | if (obj2.hasOwnProperty(key)) { 95 | obj1[key] = obj2[key]; 96 | } 97 | } 98 | } 99 | } 100 | return obj1; 101 | } 102 | 103 | function createFolder(path) { 104 | var folder = new Folder(path), 105 | folders = []; 106 | 107 | while (!folder.exists) { 108 | folders.push(folder); 109 | folder = folder.parent; 110 | } 111 | 112 | while (folder = folders.pop()) { 113 | if (!folder.create()) { 114 | throw new Error('Failed to create folder'); 115 | } 116 | } 117 | } 118 | 119 | //class 120 | function validateFileName(file_name) { 121 | if (!isString(file_name) || file_name === '') { 122 | return false; 123 | } 124 | return file_name.match(/[:;\/|,*?"'<>]/) === null; 125 | } 126 | 127 | //instance 128 | function getDirectoryPath(type) { 129 | switch (type) { 130 | case 'custom': 131 | return ''; 132 | case 'appData': 133 | return Folder.appData.absoluteURI + '/'; 134 | case 'commonFiles': 135 | return Folder.commonFiles.absoluteURI + '/'; 136 | case 'desktop': 137 | return Folder.desktop.absoluteURI + '/'; 138 | case 'myDocuments': 139 | return Folder.myDocuments.absoluteURI + '/'; 140 | case 'userData': 141 | return Folder.userData.absoluteURI + '/'; 142 | default: 143 | throw new Error('invalid type'); 144 | } 145 | } 146 | 147 | FileManager.prototype._initialize = function(path, type) { 148 | function check(path) { 149 | var paths = path.split('/'); 150 | forEach(paths, function(folder_name) { 151 | if (folder_name === '') { 152 | throw new Error('invalid path'); 153 | } 154 | }); 155 | } 156 | type = type || 'userData'; 157 | if (!isString(path)) { 158 | throw new Error('"path" must be string'); 159 | } 160 | check(path); 161 | 162 | this._cd = getDirectoryPath(type) + path; 163 | }; 164 | 165 | function getFiles(options) { 166 | options = assign({ 167 | path: null, 168 | mask: '*' 169 | }, options); 170 | 171 | var folder_path = options.path === null ? this._cd : this._cd + '/' + options.path, 172 | folder = new Folder(folder_path), 173 | files = folder.exists ? filter(folder.getFiles(options.mask), function(file) { 174 | return file instanceof File; 175 | }) : []; 176 | 177 | return files; 178 | } 179 | 180 | function getFile(path) { 181 | var file = new File(this._cd + '/' + path); 182 | return file; 183 | } 184 | 185 | function getFileNames(options) { 186 | var files = this.getFiles(options), 187 | file_names = []; 188 | 189 | forEach(files, function(file) { 190 | if (file instanceof File) { 191 | file_names.push(file.displayName); 192 | } 193 | }); 194 | 195 | return file_names; 196 | } 197 | 198 | function exists(path) { 199 | return this.getFile(path).exists; 200 | } 201 | 202 | function get_(path) { 203 | var file = new File(this._cd + '/' + path); 204 | file.encoding = 'UTF-8'; 205 | 206 | if (!file.exists) { 207 | return null; 208 | } 209 | 210 | if (!file.open('r')) { 211 | throw new Error('Can\'t read file'); 212 | } 213 | 214 | var text = file.read(); 215 | file.close(); 216 | 217 | return text; 218 | } 219 | 220 | function save(path, text) { 221 | var paths = path.split('/'), 222 | file_name = paths.pop(); 223 | if (!FileManager.validateFileName(file_name)) { 224 | throw new Error('Invalid file name: ' + file_name); 225 | } 226 | createFolder(this._cd + '/' + paths.join('/')); 227 | 228 | var file = new File(this._cd + '/' + path); 229 | if (!file.open('w')) { 230 | throw new Error('Can\'t write file'); 231 | } 232 | file.write(text); 233 | file.close(); 234 | } 235 | 236 | function delete_(path) { 237 | var file = new File(this._cd + '/' + path); 238 | if (file.exists) { 239 | return file.remove(); 240 | } 241 | return true; 242 | } 243 | 244 | /* 245 | * Exports 246 | */ 247 | root.FileManager = FileManager; 248 | 249 | })(KIKAKU); 250 | -------------------------------------------------------------------------------- /Startup/KikakuFileManager/README.md: -------------------------------------------------------------------------------- 1 | # KikakuFileManager 2 | 3 | ファイル操作用クラス。 4 | 5 | ## Usage 6 | 7 | ``` 8 | var file_manager = new KIKAKU.FileManager('AE', 'desktop'); 9 | file_manager.save('temp.txt', 'This is a text file.'); 10 | file_manager.delete('temp.txt'); 11 | ``` 12 | 13 | ## Version 14 | 15 | - v0.0.0 -------------------------------------------------------------------------------- /Startup/KikakuJSON/KikakuJSON.jsx: -------------------------------------------------------------------------------- 1 | var KIKAKU = KIKAKU || function(fn) { 2 | app.beginUndoGroup('KIKAKU'); 3 | try { 4 | fn(); 5 | } catch (e) { 6 | alert(e); 7 | } 8 | app.endUndoGroup(); 9 | }; 10 | 11 | (function(root) { 12 | // json2.js 13 | // https://github.com/douglascrockford/JSON-js 14 | var JSON = {}; 15 | (function(){"use strict";function f(e){return e<10?"0"+e:e}function quote(e){escapable.lastIndex=0;return escapable.test(e)?'"'+e.replace(escapable,function(e){var t=meta[e];return typeof t==="string"?t:"\\u"+("0000"+e.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+e+'"'}function str(e,t){var n,r,i,s,o=gap,u,a=t[e];if(a&&typeof a==="object"&&typeof a.toJSON==="function"){a=a.toJSON(e)}if(typeof rep==="function"){a=rep.call(t,e,a)}switch(typeof a){case"string":return quote(a);case"number":return isFinite(a)?String(a):"null";case"boolean":case"null":return String(a);case"object":if(!a){return"null"}gap+=indent;u=[];if(Object.prototype.toString.apply(a)==="[object Array]"){s=a.length;for(n=0;n= 0) { 203 | return arr[index]; 204 | } 205 | return null; 206 | } 207 | 208 | function getKeyFromValue(obj, value) { 209 | for (var key in obj) { 210 | if (obj[key] === value) { 211 | return key; 212 | } 213 | } 214 | return null; 215 | } 216 | 217 | function extend() { 218 | var args = Array.prototype.slice.call(arguments); 219 | if (args.length === 0) { 220 | return {}; 221 | } 222 | var obj1 = isObject(args[0]) ? args[0] : {}; 223 | for (var i = 1, l = args.length; i < l; i++) { 224 | var obj2 = args[i]; 225 | if (isObject(obj2)) { 226 | for (var key in obj2) { 227 | if (obj2.hasOwnProperty(key)) { 228 | obj1[key] = obj2[key]; 229 | } 230 | } 231 | } 232 | } 233 | return obj1; 234 | } 235 | 236 | function operator(lhs, op, rhs) { 237 | switch (op) { 238 | case '==': 239 | return lhs == rhs; 240 | case '!=': 241 | return lhs != rhs; 242 | case '<': 243 | return lhs < rhs; 244 | case '<=': 245 | return lhs <= rhs; 246 | case '>': 247 | return lhs > rhs; 248 | case '>=': 249 | return lhs >= rhs; 250 | default: 251 | throw new Error('Invalid operator: ' + op); 252 | } 253 | } 254 | 255 | function createOperatorFilter(fn, op, rhs) { 256 | return function(obj) { 257 | return operator(fn(obj), op, rhs); 258 | }; 259 | } 260 | 261 | function toLowerCase(str) { 262 | return str.replace(/\s/g, '').toLowerCase(); 263 | } 264 | 265 | //utility 266 | function forEach(obj, fn) { 267 | if (isArray(obj) || isString(obj)) { 268 | for (var i = 0, l = obj.length; i < l; i++) { 269 | fn(obj[i], i); 270 | } 271 | } else if (isObject(obj)) { 272 | for (var key in obj) { 273 | fn(obj[key], key); 274 | } 275 | } 276 | } 277 | 278 | function forEachItem(folder, fn) { 279 | if (isFolderItem(folder)) { 280 | for (var i = 1, l = folder.numItems; i <= l; i++) { 281 | var item = folder.item(i); 282 | fn(item, i); 283 | } 284 | } else if (isFunction(folder)) { 285 | fn = folder; 286 | forEach(app.project.items, function(item, i) { 287 | fn(item, i); 288 | }); 289 | } 290 | } 291 | 292 | function forEachLayer(comp, fn) { 293 | for (var i = 1, l = comp.numLayers; i <= l; i++) { 294 | var layer = comp.layer(i); 295 | fn(layer, i); 296 | } 297 | } 298 | 299 | function forEachPropertyGroup(property_group, fn) { 300 | for (var i = 1, l = property_group.numProperties; i <= l; i++) { 301 | var property = property_group.property(i); 302 | fn(property, i); 303 | } 304 | } 305 | 306 | function forEachEffect(layer, fn) { 307 | if (isAVLayer(layer)) { 308 | forEachPropertyGroup(layer.Effects, function(effect, i) { 309 | fn(effect, i); 310 | }); 311 | } 312 | } 313 | 314 | function inherits(C, P) { 315 | var F = function () {}; 316 | F.prototype = P.prototype; 317 | C.prototype = new F(); 318 | C.super_ = P; 319 | C.uber = P.prototype; 320 | C.prototype.constructor = C; 321 | } 322 | 323 | function assign(obj) { 324 | obj = Object(obj); 325 | 326 | for (var i = 1, l = arguments.length; i = 0; 490 | }; 491 | })(args[0]); 492 | break; 493 | case 'selected': 494 | fn = function(item) { 495 | return item.selected; 496 | }; 497 | break; 498 | //av item 499 | case 'width': 500 | requireArgs(2); 501 | fn = (function(op, rhs) { 502 | return createOperatorFilter(function(item) { 503 | return item.width; 504 | }, op, rhs); 505 | })(args[0], args[1]); 506 | fn = and(isAVItem, fn); 507 | break; 508 | case 'height': 509 | requireArgs(2); 510 | fn = (function(op, rhs) { 511 | return createOperatorFilter(function(item) { 512 | return item.height; 513 | }, op, rhs); 514 | })(args[0], args[1]); 515 | fn = and(isAVItem, fn); 516 | break; 517 | case 'pixelaspect': 518 | requireArgs(2); 519 | fn = (function(op, rhs) { 520 | return createOperatorFilter(function(item) { 521 | return item.pixelAspect; 522 | }, op, rhs); 523 | })(args[0], args[1]); 524 | fn = and(isAVItem, fn); 525 | break; 526 | case 'framerate': 527 | requireArgs(2); 528 | fn = (function(op, rhs) { 529 | return createOperatorFilter(function(item) { 530 | return item.framerate; 531 | }, op, rhs); 532 | })(args[0], args[1]); 533 | fn = and(isAVItem, fn); 534 | break; 535 | case 'frameduration': 536 | requireArgs(2); 537 | fn = (function(op, rhs) { 538 | return createOperatorFilter(function(item) { 539 | return item.frameDuration; 540 | }, op, rhs); 541 | })(args[0], args[1]); 542 | fn = and(isAVItem, fn); 543 | break; 544 | case 'duration': 545 | requireArgs(2); 546 | fn = (function(op, rhs) { 547 | return createOperatorFilter(function(item) { 548 | return item.duration; 549 | }, op, rhs); 550 | })(args[0], args[1]); 551 | fn = and(isAVItem, fn); 552 | break; 553 | case 'useproxy': 554 | fn = function(item) { 555 | return item.useProxy; 556 | }; 557 | fn = and(isAVItem, fn); 558 | break; 559 | case 'time': 560 | requireArgs(2); 561 | fn = (function(op, rhs) { 562 | return createOperatorFilter(function(item) { 563 | return item.time; 564 | }, op, rhs); 565 | })(args[0], args[1]); 566 | fn = and(isAVItem, fn); 567 | break; 568 | case 'hasvideo': 569 | fn = function(item) { 570 | return item.hasVideo; 571 | }; 572 | fn = and(isAVItem, fn); 573 | break; 574 | case 'hasaudio': 575 | fn = function(item) { 576 | return item.hasAudio; 577 | }; 578 | fn = and(isAVItem, fn); 579 | break; 580 | case 'footagemissing': 581 | fn = function(item) { 582 | return item.footageMissing; 583 | }; 584 | fn = and(isAVItem, fn); 585 | break; 586 | //comp item 587 | case 'dropframe': 588 | fn = function(item) { 589 | return item.dropFrame; 590 | }; 591 | fn = and(isCompItem, fn); 592 | break; 593 | case 'workareastart': 594 | requireArgs(2); 595 | fn = (function(op, rhs) { 596 | return createOperatorFilter(function(item) { 597 | return item.workAreaStart; 598 | }, op, rhs); 599 | })(args[0], args[1]); 600 | fn = and(isCompItem, fn); 601 | break; 602 | case 'workareaduration': 603 | requireArgs(2); 604 | fn = (function(op, rhs) { 605 | return createOperatorFilter(function(item) { 606 | return item.workAreaDuration; 607 | }, op, rhs); 608 | })(args[0], args[1]); 609 | fn = and(isCompItem, fn); 610 | break; 611 | case 'numlayers': 612 | requireArgs(2); 613 | fn = (function(op, rhs) { 614 | return createOperatorFilter(function(item) { 615 | return item.numLayers; 616 | }, op, rhs); 617 | })(args[0], args[1]); 618 | fn = and(isCompItem, fn); 619 | break; 620 | case 'hideshylayers': 621 | fn = function(item) { 622 | return item.hideShyLayers; 623 | }; 624 | fn = and(isCompItem, fn); 625 | break; 626 | case 'motionblur': 627 | fn = function(item) { 628 | return item.motionBlur; 629 | }; 630 | fn = and(isCompItem, fn); 631 | break; 632 | case 'draft3d': 633 | fn = function(item) { 634 | return item.draft3d; 635 | }; 636 | fn = and(isCompItem, fn); 637 | break; 638 | case 'frameblending': 639 | fn = function(item) { 640 | return item.frameBlending; 641 | }; 642 | fn = and(isCompItem, fn); 643 | break; 644 | case 'preservenestedframerate': 645 | fn = function(item) { 646 | return item.preserveNestedFrameRate; 647 | }; 648 | fn = and(isCompItem, fn); 649 | break; 650 | case 'displaystarttime': 651 | requireArgs(2); 652 | fn = (function(op, rhs) { 653 | return createOperatorFilter(function(item) { 654 | return item.displayStartTime; 655 | }, op, rhs); 656 | })(args[0], args[1]); 657 | fn = and(isCompItem, fn); 658 | break; 659 | case 'shutterangle': 660 | requireArgs(2); 661 | fn = (function(op, rhs) { 662 | return createOperatorFilter(function(item) { 663 | return item.shutterAngle; 664 | }, op, rhs); 665 | })(args[0], args[1]); 666 | fn = and(isCompItem, fn); 667 | break; 668 | case 'shutterphase': 669 | requireArgs(2); 670 | fn = (function(op, rhs) { 671 | return createOperatorFilter(function(item) { 672 | return item.shutterPhase; 673 | }, op, rhs); 674 | })(args[0], args[1]); 675 | fn = and(isCompItem, fn); 676 | break; 677 | default: 678 | error('not supported'); 679 | break; 680 | } 681 | 682 | if (invert) { 683 | fn = not(fn); 684 | } 685 | 686 | return fn; 687 | } 688 | 689 | function createItemFilter(filters) { 690 | if (isUndefined(filters)) { 691 | filters = ['all']; 692 | } else if (!isArray(filters)) { 693 | filters = [filters]; 694 | } 695 | 696 | var fns = []; 697 | forEach(filters, function(filter) { 698 | if (isArray(filter)) { 699 | fns.push(getItemFilter.apply(null, filter)); 700 | } else if (isFunction(filter)) { 701 | fns.push(filter); 702 | } else { 703 | fns.push(getItemFilter(filter)); 704 | } 705 | }); 706 | 707 | return and(fns); 708 | } 709 | 710 | function getItems(fn) { 711 | fn = isFunction(fn) ? fn : createItemFilter(fn); 712 | 713 | var project = app.project, 714 | items = []; 715 | for (var i = 1, l = project.numItems; i <= l; i++) { 716 | var item = project.item(i); 717 | if (fn(item)) { 718 | items.push(item); 719 | } 720 | } 721 | return items; 722 | } 723 | 724 | function getItem(fn) { 725 | fn = isFunction(fn) ? fn : createItemFilter(fn); 726 | 727 | var project = app.project; 728 | for (var i = 1, l = project.numItems; i <= l; i++) { 729 | var item = project.item(i); 730 | if (fn(item)) { 731 | return item; 732 | } 733 | } 734 | return null; 735 | } 736 | 737 | function getActiveItem() { 738 | var project = app.project; 739 | if (!project) { 740 | return null; 741 | } 742 | var item = project.activeItem; 743 | if (!item) { 744 | return null; 745 | } 746 | return item; 747 | } 748 | 749 | function getActiveComp() { 750 | var item = getActiveItem(); 751 | if (item !== null && isCompItem(item)) { 752 | return item; 753 | } 754 | return null; 755 | } 756 | 757 | function getCompByName(name) { 758 | return getItem(function(item) { 759 | if (isCompItem(item) && item.name === name) { 760 | return true; 761 | } 762 | return false; 763 | }); 764 | } 765 | 766 | function getAVItemByName(name) { 767 | return getItem(function(item) { 768 | if (isAVItem(item) && item.name === name) { 769 | return true; 770 | } 771 | return false; 772 | }); 773 | } 774 | 775 | //layer 776 | function isTextLayer(layer) { 777 | return layer instanceof TextLayer; 778 | } 779 | 780 | function isShapeLayer(layer) { 781 | return layer instanceof ShapeLayer; 782 | } 783 | 784 | function isAVLayer(layer, strict) { 785 | return (layer instanceof AVLayer && (layer.hasVideo || !strict)) || isTextLayer(layer) || isShapeLayer(layer); 786 | } 787 | 788 | function isCameraLayer(layer) { 789 | return layer instanceof CameraLayer; 790 | } 791 | 792 | function isLightLayer(layer) { 793 | return layer instanceof LightLayer; 794 | } 795 | 796 | function isNullLayer(layer) { 797 | return layer.nullLayer; 798 | } 799 | 800 | function isSolidLayer(layer) { 801 | return isAVLayer(layer) && isFootageItem(layer.source) && layer.source.mainSource instanceof SolidSource; 802 | } 803 | 804 | function isCompLayer(layer) { 805 | return isAVLayer(layer) && isCompItem(layer.source); 806 | } 807 | 808 | function getLayerFilter() { 809 | function error(str) { 810 | throw new Error(str + ': ' + type); 811 | } 812 | 813 | function requireArgs(num) { 814 | if (args.length < num) { 815 | error('few arguments'); 816 | } 817 | } 818 | 819 | var args = Array.prototype.slice.call(arguments), 820 | type = args.shift(), 821 | invert = false, 822 | fn = null; 823 | 824 | if (type[0] === '!') { 825 | invert = true; 826 | type = type.slice(1); 827 | } 828 | 829 | switch (toLowerCase(type)) { 830 | case 'none': 831 | fn = function() { 832 | return false; 833 | }; 834 | break; 835 | case 'all': 836 | fn = function() { 837 | return true; 838 | }; 839 | break; 840 | case 'av': 841 | fn = isAVLayer; 842 | break; 843 | case 'text': 844 | fn = isTextLayer; 845 | break; 846 | case 'shape': 847 | fn = isShapeLayer; 848 | break; 849 | case 'null': 850 | fn = isNullLayer; 851 | break; 852 | case 'camera': 853 | fn = isCameraLayer; 854 | break; 855 | case 'light': 856 | fn = isLightLayer; 857 | break; 858 | case 'index': 859 | requireArgs(2); 860 | fn = (function(op, rhs) { 861 | return createOperatorFilter(function(layer) { 862 | return layer.index; 863 | }, op, rhs); 864 | })(args[0], args[1]); 865 | break; 866 | case 'name': 867 | requireArgs(1); 868 | fn = (function(name) { 869 | return function(layer) { 870 | return layer.name === name; 871 | }; 872 | })(args[0]); 873 | break; 874 | case 'time': 875 | requireArgs(2); 876 | fn = (function(op, rhs) { 877 | return createOperatorFilter(function(layer) { 878 | return layer.time; 879 | }, op, rhs); 880 | })(args[0], args[1]); 881 | break; 882 | case 'starttime': 883 | requireArgs(2); 884 | fn = (function(op, rhs) { 885 | return createOperatorFilter(function(layer) { 886 | return layer.startTime; 887 | }, op, rhs); 888 | })(args[0], args[1]); 889 | break; 890 | case 'stretch': 891 | requireArgs(2); 892 | fn = (function(op, rhs) { 893 | return createOperatorFilter(function(layer) { 894 | return layer.stretch; 895 | }, op, rhs); 896 | })(args[0], args[1]); 897 | break; 898 | case 'inpoint': 899 | requireArgs(2); 900 | fn = (function(op, rhs) { 901 | return createOperatorFilter(function(layer) { 902 | return layer.inPoint; 903 | }, op, rhs); 904 | })(args[0], args[1]); 905 | break; 906 | case 'outpoint': 907 | requireArgs(2); 908 | fn = (function(op, rhs) { 909 | return createOperatorFilter(function(layer) { 910 | return layer.outPoint; 911 | }, op, rhs); 912 | })(args[0], args[1]); 913 | break; 914 | case 'enabled': 915 | fn = function(layer) { 916 | return layer.enabled; 917 | }; 918 | break; 919 | case 'solo': 920 | fn = function(layer) { 921 | return layer.solo; 922 | }; 923 | break; 924 | case 'shy': 925 | fn = function(layer) { 926 | return layer.shy; 927 | }; 928 | break; 929 | case 'locked': 930 | fn = function(layer) { 931 | return layer.locked; 932 | }; 933 | break; 934 | case 'hasvideo': 935 | fn = function(layer) { 936 | return layer.hasVideo; 937 | }; 938 | break; 939 | case 'active': 940 | fn = function(layer) { 941 | return layer.active; 942 | }; 943 | break; 944 | case 'comment': 945 | requireArgs(1); 946 | fn = (function(comment) { 947 | return function(layer) { 948 | return layer.comment.indexOf(comment) >= 0; 949 | }; 950 | })(args[0]); 951 | break; 952 | case 'isnameset': 953 | fn = function(layer) { 954 | return layer.isNameSet; 955 | }; 956 | break; 957 | case 'selected': 958 | fn = function(layer) { 959 | return layer.selected; 960 | }; 961 | break; 962 | //av 963 | case 'solid': 964 | fn = isSolidLayer; 965 | break; 966 | case 'file': 967 | fn = function(layer) { 968 | return isFootageItem(layer.source) && layer.source.mainSource instanceof FileSource; 969 | }; 970 | fn = and(isAVLayer, fn); 971 | break; 972 | case 'still': 973 | fn = function(layer) { 974 | return isFootageItem(layer.source) && layer.source.mainSource.isStill; 975 | }; 976 | fn = and(isAVLayer, fn); 977 | break; 978 | case 'comp': 979 | fn = isCompLayer; 980 | break; 981 | case 'isnamefromsource': 982 | fn = function(layer) { 983 | return layer.isNameFromSource; 984 | }; 985 | fn = and(isAVLayer, fn); 986 | break; 987 | case 'height': 988 | requireArgs(2); 989 | fn = (function(op, rhs) { 990 | return createOperatorFilter(function(layer) { 991 | return layer.height; 992 | }, op, rhs); 993 | })(args[0], args[1]); 994 | fn = and(isAVLayer, fn); 995 | break; 996 | case 'width': 997 | requireArgs(2); 998 | fn = (function(op, rhs) { 999 | return createOperatorFilter(function(layer) { 1000 | return layer.width; 1001 | }, op, rhs); 1002 | })(args[0], args[1]); 1003 | fn = and(isAVLayer, fn); 1004 | break; 1005 | case 'audioenabled': 1006 | fn = function(layer) { 1007 | return layer.audioEnabled; 1008 | }; 1009 | fn = and(isAVLayer, fn); 1010 | break; 1011 | case 'motionblur': 1012 | fn = function(layer) { 1013 | return layer.motionBlur; 1014 | }; 1015 | fn = and(isAVLayer, fn); 1016 | break; 1017 | case 'effectsactive': 1018 | fn = function(layer) { 1019 | return layer.effectsActive; 1020 | }; 1021 | fn = and(isAVLayer, fn); 1022 | break; 1023 | case 'adjustment': 1024 | case 'adjustmentlayer': 1025 | fn = function(layer) { 1026 | return layer.adjustmentLayer; 1027 | }; 1028 | fn = and(isAVLayer, fn); 1029 | break; 1030 | case 'guide': 1031 | case 'guidelayer': 1032 | fn = function(layer) { 1033 | return layer.guideLayer; 1034 | }; 1035 | fn = and(isAVLayer, fn); 1036 | break; 1037 | case '3d': 1038 | case 'threed': 1039 | case 'threedlayer': 1040 | fn = function(layer) { 1041 | return layer.threeDLayer; 1042 | }; 1043 | fn = and(isAVLayer, fn); 1044 | break; 1045 | case '2d': 1046 | case 'twod': 1047 | fn = function(layer) { 1048 | return !layer.threeDLayer; 1049 | }; 1050 | fn = and(isAVLayer, fn); 1051 | break; 1052 | case 'threedperchar': 1053 | fn = function(layer) { 1054 | return layer.threeDPerChar; 1055 | }; 1056 | fn = and(isAVLayer, fn); 1057 | break; 1058 | case 'environment': 1059 | case 'environmentlayer': 1060 | fn = function(layer) { 1061 | return layer.environmentLayer; 1062 | }; 1063 | fn = and(isAVLayer, fn); 1064 | break; 1065 | case 'collapse': 1066 | case 'collapsetransformation': 1067 | fn = function(layer) { 1068 | return layer.collapseTransformation; 1069 | }; 1070 | fn = and(isAVLayer, fn); 1071 | break; 1072 | case 'frameblending': 1073 | fn = function(layer) { 1074 | return layer.frameBlending; 1075 | }; 1076 | fn = and(isAVLayer, fn); 1077 | break; 1078 | case 'timeremap': 1079 | case 'timeremapenabled': 1080 | fn = function(layer) { 1081 | return layer.timeRemapEnabled; 1082 | }; 1083 | fn = and(isAVLayer, fn); 1084 | break; 1085 | case 'hasaudio': 1086 | fn = function(layer) { 1087 | return layer.hasAudio; 1088 | }; 1089 | fn = and(isAVLayer, fn); 1090 | break; 1091 | case 'audioactive': 1092 | fn = function(layer) { 1093 | return layer.audioActive; 1094 | }; 1095 | fn = and(isAVLayer, fn); 1096 | break; 1097 | case 'preservetransparency': 1098 | fn = function(layer) { 1099 | return layer.preserveTransparency; 1100 | }; 1101 | fn = and(isAVLayer, fn); 1102 | break; 1103 | case 'istrackmatte': 1104 | fn = function(layer) { 1105 | return layer.isTrackMatte; 1106 | }; 1107 | fn = and(isAVLayer, fn); 1108 | break; 1109 | case 'hastrackmatte': 1110 | fn = function(layer) { 1111 | return layer.hasTrackMatte; 1112 | }; 1113 | fn = and(isAVLayer, fn); 1114 | break; 1115 | default: 1116 | error('not supported'); 1117 | break; 1118 | } 1119 | 1120 | if (invert) { 1121 | fn = not(fn); 1122 | } 1123 | 1124 | return fn; 1125 | } 1126 | 1127 | function createLayerFilter(filters) { 1128 | if (isUndefined(filters)) { 1129 | filters = ['all']; 1130 | } else if (!isArray(filters)) { 1131 | filters = [filters]; 1132 | } 1133 | 1134 | var fns = []; 1135 | forEach(filters, function(filter) { 1136 | if (isArray(filter)) { 1137 | fns.push(getLayerFilter.apply(null, filter)); 1138 | } else if (isFunction(filter)) { 1139 | fns.push(filter); 1140 | } else { 1141 | fns.push(getLayerFilter(filter)); 1142 | } 1143 | }); 1144 | 1145 | return and(fns); 1146 | } 1147 | 1148 | function getArgumentComp(comp) { 1149 | if (isUndefined(comp)) { 1150 | comp = getActiveComp(); 1151 | } else if (isString(comp)) { 1152 | comp = getCompByName(comp); 1153 | } 1154 | return comp; 1155 | } 1156 | 1157 | function getLayer(fn, comp) { 1158 | fn = isFunction(fn) ? fn : createLayerFilter(fn); 1159 | comp = getArgumentComp(comp); 1160 | if (!comp) { 1161 | return null; 1162 | } 1163 | 1164 | for (var i = 1, l = comp.numLayers; i <= l; i++) { 1165 | var layer = comp.layer(i); 1166 | if (fn(layer)) { 1167 | return layer; 1168 | } 1169 | } 1170 | 1171 | return null; 1172 | } 1173 | 1174 | function getLayers(fn, comp) { 1175 | fn = isFunction(fn) ? fn : createLayerFilter(fn); 1176 | comp = getArgumentComp(comp); 1177 | if (!comp) { 1178 | return []; 1179 | } 1180 | 1181 | var layers = []; 1182 | forEachLayer(comp, function(layer) { 1183 | if (fn(layer)) { 1184 | layers.push(layer); 1185 | } 1186 | }); 1187 | 1188 | return layers; 1189 | } 1190 | 1191 | function getLayerByName(name, comp) { 1192 | comp = getArgumentComp(comp); 1193 | if (!comp) { 1194 | return null; 1195 | } 1196 | 1197 | return comp.layers.byName(name); 1198 | } 1199 | 1200 | function selectLayers(fn, comp, deselect) { 1201 | fn = isFunction(fn) ? fn : createLayerFilter(fn); 1202 | comp = getArgumentComp(comp); 1203 | deselect = deselect || false; 1204 | if (!comp) { 1205 | return false; 1206 | } 1207 | 1208 | var selected = false; 1209 | forEachLayer(comp, function(layer) { 1210 | if (fn(layer)) { 1211 | layer.selected = true; 1212 | selected = true; 1213 | } else if (deselect) { 1214 | layer.selected = false; 1215 | } 1216 | }); 1217 | 1218 | return selected; 1219 | } 1220 | 1221 | function selectLayer(fn, comp, deselect) { 1222 | fn = isFunction(fn) ? fn : createLayerFilter(fn); 1223 | comp = getArgumentComp(comp); 1224 | deselect = deselect || false; 1225 | if (!comp) { 1226 | return false; 1227 | } 1228 | 1229 | var selected = false; 1230 | forEachLayer(comp, function(layer) { 1231 | if (!selected && fn(layer)) { 1232 | layer.selected = true; 1233 | selected = true; 1234 | } else if (deselect) { 1235 | layer.selected = false; 1236 | } 1237 | }); 1238 | 1239 | return selected; 1240 | } 1241 | 1242 | function deselectLayers(comp) { 1243 | comp = getArgumentComp(comp); 1244 | if (!comp) { 1245 | return; 1246 | } 1247 | forEach(comp.selectedLayers, function(layer) { 1248 | layer.selected = false; 1249 | }); 1250 | } 1251 | 1252 | function getSelectedLayers(comp) { 1253 | comp = getArgumentComp(comp); 1254 | if (!comp) { 1255 | return []; 1256 | } 1257 | return comp.selectedLayers.slice(); 1258 | } 1259 | 1260 | function getSelectedLayer(comp) { 1261 | var layers = getSelectedLayers(comp); 1262 | if (layers.length === 0) { 1263 | return null; 1264 | } 1265 | return layers[0]; 1266 | } 1267 | 1268 | //property 1269 | function isProperty(property) { 1270 | return property instanceof Property; 1271 | } 1272 | 1273 | function isPropertyGroup(property) { 1274 | return property instanceof PropertyGroup || property instanceof MaskPropertyGroup; 1275 | } 1276 | 1277 | function isHiddenProperty(property) { 1278 | var hidden = false; 1279 | try { 1280 | var selected = property.selected; 1281 | property.selected = selected; 1282 | } catch (e) { 1283 | hidden = true; 1284 | } 1285 | return hidden; 1286 | } 1287 | 1288 | function getPropertyFilter() { 1289 | function error(str) { 1290 | throw new Error(str + ': ' + type); 1291 | } 1292 | 1293 | function requireArgs(num) { 1294 | if (args.length < num) { 1295 | error('few arguments'); 1296 | } 1297 | } 1298 | 1299 | var args = Array.prototype.slice.call(arguments), 1300 | type = args.shift(), 1301 | invert = false, 1302 | fn = null; 1303 | 1304 | if (type[0] === '!') { 1305 | invert = true; 1306 | type = type.slice(1); 1307 | } 1308 | 1309 | switch (toLowerCase(type)) { 1310 | case 'none': 1311 | fn = function() { 1312 | return false; 1313 | }; 1314 | break; 1315 | case 'all': 1316 | fn = function() { 1317 | return true; 1318 | }; 1319 | break; 1320 | case 'property': 1321 | fn = isProperty; 1322 | break; 1323 | case 'propertygroup': 1324 | fn = isPropertyGroup; 1325 | break; 1326 | case 'name': 1327 | requireArgs(1); 1328 | fn = (function(name) { 1329 | return function(property) { 1330 | return property.name === name; 1331 | }; 1332 | })(args[0]); 1333 | break; 1334 | case 'matchname': 1335 | requireArgs(1); 1336 | fn = (function(name) { 1337 | return function(property) { 1338 | return property.matchName === name; 1339 | }; 1340 | })(args[0]); 1341 | break; 1342 | case 'propertyindex': 1343 | requireArgs(2); 1344 | fn = (function(op, rhs) { 1345 | return createOperatorFilter(function(property) { 1346 | return property.propertyIndex; 1347 | }, op, rhs); 1348 | })(args[0], args[1]); 1349 | break; 1350 | case 'propertydepth': 1351 | requireArgs(2); 1352 | fn = (function(op, rhs) { 1353 | return createOperatorFilter(function(property) { 1354 | return property.propertyDepth; 1355 | }, op, rhs); 1356 | })(args[0], args[1]); 1357 | break; 1358 | case 'ismodified': 1359 | fn = function(property) { 1360 | return property.isModified; 1361 | }; 1362 | break; 1363 | case 'cansetenabled': 1364 | fn = function(property) { 1365 | return property.canSetEnabled; 1366 | }; 1367 | break; 1368 | case 'enabled': 1369 | fn = function(property) { 1370 | return property.enabled; 1371 | }; 1372 | break; 1373 | case 'active': 1374 | fn = function(property) { 1375 | return property.active; 1376 | }; 1377 | break; 1378 | case 'elided': 1379 | fn = function(property) { 1380 | return property.elided; 1381 | }; 1382 | break; 1383 | case 'iseffect': 1384 | fn = function(property) { 1385 | return property.isEffect; 1386 | }; 1387 | break; 1388 | case 'ismask': 1389 | fn = function(property) { 1390 | return property.isMask; 1391 | }; 1392 | break; 1393 | case 'selected': 1394 | fn = function(property) { 1395 | return property.selected; 1396 | }; 1397 | break; 1398 | //property 1399 | case 'novalue': 1400 | case 'no_value': 1401 | fn = function(property) { 1402 | return property.propertyValueType === PropertyValueType.NO_VALUE; 1403 | }; 1404 | fn = and(isProperty, fn); 1405 | break; 1406 | case 'threedspatial': 1407 | case 'threed_spatial': 1408 | fn = function(property) { 1409 | return property.propertyValueType === PropertyValueType.ThreeD_SPATIAL; 1410 | }; 1411 | fn = and(isProperty, fn); 1412 | break; 1413 | case 'threed': 1414 | fn = function(property) { 1415 | return property.propertyValueType === PropertyValueType.ThreeD; 1416 | }; 1417 | fn = and(isProperty, fn); 1418 | break; 1419 | case '3d': 1420 | fn = function(property) { 1421 | return property.propertyValueType === PropertyValueType.ThreeD_SPATIAL || property.propertyValueType === PropertyValueType.ThreeD; 1422 | }; 1423 | fn = and(isProperty, fn); 1424 | break; 1425 | case 'twodspatial': 1426 | case 'twod_spatial': 1427 | fn = function(property) { 1428 | return property.propertyValueType === PropertyValueType.TwoD_SPATIAL; 1429 | }; 1430 | fn = and(isProperty, fn); 1431 | break; 1432 | case 'twod': 1433 | fn = function(property) { 1434 | return property.propertyValueType === PropertyValueType.TwoD; 1435 | }; 1436 | fn = and(isProperty, fn); 1437 | break; 1438 | case '2d': 1439 | fn = function(property) { 1440 | return property.propertyValueType === PropertyValueType.TwoD_SPATIAL || property.propertyValueType === PropertyValueType.TwoD; 1441 | }; 1442 | fn = and(isProperty, fn); 1443 | break; 1444 | case 'oned': 1445 | fn = function(property) { 1446 | return property.propertyValueType === PropertyValueType.OneD; 1447 | }; 1448 | fn = and(isProperty, fn); 1449 | break; 1450 | case 'color': 1451 | fn = function(property) { 1452 | return property.propertyValueType === PropertyValueType.COLOR; 1453 | }; 1454 | fn = and(isProperty, fn); 1455 | break; 1456 | case 'customvalue': 1457 | case 'custom_value': 1458 | fn = function(property) { 1459 | return property.propertyValueType === PropertyValueType.CUSTOM_VALUE; 1460 | }; 1461 | fn = and(isProperty, fn); 1462 | break; 1463 | case 'marker': 1464 | fn = function(property) { 1465 | return property.propertyValueType === PropertyValueType.MARKER; 1466 | }; 1467 | fn = and(isProperty, fn); 1468 | break; 1469 | case 'layerindex': 1470 | case 'layer_index': 1471 | fn = function(property) { 1472 | return property.propertyValueType === PropertyValueType.LAYER_INDEX; 1473 | }; 1474 | fn = and(isProperty, fn); 1475 | break; 1476 | case 'maskindex': 1477 | case 'mask_index': 1478 | fn = function(property) { 1479 | return property.propertyValueType === PropertyValueType.MASK_INDEX; 1480 | }; 1481 | fn = and(isProperty, fn); 1482 | break; 1483 | case 'shape': 1484 | fn = function(property) { 1485 | return property.propertyValueType === PropertyValueType.SHAPE; 1486 | }; 1487 | fn = and(isProperty, fn); 1488 | break; 1489 | case 'textdocument': 1490 | case 'text_document': 1491 | fn = function(property) { 1492 | return property.propertyValueType === PropertyValueType.TEXT_DOCUMENT; 1493 | }; 1494 | fn = and(isProperty, fn); 1495 | break; 1496 | case '1d': 1497 | fn = function(property) { 1498 | return property.propertyValueType === PropertyValueType.OneD || property.propertyValueType === PropertyValueType.LAYER_INDEX || property.propertyValueType === PropertyValueType.MASK_INDEX; 1499 | }; 1500 | fn = and(isProperty, fn); 1501 | break; 1502 | case 'hasmin': 1503 | fn = function(property) { 1504 | return property.hasMin; 1505 | }; 1506 | fn = and(isProperty, fn); 1507 | break; 1508 | case 'hasmax': 1509 | fn = function(property) { 1510 | return property.hasMax; 1511 | }; 1512 | fn = and(isProperty, fn); 1513 | break; 1514 | case 'isspatial': 1515 | fn = function(property) { 1516 | return property.isSpatial; 1517 | }; 1518 | fn = and(isProperty, fn); 1519 | break; 1520 | case 'canvaryovertime': 1521 | fn = function(property) { 1522 | return property.canVaryOverTime; 1523 | }; 1524 | fn = and(isProperty, fn); 1525 | break; 1526 | case 'istimevarying': 1527 | fn = function(property) { 1528 | return property.isTimeVarying; 1529 | }; 1530 | fn = and(isProperty, fn); 1531 | break; 1532 | case 'numkeys': 1533 | requireArgs(2); 1534 | fn = (function(op, rhs) { 1535 | return createOperatorFilter(function(property) { 1536 | return property.numKeys; 1537 | }, op, rhs); 1538 | })(args[0], args[1]); 1539 | fn = and(isProperty, fn); 1540 | break; 1541 | case 'cansetexpression': 1542 | fn = function(property) { 1543 | return property.canSetExpression; 1544 | }; 1545 | fn = and(isProperty, fn); 1546 | break; 1547 | case 'expressionenabled': 1548 | fn = function(property) { 1549 | return property.expressionEnabled; 1550 | }; 1551 | fn = and(isProperty, fn); 1552 | break; 1553 | case 'propertyindex': 1554 | requireArgs(2); 1555 | fn = (function(op, rhs) { 1556 | return createOperatorFilter(function(property) { 1557 | return property.propertyIndex; 1558 | }, op, rhs); 1559 | })(args[0], args[1]); 1560 | fn = and(isProperty, fn); 1561 | break; 1562 | case 'dimensionsseparated': 1563 | fn = function(property) { 1564 | return property.dimensionsSeparated; 1565 | }; 1566 | fn = and(isProperty, fn); 1567 | break; 1568 | case 'isseparationfollower': 1569 | fn = function(property) { 1570 | return property.isSeparationFollower; 1571 | }; 1572 | fn = and(isProperty, fn); 1573 | break; 1574 | default: 1575 | error('not supported'); 1576 | break; 1577 | } 1578 | 1579 | if (invert) { 1580 | fn = not(fn); 1581 | } 1582 | 1583 | return fn; 1584 | } 1585 | 1586 | function createPropertyFilter(filters) { 1587 | if (isUndefined(filters)) { 1588 | filters = ['all']; 1589 | } else if (!isArray(filters)) { 1590 | filters = [filters]; 1591 | } 1592 | 1593 | var fns = []; 1594 | forEach(filters, function(filter) { 1595 | if (isArray(filter)) { 1596 | fns.push(getPropertyFilter.apply(null, filter)); 1597 | } else if (isFunction(filter)) { 1598 | fns.push(filter); 1599 | } else { 1600 | fns.push(getPropertyFilter(filter)); 1601 | } 1602 | }); 1603 | 1604 | return and(fns); 1605 | } 1606 | 1607 | function getSelectedProperties(options) { 1608 | if (isUndefined(options) || isObject(options)) { 1609 | options = extend({ 1610 | multiple: true, 1611 | propertyGroup: false, 1612 | filter: function() { 1613 | return true; 1614 | } 1615 | }, options); 1616 | } else if (isArray(options) || isString(options)) { 1617 | options = { 1618 | multiple: true, 1619 | propertyGroup: true, 1620 | filter: createPropertyFilter(options) 1621 | }; 1622 | } else if (isFunction(options)) { 1623 | options = { 1624 | multiple: true, 1625 | propertyGroup: true, 1626 | filter: options 1627 | }; 1628 | } 1629 | 1630 | var layers = getSelectedLayers(); 1631 | if (layers.length === 0) { 1632 | return []; 1633 | } 1634 | 1635 | if (!options.multiple) { 1636 | layers = [layers[0]]; 1637 | } 1638 | 1639 | var result = []; 1640 | forEach(layers, function(layer) { 1641 | var selected_properties = layer.selectedProperties.slice(); 1642 | forEach(selected_properties, function(selected_property) { 1643 | if ((options.propertyGroup || isProperty(selected_property)) && options.filter(selected_property)) { 1644 | result.push(selected_property); 1645 | } 1646 | }); 1647 | }); 1648 | 1649 | return result; 1650 | } 1651 | 1652 | function getSelectedPropertiesWithLayer(options) { 1653 | if (isUndefined(options) || isObject(options)) { 1654 | options = extend({ 1655 | multiple: true, 1656 | propertyGroup: false, 1657 | filter: function() { 1658 | return true; 1659 | } 1660 | }, options); 1661 | } else if (isArray(options) || isString(options)) { 1662 | options = { 1663 | multiple: true, 1664 | propertyGroup: true, 1665 | filter: createPropertyFilter(options) 1666 | }; 1667 | } else if (isFunction(options)) { 1668 | options = { 1669 | multiple: true, 1670 | propertyGroup: true, 1671 | filter: options 1672 | }; 1673 | } 1674 | 1675 | var layers = getSelectedLayers(); 1676 | if (layers.length === 0) { 1677 | return []; 1678 | } 1679 | 1680 | if (!options.multiple) { 1681 | layers = [layers[0]]; 1682 | } 1683 | 1684 | var result = []; 1685 | forEach(layers, function(layer) { 1686 | var selected_properties = layer.selectedProperties.slice(), 1687 | properties = []; 1688 | forEach(selected_properties, function(selected_property) { 1689 | if ((options.propertyGroup || isProperty(selected_property)) && options.filter(selected_property)) { 1690 | properties.push(selected_property); 1691 | } 1692 | }); 1693 | if (properties.length > 0) { 1694 | result.push({ 1695 | layer: layer, 1696 | properties: properties 1697 | }); 1698 | } 1699 | }); 1700 | 1701 | return result; 1702 | } 1703 | 1704 | function getSelectedProperty() { 1705 | var layer = getSelectedLayer(); 1706 | if (layer === null) { 1707 | return null; 1708 | } 1709 | 1710 | var properties = layer.selectedProperties.slice(), 1711 | property = find(properties, function(property) { 1712 | return isProperty(property); 1713 | }); 1714 | 1715 | return property; 1716 | } 1717 | 1718 | function getSelectedPropertyWithLayer() { 1719 | var layer = getSelectedLayer(); 1720 | if (layer === null) { 1721 | return null; 1722 | } 1723 | 1724 | var properties = layer.selectedProperties.slice(), 1725 | property = find(properties, function(property) { 1726 | return isProperty(property); 1727 | }); 1728 | 1729 | if (property === null) { 1730 | return null; 1731 | } 1732 | 1733 | return { 1734 | layer: layer, 1735 | property: property 1736 | }; 1737 | } 1738 | 1739 | function getPathOfProperty(property, type) { 1740 | type = type || 'name'; 1741 | var names = []; 1742 | while (property !== null) { 1743 | if (type == 'name') { 1744 | names.push(property.name); 1745 | } else if (type == 'matchname') { 1746 | names.push(property.matchName); 1747 | } 1748 | property = property.parentProperty; 1749 | } 1750 | names.pop(); 1751 | names.reverse(); 1752 | return names; 1753 | } 1754 | 1755 | function getPathOfSelectedProperty(type) { 1756 | type = type || 'name'; 1757 | if (!(type == 'name' || type == 'matchname')) { 1758 | throw new Error('type must be "name" or "matchname"'); 1759 | } 1760 | 1761 | var property = getSelectedProperty(); 1762 | if (property === null) { 1763 | return null; 1764 | } 1765 | 1766 | return getPathOfProperty(property, type); 1767 | } 1768 | 1769 | function getPropertyFromPath(layer, path) { 1770 | var property = layer; 1771 | for (var i = 0, l = path.length; i < l; i++) { 1772 | var name = path[i]; 1773 | if (isString(name) && /^\d+$/.test(name)) { 1774 | name = parseInt(name); 1775 | } 1776 | property = property.property(name); 1777 | if (property === null) { 1778 | return null; 1779 | } 1780 | } 1781 | return property; 1782 | } 1783 | 1784 | function getLayerOfProperty(property) { 1785 | var parent; 1786 | while (parent = property.parentProperty) { 1787 | property = parent; 1788 | } 1789 | return property; 1790 | } 1791 | 1792 | //color 1793 | function rgbToHsl(rgba) { 1794 | var r = clamp(rgba[0], 0, 1), 1795 | g = clamp(rgba[1], 0, 1), 1796 | b = clamp(rgba[2], 0, 1); 1797 | 1798 | var max = Math.max(r, g, b), 1799 | min = Math.min(r, g, b), 1800 | h, 1801 | s, 1802 | l = (max + min) / 2; 1803 | 1804 | if (max == min) { 1805 | h = s = 0; 1806 | } else { 1807 | var d = max - min; 1808 | s = l > 0.5 ? d / (2 - max - min) : d / (max + min); 1809 | switch (max) { 1810 | case r: 1811 | h = (g - b) / d + (g < b ? 6 : 0); 1812 | break; 1813 | case g: 1814 | h = (b - r) / d + 2; 1815 | break; 1816 | case b: 1817 | h = (r - g) / d + 4; 1818 | break; 1819 | } 1820 | h /= 6; 1821 | } 1822 | 1823 | return [h, s, l, rgba[3]]; 1824 | } 1825 | 1826 | function hslToRgb(hsla) { 1827 | function clampH(h) { 1828 | return (((h % 1) + 1) % 1); 1829 | } 1830 | 1831 | function hue2rgb(p, q, t) { 1832 | if (t < 0) t += 1; 1833 | if (t > 1) t -= 1; 1834 | if (t < 1 / 6) return p + (q - p) * 6 * t; 1835 | if (t < 1 / 2) return q; 1836 | if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; 1837 | return p; 1838 | } 1839 | 1840 | var h = clampH(hsla[0]), 1841 | s = clamp(hsla[1], 0, 1), 1842 | l = clamp(hsla[2], 0, 1), 1843 | r, g, b; 1844 | 1845 | if (s === 0) { 1846 | r = g = b = l; 1847 | } else { 1848 | var q = l < 0.5 ? l * (1 + s) : l + s - l * s, 1849 | p = 2 * l - q; 1850 | 1851 | r = hue2rgb(p, q, h + 1 / 3); 1852 | g = hue2rgb(p, q, h); 1853 | b = hue2rgb(p, q, h - 1 / 3); 1854 | } 1855 | 1856 | return [r, g, b, hsla[3]]; 1857 | } 1858 | 1859 | function rgbToYuv(rgba) { 1860 | var r = clamp(rgba[0], 0, 1), 1861 | g = clamp(rgba[1], 0, 1), 1862 | b = clamp(rgba[2], 0, 1), 1863 | y = 0.299 * r + 0.587 * g + 0.114 * b, 1864 | u = -0.169 * r - 0.331 * g + 0.5 * b, 1865 | v = 0.5 * r - 0.419 * g - 0.081 * b; 1866 | 1867 | return [y, u + 0.5, v + 0.5, rgba[3]]; 1868 | } 1869 | 1870 | function yuvToRgb(yuva) { 1871 | var y = clamp(yuva[0], 0, 1), 1872 | u = clamp(yuva[1], 0, 1) - 0.5, 1873 | v = clamp(yuva[2], 0, 1) - 0.5, 1874 | r = 1 * y + 1.402 * v, 1875 | g = 1 * y - 0.344 * u - 0.714 * v, 1876 | b = 1 * y + 1.772 * u; 1877 | 1878 | return [r, g, b, yuva[3]]; 1879 | } 1880 | 1881 | root.Utils = Utils; 1882 | 1883 | })(KIKAKU); 1884 | -------------------------------------------------------------------------------- /Startup/KikakuUtils/README.md: -------------------------------------------------------------------------------- 1 | # KikakuUtils 2 | 3 | 便利ライブラリ。 4 | 5 | ## Usage 6 | 7 | **Example #1** 8 | 9 | ``` 10 | (function () { 11 | var Utils = KIKAKU.Utils; 12 | 13 | var comp = Utils.getActiveComp(); 14 | if (comp) { 15 | Utils.forEachLayer(comp, function (layer) { 16 | if (Utils.isAVLayer(layer)) { 17 | layer.blendingMode = BlendingMode.SCREEN; 18 | } 19 | }); 20 | } 21 | })(); 22 | ``` 23 | 24 | ## Version 25 | 26 | - v1.1.0 Modified getSelectedProperties and getSelectedProperty. Added getSelectedPropertiesWithLayer and getSelectedPropertyWithLayer. 27 | - v1.0.1 Fixed hslToRgb 28 | - v1.0.0 -------------------------------------------------------------------------------- /Startup/README.md: -------------------------------------------------------------------------------- 1 | # Startup Scripts 2 | 3 | Startup向けスクリプト。 4 | 5 | ## KikakuEventDispatcher 6 | 7 | 単純なイベントディスパッチャー。 8 | 9 | ## KikakuFileManager 10 | 11 | ファイル操作用クラス。 12 | 13 | ## KikakuJSON 14 | 15 | JSONのpolyfill。中身はjson2.js。 16 | 17 | ## KikakuSettingManager 18 | 19 | 設定操作用クラス。 20 | 21 | ## KikakuUIBuilder 22 | 23 | ScriptUIを楽に作る。 24 | 25 | ## KikakuUnit 26 | 27 | 簡易テスト用。 28 | 29 | ## KikakuUtils 30 | 31 | 便利関数集。 -------------------------------------------------------------------------------- /typings/kikaku/kikaku.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | /// 5 | /// 6 | /// 7 | /// -------------------------------------------------------------------------------- /typings/kikaku/kikaku.event_dispatcher.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace KIKAKU { 2 | 3 | export class EventDispatcher { 4 | static VERSION: string; 5 | static AUTHOR: string; 6 | 7 | addEventListener(type: string, fn: Function | string, ctx?: any): void; 8 | removeEventListener(type: string, fn: Function | string, ctx?: any): void; 9 | dispatchEvent(type: string): void; 10 | } 11 | 12 | } -------------------------------------------------------------------------------- /typings/kikaku/kikaku.file_manager.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace KIKAKU { 2 | 3 | export class FileManager { 4 | static VERSION: string; 5 | static AUTHOR: string; 6 | 7 | static validateFileName(fileName: string): boolean; 8 | 9 | constructor(path: string, type?: string); 10 | 11 | getFiles(options?: {path?: string, mask?: string}): File[]; 12 | getFile(fileName: string): File; 13 | getFileNames(options?: {path?: string, mask?: string}): string[]; 14 | exists(fileName: string): boolean; 15 | get(fileName: string): string | void; 16 | save(fileName: string, text: string): void; 17 | delete(fileName: string): boolean; 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /typings/kikaku/kikaku.json.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace KIKAKU { 2 | 3 | export class JSON { 4 | static stringify(value: any, replacer?: any, space?: any): string; 5 | static parse(text: string, reviver?: any): any; 6 | } 7 | 8 | } -------------------------------------------------------------------------------- /typings/kikaku/kikaku.setting_manager.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace KIKAKU { 2 | 3 | export class SettingManager { 4 | static VERSION: string; 5 | static AUTHOR: string; 6 | 7 | constructor(section: string); 8 | 9 | have(key: string): boolean; 10 | get(key: string, defaulValue: any): any; 11 | save(key: string, value: any): void; 12 | delete(key: string): void; 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /typings/kikaku/kikaku.ui_builder.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare namespace KIKAKU { 4 | 5 | namespace UIBuilder { 6 | export enum PARAMETER_TYPE { 7 | HEADING, 8 | SEPARATOR, 9 | SPACE, 10 | PANEL, 11 | PANEL_END, 12 | TEXT, 13 | TEXTS, 14 | TEXTAREA, 15 | TEXTAREAS, 16 | STATICTEXT, 17 | STATICTEXTS, 18 | NUMBER, 19 | NUMBERS, 20 | SLIDER, 21 | POINT, 22 | POINT3D, 23 | FILE, 24 | FOLDER, 25 | CHECKBOX, 26 | CHECKBOXES, 27 | RADIOBUTTON, 28 | COLOR, 29 | COLORS, 30 | POPUP, 31 | POPUPS, 32 | LISTBOX, 33 | LISTBOXES, 34 | SCRIPT, 35 | HELP, 36 | CUSTOM 37 | } 38 | 39 | export interface CustomParameter { 40 | getHeight(): number; 41 | build(group: Group, builder: UIBuilder): void; 42 | init?(obj?: any): void; 43 | get?(): any; 44 | set?(value: any): void; 45 | execute?(undo?: boolean): void; 46 | enable?(): void; 47 | disable?(): void; 48 | getItems?(): string[]; 49 | addItems?(item: string | string[]): void; 50 | removeItem?(item: string): void; 51 | replaceItems?(items: string | string[]): void; 52 | toJSON?(): { 53 | value?: any; 54 | items?: string[]; 55 | }; 56 | } 57 | } 58 | 59 | export class UIBuilder { 60 | static LIBRARY_NAME: string; 61 | static VERSION: string; 62 | static AUTHOR: string; 63 | static API: { 64 | (script: string, name: string, ...args): any; 65 | has(script: string, name: string): boolean; 66 | }; 67 | 68 | constructor(global: any, name: string, options?: { 69 | version?: string; 70 | author?: string; 71 | url?: string; 72 | title?: string; 73 | resizeable?: boolean; 74 | numberOfScriptColumns?: number; 75 | titleWidth?: number; 76 | width?: number; 77 | help?: boolean; 78 | autoSave?: boolean; 79 | fileType?: string; 80 | }); 81 | 82 | getName(): string; 83 | getVersion(): string; 84 | getAuthor(): string; 85 | getUrl(): string; 86 | 87 | add(type: string | UIBuilder.PARAMETER_TYPE, name: string, value?: any, options?: any): UIBuilder; 88 | 89 | api(name: string, fn: Function): UIBuilder; 90 | 91 | on(type: string, fn: Function): UIBuilder; 92 | off(type: string, fn: Function): UIBuilder; 93 | trigger(type: string, ...args): UIBuilder; 94 | 95 | get(name: string, index?: number): any; 96 | set(name: string, value: any): UIBuilder; 97 | set(name: string, index: number, value: any): UIBuilder; 98 | execute(name: string, undo?: boolean): any; 99 | enable(name: string): UIBuilder; 100 | disable(name: string): UIBuilder; 101 | getItems(name: string, index?: number): string[]; 102 | replaceItems(name: string, items: string[]): UIBuilder; 103 | replaceItems(name: string, index: number, items: string[]): UIBuilder; 104 | addItems(name: string, items: string | string[]): UIBuilder; 105 | addItems(name: string, index: number, items: string | string[]): UIBuilder; 106 | removeItem(name: string, item: string): UIBuilder; 107 | removeItem(name: string, index: number, item: string): UIBuilder; 108 | 109 | getSetting(key: string, defaultValue: any): void; 110 | saveSetting(key: string, value: any): void; 111 | deleteSetting(key: string): void; 112 | 113 | getFileNames(): string[]; 114 | existsFile(fileName: string): boolean; 115 | getFile(fileName: string): any; 116 | saveFile(fileName: string, data: any): void; 117 | deleteFile(fileName: string): void; 118 | 119 | update(): void; 120 | close(): void; 121 | 122 | build(): void; 123 | } 124 | } -------------------------------------------------------------------------------- /typings/kikaku/kikaku.unit.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace KIKAKU { 2 | 3 | export class Unit { 4 | static test(name: string, tests: { 5 | [name: string]: Function; 6 | }): boolean; 7 | static test(name: string, hooks: { 8 | before?: Function; 9 | beforeEach?: Function; 10 | afterEach?: Function; 11 | after?: Function; 12 | }, tests: { 13 | [name: string]: Function; 14 | }): any; 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /typings/kikaku/kikaku.utils.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare namespace KIKAKU.Utils { 4 | 5 | export var VERSION: string; 6 | export var AUTHOR: string; 7 | 8 | //utility 9 | export function isObject(obj: any): boolean; 10 | export function isArray(obj: any): boolean; 11 | export function isFunction(obj: any): boolean; 12 | export function isString(obj: any): boolean; 13 | export function isNumber(obj: any): boolean; 14 | export function isBoolean(obj: any): boolean; 15 | export function isUndefined(obj: any): boolean; 16 | 17 | export function forEach(obj: Object | any[], fn: Function): void; 18 | export function forEachItem(folder: FolderItem, fn: Function): void; 19 | export function forEachItem(fn: Function): void; 20 | export function forEachLayer(comp: CompItem, fn: Function): void; 21 | export function forEachPropertyGroup(propertyGrouop: PropertyGroup, fn: Function): void; 22 | export function forEachEffect(layer: AVLayer, fn: Function): void; 23 | 24 | export function inherits(C: any, P: any): void; 25 | 26 | export function assign(obj: Object, ...others): Object; 27 | export function map(arr: any[], fn: Function): any[]; 28 | export function reduce(arr: any[], fn: Function, initialValue?: any): any; 29 | export function filter(arr: any[], fn: Function): any[]; 30 | export function some(arr: any[], fn: Function): boolean; 31 | export function every(arr: any[], fn: Function): boolean; 32 | 33 | export function inArray(arr: any[], fn: Function | any): number; 34 | export function find(arr: any[], fn: Function): any | void; 35 | 36 | export function clamp(v: any, mn: any, mx: any): any; 37 | export function trim(str: string): string; 38 | 39 | //item 40 | export function isFootageItem(item: Item): boolean; 41 | export function isCompItem(item: Item): boolean; 42 | export function isAVItem(item: Item): boolean; 43 | export function isFolderItem(item: Item): boolean; 44 | 45 | export function createItemFilter(filters?: any): Function; 46 | 47 | export function getItems(fn: Function | any): Item[]; 48 | export function getItem(fn: Function | any): Item | void; 49 | export function getActiveItem(): Item | void; 50 | export function getActiveComp(): CompItem | void; 51 | export function getCompByName(name: string): CompItem | void; 52 | export function getAVItemByName(name: string): AVItem | void; 53 | 54 | //layer 55 | export function isTextLayer(layer: Layer): boolean; 56 | export function isShapeLayer(layer: Layer): boolean; 57 | export function isAVLayer(layer: Layer): boolean; 58 | export function isNullLayer(layer: Layer): boolean; 59 | export function isSolidLayer(layer: Layer): boolean; 60 | export function isCompLayer(layer: Layer): boolean; 61 | export function isCameraLayer(layer: Layer): boolean; 62 | export function isLightLayer(layer: Layer): boolean; 63 | 64 | export function createLayerFilter(filters?: any): Function; 65 | 66 | export function getLayers(fn?: Function | any, comp?: CompItem): Layer[]; 67 | export function getLayer(fn?: Function | any, comp?: CompItem): Layer | void; 68 | export function getLayerByName(name: string, comp?: CompItem): Layer | void; 69 | 70 | export function selectLayers(fn?: Function | any, comp?: CompItem, deselect?: boolean): boolean; 71 | export function selectLayer(fn?: Function | any, comp?: CompItem, deselect?: boolean): boolean; 72 | export function deselectLayers(comp?: CompItem): void; 73 | 74 | export function getSelectedLayers(comp?: CompItem): Layer[]; 75 | export function getSelectedLayer(comp?: CompItem): Layer | void; 76 | 77 | //property 78 | export function isProperty(property: PropertyBase): boolean; 79 | export function isPropertyGroup(property: PropertyBase): boolean; 80 | export function isHiddenProperty(property: PropertyBase): boolean; 81 | 82 | export function createPropertyFilter(filters?: any): Function; 83 | 84 | export function getSelectedProperties(options?: {multiple?: boolean, propertyGroup?: boolean, filter?: Function}): PropertyBase[]; 85 | export function getSelectedPropertiesWithLayer(options?: {multiple?: boolean, propertyGroup?: boolean, filter?: Function}): {layer: Layer; properties: PropertyBase[]}[]; 86 | export function getSelectedProperty(): PropertyBase | void; 87 | export function getSelectedPropertyWithLayer(): {layer: Layer; property: PropertyBase;} | void; 88 | export function getPathOfProperty(property: PropertyBase, type?: string): string[]; 89 | export function getPathOfSelectedProperty(type?: string): PropertyBase | void; 90 | export function getPropertyFromPath(layer: Layer, path: (string | number)[]): void; 91 | export function getLayerOfProperty(property: PropertyBase): Layer; 92 | 93 | //color 94 | export function rgbToHsl(rgba: [number, number, number, number]): [number, number, number, number]; 95 | export function hslToRgb(hsla: [number, number, number, number]): [number, number, number, number]; 96 | export function rgbToYuv(rgba: [number, number, number, number]): [number, number, number, number]; 97 | export function yuvToRgb(yuva: [number, number, number, number]): [number, number, number, number]; 98 | 99 | } --------------------------------------------------------------------------------