-
-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(expression): adds expressions (#468)
* feat(expression): adds expressions Adds the expression editor from modV 2 fix #453 fix #415 * feat(expressions): adds time variable to scope * feat(expressions): adds preset save/restore to expressions state * feat(expressions): Make textarea fill up the whole space * revert(expression): reduces textarea size to align with tween textarea Co-authored-by: Tim Pietrusky <[email protected]>
- Loading branch information
1 parent
1d66a15
commit ab13872
Showing
6 changed files
with
280 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3079,6 +3079,11 @@ [email protected]: | |
resolved "https://registry.yarnpkg.com/complex.js/-/complex.js-2.0.11.tgz#09a873fbf15ffd8c18c9c2201ccef425c32b8bf1" | ||
integrity sha512-6IArJLApNtdg1P1dFtn3dnyzoZBEF0MwMnrfF1exSBRpZYoy4yieMkpZhQDC0uwctw48vii0CFVyHfpgZ/DfGw== | ||
|
||
[email protected]: | ||
version "2.0.4" | ||
resolved "https://registry.yarnpkg.com/complex.js/-/complex.js-2.0.4.tgz#d8e7cfb9652d1e853e723386421c1a0ca7a48373" | ||
integrity sha512-Syl95HpxUTS0QjwNxencZsKukgh1zdS9uXeXX2Us0pHaqBR6kiZZi0AkZ9VpZFwHJyVIUVzI4EumjWdXP3fy6w== | ||
|
||
component-emitter@^1.2.1: | ||
version "1.3.0" | ||
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" | ||
|
@@ -3689,6 +3694,11 @@ [email protected]: | |
resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.0.tgz#39466113a9e036111d02f82489b5fd6b0b5ed231" | ||
integrity sha512-vDPw+rDgn3bZe1+F/pyEwb1oMG2XTlRVgAa6B4KccTEpYgF8w6eQllVbQcfIJnZyvzFtFpxnpGtx8dd7DJp/Rw== | ||
|
||
[email protected]: | ||
version "9.0.1" | ||
resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-9.0.1.tgz#1cc8b228177da7ab6498c1cc06eb130a290e6e1e" | ||
integrity sha512-2h0iKbJwnImBk4TGk7CG1xadoA0g3LDPlQhQzbZ221zvG0p2YVUedbKIPsOZXKZGx6YmZMJKYOalpCMxSdDqTQ== | ||
|
||
decode-uri-component@^0.2.0: | ||
version "0.2.0" | ||
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" | ||
|
@@ -4403,7 +4413,7 @@ escape-html@~1.0.3: | |
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" | ||
integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= | ||
|
||
[email protected]: | ||
[email protected], escape-latex@^1.0.0: | ||
version "1.2.0" | ||
resolved "https://registry.yarnpkg.com/escape-latex/-/escape-latex-1.2.0.tgz#07c03818cf7dac250cce517f4fda1b001ef2bca1" | ||
integrity sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw== | ||
|
@@ -5208,6 +5218,11 @@ [email protected]: | |
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.0.12.tgz#0526d47c65a5fb4854df78bc77f7bec708d7b8c3" | ||
integrity sha512-8Z1K0VTG4hzYY7kA/1sj4/r1/RWLBD3xwReT/RCrUCbzPszjNQCCsy3ktkU/eaEqX3MYa4pY37a52eiBlPMlhA== | ||
|
||
[email protected]: | ||
version "4.0.4" | ||
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.0.4.tgz#04e567110718adf7b52974a10434ab4c67a5183e" | ||
integrity sha512-aK/oGatyYLTtXRHjfEsytX5fieeR5H4s8sLorzcT12taFS+dbMZejnvm9gRa8mZAPwci24ucjq9epDyaq5u8Iw== | ||
|
||
fragment-cache@^0.2.1: | ||
version "0.2.1" | ||
resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" | ||
|
@@ -7636,6 +7651,20 @@ mathjs-expression-parser@^1.0.2: | |
dependencies: | ||
mathjs "^5.2.3" | ||
|
||
mathjs@^3.20.2: | ||
version "3.20.2" | ||
resolved "https://registry.yarnpkg.com/mathjs/-/mathjs-3.20.2.tgz#3218aebde7de8cb5627c8fe3a1a216bf399ba91d" | ||
integrity sha512-3f6/+uf1cUtIz1rYFz775wekl/UEDSQ3mU6xdxW7qzpvvhc2v28i3UtLsGTRB+u8OqDWoSX6Dz8gehaGFs6tCA== | ||
dependencies: | ||
complex.js "2.0.4" | ||
decimal.js "9.0.1" | ||
escape-latex "^1.0.0" | ||
fraction.js "4.0.4" | ||
javascript-natural-sort "0.7.1" | ||
seed-random "2.2.0" | ||
tiny-emitter "2.0.2" | ||
typed-function "0.10.7" | ||
|
||
mathjs@^5.2.3: | ||
version "5.10.3" | ||
resolved "https://registry.yarnpkg.com/mathjs/-/mathjs-5.10.3.tgz#e998885f932ea8886db8b40f7f5b199f89b427f1" | ||
|
@@ -11687,6 +11716,11 @@ timsort@^0.3.0: | |
resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" | ||
integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= | ||
|
||
[email protected]: | ||
version "2.0.2" | ||
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.0.2.tgz#82d27468aca5ade8e5fd1e6d22b57dd43ebdfb7c" | ||
integrity sha512-2NM0auVBGft5tee/OxP4PI3d8WItkDM+fPnaRAVo6xTDI2knbz9eC5ArWGqtGlYqiH3RU5yMpdyTTO7MguC4ow== | ||
|
||
[email protected]: | ||
version "2.1.0" | ||
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" | ||
|
@@ -11875,6 +11909,11 @@ type-is@~1.6.17, type-is@~1.6.18: | |
media-typer "0.3.0" | ||
mime-types "~2.1.24" | ||
|
||
[email protected]: | ||
version "0.10.7" | ||
resolved "https://registry.yarnpkg.com/typed-function/-/typed-function-0.10.7.tgz#f702af7d77a64b61abf86799ff2d74266ebc4477" | ||
integrity sha512-3mlZ5AwRMbLvUKkc8a1TI4RUJUS2H27pmD5q0lHRObgsoWzhDAX01yg82kwSP1FUw922/4Y9ZliIEh0qJZcz+g== | ||
|
||
[email protected]: | ||
version "1.1.0" | ||
resolved "https://registry.yarnpkg.com/typed-function/-/typed-function-1.1.0.tgz#ea149706e0fb42aca1791c053a6d94ccd6c4fdcb" | ||
|