-
Notifications
You must be signed in to change notification settings - Fork 0
/
triggers.js
110 lines (97 loc) · 3.05 KB
/
triggers.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
(function () {
// Domain
var trigger = function (value, motion, acc) {
this.value = value;
this.motion = motion;
this.selected = false;
this.p = { x: 0, y: 0 };
this.accidental = acc;
this.size = 0.13;
};
trigger.prototype.update = function (t) {
this.p = this.motion(t);
};
trigger.prototype.render = function (draw, type) {
var state = this.selected ? 'selected' : 'none'
draw.trigger(this.p.x, this.p.y, this.size, this.value, type, state, this.accidental);
};
var sqr = function(x) { return x * x };
var sqrDist = function(v, w) { return sqr(v.x - w.x) + sqr(v.y - w.y) };
var sqrDistToSegment = function(p, v, w) {
var l2 = sqrDist(v, w);
if (l2 == 0) return sqrDist(p, v);
var t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2;
if (t < 0) return sqrDist(p, v);
if (t > 1) return sqrDist(p, w);
return sqrDist(p, { x: v.x + t*(w.x - v.x), y: v.y + t*(w.y - v.y) });
};
var isNeighbouringLocation = function (l, r, size) {
return sqrDist(l, r) <= sqr(size*1.1);
};
var isNeighbouringThird = function (l, r) {
// NEEDS DOING PROPERLY in the music domain. Must handle non diatonic too; eg 'me' etc
var nextThird = { do: 'mi', mi: 'sol', sol: 'ti', ti: 're', re: 'fa', fa: 'la', la: 'do' };
return nextThird[l] === r || nextThird[r] === l;
};
trigger.prototype.touch = function (sel, s, e) {
if (this.selected) { return; }
var self = this;
var last = sel[sel.length-1];
if (sel.length > 0 && !isNeighbouringThird(this.value, last.value)) { return; }
if (sel.length > 0 && !isNeighbouringLocation(self.p, last.p, self.size)) { return; }
if (sel.some(function (t) { return self.value === t.value;})) { return; }
var p = { x: this.p.x, y: this.p.y };
var sqrDist = sqrDistToSegment(p, s, e);
if (sqrDist <= sqr(this.size*0.8)) {
this.selected = true;
sel.push(this);
}
};
//////
var dropIn = function (x, y) {
return function (t) {
return {
x: x,
y: y + Math.max(1+y+x/5-t*2, 0)
};
};
}
musis.triggers = function (infos, type) {
this.t = 0;
this.triggers = [];
this.selected = [];
this.type = type;
var num = infos.length;
var self = this;
for (var y=0; y<=5; y++) {
for (var x=-5; x<=5; x++) {
var i = infos[Math.floor(Math.random()*infos.length)];
var motion = dropIn(x/7, y/7);
self.triggers.push( new trigger(i.value, motion, i.acc) );
}
}
};
musis.triggers.prototype.update = function (dt) {
this.t += dt;
var t = this.t;
this.triggers.map(function(trigger) { trigger.update(t); });
};
musis.triggers.prototype.render = function (draw) {
var self = this;
this.triggers.map(function(trigger) { trigger.render(draw, self.type); });
};
musis.triggers.prototype.touch = function (tx, ty) {
var sel = this.selected;
this.triggers.map(function(trigger) { trigger.touch(sel, tx, ty); });
};
musis.triggers.prototype.nextHarmony = function () {
if (this.selected.length < 3) {
this.triggers.map(function(t) { t.selected = false; });
this.selected = [];
return;
}
return this.selected.map(function (t) {
return t.value;
});
};
})();