AfterEffect(AE)插件是Adobe公司开发的特效制作软件,稳定快速的功能和特效,在视频制作领域使用非常广泛,本文向大家介绍如何在项目里进行命令行渲染功能源代码如下所示:,我来为大家科普一下关于ae morphings插件用法?以下内容希望对你有帮助!
ae morphings插件用法
AfterEffect(AE)插件是Adobe公司开发的特效制作软件,稳定快速的功能和特效,在视频制作领域使用非常广泛,本文向大家介绍如何在项目里进行命令行渲染功能。源代码如下所示:
// Command line renderer for After Effects.
// This function constructs an AECommandLineRenderer object.
// One and only one of these will be created to perform rendering tasks
// at the end of this file.
//
// The constructor has 3 sections:
// [1] define all the variable-type attributes used by this class;
// [2] define all the functions used by this class;
// [3] assign all the functions to be method-type attributes.
//
function AECommandLineRenderer()
{
// [1] define all the variable-type attributes used by this class
//
// Input before parsing
//
this.inArgs = null;
//
// Input after parsing
//
this.in_project_path = null;
this.in_teamproject_name = null;
this.in_comp_name = null;
this.in_rq_index = null;
this.in_RStemplate = null;
this.in_OMtemplate = null;
this.in_output_path = null;
this.in_logfile_path = null;
this.in_start_frame = null;
this.in_end_frame = null;
this.in_increment = null;
this.in_image_cache_percent = null;
this.in_max_mem_percent = null;
this.in_verbose_flag = null;
this.in_close_flag = null;
this.in_sound_flag = null;
this.in_port_address = null;
this.in_stop_on_missing_frame = true;
//
// Exit codes:
//
this.EXIT_OK = 0;
this.EXIT_FAILURE_CODE_FROM_APP = 1;
this.EXIT_SHOW_USAGE = 2;
this.EXIT_SYNTAX_ERROR = 3;
this.EXIT_SYNTAX_ERROR_USER_LOG = 4;
this.EXIT_OTHER_SCRIPTING_ERROR = 5;
this.EXIT_OTHER_SCRIPTING_ERROR_USER_LOG = 6;
this.EXIT_AERENDER_RUNTIME = 7;
this.EXIT_AERENDER_RUNTIME_USER_LOG = 8;
this.EXIT_AE_RUNTIME = 9;
this.EXIT_AE_RUNTIME_USER_LOG = 10;
this.EXIT_CANNOT_OPEN_SOCKET = 11;
this.EXIT_CODE_NO_LONGER_IN_USE = 12;
//
// Exit code message prefixes:
//
this.EXIT_MSG_PREFIX = new Array(
"", // EXIT_OK
"ERROR: ", // EXIT_FAILURE_CODE_FROM_APP
"USAGE: ", // EXIT_SHOW_USAGE
"SYNTAX ERROR: ", // EXIT_SYNTAX_ERROR
"SYNTAX ERROR: ", // EXIT_SYNTAX_ERROR_USER_LOG
"ERROR: ", // EXIT_OTHER_SCRIPTING_ERROR
"ERROR: ", // EXIT_OTHER_SCRIPTING_ERROR_USER_LOG
"ERROR: ", // EXIT_AERENDER_ERROR
"ERROR: ", // EXIT_AERENDER_ERROR_USER_LOG
"ERROR: ", // EXIT_AE_RUNTIME
"ERROR: ", // EXIT_AE_RUNTIME_USER_LOG
"ERROR: ", // EXIT_CANNOT_OPEN_SOCKET
"", // EXIT_CODE_NO_LONGER_IN_USE
);
//
// Messages:
//
this.MSG_NONE = "";
this.MSG_NOT_HANDLED_HERE = "reported by another script or AE runtime.";
this.MSG_SHOW_USAGE = "";
this.MSG_TRIED_TO_PARSE_UNDEFINED = "aerender tried to parse an undefined argument.";
this.MSG_UNDEFINED_VALUE_FOR_FLAG = "no value given for flag: ";
this.MSG_BAD_FLAG = "Illegal argument flag: ";
this.MSG_NO_PROJECT = "No project provided and no project open.";
this.MSG_BAD_VERBOSE_FLAG = "Bad value for -verbose.";
this.MSG_BAD_CLOSE_FLAG = "Bad value for -close.";
this.MSG_BAD_SOUND_FLAG = "Bad value for -sound.";
this.MSG_BAD_INCREMENT = "Bad value for -increment. Must be between 1 and 100, inclusive.";
this.MSG_COMP_NOT_FOUND = "No comp was found with the given name.";
this.MSG_RQINDEX_NOT_FOUND = "No render queue item was found with the given index.";
this.MSG_AE_RUNTIME = "Runtime error in After Effects.";
this.MSG_ADDING_TO_RQ = "PROGRESS: Adding specified comp to Render Queue";
this.MSG_NEEDS_OUTPUT = "Specified render queue item needs output file but none provided.";
this.MSG_RS_TEMPLATE_NOT_FOUND = "No render settings template was found with the given name.";
this.MSG_OM_TEMPLATE_NOT_FOUND = "No output module template was found with the given name.";
this.MSG_CAN_NOT_OPEN_SOCKET = "Can not open socket.";
this.MSG_NO_COMP_YES_TEMPLATE = "WARNING: -RStemplate argument ignored since no -comp or -rqindex provided.";
this.MSG_NO_COMP_YES_OMTEMPLATE = "WARNING: -OMtemplate argument ignored since no -comp or -rqindex provided.";
this.MSG_NO_COMP_YES_OUTPUT = "WARNING: -output argument ignored since no -comp or -rqindex provided.";
this.MSG_NO_COMP_YES_START_OR_END = "WARNING: -s and/or -e arguments ignored since no -comp or -rqindex provided.";
this.MSG_NO_COMP_YES_INCREMENT = "WARNING: -i argument ignored since no -comp or -rqindex provided.";
this.MSG_SKIPPING_WILL_CONTINUE = "INFO: Skipping render queue item with correct comp name but marked to continue from a partly complete render.";
this.MSG_RENDER_ABORTED = "INFO: Render aborted.";
// These three don't get the prefix printed since they are not exit messages
this.MSG_LOG_DIR_NO_EXISTS = "aerender ERROR: Directory specified for log file does not exist: ";
this.MSG_LOG_DIR_NOT_A_DIR = "aerender ERROR: Directory specified for log file is a file, not a directory: ";
this.MSG_LOG_CAN_NOT_OPEN = "aerender ERROR: Can not open log file. Try checking write protection of directory: ";
//
// Variables for rendering
//
this.log_file = null;
this.has_user_log_file = false;
this.is_verbose_mode = true;
this.saved_sound_setting = null;
this.my_sound_setting = null;
// [2] define all the functions used by this class
//
// Report an error. This writes errors to the log file, if present.
// This is called from the context of the application, so we
// need to precede variable names with gAECommandLineRenderer
//
function checkParentDied()
{
var result = false;
if(gAECommandLineRenderer.log_file instanceof Socket) {
if(! gAECommandLineRenderer.log_file.connected) {
app.project.renderQueue.stopRendering();
result = true;
}
}
return result;
}
function my_onError(error_string, severity_string)
{
// This method is called with a variety of types of messages.
// The severity_string tells us what kind.
// Choices are:
// NAKED, INFO, WARNING, PROBLEM, FATAL, PROGRESS, and DEBUG
// Two of these, PROBLEM and FATAL, are errors that should cause us to change
// the exit code:
checkParentDied();
if (severity_string == "PROBLEM" || severity_string == "FATAL") {
// These two errors cause us to change the exit code.
// We don't write an error or throw here, because we got here as part of a thrown
// error already, and the message will be printed as part of the catch.
gAECommandLineRenderer.SetExitCode(gAECommandLineRenderer.EXIT_AE_RUNTIME);
} else {
// PROBLEM and FATAL will throw exceptions, and so will be logged to the file
// when we catch the exception.
// All other errors (NAKED, INFO, WARNING, PROGRESS, and DEBUG) will not
// throw exceptions. So we log them to the file right here:
if (gAECommandLineRenderer.is_verbose_mode) {
if (gAECommandLineRenderer.log_file != null) {
if (severity_string == "NAKED") {
// everybody is confused by this category. Just use INFO instead.
gAECommandLineRenderer.log_file.writeln("INFO:" error_string);
} else {
gAECommandLineRenderer.log_file.writeln(severity_string ":" error_string);
}
}
}
}
// call the error handler that was in place before we started rendering.
if (gAECommandLineRenderer.oldErrorHandler) {
gAECommandLineRenderer.oldErrorHandler(error_string,severity_string);
}
}
// Report an error and throw an exception.
// Causes the script to exit.
function my_SetExitCodeAndThrowException(code, message)
{
this.SetExitCode(code);
throw (this.EXIT_MSG_PREFIX[code] message);
}
// Report an error. This establishes exitCodes for reporting errors from AfterFX.
function my_SetExitCode(code)
{
// Some codes are set differently depending on whether we have a custom user
// log file. Check for these and use the alternate if appropriate.
var real_code = code;
if (gAECommandLineRenderer.has_user_log_file) {
switch (real_code) {
case gAECommandLineRenderer.EXIT_SYNTAX_ERROR:
real_code = gAECommandLineRenderer.EXIT_SYNTAX_ERROR_USER_LOG;
break;
case gAECommandLineRenderer.EXIT_OTHER_SCRIPTING_ERROR:
real_code = gAECommandLineRenderer.EXIT_OTHER_SCRIPTING_ERROR_USER_LOG;
break;
case gAECommandLineRenderer.EXIT_AERENDER_RUNTIME:
real_code = gAECommandLineRenderer.EXIT_AERENDER_RUNTIME_USER_LOG;
break;
case gAECommandLineRenderer.EXIT_AE_RUNTIME:
real_code = gAECommandLineRenderer.EXIT_AE_RUNTIME_USER_LOG;
break;
}
}
// Always keep the first error. So only set if the exitCode is still EXIT_OK.
if (app.exitCode == gAECommandLineRenderer.EXIT_OK) {
app.exitCode = real_code;
}
}
// Arguments may be enclosed in quotes. This
// will remove them and return the result.
function my_StripAnyEnclosingQuotes(inString)
{
var result = inString;
if (inString &&
inString.charAt(0) == '"' &&
inString.charAt(inString.length-1) == '"') {
result = inString.substring(1,inString.length-1);
}
return result;
}
// Make sure the value is there, and returns it, stripping away any enclosing quotes.
//
function my_GetValueForFlag(arg_num, the_flag)
{
if (!this.inArgs[arg_num]) {
this.SetExitCodeAndThrowException(this.EXIT_SYNTAX_ERROR, (this.MSG_UNDEFINED_VALUE_FOR_FLAG the_flag));
}
return this.StripAnyEnclosingQuotes(this.inArgs[arg_num]);
}
// Parse the parameter.
// Return the number of arguments used in parsing the parameter.
function my_ParseParamStartingAt(arg_num)
{
if (!this.inArgs[arg_num]) {
this.SetExitCodeAndThrowException(this.EXIT_AERENDER_RUNTIME, this.MSG_TRIED_TO_PARSE_UNDEFINED);
}
var num_args_parsed = 0;
// Check for a valid flag:
var my_flag = this.inArgs[arg_num];
if (my_flag == "-port") {
// -port is used by aerender to specify a port address for a socket.
//
// Note: this value is sought/parsed earlier, in the SetupDefaultLog method.
// We can just ignore here.
var dummy = this.GetValueForFlag(arg_num 1,my_flag);
num_args_parsed = 2;
}
if (my_flag == "-project") {
this.in_project_path = this.GetValueForFlag(arg_num 1,my_flag);
num_args_parsed = 2;
}
if (my_flag == "-teamproject") {
this.in_teamproject_name = this.GetValueForFlag(arg_num 1,my_flag);
num_args_parsed = 2;
}
if (my_flag == "-comp") {
this.in_comp_name = this.GetValueForFlag(arg_num 1,my_flag);
num_args_parsed = 2;
}
if (my_flag == "-rqindex") {
this.in_rq_index = parseInt(this.GetValueForFlag(arg_num 1,my_flag));
num_args_parsed = 2;
}
if (my_flag == "-RStemplate") {
this.in_RStemplate = this.GetValueForFlag(arg_num 1,my_flag);
num_args_parsed = 2;
}
if (my_flag == "-OMtemplate") {
this.in_OMtemplate = this.GetValueForFlag(arg_num 1,my_flag);
num_args_parsed = 2;
}
if (my_flag == "-output") {
this.in_output_path = this.GetValueForFlag(arg_num 1,my_flag);
num_args_parsed = 2;
}
if (my_flag == "-log") {
this.in_logfile_path = this.GetValueForFlag(arg_num 1,my_flag);
num_args_parsed = 2;
}
if (my_flag == "-s") {
this.in_start_frame = this.GetValueForFlag(arg_num 1,my_flag);
num_args_parsed = 2;
}
if (my_flag == "-e") {
this.in_end_frame = this.GetValueForFlag(arg_num 1,my_flag);
num_args_parsed = 2;
}
if (my_flag == "-i") {
this.in_increment = this.GetValueForFlag(arg_num 1,my_flag);
num_args_parsed = 2;
}
if (my_flag == "-mem_usage") {
this.in_image_cache_percent = this.GetValueForFlag(arg_num 1,my_flag);
this.in_max_mem_percent = this.GetValueForFlag(arg_num 2,my_flag);
num_args_parsed = 3;
}
if (my_flag == "-v") {
this.in_verbose_flag = this.GetValueForFlag(arg_num 1,my_flag);
num_args_parsed = 2;
}
if (my_flag == "-close") {
this.in_close_flag = this.GetValueForFlag(arg_num 1,my_flag);
num_args_parsed = 2;
}
if (my_flag == "-sound") {
this.in_sound_flag = this.GetValueForFlag(arg_num 1,my_flag);
num_args_parsed = 2;
}
if (my_flag == "-doSavePrefsOnQuit") {
// The effect of this flag will be taken into account when we
// exit the app. See comment in the "finally" block.
// All we do here is increment the num_args_parsed count.
num_args_parsed = 1;
}
if (my_flag == "-continueOnMissingFootage") {
this.in_stop_on_missing_frame = false;
num_args_parsed = 1;
}
if (num_args_parsed == 0) {
this.SetExitCodeAndThrowException(this.EXIT_SYNTAX_ERROR, (this.MSG_BAD_FLAG my_flag));
}
return num_args_parsed;
}
// This parses the inArgs array. Assumes
// the array has already been filled.
function my_ParseInArgs()
{
// First, undefine all the inputs we're potentially looking for
this.in_project_path = null;
this.in_teamproject_name = null;
this.in_comp_name = null;
this.in_rq_index = null;
this.in_RStemplate = null;
this.in_OMtemplate = null;
this.in_output_path = null;
this.in_logfile_path = null;
this.in_start_frame = null;
this.in_end_frame = null;
this.in_increment = null;
this.in_image_cache_percent = null;
this.in_max_mem_percent = null;
this.in_verbose_flag = null;
this.in_close_flag = null;
this.in_sound_flag = null;
// Special case: check if any argument is "-help"
for (var i = 0; i < this.inArgs.length; i ) {
if (this.inArgs[i] == "-help") {
this.SetExitCodeAndThrowException(this.EXIT_SHOW_USAGE, this.MSG_SHOW_USAGE);
}
}
var arg_num = 0;
while (arg_num < this.inArgs.length) {
// ParseParamStartingAt returns the number of arguments used up parsing the param.
arg_num = this.ParseParamStartingAt(arg_num);
}
}
// This arg is treated differently than others because it's extra important
// that we exit properly in the face of anything that might go wrong even
// during initialization. So we don't parse the standard way, we check this
// before exit...
function my_IsSavePrefsArgGiven(arglist)
{
return this.IsInArray("-doSavePrefsOnQuit", arglist);
}
// Returns true if the item equals an item in the array, false if otherwise.
function my_IsInArray(needle, haystack)
{
result = false;
for (var i = 0; i < haystack.length; i ) {
if (needle == haystack[i]) {
result = true;
break;
}
}
return result;
}
function my_SetupDefaultLog(arg_list)
{
this.has_user_log_file = false;
// Clean up after a potentially bad exit last time:
if (this.log_file && this.log_file != null) {
this.log_file.close();
this.log_file = null;
}
// Open the socket.
// It is used:
// [a] to log errors if there is no user-specified log file (specified with a "-log" arg)
// [b] to log errors encountered while opening any user-specified log file.
// See if a -port argument was passed:
this.log_file = null;
for (var i = 0; i < arg_list.length; i ) {
if (arg_list[i] == "-port") {
if (arg_list.length > i 1) {
// The argument value is the port address
this.in_port_address = arg_list[i 1];
// Yes, the log_file variable is being used to hold a socket.
this.log_file = new Socket();
// cprosser [26961]
// could possibly use ISO-8856-1 for non japanese systems,
// but I am going for small changes now.
// and again cprosser 8/8/2005 [33884]
// CP_OEMCP means use the OEM code page, the default
// for the console.
// alas, it doens't understand that so we are hardcoding
// codepage 850. Not the default on windows for US systems
// but should be the default on european systems and will
// get the high ascii correct.
// Search for chcp at microsoft for info on changing
// the console.
// on the mac, leave as binary
var encoding_string = "binary";
if (system.osName.search("Windows") != -1) {
encoding_string = "WINDOWS-850";
//encoding_string = "CP_OEMCP";
}
if (app.language == Language.JAPANESE) {
encoding_string = "Shift-JIS";
}
if (app.isoLanguage == "ko_KR") {
encoding_string = "EUC-KR";
}
if (!this.log_file.open(this.in_port_address,encoding_string)) {
this.log_file = null;
this.SetExitCodeAndThrowException(this.EXIT_CANNOT_OPEN_SOCKET,
this.MSG_CAN_NOT_OPEN_SOCKET);
}
}
}
}
this.is_verbose_mode = true;
}
function my_CleanupDefaultLog()
{
// Close the log file
if (this.log_file != null) {
this.log_file.close();
this.log_file = null;
}
}
// This is the external entry point.
// Bat files or executables may call this method.
//
// This function assumes that it has been passed all the arguments.
// It parses the arguments and then renders.
function my_Render()
{
app.beginSuppressDialogs();
if(checkParentDied()) {
return;
}
try {
this.SetupDefaultLog(my_Render.arguments);
// start by assuming successful execution, exit code 0.
app.exitCode = 0;
// Check number of arguments
if (!my_Render.arguments || my_Render.arguments.length == 0) {
this.SetExitCodeAndThrowException(this.EXIT_SHOW_USAGE, this.MSG_SHOW_USAGE);
}
var numArgs = my_Render.arguments.length;
// Allocate the array of arguments:
this.inArgs = new Array(numArgs);
// Load the input arguments into the inArgs array.
for (var i = 0; i < numArgs; i ) {
this.inArgs[i] = my_Render.arguments[i];
}
// Parse the arguments, and render
this.ParseInArgs();
if(checkParentDied()) {
return;
}
this.ReallyRender();
} catch(error) {
// Add any errors to the log file.
if (this.log_file != null) {
this.log_file.writeln("aerender " error.toString());
}
this.SetExitCode(this.EXIT_AE_RUNTIME);
} finally {
// This arg is treated differently than others because it's extra important
// that we exit properly in the face of anything that might go wrong even
// during initialization. So we don't parse the standard way, we check this
// before exit...
app.setSavePreferencesOnQuit(this.IsSavePrefsArgGiven(my_Render.arguments));
this.CleanupDefaultLog();
app.endSuppressDialogs(false);
app.reportErrorOnMissingFrame = false;
}
}
function my_ReallyRender()
{
this.saved_sound_setting = null;
app.reportErrorOnMissingFrame = this.in_stop_on_missing_frame;
try {
// While rendering we'll report errors to the log file.
if (app.onError == this.onError) {
// If the previous error handler is just this one, don't store it.
// That can happen in extreme cases where this script does not get a
// chance to clean up and put back the oldErrorHandler when it's done.
this.oldErrorHandler = null;
} else {
this.oldErrorHandler = app.onError;
}
app.onError = this.onError;
// Open the user log file, if specified, and use it instead of the socket.
if (this.in_logfile_path) {
// Keep the socket open; errors we encounter while opening the
// user log file will be logged to the socket.
var user_log_file = new File(this.in_logfile_path);
var parent_dir = user_log_file.parent;
if (!parent_dir.exists) {
if (this.log_file) {
this.log_file.writeln(this.MSG_LOG_DIR_NO_EXISTS this.in_logfile_path);
}
this.SetExitCodeAndThrowException(this.EXIT_AE_RUNTIME, this.MSG_AE_RUNTIME);
}
var test_folder = Folder(parent_dir);
if (!(test_folder instanceof Folder)) {
if (this.log_file) {
this.log_file.writeln(this.MSG_LOG_DIR_NOT_A_DIR this.in_logfile_path);
}
this.SetExitCodeAndThrowException(this.EXIT_AE_RUNTIME, this.MSG_AE_RUNTIME);
}
if (!user_log_file.open("w",'TEXT','ttxt')) {
if (this.log_file) {
this.log_file.writeln(this.MSG_LOG_CAN_NOT_OPEN this.in_logfile_path);
}
this.SetExitCodeAndThrowException(this.EXIT_AE_RUNTIME, this.MSG_AE_RUNTIME);
}
// no errors were encountered opening the file.
// Close the socket and use this one instead.
if (this.log_file != null) {
this.log_file.close();
}
this.log_file = user_log_file; // which is still open
this.has_user_log_file = true;
}
if (this.in_verbose_flag) {
if (this.in_verbose_flag == "ERRORS") {
this.is_verbose_mode = false;
} else if (this.in_verbose_flag == "ERRORS_AND_PROGRESS") {
this.is_verbose_mode = true;
} else {
this.SetExitCodeAndThrowException(this.EXIT_SYNTAX_ERROR, this.MSG_BAD_VERBOSE_FLAG);
}
}
if (this.in_close_flag) {
if (this.in_close_flag != "DO_NOT_CLOSE" &&
this.in_close_flag != "DO_NOT_SAVE_CHANGES" &&
this.in_close_flag != "SAVE_CHANGES") {
this.SetExitCodeAndThrowException(this.EXIT_SYNTAX_ERROR, this.MSG_BAD_CLOSE_FLAG);
}
}
if (this.in_sound_flag) {
if (this.in_sound_flag != "ON" &&
this.in_sound_flag != "OFF" &&
this.in_sound_flag != "on" &&
this.in_sound_flag != "off") {
this.SetExitCodeAndThrowException(this.EXIT_SYNTAX_ERROR, this.MSG_BAD_SOUND_FLAG);
}
}
// Set the memory usage, if specified as an argument.
if (this.in_image_cache_percent && this.in_max_mem_percent) {
app.setMemoryUsageLimits(this.in_image_cache_percent, this.in_max_mem_percent);
}
// If the user provided a project, close the current project and open the project specified.
// Else, leave the current project open.
if (this.in_project_path) {
// Close the current project
if (app.project != null) {
app.project.close(CloseOptions.DO_NOT_SAVE_CHANGES);
}
// Open the specified project:
var proj_file = new File(this.in_project_path);
app.openFast(proj_file);
}
if (!app.project) {
this.SetExitCodeAndThrowException(this.EXIT_AERENDER_RUNTIME, this.MSG_NO_PROJECT);
}
// If the user provided a teamproject, close the current project and open the teamproject specified.
// Else, leave the current project open.
if (this.in_teamproject_name) {
// Close the current project
if (app.project != null) {
app.project.close(CloseOptions.DO_NOT_SAVE_CHANGES);
}
// Open the specified team project:
app.openTeamProject(this.in_teamproject_name);
}
if (!app.project) {
this.SetExitCodeAndThrowException(this.EXIT_AERENDER_RUNTIME, this.MSG_NO_PROJECT);
}
// Get the RenderQueueItem for the specified comp, if specified.
var rqi = null;
if (this.in_comp_name) {
rqi = this.GetFirstQueuedRQItemWithName(this.in_comp_name);
} else if (this.in_rq_index != null) {
this.log_file.writeln("rqindex " this.in_rq_index "num " app.project.renderQueue.numItems);
if (this.in_rq_index >= 1 && this.in_rq_index <= app.project.renderQueue.numItems) {
rqi = app.project.renderQueue.item(this.in_rq_index);
} else {
this.SetExitCodeAndThrowException(this.EXIT_AERENDER_RUNTIME, this.MSG_RQINDEX_NOT_FOUND);
}
}
if (this.in_comp_name && !rqi) {
// Try to find the comp in the project and add to the render queue:
rqi = this.AddCompToRenderQueue(this.in_comp_name);
if (rqi) {
if (this.log_file != null) {
this.log_file.writeln(this.MSG_ADDING_TO_RQ);
}
} else {
this.SetExitCodeAndThrowException(this.EXIT_AERENDER_RUNTIME, this.MSG_COMP_NOT_FOUND);
}
}
// Apply the templates, if provided
if (this.in_RStemplate) {
if (!rqi) {
if (this.log_file != null) {
this.log_file.writeln(this.MSG_NO_COMP_YES_TEMPLATE);
}
} else {
if (!this.IsInArray(this.in_RStemplate, rqi.templates)) {
this.SetExitCodeAndThrowException(this.EXIT_AERENDER_RUNTIME, this.MSG_RS_TEMPLATE_NOT_FOUND);
}
rqi.applyTemplate(this.in_RStemplate);
}
}
if (this.in_OMtemplate) {
if (!rqi) {
if (this.log_file != null) {
this.log_file.writeln(this.MSG_NO_COMP_YES_OMTEMPLATE);
}
} else {
if (!this.IsInArray(this.in_OMtemplate, rqi.outputModule(1).templates)) {
this.SetExitCodeAndThrowException(this.EXIT_AERENDER_RUNTIME, this.MSG_OM_TEMPLATE_NOT_FOUND);
}
rqi.outputModule(1).applyTemplate(this.in_OMtemplate);
}
}
// If a comp was specified, make it the only one to render.
// If none was provided, leave everything alone so render queue renders as is.
if (rqi) {
this.EstablishAsOnlyQueuedItem(rqi);
}
if (rqi) {
// If the user provided a path, set the output path on rqi's OutputModule
if (rqi.status == RQItemStatus.NEEDS_OUTPUT && !this.in_output_path) {
this.SetExitCodeAndThrowException(this.EXIT_AERENDER_RUNTIME, this.MSG_NEEDS_OUTPUT);
}
if (this.in_output_path) {
var om = rqi.outputModule(1);
om.file = new File(this.in_output_path);
}
} else {
if (this.in_output_path) {
if (this.log_file != null) {
this.log_file.writeln(this.MSG_NO_COMP_YES_OUTPUT);
}
}
}
// Set the start and end frames.
if (this.in_start_frame || this.in_end_frame) {
if (!rqi) {
if (this.log_file != null) {
this.log_file.writeln(this.MSG_NO_COMP_YES_START_OR_END);
}
} else {
// Render times are stored as timeSpanStart and timeSpanDuration.
// Setting only the timeSpanStart will not change the timeSpanDuration and
// so will move the end time, but we want the end time unchanged if
// it was not specified.
// So we must calculate both start_time and end_time,
// then set both timeSpanStart and timeSpanDuration.
// Note: frameDuration is stored in the comp.
var start_time = rqi.timeSpanStart;
var end_time = rqi.timeSpanStart rqi.timeSpanDuration;
if (this.in_start_frame) {
start_time = -rqi.comp.displayStartTime ((parseInt(this.in_start_frame,10) - app.project.displayStartFrame) * rqi.comp.frameDuration);
}
if (this.in_end_frame) {
// The way AE works, final frame is not included.
// But aerender wants final frame included.
// So, just add 1 to end frame right here before setting
// duration for AE:
// Note: must call parseInt() here, or the 1 will be added as if it
// were a string. For example, 35 would become 351, not 36. Hoo boy!
var end_frame_plus_one = parseInt(this.in_end_frame,10) 1.0 - app.project.displayStartFrame;
end_time = -rqi.comp.displayStartTime (end_frame_plus_one * rqi.comp.frameDuration);
}
rqi.timeSpanStart = start_time;
rqi.timeSpanDuration = end_time - start_time;
}
}
// Set the skipFrames (based on increment).
if (this.in_increment) {
if (this.in_increment < 1 || this.in_increment > 100) {
this.SetExitCodeAndThrowException(this.EXIT_SYNTAX_ERROR, this.MSG_BAD_INCREMENT);
}
if (!rqi) {
if (this.log_file != null) {
this.log_file.writeln(this.MSG_NO_COMP_YES_INCREMENT);
}
} else {
// Set the skipFrames based on the increment.
//
// Increment as defined here is one greater then the
// the render queue item's skipFrames.
// skipFrames 0 is the same as increment of 1.
//
rqi.skipFrames = (this.in_increment - 1);
}
}
// If we are in verbose mode, set the log type to ERRORS_AND_PER_FRAME_INFO
// for all RQ items we are about to render.
if (this.is_verbose_mode) {
this.SetLogPerFrameInfoInRQ();
}
this.SaveAndSetRenderSoundSetting();
// Render!
// true skips the recursive check for footage files
// and will only check the one's used
if(checkParentDied()) {
return;
}
app.project.renderQueue.render(true);
} catch(error) {
// Add any errors to the log file.
if (this.log_file != null) {
this.log_file.writeln("aerender " error.toString());
}
// It's possible that errors were encountered while trying to render.
// Stop the render if in progress for a clean exit from the application.
if (app.project && app.project.renderQueue && app.project.renderQueue.rendering) {
// This will prevent the message "render stopped by user" from showing up...
app.onError = null;
app.project.renderQueue.stopRendering();
// This will print a better message:
if (this.log_file != null) {
this.log_file.writeln(this.MSG_RENDER_ABORTED);
}
app.onError = this.onError;
}
this.SetExitCode(this.EXIT_AE_RUNTIME);
} finally {
// Close the project.
this.CloseProjectIfDesired();
// Put back the old error handler
app.onError = this.oldErrorHandler;
// Restore the setting for hearing the render-done sound.
this.RestoreRenderSoundSetting()
}
}
// Returns the first item on the render queue that:
// [a] contains a comp named comp_name
// [b] has a render status of QUEUED or UNQUEUED or NEEDS_OUTPUT
// Note that if the status is NEEDS_OUTPUT, one better be provided or
// an error will result.
//
// If not found, returns null.
//
function my_GetFirstQueuedRQItemWithName(comp_name)
{
var result = null;
var rq = app.project.renderQueue;
if (rq && rq.numItems > 0) {
var cur_item;
// the items are indexed from 1 to numItems.
for (var i = 1; i <= rq.numItems; i ) {
cur_item = rq.item(i);
if (cur_item.comp.name == comp_name &&
cur_item.status == RQItemStatus.WILL_CONTINUE) {
if (this.log_file != null) {
this.log_file.writeln(this.MSG_SKIPPING_WILL_CONTINUE);
}
}
if (cur_item.comp.name == comp_name &&
(cur_item.status == RQItemStatus.QUEUED ||
// pmi 9/24/03 -- do not render unqueued items. Let a new
// one be added instead.
// cur_item.status == RQItemStatus.UNQUEUED ||
cur_item.status == RQItemStatus.NEEDS_OUTPUT)) {
// We found it!
result = cur_item;
break;
}
}
}
return result;
}
// Find a comp with the given name, and adds it to the render queue.
// Returns the newly added render queue item
//
// If not found, returns null.
//
function my_AddCompToRenderQueue(comp_name)
{
var result = null;
// Get the comp with the name we are after
var cur_item;
var desired_comp = null;
// the items in the project are indexed from 1 to numItems
for (var i = 1; i <= app.project.numItems; i ) {
cur_item = app.project.item(i);
if (cur_item instanceof CompItem && cur_item.name == comp_name) {
desired_comp = cur_item;
break;
}
}
// Add the desired_comp to the render queue. The add() method
// returns the new render queue item.
if (desired_comp) {
result = app.project.renderQueue.items.add(desired_comp);
}
return result;
}
// Sets the render flag on all RenderQueueItems other than rqi to false,
//
function my_EstablishAsOnlyQueuedItem(rqi)
{
var rq = app.project.renderQueue;
if (rq && rq.numItems > 0) {
var cur_item;
// the items are indexed from 1 to numItems.
for (var i = 1; i <= rq.numItems; i ) {
cur_item = rq.item(i);
if (cur_item == rqi) {
cur_item.render = true;
} else {
// You can only change the render flag when these are the current status value:
if (cur_item.status == RQItemStatus.QUEUED ||
cur_item.status == RQItemStatus.UNQUEUED ||
cur_item.status == RQItemStatus.NEEDS_OUTPUT ||
cur_item.status == RQItemStatus.WILL_CONTINUE) {
cur_item.render = false;
}
}
}
}
}
// Sets the log type to be ERRORS_AND_PER_FRAME_INFO for all items that are going to render.
//
function my_SetLogPerFrameInfoInRQ()
{
var rq = app.project.renderQueue;
if (rq && rq.numItems > 0) {
var cur_item;
// the items are indexed from 1 to numItems.
for (var i = 1; i <= rq.numItems; i ) {
cur_item = rq.item(i);
if (cur_item.render == true) {
if (cur_item.status != RQItemStatus.USER_STOPPED &&
cur_item.status != RQItemStatus.ERR_STOPPED &&
cur_item.status != RQItemStatus.RENDERING &&
cur_item.status != RQItemStatus.DONE) {
cur_item.logType = LogType.ERRORS_AND_PER_FRAME_INFO;
}
}
}
}
}
// Closes the project if the close flag specifies to do so
//
function my_CloseProjectIfDesired()
{
if (app.project) {
// Close the project we just used, if desired
if (!this.in_close_flag || this.in_close_flag == "DO_NOT_SAVE_CHANGES") {
// If no flag provided, this is the default.
app.project.close(CloseOptions.DO_NOT_SAVE_CHANGES);
} else {
if (this.in_close_flag == "SAVE_CHANGES") {
app.project.close(CloseOptions.SAVE_CHANGES);
}
// otherwise, flag is DO_NOT_CLOSE, so we do nothing.
}
}
}
function my_SaveAndSetRenderSoundSetting()
{
// Save the current setting for hearing the render-done sound, we'll restore it later.
if (app.preferences.havePref("Misc Section",
"Play sound when render finishes", PREFType.PREF_Type_MACHINE_INDEPENDENT)) {
// Get the current value if the pref exists.
this.saved_sound_setting = app.preferences.getPrefAsLong("Misc Section",
"Play sound when render finishes", PREFType.PREF_Type_MACHINE_INDEPENDENT);
} else {
// default is to play the sound, value of 1.
// Use this if the pref does not yet exist.
this.saved_sound_setting = 1;
}
// Set the setting for hearing the render-done sound, based on the input, default is off.
this.my_sound_setting = 0; // 0 is off
if (this.in_sound_flag && (this.in_sound_flag == "ON" || this.in_sound_flag == "on")) {
this.my_sound_setting = 1; // 1 is on
}
app.preferences.savePrefAsLong("Misc Section",
"Play sound when render finishes",
this.my_sound_setting, PREFType.PREF_Type_MACHINE_INDEPENDENT);
}
function my_RestoreRenderSoundSetting()
{
if (this.saved_sound_setting) {
app.preferences.savePrefAsLong("Misc Section",
"Play sound when render finishes",
this.saved_sound_setting, PREFType.PREF_Type_MACHINE_INDEPENDENT);
}
}
// [3] assign all the functions to be method-type attributes.
//
this.onError = my_onError;
this.SetExitCodeAndThrowException = my_SetExitCodeAndThrowException;
this.SetExitCode = my_SetExitCode;
this.StripAnyEnclosingQuotes = my_StripAnyEnclosingQuotes;
this.GetValueForFlag = my_GetValueForFlag;
this.ParseParamStartingAt = my_ParseParamStartingAt;
this.ParseInArgs = my_ParseInArgs;
this.IsInArray = my_IsInArray;
this.SetupDefaultLog = my_SetupDefaultLog;
this.CleanupDefaultLog = my_CleanupDefaultLog;
this.Render = my_Render;
this.ReallyRender = my_ReallyRender;
this.GetFirstQueuedRQItemWithName = my_GetFirstQueuedRQItemWithName;
this.AddCompToRenderQueue = my_AddCompToRenderQueue;
this.EstablishAsOnlyQueuedItem = my_EstablishAsOnlyQueuedItem;
this.SetLogPerFrameInfoInRQ = my_SetLogPerFrameInfoInRQ;
this.CloseProjectIfDesired = my_CloseProjectIfDesired;
this.SaveAndSetRenderSoundSetting = my_SaveAndSetRenderSoundSetting;
this.RestoreRenderSoundSetting = my_RestoreRenderSoundSetting;
this.IsSavePrefsArgGiven = my_IsSavePrefsArgGiven;
}
var gAECommandLineRenderer = new AECommandLineRenderer();
,