add color picker for audio min max
dependencies hashes: openFrameworks d78075f4bca6be2a2533c6e51a75cc1f18404501 ofxMsdfgen e14da13d02c4dff04fb69d7923469f606924e6c3 ofxGPUFont d482bb7cbdf6b296fa4ab5abcf73fb5ff8c8b239 ofxVariableLab 0b5f9bdebc1e5550621957e73c040c258ec6317b ofxProfiler a868e34fa1a79189dd4fbdede2938e308535e5e8 theatre 86d3e07f6f2c75fd6e08fca8c97e3617c9e23b18
This commit is contained in:
parent
086e93e786
commit
f421a344b1
8 changed files with 1189 additions and 71 deletions
|
@ -576,6 +576,7 @@
|
|||
};
|
||||
</script>
|
||||
<!--<script id="core-and-studio.min.js" type="application/javascript" src="/web/theatre_modules/core-and-studio.js"></script>-->
|
||||
<script src="/web/js/vanilla-picker.js"> </script>
|
||||
<script type="module" src="/web/js/main.js"> </script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -552,3 +552,8 @@ li.layerMover div.selected svg circle {
|
|||
.panelMomWrapper {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* ASYA: color picker can be changed like this */
|
||||
.picker_wrapper.popup .picker_arrow::before {
|
||||
/*background: pink;*/
|
||||
}
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
import {
|
||||
mapValue,
|
||||
smoothValue,
|
||||
mix,
|
||||
toCssClass,
|
||||
flattenObject,
|
||||
deFlattenObject,
|
||||
clone,
|
||||
rgbaToHexa,
|
||||
hexaToRgba,
|
||||
} from './utils.js';
|
||||
|
||||
window.mapValue = mapValue;
|
||||
|
@ -122,6 +125,9 @@ const Audio = function(tp, record) {
|
|||
} else if (propTitle.split('.')[0] === 'fontVariationAxes') {
|
||||
return layer.props.fontVariationAxes
|
||||
.props[propTitle.split('.')[1]].range;
|
||||
} else {
|
||||
console.error('Audio::getDefaultRange', 'propTitle not recognized', {propTitle});
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -133,31 +139,10 @@ const Audio = function(tp, record) {
|
|||
return m;
|
||||
}
|
||||
return savedMapping[layer.id()][propTitle];
|
||||
} else if (propTitle === 'color') {
|
||||
const mm = getDefaultRange(layer, 'color');
|
||||
if (config.audio.colorSeparateRGBA) {
|
||||
const r = new AudioMappingOptions();
|
||||
r.min_out = mm[0];
|
||||
r.max_out = mm[1];
|
||||
const g = new AudioMappingOptions();
|
||||
g.min_out = mm[0];
|
||||
g.max_out = mm[1];
|
||||
const b = new AudioMappingOptions();
|
||||
b.min_out = mm[0];
|
||||
b.max_out = mm[1];
|
||||
const a = new AudioMappingOptions();
|
||||
a.min_out = 1.0; // NOTE: dirty, dirty
|
||||
a.max_out = 1.0; // hardcoded value, you
|
||||
return [{r}, {g}, {b}, {a}];
|
||||
} else {
|
||||
const o = new AudioMappingOptions();
|
||||
o.min_out = {r: mm[0], b: mm[0], g: mm[0], a: mm[0]};
|
||||
o.max_out = {r: mm[1], b: mm[1], g: mm[1], a: mm[1]};
|
||||
return o;
|
||||
}
|
||||
} else {
|
||||
const o = new AudioMappingOptions();
|
||||
const mm = getDefaultRange(layer, propTitle);
|
||||
o.value = mm[0]; // hmmmm
|
||||
o.min_out = mm[0];
|
||||
o.max_out = mm[1];
|
||||
return o;
|
||||
|
@ -207,14 +192,14 @@ const Audio = function(tp, record) {
|
|||
if (!mapping[layer.id()].hasOwnProperty(propTitle)) {
|
||||
// no propTitle
|
||||
// perhaps color?
|
||||
if (config.audio.colorSeparateRGBA && propTitle === 'color') {
|
||||
let isGood = true;
|
||||
isGood = removeAudioMapping(layer, 'color.r');
|
||||
isGood = removeAudioMapping(layer, 'color.g');
|
||||
isGood = removeAudioMapping(layer, 'color.b');
|
||||
isGood = removeAudioMapping(layer, 'color.a');
|
||||
return isGood;
|
||||
}
|
||||
//if (config.audio.colorSeparateRGBA && propTitle === 'color') {
|
||||
//let isGood = true;
|
||||
//isGood = removeAudioMapping(layer, 'color.r');
|
||||
//isGood = removeAudioMapping(layer, 'color.g');
|
||||
//isGood = removeAudioMapping(layer, 'color.b');
|
||||
//isGood = removeAudioMapping(layer, 'color.a');
|
||||
//return isGood;
|
||||
//}
|
||||
return false;
|
||||
}
|
||||
delete mapping[layer.id()][propTitle];
|
||||
|
@ -243,35 +228,21 @@ const Audio = function(tp, record) {
|
|||
audioOptions.classList.add(toCssClass(`audioOptions${propTitle}`));
|
||||
audioOptions.style.position = 'relative';
|
||||
audioOptions.style.width = '100%';
|
||||
if (propTitle.split('.')[0] === 'color' && propTitle.split('.').length > 1) {
|
||||
audioOptions.classList.add(toCssClass('audioOptionscolor'));
|
||||
switch(propTitle.split('.')[1]) {
|
||||
case 'r': {
|
||||
audioOptions.style.background = config.audio.colors.options_r_background;
|
||||
break;
|
||||
}
|
||||
case 'g': {
|
||||
audioOptions.style.background = config.audio.colors.options_g_background;
|
||||
break;
|
||||
}
|
||||
case 'b': {
|
||||
audioOptions.style.background = config.audio.colors.options_b_background;
|
||||
break;
|
||||
}
|
||||
case 'a': {
|
||||
audioOptions.style.background = config.audio.colors.options_a_background;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
audioOptions.style.background = config.audio.colors.options_background; // AUDIO COLOR
|
||||
|
||||
}
|
||||
audioOptions.style.background = config.audio.colors.options_background; // AUDIO COLOR
|
||||
audioOptions.style.order = parseInt(container.style.order) + 1;
|
||||
|
||||
const updateMappingOptions = () => {
|
||||
mappingOptions.min_out = parseFloat(panel.querySelector(toCssClass(`audio_min${propTitle}`,'#')).value);
|
||||
mappingOptions.max_out = parseFloat(panel.querySelector(toCssClass(`audio_max${propTitle}`,'#')).value);
|
||||
if (propTitle === 'color') {
|
||||
mappingOptions.min_out = hexaToRgba(panel.querySelector(toCssClass(`audio_min${propTitle}`,'#')).value);
|
||||
const max_cssClass = toCssClass(`audio_max${propTitle}`,'#');
|
||||
const max_inputDom = panel.querySelector(max_cssClass);
|
||||
const max_value = max_inputDom.value;
|
||||
const max_rgba = hexaToRgba(max_value);
|
||||
mappingOptions.max_out = max_rgba;
|
||||
} else {
|
||||
mappingOptions.min_out = parseFloat(panel.querySelector(toCssClass(`audio_min${propTitle}`,'#')).value);
|
||||
mappingOptions.max_out = parseFloat(panel.querySelector(toCssClass(`audio_max${propTitle}`,'#')).value);
|
||||
}
|
||||
mappingOptions.sync =
|
||||
panel.querySelector(`input[name="${toCssClass('audio_sync' + propTitle)}"]:checked`).value;
|
||||
const s = panel.querySelector(toCssClass(`audio_smoothing${propTitle}`,'#')).value;
|
||||
|
@ -379,26 +350,102 @@ const Audio = function(tp, record) {
|
|||
min_inputDom_label.for = 'audio_min';
|
||||
min_inputDom_label.innerHTML = 'min ';
|
||||
const min_inputDom = document.createElement('input');
|
||||
min_inputDom.type = 'number';
|
||||
if (propTitle === 'color') {
|
||||
min_inputDom.type = 'text';
|
||||
min_inputDom.value = `${rgbaToHexa(mappingOptions.min_out)}`;
|
||||
const min_preview = document.createElement('div');
|
||||
min_preview.classList.add('color_preview');
|
||||
min_preview.style.width = '25px';
|
||||
min_preview.style.height = '25px';
|
||||
min_preview.style.borderRadius = '50%';
|
||||
min_preview.style.border = '1px solid black';
|
||||
min_preview.style.background = min_inputDom.value;
|
||||
min_Cont.append(min_preview);
|
||||
const picker = new Picker({
|
||||
'parent': min_preview,
|
||||
'color': min_inputDom.value,
|
||||
'popup': 'bottom',
|
||||
});
|
||||
picker.onChange = (color) => {
|
||||
min_preview.style.background = color.rgbaString;
|
||||
min_inputDom.value = color.hex;
|
||||
updateMappingOptions();
|
||||
//mappingOptions.min_out = {
|
||||
//r: color.rgba[0] / 255,
|
||||
//g: color.rgba[1] / 255,
|
||||
//b: color.rgba[2] / 255,
|
||||
//a: color.rgba[3],
|
||||
//};
|
||||
};
|
||||
min_inputDom.addEventListener('focus', () => {
|
||||
picker.show();
|
||||
min_preview.querySelector('.picker_editor input').focus();
|
||||
});
|
||||
min_inputDom.addEventListener('click', () => {
|
||||
picker.show();
|
||||
min_preview.querySelector('.picker_editor input').focus();
|
||||
});
|
||||
} else {
|
||||
min_inputDom.type = 'number';
|
||||
min_inputDom.value = `${mappingOptions.min_out}`;
|
||||
}
|
||||
min_inputDom.name = toCssClass(`audio_min${propTitle}`);
|
||||
min_inputDom.id = toCssClass(`audio_min${propTitle}`);
|
||||
if (Array.isArray(defaultRange) && defaultRange.length >= 2) {
|
||||
min_inputDom.title = `default: ${defaultRange[0]}`;
|
||||
min_inputDom.title = `default: ${JSON.stringify(defaultRange[0])}`;
|
||||
}
|
||||
min_inputDom.value = `${mappingOptions.min_out}`;
|
||||
const max_Cont = document.createElement('div');
|
||||
max_Cont.classList.add('audio_max_Cont');
|
||||
const max_inputDom_label = document.createElement('label');
|
||||
max_inputDom_label.for = 'audio_max';
|
||||
max_inputDom_label.innerHTML = 'max ';
|
||||
const max_inputDom = document.createElement('input');
|
||||
max_inputDom.type = 'number';
|
||||
if (propTitle === 'color') {
|
||||
max_inputDom.type = 'text';
|
||||
max_inputDom.value = `${rgbaToHexa(mappingOptions.max_out)}`;
|
||||
|
||||
const max_preview = document.createElement('div');
|
||||
max_preview.classList.add('color_preview');
|
||||
max_preview.style.width = '25px';
|
||||
max_preview.style.height = '25px';
|
||||
max_preview.style.borderRadius = '50%';
|
||||
max_preview.style.border = '1px solid black';
|
||||
max_preview.style.background = max_inputDom.value;
|
||||
max_Cont.append(max_preview);
|
||||
const picker = new Picker({
|
||||
'parent': max_preview,
|
||||
'color': max_inputDom.value,
|
||||
'popup': 'bottom',
|
||||
});
|
||||
picker.onChange = (color) => {
|
||||
max_preview.style.background = color.rgbaString;
|
||||
max_inputDom.value = color.hex;
|
||||
updateMappingOptions();
|
||||
//mappingOptions.max_out = {
|
||||
//r: color.rgba[0] / 255,
|
||||
//g: color.rgba[1] / 255,
|
||||
//b: color.rgba[2] / 255,
|
||||
//a: color.rgba[3],
|
||||
//};
|
||||
};
|
||||
max_inputDom.addEventListener('focus', () => {
|
||||
picker.show();
|
||||
max_preview.querySelector('.picker_editor input').focus();
|
||||
});
|
||||
max_inputDom.addEventListener('click', () => {
|
||||
picker.show();
|
||||
max_preview.querySelector('.picker_editor input').focus();
|
||||
});
|
||||
|
||||
} else {
|
||||
max_inputDom.type = 'number';
|
||||
max_inputDom.value = `${mappingOptions.max_out}`;
|
||||
}
|
||||
max_inputDom.name = toCssClass(`audio_max${propTitle}`);
|
||||
max_inputDom.id = toCssClass(`audio_max${propTitle}`);
|
||||
if (Array.isArray(defaultRange) && defaultRange.length >= 2) {
|
||||
max_inputDom.title = `default: ${defaultRange[1]}`;
|
||||
max_inputDom.title = `default: ${JSON.stringify(defaultRange[1])}`;
|
||||
}
|
||||
max_inputDom.value = `${mappingOptions.max_out}`;
|
||||
const smoothing_inputDom_label = document.createElement('label');
|
||||
smoothing_inputDom_label.for = 'audio_smoothing';
|
||||
smoothing_inputDom_label.innerHTML = 'audio smoothing';
|
||||
|
@ -679,6 +726,7 @@ const Audio = function(tp, record) {
|
|||
}
|
||||
addAudioMapping(layer, propTitle);
|
||||
addAudioOptions(layer, propTitle);
|
||||
|
||||
layer.updateValuesViaTheatre(false);
|
||||
};
|
||||
const removeAudio = (layer, propTitle) => {
|
||||
|
@ -1106,7 +1154,7 @@ const Audio = function(tp, record) {
|
|||
switch (m.sync) {
|
||||
case 'volume': {
|
||||
let a = mapValue(m.max_v, m.min_in, m.max_in, m.min_out, m.max_out, true);
|
||||
m.value = m.value * m.smoothing + (1.0 - m.smoothing) * a;
|
||||
m.value = smoothValue(m.value, a, m.smoothing);
|
||||
propsToSet.push({
|
||||
id: layerID,
|
||||
title: propTitle,
|
||||
|
@ -1121,7 +1169,7 @@ const Audio = function(tp, record) {
|
|||
const fi = config.audio.pitchCombineFrequencies ? ri : mi;
|
||||
let a = mapValue(fi, m.min_freq, m.max_freq, m.min_out, m.max_out, true);
|
||||
if (!isNaN(a)) {
|
||||
m.value = m.value * m.smoothing + (1.0 - m.smoothing) * a;
|
||||
m.value = smoothValue(m.value, a, m.smoothing);
|
||||
propsToSet.push({
|
||||
id: layerID,
|
||||
title: propTitle,
|
||||
|
@ -1133,7 +1181,7 @@ const Audio = function(tp, record) {
|
|||
case 'clarity': {
|
||||
const a = mapValue(m.c, 0.01, 0.05, m.min_out, m.max_out, true);
|
||||
if (!isNaN(a)) {
|
||||
m.value = m.value * m.smoothing + (1.0 - m.smoothing) * a;
|
||||
m.value = smoothValue(m.value, a, m.smoothing);
|
||||
propsToSet.push({
|
||||
id: layerID,
|
||||
title: propTitle,
|
||||
|
@ -1172,7 +1220,7 @@ const Audio = function(tp, record) {
|
|||
};
|
||||
});
|
||||
Object.keys(values).forEach((layerID) => {
|
||||
deFlattenObject(values[layerID]);
|
||||
deFlattenObject(values[layerID], ['color']);
|
||||
record.liveUpdater.immediateUpdate(getLayer(layerID), values[layerID]);
|
||||
});
|
||||
//}
|
||||
|
@ -1218,7 +1266,7 @@ const Audio = function(tp, record) {
|
|||
//}
|
||||
});
|
||||
Object.keys(values).forEach((layerID) => {
|
||||
deFlattenObject(values[layerID]);
|
||||
deFlattenObject(values[layerID], ['color']);
|
||||
record.liveUpdater.immediateUpdate(getLayer(layerID), values[layerID]);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ const config = {
|
|||
'rotation': [0, 180],
|
||||
'mirror_x_distance': [0, 200],
|
||||
'mirror_y_distance': [0, 70],
|
||||
'color': [0, 1],
|
||||
'color': [{'r': 0, 'g': 0, 'b': 0, 'a': 1}, {'r': 1, 'g': 1, 'b': 1, 'a': 1}],
|
||||
'letterDelays': [0, 1000],
|
||||
},
|
||||
ignoreProps: {
|
||||
|
@ -109,7 +109,7 @@ const config = {
|
|||
fftBandsAnalysed: 256 * 8,
|
||||
fftBandsUsed: 256 / 2,
|
||||
fftHeight: 256 / 4,
|
||||
colorSeparateRGBA: true,
|
||||
colorSeparateRGBA: false,
|
||||
ignoreOutboundFrequencies: true,
|
||||
pitchCombineFrequencies: false,
|
||||
rolloverResetLoop: true,
|
||||
|
|
|
@ -346,6 +346,7 @@ const TheatrePlay = function(autoInit = false) {
|
|||
};
|
||||
this.addShadowCss = () => {
|
||||
if (this.shadowRoot.querySelector(`#tpShadowCss`) === null) {
|
||||
this.shadowRoot.insertBefore(Picker.StyleElement.cloneNode(true), this.shadowRoot.querySelector('#pointer-root'));
|
||||
let style = document.createElement("link");
|
||||
style.setAttribute('id', 'tpShadowCss');
|
||||
style.setAttribute('rel', 'stylesheet');
|
||||
|
|
|
@ -374,11 +374,37 @@ function arraysEqual(a, b, sortingMatters = false) {
|
|||
return true;
|
||||
}
|
||||
|
||||
// NOTE: will break if input is not number or rgba
|
||||
const mapValue = (value, low1, high1, low2, high2, clamp=false) => {
|
||||
const mapped = low2 + (high2 - low2) * (value - low1) / (high1 - low1);
|
||||
return clamp ? Math.min(high2 > low2 ? high2 : low2, Math.max(low2 < high2 ? low2 : high2, mapped)) : mapped;
|
||||
if (typeof low2 === 'number') {
|
||||
const mapped = low2 + (high2 - low2) * (value - low1) / (high1 - low1);
|
||||
return clamp ? Math.min(high2 > low2 ? high2 : low2, Math.max(low2 < high2 ? low2 : high2, mapped)) : mapped;
|
||||
} else if (typeof low2 === 'object' && typeof low2.r === 'number') {
|
||||
const mapped = {
|
||||
r: mapValue(value, low1, high1, low2.r, high2.r, clamp),
|
||||
g: mapValue(value, low1, high1, low2.g, high2.g, clamp),
|
||||
b: mapValue(value, low1, high1, low2.b, high2.b, clamp),
|
||||
a: mapValue(value, low1, high1, low2.a, high2.a, clamp),
|
||||
};
|
||||
return mapped;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// NOTE: will break if input is not number or rgba
|
||||
const smoothValue = (oldValue, newValue, smoothing) => {
|
||||
if (typeof oldValue === 'number') {
|
||||
return oldValue * smoothing + (1.0 - smoothing) * newValue;
|
||||
} else {
|
||||
return {
|
||||
r: smoothValue(oldValue.r, newValue.r, smoothing),
|
||||
g: smoothValue(oldValue.g, newValue.g, smoothing),
|
||||
b: smoothValue(oldValue.b, newValue.b, smoothing),
|
||||
a: smoothValue(oldValue.a, newValue.a, smoothing),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const isMobile = () => {
|
||||
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
|
||||
return true;
|
||||
|
@ -478,6 +504,28 @@ const getNestedProperty = (o, a, verify = false) => {
|
|||
return o[b[0]];
|
||||
};
|
||||
|
||||
// NOTE: all input values are range 0-1
|
||||
const rgbaToHexa = (rgba) => {
|
||||
return '#' + (
|
||||
('0' + Math.round(rgba.r * 255).toString(16)).slice(-2) +
|
||||
('0' + Math.round(rgba.g * 255).toString(16)).slice(-2) +
|
||||
('0' + Math.round(rgba.b * 255).toString(16)).slice(-2) +
|
||||
('0' + Math.round(rgba.a * 255).toString(16)).slice(-2)
|
||||
).toUpperCase();
|
||||
};
|
||||
|
||||
// NOTE: all output values are range 0-1
|
||||
const hexaToRgba = (hexa) => {
|
||||
const o = hexa[0] === '#' ? 1 : 0;
|
||||
return {
|
||||
r: parseInt(hexa.slice(o + 0, o + 2), 16) / 255,
|
||||
g: parseInt(hexa.slice(o + 2, o + 4), 16) / 255,
|
||||
b: parseInt(hexa.slice(o + 4, o + 6), 16) / 255,
|
||||
a: parseInt(hexa.slice(o + 6, o + 8), 16) / 255
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////
|
||||
// you can test these functions in
|
||||
// the browser like so:
|
||||
|
@ -507,6 +555,7 @@ export {
|
|||
getParents,
|
||||
arraysEqual,
|
||||
mapValue,
|
||||
smoothValue,
|
||||
isMobile,
|
||||
sequencialPromises,
|
||||
toCssClass,
|
||||
|
@ -514,4 +563,6 @@ export {
|
|||
flattenObject,
|
||||
deFlattenObject,
|
||||
getNestedProperty,
|
||||
rgbaToHexa,
|
||||
hexaToRgba,
|
||||
}
|
||||
|
|
1009
bin/em/variabletime/web/js/vanilla-picker.js
Normal file
1009
bin/em/variabletime/web/js/vanilla-picker.js
Normal file
File diff suppressed because it is too large
Load diff
|
@ -9,11 +9,14 @@ fly ()
|
|||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
PREVIOUS_DIR=$(pwd)
|
||||
|
||||
#. ~/.bash_aliases
|
||||
|
||||
cd $DIR
|
||||
|
||||
#echo $(fly /usr/bin/chromium --incognito --screen=1 $@)
|
||||
#/usr/bin/chromium --incognito --screen=1 $@ &
|
||||
fly flatpak run com.github.Eloston.UngoogledChromium --screen=1 --disk-cache-dir=/dev/null --disk-cache-size=1 --enable-logging --password-store=basic --v=1 $@ &
|
||||
#flatchrome Tmp --screen=1 --disk-cache-dir=/dev/null --disk-cache-size=1 --enable-logging --password-store=basic --v=1 $@ &
|
||||
browser_pid=$!
|
||||
echo $browser_pid > .browserpid
|
||||
|
||||
|
|
Loading…
Reference in a new issue