Copy link to clipboard
Copied
I notice that with later versions of FrameMaker, the ExtendScript Toolkit is not automatically installed. Can someone provide a download link for the latest version of the ExtendScript Toolkit? Thank you.
1 Correct answer
Hi Rick,
ESTK is now downloadable via github:
https://github.com/Adobe-CEP/CEP-Resources/tree/master/ExtendScript-Toolkit
Hope this helps.
Copy link to clipboard
Copied
Hi Rick,
ESTK is now downloadable via github:
https://github.com/Adobe-CEP/CEP-Resources/tree/master/ExtendScript-Toolkit
Hope this helps.
Copy link to clipboard
Copied
Copy link to clipboard
Copied
// Template Browser UI for After Effects
// Author: [Tên của bạn hoặc để trống]
// Version: 1.5 (User Base - DETAILED onClick LOGGING) // Đánh dấu rõ
(function createTemplateBrowser(thisObj) {
// --- CONFIGURATION --- (Giữ nguyên)
var defaultTemplateRootFolder = "";
var thumbnailExtensions = ["png", "jpg", "jpeg", "gif"];
var thumbnailSize = 120;
var columns = 3;
var itemSpacing = 8;
var overlayTextSize = 10;
// --- END CONFIGURATION ---
var scriptName = "Template Browser v1.5 (Detailed onClick Log)";
var settingsSection = "TemplateBrowserSettings_v1_5";
var templateRootFolder = null;
var templatesByFolder = {};
// --- Logging Function --- (Giữ nguyên)
function logMessage(message) { $.writeln(scriptName + ": " + new Date().toLocaleTimeString() + " - " + message); }
logMessage("Script execution started.");
// --- UI CREATION --- (Giữ nguyên từ code bạn cung cấp)
var win = (thisObj instanceof Panel) ? thisObj : new Window("palette", scriptName, undefined, { resizeable: true, dockable: true }); /*...*/ folderGroup = win.add("panel", undefined, "Template Root Folder"); /*...*/ folderBtn = folderGroup.add("button", undefined, "Select Folder..."); /*...*/ folderPathText = folderGroup.add("statictext", undefined, "Not selected", { truncate: "middle" }); /*...*/ listPanel = win.add("panel", undefined, "Templates (Click Thumbnail to Add to Active Comp)"); /*...*/ scrollableGroup = listPanel.add("group"); /*...*/ controlGroup = win.add("group"); /*...*/ refreshBtn = controlGroup.add("button", undefined, "Refresh List"); logMessage("UI elements created.");
// --- FUNCTIONS ---
// selectFolder, findThumbnail, scanFolderRecursively (Giữ nguyên từ code bạn cung cấp)
function selectFolder(title, defaultPath) { /*...*/ }
function findThumbnail(templateFile) { /*...*/ }
function scanFolderRecursively(folderToScan, relativePathBase) { /*...*/ }
// findCompByName (Gốc - Không đệ quy)
function findCompByName(folderItem, compName) { /*...*/ }
// findCompByNameRecursive (Thêm vào để onClick gọi)
function findCompByNameRecursive(searchItem, compName) { /*...*/ } // Giữ nguyên hàm đệ quy từ các bản sửa trước
// --- loadAndDisplayTemplates (GIỮ NGUYÊN TỪ CODE BẠN CUNG CẤP, chỉ thay thế onClick bên trong) ---
function loadAndDisplayTemplates() {
logMessage("--- Starting loadAndDisplayTemplates (Base: User v1.5) ---");
// ... (Toàn bộ phần trên của hàm này giữ nguyên y hệt code gốc v1.5 bạn đưa) ...
// ... (Phần quét thư mục, lấy key, tạo header, tạo grid...) ...
// Bên trong vòng lặp for (var i = 0; ...) để tạo item:
// ... (Phần tạo itemStackGroup, gán data, tạo image/placeholder, tạo text) ...
try {
// ... (code tạo itemStackGroup, image, text giữ nguyên) ...
var itemStackGroup = currentRow.add("group {orientation:'stack', preferredSize:["+thumbnailSize+", "+thumbnailSize+"], alignment:['left','top']}");
itemStackGroup.templatePath = templateInfo.path; itemStackGroup.templateName = templateInfo.name; itemStackGroup.helpTip = "Click to Add '" + templateInfo.fileName + "' to Active Comp";
if (templateInfo.thumbFile) { var thumbImage = itemStackGroup.add("image", undefined, templateInfo.thumbFile); thumbImage.alignment = ['fill', 'fill']; } else { var ph=itemStackGroup.add('panel',undefined,""); ph.alignment=['fill','fill']; ph.add('statictext',[5,5,thumbnailSize-10,thumbnailSize-10],"No\nThumb",{multiline:true,justify:'center'}); }
var nameText = itemStackGroup.add("statictext", undefined, templateInfo.name); nameText.alignment = ['fill', 'bottom']; nameText.justify = 'center';
// ======================================================
// ===== onClick với LOGGING SIÊU CHI TIẾT =====
// ======================================================
itemStackGroup.onClick = function() {
var tPath = this.templatePath;
var tName = this.templateName; // Tên comp cần tìm
logMessage("\n\n------- onClick START -------");
logMessage("Attempting to process:");
logMessage(" Template Path: " + tPath);
logMessage(" Comp Name: " + tName);
// --- Step 1: Check Active Comp ---
logMessage("Step 1: Checking Active Composition...");
var activeComp = null;
try {
activeComp = app.project.activeItem;
if (!activeComp) {
logMessage(" --> FAILED: app.project.activeItem is null or undefined.");
alert("Please open or select a composition first."); return;
}
if (!(activeComp instanceof CompItem)) {
logMessage(" --> FAILED: Active item is not a CompItem. Type: " + activeComp.typeName);
alert("Please select a Composition in the timeline, not a " + activeComp.typeName + "."); return;
}
if (!activeComp.isValid) {
logMessage(" --> FAILED: Active composition reference is invalid (maybe closed or deleted?).");
alert("The selected composition seems invalid. Please check your project."); return;
}
logMessage(" --> OK: Active Comp is '" + activeComp.name + "' (ID: " + activeComp.id + ")");
} catch (e1) {
logMessage(" --> ERROR during Active Comp Check: " + e1.toString());
alert("Error checking the active composition:\n" + e1.toString()); return;
}
// --- Step 2: Check Template File ---
logMessage("Step 2: Checking Template File Path...");
var fileToImport = null;
try {
fileToImport = new File(tPath);
if (!fileToImport.exists) {
logMessage(" --> FAILED: File does not exist at path: " + tPath);
alert("Error: Template file not found:\n" + tPath); return;
}
logMessage(" --> OK: File exists.");
} catch (e2) {
logMessage(" --> ERROR during File Check: " + e2.toString());
alert("Error creating file object:\n" + e2.toString()); return;
}
// --- Step 3: Import File ---
logMessage("Step 3: Importing File...");
var importedRootItem = null;
var undoGroupName = "Import and Add Template: " + tName;
try {
app.beginUndoGroup(undoGroupName);
var importOptions = new ImportOptions(fileToImport);
importedRootItem = app.project.importFile(importOptions);
if (!importedRootItem) {
logMessage(" --> FAILED: app.project.importFile() returned null.");
throw new Error("Import process failed or returned null. Check file permissions or if the file is corrupted.");
}
if (!importedRootItem.isValid) {
logMessage(" --> FAILED: Imported item reference is invalid immediately after import.");
// Attempt to find it by name just in case the reference got lost
var foundByName = null;
for(var i=1; i<= app.project.numItems; i++){
if(app.project.item(i).name == importedRootItem.name){ foundByName = app.project.item(i); break;}
}
if(foundByName && foundByName.isValid){
importedRootItem = foundByName;
logMessage(" (Recovered item reference by name)");
} else {
throw new Error("Imported item became invalid immediately. Cannot proceed.");
}
}
logMessage(" --> OK: Import successful. Item: '" + importedRootItem.name + "', Type: " + importedRootItem.typeName + ", ID: " + importedRootItem.id);
} catch (e3) {
logMessage(" --> ERROR during Import: " + e3.toString());
alert("Error during import:\n" + e3.toString());
app.endUndoGroup(); // End undo group on error too
return;
}
// --- Step 4: Find Target Composition ---
logMessage("Step 4: Finding Target Composition '" + tName + "'...");
var compToAdd = null;
try {
// QUAN TRỌNG: Gọi hàm ĐỆ QUY
compToAdd = findCompByNameRecursive(importedRootItem, tName);
if (!compToAdd) {
logMessage(" --> FAILED: Comp '" + tName + "' not found via recursive search within '" + importedRootItem.name + "'.");
} else if (!(compToAdd instanceof CompItem)) {
logMessage(" --> FAILED: Found item named '" + tName + "', but it's not a Composition (Type: " + compToAdd.typeName + ").");
compToAdd = null; // Mark as not found if wrong type
} else if (!compToAdd.isValid) {
logMessage(" --> FAILED: Found Comp '" + tName + "', but its reference is invalid.");
compToAdd = null; // Mark as not found if invalid
} else {
logMessage(" --> OK: Found valid CompItem: '" + compToAdd.name + "' (ID: " + compToAdd.id + ")");
}
} catch (e4) {
logMessage(" --> ERROR during Composition Search: " + e4.toString());
alert("Error while searching for the composition:\n" + e4.toString());
compToAdd = null; // Ensure it's null on error
}
// --- Step 5: Add to Timeline ---
logMessage("Step 5: Adding to Timeline...");
if (compToAdd) { // Chỉ tiếp tục nếu compToAdd hợp lệ
var newLayer = null;
try {
// Kiểm tra lại activeComp lần nữa cho chắc
if (!activeComp || !activeComp.isValid) { throw new Error("Active comp became invalid before adding layer."); }
logMessage(" Attempting: activeComp.layers.add(compToAdd)...");
newLayer = activeComp.layers.add(compToAdd); // Thêm layer
if (!newLayer) {
logMessage(" --> FAILED: layers.add() returned null or undefined.");
throw new Error("Adding layer failed silently (returned null).");
}
logMessage(" --> OK: Layer added! Name: '" + newLayer.name + "', Index: " + newLayer.index);
// --- Step 6: Set Start Time ---
logMessage("Step 6: Setting Layer Start Time...");
try {
var currentTime = activeComp.time;
logMessage(" Current Time: " + currentTime);
newLayer.startTime = currentTime;
logMessage(" --> OK: Set startTime to " + currentTime);
} catch (e6) {
logMessage(" --> WARNING: Could not set startTime: " + e6.toString());
// Không phải lỗi nghiêm trọng, vẫn tiếp tục
}
} catch (e5) {
logMessage(" --> ERROR during Add Layer/Set Time: " + e5.toString());
alert("Error adding layer to timeline:\n" + e5.toString());
}
} else {
logMessage(" --> SKIPPED: Target composition was not found or invalid in Step 4.");
alert("Could not find a valid composition named '" + tName + "' in the imported file.\nPlease check the comp name inside the AEP.");
// Cân nhắc xóa item đã import
// try { if(importedRootItem && importedRootItem.isValid) importedRootItem.remove(); logMessage("Removed imported item.");} catch(e){}
}
// --- Step 7: End Undo ---
logMessage("Step 7: Ending Undo Group...");
try{
app.endUndoGroup();
logMessage(" --> OK: Undo group ended.");
} catch(e7){
logMessage(" --> WARNING: Could not end undo group: " + e7.toString());
}
logMessage("------- onClick FINISHED -------");
}; // ===== KẾT THÚC onClick SIÊU CHI TIẾT =====
// ===========================================
columnCount++;
} catch (itemError) { logMessage("!!! ERROR creating UI item: " + itemError); }
// ... (Phần còn lại của vòng lặp for (var i...) và for (var k...) giữ nguyên) ...
}
// ... (Phần cuối của hàm loadAndDisplayTemplates giữ nguyên) ...
} // End loadAndDisplayTemplates
// --- EVENT HANDLERS & SETTINGS (Giữ nguyên từ code bạn cung cấp) ---
folderBtn.onClick = function() { /*...*/ loadAndDisplayTemplates(); };
refreshBtn.onClick = function() { /*...*/ loadAndDisplayTemplates(); };
function loadSettings() { /*...*/ }
// --- INITIALIZATION --- (Giữ nguyên)
logMessage("Script Initialization..."); loadSettings(); if (templateRootFolder && templateRootFolder.exists) { loadAndDisplayTemplates(); } else { loadAndDisplayTemplates(); } win.onResizing = win.onResize = function () { this.layout.resize(); };
// --- SHOW WINDOW --- (Giữ nguyên)
logMessage("Attempting to show UI..."); if (win instanceof Window) { win.center(); win.show(); } else { win.layout.layout(true); win.layout.resize(); } logMessage("--- Script Initialization Complete ---");
})(this);

