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:
themancalledjakob 2024-03-31 10:11:51 +02:00
parent 086e93e786
commit f421a344b1
8 changed files with 1189 additions and 71 deletions

View file

@ -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>

View file

@ -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;*/
}

View file

@ -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.order = parseInt(container.style.order) + 1;
const updateMappingOptions = () => {
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');
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');
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]);
});
}

View file

@ -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,

View file

@ -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');

View file

@ -374,10 +374,36 @@ 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) => {
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)) {
@ -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,
}

File diff suppressed because it is too large Load diff

View file

@ -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