audioLayer panel injection
dependencies hashes: openFrameworks d78075f4bca6be2a2533c6e51a75cc1f18404501 ofxMsdfgen e14da13d02c4dff04fb69d7923469f606924e6c3 ofxGPUFont d482bb7cbdf6b296fa4ab5abcf73fb5ff8c8b239 ofxVariableLab 0b5f9bdebc1e5550621957e73c040c258ec6317b ofxProfiler a868e34fa1a79189dd4fbdede2938e308535e5e8 theatre 15b2b9543be7a9ed5c8889e04df715f91d479d45
This commit is contained in:
parent
8353bb837c
commit
3b6a57024d
6 changed files with 281 additions and 46 deletions
|
@ -732,3 +732,19 @@ input:disabled {
|
|||
background: darkgrey;
|
||||
color: lightgrey;
|
||||
}
|
||||
|
||||
/* ASYA: most the following code does not work*/
|
||||
.onOffIndicatorWrapper input[type=checkbox] + label::after {
|
||||
content: ' OFF';
|
||||
}
|
||||
|
||||
.onOffIndicatorWrapper input[type=checkbox]:checked + label{
|
||||
color: #1cba94;
|
||||
}
|
||||
|
||||
.onOffIndicatorWrapper input[type=checkbox]:checked + label::after{
|
||||
content: ' ON';
|
||||
}
|
||||
.onOffIndicatorWrapper {
|
||||
width: auto;
|
||||
}
|
||||
|
|
|
@ -1,26 +1,28 @@
|
|||
import {
|
||||
sanitizeTheatreKey,
|
||||
arraysEqual,
|
||||
clone,
|
||||
} from './utils.js';
|
||||
|
||||
const AudioLayer = function(tp, audioLayerID, values = false, autoInit = true) {
|
||||
// private
|
||||
let props = { };
|
||||
if (typeof values === 'string') {
|
||||
const filename = sanitizeTheatreKey(values);
|
||||
const audioID = sanitizeTheatreKey(values);
|
||||
values = {};
|
||||
values[filename] = false;
|
||||
values[audioID] = false;
|
||||
}
|
||||
if (typeof values === 'object') {
|
||||
props[Object.keys(values)[0]] = tp.core.types.boolean(false);
|
||||
}
|
||||
|
||||
const onValuesChangeCallbacks = [];
|
||||
let hierarchyPanelButton = null;
|
||||
let panelFinderTimeout = false;
|
||||
|
||||
// private functions
|
||||
//
|
||||
const onValuesChange = (values) => {
|
||||
console.log(values);
|
||||
const n_callbacks = onValuesChangeCallbacks.length;
|
||||
const successes = [];
|
||||
if (n_callbacks > 0) {
|
||||
|
@ -38,18 +40,173 @@ const AudioLayer = function(tp, audioLayerID, values = false, autoInit = true) {
|
|||
});
|
||||
}
|
||||
};
|
||||
|
||||
const findInjectPanel = () => {
|
||||
console.log('AudioLayer::findInjectPanel');
|
||||
const sequencePanel = tp.getSequencePanel();
|
||||
const sequencePanelLeft = tp.getSequencePanelLeft();
|
||||
const getHierarchyPanelButton = () => {
|
||||
if (hierarchyPanelButton === null) {
|
||||
hierarchyPanelButton = tp.shadowRoot.querySelector(`.layerMover${this.id()}`);
|
||||
}
|
||||
return hierarchyPanelButton;
|
||||
};
|
||||
|
||||
const setTime = (filename, start, stop) => {
|
||||
filename = sanitizeTheatreKey(filename);
|
||||
const getPanelPropDiamond = (panelPropTitle) => {
|
||||
return panelPropTitle.previousSibling;
|
||||
};
|
||||
|
||||
const getPanelPropInput = (panelPropTitle) => {
|
||||
return panelPropTitle
|
||||
.parentElement
|
||||
.nextSibling
|
||||
.querySelector('input');
|
||||
};
|
||||
|
||||
const findInjectPanel = () => {
|
||||
let doItAgain = true;
|
||||
|
||||
console.log('AudioLayer::findInjectPanel');
|
||||
const panel = tp.getPanel();
|
||||
|
||||
let panelSuccesses = 0;
|
||||
const audioIDs = Object.keys(this.theatreObject.value);
|
||||
{ // PANEL
|
||||
for (let i = 0; i < audioIDs.length; i++) {
|
||||
const audioID = audioIDs[i];
|
||||
let panelPropTitle = tp.getPanelPropTitle(audioID);
|
||||
const panelPropContainer = tp.getPanelPropContainer(panelPropTitle);
|
||||
if (panelPropTitle === null || panelPropContainer == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Phase 1) prevent unwanted interaction
|
||||
|
||||
// remove theatrejs listeners
|
||||
// such as contextmenu
|
||||
// NOTE: this does not work with stop(Immediate)Propagation here
|
||||
const tmp = panelPropTitle.cloneNode(true);
|
||||
panelPropTitle.parentNode.replaceChild(tmp, panelPropTitle);
|
||||
panelPropTitle = tmp;
|
||||
|
||||
// remove diamond
|
||||
const diamond = getPanelPropDiamond(panelPropTitle);
|
||||
if (diamond !== null) {
|
||||
diamond.remove();
|
||||
}
|
||||
// unchangeable boolean
|
||||
const boolean = getPanelPropInput(panelPropTitle);
|
||||
boolean.disabled = true;
|
||||
boolean.parentElement.classList.add('onOffIndicatorWrapper');
|
||||
boolean.classList.add('onOffIndicator');
|
||||
boolean.style.width = 'auto';
|
||||
|
||||
const container = document.createElement('div');
|
||||
container.innerHTML = `
|
||||
<div class="main_panel_button button delete${audioID}">
|
||||
delete
|
||||
</div>
|
||||
`;
|
||||
for (let i = 0; i < container.children.length; i++) {
|
||||
panelPropContainer.append(container.children[i]);
|
||||
};
|
||||
panelPropContainer.querySelector(`.button.delete${audioID}`)
|
||||
.addEventListener('click', () => {
|
||||
this.removeFile(audioID);
|
||||
});
|
||||
|
||||
panelSuccesses++;
|
||||
};
|
||||
}
|
||||
if (panelSuccesses === audioIDs.length) {
|
||||
doItAgain = false;
|
||||
}
|
||||
|
||||
if (doItAgain) {
|
||||
clearTimeout(panelFinderTimeout);
|
||||
panelFinderTimeout = setTimeout(() => {
|
||||
this.findInjectPanel();
|
||||
}, 30);
|
||||
}
|
||||
}
|
||||
const findInjectSequencePanel = () => {
|
||||
let doItAgain = true;
|
||||
let sequencePanelSuccess = 0;
|
||||
const sequencePanel = tp.getSequencePanel();
|
||||
const sequencePanelLeft = tp.getSequencePanelLeft();
|
||||
if (sequencePanelLeft !== null) { // SEQUENCE PANEL LEFT
|
||||
const propTitles = sequencePanelLeft.querySelectorAll('[data-testid="SequencePanel-PropTitle"]');
|
||||
const audioLayerTitle = (() => {
|
||||
const titles = sequencePanelLeft.querySelectorAll('[data-testid="SequencePanel-Title"]');
|
||||
for (let i = 0; i < titles.length; i++) {
|
||||
if (titles[i].innerHTML === this.id()) {
|
||||
return titles[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
})();
|
||||
if (audioLayerTitle !== null) {
|
||||
const audioSection = audioLayerTitle.closest('li');
|
||||
if (audioSection !== null) {
|
||||
const audioPropTitles = audioSection.querySelectorAll('[data-testid="SequencePanel-PropTitle"]');
|
||||
window.audioPropTitles = audioPropTitles;
|
||||
audioPropTitles.forEach((audioPropTitle) => {
|
||||
const diamond = (() => {
|
||||
const potential = audioPropTitle.nextSibling;
|
||||
if (potential !== null
|
||||
&& potential.nodeName.toLowerCase() === 'div'
|
||||
&& potential.querySelectorAll(':scope > [data-pi-key]').length === 3) {
|
||||
return potential;
|
||||
}
|
||||
return null;
|
||||
})();
|
||||
if (diamond !== null) {
|
||||
diamond.style.display = 'none';
|
||||
}
|
||||
if (audioPropTitle.innerHTML.length > config.audio.maxFilenameLength) {
|
||||
const file = audioPropTitle.innerHTML;
|
||||
const m = (config.audio.maxFilenameLength / 2) - 2;
|
||||
audioPropTitle.innerHTML = file.substr(0,m) + '..' + file.substr(file.length - m, m);
|
||||
}
|
||||
});
|
||||
sequencePanelSuccess++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sequencePanelLeft !== null) { // SEQUENCE PANEL RIGHT
|
||||
const audioSectionAnchor = sequencePanelLeft
|
||||
.nextSibling
|
||||
.querySelector(`[data-pi-key*="${this.id()}"]`);
|
||||
if (audioSectionAnchor !== null) {
|
||||
const audioSection = audioSectionAnchor.closest('li');
|
||||
if (audioSection !== null) {
|
||||
audioSection.addEventListener('contextmenu', (e) => {
|
||||
e.stopPropagation();
|
||||
e.stopImmediatePropagation();
|
||||
});
|
||||
audioSection.querySelectorAll('*').forEach((element) => {
|
||||
element.addEventListener('contextmenu', (e) => {
|
||||
e.stopPropagation();
|
||||
e.stopImmediatePropagation();
|
||||
});
|
||||
});
|
||||
sequencePanelSuccess++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sequencePanelSuccess === 2) {
|
||||
doItAgain = false;
|
||||
}
|
||||
|
||||
if (doItAgain) {
|
||||
clearTimeout(panelFinderTimeout);
|
||||
panelFinderTimeout = setTimeout(() => {
|
||||
this.findInjectSequencePanel();
|
||||
}, 30);
|
||||
}
|
||||
};
|
||||
|
||||
const setTime = (audioID, start, stop) => {
|
||||
audioID = sanitizeTheatreKey(audioID);
|
||||
return new Promise((resolve) => {
|
||||
const keyframes = [{
|
||||
path: [filename],
|
||||
path: [audioID],
|
||||
keyframes: [{
|
||||
position: -1,
|
||||
value: false,
|
||||
|
@ -67,11 +224,11 @@ const AudioLayer = function(tp, audioLayerID, values = false, autoInit = true) {
|
|||
},
|
||||
],
|
||||
}];
|
||||
if (tp.getKeyframes(this, [filename]).length > 0) {
|
||||
if (tp.getKeyframes(this, [audioID]).length > 0) {
|
||||
tp.studio.transaction(({
|
||||
__experimental_deleteKeyframes
|
||||
}) => {
|
||||
__experimental_deleteKeyframes(this.theatreObject.props[filename]);
|
||||
__experimental_deleteKeyframes(this.theatreObject.props[audioID]);
|
||||
});
|
||||
}
|
||||
tp.addKeyframes(this, keyframes).then(() => {
|
||||
|
@ -80,6 +237,15 @@ const AudioLayer = function(tp, audioLayerID, values = false, autoInit = true) {
|
|||
});
|
||||
};
|
||||
|
||||
const getValue = (audioID) => {
|
||||
const values = this.theatreObject.value;
|
||||
if (typeof values[audioID] !== 'undefined') {
|
||||
return values[audioID];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const init = () => {
|
||||
return new Promise((resolve) => {
|
||||
this.theatreObject = tp.addObject(audioLayerID, this.props, onValuesChange);
|
||||
|
@ -97,33 +263,21 @@ const AudioLayer = function(tp, audioLayerID, values = false, autoInit = true) {
|
|||
};
|
||||
|
||||
const remove = () => {
|
||||
tp.removeObject(audioLayerID);
|
||||
};
|
||||
|
||||
// public
|
||||
this.props = props;
|
||||
|
||||
this.findInjectPanel = findInjectPanel;
|
||||
this.findInjectSequencePanel = findInjectSequencePanel;
|
||||
|
||||
this.setFile = (filename) => {
|
||||
filename = sanitizeTheatreKey(filename);
|
||||
const values = {};
|
||||
values[filename] = false;
|
||||
props = {};
|
||||
props[filename] = tp.core.types.boolean(values[filename]);
|
||||
this.props = props;
|
||||
tp.changeObject(audioLayerID, this.props);
|
||||
tp.studio.transaction(({
|
||||
set
|
||||
}) => {
|
||||
set(this.theatreObject.props, values);
|
||||
});
|
||||
};
|
||||
this.addFile = (filename) => {
|
||||
this.addFile = (audioID) => {
|
||||
return new Promise((resolve) => {
|
||||
filename = sanitizeTheatreKey(filename);
|
||||
audioID = sanitizeTheatreKey(audioID);
|
||||
const values = this.theatreObject.value;
|
||||
values[filename] = false;
|
||||
props[filename] = tp.core.types.boolean(values[filename]);
|
||||
values[audioID] = false;
|
||||
props[audioID] = tp.core.types.boolean(values[audioID]);
|
||||
this.props = props;
|
||||
|
||||
const setDummy = () => {
|
||||
|
@ -154,12 +308,12 @@ const AudioLayer = function(tp, audioLayerID, values = false, autoInit = true) {
|
|||
setDummy();
|
||||
});
|
||||
};
|
||||
this.removeFile = (filename) => {
|
||||
this.removeFile = (audioID) => {
|
||||
return new Promise((resolve) => {
|
||||
filename = sanitizeTheatreKey(filename);
|
||||
const values = this.theatreObject.value;
|
||||
delete values[filename];
|
||||
delete props[filename];
|
||||
audioID = sanitizeTheatreKey(audioID);
|
||||
const values = clone(this.theatreObject.value);
|
||||
delete values[audioID];
|
||||
delete props[audioID];
|
||||
this.props = props;
|
||||
const setDummy = () => {
|
||||
tp.changeObject(audioLayerID, {
|
||||
|
@ -175,16 +329,53 @@ const AudioLayer = function(tp, audioLayerID, values = false, autoInit = true) {
|
|||
const givenValueKeys = Object.keys(againChangedValues);
|
||||
if (arraysEqual(expectedValueKeys, givenValueKeys)) {
|
||||
resolve();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
tp.changeObject(audioLayerID, this.props);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
setDummy();
|
||||
|
||||
if (!audio.audioPlayer.remove(audioID)) {
|
||||
console.log('AudioLayer::remove', `could not remove ${audioID} from audioPlayer`);
|
||||
}
|
||||
});
|
||||
};
|
||||
this.setTime = setTime;
|
||||
|
||||
this.getValue = getValue;
|
||||
|
||||
this.isSelected = () => {
|
||||
const panel = getHierarchyPanelButton();
|
||||
if (panel === null) {
|
||||
return false;
|
||||
} else {
|
||||
const notSelected = panel.querySelector('.not-selected');
|
||||
return !notSelected;
|
||||
}
|
||||
};
|
||||
|
||||
this.select = () => {
|
||||
const panel = getHierarchyPanelButton();
|
||||
const selectables = panel.querySelector('.not-selected');
|
||||
if (selectables !== null && typeof selectables.dispatchEvent === 'function') {
|
||||
var clickEvent = new MouseEvent("click", {
|
||||
"view": window,
|
||||
"bubbles": true,
|
||||
"cancelable": false
|
||||
});
|
||||
selectables.dispatchEvent(clickEvent);
|
||||
} else {
|
||||
window.debugElement = panel;
|
||||
}
|
||||
};
|
||||
|
||||
this.init = init;
|
||||
|
||||
this.id = () => {
|
||||
|
|
|
@ -59,19 +59,32 @@ const AudioPlayer = function() {
|
|||
startTime
|
||||
});
|
||||
};
|
||||
this.remove = (audioID) => {
|
||||
const index = audioElements.findIndex((e) => { return e.audioID === audioID; });
|
||||
if (index < 0) {
|
||||
return false;
|
||||
} else {
|
||||
audioElements.splice(index, 1);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
this.update = () => {
|
||||
audioElements.forEach((audioElement, i) => {
|
||||
if (tp.isPlaying() && !record.isRecording()) {
|
||||
const shouldBePlaying = getAudioLayer().theatreObject.value[audioElement.audioID];
|
||||
if (shouldBePlaying && audioElement.audioDomElement.paused) {
|
||||
// sequence position is always greater than startTime
|
||||
// this is true, as it is written
|
||||
const diff = tp.sheet.sequence.position - audioElement.startTime;
|
||||
audioElement.audioDomElement.currentTime = diff;
|
||||
audioElement.audioDomElement.play();
|
||||
} else if (!shouldBePlaying && !audioElement.audioDomElement.paused) {
|
||||
audioElement.audioDomElement.pause();
|
||||
audioElement.audioDomElement.currentTime = 0;
|
||||
const shouldBePlaying = getAudioLayer().getValue([audioElement.audioID]);
|
||||
if (shouldBePlaying !== null) {
|
||||
if (shouldBePlaying && audioElement.audioDomElement.paused) {
|
||||
// sequence position is always greater than startTime
|
||||
// this is true, as it is written
|
||||
const diff = tp.sheet.sequence.position - audioElement.startTime;
|
||||
audioElement.audioDomElement.currentTime = diff;
|
||||
audioElement.audioDomElement.play();
|
||||
} else if (!shouldBePlaying && !audioElement.audioDomElement.paused) {
|
||||
audioElement.audioDomElement.pause();
|
||||
audioElement.audioDomElement.currentTime = 0;
|
||||
}
|
||||
} else {
|
||||
console.log('AudioPlayer::update',`${audioElement.audioID} does not exist in audioLayer.`);
|
||||
}
|
||||
} else if (!audioElement.audioDomElement.paused) {
|
||||
audioElement.audioDomElement.pause();
|
||||
|
|
|
@ -586,6 +586,9 @@ const deleteLayer = (id, saveProject = true) => {
|
|||
const addAudioLayer = (filename = false) => {
|
||||
return new Promise((resolve) => {
|
||||
const audioLayerID = (() => {
|
||||
if (audioLayers.length === 0) {
|
||||
return 'audio';
|
||||
}
|
||||
let index = 0;
|
||||
for (let i = 0; i < audioLayers.length; i++) {
|
||||
if (audioLayers.findIndex((audioLayer) => audioLayer.id() === `audio-${index}`) < 0) {
|
||||
|
|
|
@ -284,6 +284,11 @@ const TheatrePlay = function(autoInit = false) {
|
|||
friendlySequenceNames();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
// dirty, should be not in here:
|
||||
if (getAudioLayers().length > 0) {
|
||||
getAudioLayer().findInjectSequencePanel();
|
||||
}
|
||||
};
|
||||
|
||||
//public
|
||||
|
|
|
@ -372,6 +372,12 @@ function getParents(elem, until = null) {
|
|||
return parents;
|
||||
}
|
||||
|
||||
function removeAllEventListeners(elem) {
|
||||
const tmp = elem.cloneNode(true);
|
||||
elem.parentNode.replaceChild(tmp, elem);
|
||||
elem = tmp;
|
||||
}
|
||||
|
||||
function arraysEqual(a, b, sortingMatters = false) {
|
||||
if (a === b) return true;
|
||||
if (a == null || b == null) return false;
|
||||
|
@ -618,6 +624,7 @@ export {
|
|||
mixObject,
|
||||
clone,
|
||||
getParents,
|
||||
removeAllEventListeners,
|
||||
arraysEqual,
|
||||
mapValue,
|
||||
smoothValue,
|
||||
|
|
Loading…
Reference in a new issue