so much faster keyframe adding

This commit is contained in:
themancalledjakob 2024-03-05 17:12:18 +01:00
parent d95ec3d965
commit f18bafc543
4 changed files with 85 additions and 176 deletions

View file

@ -430,7 +430,7 @@ window.getLayers = () => {
return layers; return layers;
}; };
window.getLayer = (layerID) => { window.getLayer = (layerID = tp.studio.selection[0].address.objectKey) => {
if (layerID === 'artboard') { if (layerID === 'artboard') {
return artboard; return artboard;
} else { } else {
@ -610,5 +610,4 @@ const initPanels = () => {
}); });
}); });
} }
}; };

View file

@ -431,7 +431,7 @@ const Record = function(tp) {
console.log('Record::startRecording', `whoops input_clone for ${propTitle} is null`); console.log('Record::startRecording', `whoops input_clone for ${propTitle} is null`);
} }
}); });
tp.sheet.sequence.position = 0; //tp.sheet.sequence.position = 0;
tp.sheet.sequence.play(); tp.sheet.sequence.play();
}); });
isRecording = RECORDING; isRecording = RECORDING;
@ -502,7 +502,7 @@ const Record = function(tp) {
const kf = clone(keyframes); const kf = clone(keyframes);
promises.push(() => { promises.push(() => {
return new Promise((subResolve) => { return new Promise((subResolve) => {
tp.setKeyframes(layer, keyframes).then(() => { tp.addKeyframes(layer, keyframes).then(() => {
layer.updateValuesViaTheatre(true); layer.updateValuesViaTheatre(true);
subResolve(); subResolve();
}); });

View file

@ -8,6 +8,7 @@ import {
getParents, getParents,
arraysEqual, arraysEqual,
sequencialPromises, sequencialPromises,
getNestedProperty,
} from './utils.js'; } from './utils.js';
//import { //import {
@ -141,177 +142,90 @@ const TheatrePlay = function(autoInit = false) {
} }
return t.parentElement.querySelector('[title="Sequence this prop"]'); return t.parentElement.querySelector('[title="Sequence this prop"]');
}; };
const isSequenced = (path) => { const isSequenced = (path, layer = getLayer()) => {
return getSequenceButton(path) === null; if (!Array.isArray(path)) {
}; path = path.split('.');
const setSequenced = (propTitle, sequenced, metaResolve = false) => {
const f = (resolve) => {
const propIsSequenced = isSequenced(propTitle);
const somethingToDo = sequenced !== propIsSequenced;
if (somethingToDo) {
const contextItem = sequenced ? 'sequence' : 'make static';
const antiContextItem = sequenced ? 'make static' : 'sequence';
const finishedSequencedEvent = (e) => {
// only care about events from our prop
if (propTitle === e.detail.prop.join('.')) {
// if we un-sequence, we listen to stateEditors' event
if (!sequenced && e.detail.origin === 'stateEditors.ts' && e.detail.sequenced === sequenced) {
window.removeEventListener('sequenceEvent', finishedSequencedEvent);
resolve(true);
// if we sequence, then we wait until the track is there
} else if (sequenced && e.detail.origin === 'BasicKeyframedTrack.tsx' && e.detail.sequenced === sequenced) {
window.removeEventListener('sequenceEvent', finishedSequencedEvent);
resolve(true);
} else {
// pretty verbose
//console.log('TheatrePlayu::setSequenced', 'ignored event', e, e.detail);
}
}
};
let counter = 0;
const clickContextMenu = (e) => {
let done = false;
if (e.target !== null) {
e.target.removeEventListener('contextmenu', clickContextMenu);
}
tp.shadowRoot.querySelectorAll('ul li span').forEach((s) => {
if (s.innerHTML.toLowerCase() === contextItem.toLowerCase()) {
window.addEventListener('sequenceEvent', finishedSequencedEvent);
s.click();
done = true;
} else if (s.innerHTML.toLowerCase() === antiContextItem.toLowerCase()) {
done = true;
resolve(false);
}
});
if (!done) {
setTimeout(() => {
if (counter < 4) {
clickContextMenu(e);
counter++;
} else {
setSequenced(propTitle, sequenced, resolve);
}
}, 100);
}
};
getPanelPropTitle(propTitle).addEventListener('contextmenu', clickContextMenu);
getPanelPropTitle(propTitle).dispatchEvent(new Event('contextmenu'));
} else {
resolve();
}
};
if (!metaResolve) {
return new Promise((resolve) => {
f(resolve);
});
} else {
f(metaResolve);
} }
const prop = getNestedProperty(layer.theatreObject.props, path);
return studio.__experimental.__experimental_isPropSequenced(prop);
// is this better than this?
//return getSequenceButton(path) === null;
}; };
const setSequenced = (path, sequenced = true, layer = getLayer()) => {
if (!Array.isArray(path)) {
path = path.split('.');
}
return new Promise((resolve) => {
if(isSequenced(path, layer) === sequenced) {
resolve(true);
} else {
const prop = getNestedProperty(layer.theatreObject.props, path);
if (sequenced) {
tp.studio.__experimental.__experimental_setPropAsSequenced(prop);
} else {
tp.studio.__experimental.__experimental_setPropAsStatic(prop);
}
let count = 0;
const interval = setInterval(() => {
if (isSequenced(path, layer) === sequenced) {
clearInterval(interval);
resolve(true);
} else if (count >= 10) {
clearInterval(interval);
resolve(false);
}
count++;
}, 10);
}
});
};
/*
* layer = getLayer()
* keyframes = [
* {
* path: ['fontVariationAxes','Weight'],
* keyframes: [
* {
* "id": "yHFP-HCINm", // not sure if used when sent back
* "position": 0,
* "connectedRight": true, // optional
* "handles": [ 0.5, 1, 0.5, 0 ], // optional
* "type": "bezier", // optional
* "value": 200
* }, ...
* ]
* }, ...
* ]
*/
const addKeyframes = (layer, keyframes) => { const addKeyframes = (layer, keyframes) => {
return new Promise((resolve) => { return new Promise((resolve) => {
if (!Array.isArray(keyframes)) {
resolve(false);
return false;
}
const existingKeyframes = getKeyframes(layer);
const promises = []; const promises = [];
const ms = 0; //config.tp.addKeyframesTimeout_s * 1000;
keyframes.forEach((k) => { keyframes.forEach((k) => {
let prop = layer.theatreObject.props;
for (let i = 0; i < k.path.length; i++) {
prop = prop[k.path[i]];
}
const position = tp.sheet.sequence.position;
promises.push(() => { promises.push(() => {
return new Promise((subResolve) => { return new Promise((subResolve) => {
setTimeout(() => { let prop = layer.theatreObject.props;
if (layer.isSelected()) { for (let i = 0; i < k.path.length; i++) {
setSequenced(k.path.join('.'), true) prop = prop[k.path[i]];
.then(() => {
subResolve();
});
} else {
// we cannot select layers without pseudoclicking
// so let's wait for a happy 'injected' event that
// closes off the selection
//
// first, the listener callback
const f = () => {
tp.getPanel().removeEventListener('injected', f);
setSequenced(k.path.join('.'), true)
.then(() => {
subResolve();
});
};
// then add it
tp.getPanel().addEventListener('injected', f);
// and fire the click
layer.select();
}
}, ms); // * promises.length);
})
});
let propHasKeyframesAt = -1;
if (existingKeyframes !== null &&
existingKeyframes !== false &&
typeof existingKeyframes !== 'undefined' &&
Array.isArray(existingKeyframes)) {
existingKeyframes.forEach((existingK, existingKI) => {
if (arraysEqual(k.path, existingK.path)) {
propHasKeyframesAt = existingKI;
} }
}); setSequenced(k.path, true, layer).then(() => {
} tp.studio.transaction(({
k.keyframes.forEach((keyframe) => { __experimental_addKeyframes
let alreadyThere = false; }) => {
if (propHasKeyframesAt >= 0) { __experimental_addKeyframes(prop, k.keyframes);
existingKeyframes[propHasKeyframesAt].keyframes.forEach((kf) => { });
if (keyframe.position === kf.position &&
keyframe.value === kf.value) {
alreadyThere = true;
}
});
}
if (!alreadyThere) {
promises.push(() => {
return new Promise((subResolve) => {
setTimeout(() => {
tp.sheet.sequence.position = keyframe.position;
this.studio.transaction(({
set
}) => {
set(prop, keyframe.value);
subResolve();
});
}, ms); // * promises.length);
})
});
}
});
promises.push(() => {
return new Promise((subResolve) => {
setTimeout(() => {
tp.sheet.sequence.position = position;
subResolve(); subResolve();
}, ms); // * promises.length); });
}) });
}); });
}); });
sequencialPromises(promises, resolve); sequencialPromises(promises, resolve);
//Promise.all(promises).then(() => {
//resolve();
//});
}); });
}; };
// NOTE: instead of setting proptitle static and then sequenced again,
// we could simply delete all keyframes. but hey, pfff...
const setKeyframes = (layer, keyframes) => { const setKeyframes = (layer, keyframes) => {
return new Promise((resolve) => { return new Promise((resolve) => {
if (!Array.isArray(keyframes)) { if (!Array.isArray(keyframes)) {
@ -1228,17 +1142,13 @@ const TheatrePlay = function(autoInit = false) {
console.log('TheatrePlay::loadProject'); console.log('TheatrePlay::loadProject');
this.isProjectLoaded = false; this.isProjectLoaded = false;
return new Promise((resolve) => { return new Promise((resolve) => {
console.log('this is happening');
if (projectId === false) { if (projectId === false) {
projectId = this.sheet.project.address.projectId; projectId = this.sheet.project.address.projectId;
console.log('this is happening');
} }
if (project === false) { if (project === false) {
project = this.getProject(projectId, true); project = this.getProject(projectId, true);
console.log('this is happening');
} }
if (project !== false) { // if project is not saved yet, create new if (project !== false) { // if project is not saved yet, create new
console.log('this is happening');
// get all objects // get all objects
const objects = project const objects = project
.theatre .theatre
@ -1282,17 +1192,12 @@ const TheatrePlay = function(autoInit = false) {
.filter((e) => e.indexOf('layer-') === 0) .filter((e) => e.indexOf('layer-') === 0)
.forEach((layerId) => { .forEach((layerId) => {
window.project_fontsHashMap = project.fontsHashMap; window.project_fontsHashMap = project.fontsHashMap;
console.log(layerId, objects[layerId]);
layerPromises.push(window.addExistingLayer(layerId, objects[layerId])); layerPromises.push(window.addExistingLayer(layerId, objects[layerId]));
}); });
console.log('this is happening');
console.log({layerPromises});
Promise.all(layerPromises).then(() => { Promise.all(layerPromises).then(() => {
console.log('this is happening');
window.layerOrder.set(project.layerOrder); window.layerOrder.set(project.layerOrder);
this.duration = this.core.val(this.sheet.sequence.pointer.length); this.duration = this.core.val(this.sheet.sequence.pointer.length);
if (project.layerOrder.length > 0) { if (project.layerOrder.length > 0) {
console.log('this is happening');
getLayers().forEach((layer) => { getLayers().forEach((layer) => {
if (layer.id() === project.layerOrder[project.layerOrder.length - 1]) { if (layer.id() === project.layerOrder[project.layerOrder.length - 1]) {
layer.select(); layer.select();
@ -1308,37 +1213,29 @@ const TheatrePlay = function(autoInit = false) {
}); });
} }
resolve(); resolve();
console.log('RESOLVED');
this.isProjectLoaded = true; this.isProjectLoaded = true;
}); });
} else { } else {
console.log('this is happening');
if (getLayers().length === 0 && config.layer.autoCreateFirstLayer) { if (getLayers().length === 0 && config.layer.autoCreateFirstLayer) {
console.log('this is happening');
getFontsAndAxes().then((newFontsAndAxes) => { getFontsAndAxes().then((newFontsAndAxes) => {
console.log('this is happening');
const autoInitLayer = false; const autoInitLayer = false;
const layer = addLayer(autoInitLayer); const layer = addLayer(autoInitLayer);
layer.init().then(() => { layer.init().then(() => {
layer.select(); layer.select();
this.duration = this.core.val(this.sheet.sequence.pointer.length); this.duration = this.core.val(this.sheet.sequence.pointer.length);
resolve(); resolve();
console.log('RESOLVED');
this.isProjectLoaded = true; this.isProjectLoaded = true;
}); });
}); });
} else { } else {
console.log('this is happening');
const layers = getLayers(); const layers = getLayers();
if (layers.length > 0) { if (layers.length > 0) {
} }
this.duration = this.core.val(this.sheet.sequence.pointer.length); this.duration = this.core.val(this.sheet.sequence.pointer.length);
resolve(); resolve();
console.log('RESOLVED');
this.isProjectLoaded = true; this.isProjectLoaded = true;
} }
} }
console.log('this is happening and there was no resolve?');
}); });
}; };
this.startNewProject = () => { this.startNewProject = () => {

View file

@ -472,6 +472,18 @@ const deFlattenObject = (o, ignoreKeys = [], pathSymbol = '.') => {
}); });
}; };
const getNestedProperty = (o, a, verify = false) => {
if (verify && (!Array.isArray(a) || typeof o !== "object" || !o.hasOwnProperty(a[0]))) {
return false;
}
let b = clone(a);
if (b.length > 1) {
o = o[b.shift()];
return getNestedProperty(o, b, verify);
}
return o[b[0]];
};
///////////////////////////////////// /////////////////////////////////////
// you can test these functions in // you can test these functions in
// the browser like so: // the browser like so:
@ -507,4 +519,5 @@ export {
renameProperty, renameProperty,
flattenObject, flattenObject,
deFlattenObject, deFlattenObject,
getNestedProperty,
} }