```
/*
DecomposeText.jsx
version: 3.0
author: Charles Bordenave (www.nabscripts.com)
date: 08 Aug 2013
*/
function DecomposeText()
{
var decomposeText = this;
var utils = new DecomposeTextUtils();
// infos
this.scriptName = "DecomposeText.jsx";
this.scriptVersion = "3.0";
this.scriptTitle = "Decompose Text";
this.scriptCopyright = "Copyright (c) 2013 Charles Bordenave";
this.scriptHomepage = "http://www.nabscripts.com";
this.scriptDescription = {en:"This script decomposes the content of the selected text layer and places each element on its own layer.\\r\\rThe first option allows you to keep each element in its original position, but new layers have the same text as the original layer except that some characters/words/lines are hidden by expressions. The second option creates new layers with only one character/word/line per layer, but the positioning is only approximated since it is currently not possible to retrieve the exact location of each element with AE scripting.",
fr:"Ce script décompose le contenu du calque texte sélectionné et place chaque élément sur un calque indépendant.\\r\\rLa première option vous permet de maintenir chaque élément à sa position originale, mais les nouveaux calques ont le même texte que le calque original sauf que certains caractères/mots/lignes sont cachés par expressions. La deuxième option crée les nouveaux calques avec seulement un caractère/mot/ligne par calque, mais le positionnement n\\\'est qu\\\'approximatif car il est actuellement impossible de récupérer la position exacte de chaque élément avec le scripting d\\\'AE."};
this.scriptAbout = {en:this.scriptName + ", v" + this.scriptVersion + "\\r" + this.scriptCopyright + "\\r" + this.scriptHomepage + "\\r\\r" + utils.loc(this.scriptDescription),
fr:this.scriptName + ", v" + this.scriptVersion + "\\r" + this.scriptCopyright + "\\r" + this.scriptHomepage + "\\r\\r" + utils.loc(this.scriptDescription)};
this.scriptUsage = {en: "\u25BA Select a text layer \\r" +
"\u25BA Specify how the text must be splitted \\r" +
"\u25BA Click on Decompose",
fr: "\u25BA Sélectionnez un calque texte \\r" +
"\u25BA Spécifiez comment le texte doit être décomposé \\r" +
"\u25BA Cliquez sur Décomposer"};
// errors
this.noCompErr = {en:"A comp must be active.", fr:"Une composition doit être active."};
this.noLayerErr = {en:"Please select a text layer.", fr:"Veuillez sélectionner un calque texte."};
this.badSelLayerErr = this.noLayerErr;
this.paragraphTextErr = {en:"Paragraph text is not supported.", fr:"Le texte paragraphe n'est pas supporté."};
// UI strings and default settings
this.aboutBtnName = "?";
this.methodStName = {en:"Decompose into:", fr:"Décompose en:"};
this.methodLstChoices = {en:'["Characters", "Words", "Lines"]', fr:'["Caractères", "Mots", "Lignes"]'};
this.methodLstSelDflt = 0;
this.withExprRbName = {en:"Original position using expressions", fr:"Position originale avec expressions"};
this.withoutExprRbName = {en:"Approx. position without expressions", fr:"Position approx. sans expressions"};
this.useExprDfltVal = true;
this.runBtnName = {en:"Decompose", fr:"Décomposer"};
// internals
this.basedOnMode = { charactersExcludingSpaces:2, words:3, lines:4 };
this.splitInto = this.methodLstSelDflt;
this.useExprB = this.useExprDfltVal;
this.buildUI = function (thisObj)
{
// dockable panel or palette
var pal = (thisObj instanceof Panel) ? thisObj : new Window("palette", this.scriptTitle, undefined, {resizeable:false});
// resource specifications
var res =
"group { orientation:'column', alignment:['left','top'], alignChildren:['right','top'], \
gr1: Group { \
aboutBtn: Button { text:'" + this.aboutBtnName + "', preferredSize:[25,20] } \
}, \
gr2: Group { \
methodSt: StaticText { text:'" + utils.loc(this.methodStName) + "' }, \
methodLst: DropDownList { properties:{items:" + utils.loc(this.methodLstChoices) + "}, preferredSize:[110,-1] } \
}, \
gr3: Group { orientation:'column', alignChildren:['left','top'], \
withExpr: RadioButton { text:'" + utils.loc(this.withExprRbName) + "', value:'" + this.useExprDfltVal + "' }, \
withoutExpr: RadioButton { text:'" + utils.loc(this.withoutExprRbName) + "' } \
}, \
gr4: Group { orientation:'row', alignment:['fill','top'], \
runBtn: Button { text:'" + utils.loc(this.runBtnName) + "', alignment:['right','center'] } \
} \
}";
pal.gr = pal.add(res);
pal.gr.gr2.methodLst.selection = this.methodLstSelDflt;
// event callbacks
pal.gr.gr1.aboutBtn.onClick = function ()
{
utils.createAboutDlg(decomposeText.scriptAbout, decomposeText.scriptUsage);
};
pal.gr.gr2.methodLst.onChange = function ()
{
decomposeText.splitInto = this.selection.index;
};
pal.gr.gr3.withExpr.onClick = function ()
{
decomposeText.useExprB = this.value;
};
pal.gr.gr3.withoutExpr.onClick = function ()
{
decomposeText.useExprB = !this.value;
};
pal.gr.gr4.runBtn.onClick = function ()
{
decomposeText.decompose();
};
// show user interface
if (pal instanceof Window)
{
pal.center();
pal.show();
}
else
{
pal.layout.layout(true);
}
};
// Determines whether the active item is a composition
this.checkActiveItem = function ()
{
return !(app.project.activeItem instanceof CompItem);
};
// Determines whether a given layer is a text layer
this.checkLayerType = function (layer)
{
return !(layer instanceof TextLayer);
}
// Functional part of the script: places each character (or word or lines) of the selected text layer on its own layer
this.decompose = function ()
{
try
{
var comp = app.project.activeItem;
var err = this.noCompErr;
if (this.checkActiveItem(comp)) throw(err);
var layer = comp.selectedLayers[0];
var err = this.noLayerErr;
if (!layer) throw(err);
var err = this.badSelLayerErr;
if (this.checkLayerType(layer)) throw(err);
var err = this.paragraphTextErr;
if (layer.property("ADBE Text Properties").property("ADBE Text Document").value.boxText) throw(err);
var textPos = layer.position.value;
var textString = layer.sourceText.value.toString();
var textBox = layer.sourceRectAtTime(comp.time, false);
var textJust = layer.property("ADBE Text Properties").property("ADBE Text Document").value.justification;
var textOffset = 0; // left
if (textJust == ParagraphJustification.CENTER_JUSTIFY) // center
textOffset -= textBox.width / 2;
else if (textJust == ParagraphJustification.RIGHT_JUSTIFY) // right
textOffset -= textBox.width;
var textStartPos = textPos + textOffset;
var lastLength = 0;
app.beginUndoGroup(this.scriptTitle);
switch (this.splitInto)
{
case 0: // split into characters
{
var numSkips = 0;
for (var charId = 0; charId < textString.length; charId++)
{
var character = textString.charAt(charId);
if (character.match(/\s+/))
{
numSkips++;
continue;
}
var newLayer = layer.duplicate();
newLayer.name = character;
if (this.useExprB)
{
var animator = newLayer.property("ADBE Text Properties").property("ADBE Text Animators").addProperty("ADBE Text Animator");
var opacityProp = animator.property("ADBE Text Animator Properties").addProperty("ADBE Text Opacity");
var expressionSelector = animator.property("ADBE Text Selectors").addProperty("ADBE Text Expressible Selector");
opacityProp.setValue(0);
expressionSelector.property("ADBE Text Expressible Amount").expression = "selectorValue * (textIndex != " + (charId+1-numSkips) + ");";
var basedOnProp = animator.property("ADBE Text Selectors").property("ADBE Text Expressible Selector").property("ADBE Text Range Type2");
basedOnProp.setValue(this.basedOnMode.charactersExcludingSpaces);
}
else
{
newLayer.sourceText.setValue(character);
var newPos = textStartPos + [textBox.width * (charId / textString.length), 0, 0];
newLayer.position.setValue(newPos);
}
}
break;
}
case 1: // split into words
{
var words = textString.split(/\s+/);
for (var wordId = 0; wordId < words.length; wordId++)
{
var word = words[wordId];
var newLayer = layer.duplicate();
newLayer.name = word;
if (this.useExprB)
{
var animator = newLayer.property("ADBE Text Properties").property("ADBE Text Animators").addProperty("ADBE Text Animator");
var opacityProp = animator.property("ADBE Text Animator Properties").addProperty("ADBE Text Opacity");
var expressionSelector = animator.property("ADBE Text Selectors").addProperty("ADBE Text Expressible Selector");
opacityProp.setValue(0);
expressionSelector.property("ADBE Text Expressible Amount").expression = "selectorValue * (textIndex != " + (wordId+1) + ");";
var basedOnProp = animator.property("ADBE Text Selectors").property("ADBE Text Expressible Selector").property("ADBE Text Range Type2");
basedOnProp.setValue(this.basedOnMode.words);
}
else
{
newLayer.sourceText.setValue(word);
var wordWidth = newLayer.sourceRectAtTime(comp.time, false).width;
if (wordId > 0)
{
lastLength += 25; // accounts for spaces
}
var newPos = textStartPos + [lastLength, 0, 0];
newLayer.position.setValue(newPos);
lastLength += wordWidth;
}
}
break;
}
case 2: // split into lines
{
var lines = textString.split(/\r+/);
for (var lineId = 0; lineId < lines.length; lineId++)
{
var line = lines[lineId];
var newLayer = layer.duplicate();
newLayer.name = line;
if (this.useExprB)
{
var animator = newLayer.property("ADBE Text Properties").property("ADBE Text Animators").addProperty("ADBE Text Animator");
var opacityProp = animator.property("ADBE Text Animator Properties").addProperty("ADBE Text Opacity");
var expressionSelector = animator.property("ADBE Text Selectors").addProperty("ADBE Text Expressible Selector");
opacityProp.setValue(0);
expressionSelector.property("ADBE Text Expressible Amount").expression = "selectorValue * (textIndex != " + (lineId+1) + ");";
var basedOnProp = animator.property("ADBE Text Selectors").property("ADBE Text Expressible Selector").property("ADBE Text Range Type2");
basedOnProp.setValue(this.basedOnMode.lines);
}
else
{
newLayer.sourceText.setValue(line);
var lineHeight = newLayer.sourceRectAtTime(comp.time, false).height;
var newPos = textStartPos + [0, lastLength, 0];
newLayer.position.setValue(newPos);
lastLength += lineHeight + 25; // accounts for leading
}
}
break;
}
default:
break;
}
layer.enabled = false;
layer.selected = false;
app.endUndoGroup();
}
catch(err)
{
utils.throwErr(err);
}
};
this.run = function (thisObj)
{
this.buildUI(thisObj);
};
}
// utilities
function DecomposeTextUtils()
{
var utils = this;
this.loc = function (str)
{
var lang = parseFloat(app.version) < 9 ? $.locale : app.isoLanguage;
return lang.toLowerCase().match("fr") ? str.fr : str.en;
};
this.throwErr = function (err)
{
var title = $.fileName.substring($.fileName.lastIndexOf("/")+1, $.fileName.lastIndexOf("."));
alert(this.loc(err), title, true);
};
this.createAboutDlg = function (aboutStr, usageStr)
{
eval(unescape('%09%09%76%61%72%20%64%6C%67%20%3D%20%6E%65%77%20%57%69%6E%64%6F%77%28%22%64%69%61%6C%6F%67%22%2C%20%22%41%62%6F%75%74%22%29%3B%0A%09%20%20%20%20%20%20%09%20%20%20%20%20%20%20%09%0A%09%20%20%20%20%76%61%72%20%72%65%73%20%3D%0A%09%09%22%67%72%6F%75%70%20%7B%20%6F%72%69%65%6E%74%61%74%69%6F%6E%3A%27%63%6F%6C%75%6D%6E%27%2C%20%61%6C%69%67%6E%6D%65%6E%74%3A%5B%27%66%69%6C%6C%27%2C%27%66%69%6C%6C%27%5D%2C%20%61%6C%69%67%6E%43%68%69%6C%64%72%65%6E%3A%5B%27%66%69%6C%6C%27%2C%27%66%69%6C%6C%27%5D%2C%20%5C%0A%09%09%09%70%6E%6C%3A%20%50%61%6E%65%6C%20%7B%20%74%79%70%65%3A%27%74%61%62%62%65%64%70%61%6E%65%6C%27%2C%20%5C%0A%09%09%09%09%61%62%6F%75%74%54%61%62%3A%20%50%61%6E%65%6C%20%7B%20%74%79%70%65%3A%27%74%61%62%27%2C%20%74%65%78%74%3A%27%44%65%73%63%72%69%70%74%69%6F%6E%27%2C%20%5C%0A%09%09%09%09%09%61%62%6F%75%74%45%74%3A%20%45%64%69%74%54%65%78%74%20%7B%20%74%65%78%74%3A%27%22%20%2B%20%74%68%69%73%2E%6C%6F%63%28%61%62%6F%75%74%53%74%72%29%20%2B%20%22%27%2C%20%70%72%65%66%65%72%72%65%64%53%69%7A%65%3A%5B%33%36%30%2C%32%30%30%5D%2C%20%70%72%6F%70%65%72%74%69%65%73%3A%7B%6D%75%6C%74%69%6C%69%6E%65%3A%74%72%75%65%7D%20%7D%20%5C%0A%09%09%09%09%7D%2C%20%5C%0A%09%09%09%09%75%73%61%67%65%54%61%62%3A%20%50%61%6E%65%6C%20%7B%20%74%79%70%65%3A%27%74%61%62%27%2C%20%74%65%78%74%3A%27%55%73%61%67%65%27%2C%20%5C%0A%09%09%09%09%09%75%73%61%67%65%45%74%3A%20%45%64%69%74%54%65%78%74%20%7B%20%74%65%78%74%3A%27%22%20%2B%20%74%68%69%73%2E%6C%6F%63%28%75%73%61%67%65%53%74%72%29%20%2B%20%22%27%2C%20%70%72%65%66%65%72%72%65%64%53%69%7A%65%3A%5B%33%36%30%2C%32%30%30%5D%2C%20%70%72%6F%70%65%72%74%69%65%73%3A%7B%6D%75%6C%74%69%6C%69%6E%65%3A%74%72%75%65%7D%20%7D%20%5C%0A%09%09%09%09%7D%20%5C%0A%09%09%09%7D%2C%20%5C%0A%09%09%09%62%74%6E%73%3A%20%47%72%6F%75%70%20%7B%20%6F%72%69%65%6E%74%61%74%69%6F%6E%3A%27%72%6F%77%27%2C%20%61%6C%69%67%6E%6D%65%6E%74%3A%5B%27%66%69%6C%6C%27%2C%27%62%6F%74%74%6F%6D%27%5D%2C%20%5C%0A%09%09%09%09%6F%74%68%65%72%53%63%72%69%70%74%73%42%74%6E%3A%20%42%75%74%74%6F%6E%20%7B%20%74%65%78%74%3A%27%4F%74%68%65%72%20%53%63%72%69%70%74%73%2E%2E%2E%27%2C%20%61%6C%69%67%6E%6D%65%6E%74%3A%5B%27%6C%65%66%74%27%2C%27%63%65%6E%74%65%72%27%5D%20%7D%2C%20%5C%0A%09%09%09%09%6F%6B%42%74%6E%3A%20%42%75%74%74%6F%6E%20%7B%20%74%65%78%74%3A%27%4F%6B%27%2C%20%61%6C%69%67%6E%6D%65%6E%74%3A%5B%27%72%69%67%68%74%27%2C%27%63%65%6E%74%65%72%27%5D%20%7D%20%5C%0A%09%09%09%7D%20%5C%0A%09%09%7D%22%3B%20%0A%09%09%64%6C%67%2E%67%72%20%3D%20%64%6C%67%2E%61%64%64%28%72%65%73%29%3B%0A%09%09%0A%09%09%64%6C%67%2E%67%72%2E%70%6E%6C%2E%61%62%6F%75%74%54%61%62%2E%61%62%6F%75%74%45%74%2E%6F%6E%43%68%61%6E%67%65%20%3D%20%64%6C%67%2E%67%72%2E%70%6E%6C%2E%61%62%6F%75%74%54%61%62%2E%61%62%6F%75%74%45%74%2E%6F%6E%43%68%61%6E%67%69%6E%67%20%3D%20%66%75%6E%63%74%69%6F%6E%20%28%29%0A%09%09%7B%0A%09%09%09%74%68%69%73%2E%74%65%78%74%20%3D%20%75%74%69%6C%73%2E%6C%6F%63%28%61%62%6F%75%74%53%74%72%29%2E%72%65%70%6C%61%63%65%28%2F%5C%5C%72%2F%67%2C%20%27%5C%72%27%29%3B%0A%09%09%7D%3B%0A%09%09%0A%09%09%64%6C%67%2E%67%72%2E%70%6E%6C%2E%75%73%61%67%65%54%61%62%2E%75%73%61%67%65%45%74%2E%6F%6E%43%68%61%6E%67%65%20%3D%20%64%6C%67%2E%67%72%2E%70%6E%6C%2E%75%73%61%67%65%54%61%62%2E%75%73%61%67%65%45%74%2E%6F%6E%43%68%61%6E%67%69%6E%67%20%3D%20%66%75%6E%63%74%69%6F%6E%20%28%29%0A%09%09%7B%0A%09%09%09%74%68%69%73%2E%74%65%78%74%20%3D%20%75%74%69%6C%73%2E%6C%6F%63%28%75%73%61%67%65%53%74%72%29%2E%72%65%70%6C%61%63%65%28%2F%5C%5C%72%2F%67%2C%20%27%5C%72%27%29%2E%72%65%70%6C%61%63%65%28%2F%5C%5C%27%2F%67%2C%20%22%27%22%29%3B%0A%09%09%7D%3B%0A%09%09%09%0A%09%09%64%6C%67%2E%67%72%2E%62%74%6E%73%2E%6F%74%68%65%72%53%63%72%69%70%74%73%42%74%6E%2E%6F%6E%43%6C%69%63%6B%20%3D%20%66%75%6E%63%74%69%6F%6E%20%28%29%0A%09%09%7B%0A%09%09%09%76%61%72%20%63%6D%64%20%3D%20%22%22%3B%0A%09%09%09%76%61%72%20%75%72%6C%20%3D%20%22%68%74%74%70%3A%2F%2F%61%65%73%63%72%69%70%74%73%2E%63%6F%6D%2F%61%75%74%68%6F%72%73%2F%6D%2D%70%2F%6E%61%62%2F%22%3B%0A%09%0A%09%09%09%69%66%20%28%24%2E%6F%73%2E%69%6E%64%65%78%4F%66%28%22%57%69%6E%22%29%20%21%3D%20%2D%31%29%0A%09%09%09%7B%0A%09%20%20%20%20%20%20%20%20%09%69%66%20%28%46%69%6C%65%28%22%43%3A%2F%50%72%6F%67%72%61%6D%20%46%69%6C%65%73%2F%4D%6F%7A%69%6C%6C%61%20%46%69%72%65%66%6F%78%2F%66%69%72%65%66%6F%78%2E%65%78%65%22%29%2E%65%78%69%73%74%73%29%0A%09%09%09%09%09%63%6D%64%20%2B%3D%20%22%43%3A%2F%50%72%6F%67%72%61%6D%20%46%69%6C%65%73%2F%4D%6F%7A%69%6C%6C%61%20%46%69%72%65%66%6F%78%2F%66%69%72%65%66%6F%78%2E%65%78%65%20%22%20%2B%20%75%72%6C%3B%0A%09%09%09%09%65%6C%73%65%20%69%66%20%28%46%69%6C%65%28%22%43%3A%2F%50%72%6F%67%72%61%6D%20%46%69%6C%65%73%20%28%78%38%36%29%2F%4D%6F%7A%69%6C%6C%61%20%46%69%72%65%66%6F%78%2F%66%69%72%65%66%6F%78%2E%65%78%65%22%29%2E%65%78%69%73%74%73%29%0A%09%09%09%09%09%63%6D%64%20%2B%3D%20%22%43%3A%2F%50%72%6F%67%72%61%6D%20%46%69%6C%65%73%20%28%78%38%36%29%2F%4D%6F%7A%69%6C%6C%61%20%46%69%72%65%66%6F%78%2F%66%69%72%65%66%6F%78%2E%65%78%65%20%22%20%2B%20%75%72%6C%3B%0A%09%09%09%09%65%6C%73%65%0A%09%09%09%09%09%63%6D%64%20%2B%3D%20%22%43%3A%2F%50%72%6F%67%72%61%6D%20%46%69%6C%65%73%2F%49%6E%74%65%72%6E%65%74%20%45%78%70%6C%6F%72%65%72%2F%69%65%78%70%6C%6F%72%65%2E%65%78%65%20%22%20%2B%20%75%72%6C%3B%0A%09%09%09%7D%0A%09%09%09%65%6C%73%65%0A%09%09%09%09%63%6D%64%20%2B%3D%20%22%6F%70%65%6E%20%5C%22%22%20%2B%20%75%72%6C%20%2B%20%22%5C%22%22%3B%20%20%20%20%20%20%20%20%20%0A%09%09%09%74%72%79%0A%09%09%09%7B%0A%09%09%09%09%73%79%73%74%65%6D%2E%63%61%6C%6C%53%79%73%74%65%6D%28%63%6D%64%29%3B%0A%09%09%09%7D%0A%09%09%09%63%61%74%63%68%28%65%29%0A%09%09%09%7B%0A%09%09%09%09%61%6C%65%72%74%28%65%29%3B%0A%09%09%09%7D%0A%09%09%7D%3B%0A%09%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%09%09%64%6C%67%2E%67%72%2E%62%74%6E%73%2E%6F%6B%42%74%6E%2E%6F%6E%43%6C%69%63%6B%20%3D%20%66%75%6E%63%74%69%6F%6E%20%28%29%20%0A%09%09%7B%0A%09%09%09%64%6C%67%2E%63%6C%6F%73%65%28%29%3B%20%0A%09%09%7D%3B%0A%09%20%20%20%20%20%20%20%0A%09%09%64%6C%67%2E%63%65%6E%74%65%72%28%29%3B%0A%09%09%64%6C%67%2E%73%68%6F%77%28%29%3B'));
};
}
// run script
new DecomposeText().run(this);
```
- 脚本管理器
- 读取文件夹内文件
- 层层时间线偏移Sequencer.jsx
- 层层随机时间偏移
- 文字分离char_separate_1.3
- 分解文字 把一个文字层分成若干个文字层
- 快速导入Smart Import
- 查找与替换字符 Find and Replace Text.jsx
- 层改名Selected_Layers_Renamer.jsx
- 创建灯光为选择的三维层.jsx
- 创建摄像机为选择的三维图层.jsx
- 创建调节图层CreateTrimmedAdjustmentLayer.jsx
- 创建调节图层多个CreateSeveralTrimmedAdjustmentLayers.jsx
- 创建一个空物体到选择的层Add Parented Null to Selected Layers.jsx
- 文字分离DecomposeText
- 修改渲染输出文件位置Change Render Locations
- AE脚本读取txt文档并写入数组
- AE脚本把数组写入到txt文档中
- AE提取字幕脚本
- AE批量用txt内容替换字幕脚本