lock mode #4
12
common.js
12
common.js
@ -5,7 +5,8 @@ function isNumeric(str) {
|
||||
}
|
||||
|
||||
function DropDown(props) {
|
||||
return e('select', {type: "number", onChange: props.onChange, value: props.value},
|
||||
let className = props.locked ? 'locked-component' : '';
|
||||
return e('select', {className, type: "number", onChange: props.onChange, value: props.value},
|
||||
...props.options.map((item) => Option(item)));
|
||||
}
|
||||
|
||||
@ -18,11 +19,13 @@ function Label(text){
|
||||
}
|
||||
|
||||
function NumberBox(props){
|
||||
return e('input', {type: "number", onChange: props.onChange, step: props.step, value: props.value, className: props.className}, null);
|
||||
let extraClassName = props.locked ? ' locked-component' : '';
|
||||
return e('input', {type: "number", onChange: props.onChange, step: props.step, value: props.value, className: props.className + extraClassName}, null);
|
||||
}
|
||||
|
||||
function TextBox(props){
|
||||
return e('input', {type: "text", value: props.value, onChange: props.onChange, id: props.id});
|
||||
let className = props.locked ? 'locked-component' : '';
|
||||
return e('input', {className, type: "text", value: props.value, onChange: props.onChange, id: props.id});
|
||||
}
|
||||
|
||||
function Option(str, value){
|
||||
@ -30,7 +33,8 @@ function Option(str, value){
|
||||
}
|
||||
|
||||
function Button(props){
|
||||
return e('button', {onClick: props.onClick}, props.text);
|
||||
let className = props.locked ? 'locked-component' : '';
|
||||
return e('button', {onClick: props.onClick, className}, props.text);
|
||||
}
|
||||
|
||||
function Switch(props){
|
||||
|
20
enums.js
20
enums.js
@ -5,13 +5,13 @@
|
||||
|
||||
|
||||
// NOT A REACT FUNCTIONAL COMPONENT. MERELY RETURNS AN ARRAY WHICH IS UNPACKED
|
||||
function EnumeratorItems(index, enumBreakPoints, setEnumBreakPoints, enumNames, setEnumNames, djParam){
|
||||
function EnumeratorItems(index, enumBreakPoints, setEnumBreakPoints, enumNames, setEnumNames, djParam, locked){
|
||||
let items = [];
|
||||
for (let i = 0; i < MAXENUMPOINTS; i++){
|
||||
|
||||
items.push(ListItem(e(TextBox, {onChange: CreateMatrixParamChanger(enumNames, setEnumNames, index, i), value: enumNames[index][i], id:`text-${djParam}-${enumNames[index][i]}`}, null)));
|
||||
items.push(ListItem(e(TextBox, {locked, onChange: CreateMatrixParamChanger(enumNames, setEnumNames, index, i), value: enumNames[index][i], id:`text-${djParam}-${enumNames[index][i]}`}, null)));
|
||||
// Add 1 to make up for the lower enum bound
|
||||
items.push(ListItem(e(NumberBox, {onChange: CreateMatrixParamChanger(enumBreakPoints, setEnumBreakPoints, index, i + 1), value:enumBreakPoints[index][i + 1]}, null)));
|
||||
items.push(ListItem(e(NumberBox, {locked, onChange: CreateMatrixParamChanger(enumBreakPoints, setEnumBreakPoints, index, i + 1), value:enumBreakPoints[index][i + 1]}, null)));
|
||||
}
|
||||
return items;
|
||||
}
|
||||
@ -20,13 +20,13 @@ function EnumeratorRow(props){
|
||||
let linkedText = props.linked ? "<- mods" : "";
|
||||
|
||||
let content = e('ul', {className: 'lfo-item', id: `${props.djParam}-enum-row`},
|
||||
ListItem(DropDown({onChange: props.setInstanceNum, value:props.instanceNum, options: INSTANCEOPTIONS})),
|
||||
ListItem(DropDown({onChange: props.setDjParam, value: props.djParam, options: MODPARAMOPTIONS})),
|
||||
ListItem(e(NumberBox, {onChange: props.setEnumItemCounts, step:1, value:props.enumItems, className: 'enum-count'}, null)),
|
||||
ListItem(e(NumberBox, {onChange: CreateMatrixParamChanger(props.enumBreakPoints, props.setEnumBreakPoints, props.index, 0), value:props.enumBreakPoints[props.index][0], step:0.1}, null)),
|
||||
...(EnumeratorItems(props.index, props.enumBreakPoints, props.setEnumBreakPoints, props.enumNames, props.setEnumNames, props.djParam).slice(0, props.enumItems * 2)),
|
||||
ListItem(e(Button, {text:'+', onClick: props.addEnum}, null)),
|
||||
ListItem(e(Button, {text:'-', onClick: props.removeEnum}, null)),
|
||||
ListItem(DropDown({locked:props.locked, onChange: props.setInstanceNum, value:props.instanceNum, options: INSTANCEOPTIONS})),
|
||||
ListItem(DropDown({locked:props.locked, onChange: props.setDjParam, value: props.djParam, options: MODPARAMOPTIONS})),
|
||||
ListItem(e(NumberBox, {locked:props.locked, onChange: props.setEnumItemCounts, step:1, value:props.enumItems, className: 'enum-count'}, null)),
|
||||
ListItem(e(NumberBox, {locked:props.locked, onChange: CreateMatrixParamChanger(props.enumBreakPoints, props.setEnumBreakPoints, props.index, 0), value:props.enumBreakPoints[props.index][0], step:0.1}, null)),
|
||||
...(EnumeratorItems(props.index, props.enumBreakPoints, props.setEnumBreakPoints, props.enumNames, props.setEnumNames, props.djParam, props.locked).slice(0, props.enumItems * 2)),
|
||||
ListItem(e(Button, {locked:props.locked, text:'+', onClick: props.addEnum}, null)),
|
||||
ListItem(e(Button, {locked:props.locked, text:'-', onClick: props.removeEnum}, null)),
|
||||
ListItem(e("div", {className:"linked"}, linkedText))
|
||||
);
|
||||
if (props.visible){
|
||||
|
397
lfogui.css
397
lfogui.css
@ -1,181 +1,272 @@
|
||||
html,
|
||||
body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0px;
|
||||
border: 0;
|
||||
overflow: hidden; /* Disable scrollbars */
|
||||
display: block; /* No floating content on sides */
|
||||
}
|
||||
* {
|
||||
--locked-color: #5fadbf;
|
||||
--unlocked-color: #ff5153;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
background-color: #333333;
|
||||
}
|
||||
html, body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0px;
|
||||
border: 0;
|
||||
overflow: hidden; /* Disable scrollbars */
|
||||
display: block; /* No floating content on sides */
|
||||
}
|
||||
|
||||
li {
|
||||
float: left;
|
||||
}
|
||||
ul {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
background-color: #333333;
|
||||
}
|
||||
|
||||
li {
|
||||
float: left;
|
||||
}
|
||||
|
||||
|
||||
input[type=number] {
|
||||
width: 50px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
input[type=number] {
|
||||
width: 50px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
input[type=text] {
|
||||
width: 60px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
input[type=text] {
|
||||
width: 60px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.timeInput {
|
||||
width: 80px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.timeInput {
|
||||
width: 80px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#matrix {
|
||||
background-color: aquamarine;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
#matrix {
|
||||
background-color: aquamarine;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.numbox-unclicked {
|
||||
user-select: none;
|
||||
border: solid;
|
||||
font-size: 12vw;
|
||||
}
|
||||
.numbox-unclicked {
|
||||
user-select: none;
|
||||
border: solid;
|
||||
font-size: 12vw;
|
||||
}
|
||||
|
||||
.numbox-clicked {
|
||||
user-select: none;
|
||||
border : solid;
|
||||
font-size: 12vw;
|
||||
}
|
||||
.numbox-clicked {
|
||||
user-select: none;
|
||||
border : solid;
|
||||
font-size: 12vw;
|
||||
}
|
||||
|
||||
.param-input-label {
|
||||
width: 93%;
|
||||
font-size: 5vw;
|
||||
}
|
||||
.param-input-label {
|
||||
width: 93%;
|
||||
font-size: 5vw;
|
||||
}
|
||||
|
||||
.lfo-input-label {
|
||||
width: 40%;
|
||||
font-size: 5vw;
|
||||
}
|
||||
.lfo-input-label {
|
||||
width: 40%;
|
||||
font-size: 5vw;
|
||||
}
|
||||
|
||||
/* The switch - the box around the slider */
|
||||
.switch {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 30px;
|
||||
height: 17px;
|
||||
}
|
||||
/* The switch - the box around the slider */
|
||||
.switch {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 30px;
|
||||
height: 17px;
|
||||
}
|
||||
|
||||
/* Hide default HTML checkbox */
|
||||
.switch input {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
/* Hide default HTML checkbox */
|
||||
.switch input {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/* The slider */
|
||||
.slider {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #ccc;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
}
|
||||
/* The slider */
|
||||
.slider {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #ccc;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
.slider:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 13px;
|
||||
width: 13px;
|
||||
left: 2px;
|
||||
bottom: 2px;
|
||||
background-color: white;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
}
|
||||
.slider:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 13px;
|
||||
width: 13px;
|
||||
left: 2px;
|
||||
bottom: 2px;
|
||||
background-color: white;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
input:checked + .slider {
|
||||
background-color: #2196F3;
|
||||
}
|
||||
input:checked + .slider {
|
||||
background-color: #2196F3;
|
||||
}
|
||||
|
||||
input:focus + .slider {
|
||||
box-shadow: 0 0 1px #2196F3;
|
||||
}
|
||||
input:focus + .slider {
|
||||
box-shadow: 0 0 1px #2196F3;
|
||||
}
|
||||
|
||||
input:checked + .slider:before {
|
||||
-webkit-transform: translateX(13px);
|
||||
-ms-transform: translateX(13px);
|
||||
transform: translateX(13px);
|
||||
}
|
||||
input:checked + .slider:before {
|
||||
-webkit-transform: translateX(13px);
|
||||
-ms-transform: translateX(13px);
|
||||
transform: translateX(13px);
|
||||
}
|
||||
|
||||
/* Rounded sliders */
|
||||
.slider.round {
|
||||
border-radius: 17px;
|
||||
}
|
||||
/* Rounded sliders */
|
||||
.slider.round {
|
||||
border-radius: 17px;
|
||||
}
|
||||
|
||||
.slider.round:before {
|
||||
border-radius: 50%;
|
||||
}
|
||||
.slider.round:before {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
h5 {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
h5 {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.enum-count {
|
||||
background-color: aquamarine;
|
||||
}
|
||||
.enum-count {
|
||||
background-color: aquamarine;
|
||||
}
|
||||
|
||||
.label {
|
||||
background-color: aliceblue;
|
||||
padding: 0 4px 0 4px;
|
||||
margin: 0 2px 0 2px;
|
||||
border-color: #333333;
|
||||
border-width: 1px;
|
||||
}
|
||||
.label {
|
||||
background-color: aliceblue;
|
||||
padding: 0 4px 0 4px;
|
||||
margin: 0 2px 0 2px;
|
||||
border-color: #333333;
|
||||
border-width: 1px;
|
||||
}
|
||||
|
||||
.base-val {
|
||||
background-color: lightgray;
|
||||
border-color: #333333;
|
||||
border-width: 1px;
|
||||
width: 50px;
|
||||
margin-left: 2px;
|
||||
margin-top: 1px;
|
||||
}
|
||||
.base-val {
|
||||
background-color: lightgray;
|
||||
border-color: #333333;
|
||||
border-width: 1px;
|
||||
width: 50px;
|
||||
margin-left: 2px;
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
.linked {
|
||||
color: red;
|
||||
border-width: 1px;
|
||||
width: 50px;
|
||||
font-size: small;
|
||||
margin-left: 2px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
.linked {
|
||||
color: red;
|
||||
border-width: 1px;
|
||||
width: 50px;
|
||||
font-size: small;
|
||||
margin-left: 2px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
|
||||
@keyframes pulse-animation {
|
||||
0% {
|
||||
color: black;
|
||||
}
|
||||
100% {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
@keyframes pulse-animation {
|
||||
0% {
|
||||
color: black;
|
||||
}
|
||||
100% {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
|
||||
#pulse {
|
||||
animation: pulse-animation 0.2s normal;
|
||||
}
|
||||
#pulse {
|
||||
animation: pulse-animation 0.2s normal;
|
||||
}
|
||||
|
||||
/* :::::::::::::: LOCK CSS */
|
||||
|
||||
.locked-component {
|
||||
pointer-events: none;
|
||||
background-color: #333333;
|
||||
color : white;
|
||||
}
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
/* Locked */
|
||||
.lock {
|
||||
margin-top: 14px;
|
||||
width: 24px;
|
||||
height: 21px;
|
||||
border: 3px solid var(--locked-color);
|
||||
border-radius: 5px;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
-webkit-transition: all 0.1s ease-in-out;
|
||||
transition: all 0.1s ease-in-out;
|
||||
}
|
||||
.lock:after {
|
||||
content: "";
|
||||
display: block;
|
||||
background: var(--locked-color);
|
||||
width: 3px;
|
||||
height: 7px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin: -3.5px 0 0 -2px;
|
||||
-webkit-transition: all 0.1s ease-in-out;
|
||||
transition: all 0.1s ease-in-out;
|
||||
}
|
||||
.lock:before {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
bottom: 100%;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
margin-left: -8px;
|
||||
border: 3px solid var(--locked-color);
|
||||
border-top-right-radius: 50%;
|
||||
border-top-left-radius: 50%;
|
||||
border-bottom: 0;
|
||||
-webkit-transition: all 0.1s ease-in-out;
|
||||
transition: all 0.1s ease-in-out;
|
||||
}
|
||||
/* Locked Hover */
|
||||
.lock:hover:before {
|
||||
height: 12px;
|
||||
}
|
||||
/* Unlocked */
|
||||
.unlocked {
|
||||
transform: rotate(10deg);
|
||||
}
|
||||
.unlocked:before {
|
||||
bottom: 130%;
|
||||
left: 31%;
|
||||
margin-left: -11.5px;
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
.unlocked,
|
||||
.unlocked:before {
|
||||
border-color: var(--unlocked-color);
|
||||
}
|
||||
.unlocked:after {
|
||||
background: var(--unlocked-color);
|
||||
}
|
||||
/* Unlocked Hover */
|
||||
.unlocked:hover {
|
||||
transform: rotate(3deg);
|
||||
}
|
||||
.unlocked:hover:before {
|
||||
height: 10px;
|
||||
left: 40%;
|
||||
bottom: 124%;
|
||||
transform: rotate(-30deg);
|
||||
}
|
29
lfogui.js
29
lfogui.js
@ -20,6 +20,11 @@ const ViewModes = Object.freeze({
|
||||
ENUM: 1
|
||||
});
|
||||
|
||||
const LockModes = Object.freeze({
|
||||
UNLOCK: 0,
|
||||
LOCK: 1
|
||||
});
|
||||
|
||||
|
||||
var modPhases = Array(MAXLFOS).fill(0);
|
||||
var firstUpdateTime = Date.now();
|
||||
@ -43,6 +48,14 @@ function MasterLfoHandler(){
|
||||
setViewMode(ViewModes.MOD);
|
||||
};
|
||||
|
||||
const [lockMode, setLockMode] = React.useState(LockModes.LOCK);
|
||||
const toggleLockMode = () => {
|
||||
if (lockMode === LockModes.UNLOCK)
|
||||
setLockMode(LockModes.LOCK);
|
||||
else
|
||||
setLockMode(LockModes.UNLOCK);
|
||||
};
|
||||
|
||||
/// MODULATOR ARRAYS
|
||||
|
||||
const [userDefinedWave, setUserDefinedWave] = React.useState(Array(50).fill(0));
|
||||
@ -262,6 +275,7 @@ function MasterLfoHandler(){
|
||||
modContents.push(
|
||||
|
||||
e(LfoRow, {
|
||||
locked : lockMode,
|
||||
instanceNum : modInstanceNumArr[i],
|
||||
setInstanceNum: CreateParamChanger(modInstanceNumArr, setModInstanceNumArr, i),
|
||||
|
||||
@ -343,7 +357,7 @@ function MasterLfoHandler(){
|
||||
enumContents.push(
|
||||
e(EnumeratorRow, {
|
||||
index: i,
|
||||
|
||||
locked : lockMode,
|
||||
instanceNum : enumInstanceNumArr[i],
|
||||
setInstanceNum: CreateParamChanger(enumInstanceNumArr, setEnumInstanceNumArr, i),
|
||||
enumItems: enumItemCounts[i],
|
||||
@ -425,8 +439,19 @@ function MasterLfoHandler(){
|
||||
labels = ENUMERATORLABELS;
|
||||
}
|
||||
|
||||
let lockClass;
|
||||
if (lockMode == LockModes.LOCK){
|
||||
lockClass = 'lock';
|
||||
}
|
||||
else {
|
||||
lockClass = 'lock unlocked';
|
||||
}
|
||||
|
||||
return e('div', null,
|
||||
e(Switch, {ontoggle: toggleViewMode}, null),
|
||||
e('div', {className: 'container'},
|
||||
e(Switch, {ontoggle: toggleViewMode}, null),
|
||||
e('span', {className: lockClass, onClick: toggleLockMode}, null)),
|
||||
|
||||
e('h5', null, title),
|
||||
e('ul', null, ...labels.map(x => ListItem(Label(x)))),
|
||||
e('div', {id: 'grid'}, ...grid)
|
||||
|
@ -34,17 +34,17 @@ function LfoRow(props){
|
||||
let typeOption = null;
|
||||
|
||||
if (props.type == "LFO"){
|
||||
typeOption = ListItem(DropDown({onChange: props.setShape, value:props.shape, options: SHAPETYPES}));
|
||||
typeOption = ListItem(DropDown({locked:props.locked, onChange: props.setShape, value:props.shape, options: SHAPETYPES}));
|
||||
}
|
||||
else if (props.type == "Noise"){
|
||||
typeOption = ListItem(DropDown({onChange: props.setNoise, value:props.noise, options: NOISETYPES}));
|
||||
typeOption = ListItem(DropDown({locked:props.locked, onChange: props.setNoise, value:props.noise, options: NOISETYPES}));
|
||||
}
|
||||
|
||||
let content = e('ul', {className: 'lfo-item'},
|
||||
ListItem(DropDown({onChange: props.setInstanceNum, value:props.instanceNum, options: INSTANCEOPTIONS})),
|
||||
ListItem(DropDown({options: TYPEOPTIONS, onChange: props.setType, value:props.type})),
|
||||
ListItem(DropDown({locked:props.locked, onChange: props.setInstanceNum, value:props.instanceNum, options: INSTANCEOPTIONS})),
|
||||
ListItem(DropDown({locked:props.locked, options: TYPEOPTIONS, onChange: props.setType, value:props.type})),
|
||||
typeOption,
|
||||
ListItem(DropDown({onChange: props.setDjParam, value: props.djParam, options: MODPARAMOPTIONS})),
|
||||
ListItem(DropDown({locked:props.locked, onChange: props.setDjParam, value: props.djParam, options: MODPARAMOPTIONS})),
|
||||
ListItem(e("input", {onChange:props.setFreq, value:props.freq, className:"timeInput"}, null)),
|
||||
ListItem(e(NumberBox, {onChange:props.setMin, value:props.min, step:0.1}, null)),
|
||||
ListItem(e(NumberBox, {onChange:props.setMax, value:props.max, step:0.1}, null)),
|
||||
@ -52,8 +52,8 @@ function LfoRow(props){
|
||||
ListItem(e(NumberBox, {onChange:props.setPhase, value:props.phase, step:0.1}, null)),
|
||||
ListItem(e("div", {className:"base-val"}, center.toString())),
|
||||
ListItem(e("input", {type: 'range', min: 0, max: 1, step: 0.01, readonly: true, id: `slider-${props.instanceNum}-${props.djParam}`})),
|
||||
ListItem(e(Button, {text:'+', onClick: props.addLfo}, null)),
|
||||
ListItem(e(Button, {text:'-', onClick: props.removeLfo}, null)),
|
||||
ListItem(e(Button, {text:'+', onClick: props.addLfo, locked: props.locked}, null)),
|
||||
ListItem(e(Button, {text:'-', onClick: props.removeLfo, locked: props.locked}, null)),
|
||||
ListItem(e("div", {className:"linked"}, linkedText)),
|
||||
);
|
||||
if (props.visible){
|
||||
|
Loading…
Reference in New Issue
Block a user