2023-09-24 18:39:52 +02:00
|
|
|
const Record = function(tp) {
|
|
|
|
|
|
|
|
const hot = {};
|
2023-09-28 16:41:11 +02:00
|
|
|
let isRecording = false;
|
2023-09-24 18:39:52 +02:00
|
|
|
|
2023-09-28 16:41:11 +02:00
|
|
|
const addRecordButton = (layer, propTitle) => {
|
2023-09-24 18:39:52 +02:00
|
|
|
const panel = tp.getPanel();
|
|
|
|
const panelPropTitle = tp.getPanelPropTitle(propTitle);
|
|
|
|
if (panelPropTitle !== null) {
|
|
|
|
const container = tp.getPanelPropContainer(panelPropTitle);
|
|
|
|
if (container === null) {
|
|
|
|
console.log("Record::addRecordButton",
|
|
|
|
`impossible! cannot find panelPropContainer for ${propTitle}`);
|
|
|
|
} else if (container.querySelector('.recordButton') !== null) {
|
2023-09-28 16:41:11 +02:00
|
|
|
// this is super verbose, let's not log by default
|
|
|
|
//console.log("Record::addRecordButton",
|
|
|
|
//`already added an record button for ${propTitle}`);
|
2023-09-24 18:39:52 +02:00
|
|
|
} else {
|
|
|
|
const button = document.createElement('div');
|
|
|
|
button.classList.add('recordButton');
|
|
|
|
button.classList.add(`recordButton${propTitle}`);
|
|
|
|
button.innerHTML = `<img src="/web/assets/record.svg" alt="record" />`;
|
|
|
|
container.append(button);
|
|
|
|
button.addEventListener('click', () => {
|
|
|
|
if (!hot.hasOwnProperty(layer.id())) {
|
|
|
|
hot[layer.id()] = {};
|
|
|
|
}
|
|
|
|
if (!hot[layer.id()].hasOwnProperty(propTitle)) {
|
2023-09-28 16:41:11 +02:00
|
|
|
hot[layer.id()][propTitle] = {
|
|
|
|
recording: [],
|
|
|
|
};
|
2023-09-24 18:39:52 +02:00
|
|
|
button.classList.add('active');
|
2023-09-28 16:41:11 +02:00
|
|
|
startRecording();
|
2023-09-24 18:39:52 +02:00
|
|
|
} else {
|
2023-09-28 16:41:11 +02:00
|
|
|
stopRecording();
|
2023-09-24 18:39:52 +02:00
|
|
|
delete hot[layer.id()][propTitle];
|
|
|
|
if (Object.keys(hot[layer.id()]).length === 0) {
|
|
|
|
delete hot[layer.id()];
|
|
|
|
}
|
|
|
|
button.classList.remove('active');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
console.log("Record::addRecordButton",
|
|
|
|
`cannot find panelPropTitle for ${propTitle}`);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-09-28 16:41:11 +02:00
|
|
|
const cloneInput = (layer, propTitle) => {
|
|
|
|
const panel = tp.getPanel();
|
|
|
|
const panelPropTitle = tp.getPanelPropTitle(propTitle);
|
|
|
|
if (panelPropTitle !== null) {
|
|
|
|
const container = tp.getPanelPropContainer(panelPropTitle);
|
|
|
|
if (container === null) {
|
|
|
|
console.log("Record::cloneInput",
|
|
|
|
`impossible! cannot find panelPropContainer for ${propTitle}`);
|
|
|
|
} else if (container.querySelector('input.recording') !== null) {
|
|
|
|
console.log("Record::cloneInput",
|
|
|
|
`already cloned input for ${propTitle}`);
|
|
|
|
} else {
|
|
|
|
const input = container.querySelector('input');
|
|
|
|
if (input === null) {
|
|
|
|
console.log("Record::cloneInput",
|
|
|
|
`uuh.. seems there is no input to clone for ${propTitle}`);
|
|
|
|
} else {
|
|
|
|
const input_clone = input.cloneNode();
|
|
|
|
input_clone.classList.value = '';
|
|
|
|
input_clone.classList.add('recording');
|
|
|
|
input.parentNode.after(input_clone);
|
|
|
|
input.setAttribute('data-previousDisplay', input.style.display);
|
|
|
|
input.style.display = 'none';
|
|
|
|
return input_clone;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
};
|
|
|
|
|
|
|
|
const uncloneInput = (layer, propTitle) => {
|
|
|
|
const panel = tp.getPanel();
|
|
|
|
const panelPropTitle = tp.getPanelPropTitle(propTitle);
|
|
|
|
if (panelPropTitle !== null) {
|
|
|
|
const container = tp.getPanelPropContainer(panelPropTitle);
|
|
|
|
if (container === null) {
|
|
|
|
console.log("Record::uncloneInput",
|
|
|
|
`impossible! cannot find panelPropContainer for ${propTitle}`);
|
|
|
|
} else if (container.querySelector('input.recording') === null) {
|
|
|
|
console.log("Record::uncloneInput",
|
|
|
|
`already uncloned input for ${propTitle}`);
|
|
|
|
} else {
|
|
|
|
const input = container.querySelector('input:not(.recording)');
|
|
|
|
const input_clone = container.querySelector('input.recording');
|
|
|
|
if (input === null ) {
|
|
|
|
console.log("Record::uncloneInput",
|
|
|
|
`uuh.. seems there is no input for ${propTitle}`);
|
|
|
|
} else if (input_clone === null ) {
|
|
|
|
console.log("Record::uncloneInput",
|
|
|
|
`uuh.. seems there is no input_clone for ${propTitle}`);
|
|
|
|
} else {
|
|
|
|
input_clone.remove();
|
|
|
|
input.removeAttribute('data-previousDisplay');
|
|
|
|
const previousInputDisplay = input.getAttribute('data-previousDisplay');
|
|
|
|
input.style.display = previousInputDisplay;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const injectPanel = (layer) => {
|
|
|
|
const props = Object.keys(layer.theatreObject.value);
|
|
|
|
props.forEach((propTitle) => {
|
|
|
|
if (config.record.ignoreProps.indexOf(propTitle) < 0) {
|
|
|
|
addRecordButton(layer, propTitle);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
const startRecording = () => {
|
|
|
|
tp.sheet.sequence.pause();
|
|
|
|
const layerKeys = Object.keys(hot);
|
|
|
|
layerKeys.forEach((layerID) => {
|
|
|
|
const layer = getLayer(layerID);
|
|
|
|
layer.updateValuesViaTheatre(false);
|
|
|
|
const propTitles = Object.keys(hot[layerID]);
|
|
|
|
propTitles.forEach((propTitle) => {
|
|
|
|
// NOTE: layerID is not actually used atm
|
|
|
|
// and should be the layer anyways
|
|
|
|
const input_clone = cloneInput(layerID, propTitle);
|
|
|
|
if (input_clone !== null) {
|
|
|
|
input_clone.addEventListener('change', (e) => {
|
|
|
|
hot[layerID][propTitle].recording.push({
|
|
|
|
position: tp.sheet.sequence.position,
|
|
|
|
value: parseFloat(input_clone.value),
|
|
|
|
});
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
console.log('whoops input_clone is null');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
tp.sheet.sequence.position = 0;
|
|
|
|
tp.sheet.sequence.play();
|
|
|
|
});
|
|
|
|
isRecording = true;
|
|
|
|
};
|
|
|
|
const stopRecording = () => {
|
|
|
|
console.log('stoprecording');
|
|
|
|
const layerKeys = Object.keys(hot);
|
|
|
|
console.log({layerKeys});
|
|
|
|
layerKeys.forEach((layerID) => {
|
|
|
|
console.log(layerID);
|
|
|
|
const layer = getLayer(layerID);
|
|
|
|
layer.updateValuesViaTheatre(true);
|
|
|
|
const propTitles = Object.keys(hot[layerID]);
|
|
|
|
const keyframes = [];
|
|
|
|
propTitles.forEach((propTitle) => {
|
|
|
|
console.log(propTitle);
|
|
|
|
// NOTE: layerID is not actually used atm
|
|
|
|
// and should be the layer anyways
|
|
|
|
uncloneInput(layerID, propTitle);
|
|
|
|
console.log('should have uncloned input for ' + propTitle);
|
|
|
|
keyframes.push({
|
|
|
|
path: [propTitle],
|
|
|
|
keyframes: hot[layerID][propTitle].recording,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
setTimeout(() => {
|
|
|
|
console.log('adding the keyframes now because we wnat it to happen right now please');
|
|
|
|
tp.addKeyframes(layer, keyframes);
|
|
|
|
}, 2000);
|
|
|
|
});
|
|
|
|
isRecording = false;
|
|
|
|
};
|
|
|
|
|
2023-09-24 18:39:52 +02:00
|
|
|
// public
|
|
|
|
this.addRecordButton = addRecordButton;
|
2023-09-28 16:41:11 +02:00
|
|
|
this.getHot = () => {
|
|
|
|
return hot;
|
|
|
|
};
|
|
|
|
this.isRecording = () => {
|
|
|
|
return isRecording;
|
|
|
|
};
|
|
|
|
this.injectPanel = injectPanel;
|
|
|
|
this.startRecording = startRecording;
|
|
|
|
this.stopRecording = stopRecording;
|
2023-09-24 18:39:52 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
export {
|
|
|
|
Record
|
|
|
|
}
|