mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-29 04:26:55 -06:00
M13.7: Essential Graphics scripting hooks, Font and uniform Scale controls, Open in Essential Graphics
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
5aae82b05c
commit
558de71720
@@ -715,6 +715,19 @@ Property.prototype.property = function () { return null; };
|
||||
});
|
||||
def("isDropdownEffect", function () { return false; });
|
||||
|
||||
// Essential Graphics: expose this property in `comp` (its own composition).
|
||||
P.canAddToMotionGraphicsTemplate = function (comp) {
|
||||
if (!comp || comp.__id !== this.__layer.__comp) return false;
|
||||
return __call("essential.canAdd", this.__ref()).ok === true;
|
||||
};
|
||||
P.addToMotionGraphicsTemplateAs = function (comp, name) {
|
||||
if (!this.canAddToMotionGraphicsTemplate(comp)) return false;
|
||||
var p = this.__ref();
|
||||
if (name !== undefined && name !== null) p.name = String(name);
|
||||
__call("essential.addProperty", p);
|
||||
return true;
|
||||
};
|
||||
P.addToMotionGraphicsTemplate = function (comp) { return this.addToMotionGraphicsTemplateAs(comp); };
|
||||
P.getSeparationFollower = function (dim) {
|
||||
return this.parentProperty.property(["ADBE Position_0", "ADBE Position_1", "ADBE Position_2"][dim]);
|
||||
};
|
||||
@@ -875,8 +888,6 @@ Property.prototype.property = function () { return null; };
|
||||
};
|
||||
P.keyLabel = function () { return 0; };
|
||||
P.setLabelAtKey = function () {};
|
||||
P.addToMotionGraphicsTemplate = function () { return false; };
|
||||
P.canAddToMotionGraphicsTemplate = function () { return false; };
|
||||
})();
|
||||
|
||||
// Layer / composition markers (`layer.marker`, `comp.markerProperty`): keyframes are markers.
|
||||
@@ -1422,7 +1433,47 @@ CompItem.prototype.constructor = CompItem;
|
||||
};
|
||||
P.openInViewer = function () { __call("comp.open", { comp: this.__id }); return null; };
|
||||
P.duplicate = function () { return __item(__call("project.duplicate", { items: [this.__id] }).items[0]); };
|
||||
P.exportAsMotionGraphicsTemplate = function () { return false; };
|
||||
// Essential Graphics (templates are EffectCraft's open .ectemplate files).
|
||||
P.__eg = function () { return __call("essential.list", { comp: this.__id }); };
|
||||
P.__controllers = function () {
|
||||
var out = [];
|
||||
(function walk(list) {
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
if (list[i].kind === "property" || list[i].kind === "media") out.push(list[i]);
|
||||
if (list[i].children) walk(list[i].children);
|
||||
}
|
||||
})(this.__eg().controls);
|
||||
return out;
|
||||
};
|
||||
def("motionGraphicsTemplateName", function () { return this.__eg().name; }, function (v) {
|
||||
__call("essential.setName", { comp: this.__id, name: String(v) });
|
||||
});
|
||||
def("motionGraphicsTemplateControllerCount", function () { return this.__controllers().length; });
|
||||
P.getMotionGraphicsTemplateControllerName = function (i) {
|
||||
var c = this.__controllers();
|
||||
i = __num(i, "index");
|
||||
if (i < 1 || i > c.length) throw __err("controller index " + i + " is out of range 1.." + c.length);
|
||||
return c[i - 1].name;
|
||||
};
|
||||
P.setMotionGraphicsControllerName = function (i, name) {
|
||||
var c = this.__controllers();
|
||||
i = __num(i, "index");
|
||||
if (i < 1 || i > c.length) throw __err("controller index " + i + " is out of range 1.." + c.length);
|
||||
__call("essential.rename", { comp: this.__id, control: c[i - 1].id, name: String(name) });
|
||||
return String(name);
|
||||
};
|
||||
P.openInEssentialGraphics = function () { __call("comp.openInEssentialGraphics", { comp: this.__id }); };
|
||||
P.exportAsMotionGraphicsTemplate = function (overwrite, path) {
|
||||
var f = __str(path);
|
||||
if (!f) return false;
|
||||
if (!/\.[A-Za-z0-9]+$/.test(f)) f += ".ectemplate";
|
||||
if (!overwrite && JSON.parse(__file("exists", f)) === true) return false;
|
||||
if (this.__controllers().length === 0) return false;
|
||||
// The file gate applies to templates too.
|
||||
__file("write", f, "");
|
||||
__call("essential.exportTemplate", { comp: this.__id, path: f });
|
||||
return true;
|
||||
};
|
||||
})();
|
||||
|
||||
function FootageItem(id) {
|
||||
|
||||
@@ -142,6 +142,49 @@ fn on_changing_fires_per_keystroke_and_slider_step() {
|
||||
s.execute("scriptui.close", json!({})).unwrap();
|
||||
}
|
||||
|
||||
const MOGRT: &str = r#"
|
||||
var c = app.project.activeItem;
|
||||
var t = c.layer(1);
|
||||
var st = t.property("ADBE Text Properties").property("ADBE Text Document");
|
||||
var op = t.property("ADBE Transform Group").property("ADBE Opacity");
|
||||
var r = [st.canAddToMotionGraphicsTemplate(c), st.addToMotionGraphicsTemplate(c), op.addToMotionGraphicsTemplateAs(c, "Fade")];
|
||||
c.motionGraphicsTemplateName = "Lower Third";
|
||||
c.setMotionGraphicsControllerName(1, "Title");
|
||||
r.concat([c.motionGraphicsTemplateName, c.motionGraphicsTemplateControllerCount, c.getMotionGraphicsTemplateControllerName(1), c.getMotionGraphicsTemplateControllerName(2)]).join("|")
|
||||
"#;
|
||||
|
||||
#[test]
|
||||
fn essential_graphics_scripting_hooks() {
|
||||
let mut s = session();
|
||||
s.execute("comp.new", json!({"name": "Card", "width": 64, "height": 64, "duration": 1})).unwrap();
|
||||
s.execute("layer.newText", json!({"text": "Hi"})).unwrap();
|
||||
let o = run_code(&mut s, MOGRT, "mogrt.jsx");
|
||||
assert!(o.error.is_none(), "{:?} {:?}", o.error, o.output);
|
||||
assert_eq!(o.result, json!("true|true|true|Lower Third|2|Title|Fade"));
|
||||
let cid = s.active_comp_id().unwrap();
|
||||
assert_eq!(s.project.comp(cid).unwrap().essential.as_ref().unwrap().name, "Lower Third");
|
||||
// Another comp can't take this comp's properties.
|
||||
s.execute("comp.new", json!({"name": "Other", "width": 64, "height": 64, "duration": 1})).unwrap();
|
||||
let code = "var card = null; for (var i = 1; i <= app.project.numItems; i++) if (app.project.item(i).name === 'Card') card = app.project.item(i); var o = app.project.activeItem; var p = card.layer(1).property('ADBE Transform Group').property('ADBE Position'); [p.canAddToMotionGraphicsTemplate(o), p.canAddToMotionGraphicsTemplate(card)].join('|')";
|
||||
let o = run_code(&mut s, code, "x.jsx");
|
||||
assert_eq!(o.result, json!("false|true"), "{:?}", o.error);
|
||||
// Export (behind the file-write preference).
|
||||
let dir = std::env::temp_dir().join(format!("ec-mogrt-{}", std::process::id()));
|
||||
let _ = std::fs::create_dir_all(&dir);
|
||||
let path = dir.join("lower.ectemplate");
|
||||
let export = format!(
|
||||
"var card = null; for (var i = 1; i <= app.project.numItems; i++) if (app.project.item(i).name === 'Card') card = app.project.item(i); card.exportAsMotionGraphicsTemplate(false, {:?})",
|
||||
path.to_string_lossy()
|
||||
);
|
||||
assert!(run_code(&mut s, &export, "x.jsx").error.is_some());
|
||||
s.prefs.scripting.allow_scripts_write_files = true;
|
||||
assert_eq!(run_code(&mut s, &export, "x.jsx").result, json!(true));
|
||||
assert!(std::fs::metadata(&path).unwrap().len() > 100);
|
||||
// It exists now: no overwrite → false.
|
||||
assert_eq!(run_code(&mut s, &export, "x.jsx").result, json!(false));
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sockets_talk_tcp_behind_the_network_preference() {
|
||||
use std::io::{BufRead, BufReader, Write};
|
||||
|
||||
Reference in New Issue
Block a user