mirror of
https://github.com/KevinMidboe/linguist.git
synced 2025-10-28 17:20:22 +00:00
Add .sc as a SuperCollider file extension
This commit is contained in:
@@ -2299,6 +2299,7 @@ SuperCollider:
|
||||
lexer: Text only
|
||||
extensions:
|
||||
- .scd
|
||||
- .sc
|
||||
|
||||
Swift:
|
||||
type: programming
|
||||
|
||||
19
samples/SuperCollider/WarpPreset.sc
Normal file
19
samples/SuperCollider/WarpPreset.sc
Normal file
@@ -0,0 +1,19 @@
|
||||
WarpPreset {
|
||||
*new {|path|
|
||||
if(path.notNil) {
|
||||
^Object.readArchive(path);
|
||||
};
|
||||
|
||||
^super.new.init();
|
||||
}
|
||||
|
||||
init {
|
||||
|
||||
}
|
||||
|
||||
save {
|
||||
Dialog.savePanel({|path|
|
||||
this.writeArchive(path);
|
||||
});
|
||||
}
|
||||
}
|
||||
286
samples/SuperCollider/WarpTate.sc
Normal file
286
samples/SuperCollider/WarpTate.sc
Normal file
@@ -0,0 +1,286 @@
|
||||
WarpTate {
|
||||
classvar <numSections = 8;
|
||||
// classvar <sectionDur = 3 * 60;
|
||||
classvar <sectionDur = 60;
|
||||
|
||||
var <sensorKeys;
|
||||
var <clock;
|
||||
var <tempo;
|
||||
var <>tempoChannel;
|
||||
var <>tempoControl;
|
||||
var <out;
|
||||
var <tracks;
|
||||
var <>sections;
|
||||
var <availableControls;
|
||||
var <controls;
|
||||
var <sensorVals;
|
||||
var <sensorPrevs;
|
||||
var <sensorMins;
|
||||
var <sensorMaxs;
|
||||
var <>sensorMinAdj;
|
||||
var <>sensorMaxAdj;
|
||||
var <doAdjusts;
|
||||
var <playRout;
|
||||
|
||||
*new {
|
||||
^super.new.init;
|
||||
}
|
||||
|
||||
init {
|
||||
tempo = 120;
|
||||
tempoChannel = 15;
|
||||
tempoControl = 3;
|
||||
clock = TempoClock.default
|
||||
.tempo_(2)
|
||||
.permanent_(true);
|
||||
|
||||
MIDIClient.init;
|
||||
out = MIDIOut.newByName("IAC Driver", "Bus 1");
|
||||
out.latency = 0;
|
||||
|
||||
tracks = IdentityDictionary[];
|
||||
sections = Array.newClear(WarpTate.numSections);
|
||||
// sections is a List of IdentityDictionary to be mapped to
|
||||
// WarpTrack settings var
|
||||
// e.g. List[IdentityDictionary[
|
||||
// '303_1' -> IdentityDictionary['notes' -> List[42]],
|
||||
// '808_1' -> IdentityDictionary['notes' -> List[24]]
|
||||
// ]
|
||||
// ]
|
||||
sensorKeys = ['303a', '303b', '808a', '808b'];
|
||||
|
||||
// channel 16 reserved for tempo changes
|
||||
availableControls = 15.collect {|channel|
|
||||
(0..120).reject({|item, i|
|
||||
[ 0, 1, 2, 4, 5, 6, 7, 8, 10, 11, 12, 13, 64, 65, 66, 67, 68,
|
||||
69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 84, 91, 92, 93, 94,
|
||||
95, 96, 97, 98, 99, 100, 102 ].includes(item)
|
||||
});
|
||||
};
|
||||
|
||||
controls = (0..127).collect { IdentityDictionary[] };
|
||||
|
||||
this.addOSCdefs();
|
||||
|
||||
CmdPeriod.add({this.stop});
|
||||
}
|
||||
|
||||
tempo_ {|argTempo|
|
||||
if(argTempo >= 50 && argTempo <= 177) {
|
||||
tempo = argTempo;
|
||||
clock.tempo = tempo / 60;
|
||||
|
||||
out.control(tempoChannel, tempoControl, tempo - 50);
|
||||
} {
|
||||
"Tempo out of Logic's range :(".postln;
|
||||
};
|
||||
}
|
||||
|
||||
addTrack {|trackKey, channel, type|
|
||||
tracks[trackKey] = WarpTrack(this, trackKey, channel, type);
|
||||
^tracks[trackKey];
|
||||
}
|
||||
|
||||
loadTrack {|preset, checkAvailable|
|
||||
var track = WarpTrack.load(this, preset, checkAvailable),
|
||||
trackKey = track.settings['key'];
|
||||
|
||||
tracks[trackKey] = track;
|
||||
^tracks[trackKey];
|
||||
}
|
||||
|
||||
readTrack {|path|
|
||||
var track = WarpTrack.read(this, path),
|
||||
trackKey = track.settings['key'];
|
||||
|
||||
tracks[trackKey] = track;
|
||||
^tracks[trackKey];
|
||||
}
|
||||
|
||||
removeTrack {|trackKey|
|
||||
tracks[trackKey].allOff();
|
||||
tracks[trackKey] = nil;
|
||||
}
|
||||
|
||||
removeAllTracks {
|
||||
tracks = IdentityDictionary[];
|
||||
}
|
||||
|
||||
on {|trackKey, note|
|
||||
tracks[trackKey].on(note);
|
||||
}
|
||||
|
||||
off {|trackKey, note|
|
||||
tracks[trackKey].off(note);
|
||||
}
|
||||
|
||||
hit {|trackKey, note=60, vel=127, dur=1|
|
||||
tracks[trackKey].hit(note, vel, dur);
|
||||
}
|
||||
|
||||
noteOn {|midiChannel, note, vel|
|
||||
out.noteOn(midiChannel, note, vel);
|
||||
}
|
||||
|
||||
noteOff {|midiChannel, note, vel|
|
||||
out.noteOff(midiChannel, note, vel);
|
||||
}
|
||||
|
||||
control {|midiChannel, num, val|
|
||||
out.control(midiChannel, num, val);
|
||||
}
|
||||
|
||||
isControlAvailable {|channel, controlNum|
|
||||
^controls[channel].keys.includes(controlNum.asSymbol).not;
|
||||
}
|
||||
|
||||
setControl {|channel, num, key|
|
||||
controls[channel][num.asSymbol] = key;
|
||||
availableControls[channel].remove(num);
|
||||
}
|
||||
|
||||
assign {|trackKey, paramKey, controlNum, learn=false|
|
||||
var channel = tracks[trackKey].settings['midiChannel'];
|
||||
|
||||
if(controlNum.notNil && this.isControlAvailable(channel, controlNum)) {
|
||||
tracks[trackKey].assign(paramKey, controlNum, learn);
|
||||
availableControls[channel].removeAt(0);
|
||||
|
||||
} {
|
||||
if(availableControls[channel].size > 0) {
|
||||
tracks[trackKey].assign(paramKey, availableControls[channel][0], learn);
|
||||
availableControls[channel].removeAt(0);
|
||||
} {
|
||||
"no controls left!".postln;
|
||||
};
|
||||
};
|
||||
|
||||
"Don't forget to turn off MIDI learn".postln
|
||||
}
|
||||
|
||||
setParam {|trackKey, paramKey, val|
|
||||
var track, param;
|
||||
|
||||
if((track = tracks[trackKey]).notNil) {
|
||||
if(track.params[paramKey].notNil) {
|
||||
track.setParam(paramKey, val);
|
||||
} {
|
||||
"paramKey doesn't exist".postln;
|
||||
};
|
||||
} {
|
||||
"track key doesn't exist".postln;
|
||||
};
|
||||
}
|
||||
|
||||
// sec takes IdentityDictionarys of WarpTrack settings
|
||||
addSection {|index, tempo=120, presets|
|
||||
// Add section with tempo
|
||||
sections[index] = IdentityDictionary[
|
||||
'tempo' -> tempo,
|
||||
'tracks' -> presets
|
||||
];
|
||||
|
||||
presets.do {|preset, i|
|
||||
// create track if there ain't one with this key
|
||||
if(tracks.includesKey(preset['key']).not) {
|
||||
this.loadTrack(preset, true);
|
||||
};
|
||||
|
||||
// store the preset
|
||||
// sections[index]['tracks'][preset['key']] = preset;
|
||||
};
|
||||
|
||||
^sections;
|
||||
}
|
||||
|
||||
play {
|
||||
|
||||
if(sections.any {|item, i| item.notNil; }) {
|
||||
playRout = Routine {
|
||||
inf.do {|i|
|
||||
sections.do {|section|
|
||||
if(section.notNil) {
|
||||
if(i !== 0) {
|
||||
tracks.do {|track|
|
||||
track.allOff();
|
||||
};
|
||||
this.removeAllTracks();
|
||||
};
|
||||
|
||||
this.tempo = section['tempo'];
|
||||
|
||||
section['tracks'].do {|track, i|
|
||||
var newTrack = this.loadTrack(track, false);
|
||||
newTrack.play();
|
||||
};
|
||||
sectionDur.wait;
|
||||
};
|
||||
};
|
||||
}
|
||||
};
|
||||
clock.playNextBar(playRout);
|
||||
} {
|
||||
"no sections added!".postln;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
stop {
|
||||
playRout.stop;
|
||||
|
||||
tracks.do {|track|
|
||||
track.allOff();
|
||||
out.allNotesOff(track.settings['midiChannel']);
|
||||
}
|
||||
}
|
||||
|
||||
addOSCdefs {
|
||||
sensorVals = 0!sensorKeys.size;
|
||||
sensorPrevs = 0!sensorKeys.size;
|
||||
sensorMins = 9999!sensorKeys.size;
|
||||
sensorMaxs = 0!sensorKeys.size;
|
||||
sensorMinAdj = sensorMinAdj ?? { 0.005 };
|
||||
sensorMaxAdj = sensorMaxAdj ?? { 0.01 };
|
||||
doAdjusts = false!sensorKeys.size;
|
||||
|
||||
sensorKeys.do {|sensorKey, i|
|
||||
OSCdef(("sensor_" ++ sensorKey).asSymbol, {|msg, time, addr, recvPort|
|
||||
var val = msg[1];
|
||||
|
||||
|
||||
sensorPrevs[i] = sensorVals[i];
|
||||
sensorVals[i] = val;
|
||||
|
||||
if(doAdjusts[i]) {
|
||||
sensorMins[i] = min(val, sensorMins[i]);
|
||||
sensorMaxs[i] = max(val, sensorMaxs[i]);
|
||||
|
||||
if(val < sensorMaxs[i]) {
|
||||
sensorMaxs[i] = sensorMaxs[i] - sensorMaxAdj;
|
||||
};
|
||||
|
||||
if(val > sensorMins[i]) {
|
||||
sensorMins[i] = sensorMins[i] + sensorMinAdj;
|
||||
};
|
||||
} {
|
||||
val = val.clip(sensorMins[i], sensorMaxs[i]);
|
||||
};
|
||||
|
||||
|
||||
tracks.do {|track, j|
|
||||
if(track.settings['sensorFuncs'].includesKey(sensorKey)) {
|
||||
track.sensor(
|
||||
sensorKey,
|
||||
val.linlin(
|
||||
sensorMins[i],
|
||||
sensorMaxs[i],
|
||||
127,
|
||||
0
|
||||
)
|
||||
);
|
||||
};
|
||||
}
|
||||
}, ("/prox/" ++ sensorKey).asSymbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
263
samples/SuperCollider/WarpTrack.sc
Normal file
263
samples/SuperCollider/WarpTrack.sc
Normal file
@@ -0,0 +1,263 @@
|
||||
WarpTrack {
|
||||
classvar <defaults;
|
||||
|
||||
var <parent;
|
||||
var <settings;
|
||||
|
||||
*initClass {
|
||||
defaults['303_1'] = defaults['303'].copy;
|
||||
defaults['303_1']['paramControls'].putPairs([
|
||||
'Bus 1', 46,
|
||||
'Bus 2', 45,
|
||||
'Bus 3', 48,
|
||||
'echovol', 47
|
||||
]);
|
||||
defaults['303_1']['params'].putPairs([
|
||||
'Bus 1', 0,
|
||||
'Bus 2', 0,
|
||||
'Bus 3', 0,
|
||||
'echovol', 0
|
||||
]);
|
||||
|
||||
defaults['303_2'] = defaults['303_1'].copy;
|
||||
defaults['303_2']['paramControls'].putPairs([
|
||||
]);
|
||||
defaults['303_2']['params'].putPairs([
|
||||
]);
|
||||
|
||||
defaults['808_1'] = defaults['808'].copy;
|
||||
defaults['808_1']['paramControls'].putPairs([
|
||||
'bitcrusher', 88,
|
||||
'Send 1', 89,
|
||||
'Send 2', 90,
|
||||
'Send 3', 101
|
||||
]);
|
||||
defaults['808_1']['params'].putPairs([
|
||||
'bitcrusher', 0,
|
||||
'Send 1', 0,
|
||||
'Send 2', 0,
|
||||
'Send 3', 0
|
||||
]);
|
||||
|
||||
defaults['808_2'] = defaults['808_1'].copy;
|
||||
defaults['808_2']['paramControls'].putPairs([]);
|
||||
defaults['808_2']['params'].putPairs([]);
|
||||
}
|
||||
|
||||
*new {|argParent, argKey, argMidiChannel, argType|
|
||||
^super.new.init(argParent, argKey, argMidiChannel, argType);
|
||||
}
|
||||
|
||||
*read {|argParent, path|
|
||||
^super.new.init(argParent).readPreset(path);
|
||||
}
|
||||
|
||||
*load {|argParent, preset, checkAvailable|
|
||||
^super.new.init(argParent).loadPreset(preset, checkAvailable);
|
||||
}
|
||||
|
||||
init {|argParent, argKey, argMidiChannel, argType|
|
||||
parent = argParent;
|
||||
|
||||
settings = IdentityDictionary[
|
||||
'key' -> argKey,
|
||||
'midiChannel' -> argMidiChannel,
|
||||
'notes' -> Set[],
|
||||
'params' -> IdentityDictionary[],
|
||||
'paramControls' -> IdentityDictionary[],
|
||||
'patternTrack' -> true,
|
||||
'sensorFuncs' -> IdentityDictionary[]
|
||||
];
|
||||
|
||||
if(argType.notNil) {
|
||||
settings['type'] = argType;
|
||||
if(WarpTrack.defaults.keys.includes(argType)) {
|
||||
['paramControls', 'params'].do {|key, i|
|
||||
settings[key] = WarpTrack.defaults[argType][key];
|
||||
}
|
||||
};
|
||||
|
||||
this.initParams();
|
||||
};
|
||||
}
|
||||
|
||||
on {|note|
|
||||
var clock = parent.clock;
|
||||
var sub = 1 / (parent.clock.tempo * 16); // one sub division
|
||||
|
||||
clock.schedAbs(clock.nextBar - sub, {
|
||||
if(settings['patternTrack']) {
|
||||
this.allOff();
|
||||
} {
|
||||
this.off(note);
|
||||
};
|
||||
});
|
||||
|
||||
parent.clock.playNextBar({
|
||||
settings['notes'].add(note);
|
||||
parent.noteOn(settings['midiChannel'], note, 127);
|
||||
});
|
||||
}
|
||||
|
||||
off {|note|
|
||||
// settings['notes'].remove(note);
|
||||
parent.noteOff(settings['midiChannel'], note, 0);
|
||||
}
|
||||
|
||||
hit {|note=60, vel=127, dur=1, quant=0|
|
||||
{
|
||||
parent.noteOn(settings['midiChannel'], note, vel);
|
||||
dur.wait;
|
||||
parent.noteOff(settings['midiChannel'], note, vel);
|
||||
}.fork(parent.clock, quant:quant);
|
||||
}
|
||||
|
||||
allOff {
|
||||
settings['notes'].do {|note, i|
|
||||
this.off(note);
|
||||
};
|
||||
}
|
||||
|
||||
assign {|paramKey, num, learn=false, init=true, checkAvailable=true|
|
||||
if(num.notNil) {
|
||||
this.assignAll(IdentityDictionary[paramKey -> num], learn, init, checkAvailable);
|
||||
} {
|
||||
parent.assign(settings['key'], paramKey, nil, learn);
|
||||
};
|
||||
}
|
||||
|
||||
assignAll {|paramControls, learn=false, init=true, checkAvailable=true|
|
||||
var action = {
|
||||
var channel = settings['midiChannel'];
|
||||
|
||||
paramControls.keysValuesDo { |paramKey, num|
|
||||
if(checkAvailable.not ||
|
||||
(checkAvailable && parent.isControlAvailable(channel, num))) {
|
||||
settings['paramControls'][paramKey] = num;
|
||||
if(init) {
|
||||
settings['params'][paramKey] = 0;
|
||||
};
|
||||
parent.setControl(channel, num, paramKey);
|
||||
if(learn) {
|
||||
parent.control(channel, num, 127);
|
||||
0.05.wait;
|
||||
parent.control(channel, num, 0);
|
||||
};
|
||||
paramKey ++ " assigned to controlNum " ++ num;
|
||||
} {
|
||||
("this controlNum " ++ num ++ " is already assigned!").postln;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
if(learn) {
|
||||
action.fork;
|
||||
} {
|
||||
action.();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
initParams {
|
||||
settings['params'].keysValuesDo { |key, value|
|
||||
this.setParam(key, value);
|
||||
};
|
||||
settings['paramControls'].keysValuesDo { |key, value|
|
||||
parent.setControl(settings['midiChannel'], value, key);
|
||||
};
|
||||
}
|
||||
|
||||
setParam {|paramKey, val, quant|
|
||||
var func = {
|
||||
parent.control(
|
||||
settings['midiChannel'],
|
||||
settings['paramControls'][paramKey],
|
||||
val
|
||||
);
|
||||
|
||||
settings['params'][paramKey] = val;
|
||||
};
|
||||
|
||||
if(quant.notNil) {
|
||||
{
|
||||
func.();
|
||||
}.fork(parent.clock, quant:quant);
|
||||
} {
|
||||
func.();
|
||||
};
|
||||
}
|
||||
|
||||
readPreset {|path, checkAvailable=true|
|
||||
this.loadPreset(Object.readArchive(path), checkAvailable);
|
||||
}
|
||||
|
||||
loadPreset {|preset, checkAvailable=true|
|
||||
// copy all settings except notes and paramControls
|
||||
preset.keys.reject({|settingKey, i|
|
||||
['notes', 'paramControls'].includes(settingKey);
|
||||
}).do {|presetKey, i|
|
||||
settings[presetKey] = preset[presetKey];
|
||||
};
|
||||
|
||||
// copy notes if it's a patternTrack
|
||||
if(preset['patternTrack']) {
|
||||
settings['notes'] = preset['notes'];
|
||||
};
|
||||
|
||||
// assign all without learn or init
|
||||
this.assignAll(
|
||||
preset['paramControls'],
|
||||
false,
|
||||
false,
|
||||
checkAvailable
|
||||
);
|
||||
|
||||
this.initParams();
|
||||
|
||||
// if(settings['notes'].size > 0) {
|
||||
// this.on(settings['notes'].asArray[0]);
|
||||
// };
|
||||
}
|
||||
|
||||
sensor {|sensorKey, val|
|
||||
settings['sensorFuncs'][sensorKey].do {|func, i|
|
||||
func.(this, val);
|
||||
}
|
||||
}
|
||||
|
||||
addFunc {|sensorKey, funcKey, func|
|
||||
if(parent.sensorKeys.includes(sensorKey)) {
|
||||
if(settings['sensorFuncs'].includesKey(sensorKey).not) {
|
||||
settings['sensorFuncs'][sensorKey] = IdentityDictionary[];
|
||||
};
|
||||
|
||||
settings['sensorFuncs'][sensorKey][funcKey] = func;
|
||||
} {
|
||||
"parent doesn't have that sensor key".postln;
|
||||
};
|
||||
}
|
||||
|
||||
removeFunc {|sensorKey, funcKey|
|
||||
settings['sensorFuncs'][sensorKey].removeAt(funcKey);
|
||||
|
||||
if(settings['sensorFuncs'][sensorKey].isEmpty) {
|
||||
settings['sensorFuncs'].removeAt(sensorKey);
|
||||
};
|
||||
}
|
||||
|
||||
availableControls {
|
||||
^parent.availableControls[settings['midiChannel']].copy;
|
||||
}
|
||||
|
||||
save {
|
||||
Dialog.savePanel({|path|
|
||||
settings.writeArchive(path);
|
||||
});
|
||||
}
|
||||
|
||||
play {
|
||||
if(settings['patternTrack'] && settings['notes'].notEmpty) {
|
||||
this.on(settings['notes'].choose);
|
||||
};
|
||||
}
|
||||
}
|
||||
127
samples/SuperCollider/WarpUtil.sc
Normal file
127
samples/SuperCollider/WarpUtil.sc
Normal file
@@ -0,0 +1,127 @@
|
||||
WarpUtil {
|
||||
var <>parent;
|
||||
var <curSensor;
|
||||
|
||||
var <win;
|
||||
var <texts;
|
||||
var <sensorSlider;
|
||||
var <sliders;
|
||||
var <updateRout;
|
||||
|
||||
*new {|argParent|
|
||||
^super.new.init(argParent);
|
||||
}
|
||||
|
||||
init {|argParent|
|
||||
parent = argParent;
|
||||
texts = IdentityDictionary[];
|
||||
|
||||
this.makeView();
|
||||
this.startUpdate();
|
||||
}
|
||||
|
||||
calibrate {
|
||||
{
|
||||
parent.doAdjusts.size.do {|i|
|
||||
parent.sensorMaxs[i] = 0;
|
||||
parent.sensorMins[i] = 9999;
|
||||
parent.doAdjusts[i] = true;
|
||||
};
|
||||
|
||||
sliders.do {|slider, i|
|
||||
if(parent.sensorKeys[i] !== curSensor) {
|
||||
slider.valueAction_(0);
|
||||
0.1.wait;
|
||||
slider.valueAction_(1);
|
||||
};
|
||||
}
|
||||
}.fork(AppClock);
|
||||
}
|
||||
|
||||
stopCalibrate {
|
||||
parent.doAdjusts.size.do {|i|
|
||||
parent.doAdjusts[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
makeView {
|
||||
var width = 370;
|
||||
|
||||
if(win.notNil) {
|
||||
win.close;
|
||||
};
|
||||
|
||||
win = Window("Sensor Inspector", Rect(256, 10, width, 424)).front;
|
||||
win.view.addFlowLayout;
|
||||
|
||||
['sensorVals', 'sensorPrevs', 'sensorMins', 'sensorMaxs'].do {|label, i|
|
||||
StaticText(win, (width * 0.5)@20)
|
||||
.string_(label.asString);
|
||||
|
||||
win.view.decorator.nextLine;
|
||||
|
||||
|
||||
texts[label] = StaticText(win, (width / 2)@40);
|
||||
|
||||
if(curSensor.notNil) {
|
||||
texts[label].string_(
|
||||
"\t" ++ parent.perform(label).at(
|
||||
parent.sensorKeys.indexOf(curSensor)
|
||||
);
|
||||
);
|
||||
};
|
||||
|
||||
win.view.decorator.nextLine;
|
||||
};
|
||||
|
||||
sensorSlider = EZSlider(win, 280@20, label: curSensor.asString);
|
||||
|
||||
sliders = parent.sensorKeys.collect { |sensorKey, i|
|
||||
EZSlider(win, 280@20, label: sensorKey.asString)
|
||||
.action_({|ez|
|
||||
NetAddr.localAddr.sendMsg(
|
||||
"/prox/" ++ sensorKey,
|
||||
ez.value * 100
|
||||
);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
startUpdate {
|
||||
updateRout = Routine {
|
||||
inf.do {|i|
|
||||
var index;
|
||||
|
||||
if(curSensor.notNil) {
|
||||
index = parent.sensorKeys.indexOf(curSensor);
|
||||
|
||||
['sensorVals', 'sensorPrevs', 'sensorMins',
|
||||
'sensorMaxs'].do {|label, i|
|
||||
|
||||
texts[label]
|
||||
.string_("\t" ++ parent.perform(label)[index]);
|
||||
};
|
||||
|
||||
sensorSlider.value = parent.sensorVals[index].linlin(
|
||||
parent.sensorMins[index],
|
||||
parent.sensorMaxs[index],
|
||||
0,
|
||||
1
|
||||
);
|
||||
};
|
||||
0.05.wait;
|
||||
}
|
||||
};
|
||||
|
||||
updateRout.play(AppClock);
|
||||
}
|
||||
|
||||
stopUpdate {
|
||||
updateRout.stop();
|
||||
}
|
||||
|
||||
curSensor_ {|argCurSensor|
|
||||
curSensor = argCurSensor;
|
||||
this.makeView();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user