Skip to content

Commit

Permalink
Merge branch 'main' into next
Browse files Browse the repository at this point in the history
  • Loading branch information
TimPietrusky committed Dec 4, 2020
2 parents e6580fe + 5dc3021 commit 8df9273
Show file tree
Hide file tree
Showing 6 changed files with 281 additions and 15 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"productName": "modV",
"description": "modular audio visualisation powered by JavaScript",
"author": "vcync",
"version": "3.4.0",
"version": "3.5.0",
"private": true,
"homepage": "https://modv.vcync.gl/",
"repository": {
Expand Down Expand Up @@ -39,6 +39,7 @@
"interactive-shader-format": "github:vcync/interactive-shader-format-js#feat/ImageBitmap",
"lfo-for-modv": "0.0.1",
"lodash.get": "^4.4.2",
"mathjs": "^3.20.2",
"meyda": "^5.0.1",
"mkdirp": "^0.5.1",
"npm": "6.14.6",
Expand Down
128 changes: 128 additions & 0 deletions src/application/worker/store/modules/expressions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import math from "mathjs";
import uuidv4 from "uuid/v4";

const state = {
assignments: {}
};

// getters
const getters = {
getByInputId: state => inputId => {
const assignmentValues = Object.values(state.assignments);

return assignmentValues.find(assignment => assignment.inputId === inputId);
}
};

function compileExpression(expression) {
const scope = { value: 0, time: 0 };

let newFunction;
try {
const node = math.parse(expression, scope);

newFunction = node.compile();
newFunction.eval(scope);
} catch (e) {
throw e;
}

return newFunction;
}

// actions
const actions = {
create({ commit }, { expression = "value", id, inputId }) {
if (!inputId) {
throw new Error("Input ID required");
}

if (expression.trim() === "value") {
return null;
}

const expressionId = id || uuidv4();

const func = compileExpression(expression);

if (!func) {
throw new Error("Unable to compile Expression");
}

const assignment = {
id: expressionId,
inputId,
func,
expression
};

commit("ADD_EXPRESSION", { assignment });

return expressionId;
},

update({ commit }, { id, expression = "value" }) {
if (!id) {
throw new Error("Expression ID required");
}

const existingExpression = state.assignments[id];

if (!existingExpression) {
throw new Error(`Existing expression with ID ${id} not found`);
}

if (expression.trim() === "value") {
commit("REMOVE_EXPRESSION", { id });
return null;
}

const func = compileExpression(expression);

if (!func) {
throw new Error("Unable to compile Expression");
}

existingExpression.func = func;
existingExpression.expression = expression;

commit("ADD_EXPRESSION", { assignment: existingExpression });
return existingExpression.id;
},

remove({ commit }, args) {
commit("REMOVE_EXPRESSION", args);
},

createPresetData() {
return state;
},

async loadPresetData({ dispatch }, data) {
const assignments = Object.values(data.assignments);
for (let i = 0, len = assignments.length; i < len; i++) {
const assignment = assignments[i];

await dispatch("create", assignment);
}
}
};

// mutations
const mutations = {
ADD_EXPRESSION(state, { assignment }) {
state.assignments[assignment.id] = assignment;
},

REMOVE_EXPRESSION(state, { id }) {
delete state.assignments[id];
}
};

export default {
namespaced: true,
state,
getters,
actions,
mutations
};
25 changes: 13 additions & 12 deletions src/application/worker/store/modules/modules.js
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ const actions = {
{ moduleId, prop, data, group, groupName, writeToSwap }
) {
const moduleName = state.active[moduleId].$moduleName;
const inputId = state.active[moduleId].$props[prop].id;
const propData = state.registered[moduleName].props[prop];
const currentValue = state.active[moduleId][prop];
const { type } = propData;
Expand All @@ -347,18 +348,18 @@ const actions = {

let dataOut = data;

// store.getters['plugins/enabledPlugins']
// .filter(plugin => 'processValue' in plugin.plugin)
// .forEach(plugin => {
// const newValue = plugin.plugin.processValue({
// currentValue: data,
// controlVariable: prop,
// delta: modV.delta,
// moduleName: name
// })

// if (typeof newValue !== 'undefined') dataOut = newValue
// })
const expressionAssignment = store.getters["expressions/getByInputId"](
inputId
);

if (expressionAssignment) {
const scope = {
value: dataOut,
time: Date.now()
};

dataOut = expressionAssignment.func.eval(scope);
}

if (store.state.dataTypes[type] && store.state.dataTypes[type].create) {
dataOut = await store.state.dataTypes[type].create(dataOut);
Expand Down
15 changes: 14 additions & 1 deletion src/components/InputConfig.vue
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,18 @@
</c>
</template>
</CollapsibleRow>

<CollapsibleRow>
<template v-slot:label>
Expression
</template>

<template v-slot:body>
<c span="1..">
<Expression :input-id="inputConfig.id" />
</c>
</template>
</CollapsibleRow>
</grid>
</div>
<div v-else>
Expand All @@ -77,13 +89,15 @@
import AudioFeatures from "./InputLinkComponents/AudioFeatures";
import MIDI from "./InputLinkComponents/MIDI";
import Tween from "./InputLinkComponents/Tween";
import Expression from "./InputLinkComponents/Expression";
import CollapsibleRow from "./CollapsibleRow";
export default {
components: {
AudioFeatures,
MIDI,
Tween,
Expression,
CollapsibleRow
},
Expand Down Expand Up @@ -175,7 +189,6 @@ grid.borders > c:not(:last-child):not(:first-child) {

<style>
.input-config input,
.input-config textarea,
.input-config .select {
max-width: 120px !important;
}
Expand Down
84 changes: 84 additions & 0 deletions src/components/InputLinkComponents/Expression.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<template>
<grid columns="4" v-infoView="{ title: iVTitle, body: iVBody, id: iVID }">
<c span="1..">
<grid columns="4">
<c span="2+2">
<Textarea v-model="expression" @change="updateExpression" />
</c>
</grid>
</c>
</grid>
</template>

<script>
export default {
props: {
inputId: {
type: String,
required: true
}
},
data() {
return {
iVTitle: "Expression",
iVBody:
"Expressions allow assigned input values to be shaped with JavaScript synax and math. Multiplication, division, custom intensity curves - whatever goes. `value` is the incoming number, want to make everything 3 times as punchy? `value * 3`. Need to soften things a little? `value / 2`. More examples can be found on modV's website under Guides, Expression.",
iVID: "Expression",
expression: "value",
expressionId: null
};
},
created() {
this.restoreExpressionValues();
},
methods: {
async updateExpression() {
const { inputId, expression, expressionId } = this;
if (expressionId) {
this.expressionId = await this.$modV.store.dispatch(
"expressions/update",
{
id: expressionId,
expression
}
);
} else {
this.expressionId = await this.$modV.store.dispatch(
"expressions/create",
{
expression,
inputId
}
);
}
},
restoreExpressionValues(inputId = this.inputId) {
const expressionAssignment = this.$modV.store.getters[
"expressions/getByInputId"
](inputId);
if (expressionAssignment) {
this.expression = expressionAssignment.expression;
this.expressionId = expressionAssignment.id;
} else {
this.expression = "value";
this.expressionId = null;
}
}
},
watch: {
inputId(inputId) {
this.restoreExpressionValues(inputId);
}
}
};
</script>

<style scoped></style>
Loading

0 comments on commit 8df9273

Please sign in to comment.