Copy link to clipboard
Copied
I need to test if there are unsaved changes to the project in the After Effects application. Is there any way to do that? I get really close with this hacky solution -- save the project to a temp location and compare it to the current project:
function projectHasUnsavedChanges() {
if (!app.project || !app.project.file) {
return false;
}
var currentFile = app.project.file;
// create_uuid pulled from https://stackoverflow.com/questions/105034/how-to-create-guid-uuid
var tempProjectFile = new File(Folder.temp.fsName + '/' + create_uuid() + '.tmp.aep');
app.project.save(tempProjectFile);
var filesIdentical = byte_compare_files(tempProjectFile, currentFile);
tempProjectFile.remove();
return !filesIdentical;
}
This solution has a huge side-effect making it unacceptable. Basically whenever .save() is called, it changes the After Effects active project file to the saved location. Furthermore it adds the saved file to the recent history. Given I am just trying to do a test for unsaved changes, this doesn't work.
Are there any other options out there?
Thanks!
Copy link to clipboard
Copied
AEGP_ProjectIsDirty ?
Copy link to clipboard
Copied
Thank you for the reference. But how do I leverage this from ExtendScript, i.e. via ExternalObject or something?
Copy link to clipboard
Copied
either an ExternalObject or if you already have an AEGP running you could have it check the flag in idle hook and write it's status to a javascript global.
Copy link to clipboard
Copied
I do not have an AEGP running. My project is just an extension with Script UI, so I would be trying to invoke AEGP_ProjectIsDirty from ExtendScript. But how to do that? For example, I don't know what to put in ExternalObject:
// Completely non-working and invalid code...
var projectSuite6 = new ExternalObject('lib:?AEGP_ProjSuite6?');
var project = projectSuite6.AEGP_GetProjectProjectByIndex(0);
var isDirty = project.AEGP_ProjectIsDirty();
Thanks
Copy link to clipboard
Copied
you'll need to compile an external object handling dll, which would put you in the C realm anyways...
AEGP calls are accessible only via the C API, so unless you're willing to travel that road i guess that's not a valid solution for you.
Copy link to clipboard
Copied
here's a hacky thought:
through javascript, do a system call like this:
tasklist /v /fo list /fi "imagename eq afterfx*"| find /i "window title:"
it will retreive the name text of the title of AE's window. if the name ends with an asterix then the project has unsaved changed.
(the command i showed here is very slow. perhaps there's a faster way to find AE's process)
Copy link to clipboard
Copied
Copy link to clipboard
Copied
that wasn't a C solution. it was purely javascript.
Copy link to clipboard
Copied
Copy link to clipboard
Copied
I figured out a way, sort of, to do this. I am hoping to get feedback on it's viability and maybe a way to improve the idea. It takes advantage of three facts:
Armed with this information, I can keep track of what revision the project has when the project is saved:
var projectState = (function () {
var xmpLib = new ExternalObject('lib:AdobeXMPScript');
var currentModifyDate;
var revisionWhenReadModifyDate;
var currentState;
function getState() {
return currentState;
}
function update() {
var actualModifyDate = readModifyDateFromXmp();
var actualRevision = (app.project && app.project.revision) || undefined;
if (actualModifyDate !== currentModifyDate) {
currentModifyDate = actualModifyDate;
revisionWhenReadModifyDate = actualRevision;
}
// 0 = project not loaded, 1 = project loaded with no changes, 2 = project loaded with changes
currentState = !currentModifyDate ? 0 : ((revisionWhenReadModifyDate === actualRevision) ? 1 : 2);
}
function readModifyDateFromXmp() {
if (!app.project || !app.project.file || !app.project.xmpPacket) {
return undefined;
}
var xmpMeta = new XMPMeta(app.project.xmpPacket);
return xmpMeta.getProperty(XMPConst.NS_XMP, 'ModifyDate').toString();
}
return {
getState: getState,
update: update
};
})();
The major drawback here is I need read the project revision immediately when the project is saved or opened. I cannot find events for either of these, so in order to keep the state up to date I need to poll projectState.update() every second or so. If I had events for project saving and opening that would solve the problem, I think. But if I do that, then I projectState.getState() gives me an accurate reading of 'dirty' state. There is of course a race condition that if the user saves the file and makes a quick modification before projectState.update() is called, the state will be incorrect. Events for project save or opened would solve that as well...
Oh also, if the extension is started while the project state is dirty, the result will be inaccurate also. So this doesn't totally work, but it gets close.
Thoughts?
Copy link to clipboard
Copied
Sorry to revive such an old post, but do you have any suggestions regarding building an externalobject with AEGP functionality?
Everything I seem to be trying isn't working, and I think its related to establishing that initial connection with AE.
For a test I'm simply trying to run AEGP_executeScript, but the code fails without exception when I try to set my SuiteHandler like I would in an actual AEGP.
```
Copy link to clipboard
Copied
can you elborate on that snippet in some wider context? it's impossible to tell by these two lines...