so much faster keyframe adding
This commit is contained in:
parent
d95ec3d965
commit
f18bafc543
4 changed files with 85 additions and 176 deletions
|
@ -430,7 +430,7 @@ window.getLayers = () => {
|
|||
return layers;
|
||||
};
|
||||
|
||||
window.getLayer = (layerID) => {
|
||||
window.getLayer = (layerID = tp.studio.selection[0].address.objectKey) => {
|
||||
if (layerID === 'artboard') {
|
||||
return artboard;
|
||||
} else {
|
||||
|
@ -610,5 +610,4 @@ const initPanels = () => {
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -431,7 +431,7 @@ const Record = function(tp) {
|
|||
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();
|
||||
});
|
||||
isRecording = RECORDING;
|
||||
|
@ -502,7 +502,7 @@ const Record = function(tp) {
|
|||
const kf = clone(keyframes);
|
||||
promises.push(() => {
|
||||
return new Promise((subResolve) => {
|
||||
tp.setKeyframes(layer, keyframes).then(() => {
|
||||
tp.addKeyframes(layer, keyframes).then(() => {
|
||||
layer.updateValuesViaTheatre(true);
|
||||
subResolve();
|
||||
});
|
||||
|
|
|
@ -8,6 +8,7 @@ import {
|
|||
getParents,
|
||||
arraysEqual,
|
||||
sequencialPromises,
|
||||
getNestedProperty,
|
||||
} from './utils.js';
|
||||
|
||||
//import {
|
||||
|
@ -141,177 +142,90 @@ const TheatrePlay = function(autoInit = false) {
|
|||
}
|
||||
return t.parentElement.querySelector('[title="Sequence this prop"]');
|
||||
};
|
||||
const isSequenced = (path) => {
|
||||
return getSequenceButton(path) === null;
|
||||
};
|
||||
|
||||
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 isSequenced = (path, layer = getLayer()) => {
|
||||
if (!Array.isArray(path)) {
|
||||
path = path.split('.');
|
||||
}
|
||||
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) => {
|
||||
return new Promise((resolve) => {
|
||||
if (!Array.isArray(keyframes)) {
|
||||
resolve(false);
|
||||
return false;
|
||||
}
|
||||
const existingKeyframes = getKeyframes(layer);
|
||||
const promises = [];
|
||||
const ms = 0; //config.tp.addKeyframesTimeout_s * 1000;
|
||||
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(() => {
|
||||
return new Promise((subResolve) => {
|
||||
setTimeout(() => {
|
||||
if (layer.isSelected()) {
|
||||
setSequenced(k.path.join('.'), true)
|
||||
.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;
|
||||
let prop = layer.theatreObject.props;
|
||||
for (let i = 0; i < k.path.length; i++) {
|
||||
prop = prop[k.path[i]];
|
||||
}
|
||||
});
|
||||
}
|
||||
k.keyframes.forEach((keyframe) => {
|
||||
let alreadyThere = false;
|
||||
if (propHasKeyframesAt >= 0) {
|
||||
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;
|
||||
setSequenced(k.path, true, layer).then(() => {
|
||||
tp.studio.transaction(({
|
||||
__experimental_addKeyframes
|
||||
}) => {
|
||||
__experimental_addKeyframes(prop, k.keyframes);
|
||||
});
|
||||
subResolve();
|
||||
}, ms); // * promises.length);
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
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) => {
|
||||
return new Promise((resolve) => {
|
||||
if (!Array.isArray(keyframes)) {
|
||||
|
@ -1228,17 +1142,13 @@ const TheatrePlay = function(autoInit = false) {
|
|||
console.log('TheatrePlay::loadProject');
|
||||
this.isProjectLoaded = false;
|
||||
return new Promise((resolve) => {
|
||||
console.log('this is happening');
|
||||
if (projectId === false) {
|
||||
projectId = this.sheet.project.address.projectId;
|
||||
console.log('this is happening');
|
||||
}
|
||||
if (project === false) {
|
||||
project = this.getProject(projectId, true);
|
||||
console.log('this is happening');
|
||||
}
|
||||
if (project !== false) { // if project is not saved yet, create new
|
||||
console.log('this is happening');
|
||||
// get all objects
|
||||
const objects = project
|
||||
.theatre
|
||||
|
@ -1282,17 +1192,12 @@ const TheatrePlay = function(autoInit = false) {
|
|||
.filter((e) => e.indexOf('layer-') === 0)
|
||||
.forEach((layerId) => {
|
||||
window.project_fontsHashMap = project.fontsHashMap;
|
||||
console.log(layerId, objects[layerId]);
|
||||
layerPromises.push(window.addExistingLayer(layerId, objects[layerId]));
|
||||
});
|
||||
console.log('this is happening');
|
||||
console.log({layerPromises});
|
||||
Promise.all(layerPromises).then(() => {
|
||||
console.log('this is happening');
|
||||
window.layerOrder.set(project.layerOrder);
|
||||
this.duration = this.core.val(this.sheet.sequence.pointer.length);
|
||||
if (project.layerOrder.length > 0) {
|
||||
console.log('this is happening');
|
||||
getLayers().forEach((layer) => {
|
||||
if (layer.id() === project.layerOrder[project.layerOrder.length - 1]) {
|
||||
layer.select();
|
||||
|
@ -1308,37 +1213,29 @@ const TheatrePlay = function(autoInit = false) {
|
|||
});
|
||||
}
|
||||
resolve();
|
||||
console.log('RESOLVED');
|
||||
this.isProjectLoaded = true;
|
||||
});
|
||||
} else {
|
||||
console.log('this is happening');
|
||||
if (getLayers().length === 0 && config.layer.autoCreateFirstLayer) {
|
||||
console.log('this is happening');
|
||||
getFontsAndAxes().then((newFontsAndAxes) => {
|
||||
console.log('this is happening');
|
||||
const autoInitLayer = false;
|
||||
const layer = addLayer(autoInitLayer);
|
||||
layer.init().then(() => {
|
||||
layer.select();
|
||||
this.duration = this.core.val(this.sheet.sequence.pointer.length);
|
||||
resolve();
|
||||
console.log('RESOLVED');
|
||||
this.isProjectLoaded = true;
|
||||
});
|
||||
});
|
||||
} else {
|
||||
console.log('this is happening');
|
||||
const layers = getLayers();
|
||||
if (layers.length > 0) {
|
||||
}
|
||||
this.duration = this.core.val(this.sheet.sequence.pointer.length);
|
||||
resolve();
|
||||
console.log('RESOLVED');
|
||||
this.isProjectLoaded = true;
|
||||
}
|
||||
}
|
||||
console.log('this is happening and there was no resolve?');
|
||||
});
|
||||
};
|
||||
this.startNewProject = () => {
|
||||
|
|
|
@ -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
|
||||
// the browser like so:
|
||||
|
@ -507,4 +519,5 @@ export {
|
|||
renameProperty,
|
||||
flattenObject,
|
||||
deFlattenObject,
|
||||
getNestedProperty,
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue