mirror of
https://codeberg.org/uzu/strudel
synced 2026-07-21 20:55:12 -04:00
Add uniform pattern function doc
This commit is contained in:
@@ -44,7 +44,7 @@ class UniformValue {
|
||||
|
||||
get(elapsed) {
|
||||
// Adjust the value according to the rate of change
|
||||
const offset = (this.desired - this.value) / (this.slow * Math.min(1, elapsed * 60));
|
||||
const offset = (this.desired - this.value) / (this.slow * Math.max(1, elapsed * 60));
|
||||
// Ignore small changes
|
||||
if (Math.abs(offset) > 1e-3) this.value += offset;
|
||||
return this.value;
|
||||
@@ -72,7 +72,6 @@ export function setUniform(instanceName, name, value, incr, position, slow) {
|
||||
uniformValue = uniform.value[idx];
|
||||
}
|
||||
uniformValue.slow = slow;
|
||||
// TODO: handle direct assignment, this is incrementing by default
|
||||
if (incr) uniformValue.desired += value;
|
||||
else uniformValue.desired = value;
|
||||
} else {
|
||||
|
||||
+40
-12
@@ -4,19 +4,31 @@ Copyright (C) 2024 Strudel contributors
|
||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Pattern, reify, register, logger } from '@strudel/core';
|
||||
import { reify, register, logger } from '@strudel/core';
|
||||
import { setUniform } from './shader.mjs';
|
||||
|
||||
/**
|
||||
* Update a shader.
|
||||
* Update a shader uniform value. A uniform name consists of
|
||||
*
|
||||
* - a name
|
||||
* - optional array position seperated by ':'. The position can be an index number, or 'seq' | 'random' to assign a different index per events.
|
||||
*
|
||||
* The uniform can also be configured with an object to pass extra options:
|
||||
*
|
||||
* @name uniform
|
||||
* @param {string} name: the uniform name and optional position.
|
||||
* @param {number} gain: the value multiplier - defaults to 1.
|
||||
* @param {number} slow: the value change rate, set to 1 for instant update - defaults to 10.
|
||||
* @param {boolean} onTrigger: update the uniform only when the pattern trigger. In that case, the uniform position is mapped to the event note/sound when it is not explicity set.
|
||||
*
|
||||
* @example
|
||||
* pan(sine.uniform("iColor"))
|
||||
* @example
|
||||
* gain("<.5 .3>".uniform("rotations:seq"))
|
||||
* gain(".5 .3").uniform("mod:0 mod:1")
|
||||
* @example
|
||||
* s("bd sd").uniform({onTrigger: true, dest: "moveFWD"})
|
||||
* dist("<.5 .3>".uniform("rotations:seq"))
|
||||
* @example
|
||||
* s("bd sd").uniform({name: 'rotations', gain: 0.2, slow: "<5 20>", onTrigger: true})
|
||||
*/
|
||||
export const uniform = register('uniform', (options, pat) => {
|
||||
// The shader instance name
|
||||
@@ -25,13 +37,7 @@ export const uniform = register('uniform', (options, pat) => {
|
||||
// Are the uniform updated on trigger
|
||||
const onTrigger = options.onTrigger || false;
|
||||
|
||||
const setCtx = (uniformParam) => (ctx) => ({
|
||||
uniformParam,
|
||||
onTrigger: () => {},
|
||||
dominantTrigger: true,
|
||||
...ctx,
|
||||
});
|
||||
|
||||
// Helper to assign uniform position
|
||||
const pitches = { _count: 0 };
|
||||
const getPosition = (value, dest) => {
|
||||
if (typeof dest === 'number') return dest;
|
||||
@@ -45,9 +51,10 @@ export const uniform = register('uniform', (options, pat) => {
|
||||
}
|
||||
return pitches[note];
|
||||
} else {
|
||||
throw 'Invalid position' + dest;
|
||||
logger('Invalid position' + dest, 'error');
|
||||
}
|
||||
};
|
||||
// Helper to decode the uniform position
|
||||
const getUniformPosition = (value, dest) => {
|
||||
if (typeof dest === 'string') {
|
||||
return [dest, 0];
|
||||
@@ -56,15 +63,31 @@ export const uniform = register('uniform', (options, pat) => {
|
||||
}
|
||||
};
|
||||
|
||||
// The option pattern context
|
||||
const setCtx = (uniformParam) => (ctx) => ({
|
||||
// The option name
|
||||
uniformParam,
|
||||
// Disable event trigger
|
||||
onTrigger: () => {},
|
||||
dominantTrigger: true,
|
||||
...ctx,
|
||||
});
|
||||
|
||||
// Collect the option patterns
|
||||
const optionsPats = [];
|
||||
if (Array.isArray(options) || typeof options === 'string')
|
||||
optionsPats.push(reify(options).withContext(setCtx('dest')));
|
||||
else {
|
||||
// dest was the initial name, that can be removed
|
||||
if (options.dest) optionsPats.push(reify(options.dest).withContext(setCtx('dest')));
|
||||
if (options.name) optionsPats.push(reify(options.name).withContext(setCtx('dest')));
|
||||
if (options.gain) optionsPats.push(reify(options.gain).withContext(setCtx('gain')));
|
||||
if (options.slow) optionsPats.push(reify(options.slow).withContext(setCtx('slow')));
|
||||
}
|
||||
|
||||
// Run the base pattern along with all the options
|
||||
return stack(pat, ...optionsPats).withHaps((haps) => {
|
||||
// Collect the current options
|
||||
let dest;
|
||||
let gain = 1;
|
||||
let slow = 10;
|
||||
@@ -80,18 +103,23 @@ export const uniform = register('uniform', (options, pat) => {
|
||||
source = hap;
|
||||
}
|
||||
});
|
||||
|
||||
if (dest && source) {
|
||||
if (onTrigger) {
|
||||
// Set the uniform when the source trigger
|
||||
source.context.onTrigger = (_, hap) => {
|
||||
const [uniform, position] = getUniformPosition(hap.value, dest);
|
||||
setUniform(instance, uniform, (hap.value.gain || 1) * gain, true, position, slow);
|
||||
};
|
||||
source.context.dominantTrigger = false;
|
||||
} else {
|
||||
// Set the uniform now.
|
||||
const [uniform, position] = getUniformPosition(source.value, dest);
|
||||
setUniform(instance, uniform, source.value * gain, false, position, slow);
|
||||
}
|
||||
}
|
||||
|
||||
// The options haps are kept so that the current values are highlighted on screen
|
||||
return haps;
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user