├── README.md └── GoodBoyLabels.js /README.md: -------------------------------------------------------------------------------- 1 | # Get-Layers-Label-Colors-using-CEP 2 | image 3 | 4 | _Note: This is for CEP panels. I am not using ExtendScript here. 5 | If you want to use ExtendScript, you might want to check out this code by [stibinator](https://github.com/stibinator/AEScripts/blob/master/ScriptUI%20Panels/simplify%20duik%20icons.jsx#L283)._ 6 | 7 | _Now works on both macOS and windows._ 8 | 9 | ### Usage 10 | call the function: 11 | ``` 12 | getLabelsInfo(); 13 | ``` 14 | 15 | ### return 16 | returns an object with two arrays, "colors" and "names". 17 | Both arrays are sorted using the label ID. 18 | 19 | Example: 20 | ```js 21 | { 22 | colors: (17) ["", "B53838", "E4D84c", "A9CBC7", "E5BCC9", "A9A9CA", "E7C19E", "B3C7B3", "677dE0", "4aA44c", "8E2c9A", "E8920D", "7F452a", "F46dD6", "3dA2A5", "A89677", "1E401E"] 23 | names: (17) ["", "Red", "Yellow", "Aqua", "Pink", "Lavender", "Peach", "Sea Foam", "Blue", "Green", "Purple", "Orange", "Brown", "Fuchsia", "Cyan", "Sandstone", "Dark Green"] 24 | } 25 | ``` 26 | 27 | 28 | 29 | # What and Why 30 | Label colors in Ae Preferences look like this: 31 | ``` 32 | ["Label Preference Color Section 5"] 33 | "Label Color ID 2 # 1" = FFB5"88" 34 | "Label Color ID 2 # 10" = FF8E","9A 35 | "Label Color ID 2 # 11" = FFE8920D 36 | "Label Color ID 2 # 12" = FF7F"E*" 37 | "Label Color ID 2 # 13" = FFF4"m"D6 38 | "Label Color ID 2 # 14" = FF"="A2A5 39 | "Label Color ID 2 # 15" = FFA896"w" 40 | "Label Color ID 2 # 16" = FF1E"@"1E 41 | "Label Color ID 2 # 2" = FFE4D8"L" 42 | "Label Color ID 2 # 3" = FFA9CBC7 43 | "Label Color ID 2 # 4" = FFE5BCC9 44 | "Label Color ID 2 # 5" = FFA9A9CA 45 | "Label Color ID 2 # 6" = FFE7C19E 46 | "Label Color ID 2 # 7" = FFB3C7B3 47 | "Label Color ID 2 # 8" = FF"g}"E0 48 | "Label Color ID 2 # 9" = FF"J"A4"L" 49 | ``` 50 | 51 | After a lot of google searches, I found a comment by RenderTom pointing out that the values are a weird mix of ASCII and hex. (The parts inside the quotation marks are ASCII). **This repository finds the preference file, reads it, finds that section, and converts each value into propper hex.** 52 | 53 | 54 | 55 | The first element is empty because there is no label for the number 0, but that's okay since the `layer.label` [attribute](https://ae-scripting.docsforadobe.dev/layers/layer.html#layer-label) in ExtendScript returns an index that matches that convention. 56 | 57 | ### requirements 58 | requires [using nodejs as part of your project](https://www.davidebarranca.com/2015/12/html-panel-tips-19-cc2015-1-cep6-1-node-js-fixes/). 59 | 60 | ### limitations 61 | - Will not work on After-Effects beta. If you want it to work, make sure the path to the preferences file says "After-Effects (Beta)" instad of "After-Effects". 62 | - Will only work in English After-Effects because the preferences file name is language based (can be fixed by getting the file with the suffix "general.txt") 63 | If you do, feel free to contirbute to this repo with solutions. 64 | 65 | 66 | # Support 67 | If this helped you [consider buying one of my tools](https://www.goodboy.ninja/) or sharing this elsewhere where people might need it. 68 | 69 | Good Boy Ninja 70 | 71 | 72 | . 73 | . 74 | . 75 | 76 | _related keywords that may have brought you here: 77 | Label Color ID 2, .getPrefAsString(), RGB-HEX-ASCII , after effects getprefasstring label, Scripting: Retrieving Label Color from Preferences,Reading the label colors from preferences file, Get Label colors from Pref , ExtendScript, JavaScript, Labels_ 78 | 79 | -------------------------------------------------------------------------------- /GoodBoyLabels.js: -------------------------------------------------------------------------------- 1 | // main function 2 | function getLabelsInfo() { 3 | 4 | const result = { 5 | names: Array(17).fill("#000000"), 6 | colors: Array(17).fill("Black"), 7 | }; 8 | 9 | // requires nodejs to read the preference file 10 | const fs = cep_node.require('fs'); 11 | const path = cep_node.require('path'); 12 | const cs = new CSInterface(); 13 | 14 | // check if macOS or windows 15 | const osName = cs.getOSInformation().toLowerCase(); 16 | const isMacOS = osName.indexOf('windows') > -1 ? false : true; 17 | 18 | let version = cs.getHostEnvironment().appVersion; 19 | version = version.split(".")[0] + "." + version.split(".")[1]; 20 | let userDataFolder = cs.getSystemPath(SystemPath.USER_DATA); 21 | let prefsFolder = isMacOS ? path.join(path.dirname(userDataFolder), "Preferences", "Adobe", "After Effects", version) : path.join(userDataFolder, "Adobe", "After Effects", version); 22 | let prefsFile = path.join(prefsFolder, `Adobe After Effects ${version} Prefs-indep-general.txt`); 23 | 24 | if (!fs.existsSync(prefsFolder) || !fs.existsSync(prefsFile)) { 25 | console.warn("Failed to get label colors? Returning fallback result."); 26 | return result; 27 | } 28 | 29 | // read the file using nodejs and find the right sections for both label colors and label names 30 | let prefsTxt = fs.readFileSync(prefsFile, "utf8"); 31 | let hexSection = prefsTxt.substring(prefsTxt.indexOf(`"Label Color ID 2 # 1"`), prefsTxt.length); 32 | hexSection = hexSection.substring(0, hexSection.indexOf('[') - 1); 33 | let namesSection = prefsTxt.substring(prefsTxt.indexOf(`"Label Preference Text Section 7"`), prefsTxt.length); 34 | namesSection = namesSection.substring(namesSection.indexOf('['), namesSection.indexOf(']') + 1); 35 | 36 | 37 | // the names section and the hex section are really similar but have small differences. Let's parst them both together and make up for the variations as we go. 38 | let raw = Array(17).fill().map(i => ({})); 39 | [hexSection, namesSection].forEach(section => { 40 | // break to lines 41 | let isHexSection = section === hexSection; 42 | let linesSeperator = isHexSection ? '"Label Color ID ' : '"Label Text ID '; 43 | let lines = section.split(linesSeperator); 44 | let key = isHexSection ? "value" : "name"; 45 | 46 | // read from each line 47 | lines.forEach(line => { 48 | let hashIndex = line.indexOf('#'); 49 | let id = Number(line.substring(hashIndex + 1, line.indexOf('"', hashIndex + 1))); 50 | let value = line.substring(line.indexOf("= ") + 2, line.length).trim(); 51 | 52 | // for names, we also want to yeet the quotes 53 | if (!isHexSection) { 54 | value = value.replace(/['"]+/g, ''); 55 | } 56 | 57 | raw[id][key] = value; // register value or name in the raw array 58 | }); 59 | }); 60 | 61 | // fix them colors 62 | for (let i = 0; i < raw.length; i++) { 63 | let crntInfoSet = raw[i]; 64 | let id = i; 65 | let rawName = crntInfoSet["name"]; 66 | let rawColor = crntInfoSet["value"]; 67 | 68 | // raw color is weird. It's half HEX and half ASCII. 69 | // the part that's ASCII is inside quotation marks. 70 | // Let's convert it to hex 71 | 72 | const splits = rawColor.split('"'); 73 | const filteredIndexes = splits.map((s, i) => { 74 | if (i % 2 !== 0) return i; 75 | }).filter(i => i); 76 | splits.forEach((s, i) => { 77 | if (filteredIndexes.includes(i)) { 78 | splits[i] = ascii2hex(splits[i]); 79 | } 80 | }); 81 | const hexColor = splits.join('').substring(2); 82 | 83 | result.names[id] = rawName; 84 | result.colors[id] = hexColor; 85 | 86 | } 87 | return result; 88 | 89 | }; 90 | 91 | 92 | // util function to convert ascii to hex 93 | function ascii2hex(str) { 94 | var arr = []; 95 | 96 | for (var i = 0, l = str.length; i < l; i++) { 97 | var hex = Number(str.charCodeAt(i)).toString(16); 98 | arr.push(hex); 99 | } 100 | return arr.join(''); 101 | } 102 | --------------------------------------------------------------------------------