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;
|
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 = () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -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();
|
||||||
});
|
});
|
||||||
|
|
|
@ -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 = () => {
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue