Subversion Repositories DIN Is Noise

Rev

Rev 2333 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
964 jag 1
/*
2
* din.cc
2302 jag 3
* DIN Is Noise is copyright (c) 2006-2025 Jagannathan Sampath
1713 jag 4
* DIN Is Noise is released under GNU Public License 2.0
1479 jag 5
* For more information, please visit https://dinisnoise.org/
964 jag 6
*/
7
 
8
#include "main.h"
9
#include "din.h"
10
#include "console.h"
11
#include "solver.h"
12
#include "container.h"
13
#include "utils.h"
14
#include "input.h"
15
#include "color.h"
16
#include "random.h"
17
#include "command.h"
18
#include "delay.h"
19
#include "chrono.h"
20
#include "delay.h"
21
#include "tcl_interp.h"
22
#include "font.h"
23
#include "scale_info.h"
24
#include "ui_list.h"
25
#include "vector2d.h"
26
#include "keyboard_keyboard.h"
1840 jag 27
#include "defvelaccel.h"
964 jag 28
#include "log.h"
29
#include <sstream>
30
#include <algorithm>
1801 jag 31
 
1472 jag 32
#define ENDER -1
1847 jag 33
#define LAUNCHLATER 1
1434 jag 34
 
964 jag 35
extern string user_data_dir; // user data directory
36
extern console cons; // console
37
extern viewport view; // viewport
38
extern int mousex, mousey, mouseyy; // mouse pos
39
extern int lmb, rmb, mmb; // mouse button state
1651 jag 40
extern int LEFT, BOTTOM, RIGHT, TOP; // microtonal keyboard extents
964 jag 41
extern int HEIGHT; // default number of volumes on the microtonal keyboard
42
extern int WIDTH; // default number of microtones in a range
43
extern int NUM_OCTAVES; // number of octaves the board spans
44
extern map<string, int> NOTE_POS; // interval name -> value, 1 - 1, 1# - 2, 2 - 3  etc
45
extern int SAMPLE_RATE; // sampling rate
46
extern map<string, float> INTERVALS; // interval name -> value
47
extern audio_out aout; // audio output
48
extern tcl_interp interpreter; // integrated tcl interpreter
1756 jag 49
extern int TRAILSIZE; // drone trail size (== number of trail points)
964 jag 50
extern audio_clock clk; // audio clock
2188 jag 51
 
964 jag 52
extern din din0; // microtonal-keyboard
53
extern float VOLUME; // volume of voice on microtonal-keyboard
54
extern curve_library wav_lib; // waveform library
55
extern float FRAME_TIME; // time per frame in seconds
56
extern int quit; // user wants to quit?
57
extern int line_height; // of text
1310 jag 58
extern keyboard_keyboard keybd2; // keyboard-keyboard
59
extern int IPS; // inputs per second
60
extern beat2value octave_shift; // octave shift over bpm
1765 jag 61
 
964 jag 62
extern const float PI_BY_180;
1432 jag 63
extern const float PI;
964 jag 64
extern mouse_slider mouse_slider0;
65
extern const char* s_drones;
1437 jag 66
extern float VOICE_VOLUME;
67
 
1765 jag 68
typedef std::list<mesh>::iterator mesh_iterator;
69
 
2135 jag 70
extern int doublebpm;
2291 jag 71
extern float BPM_MULT;
2135 jag 72
 
2188 jag 73
extern int BEATER;
74
 
75
 
2291 jag 76
 
1719 jag 77
// din::din () in eval.cc
964 jag 78
 
79
void din::setup () {
1909 jag 80
 
81
  dinfo.load ();
964 jag 82
 
83
  droneed.add (&drone_wave, &dronelis);
84
  droneed.attach_library (&wav_lib);
85
 
86
  wavsol (&wave);
87
  wavplay.set_wave (&wavsol);
88
 
89
  waved.add (&wave, &wavlis);
90
  waved.attach_library (&wav_lib);
2327 jag 91
  moded.attach_library (&gatlib);
964 jag 92
 
93
  gatr.setup ();
2264 jag 94
  gatr.setswing (swing);
2265 jag 95
  gatr.setaccent (accent);
2188 jag 96
  BEATER = gated.ed;
964 jag 97
  gated.attach_library (&gatlib);
98
  gated.add (gatr.crv, &gatrlis);
2264 jag 99
  gated.add (&swing, &gatrlis);
2265 jag 100
  gated.add (&accent, &gatrlis);
964 jag 101
  gated.bv.push_back (&gatr);
102
 
103
  am_depth = 0;
104
  fm_depth = 0;
105
 
106
  fm.setup ();
107
  am.setup ();
108
 
109
  moded.add (fm.crv, &fmlis);
110
  moded.add (am.crv, &amlis);
111
  moded.bv.push_back (&fm);
112
  moded.bv.push_back (&am);
113
 
114
  fmlis.set (&fm);
115
  amlis.set (&am);
116
  gatrlis.set (&gatr);
117
 
118
  dinfo.gravity.calc ();
119
 
120
}
121
 
122
void din::scale_loaded () {
123
  int load_drones_too = 1, load_ranges_too = 1;
124
  load_scale (load_drones_too, load_ranges_too);
125
}
126
 
127
void din::scale_changed () {
128
  reset_all_ranges ();
129
}
130
 
131
void din::load_scale (int _load_drones_, int _load_ranges_) {
132
  setup_ranges (NUM_OCTAVES, _load_ranges_);
133
  if (_load_drones_) load_drones ();
1402 jag 134
  refresh_all_drones ();
964 jag 135
}
136
 
137
int din::load_ranges () {
138
 
139
  string fname = user_data_dir + scaleinfo.name + ".ranges";
140
  dlog << "<< loading ranges from: " << fname;
141
  ifstream file (fname.c_str(), ios::in);
142
  if (!file) {
143
    dlog << "!!! couldnt load range pos from " << fname << ", will use defaults +++" << endl;
144
    return 0;
145
  }
146
 
147
  string ignore;
148
 
149
  file >> ignore >> NUM_OCTAVES;
150
  int n; file >> ignore >> n;
151
  create_ranges (n);
152
 
153
  int l = LEFT, r, w, h;
154
  for (int i = 0; i < num_ranges; ++i) {
155
    range& R = ranges[i];
156
    file >> w >> h;
157
    r = l + w;
158
    R.extents (l, BOTTOM, r, BOTTOM + h);
159
    l = r;
160
    file >> R.mod.active >>
1438 jag 161
            R.fixed >>
1763 jag 162
            R.mod.am.depth >> R.mod.am.bv.bpm >> R.mod.am.bv.now >> R.mod.am.bv.bps >> R.mod.am.initial >>
163
            R.mod.fm.depth >> R.mod.fm.bv.bpm >> R.mod.fm.bv.now >> R.mod.fm.bv.bps >> R.mod.fm.initial;
964 jag 164
            R.notes[0].load (file) >> R.intervals[0];
165
            R.notes[1].load (file) >> R.intervals[1];
1802 jag 166
    R.fixed = range::CENTER;
964 jag 167
  }
168
 
169
  dlog << ", done >>>" << endl;
170
 
171
  return 1;
172
 
173
}
174
 
175
void din::save_ranges () {
176
 
177
  string fname = user_data_dir + scaleinfo.name + ".ranges";
178
  ofstream file (fname.c_str(), ios::out);
179
  if (file) {
180
    file << "num_octaves " << NUM_OCTAVES << endl;
181
    file << "num_ranges " << num_ranges << endl;
182
    for (int i = 0; i < num_ranges; ++i) {
183
      range& r = ranges[i];
1694 jag 184
      file << r.extents.width << spc << r.extents.height << spc << r.mod.active << spc
1763 jag 185
            << r.fixed << spc
186
            << r.mod.am.depth << spc << r.mod.am.bv.bpm << spc << r.mod.am.bv.now << spc << r.mod.am.bv.bps << spc << r.mod.am.initial << spc
187
            << r.mod.fm.depth << spc << r.mod.fm.bv.bpm << spc << r.mod.fm.bv.now << spc << r.mod.fm.bv.bps << spc << r.mod.fm.initial << spc;
1694 jag 188
            r.notes[0].save (file) << r.intervals[0] << spc;
189
            r.notes[1].save (file) << r.intervals[1] << spc;
964 jag 190
    }
191
    dlog << "+++ saved ranges in " << fname << " +++" << endl;
192
  }
193
 
194
}
195
 
196
void din::setup_ranges (int last_num_octaves, int load) {
1238 jag 197
 
964 jag 198
  if (load) {
199
    load_ranges ();
200
  } else {
201
    int last_num_ranges = num_ranges;
1982 jag 202
    int ht = lastr->extents.height;
964 jag 203
    create_ranges (NUM_OCTAVES * scaleinfo.num_ranges);
204
    set_range_width (last_num_ranges, last_range, WIDTH);
1982 jag 205
    set_range_height (last_num_ranges, last_range, ht);
964 jag 206
    init_range_mod (last_num_ranges, last_range);
207
    if (last_num_octaves < NUM_OCTAVES) calc_added_range_notes (last_num_octaves, last_num_ranges);
208
  }
209
 
210
  find_current_range ();
211
 
212
}
213
 
214
void din::reset_all_ranges () {
2003 jag 215
  int lr = last_range;
216
  int r0 = lr + 1;
217
    create_ranges (NUM_OCTAVES * scaleinfo.num_ranges);
218
  int r1 = last_range;
219
  if (r1 > r0) {
220
    set_range_width (r0, r1, WIDTH);
221
    set_range_height (r0, r1, ranges[lr].extents.height);
222
    init_range_mod (r0, r1);
223
  }
964 jag 224
  calc_added_range_notes (0, 0);
2001 jag 225
  find_current_range ();
226
  find_visible_ranges ();
1402 jag 227
  refresh_all_drones ();
964 jag 228
}
229
 
2003 jag 230
void din::create_ranges (int n) {
231
  ranges.resize (n);
232
  initranpar (n);
233
}
234
 
235
void din::initranpar (int n) {
236
  num_ranges = n;
237
  last_range = max (0, num_ranges - 1);
238
  firstr = &ranges [0];
239
  lastr = &ranges [last_range];
240
  clamp<int> (0, dinfo.sel_range, last_range);
241
  MENU.sp_range.set_limits (0, last_range);
242
}
243
 
964 jag 244
void din::calc_added_range_notes (int p, int r) {
245
  int rn = r;
246
  for (; p < NUM_OCTAVES; ++p) {
247
    for (int i = 0, j = 1; i < scaleinfo.num_ranges; ++i, ++j) {
248
      range& R = ranges[r++];
249
      note& n0 = R.notes[0];
250
      note& n1 = R.notes[1];
251
      n0.scale_pos = i;
252
      n1.scale_pos = j;
253
      n0.octave = n1.octave = p;
254
      string& i0 = R.intervals[0];
255
      string& i1 = R.intervals[1];
256
      i0 = scaleinfo.notes[i];
257
      i1 = scaleinfo.notes[j];
258
      R.calc (scaleinfo);
259
      n0.set_name (i0, scaleinfo.western);
260
      n1.set_name (i1, scaleinfo.western);
261
    }
262
  }
263
  if (rn) {
264
    range &R1 = ranges[rn-1], &R = ranges[rn];
265
    // last note of existing ranges should be = to first note of first new range
266
    if (!equals (R.notes[0].hz, R1.notes[1].hz)) {
267
      R.notes[0]=R1.notes[1];
268
      R.intervals[0]=R1.intervals[1];
269
      R.delta_step = R.notes[1].step - R.notes[0].step;
270
    }
271
  }
272
}
273
 
274
void din::init_range_mod (int s, int t) {
275
  for (int i = s; i <= t; ++i) ranges[i].init_mod ();
276
}
277
 
278
void din::set_range_width (int ran, int sz) {
279
  range& R = ranges[ran];
280
  int delta = sz - R.extents.width;
281
  R.extents (R.extents.left, R.extents.bottom, R.extents.left + sz, R.extents.top);
282
  R.mod.fm.initial = R.extents.width;
283
  R.mod.fm.bv.now = 0;
284
  for (int i = ran + 1; i < num_ranges; ++i) {
285
    range& Ri = ranges[i];
286
    Ri.extents (Ri.extents.left + delta, Ri.extents.bottom, Ri.extents.right + delta, Ri.extents.top);
287
  }
1402 jag 288
  refresh_drones (ran, last_range);
964 jag 289
  find_visible_ranges ();
290
}
291
 
292
void din::set_range_width (int s, int t, int sz) {
293
  int r, l;
294
  if (s < 1) r = LEFT; else r = ranges[s-1].extents.right;
295
  for (int i = s; i <= t; ++i) {
296
    l = r;
297
    r = l + sz;
298
    range& R = ranges[i];
299
    R.extents (l, R.extents.bottom, r, R.extents.top);
300
    R.mod.fm.initial = R.extents.width;
301
    R.mod.fm.bv.now = 0;
302
  }
1402 jag 303
  refresh_drones (s, t);
964 jag 304
  find_visible_ranges ();
305
}
306
 
307
void din::set_range_height (int s, int t, int h) {
308
  for (int i = s; i <= t; ++i) {
309
    range& R = ranges[i];
310
    R.extents (R.extents.left, BOTTOM, R.extents.right, BOTTOM+h);
311
    R.mod.am.initial = h;
312
    R.mod.am.bv.now = 0;
313
  }
1402 jag 314
  refresh_drones (s, t);
964 jag 315
}
316
 
317
void din::set_range_height (int r, int h) {
318
  range& R = ranges[r];
319
  R.extents (R.extents.left, BOTTOM, R.extents.right, BOTTOM + h);
320
  R.mod.am.initial = h;
321
  R.mod.am.bv.now = 0;
1402 jag 322
  refresh_drones (r);
964 jag 323
}
324
 
325
void din::default_range_to_all (int h) {
1084 jag 326
  extern multi_curve ran_width_crv, ran_height_crv;
327
  if (h) {
964 jag 328
    set_range_height (0, last_range, HEIGHT);
1084 jag 329
    ran_height_crv.load ("range-height.crv.default");
330
 
331
  }
332
  else {
964 jag 333
    set_range_width (0, last_range, WIDTH);
1084 jag 334
    ran_width_crv.load ("range-width.crv.default");
335
  }
964 jag 336
}
337
 
338
void din::selected_range_to_all (int h) {
339
  if (h)
340
    set_range_height (0, last_range, ranges[dinfo.sel_range].extents.height);
341
  else
342
    set_range_width (0, last_range, ranges[dinfo.sel_range].extents.width);
343
}
344
 
345
void din::default_range_to_selected (int h) {
346
  if (h)
347
    set_range_height (dinfo.sel_range, HEIGHT);
348
  else
349
    set_range_width (dinfo.sel_range, WIDTH);
350
}
351
 
352
int din::range_left_changed (int r, int dx, int mr) {
353
  int valid = 0;
354
  range& R = ranges [r];
1605 jag 355
  int oldleft = R.extents.left;
964 jag 356
  if (dx != 0) {
1605 jag 357
    int newleft = oldleft + dx;
358
    valid = newleft < R.extents.right ? 1 : 0;
964 jag 359
    if (valid) {
1605 jag 360
      if (adjustranges.others) {
361
        R.extents (newleft, R.extents.bottom, R.extents.right, R.extents.top);
362
        for (int i = 0; i < r; ++i) {
363
          range& ir = ranges [i];
364
          ir.extents (ir.extents.left + dx, ir.extents.bottom, ir.extents.right + dx, ir.extents.top);
365
        }
366
      } else {
367
        int j = r - 1;
368
        if (j > -1) {
369
          range& rl = ranges[j];
370
          box<int>& rle = rl.extents;
371
          if (rle.left < newleft) {
372
            R.extents (newleft, R.extents.bottom, R.extents.right, R.extents.top);
373
            rle (rle.left, rle.bottom, R.extents.left, rle.top);
374
          }
375
        } else {
376
          R.extents (newleft, R.extents.bottom, R.extents.right, R.extents.top);
377
        }
378
      }
379
      if (mr) { // reset modulation
964 jag 380
        R.mod.fm.initial = R.extents.width;
381
        R.mod.fm.bv.now = 0;
382
      }
1605 jag 383
      if (R.mod.active == 0) R.print_hz_per_pixel ();
964 jag 384
    }
385
    LEFT = ranges[0].extents.left;
386
  }
387
  return valid;
388
}
389
 
390
int din::range_right_changed (int r, int dx, int mr) {
391
  int valid = 0;
392
  range& R = ranges [r];
1605 jag 393
  int oldright = R.extents.right;
964 jag 394
  if (dx != 0) {
1605 jag 395
    int newright = oldright + dx;
396
    valid = newright > R.extents.left ? 1 : 0;
964 jag 397
    if (valid) {
1605 jag 398
      if (adjustranges.others) {
399
        R.extents (R.extents.left, R.extents.bottom, newright, R.extents.top);
400
        for (int i = r + 1; i < num_ranges; ++i) {
401
          range& ir = ranges [i];
402
          ir.extents (ir.extents.left + dx, ir.extents.bottom, ir.extents.right + dx, ir.extents.top);
403
        }
404
      } else {
405
        int j = r + 1;
406
        if (j < num_ranges) {
407
          range& rr = ranges[j];
408
          box<int>& rre = rr.extents;
409
          if (newright < rre.right) {
410
            R.extents (R.extents.left, R.extents.bottom, newright, R.extents.top);
411
            rre (newright, rre.bottom, rre.right, rre.top);
412
          }
413
        } else {
414
          R.extents (R.extents.left, R.extents.bottom, newright, R.extents.top);
415
        }
416
      }
417
      if (mr) { // reset modulation
964 jag 418
        R.mod.fm.initial = R.extents.width;
419
        R.mod.fm.bv.now = 0;
420
      }
1605 jag 421
      if (R.mod.active == 0) R.print_hz_per_pixel ();
964 jag 422
    }
423
  }
424
  return valid;
425
}
426
 
427
void din::calc_all_range_notes () {
428
  int r = 0;
429
  for (int i = 0; i < num_ranges; ++i) ranges[r++].calc (scaleinfo);
430
}
431
 
432
void din::tonic_changed () {
433
  all_notes.set_tonic (scaleinfo.tonic);
434
  calc_all_range_notes ();
1402 jag 435
  refresh_all_drones ();
436
  notate_all_ranges ();
964 jag 437
}
438
 
1402 jag 439
void din::notate_all_ranges () {
2001 jag 440
 
964 jag 441
  extern int NOTATION;
442
  int western = scaleinfo.western;
443
 
1829 jag 444
  switch (NOTATION) {
445
 
446
    case WESTERN:
447
      extern const char* WESTERN_FLAT [];
448
      for (int i = 0; i < num_ranges; ++i) {
449
        range& ri = ranges [i];
450
        string i0 = ri.intervals[0], i1 = ri.intervals[1];
451
        int ii0 = NOTE_POS[i0], ii1 = NOTE_POS[i1];
452
        int kii0 = (western + ii0) % 12;
453
        int kii1 = (western + ii1) % 12;
454
        ri.notes[0].set_name (WESTERN_FLAT[kii0]);
455
        ri.notes[1].set_name (WESTERN_FLAT[kii1]);
456
      }
457
      break;
458
 
459
    case NUMERIC:
460
      for (int i = 0; i < num_ranges; ++i) {
461
        range& ri = ranges [i];
462
        ri.notes[0].set_name (ri.intervals[0]);
463
        ri.notes[1].set_name (ri.intervals[1]);
464
      }
465
      break;
466
 
467
    default:
468
      extern map<string, string> INT2IND;
469
      for (int i = 0; i < num_ranges; ++i) {
470
        range& ri = ranges [i];
471
        ri.notes[0].set_name (INT2IND[ri.intervals[0]]);
472
        ri.notes[1].set_name (INT2IND[ri.intervals[1]]);
473
      }
964 jag 474
  }
475
}
476
 
477
void din::mouse2tonic () {
478
  // set mouse at tonic
479
  range& r = ranges[scaleinfo.notes.size () - 1]; // range of middle tonic
480
  int wx = r.extents.left;
481
  if (wx >= 0 && wx <= view.xmax) {
482
    warp_mouse (wx, mousey);
483
    MENU.screen_mousex = wx;
484
    MENU.screen_mousey = mousey;
485
  }
486
}
487
 
488
float din::get_note_value (const string& s) {
489
  return scaleinfo.intervals[s];
490
}
491
 
492
void din::tuning_changed () {
493
  scaleinfo.intervals = INTERVALS;
494
  calc_all_range_notes ();
1402 jag 495
  refresh_all_drones ();
964 jag 496
}
497
 
1868 jag 498
void din::save () {
964 jag 499
  save_ranges ();
500
  save_drones ();
1168 jag 501
  wave.save ("microtonal-keyboard-waveform.crv");
2264 jag 502
  swing.save ("swing.crv");
2265 jag 503
  accent.save ("accent.crv");
964 jag 504
  scaleinfo.save_scale ();
1868 jag 505
  dinfo.save ();
964 jag 506
}
507
 
508
din::~din () {
509
  if (dvap) delete[] dvap;
510
  if (dap) delete[] dap;
1804 jag 511
  if (dcol) delete[] dcol;
1476 jag 512
  if (con_pts) delete[] con_pts;
513
  if (con_clr) delete[] con_clr;
964 jag 514
  for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) delete *i;
1503 jag 515
  for (int i = 0, j = drone_pendulums.size (); i < j; ++i) {
516
    group* grp = drone_pendulums[i];
517
    if (grp) delete grp;
518
  }
964 jag 519
  dlog << "--- destroyed microtonal-keyboard ---" << endl;
520
}
521
 
522
void din::sample_rate_changed () {
523
  for (int i = 0; i < num_ranges; ++i) ranges[i].sample_rate_changed ();
524
  beat2value* bv [] = {&fm, &am, &gatr, &octave_shift};
525
  for (int i = 0; i < 4; ++i) bv[i]->set_bpm (bv[i]->bpm);
526
  select_all_drones ();
527
  change_drone_bpm (modulator::FM, 0);
528
  change_drone_bpm (modulator::AM, 0);
529
  update_drone_tone ();
530
}
531
 
532
void din::samples_per_channel_changed () {
533
  wavplay.realloc ();
534
  for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
535
    drone& di = *(*i);
536
    di.player.realloc ();
537
    di.update_pv = drone::EMPLACE;
538
  }
539
}
540
 
541
void din::load_drones () {
542
 
543
  string fdrone = user_data_dir + scaleinfo.name + ".drone";
544
  ifstream file (fdrone.c_str(), ios::in);
545
  drones.clear ();
546
 
547
  rising = falling = 0;
548
 
549
  if (!file) return; else {
550
    string ignore;
551
    num_drones = 0;
552
    file >> ignore >> drone::UID;
1656 jag 553
    file >> ignore >> num_drones;
1814 jag 554
    print_num_drones ();
2271 jag 555
    file >> ignore >> drone::MASTERVOLUME;
964 jag 556
    dlog << "<<< loading " << num_drones << " drones from: " << fdrone;
1747 jag 557
 
558
    int T = 0;
964 jag 559
    for (int i = 0; i < num_drones; ++i) {
560
      drone* pdi = new drone;
561
      drone& di = *pdi;
562
      file >> ignore >> di.id;
1387 jag 563
      file >> ignore >> di.is;
1616 jag 564
      file >> ignore >> di.cx >> di.cy >> di.posafxvel.pt.x >> di.posafxvel.pt.y >> di.posafxvel.yes;
964 jag 565
      file >> ignore >> di.player.x >> di.vol;
566
      file >> ignore >> di.r >> di.g >> di.b;
1767 jag 567
      //file >> ignore >> di.arrow.u >> di.arrow.v;
568
      file >> ignore >> di.arrow;
1806 jag 569
      file >> ignore >> di.mod.am.result >> di.mod.am.bv.now >> di.mod.am.bv.delta >> di.mod.am.depth >> di.mod.am.bv.bpm >> di.mod.am.bv.bps >> di.mod.fm.result >> di.mod.fm.bv.now >> di.mod.fm.bv.delta >> di.mod.fm.depth >> di.mod.fm.bv.bpm >> di.mod.fm.bv.bps >> di.mod.am.id >> di.autorot.v >> di.mod.fm.id >> di.autorot.a;
1693 jag 570
      di.mod.am.calcdir (di);
571
      di.mod.fm.calcdir (di);
1747 jag 572
      file >> ignore >> di.trail.total; if (T < di.trail.total) T = di.trail.total;
573
      file >> di.handle_size;
1429 jag 574
      file >> ignore >> di.orbiting;
2076 jag 575
      file >> ignore >> di.V >> di.A >> di.vx >> di.vy >> di.vrev >> di.ax >> di.ay;
1884 jag 576
      di.modv.val = di.V;
1694 jag 577
 
964 jag 578
      file >> ignore >> di.attractor;
579
      if (di.attractor) {
580
        int n = di.attractor;
581
        for (int i = 0; i < n; ++i) {
582
          attractee ae;
583
          file >> ae.id;
584
          di.attractees.push_back (ae);
585
        }
586
        attractors.push_back (pdi);
587
      }
1878 jag 588
 
964 jag 589
      file >> ignore >> di.launcher;
590
      if (di.launcher) {
1896 jag 591
        float tt; file >> tt >> di.lpm >> di.dpl >> di.gen;
964 jag 592
        di.launch_every.triggert = tt;
1896 jag 593
        di.launch_every.startt = ui_clk ();
964 jag 594
        launchers.push_back (pdi);
1878 jag 595
      } else {
1892 jag 596
        extern void initlaunch (drone*);
597
        initlaunch (pdi);
964 jag 598
      }
599
 
600
      file >> ignore >> di.num_targets;
601
      if (di.num_targets) {
602
        file >> ignore >> di.cur_target;
603
        vector<drone*>& targets = di.targets;
604
        targets.clear ();
605
        for (int i = 0; i < di.num_targets; ++i) {
1712 jag 606
          uintptr_t pt; file >> pt;
964 jag 607
          targets.push_back ((drone*) pt);
608
        }
609
      }
610
 
611
      file >> ignore >> di.tracking;
612
      if (di.tracking) {
1712 jag 613
        uintptr_t id; file >> id;
964 jag 614
        di.tracked_drone = (drone *) id;
615
        trackers.push_back (pdi);
616
      }
617
 
618
      file >> ignore >> di.gravity;
619
      if (di.gravity) gravitated.push_back (pdi);
620
 
1712 jag 621
      uintptr_t pt; file >> ignore >> pt;
964 jag 622
      di.target = (drone *) pt;
623
      if (di.target) satellites.push_back (pdi);
624
 
1693 jag 625
      file >> ignore >> di.reincarnate;
626
      file >> ignore >> di.birth;
627
      if (di.birth != -1) {
628
        float elapsed = di.birth;
629
        di.birth = ui_clk () - elapsed;
1566 jag 630
      }
964 jag 631
 
632
      file >> ignore >> di.life;
633
      file >> ignore >> di.insert;
634
      file >> ignore >> di.snap;
1226 jag 635
      file >> ignore >> di.frozen;
636
      if (di.frozen) {
1429 jag 637
        di.frozen = 1;
1226 jag 638
        di.froze_at = ui_clk ();
1555 jag 639
        di.set_pos (di.cx + di.mod.fm.result, di.cy + di.mod.am.result);
1250 jag 640
      } else {
1555 jag 641
        di.set_pos (di.cx, di.cy);
1250 jag 642
        di.froze_at = -1;
1226 jag 643
      }
964 jag 644
 
1990 jag 645
      drones.push_back (pdi);
964 jag 646
      di.state = drone::RISING;
647
      risers.push_back (pdi);
648
      ++rising;
1990 jag 649
      di.fdr.set (0.0f, 1.0f, 1, MENU.riset());
964 jag 650
 
1387 jag 651
      float smp, spr;
652
      file >> ignore >> smp >> spr;
653
      di.nsr.set_samples (smp);
654
      di.nsr.set_spread (spr);
655
 
1472 jag 656
      file >> ignore;
1510 jag 657
      drone::proc_conn [pdi] = false;
1712 jag 658
      long long cd;
1492 jag 659
      double mag;
1472 jag 660
      while (file.eof () == 0) {
661
        file >> cd;
662
        if (cd == ENDER)
663
          break;
1476 jag 664
        else {
1472 jag 665
          di.connections.push_back ((drone *)cd);
1492 jag 666
          file >> mag; di.mags.push_back (mag);
1677 jag 667
          ++di.nconn;
1476 jag 668
          ++totcon;
669
        }
1472 jag 670
      }
671
 
1546 jag 672
      {
673
        float start, end, amount;
1574 jag 674
        file >> ignore >> start >> end >> amount;
1546 jag 675
        di.gab.set (start, end);
676
        di.gab.amount = amount;
677
      }
678
 
1694 jag 679
      {
680
        file >> ignore >> di.chuck.yes;
681
        if (di.chuck.yes) file >> di.chuck;
682
      }
683
 
1574 jag 684
    } // load complete
964 jag 685
 
1747 jag 686
    trail_t::alloc (T);
687
 
1476 jag 688
    _2totcon = 2 * totcon;
689
    alloc_conns ();
690
 
964 jag 691
    // load the meshes
692
    //
693
    map<int, drone*> dmap;
1438 jag 694
    file >> ignore >> meshh.num;
695
    if (meshh.num) {
696
      for (int m = 0; m < meshh.num; ++m) {
964 jag 697
        mesh a_mesh;
698
        file >> ignore >> a_mesh.r >> a_mesh.g >> a_mesh.b;
699
        int num_polys;
700
        file >> ignore >> num_polys;
701
        for (int i = 0; i < num_polys; ++i) {
702
          drone* drones[4] = {0}; // 4 drones to a poly
703
          file >> ignore;
704
          for (int p = 0; p < 4; ++p) {
705
            int id; file >> id;
706
            drone* did = dmap [id];
707
            if (did == 0) {
708
              did = get_drone (id);
709
              dmap[id] = did;
710
            }
711
            drones[p] = did;
712
          }
713
          a_mesh.add_poly (drones[0], drones[1], drones[2], drones[3]);
714
        }
715
        meshes.push_back (a_mesh);
716
      }
717
    }
1438 jag 718
    file >> ignore >> meshh.draw;
964 jag 719
 
720
    // load drone tracked by gravity
1906 jag 721
    gravity_t& grav = dinfo.gravity;
722
    int bid = 0, tid = 0;
723
    file >> ignore >> bid >> tid;
724
    if (bid) grav.tracked_drone[0] = get_drone (bid);
725
    if (tid) grav.tracked_drone[1] = get_drone (tid);
964 jag 726
 
1252 jag 727
    load_selected_drones (file);
728
 
1509 jag 729
    load_drone_pendulum_groups (file);
730
 
964 jag 731
    // convert attractees
732
    for (drone_iterator i = attractors.begin (), j = attractors.end(); i != j; ++i) {
733
      drone& di = *(*i);
734
      for (list<attractee>::iterator iter = di.attractees.begin (), jter = di.attractees.end (); iter != jter; ++iter) {
735
        attractee& ae = *iter;
736
        ae.d = get_drone (ae.id);
737
      }
738
    }
739
 
740
    // convert tracked drone
741
    for (drone_iterator i = trackers.begin (), j = trackers.end(); i != j; ++i) {
742
      drone& di = *(*i);
1694 jag 743
      di.tracked_drone = get_drone ((uintptr_t) di.tracked_drone);
964 jag 744
    }
745
 
1472 jag 746
    // convert targets and connections
964 jag 747
    for (drone_iterator i = drones.begin (), j = drones.end (); i != j; ++i) {
748
      drone& di = *(*i);
749
      if (di.num_targets) for (int i = 0; i < di.num_targets; ++i) di.targets[i] = get_drone ((uintptr_t) di.targets[i]);
1694 jag 750
      if (di.nconn) for (drone_iterator p = di.connections.begin (), q = di.connections.end (); p != q; ++p) *p = get_drone ((uintptr_t) *p);
751
      if (di.chuck.yes) {
752
        if (di.chuck.sun) di.chuck.sun = get_drone ((uintptr_t) di.chuck.sun);
753
        if (di.chuck.sat) di.chuck.sat = get_drone ((uintptr_t) di.chuck.sat);
754
      }
964 jag 755
    }
756
 
757
    // convert satellites
758
    for (drone_iterator i = satellites.begin (), j = satellites.end (); i != j; ++i) {
759
      drone& di = *(*i);
760
      di.target = get_drone ((uintptr_t) di.target);
761
    }
762
 
763
    update_drone_players ();
764
 
765
    dlog << ", done. >>>" << endl;
766
  }
767
 
768
}
769
 
770
void din::save_drones () {
771
  drone_wave.save ("drone.crv");
772
  string drone_file = user_data_dir + scaleinfo.name + ".drone";
773
  ofstream file (drone_file.c_str(), ios::out);
774
  if (file) {
1461 jag 775
    file << "uid " << drone::UID << endl;
776
    file << "num_drones " << num_drones << endl;
2271 jag 777
    file << "master_volume " << drone::MASTERVOLUME << endl;
964 jag 778
    for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
779
      drone& di = *(*i);
1461 jag 780
      file << "id " << di.id << endl;
781
      file << "is " << di.is << endl;
1694 jag 782
      file << "positon " << di.cx << spc << di.cy << spc << di.posafxvel.pt.x << spc << di.posafxvel.pt.y << spc << di.posafxvel.yes << endl;
783
      file << "wavepos " << di.player.x << spc << di.vol << endl;
784
      file << "color " << di.r << spc << di.g << spc << di.b << endl;
1511 jag 785
      file << "arrow " << di.arrow << endl;
1806 jag 786
      file << "modulation " << di.mod.am.result << spc << di.mod.am.bv.now << spc << di.mod.am.bv.delta << spc << di.mod.am.depth << spc << di.mod.am.bv.bpm << spc << di.mod.am.bv.bps << spc << di.mod.fm.result << spc << di.mod.fm.bv.now << spc << di.mod.fm.bv.delta << spc << di.mod.fm.depth << spc << di.mod.fm.bv.bpm << spc << di.mod.fm.bv.bps << spc << di.mod.am.id << spc << di.autorot.v << spc << di.mod.fm.id << spc << di.autorot.a << endl;
1747 jag 787
      file << "trail+handle " << di.trail.total << spc << di.handle_size << endl;
1461 jag 788
      file << "orbiting " << di.orbiting << endl;
2076 jag 789
      file << "vel+accel " << di.V << spc << di.A << spc << di.vx << spc << di.vy << spc << di.vrev << spc << di.ax << spc << di.ay << endl;
964 jag 790
      file << "attractor " << di.attractor;
791
      if (di.attractor) { // save attractees
792
        for (list<attractee>::iterator iter = di.attractees.begin (), jter = di.attractees.end (); iter != jter; ++iter) {
793
          attractee& ae = *iter;
1694 jag 794
          file << spc << ae.id; // only save unique id, rebuild on load
964 jag 795
        }
796
      }
1461 jag 797
      file << endl;
964 jag 798
 
799
      file << "launcher " << di.launcher;
800
      if (di.launcher)
1896 jag 801
        file << spc << di.launch_every.triggert <<  spc << di.lpm << spc << di.dpl << spc << di.gen << endl;
964 jag 802
      else
1461 jag 803
        file << endl;
964 jag 804
 
1461 jag 805
      file << "launcher_targets " << di.num_targets << endl;
964 jag 806
      if (di.num_targets) {
807
        file << "cur_target " << di.cur_target;
808
        for (int t = 0; t < di.num_targets; ++t) {
809
          drone* pdt = di.targets[t];
1694 jag 810
          file << spc << pdt->id;
964 jag 811
        }
1461 jag 812
        file << endl;
964 jag 813
      }
814
 
815
      file << "tracking " << di.tracking;
1694 jag 816
      if (di.tracking) file << spc << di.tracked_drone->id << endl; else file << endl;
964 jag 817
 
1461 jag 818
      file << "gravity " << di.gravity << endl;
964 jag 819
 
820
      if (di.target) {
1461 jag 821
        file << "satellite_target " << di.target->id << endl;
822
      } else file << "satellite_target 0" << endl;
964 jag 823
 
1693 jag 824
      file << "reincarnate " << di.reincarnate << endl;
825
      if (di.birth != -1)
826
        file << "birth " << (ui_clk() - di.birth) << endl;
827
      else
1566 jag 828
        file << "birth -1" << endl;
1693 jag 829
 
1694 jag 830
      file << "life-time " << di.life << endl;
831
      file << "insert-time " << di.insert << endl;
1461 jag 832
      file << "snap " << di.snap << endl;
833
      file << "frozen " << di.frozen << endl;
964 jag 834
 
1387 jag 835
      file << "noiser ";
1461 jag 836
      file << di.nsr << endl;
1387 jag 837
 
1472 jag 838
      file << "connections ";
1677 jag 839
      if (di.nconn) {
1492 jag 840
        list<double>::iterator mi = di.mags.begin ();
841
        for (drone_iterator p = di.connections.begin(), q = di.connections.end(); p != q; ++p, ++mi) {
1694 jag 842
          file << (*p)->id << spc << *mi << spc;
1492 jag 843
        }
844
      }
1472 jag 845
      file << ENDER << endl;
846
 
1694 jag 847
      file << "gab " << di.gab.start <<  spc << di.gab.end << spc << di.gab.amount << endl;
1546 jag 848
 
1694 jag 849
      file << "chuck " << di.chuck.yes << spc;
850
      if (di.chuck.yes) file << di.chuck << endl; else file << endl;
851
 
964 jag 852
    }
853
 
1461 jag 854
    file << "num_meshes " << meshh.num << endl;
1438 jag 855
    if (meshh.num) {
964 jag 856
      for (mesh_iterator m = meshes.begin (), n = meshes.end(); m != n; ++m) { // save meshes
857
        mesh& mi = *m;
1694 jag 858
        file << "color " << mi.r << spc << mi.g << spc << mi.b << endl;
1461 jag 859
        file << "num_polys " << mi.num_polys << endl;
964 jag 860
        for (poly_iterator p = mi.polys.begin (), q = mi.polys.end (); p != q; ++p) { // save polys
861
          poly& pp = *p;
862
          file << "poly";
1694 jag 863
          for (int r = 0; r < 4; ++r) file << spc << pp.drones[r]->id; // save drone id, on reload we will point to right drone
1461 jag 864
          file << endl;
964 jag 865
        }
866
      }
867
    }
1461 jag 868
    file << "draw_meshes " << meshh.draw << endl;
964 jag 869
 
1906 jag 870
    gravity_t& grav = dinfo.gravity;
871
    file << "drone_tracked_by_gravity " ;
872
    drone* basedrone = grav.tracked_drone[0]; if (basedrone) file << basedrone->id << spc; else file << "0 ";
873
    drone* tipdrone = grav.tracked_drone[1]; if (tipdrone) file << tipdrone->id << endl; else file << '0' << endl;
1252 jag 874
 
875
    save_selected_drones (file);
1509 jag 876
 
877
    save_drone_pendulum_groups (file);
964 jag 878
 
879
    dlog << "+++ saved " << num_drones << " drones in: " << drone_file << " +++" << endl;
880
  }
881
 
882
}
883
 
1509 jag 884
void din::save_drone_pendulum_groups (ofstream& file) {
885
  int ng = drone_pendulums.size ();
1694 jag 886
  file << "groups " << ng << spc;
1509 jag 887
  for (int i = 0; i < ng; ++i) {
888
    drone_pendulum_group& dpg = *drone_pendulums[i];
1694 jag 889
    file << dpg.n << spc << dpg.orient << spc << dpg.depth << spc;
1509 jag 890
    vector<drone*> dpgd = dpg.drones;
1510 jag 891
    for (int j = 0, k = dpg.n; j < k; ++j) {
1509 jag 892
      drone* dj = dpgd[j];
1694 jag 893
      file << dj->id << spc;
1509 jag 894
    }
895
  }
1814 jag 896
  file << endl;
1509 jag 897
}
898
 
899
void din::load_drone_pendulum_groups (ifstream& file) {
900
  string ignore;
901
  int ng; file >> ignore >> ng;
1574 jag 902
  if (ng) {
903
    drone_pendulums.resize (ng);
904
    for (int i = 0; i < ng; ++i) {
905
      drone_pendulum_group* pdpg = new drone_pendulum_group ();
906
      drone_pendulum_group& dpg = *pdpg;
907
      drone_pendulums[i] = pdpg;
908
      file >> dpg.n >> dpg.orient >> dpg.depth;
909
      vector<drone*>& dpgd = dpg.drones;
910
      dpgd.resize (dpg.n);
911
      int did;
912
      for (int j = 0, k = dpg.n; j < k; ++j) {
913
        file >> did;
914
        dpgd[j] = get_drone (did);
915
      }
916
    }
917
  }
1509 jag 918
}
919
 
964 jag 920
void din::update_drone_tone () {
921
  for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
922
    drone& di = *(*i);
923
    range& r = ranges[di.range];
924
    di.step = (1 - di.pos) * r.notes[0].step + di.pos * r.notes[1].step;
925
    di.update_pv = drone::EMPLACE;
926
  }
927
}
928
 
1402 jag 929
void din::refresh_all_drones () {
964 jag 930
  for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
931
    drone& di = *(*i);
1555 jag 932
    di.set_pos (di.x, di.y);
964 jag 933
  }
934
}
935
 
1402 jag 936
void din::refresh_drones (int r1, int r2) {
964 jag 937
  for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
938
    drone& di = *(*i);
1555 jag 939
    if ((di.range >= r1) && (di.range <= r2)) di.set_pos (di.x, di.y);
964 jag 940
  }
941
}
942
 
1402 jag 943
void din::refresh_drones (int r) {
964 jag 944
  for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
945
    drone& di = *(*i);
1555 jag 946
    if (di.range == r) di.set_pos (di.x, di.y);
964 jag 947
  }
948
}
949
 
950
void din::update_drone_ranges () {
951
  for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
952
    drone& di = *(*i);
953
    if (di.range > last_range) di.range = last_range;
954
  }
955
}
956
 
1574 jag 957
void din::set_drone (drone& dd, float wx, float wy) {
1461 jag 958
 
1433 jag 959
    // create drone at position
1616 jag 960
    dd.cx = dd.posafxvel.pt.x = wx;
961
    dd.cy = dd.posafxvel.pt.y = wy;
964 jag 962
 
1433 jag 963
    // install waveform, pitch and volume
2271 jag 964
    //
965
 
1433 jag 966
    dd.sol (&drone_wave);
967
    dd.player.set_wave (&dd.sol);
2308 jag 968
    if (dd.binaural) {
2271 jag 969
      dd.sol2 (&drone_wave);
970
      dd.player2.set_wave (&dd.sol2);
2267 jag 971
    }
964 jag 972
 
1433 jag 973
    // prep to rise the drones
1828 jag 974
    dd.fdr.set (0.0f, 1.0f, 1, MENU.riset());
1555 jag 975
    dd.set_pos (dd.cx, dd.cy);
1433 jag 976
    dd.state = drone::RISING;
977
    risers.push_back (&dd);
978
    ++rising;
964 jag 979
 
1510 jag 980
    drone::proc_conn [&dd] = false;
1499 jag 981
 
1554 jag 982
    dd.setcolor ();
983
 
1433 jag 984
}
964 jag 985
 
1749 jag 986
void din::movedrone (drone& dd) {
1574 jag 987
  float cx = dd.cx, cy = dd.cy;
1449 jag 988
  if (!SHIFT) cx += delta_mousex;
989
  if (!CTRL) cy -= delta_mousey;
1499 jag 990
  dd.set_center (cx, cy);
1749 jag 991
  dd.update_pv = drone::EMPLACE;
1750 jag 992
  if (dd.chuck.yes) RESETCHUCKTRAILS(dd)
1499 jag 993
  ec = &dd;
964 jag 994
}
995
 
1554 jag 996
void din::color_selected_drones () {
997
  if (num_selected_drones) {
998
    int last = num_selected_drones - 1;
999
    float _1bylast = 1.0f / last;
1000
    for (int i = 0; i < num_selected_drones; ++i) {
1001
      drone& ds = *selected_drones[i];
1002
      get_color::data.p = i * _1bylast;
1003
      ds.setcolor ();
1004
    }
1005
  } else cons << RED_PSD << eol;
1006
}
1007
 
1731 jag 1008
void din::mortalize_drones (int reincarnate) {
1677 jag 1009
  if (num_selected_drones) {
1010
    for (int i = 0; i < num_selected_drones; ++i) {
1011
      drone& ds = *selected_drones[i];
1012
      ds.birth = ui_clk ();
1731 jag 1013
      ds.reincarnate = reincarnate;
1677 jag 1014
    }
1015
  } else cons << RED_PSD << eol;
1016
}
1017
 
1018
void din::immortalize_drones () {
1019
  if (num_selected_drones) {
1020
    for (int i = 0; i < num_selected_drones; ++i) {
1970 jag 1021
      drone* pds = selected_drones[i];
1022
      pds->birth = -1;
1023
      pds->reincarnate = 0;
1024
      if (pds->gravity) {
1025
        pds->gravity = 0;
1026
        erase (gravitated, pds);
1027
        erase (satellites, pds);
1028
      }
1677 jag 1029
    }
1030
  } else cons << RED_PSD << eol;
1031
}
1032
 
1907 jag 1033
void din::delete_drone (drone& ds) {
1034
  drone* pds = &ds;
1035
  if (ds.state == drone::RISING) if (erase (risers, pds)) --rising;
1036
  if (push_back (fallers, pds)) {
1037
    ++falling;
1038
    ds.state = drone::FALLING;
1039
    ds.fdr.set (ds.fdr.alpha, 0.0f, 1, MENU.fallt());
1040
  }
964 jag 1041
}
1042
 
1907 jag 1043
void din::delete_selected_drones () {
1044
  if (num_selected_drones) {
1045
    for (int i = 0; i < num_selected_drones; ++i) {
1046
      drone& ds = *selected_drones[i];
1047
      if (ds.reincarnate) ds.reincarnate = 0;
1048
      if (ds.state == drone::FALLING)
1049
        ds.fdr.retime (MENU.fallt());
1050
      else
1051
        delete_drone (ds);
1052
    }
1053
  } else cons << RED_PSD << eol;
1686 jag 1054
}
1055
 
964 jag 1056
int din::select_all_drones () {
1057
  clear_selected_drones ();
1058
  for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
1059
    drone* pdi = *i;
1991 jag 1060
    pdi->sel = 1;
964 jag 1061
    selected_drones.push_back (pdi);
1062
  }
1063
  print_selected_drones ();
1064
  return 1;
1065
}
1066
 
1991 jag 1067
int din::delete_all_drones () {
1068
  select_all_drones ();
1069
  thaw_drones ();
1070
  delete_selected_drones ();
1071
  return 1;
1072
}
1073
 
964 jag 1074
int din::select_launchers () {
1434 jag 1075
  CLEAR_SELECTED_DRONES
964 jag 1076
  for (drone_iterator i = launchers.begin(), j = launchers.end(); i != j; ++i) {
1077
    drone* pdi = *i;
1434 jag 1078
    add_drone_to_selection (pdi);
964 jag 1079
  }
1080
  print_selected_drones ();
1081
  return 1;
1082
}
1083
 
987 jag 1084
void din::clear_selected_drones () {
964 jag 1085
  for (int i = 0; i < num_selected_drones; ++i) selected_drones[i]->sel = 0;
1086
  selected_drones.clear ();
1087
  num_selected_drones = 0;
1088
}
1089
 
1090
void din::orbit_selected_drones () { // attach selected drones to attractor
1091
  if (num_selected_drones > 1) {
1092
    int last = num_selected_drones - 1;
1093
    drone* p_att = selected_drones [last];  // last selected drone is attractor
1094
    push_back (attractors, p_att);
1095
    drone& att = *p_att;
1096
    list<attractee>& lae = att.attractees;
1097
    for (int i = 0; i < last; ++i) { // other drones are attractees
1098
      drone* pae = selected_drones [i];
1099
      if (!pae->orbiting) {
1100
        attractee ae (pae->id, pae);
1101
        if (push_back (lae, ae)) {
1102
          ++att.attractor;
1103
          pae->orbiting = 1;
1104
        }
1105
      } else {
1106
        cons << RED << "Drone orbits already, ignored!" << eol;
1107
      }
1108
    }
1507 jag 1109
  } else cons << RED_A2D << ". Drones will orbit around the last drone!" << eol;
964 jag 1110
}
1111
 
1112
void din::remove_attractee (drone* d) {
1113
  for (drone_iterator i = attractors.begin(); i != attractors.end();) { // run thru list of attractors
1114
    drone* p_att = *i;
1115
    drone& att = *p_att;
1116
    list<attractee>& lae = att.attractees;
1117
    int erased = 0;
1118
    for (list<attractee>::iterator iter = lae.begin (); iter != lae.end();) { // run thru list of attractees
1119
      attractee& ae = *iter;
1120
      if (ae.d != d)
1121
        ++iter;
1122
      else { // remove attractee
1123
        lae.erase (iter);
1124
        if (--att.attractor == 0) {
1125
          i = attractors.erase (i);
1126
          erased = 1;
1127
        }
1128
        break;
1129
      }
1130
    }
1131
    if (!erased) ++i;
1132
  }
1133
}
1134
 
1135
void din::set_drones_under_gravity () {
1731 jag 1136
  if (num_selected_drones) {
1137
    for (int i = 0; i < num_selected_drones; ++i) {
1138
      drone* pdg = selected_drones[i];
1139
      if (pdg->y < BOTTOM) pdg->gravity = -1; else pdg->gravity = 1;
1140
      push_back (gravitated, pdg);
1760 jag 1141
      pdg->birth = ui_clk ();
1731 jag 1142
    }
1143
  } else cons << RED_PSD << eol;
964 jag 1144
}
1145
 
1146
void din::move_drones_under_gravity () {
1147
 
1883 jag 1148
  float modv = 1.0f;
964 jag 1149
  for (drone_iterator i = gravitated.begin(), j = gravitated.end(); i != j; ++i) { // run thru list of drones driven by gravity
1150
 
1151
    drone* pdi = *i;
1152
    drone& di = *pdi; // get the ith drone
1153
 
1154
    if (di.frozen == 0) {
1155
 
1156
      // current position
1157
      di.xi = di.x;
1158
      di.yi = di.y;
1159
 
1160
      // calculate new position along its velocity
1883 jag 1161
      modv = di.modv ();
1162
      di.set_pos (di.x + modv * di.vx, di.y + modv * di.vy);
1163
 
964 jag 1164
      // acceleration is due to gravity!
1165
      di.ax = dinfo.gravity.gx;
1166
      di.ay = di.gravity * dinfo.gravity.gy; // reverse gravity effect if drone launched below 0 volume line
1167
 
1168
      // update velocity ie we accelerate
1169
      di.vx += di.ax;
1170
      di.vy += di.ay;
1171
 
1172
      // bounce when reached bottom line of microtonal keyboard
1855 jag 1173
      di.bounces.max = MENU.sp_bounces ();
1174
      if ((di.bounces.max != -1) && (di.target == 0) && ((di.gravity == 1 && di.y <= BOTTOM) || (di.gravity == -1 && di.y >= BOTTOM)) ) {
1175
        if (++di.bounces.n > di.bounces.max) {
1176
          delete_drone (di);
964 jag 1177
        } else {
1247 jag 1178
          float dx = di.x - di.xi;
1179
          if (dx == 0.0f) { // slope is infinite
1555 jag 1180
            di.set_pos (di.x, BOTTOM);
964 jag 1181
          } else { // slope is available
1247 jag 1182
            float dy = di.y - di.yi;
1183
            if (dy == 0.0f)
1555 jag 1184
              di.set_pos (di.x, BOTTOM);
964 jag 1185
            else {
1186
              float m = dy * 1.0f / dx;
1555 jag 1187
              di.set_pos (di.xi + (BOTTOM - di.yi) / m, BOTTOM);
964 jag 1188
            }
1189
          }
1828 jag 1190
          float reduction = MENU.sp_rebound() / 100.0;
1829 jag 1191
          int style = dinfo.bounce.style;
1192
          if (style == din_info::bouncet::RANDOM) style = get_rand_bit ();
1193
          if (style == din_info::bouncet::BACK) di.vx *= -reduction;
1984 jag 1194
          di.vy *= -reduction;
1855 jag 1195
        }
964 jag 1196
      }
1197
 
1198
      di.move_center ();
1199
 
1200
    }
1201
  }
1202
}
1203
 
1204
void din::set_targets () {
1205
 
1206
  if (num_selected_drones == 0) {
1207
    cons << RED << "Select a launcher and drones to target" << eol;
1208
    return;
1209
  }
1210
 
1847 jag 1211
  drone* d0 = selected_drones[0];
1212
  if (d0->launcher == 0) make_launcher (d0); // first drone is launcher
964 jag 1213
 
1847 jag 1214
  d0->clear_targets ();
1215
 
964 jag 1216
  if (num_selected_drones == 1) {
1847 jag 1217
    d0->targets.push_back (d0);
1218
    d0->num_targets = d0->targets.size ();
1219
    cons << GREEN << "Selected drone is a launcher and the target too!" << eol;
964 jag 1220
    return;
1221
  }
1222
 
1223
  for (int i = 1; i < num_selected_drones; ++i) { // make other drones in selection the targets
1847 jag 1224
    drone* di = selected_drones[i];
1225
    vector<drone*> targets = d0->targets;
1226
    vector<drone*>::iterator te = targets.end ();
1227
    vector<drone*>::iterator f = find (targets.begin (), targets.end (), di);
1228
    if (f == te) d0->targets.push_back (di);
964 jag 1229
  }
1847 jag 1230
  d0->num_targets = d0->targets.size ();
1231
  cons << GREEN << "First drone is launcher, it targets " << d0->num_targets << " other drones" << eol;
964 jag 1232
 
1233
}
1234
 
1235
void din::remove_drone_from_targets (drone* T) {
1236
 
1237
  for (drone_iterator i = satellites.begin(), j = satellites.end(); i != j;) { // remove satellites going towards T
1238
    drone* pdi = *i;
1239
    drone& di = *pdi;
1240
    if (di.target == T) {
1241
      di.target = 0;
1242
      i = satellites.erase (i);
1243
      j = satellites.end ();
1244
    } else ++i;
1245
  }
1246
 
1247
  for (drone_iterator i = launchers.begin(), j = launchers.end (); i != j; ++i) { // remove target from launcher
1248
    drone* pdi = *i;
1249
    vector<drone*>& targets = pdi->targets;
1250
    vector<drone*>::iterator te = targets.end (), f = find (targets.begin (), te,  T);
1251
    if (f != te) {
1252
      targets.erase (f);
1253
      pdi->num_targets = targets.size ();
1254
      clamp (0, pdi->cur_target, pdi->num_targets - 1);
1255
    }
1256
  }
1257
}
1258
 
1259
void din::clear_targets () {
1260
  int n = 0;
1261
  for (int i = 0; i < num_selected_drones; ++i) {
1262
    drone* pdi = selected_drones[i];
1263
    if (pdi->num_targets) {
1264
      pdi->clear_targets ();
1265
      ++n;
1266
    }
1267
  }
1268
  if (n) cons << GREEN << "Cleared targets of " << n << s_drones << eol; else cons << RED << "No targets found!" << eol;
1269
}
1270
 
1271
void din::kill_old_drones () {
1272
  for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
1273
    drone& di = *(*i);
1991 jag 1274
    if ((di.birth != -1) && !di.frozen && (di.state != drone::FALLING)) {
964 jag 1275
      double elapsed = ui_clk() - di.birth;
1276
      if (elapsed >= di.life) delete_drone (di);
1277
    }
1278
  }
1279
}
1280
 
1281
void din::carry_satellites_to_orbit () { // satellites is a bunch of drones to be inserted into orbit around another drone
1282
  for (drone_iterator i = satellites.begin(), j = satellites.end(); i != j;) { // run thru satellites to be inserted into circular orbit
1283
    drone* pdi = *i;
1284
    drone& di = *pdi;
1285
    if (di.frozen == 0) {
1286
      drone& dt = *di.target; // the target we want the satellite to orbit
1997 jag 1287
      unit_vector (di.ax, di.ay, dt.sx - di.x, dt.y - di.y); // centripetal acceleration ie unit vector joining satellite & target
964 jag 1288
      float pvx = -di.ay, pvy = di.ax; // velocity to insert into orbit (just perpendicular to centripetal acceleration so its centrifugal velocity)
1289
      double now = ui_clk(), delta = now - di.birth;
1290
      float alpha = delta / di.insert; // alpha is how far we are b4 we must insert satellite into orbit; 0 => at the start, 1 => orbit now!
1997 jag 1291
      int insertnow = 0;
1292
      if (alpha >= 1.0f) {
1293
        alpha = 1.0f;
1294
        insertnow = 1;
1295
      }
1998 jag 1296
 
1297
      float ivx = di.vx + alpha * (pvx - di.vx);
1298
      float ivy = di.vy + alpha * (pvy - di.vy); // interpolate current velocity and insertion velocity 
1299
      di.vx = ivx + dinfo.gravity.gx;
1300
      di.vy = ivy + di.gravity * dinfo.gravity.gy;
1997 jag 1301
      di.modv.val = di.V;
1302
      float newx = di.x + di.V * di.vx + di.A * di.ax;
1303
      float newy = di.y + di.V * di.vy + di.A * di.ay; // update drone position
1304
      di.xi = di.x;
1305
      di.yi = di.y;
1306
      di.set_pos (newx, newy);
1307
      di.move_center ();
1308
      if (insertnow) { // insert drone into orbit now!
964 jag 1309
        list<attractee>& lae = dt.attractees;
1310
        lae.push_back (attractee (pdi->id, pdi));
1311
        push_back (attractors, di.target);
1312
        di.target = 0; // inserted into orbit, so clear
1313
        ++dt.attractor;
1314
        i = satellites.erase (i); j = satellites.end (); // no longer a satellite we need to insert
1997 jag 1315
      }
1316
      ++i;
964 jag 1317
    } else ++i;
1318
  }
1319
}
1320
 
1321
void din::toggle_launchers () {
1322
  if (num_selected_drones == 0) {
1473 jag 1323
    cons << RED_PSD << eol;
964 jag 1324
    return;
1325
  }
1326
  int nl = 0, nd = 0;
1327
  for (int i = 0; i < num_selected_drones; ++i) {
1328
    drone* pdi = selected_drones[i];
1329
    drone& di = *pdi;
1330
    di.launcher = !di.launcher;
1331
    if (di.launcher) {
1877 jag 1332
      di.launch_every.start (di.launch_every.triggert); // instant launch
964 jag 1333
      launchers.push_back (pdi);
1334
      ++nl;
1335
    } else {
1336
      erase (launchers, pdi);
1337
      ++nd;
1338
    }
1339
  }
1226 jag 1340
  cons << GREEN << "Launching from " << nl << " drones, Stopped Launching from " << nd << s_drones << eol;
964 jag 1341
}
1342
 
1847 jag 1343
void din::make_launcher (drone* pl, int l8r) {
964 jag 1344
  pl->launcher = 1;
1345
  launchers.push_back (pl);
1858 jag 1346
  alarm_t& le = pl->launch_every;
1847 jag 1347
  if (l8r)
1858 jag 1348
    le.start ();
1847 jag 1349
  else
1858 jag 1350
    le.start (le.triggert);
964 jag 1351
}
1352
 
1353
void din::make_launchers () {
1354
  if (num_selected_drones == 0) {
1473 jag 1355
    cons << RED_PSD << eol;
964 jag 1356
    return;
1357
  }
1358
  int nl = 0;
1359
  for (int i = 0; i < num_selected_drones; ++i) {
1360
    drone* pdi = selected_drones[i];
1361
    if (pdi->launcher == 0) {
1362
      make_launcher (pdi);
1363
      ++nl;
1364
    }
1365
  }
1845 jag 1366
  cons << GREEN << "Made " << nl << " launchers" << eol;
964 jag 1367
}
1368
 
1369
void din::destroy_launchers () {
1370
  if (num_selected_drones == 0) {
1473 jag 1371
    cons << RED_PSD << eol;
964 jag 1372
    return;
1373
  }
1374
  int nl = 0;
1375
  for (int i = 0; i < num_selected_drones; ++i) {
1376
    drone* pdi = selected_drones[i];
1377
    drone& di = *pdi;
1378
    if (di.launcher) {
1379
      di.launcher = 0;
1380
      erase (launchers, pdi);
1381
      if (di.tracking) {
1382
        di.tracking = 0;
1383
        di.tracked_drone = 0;
1384
        erase (trackers, pdi);
1385
      }
1386
      ++nl;
1387
    }
1388
  }
1389
  if (nl) cons << GREEN << "Stopped launching from " << nl << s_drones << eol; else cons << RED << "No drone launchers found!" << eol;
1390
}
1391
 
1812 jag 1392
void din::seloncre (drone* d) {
1393
  if (dinfo.seloncre) {
1394
    d->sel = 1;
1395
    selected_drones.push_back (d);
1814 jag 1396
    print_selected_drones ();
1812 jag 1397
  }
1398
}
1399
 
1800 jag 1400
drone* din::add_drone (float wx, float wy, int fromlauncher) {
1401
 
1761 jag 1402
  drone* newdrone = new drone (wy);
1812 jag 1403
 
1404
  seloncre (newdrone);
1405
 
1761 jag 1406
  drones.push_back (newdrone);
1407
 
1408
  ++num_drones;
1814 jag 1409
  print_num_drones ();
1761 jag 1410
 
1411
  set_drone (*newdrone, wx, wy);
1828 jag 1412
  if (!fromlauncher && !drone::anchored) balloon (newdrone);
1761 jag 1413
 
1414
  return newdrone;
1415
 
1416
}
1417
 
1735 jag 1418
void din::balloon (drone* d) {
1419
  d->reincarnate = 0;
1885 jag 1420
  d->setlife (MENU.lifetime());
1735 jag 1421
  if (d->y < BOTTOM) d->gravity = -1; else d->gravity = 1;
1761 jag 1422
  gravitated.push_back (d);
1423
  d->birth = ui_clk ();
1735 jag 1424
}
1425
 
964 jag 1426
void din::launch_drones () {
1801 jag 1427
 
1851 jag 1428
  list<drone*> l2;
1429
  int n2 = 0;
1911 jag 1430
  static const int nega [] = {1, -1};
1851 jag 1431
 
1847 jag 1432
  for (drone_iterator i = launchers.begin(), j = launchers.end(); i != j; ++i) {
1801 jag 1433
 
964 jag 1434
    drone* pdi = *i;
1435
    drone& di = *pdi;
1801 jag 1436
 
1896 jag 1437
    if (!di.frozen && di.launch_every (ui_clk())) { // time to launch a drone 
1801 jag 1438
 
1892 jag 1439
      for (int p = 0, q = di.dpl; p < q; ++p) {
1885 jag 1440
 
1892 jag 1441
        #define CALLEDFROMLAUNCHER 1
1442
        drone* newdronep = add_drone (di.x, di.y, CALLEDFROMLAUNCHER);
1443
        drone& newdrone = *newdronep;
1800 jag 1444
 
1892 jag 1445
        newdrone.launched_by = pdi;
1800 jag 1446
 
1892 jag 1447
        if (newdrone.y < BOTTOM)
1448
          newdrone.gravity = -1;
1449
        else
1450
          newdrone.gravity = 1; // reverse gravity vector if launched below microtonal keyboard
1778 jag 1451
 
2287 jag 1452
 
1453
        newdrone.is = di.is;
1785 jag 1454
 
2287 jag 1455
        // copyis (newdrone, di);
1456
 
2002 jag 1457
        newdrone.setcolor (di, 0.5f);
1785 jag 1458
 
1892 jag 1459
        // init velocity/speed
1460
        if (drone::v0.mag.rndrd) newdrone.V = drone::v0.mag.rd () * di.V; else newdrone.V = di.V;
1911 jag 1461
        int dir = nega [MENU.dva.neg.state];
1900 jag 1462
        newdrone.vx = dir * di.vx;
1463
        newdrone.vy = dir * di.vy;
1892 jag 1464
        if (drone::v0.rndrot) rotate_vector (newdrone.vx, newdrone.vy, drone::v0.rotrd());
1785 jag 1465
 
1892 jag 1466
        // init acceleration
1467
        if (drone::a0.mag.rndrd) newdrone.A = drone::a0.mag.rd () * di.V; else newdrone.A = di.A;
1468
        newdrone.ax = di.ax;
1469
        newdrone.ay = di.ay;
1470
        if (drone::a0.rndrot) rotate_vector (newdrone.ax, newdrone.ay, drone::a0.rotrd());
1840 jag 1471
 
1892 jag 1472
        newdrone.handle_size = di.handle_size;
1473
        newdrone.trail.total = di.trail.total;
1564 jag 1474
 
1892 jag 1475
        newdrone.snap = di.snap;
1761 jag 1476
 
1892 jag 1477
        newdrone.arrow = di.arrow;
1761 jag 1478
 
1892 jag 1479
        int num_targets = di.num_targets;
1480
        if (num_targets) { // launch a satellite
1481
          newdrone.insert = di.insert;
1482
          int& cur_target = di.cur_target;
1483
          newdrone.target = di.targets [cur_target];
1484
          if (++cur_target >= num_targets) cur_target = 0;
1485
          satellites.push_back (newdronep);
1486
          newdrone.orbiting = 1;
1487
        } else {
1488
          gravitated.push_back (newdronep);
1489
        }
1847 jag 1490
 
1892 jag 1491
        newdrone.reincarnate = 0;
1492
        newdrone.setlife (getval<float, double> (MENU.lifetime, di.life));
1493
        newdrone.birth = ui_clk();
1494
 
1495
        newdrone.gen.n = pdi->gen.n;
1496
        if (++newdrone.gen.n < newdrone.gen.max) {
2106 jag 1497
          newdrone.lpm = getval (MENU.ddpm, di.lpm);
1892 jag 1498
          newdrone.launch_every.triggert = ppm2t (newdrone.lpm);
1499
          newdrone.dpl = getval (MENU.ddpl, di.dpl);
1500
          l2.push_back (newdronep);
1501
          ++n2;
1502
        }
2055 jag 1503
 
1504
 
1892 jag 1505
      }
1506
 
964 jag 1507
    }
1508
  }
1847 jag 1509
 
1851 jag 1510
  if (n2) for (drone_iterator i = l2.begin(), j = l2.end(); i != j; ++i) make_launcher (*i, LAUNCHLATER);
1847 jag 1511
 
964 jag 1512
}
1513
 
1514
void din::attract_drones () {
1515
  for (drone_iterator i = attractors.begin(), j = attractors.end(); i != j; ++i) {
1516
    drone* pda = *i;
1517
    drone& da = *pda;
1518
    list<attractee>& lae = da.attractees;
1519
    for (list<attractee>::iterator iter = lae.begin (), jter = lae.end(); iter != jter; ++iter) { // run thru list of attractees
1520
      attractee& ae = *iter;
1521
      drone& de = *ae.d;
2084 jag 1522
      unit_vector<float> (de.ax, de.ay, da.sx - de.x, da.y - de.y); // centripetal acceleration
2076 jag 1523
      de.vx = de.vrev * -de.ay; de.vy = de.vrev * de.ax; // centrifugal velocity is just perpendacular to centripetal acceleration
1429 jag 1524
      if (de.frozen == 0) {
2084 jag 1525
        /*// calculate position of the drones
964 jag 1526
        de.xi = de.x;
1527
        de.yi = de.y;
1528
        de.x = de.xi + de.V * de.vx + de.A * de.ax;
1529
        de.y = de.yi + de.V * de.vy + de.A * de.ay;
1429 jag 1530
        de.move_center ();
2084 jag 1531
        de.set_pos (de.x, de.y);*/
1532
        float x = de.x + de.V * de.vx + de.A * de.ax;
1533
        float y = de.y + de.V * de.vy + de.A * de.ay;
1534
        de.set_center (x, y);
1535
        de.set_pos (x, y);
1429 jag 1536
      }
964 jag 1537
    }
1538
  }
1539
}
1540
 
987 jag 1541
void din::add_drone_to_selection (drone* pd) {
1434 jag 1542
  int& sel = pd->sel;
1449 jag 1543
  if (CTRL) {
1434 jag 1544
    if (sel) {
1545
      remove_drone_from_selection (pd);
1546
      return;
1547
    }
1548
  }
1549
  if (sel) ; else {
1550
    pd->sel = 1;
1551
    selected_drones.push_back (pd);
1552
  }
964 jag 1553
}
1554
 
1435 jag 1555
int din::get_selected_drone_id (drone* d) {
1556
  for (int i = 0; i < num_selected_drones; ++i) {
1557
    if (selected_drones[i] == d) return i;
1558
  }
1559
  return -1;
1560
}
1561
 
964 jag 1562
void din::remove_drone_from_selection (drone* pd) {
1563
  pd->sel = 0;
1435 jag 1564
  if (xforming) {
1565
    int id = get_selected_drone_id (pd);
1566
    if (id != -1) {
1567
      if (xforming == SCALE)
1568
        erase_id (svec, id);
1569
      else
1570
        erase_id (rvec, id);
1571
    }
1572
  }
964 jag 1573
  if (erase (selected_drones, pd)) --num_selected_drones;
987 jag 1574
  if (erase (browsed_drones, pd)) {
1575
    --num_browsed_drones;
1576
    last_browseable_drone = num_browsed_drones - 1;
1577
  }
964 jag 1578
}
1579
 
1580
void din::update_drone_players () {
1581
  for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
1582
    drone& di = *(*i);
1583
    di.sol (&drone_wave);
1584
    di.player.set_wave (&di.sol);
2308 jag 1585
    if (di.binaural) {
2271 jag 1586
      di.sol2 (&drone_wave);
1587
      di.player2.set_wave (&di.sol2);
1588
    }
964 jag 1589
  }
1590
}
1591
 
1811 jag 1592
void make_arrow (float* A, int k, int cap, int& n, float x, float y, float ux, float uy, float vx, float vy, float u, float v, float t) {
1505 jag 1593
 
1811 jag 1594
  // make arrow
1595
  //
1596
 
1597
  float ak2, ak3, ak2t, ak3t;
1598
 
1599
  // base to neck
1600
  A[k]=x;
1601
  A[k+1]=y;
1602
  A[k+2] = ak2 = x + ux;
1603
  A[k+3] = ak3 = y + uy;
1604
  ak2t = x + t * ux;
1605
  ak3t = y + t * uy;
1606
 
1607
  float arx = x + u * ux, ary = y + u * uy;
1608
  float vvx = v * vx, vvy = v * vy;
1609
 
1610
  // flank1 to neck
1611
  float ak4, ak5;
1612
  ak4 = A[k+4] = arx + vvx;
1613
  ak5 = A[k+5] = ary + vvy;
1614
  A[k+6] = ak2t;
1615
  A[k+7] = ak3t;
1616
 
1617
  // flank2 to neck
1618
  float ak8, ak9;
1619
  ak8 = A[k+8]= arx - vvx;
1620
  ak9 = A[k+9]= ary - vvy;
1621
  A[k+10]= ak2t;
1622
  A[k+11]= ak3t;
1623
 
1624
  if (cap) {
1625
    A[k+12]=ak4;
1626
    A[k+13]=ak5;
1627
    A[k+14]=ak2;
1628
    A[k+15]=ak3;
1629
    A[k+16]=ak2;
1630
    A[k+17]=ak3;
1631
    A[k+18]=ak8;
1632
    A[k+19]=ak9;
1633
    n = 20;
1634
  } else n = 12;
1635
 
1636
}
1637
 
964 jag 1638
void din::draw_drones () {
1639
 
1640
  glEnable (GL_BLEND);
1641
  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1642
 
1463 jag 1643
  draw_connections ();
1863 jag 1644
 
1693 jag 1645
  drawchuck ();
1463 jag 1646
 
1863 jag 1647
  if (meshh.num && meshh.draw)
964 jag 1648
    for (mesh_iterator i = meshes.begin (), j = meshes.end(); i != j; ++i) (*i).draw ();
1649
 
1909 jag 1650
  // drone trails
964 jag 1651
  for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
1652
    drone& di = *(*i);
1999 jag 1653
    glColor4f (di.r, di.g, di.b, di.fdr.amount);
1909 jag 1654
    di.trail.draw ();
964 jag 1655
  }
1811 jag 1656
 
2260 jag 1657
  // hilite selected drone
1888 jag 1658
  static int dhp [12] = {0};
964 jag 1659
  glVertexPointer (2, GL_INT, 0, dhp);
2260 jag 1660
  if (num_selected_drones == 1) {
1811 jag 1661
    drone& ds = *selected_drones[0];
2260 jag 1662
    glEnable (GL_LINE_STIPPLE);
2288 jag 1663
    glLineStipple (1, 0xffff);
1811 jag 1664
    glColor3f (ds.r, ds.g, ds.b);
1911 jag 1665
    dhp[0]=ds.sx;dhp[1]=win.top;
1666
    dhp[2]=ds.sx;dhp[3]=win.bottom;
1667
    dhp[4]=win.left;dhp[5]=ds.y;
1668
    dhp[6]=win.right;dhp[7]=ds.y;
1811 jag 1669
    glDrawArrays (GL_LINES, 0, 4);
2260 jag 1670
    glDisable (GL_LINE_STIPPLE);
1811 jag 1671
  }
1672
 
2068 jag 1673
  // draw drone handles
964 jag 1674
  if (dinfo.show_pitch_volume.drones) tb_hz_vol.clear ();
1675
  for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
1676
    drone& di = *(*i);
1812 jag 1677
    if (inbox<int> (win, di.x, di.y)) {
1999 jag 1678
      const float gr = di.r, gg = di.g, gb = di.b;
1916 jag 1679
      glColor4f (gr, gg, gb, di.fdr.amount);
1812 jag 1680
      if (dinfo.show_pitch_volume.drones && di.sel) {
2308 jag 1681
        if (di.binaural) {
2276 jag 1682
          sprintf (
2288 jag 1683
                    BUFFER, " L %0.3f + %0.3f R %0.3f @ %0.3f", di.step * SAMPLE_RATE,
2276 jag 1684
                    di.sep * SAMPLE_RATE, (di.step + di.sep) * SAMPLE_RATE, di.vol * di.gab.amount);
1685
        } else {
1686
          sprintf (
2059 jag 1687
                  BUFFER,
2075 jag 1688
                  "%0.3f @ %0.3f",
1689
                  di.step * SAMPLE_RATE, di.vol * di.gab.amount
2059 jag 1690
                ); // draw pitch/volume
2276 jag 1691
        }
2055 jag 1692
        tb_hz_vol.add (
1693
          text (
1694
            BUFFER, di.handle.right, di.handle.top,
2116 jag 1695
            di.r, di.g, di.b, text::once, text::floating,
1696
            di.handle.right - win.left, di.handle.top - win.bottom
2055 jag 1697
          )
1698
        );
1500 jag 1699
      }
1700
 
1911 jag 1701
      dhp[0]=di.sx; dhp[1]=di.handle.bottom; dhp[2]=di.handle.right;dhp[3]=di.y;
1702
      dhp[4]=di.sx; dhp[5]=di.handle.top; dhp[6]=di.handle.left; dhp[7]=di.y;
964 jag 1703
 
1911 jag 1704
      int s = di.sel;
1916 jag 1705
      const float ra[2] = {gr, 0}, ga[2] = {di.g, 1}, ba[2] = {di.b, 0};
1706
      const float rs = ra[s], gs = ga[s], bs = ba[s];
1914 jag 1707
 
2035 jag 1708
      glColor4f (gr, gg, gb, di.fdr.amount);
1916 jag 1709
      glDrawArrays (GL_QUADS, 0, 4);
1914 jag 1710
 
1911 jag 1711
      glColor4f (rs, gs, bs, di.fdr.amount);
2035 jag 1712
      glDrawArrays (GL_LINE_LOOP, 0, 4);
1911 jag 1713
 
964 jag 1714
    }
1715
  }
1716
 
1717
  if (dinfo.anchor) { // draw drone anchors
2294 jag 1718
 
964 jag 1719
    if (n_dap < num_drones) {
1720
      if (dap) delete[] dap;
2304 jag 1721
      dap = new float [4 * 2 * num_drones]; // n * xy * num_drones
964 jag 1722
      n_dap = num_drones;
1723
    }
2294 jag 1724
 
1725
    if (n_dcol < num_drones) {
1726
      if (dcol) delete[] dcol;
2304 jag 1727
      dcol = new float [4 * 4 * num_drones]; // n points * rgba * num_drones
2294 jag 1728
      n_dcol = num_drones;
1729
    }
1730
 
1731
    glEnableClientState (GL_COLOR_ARRAY);
1732
    glColorPointer (4, GL_FLOAT, 0, dcol);
1247 jag 1733
    glVertexPointer (2, GL_FLOAT, 0, dap);
2294 jag 1734
 
1735
    int ai = 0, c = 0;
964 jag 1736
    for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
1737
      drone& di = *(*i);
2068 jag 1738
      if (di.range < visl || di.range > visr)
1739
        ;
1740
      else {
2294 jag 1741
 
1742
        dap[ai++] = di.sx;
1743
        dap[ai++] = win.top;
1744
        dap[ai++] = di.sx;
1745
        dap[ai++] = win.bottom;
1746
        dap[ai++] = win.left;
1747
        dap[ai++] = di.y;
1748
        dap[ai++] = win.right;
1749
        dap[ai++] = di.y;
1750
 
2304 jag 1751
        float clrs [] = {di.r, di.g, di.b, drone::anchoropacity};
2294 jag 1752
        for (int s = 0; s < 4; ++s) {
1753
          for (int t = 0; t < 4; ++t) {
1754
            dcol[c++]=clrs[t];
1755
          }
1756
        }
1757
 
964 jag 1758
      }
1759
    }
2294 jag 1760
    glEnable (GL_BLEND);
1761
    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1762
    glDrawArrays (GL_LINES, 0, ai / 2);
1763
    glDisableClientState (GL_COLOR_ARRAY);
1764
    glDisable (GL_BLEND);
964 jag 1765
  }
1766
 
1767
  // draw velocity and acceleration vectors
1768
  if (num_drones && (dinfo.vel || dinfo.accel)) {
1769
 
1804 jag 1770
    static const int v_size = 4, a_size = 8 * v_size;
1771
 
1772
    int nn_dvap = 20 * num_drones;
964 jag 1773
    if (n_dvap < nn_dvap) {
1774
      if (dvap) delete[] dvap;
1804 jag 1775
      if (dcol) delete[] dcol;
1247 jag 1776
      dvap = new float [nn_dvap];
1804 jag 1777
      dcol = new float [2 * nn_dvap];
964 jag 1778
      n_dvap = nn_dvap;
1779
    }
1780
    int v = 0, nv = 0;
1781
    if (dinfo.vel) {
1804 jag 1782
      int ci = 0;
964 jag 1783
      for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
1784
        drone& di = *(*i);
1997 jag 1785
        if (di.range < visl || di.range > visr)
1786
          ;
1787
        else {
1884 jag 1788
          float vl =  di.modv.val * v_size, vdx = vl * di.vx, vdy = vl * di.vy, pvdx = -vdy, pvdy = vdx;
1768 jag 1789
          int dv = 12;
1790
          make_arrow (dvap, v, di.arrow.cap, dv, di.sx, di.y, vdx, vdy, pvdx, pvdy, di.arrow.u, di.arrow.v, di.arrow.t);
964 jag 1791
          di.xv = di.sx + vdx; di.yv = di.y + vdy;
1768 jag 1792
          v += dv;
1804 jag 1793
 
1999 jag 1794
          //color dic (di.r * di.gab.amount, di.g * di.gab.amount, di.b * di.gab.amount);
1795
          color dic (di.r, di.g, di.b);
1804 jag 1796
          for (int s = 0, t = dv / 2; s < t; ++s) {
1797
            dcol[ci++] = dic.r;
1798
            dcol[ci++] = dic.g;
1799
            dcol[ci++] = dic.b;
1800
            dcol[ci++] = 1.0f;
1801
          }
964 jag 1802
          ++nv;
1803
        }
1804
      }
1805
      if (nv) {
1804 jag 1806
        glEnableClientState (GL_COLOR_ARRAY);
1807
        glColorPointer (4, GL_FLOAT, 0, dcol);
1247 jag 1808
        glVertexPointer (2, GL_FLOAT, 0, dvap);
1768 jag 1809
        glDrawArrays (GL_LINES, 0, v / 2);
1804 jag 1810
        glDisableClientState (GL_COLOR_ARRAY);
964 jag 1811
      }
1812
    }
1813
 
1814
    if (dinfo.accel) {
1815
      int a = 0, na = 0;
1816
      for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
1817
        drone& di = *(*i);
1888 jag 1818
        if (di.range < visl || di.range > visr) ; else {
1247 jag 1819
          float al = di.A * a_size, adx = al * di.ax, ady = al * di.ay, padx = -ady, pady = adx;
1768 jag 1820
          int da = 12;
1821
          make_arrow (dvap, a, di.arrow.cap, da, di.sx, di.y, adx, ady, padx, pady, di.arrow.u, di.arrow.v, di.arrow.t);
964 jag 1822
          di.xa = di.sx + adx; di.ya = di.y + ady;
1768 jag 1823
          a += da;
964 jag 1824
          ++na;
1825
        }
1826
      }
1827
      if (na) {
1769 jag 1828
        glColor4f (1, 0.25, 0.5, 1);
1247 jag 1829
        glVertexPointer (2, GL_FLOAT, 0, dvap);
1768 jag 1830
        glDrawArrays (GL_LINES, 0, a / 2);
964 jag 1831
      }
1832
    }
969 jag 1833
 
964 jag 1834
  }
1835
 
969 jag 1836
  if (dinfo.show_pitch_volume.drones) tb_hz_vol.draw ();
1837
 
964 jag 1838
  glDisable (GL_BLEND);
1839
 
1460 jag 1840
 
964 jag 1841
}
1842
 
1546 jag 1843
void din::setdronemastervolume (float d) {
2038 jag 1844
  if (MENU.masvol0.state && d < 0) {
1845
    d = 0;
1846
    MENU.sp_drone_master_vol.set_value (0.0f);
1847
  }
2271 jag 1848
  drone::MASTERVOLUME = d;
964 jag 1849
  for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
1850
    drone& di = *(*i);
1851
    di.update_pv = drone::EMPLACE;
1852
  }
1241 jag 1853
  sprintf (BUFFER, "Drone master volume = %0.3f", d);
1854
  cons << YELLOW << BUFFER << eol;
964 jag 1855
}
1856
 
1857
void din::update_drone_solvers (multi_curve& crv) {
1799 jag 1858
  static const char* dw = "drone-waveform";
964 jag 1859
  for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
1860
    drone& di = *(*i);
2291 jag 1861
 
964 jag 1862
    di.sol.update ();
2308 jag 1863
    if (di.binaural) di.sol2.update ();
2291 jag 1864
 
2268 jag 1865
    if (crv.num_vertices) {
1866
      di.player.set_mix (crv, dw);
2308 jag 1867
      if (di.binaural) di.player2.set_mix (crv, dw);
2268 jag 1868
    }
964 jag 1869
  }
1870
}
1871
 
1883 jag 1872
void din::update_drone_modv_solvers () {
1873
  for (drone_iterator i = gravitated.begin(), j = gravitated.end(); i != j; ++i) {
1874
    drone& di = *(*i);
1875
    di.modv.sol.update ();
1876
  }
1877
}
1878
 
964 jag 1879
string din::get_selected_drones () {
1880
  stringstream ss;
1881
  for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
1882
    drone& di = *(*i);
1694 jag 1883
    if (di.sel) ss << di.id << spc;
964 jag 1884
  }
1885
  return ss.str();
1886
}
1887
 
1888
void din::set_drone_volume (int i, float v) {
1889
  drone* pd = get_drone (i);
1890
  if (pd) {
1891
    pd->xi = pd->x; pd->yi = pd->y;
1892
    int x = pd->x, y = (int) (BOTTOM + v *  HEIGHT + 0.5f);
1555 jag 1893
    pd->set_pos (x, y);
964 jag 1894
    pd->move_center ();
1895
  }
1896
}
1897
 
1898
void din::calc_win_mouse () {
1899
 
1900
  if (MENU.show == 0) {
1901
 
1902
    delta_mousex = mousex - prev_mousex;
1903
    delta_mousey = mousey - prev_mousey;
1904
 
1238 jag 1905
    prev_mousex = mousex;
1906
    prev_mousey = mousey;
1907
 
964 jag 1908
    prev_win_mousex = win_mousex;
1909
    prev_win_mousey = win_mousey;
1910
 
1911
    win_mousex += delta_mousex;
1912
    win_mousey -= delta_mousey;
1913
 
1914
    tonex = win_mousex;
1915
    toney = win_mousey;
1916
 
1917
  }
1918
 
1919
}
1920
 
1698 jag 1921
int din::is_drone_hit (drone& di, const box<float>& rgn) {
1922
  float x [] = {di.handle.midx, di.handle.left, di.handle.right};
1923
  float y [] = {di.handle.midy, di.handle.bottom, di.handle.top};
964 jag 1924
  for (int i = 0; i < 3; ++i)
1925
    for (int j = 0; j < 3; ++j)
1698 jag 1926
      if (inbox<float> (rgn, x[i], y[j])) return 1;
964 jag 1927
  return 0;
1928
}
1929
 
1698 jag 1930
void din::calc_selector_range (const box<float>& rgn, int& left, int& right) {
1931
  float xl = rgn.left, xr = rgn.right;
964 jag 1932
  left = right = 0;
1933
  for (int i = 0; i < num_ranges; ++i) {
1934
    range& ri = ranges[i];
1935
    if (xl >= ri.extents.left) left = max (0, i - 1);
1936
    if (xr >= ri.extents.right) right = min (last_range, i + 1);
1937
  }
1938
}
1939
 
1698 jag 1940
void din::find_selected_drones (const box<float>& rgn) {
1434 jag 1941
  // select drones that lie inside selected region
1942
  // supports ctrl & shift keys
964 jag 1943
  int sell, selr; calc_selector_range (rgn, sell, selr);
1434 jag 1944
  CLEAR_SELECTED_DRONES
964 jag 1945
  for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
1946
    drone* pdi = *i;
1947
    drone& di = *pdi;
1434 jag 1948
    if ((di.state > drone::DEAD) && (di.range >= sell) && (di.range <= selr) && is_drone_hit (di, rgn))
1949
      add_drone_to_selection (pdi);
964 jag 1950
  }
1951
  print_selected_drones ();
1952
}
1953
 
1954
void din::invert_selected_drones () {
1955
  selected_drones.clear ();
1956
  for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
1957
    drone* pdi = *i;
1958
    drone& di = *pdi;
1959
    if (di.sel)
1960
      di.sel = 0;
1961
    else {
1962
      di.sel = 1;
1963
      selected_drones.push_back (pdi);
1964
    }
1965
  }
1966
  print_selected_drones ();
1967
}
1968
 
1969
void din::print_selected_drones () {
1970
  num_selected_drones = selected_drones.size ();
1971
  if (num_selected_drones) {
1972
    if (num_selected_drones != 1) {
1973
      browsed_drones = selected_drones;
1974
      num_browsed_drones = num_selected_drones;
1975
      last_browseable_drone = num_browsed_drones - 1;
1976
      browsed_drone = -1;
1452 jag 1977
      MENU.sp_browse_drone.set_listener (MENUP.brwdl);
964 jag 1978
      MENU.sp_browse_drone.set_value (browsed_drone);
1979
    } else {
1980
      MENU.sp_browse_drone.set_listener (0);
1508 jag 1981
      ec = selected_drones[0];
964 jag 1982
    }
1983
    cons << GREEN;
2033 jag 1984
    if (uis.current == this) {
1985
      MENU.next_tab = MENUP.cb_mkb_drone_params;
1986
      MENU.next_tab_instr = this;
1987
    }
1435 jag 1988
    if (xforming) resize_xform_vectors ();
964 jag 1989
  } else {
987 jag 1990
    cons << RED;
964 jag 1991
    browsed_drones.clear ();
1992
    num_browsed_drones = 0;
1993
    browsed_drone = last_browseable_drone = -1;
1508 jag 1994
    ec = 0;
964 jag 1995
  }
1996
  cons << "Selected " << num_selected_drones << s_drones << eol;
1997
}
1998
 
1999
int din::handle_input () {
2000
 
1245 jag 2001
  static const double reptf = 1./7, repts = 1./64.;
1686 jag 2002
  static const double first_repeat_time = 0.3, other_repeat_time = 0.05;
2003
  static double start_time, repeat_time = first_repeat_time;
2026 jag 2004
  static int lmb_clicked = 0, mmbclk = 0;
1302 jag 2005
 
1807 jag 2006
  // mov
1906 jag 2007
  if (keypressedd (SDLK_a, dinfo.scroll.rept, dinfo.scroll.rept)) scroll (-dinfo.scroll.dx, 0); else
2008
  if (keypressedd (SDLK_d, dinfo.scroll.rept, dinfo.scroll.rept)) scroll (+dinfo.scroll.dx, 0); else
2009
  if (keypressedd (SDLK_w, dinfo.scroll.rept, dinfo.scroll.rept)) scroll (0, +dinfo.scroll.dy); else
2010
  if (keypressedd (SDLK_s, dinfo.scroll.rept, dinfo.scroll.rept)) scroll (0, -dinfo.scroll.dy);
2011 jag 2011
 
2026 jag 2012
  if (wheel && !MENU.show && !mouse_slider0.active) { // move board view
2013
    if (SHIFT)
2014
      scroll (0, wheel * dinfo.scroll.dy);
2015
    else
2016
      scroll (-wheel * dinfo.scroll.dx, 0);
2017
  }
2011 jag 2018
 
2026 jag 2019
  if (mmb) { // drone xform center to mouse cursor
2011 jag 2020
    if (!mmbclk) {
2021
      mmbclk = 1;
2022
      dinfo.cen.x = tonex;
2023
      dinfo.cen.y = toney;
2024
    }
1871 jag 2025
  } else {
2011 jag 2026
    mmbclk = 0;
1759 jag 2027
  }
964 jag 2028
 
2029
  if (lmb) {
1496 jag 2030
 
964 jag 2031
    if (lmb_clicked == 0) {
1686 jag 2032
      lmb_clicked = 1;
2033
      if (adding) {
2034
        add_drone (win_mousex, win_mousey);
2035
        start_time = ui_clk();
2036
      }
2037
    } else {
2038
      if (adding) {
2039
        // for spraying drones
2040
        double delta_time = ui_clk() - start_time;
2041
        if (delta_time >= repeat_time) { // click repeat
2042
          lmb_clicked = 0;
2043
          repeat_time = other_repeat_time;
2044
        }
2045
      }
964 jag 2046
    }
2047
 
2048
  } else {
1686 jag 2049
    lmb_clicked = 0;
964 jag 2050
    repeat_time = first_repeat_time;
2051
  }
2052
 
2053
  if (phrasor0.state == phrasor::recording) { // record mouse pos for playback l8r
2054
    static point<int> pt;
2055
    pt.x = win_mousex; pt.y = win_mousey;
2056
    phrasor0.add (pt);
2057
    ++phrasor0.size;
2058
  }
2059
 
2292 jag 2060
  // octave shift / double beater bpm
2061
  if (keypressed (SDLK_z)) {
2328 jag 2062
    modulate_down ();
2292 jag 2063
  }
2064
  else if (keypressed (SDLK_x)) {
2328 jag 2065
    modulate_up ();
2292 jag 2066
  }
1302 jag 2067
  else if (keypressed (SDLK_e)) {
1673 jag 2068
    if (!mouse_slider0.active) {
2007 jag 2069
      if (moving_drones) set_moving_drones (0); // stop moving
2070
      else if (!MENU.show) start_moving_drones (); // start moving
1673 jag 2071
    }
964 jag 2072
  }
1704 jag 2073
 
964 jag 2074
  else if (moving_drones) {
1679 jag 2075
    if (num_selected_drones) {
2076
      if (prev_win_mousex != win_mousex || prev_win_mousey != win_mousey) {
2077
        for (int i = 0; i < num_selected_drones; ++i) {
1749 jag 2078
          drone& di = *selected_drones[i];
2079
          movedrone (di);
1679 jag 2080
        }
2081
      }    
2082
      return 1;
2083
    } else {
2084
      cons << RED_PSD << eol;
2085
    }
964 jag 2086
  }
1302 jag 2087
 
2026 jag 2088
  else if (keypressedd (SDLK_r)) {
2089
    if (xforming == ROTATE) {
2090
      mouse_slider0.deactivate ();
2091
    } else {
2092
      if (xforming) mouse_slider0.deactivate ();
2093
      MENU.brdl.clicked (MENU.b_rotate_drones);
2094
    }
2095
  }
2096
  else if (keypressedd (SDLK_t)) {
2097
    if (xforming == SCALE)
2098
      mouse_slider0.deactivate ();
2099
    else {
2100
      if (xforming) mouse_slider0.deactivate ();
2101
      MENU.bsdl.clicked (MENU.b_scale_drones);
2102
    }
2103
  }
2035 jag 2104
  else if (keypressed (SDLK_c)) delete_selected_drones ();
2105
  else if (keypressed (SDLK_y)) {
2106
    MENU.sp_dam_depth.lbl.toggle ();
2107
  } else if (keypressed (SDLK_u)) {
2108
    MENU.sp_dam_bpm.lbl.toggle ();
2109
  } else if (keypressed (SDLK_o)) {
2110
    MENU.sp_dfm_depth.lbl.toggle ();
2111
  } else if (keypressed (SDLK_p)) {
2036 jag 2112
    if (CTRL)
2113
      toggle_this (dinfo.accel, MENU.cb_show_accel);
2114
    else
2115
      MENU.sp_dfm_bpm.lbl.toggle ();
2021 jag 2116
  }
2026 jag 2117
  else if (keypressed (SDLK_SPACE)) {
2118
    if (adjustranges.active) {
2119
      adjustranges.others = !adjustranges.others;
2120
      if (adjustranges.others) cons << GREEN << "Adjust other ranges too" << eol; else cons << YELLOW << "Adjusting this range only" << eol;
2121
    }
2031 jag 2122
    else {
2123
      if (SHIFT) freeze_drones ();
2124
      else if (CTRL) thaw_drones ();
2125
      else toggle_freeze_drones();
2126
    }
2026 jag 2127
  }
2128
  else if (keypressedd (SDLK_k)) {
2129
    if (SHIFT)
2130
      snap_drones (1);
2131
    else if (CTRL)
2132
      snap_drones (0);
2133
    else
2134
      snap_drones (-1); // toggle
2135
  }
2039 jag 2136
  else if (keypressed (SDLK_SLASH)) {
2137
    MENU.sp_drone_master_vol.lbl.toggle ();
2138
  }
1302 jag 2139
  else if (keypressed (SDLK_f)) {
2021 jag 2140
    if (SHIFT) {
2141
      dinfo.sel_range = current_range;
2142
      MENU.load_range (current_range);
2143
      MENU.next_tab = MENUP.cb_mkb_ranges;
2144
      MENU.next_tab_instr = this;
2145
    } else if (CTRL) {
2146
      MENU.cnol.picked (MENU.ol_change_note.option, 0);
2147
      print_range_info (ranges[dinfo.sel_range]);
2148
    } else {
2026 jag 2149
      if (uis.cb_voice.state)
2150
        do_phrase_recording ();
2151
      else
2152
        calc_drones_centroid ();
2021 jag 2153
    }
1302 jag 2154
  }
2155
  else if (keypressed (SDLK_v)) {
2021 jag 2156
    if (SHIFT) {
2157
      MENU.rwl.clicked (MENU.b_adjust_range_both); // adjust range left and right
2158
    } else if (CTRL) {
2159
      MENU.cnb.clicked (MENU.b_change_note_both); // change both notes of range
2160
    } else { // phrase play/pause
2161
      if (phrasor0.state == phrasor::playing) {
2162
        if (MENU.show == 0) {
2163
          phrasor0.state = phrasor::paused;
2164
          find_current_range ();
2165
          cons << YELLOW << "phrasor has PAUSED." << eol;
2166
        } else cons << RED << "Close menu!" << eol;
2167
      } else {
2168
        if (phrasor0.validate ()) {
2169
          phrasor0.play ();
2170
          if (phrasor0.state == phrasor::playing) cons << GREEN << "Phrasor is PLAYING" << eol;
1673 jag 2171
        } else {
2021 jag 2172
          pos_afx_vel (-1);
1673 jag 2173
        }
2174
      }
2021 jag 2175
    }
1302 jag 2176
  }
2177
  else if (keypressed (SDLK_g)) { // phrase clear
1673 jag 2178
      if (SHIFT) {
2179
        MENU.rwl.clicked (MENU.b_adjust_range_left); // adjust range left
2180
      } else if (CTRL) {
2181
        MENU.cnl.clicked (MENU.b_change_note_left); // change range left note
2182
      } else {
2183
        clear_all_phrases ();
2184
      }
1302 jag 2185
  }
2186
  else if (keypressed (SDLK_h)) {
1449 jag 2187
    if (SHIFT) {
1302 jag 2188
      MENU.rwl.clicked (MENU.b_adjust_range_right); // adjust range right
2189
    } else
1449 jag 2190
    if (CTRL) {
1305 jag 2191
      MENU.cnr.clicked (MENU.b_change_note_right); // change range right note
2020 jag 2192
    }
2026 jag 2193
    else
2194
      toggle_launchers (); // start/stop launching drones
2195
 
1302 jag 2196
  }
964 jag 2197
  else if (keypressedd (SDLK_q)) {
1673 jag 2198
    if (!mouse_slider0.active) {
2199
      if (SHIFT) {
2200
        MENU.picked (MENU.ol_drone_is.option, 0);
1811 jag 2201
      } else {
1835 jag 2202
        if (dinfo.wand)  {
2203
          if (wanding)
2204
            stopwanding ();
2205
          else
2206
            MENU.dcl.startwanding ();
2207
        }
1811 jag 2208
        else
2209
          add_drone (win_mousex, win_mousey);
1673 jag 2210
      }
2211
    }
2026 jag 2212
  }
2213
  else if (keypressed (SDLK_l)) {
2214
    if (SHIFT)
2215
      select_launchers ();
2055 jag 2216
    else
2026 jag 2217
      select_all_drones ();
2218
  }
2219
  else if (keypressed (SDLK_i)) {
2220
    if (SHIFT) {
2221
      dinfo.show_pitch_volume.board = !dinfo.show_pitch_volume.board;
2146 jag 2222
      justset (uis.cb_show_pitch_volume_board, dinfo.show_pitch_volume.board);
2026 jag 2223
    }
2224
    else
2225
      invert_selected_drones ();
2226
  }
2227
  else if (keypressedd (SDLK_LEFT)) {
2228
    if (SHIFT) browse_range (-1); else browse_drone (-1);
2229
  } else if (keypressedd (SDLK_RIGHT)) {
2230
    if (SHIFT) browse_range (+1); else browse_drone (+1);
2231
  }
2232
  else if (keypressed (SDLK_SEMICOLON)) select_attractors ();
2233
  else if (keypressed (SDLK_QUOTE)) select_attractees ();
2035 jag 2234
  else if (keypressedd (SDLK_LEFTBRACKET, reptf, repts)) {
2032 jag 2235
    MENU.sp_change_drone_accel.lbl.toggle ();
964 jag 2236
  }
2237
  else if (keypressedd (SDLK_RIGHTBRACKET, reptf, repts)) {
2032 jag 2238
    if (CTRL)
1731 jag 2239
      toggle_this (dinfo.vel, MENU.cb_show_vel);
2240
    else
2032 jag 2241
      MENU.sp_change_drone_vel.lbl.toggle ();
964 jag 2242
  }
2035 jag 2243
  else if (keypressedd (SDLK_EQUALS)) MENU.sp_change_drone_trail_length.lbl.toggle ();
2244
  else if (keypressedd (SDLK_MINUS)) MENU.sp_change_drone_handle_size.lbl.toggle ();
2245
  else if (keypressedd (SDLK_n)) {
2246
    clear_selected_drones ();
2247
    cons << GREEN << "Cleared drone selection" << eol;
2248
  } else if (keypressed (SDLK_b)) uis.cb_gater.toggle ();
964 jag 2249
  else if (keypressed (SDLK_j)) {
1449 jag 2250
    if (SHIFT) {
964 jag 2251
      dinfo.show_pitch_volume.drones = !dinfo.show_pitch_volume.drones;
2146 jag 2252
      justset (uis.cb_show_pitch_volume_drones, dinfo.show_pitch_volume.drones);
2031 jag 2253
    } else
2254
      flip_drone_motion ();
964 jag 2255
  }
2256
 
2129 jag 2257
  else if (keypressed (SDLK_F4)) {
2146 jag 2258
    if (SHIFT) {
2259
      ++doublebpm;
2260
      Tcl_UpdateLinkedVar (interpreter.interp, "doublebpm");
2291 jag 2261
    } else {
2328 jag 2262
      powbeat (din0.gatr, BPM_MULT);
2291 jag 2263
    }
2129 jag 2264
  } else if (keypressed (SDLK_F3)) {
2146 jag 2265
    if (SHIFT) {
2266
      --doublebpm;
2267
      Tcl_UpdateLinkedVar (interpreter.interp, "doublebpm");
2268
    } else
2328 jag 2269
      powbeat (din0.gatr, 1. / BPM_MULT);
2129 jag 2270
  }
2271
 
2039 jag 2272
  else if (keypressed (SDLK_PERIOD)) set_key_to_pitch_at_cursor ();
1910 jag 2273
  else if (keypressed (SDLK_F1)) helptext();
964 jag 2274
 
2275
  return 1;
2276
 
2277
}
2278
 
1668 jag 2279
#ifdef __SVG__
2280
void din::write_trail () {
2281
  dlog << "<svg>" << endl;
2282
  for (int i = 0; i < num_selected_drones; ++i) {
2283
    drone& ds = *selected_drones[i];
2284
    ds.trail.write ();
2285
  }
2286
  dlog << "</svg>" << endl;
2287
}
2288
#endif
964 jag 2289
 
1058 jag 2290
void din::change_drone_lifetime (spinner<float>& s) {
964 jag 2291
  if (num_selected_drones) {
2292
    for (int i = 0; i < num_selected_drones; ++i) {
2293
      drone& ds = *selected_drones[i];
1885 jag 2294
      ds.setlife (ds.life + s());
964 jag 2295
      cons << GREEN << "Drone: " << i << ", lifetime = " << ds.life << " secs" << eol;
2296
    }
2297
  } else {
1473 jag 2298
    cons << RED_PSD << eol;
964 jag 2299
  }
2300
}
2301
 
1058 jag 2302
void din::change_orbit_insertion_time (spinner<float>& s) {
964 jag 2303
  if (num_selected_drones) {
2113 jag 2304
    int nl = 0;
964 jag 2305
    for (int i = 0; i < num_selected_drones; ++i) {
2306
      drone& ds = *selected_drones[i];
2307
      if (ds.launcher) {
2113 jag 2308
        ++nl;
1058 jag 2309
        ds.insert += s ();
964 jag 2310
        if (ds.insert < 0) ds.insert = 0;
2311
        cons << "Drone: " << i << ", orbit insertion time = " << ds.insert << " secs" << eol;
2312
      }
2313
    }
2113 jag 2314
 
2315
    if (!nl) cons << RED << "Please select some drone launchers!" << eol;
964 jag 2316
  } else {
1473 jag 2317
    cons << RED_PSD << eol;
964 jag 2318
  }
2319
}
2320
 
1060 jag 2321
void din::change_drone_trail_points (spinner<int>& s) {
1058 jag 2322
  if (num_selected_drones) {
2323
    for (int i = 0; i < num_selected_drones; ++i) {
2324
      drone& ds = *selected_drones[i];
1747 jag 2325
      ds.trail.change (s());
1748 jag 2326
      cons << GREEN << "Drone: " << i << ", trail points = " << ds.trail.total << eol;
1058 jag 2327
    }
1473 jag 2328
  } else cons << RED_PSD << eol;
1058 jag 2329
}
2330
 
1060 jag 2331
void din::change_drone_handle_size (spinner<int>& s) {
1058 jag 2332
  if (num_selected_drones) {
2333
    for (int i = 0; i < num_selected_drones; ++i) {
2334
      drone& ds = *selected_drones[i];
1060 jag 2335
      ds.handle_size += s();
1871 jag 2336
      if (ds.handle_size < 0) ds.handle_size = 0;
2337
      cons << GREEN << "Drone " << i << ", handle size = " << ds.handle_size << eol;
1058 jag 2338
    }
2339
    update_drone_anchors ();
1473 jag 2340
  } else cons << RED_PSD << eol;
1058 jag 2341
}
2342
 
2102 jag 2343
void din::update_drone_anchors () {
2344
  for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
2345
    drone& di = *(*i);
2346
    di.calc_handle ();
2347
  }
2348
}
1499 jag 2349
 
1766 jag 2350
void din::change_drone_arrow (spinner<float>& s, int w) {
1854 jag 2351
  static const char* str [] = {"Shoulder position = ", "Shoulder width = ", "Neck = "};
1499 jag 2352
  if (num_selected_drones) {
2353
    for (int i = 0; i < num_selected_drones; ++i) {
2354
      drone& ds = *selected_drones[i];
1766 jag 2355
      drone::arrowt& ar = ds.arrow;
2356
      float* wa [] = {&ar.u, &ar.v, &ar.t};
1854 jag 2357
      float& ww = *wa[w];
2358
      ww += s ();
2359
      cons << GREEN << str[w] << ww << eol;
1499 jag 2360
    }
2361
  } else cons << RED_PSD << eol;
2362
}
2363
 
1768 jag 2364
void din::capdronearrows (int c) {
2365
  if (num_selected_drones) {
2366
    for (int i = 0; i < num_selected_drones; ++i) {
2367
      drone& ds = *selected_drones[i];
2368
      ds.arrow.cap = c;
2369
    }
2370
  } else cons << RED_PSD << eol;
2371
}
2372
 
964 jag 2373
void din::scroll (int dx, int dy, int warp_mouse) {
2374
 
2375
  mousex -= dx;
2376
  prev_mousex -= dx;
2201 jag 2377
 
964 jag 2378
  mousey += dy;
2379
  prev_mousey += dy;
2380
 
2381
  win (win.left + dx, win.bottom + dy, win.right + dx, win.top + dy);
2382
  find_visible_ranges (dx);
2383
 
2384
  if (warp_mouse) {
2385
    if ((mousex > 0 && mousex < view.width) && (mousey > 0 && mousey < view.height)) SDL_WarpMouse (mousex, mousey);
2386
  }
2387
 
1903 jag 2388
  dinfo.gravity.ldwx[0] = dinfo.gravity.ldwy[0] = -1; // see din::evalgravity ()
1815 jag 2389
 
964 jag 2390
}
2391
 
2392
void din::find_current_range () {
2393
  // find the range where mouse is found
2394
  if (win_mousex <= ranges[0].extents.left) current_range = 0; else
2395
  if (win_mousex >= ranges[last_range].extents.right) current_range = last_range; else
2396
  for (int i = 0; i < num_ranges; ++i) {
2397
    range& curr = ranges[i];
2147 jag 2398
    box<int>& e = curr.extents;
2399
    if ( (win_mousex >= e.left) && (win_mousex <= e.right)) {
964 jag 2400
      current_range = i;
2401
      break;
2402
    }
2403
  }
2404
  find_visible_ranges ();
2405
}
2406
 
1619 jag 2407
void din::find_visible_ranges (int dir) {
2408
  // we only draw visible ranges
964 jag 2409
  if (dir > 0) {
2410
    while ((visr < last_range) && (ranges[visr].extents.right < win.right)) ++visr;
2411
    while ((visl < last_range) && (ranges[visl].extents.right < win.left)) ++visl;
2412
  } else if (dir < 0) {
2413
    while ((visl > 0) && (ranges[visl].extents.left > win.left)) --visl;
2414
    while ((visr > 0) && (ranges[visr].extents.left > win.right)) --visr;
2415
  } else {
2416
    visl = current_range;
2417
    visr = current_range;
2418
    while ( (visl > 0) && (win.left < ranges[visl].extents.left) ) --visl;
2419
    while ( (visr < last_range) && (ranges[visr].extents.right < win.right) ) ++visr;
2420
  }
2421
}
2422
 
1247 jag 2423
int din::find_range (float x, int r) {
964 jag 2424
  while (1) {
2425
    range& curr = ranges [r];
1247 jag 2426
    float deltax = x - curr.extents.left;
964 jag 2427
    if (deltax > curr.extents.width) {
2428
      if (++r < num_ranges); else {
2429
        r = last_range;
2430
        break; // drone in last range
2431
      }
2432
    }
2433
    else if (deltax < 0) {
2434
      if (--r < 0) {
2435
        r = 0; // drone in first range
2436
        break;
2437
      }
2438
    }
2439
    else
2440
      break; // drone in current range
2441
  }
2442
  return r;
2443
}
2444
 
2445
int din::find_tone_and_volume () {
2446
 
2447
  // locate current tone
2448
  range* curr = &ranges [current_range];
2449
  int deltax = tonex - curr->extents.left;
2450
  if (deltax >= curr->extents.width) { // tone in range to the right
2451
    ++current_range;
2452
    if (current_range == num_ranges) { // snap to last range
2453
      current_range = last_range;
2454
      curr = lastr;
2455
    } else {
2456
      curr = &ranges [current_range];
2457
    }
2458
  } else if (deltax < 0) { // tone in range to the left
2459
    --current_range;
2460
    if (current_range < 0) { // snap to first range
2461
      curr = firstr;
2462
      current_range = 0;
2463
    } else {
2464
      curr = &ranges [current_range];
2465
    }
2466
  }
2467
 
2468
  // located tone so find frequency
2469
  //
2470
  deltax = tonex - curr->extents.left;
1106 jag 2471
  delta = warp_pitch (deltax * curr->extents.width_1);
964 jag 2472
  step = curr->notes[0].step + delta * curr->delta_step; // step determines frequency see note.h
2473
 
2474
  // find VOLUME
2475
  static const int if_uniq = 1;
2476
  int dv = toney - BOTTOM;
1104 jag 2477
  float iv = dv * 1.0f / ranges[current_range].extents.height;
1437 jag 2478
  float fin_vol = 1.0f;
1104 jag 2479
  if (dv < 0) { // below keyboard, silence voice
1438 jag 2480
    fin_vol = 0.0f;
2481
    wavplay.set_interpolated_pitch_volume (step, fin_vol, if_uniq);
964 jag 2482
    am_vol = 0;
1106 jag 2483
    VOLUME = -warp_vol (-iv);
964 jag 2484
  } else {
1106 jag 2485
    VOLUME = warp_vol (iv);
1104 jag 2486
    float fdr_vol = uis.fdr_voice.amount * VOLUME;
1437 jag 2487
    fin_vol = fdr_vol * VOICE_VOLUME;
2488
    wavplay.set_interpolated_pitch_volume (step, fin_vol, if_uniq);
964 jag 2489
    am_vol = fdr_vol * am_depth;
2490
  }
2491
 
1439 jag 2492
  if (dinfo.voice_is_voice == 0) {
1438 jag 2493
    nsr.set_spread (fin_vol);
2494
    nsr.set_samples (1.0f / step);
2495
  }
1437 jag 2496
 
964 jag 2497
  Tcl_UpdateLinkedVar (interpreter.interp, "volume"); // VOLUME is accessible in Tcl interpreter as variable volume
2498
 
2499
  if (dinfo.show_pitch_volume.board) {
2075 jag 2500
    sprintf (BUFFER, "%0.3f @ %0.3f", (step * SAMPLE_RATE), VOLUME);
964 jag 2501
    pitch_volume_info = BUFFER;
2502
  }
2503
 
2504
  return 1;
2505
 
2506
}
2507
 
2508
void din::draw () {
1539 jag 2509
 
964 jag 2510
  glMatrixMode (GL_PROJECTION);
2511
  glLoadIdentity ();
2201 jag 2512
    glOrtho (win.left, win.right, win.bottom, win.top, -1, 1);
964 jag 2513
 
2514
  glMatrixMode (GL_MODELVIEW);
2515
 
1495 jag 2516
  if (UI_OFF == 0) {
964 jag 2517
 
1651 jag 2518
    if (dinfo.dist.vol) draw_vol_dist ();
2519
    if (dinfo.dist.pitch) draw_pitch_dist ();
1106 jag 2520
 
964 jag 2521
    // label visible ranges
2163 jag 2522
    //
1802 jag 2523
    for (int i = visl; i < visr; ++i) ranges[i].draw_labels (range::LEFT, dinfo.show_pitch_volume.board);
964 jag 2524
    ranges[visr].draw_labels (range::BOTH, dinfo.show_pitch_volume.board);
2163 jag 2525
 
2526
    // mark selected range?
2527
    if (dinfo.mark_sel_range && !(dinfo.sel_range < visl || dinfo.sel_range > visr)) {
2528
      range& cr = ranges[dinfo.sel_range];
2529
      box<int>& cre = cr.extents;
2530
      glLineWidth (1);
2531
      /*glEnable (GL_LINE_STIPPLE);
2532
      glLineStipple (1, 0x0f0f);*/
2533
      glColor3f (0.2f, 1.0f, 1.0f);
2534
      // glColor3f (1, 1, 1);
2535
      gl_pts[0]=cre.left; gl_pts[1]=cre.bottom;
2536
      gl_pts[2]=cre.right; gl_pts[3]=cre.bottom;
2537
      gl_pts[4]=cre.right; gl_pts[5]=cre.top;
2538
      gl_pts[6]=cre.left; gl_pts[7]=cre.top;
2539
      glVertexPointer (2, GL_INT, 0, gl_pts);
2540
      glDrawArrays (GL_LINE_LOOP, 0, 4);
2541
      glLineWidth (1);
2542
      //glDisable (GL_LINE_STIPPLE);*/
2543
    }
964 jag 2544
 
2005 jag 2545
    // phrasor marker
2146 jag 2546
    phrasor0.draw (win);
964 jag 2547
 
2548
    // draw cursor info
1656 jag 2549
    int cursorx = tonex + 8, cursory = toney;
1032 jag 2550
    if (dinfo.show_pitch_volume.board && !basic_editor::hide_cursor) {
2187 jag 2551
      glColor3f (0.75f, 0.75f, 0.75f);
1656 jag 2552
      draw_string (pitch_volume_info, cursorx, cursory);
2553
      if (rising || falling) {
2554
        cursory += line_height;
2555
        draw_string (num_drones_info, cursorx, cursory);
2556
      }
964 jag 2557
    }
2558
 
1651 jag 2559
    // drones xform center
2560
    dinfo.cen.draw ();
2561
 
964 jag 2562
    // draw guide for positioning drones
2161 jag 2563
    //if (dinfo.voice == 0) {
2163 jag 2564
      /*glEnable (GL_LINE_STIPPLE);
2565
      glLineStipple (1, 0xfffc);*/
2566
      glColor3f (0.3, 0.3, 0.3);
1909 jag 2567
      glVertexPointer (2, GL_INT, 0, gl_pts);
2161 jag 2568
      gl_pts[0]=win.left;gl_pts[1]=win_mousey; //toney;
2569
      gl_pts[2]=win.right;gl_pts[3]=win_mousey; //toney;
2570
      gl_pts[4]=win_mousex;gl_pts[5]=win.bottom;
2571
      gl_pts[6]=win_mousex;gl_pts[7]=win.top;
1909 jag 2572
      glDrawArrays (GL_LINES, 0, 4);
2163 jag 2573
      //glDisable (GL_LINE_STIPPLE);
2161 jag 2574
    //}
964 jag 2575
 
1651 jag 2576
    // draw selector
964 jag 2577
    mkb_selector.draw (rgn);
2578
 
2579
  }
2580
 
2005 jag 2581
  draw_drones ();
2582
  if (MENU.cb_show_gravity.state) dinfo.gravity.drawrrow ();
964 jag 2583
 
2584
}
2585
 
2586
void din::enter () {
2147 jag 2587
  ui::enter ();
1447 jag 2588
  if (phrasor0.state == phrasor::playing)
2589
    return;
2590
  else {
1238 jag 2591
    win_mousex = win.left + mousex;
2592
    win_mousey = win.bottom + mouseyy;
964 jag 2593
  }
2594
}
2595
 
1447 jag 2596
void din::window_resized (int w, int h) {
2597
  clear_all_phrases ();
2598
  win (win.left, win.bottom, win.left + w, win.bottom + h);
2599
  warp_mouse (prev_mousex, prev_mousey);
2600
  win_mousex = win.left + mousex;
2601
  win_mousey = win.bottom + mouseyy;
2602
  find_current_range ();
2603
}
2604
 
964 jag 2605
void din::change_depth (int i, float d) {
2606
 
2607
  if (i == 1) {
2608
    fm_depth += d;
2609
    hz2step (fm_depth, fm_step);
2610
    cons << YELLOW << "Voice FM depth = " << fm_depth << eol;
1601 jag 2611
    MENU.sp_fm_depth.set_value (fm_depth);
964 jag 2612
  } else {
2613
    am_depth += d;
2614
    cons << YELLOW << "Voice AM depth = " << am_depth << eol;
1601 jag 2615
    MENU.sp_am_depth.set_value (am_depth);
964 jag 2616
  }
2617
}
2618
 
2619
void din::modulate_drones () {
1806 jag 2620
 
964 jag 2621
  for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
2622
    drone& di = *(*i);
1427 jag 2623
    if (di.frozen == 0) {
1250 jag 2624
      modulator& dm = di.mod;
2625
      dm.calc ();
1806 jag 2626
      di.autorot.calc (dm.dt);
1680 jag 2627
      // AM along a direction vector, FM along a direction vector
2628
      float x = di.cx + dm.fm.result * (*dm.fm.dirx) + dm.am.result * (*dm.am.dirx);
2629
      float y = di.cy + dm.fm.result * (*dm.fm.diry) + dm.am.result * (*dm.am.diry);
1970 jag 2630
      if (di.autorot.v.yess()) rotate_vector (di.vx, di.vy, di.autorot.v.angle.theta);
2631
      if (di.autorot.a.yess()) rotate_vector (di.ax, di.ay, di.autorot.a.angle.theta);
2025 jag 2632
      if ( ! (equals (x, di.x) && equals (y, di.y) ) ) di.set_pos (x, y);
1250 jag 2633
    }
2634
  }
964 jag 2635
}
2636
 
2076 jag 2637
void din::setvelaccel (int w, int id, int neg, int perp) {
1715 jag 2638
  if (num_selected_drones) {
1764 jag 2639
    float xx[5], yy[5];
1728 jag 2640
    int negs[2] = {1, -1};
2076 jag 2641
    xx[0] = 0; yy[0] = 0;
2642
    xx[1] = 0; yy[1] = 1;
2643
    xx[2] = 1; yy[2] = 0;
1715 jag 2644
    for (int i = 0; i < num_selected_drones; ++i) {
2645
      drone& ds = *selected_drones[i];
2076 jag 2646
      xx[3]=ds.vx;
2647
      yy[3]=ds.vy;
2648
      xx[4]=ds.ax;
2649
      yy[4]=ds.ay;
1715 jag 2650
      float* wx[2] = {&ds.vx, &ds.ax};
2651
      float* wy[2] = {&ds.vy, &ds.ay};
1806 jag 2652
      float* aft [2] = {&ds.autorot.v.autoflip.total, &ds.autorot.a.autoflip.total};
2653
      alarm_t* art [2] = {&ds.autorot.v.tik, &ds.autorot.a.tik};
1728 jag 2654
      int negg = negs[neg];
2655
      float xxx = negg * xx[id];
2656
      float yyy = negg * yy[id];
2076 jag 2657
      if (perp) {
2658
        float o = xxx;
2659
        xxx = yyy;
2660
        yyy = -o;
2661
      }
1728 jag 2662
      if (w == 2) {
2663
        ds.vx = ds.ax = xxx;
2664
        ds.vy = ds.ay = yyy;
1806 jag 2665
        ds.autorot.v.autoflip.total = ds.autorot.a.autoflip.total = 0.0f;
2666
        ds.autorot.v.tik.start ();
2667
        ds.autorot.a.tik.start ();
1728 jag 2668
      } else {
2669
        *wx[w] = xxx;
2670
        *wy[w] = yyy;
1730 jag 2671
        *aft[w] = 0.0f;
1776 jag 2672
        art[w]->start ();
1728 jag 2673
      }
1715 jag 2674
    }
2675
  } else cons << RED_PSD << eol;
2676
}
2677
 
1714 jag 2678
void din::setmoddir (int w, int id) {
1680 jag 2679
  if (num_selected_drones) {
1688 jag 2680
    const char* dirs [] = {"Vertical", "Horizontal", "Velocity", "Acceleration"};
2681
    const char* whats [] = {"AM", "FM"};
1680 jag 2682
    for (int i = 0; i < num_selected_drones; ++i) {
2683
      drone& ds = *selected_drones[i];
1693 jag 2684
      mod_params* modp [] = {&ds.mod.am, &ds.mod.fm};
2685
      mod_params* modpw = modp[w];
1714 jag 2686
      modpw->id = id;
1693 jag 2687
      modpw->calcdir (ds);
1680 jag 2688
    }
1714 jag 2689
    cons << "Set " << whats[w] << " direction of " << num_selected_drones << " drones to " << dirs[id] << eol;
1680 jag 2690
  } else cons << RED_PSD << eol;
2691
}
2692
 
1771 jag 2693
void din::setautorot (int what, int state, int tog) {
2694
  if (what == menu::autorott::BOTH) {
2695
    for (int i = 0; i < num_selected_drones; ++i) {
2696
      drone& ds = *selected_drones[i];
1806 jag 2697
      int amst [] = {state, !ds.autorot.v.yes};
2698
      int fmst [] = {state, !ds.autorot.a.yes};
1970 jag 2699
      ds.autorot.v.setyes (amst[tog]);
2700
      ds.autorot.a.setyes (fmst[tog]);
1666 jag 2701
    }
1771 jag 2702
  } else {
1769 jag 2703
    for (int i = 0; i < num_selected_drones; ++i) {
2704
      drone& ds = *selected_drones[i];
1970 jag 2705
      autorotator& ar = *ds.autorot.arr[what];
2706
      int states[] = {state, !ar.yes};
2707
      ar.setyes (states[tog]);
1769 jag 2708
    }
1771 jag 2709
  }
2710
  TOGGLEMENU
1769 jag 2711
}
2712
 
1785 jag 2713
void din::setautoflip (int what, int state, int tog) {
2714
  if (num_selected_drones) {
2715
    if (what == menu::autorott::BOTH) {
2716
      for (int i = 0; i < num_selected_drones; ++i) {
2717
        drone& ds = *selected_drones[i];
1806 jag 2718
        int amst [] = {state, !ds.autorot.v.autoflip.yes};
2719
        int fmst [] = {state, !ds.autorot.a.autoflip.yes};
2720
        ds.autorot.v.autoflip.yes = amst[tog];
2721
        ds.autorot.a.autoflip.yes = fmst[tog];
2722
        ds.autorot.v.autoflip.total = 0.0f;
2723
        ds.autorot.a.autoflip.total = 0.0f;
1785 jag 2724
 
2725
      }
1806 jag 2726
    } else {
1785 jag 2727
      for (int i = 0; i < num_selected_drones; ++i) {
2728
        drone& ds = *selected_drones[i];
1806 jag 2729
        autoflipt& af = ds.autorot.arr[what]->autoflip;
1785 jag 2730
        af.total = 0.0f;
2731
        int& yes = af.yes;
2732
        int states[] = {state, !yes};
2733
        yes = states[tog];
2734
      }
2735
    }
2736
  } else
2737
    cons << RED_PSD << eol;
1982 jag 2738
  TOGGLEMENU
1785 jag 2739
}
2740
 
1974 jag 2741
void din::setautopause (int what, int state, int tog) {
2742
  if (num_selected_drones) {
2743
    if (what == menu::autorott::BOTH) {
2744
      for (int i = 0; i < num_selected_drones; ++i) {
2745
        drone& ds = *selected_drones[i];
2746
        int amst [] = {state, !ds.autorot.v.autopause.yes};
2747
        int fmst [] = {state, !ds.autorot.a.autopause.yes};
2748
        ds.autorot.v.autopause.setyes (amst[tog], ds.autorot.v);
2749
        ds.autorot.a.autopause.setyes (fmst[tog], ds.autorot.a);
2750
      }
2751
    } else {
2752
      for (int i = 0; i < num_selected_drones; ++i) {
2753
        drone& ds = *selected_drones[i];
2754
        autorotator& ar = *ds.autorot.arr[what];
2755
        autopauset& ap = ar.autopause;
2756
        int states[] = {state, !ap.yes};
2757
        ap.setyes (states[tog], ar);
2758
      }
2759
    }
2760
  } else
2761
    cons << RED_PSD << eol;
1982 jag 2762
 
2763
  TOGGLEMENU
1974 jag 2764
}
1785 jag 2765
 
1976 jag 2766
void din::setrndflipause (int what, int which, int state, int tog) {
2767
  if (num_selected_drones) {
2768
    if (what == menu::autorott::BOTH) {
2769
      for (int i = 0; i < num_selected_drones; ++i) {
2770
        drone& ds = *selected_drones[i];
2771
        int* vw [] = {&ds.autorot.v.autoflip.rndang, &ds.autorot.v.autopause.rndt[0],&ds.autorot.v.autopause.rndt[1]};
2772
        int* aw [] = {&ds.autorot.a.autoflip.rndang, &ds.autorot.a.autopause.rndt[0],&ds.autorot.a.autopause.rndt[1]};
2773
        int& dsvw = *vw[which];
2774
        int& dsaw = *aw[which];
2775
        int vst [] = {state, !dsvw};
2776
        int ast [] = {state, !dsaw};
2777
        dsvw = vst[tog];
2778
        dsaw = ast[tog];
2779
      }
2780
    } else {
2781
      for (int i = 0; i < num_selected_drones; ++i) {
2782
        drone& ds = *selected_drones[i];
2783
        autorotator& ar = *ds.autorot.arr[what];
2784
        int* w [] = {&ar.autoflip.rndang, &ar.autopause.rndt[0], &ar.autopause.rndt[1]};
2785
        int& wv = *w[which];
2786
        int states[] = {state, !wv};
2787
        wv = states[tog];
2788
      }
2789
    }
2790
  } else
2791
    cons << RED_PSD << eol;
1982 jag 2792
 
2793
  TOGGLEMENU
1976 jag 2794
}
1974 jag 2795
 
2796
 
1976 jag 2797
 
1773 jag 2798
void din::setautorotparam (int which, int what) {
2799
  if (which == menu::autorott::BOTH) {
1666 jag 2800
    for (int i = 0; i < num_selected_drones; ++i) {
2801
      drone& ds = *selected_drones[i];
1818 jag 2802
      autorotator &var = ds.autorot.v, &aar = ds.autorot.a;
1970 jag 2803
      var.setyes (1);
2804
      aar.setyes (1);
1773 jag 2805
      if (what == menu::autorott::RPM) {
1818 jag 2806
        var.mov = aar.mov = autorotator::SMOOTH;
2807
        var.set_rpm (ds.autorot.v.rpm + MENU.autorotate.rpm());
2808
        aar.set_rpm (ds.autorot.a.rpm + MENU.autorotate.rpm());
2809
        cons << "Drone : " << i << " Velocity RPM = " << var.rpm << " Acceleration RPM = " << aar.rpm << eol;
1773 jag 2810
      } else if (what == menu::autorott::DEG) {
1818 jag 2811
        var.mov = aar.mov = autorotator::TICK;
2812
        var.chgdeg (MENU.autorotate.deg());
2813
        aar.chgdeg (MENU.autorotate.deg());
1858 jag 2814
        cons << "Drone : " << i << " Velocity Degrees per Tick = " << var.deg << ", Acceleration Degrees per Tick = " << aar.deg << eol;
1774 jag 2815
      } else if (what == menu::autorott::TPS) {
1818 jag 2816
        var.mov = aar.mov = autorotator::TICK;
2817
        var.chgtps (MENU.autorotate.tps());
2818
        aar.chgtps (MENU.autorotate.tps());
1858 jag 2819
        cons << "Drone : " << i << " Velocity Ticks per Second = " << var.tps << ", Acceleration Ticks per Second = " << aar.tps << eol;
1774 jag 2820
      } else {
1818 jag 2821
        var.mov = aar.mov = MENU.autorotate.mov.id;
1807 jag 2822
        if (MENU.autorotate.mov.id == autorotator::SMOOTH) {
1818 jag 2823
          var.set_rpm (var.rpm);
2824
          aar.set_rpm (aar.rpm);
1774 jag 2825
        } else {
1818 jag 2826
          var.settps (var.tps);
2827
          var.setdeg (var.deg);
2828
          aar.settps (aar.tps);
2829
          aar.setdeg (aar.deg);
1858 jag 2830
          alarm_t& vart = var.tik;
2831
          alarm_t& aart = aar.tik;
2832
          vart.start (vart.triggert);
2833
          aart.start (aart.triggert);
1774 jag 2834
        }
1773 jag 2835
      }
1666 jag 2836
    }
2837
  } else {
1684 jag 2838
    const char* strs[2] = {" Velocity", " Acceleration"};
1666 jag 2839
    for (int i = 0; i < num_selected_drones; ++i) {
2840
      drone& ds = *selected_drones[i];
1806 jag 2841
      autorotator& ar = *ds.autorot.arr[which];
1684 jag 2842
      ar.yes = 1;
1773 jag 2843
      if (what == menu::autorott::RPM) {
1807 jag 2844
        ar.mov = autorotator::SMOOTH;
1773 jag 2845
        ar.set_rpm (ar.rpm + MENU.autorotate.rpm());
1774 jag 2846
        cons << "Drone : " << i << strs[which] << " RPM = " << ar.rpm << eol;
1773 jag 2847
      } else if (what == menu::autorott::DEG) {
1807 jag 2848
        ar.mov = autorotator::TICK;
1773 jag 2849
        ar.chgdeg (MENU.autorotate.deg());
1858 jag 2850
        cons << "Drone : " << i << strs[which] << " Degrees per Tick = " << ar.deg << spc << ", Ticks per Second = " << ar.tps << eol;
1774 jag 2851
      } else if (what == menu::autorott::TPS) {
1807 jag 2852
        ar.mov = autorotator::TICK;
1774 jag 2853
        ar.chgtps (MENU.autorotate.tps());
1858 jag 2854
        cons << "Drone : " << i << strs[which] << " Degrees per Tick = " << ar.deg << spc << ", Ticks per Second = " << ar.tps << eol;
1773 jag 2855
      } else {
1807 jag 2856
        ar.mov = MENU.autorotate.mov.id;
2857
        if (MENU.autorotate.mov.id == autorotator::SMOOTH) {
1774 jag 2858
          ar.set_rpm (ar.rpm);
2859
        } else {
1780 jag 2860
          ar.settps (ar.tps);
1858 jag 2861
          ar.tik.start ();
1774 jag 2862
          ar.setdeg (ar.deg);
2863
        }
1773 jag 2864
      }
1666 jag 2865
    }
2866
  }
2867
}
2868
 
1690 jag 2869
void din::setautorotdir (int what, int dir) {
1769 jag 2870
  if (num_selected_drones) {
2871
    if (what == menu::autorott::BOTH) {
1690 jag 2872
      for (int i = 0; i < num_selected_drones; ++i) {
2873
        drone& ds = *selected_drones[i];
1806 jag 2874
        ds.autorot.v.dir = dir;
2875
        ds.autorot.a.dir = dir;
1690 jag 2876
      }
2877
    } else {
2878
      for (int i = 0; i < num_selected_drones; ++i) {
2879
        drone& ds = *selected_drones[i];
1806 jag 2880
        ds.autorot.arr[what]->dir = dir;
1690 jag 2881
      }
2882
    }
1769 jag 2883
    TOGGLEMENU
1690 jag 2884
  } else
2885
    cons << RED_PSD << eol;
2886
}
2887
 
1974 jag 2888
void din::setautopauseparam (int what, int which) {
2889
  static const char* pl [] = {"Every", "For"};
2890
  spinner<float>* sp [] = {MENUP.autorotate.autopause.every, MENUP.autorotate.autopause.f0r};
2891
  if (what == menu::autorott::BOTH) {
2892
    for (int i = 0; i < num_selected_drones; ++i) {
2893
      drone& ds = *selected_drones[i];
2894
      autopauset &vp = ds.autorot.v.autopause, &ap = ds.autorot.a.autopause;
2895
      spinner<float>& spw = *sp[which];
2896
      double* vapp [] = {&vp.every, &vp.f0r};
2897
      double* aapp [] = {&ap.every, &ap.f0r};
2898
      double& dv = *vapp[which];
2899
      double& da = *aapp[which];
2900
      dv += spw();
1976 jag 2901
      if (dv < 0) dv = 0.0;
1974 jag 2902
      da += spw();
1976 jag 2903
      if (da < 0) da = 0.0;
1974 jag 2904
      cons << "Drone : " << i << " Velocity Auto pause " << pl[which] << spc << dv << " seconds, Acceleration Auto pause " << pl[which] \
2905
      << da << eol;
2906
    }
2907
  } else {
2908
    const char* strs[2] = {" Velocity", " Acceleration"};
2909
    spinner<float>& spw = *sp[which];
2910
    for (int i = 0; i < num_selected_drones; ++i) {
2911
      drone& ds = *selected_drones[i];
2912
      autopauset& ap = ds.autorot.arr[what]->autopause;
2913
      double* app [] = {&ap.every, &ap.f0r};
2914
      double& dp = *app[which];
2915
      dp += spw ();
1976 jag 2916
      if (dp < 0) dp = 0.0;
1974 jag 2917
      cons << "Drone : " << i << strs[what] << " Auto pause " << pl[which] << spc << dp << " seconds" << eol;
2918
    }
2919
  }
2920
}
1730 jag 2921
 
1974 jag 2922
 
2923
 
2924
 
1730 jag 2925
void din::setautoflipangle (int what) {
1731 jag 2926
  if (what == menu::autorott::BOTH) {
1730 jag 2927
    for (int i = 0; i < num_selected_drones; ++i) {
2928
      drone& ds = *selected_drones[i];
1806 jag 2929
      autoflipt &amaf = ds.autorot.v.autoflip, &fmaf = ds.autorot.a.autoflip;
1730 jag 2930
      amaf.total = fmaf.total = 0.0f;
1772 jag 2931
      amaf.set (amaf.angle.deg + MENU.autorotate.autoflip.angle());
2932
      fmaf.set (fmaf.angle.deg + MENU.autorotate.autoflip.angle());
1785 jag 2933
      cons << "Drone : " << i << " Velocity Auto flip angle = " << amaf.angle.deg << " Acceleration Auto flip angle = " << fmaf.angle.deg << eol;
1730 jag 2934
    }
2935
  } else {
2936
    const char* strs[2] = {" Velocity", " Acceleration"};
2937
    for (int i = 0; i < num_selected_drones; ++i) {
2938
      drone& ds = *selected_drones[i];
1806 jag 2939
      autoflipt& af = ds.autorot.arr[what]->autoflip;
1730 jag 2940
      af.total = 0.0f;
1772 jag 2941
      af.set (af.angle.deg + MENU.autorotate.autoflip.angle());
1785 jag 2942
      cons << "Drone : " << i << strs[what] << " Auto flip angle = " << af.angle.deg << eol;
1730 jag 2943
    }
2944
  }
2945
}
2946
 
2333 jag 2947
int din::calc_am_fm_gater () {
2948
 
2949
  int ret = 0;
2950
 
2951
  // AM
2334 jag 2952
  /*memcpy (aout.bufL, wavplay.pvol, aout.samples_channel_size);
2333 jag 2953
  multiply (aout.bufL, aout.samples_per_channel, am_depth);
2334 jag 2954
  ret += am.modulate_and_mix (aout.ams, aout.mix, aout.mixa, aout.samples_per_channel, aout.bufL);*/
2955
  ret += am.modulate_and_mix (aout.ams, aout.mix, aout.mixa, aout.samples_per_channel, am_depth);
2333 jag 2956
 
2957
  // FM
2958
  ret += fm.modulate_and_mix (aout.fms, aout.mix, aout.mixa, aout.samples_per_channel, fm_step);
2959
 
2960
  // beater
2961
  ret += gatr.gen_and_mix (aout.gatr, aout.mix, aout.mixa, aout.samples_per_channel);
2962
 
2963
  return ret;
2964
}
2965
 
964 jag 2966
int din::render_audio (float* out0, float* out1) {
2967
 
2968
  int ret = 0;
2969
 
2333 jag 2970
  find_tone_and_volume ();
2971
 
2334 jag 2972
  ret = calc_am_fm_gater (); // compute voice AM & FM & beater over bpm 
964 jag 2973
 
2974
  float *lout = out0, *rout = out1;
2975
 
1439 jag 2976
  if (dinfo.voice_is_voice) {
1437 jag 2977
    wavplay.gen_wav_fm_am_mix (lout, aout.samples_per_channel);
2978
    ret += wavplay.mixer.active;
1438 jag 2979
  } else { // voice is noise 
1437 jag 2980
    nsr (lout, rout, aout.samples_per_channel, 1.0f);
2981
    ret = 1;
2982
  }
2983
 
1558 jag 2984
  // gater on voice
964 jag 2985
  lout = out0;
2986
  rout = out1;
2987
  if (uis.fdr_gater.on) {
2988
    memcpy (aout.result, lout, aout.samples_channel_size); // voice
2989
    multiply (lout, aout.gatr, aout.samples_per_channel); // voice * gater
2990
    fill (aout.bufR, fdr_gater_prev_amount, uis.fdr_gater.amount, aout.samples_per_channel);
2991
    fdr_gater_prev_amount = uis.fdr_gater.amount;
2992
    tween (lout, aout.result, aout.samples_per_channel, aout.bufR); // voice > voice*gater
2993
  } else {
2994
    if (dinfo.gater) multiply (lout, aout.gatr, aout.samples_per_channel); // voice * gater
2995
  }
2996
  memcpy (rout, lout, aout.samples_channel_size); // copy left -> right
2997
 
2998
  // render drones
2999
  for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
3000
    drone& di = *(*i);
3001
    float* lout = out0, *rout = out1;
1658 jag 3002
    if (di.update_pv) di.update_pitch_volume ();
2266 jag 3003
    if (di.is < drone::NOISE) {
1387 jag 3004
      play& dp = di.player;
2266 jag 3005
      if (di.is == drone::DRONE) {
3006
        dp.master (lout, rout, aout.result, aout.samples_per_channel, dp.pvol);
3007
        ret += dp.mixer.active;
3008
      } else {
3009
        play& dp2 = di.player2;
3010
        dp.master (lout, aout.result, aout.samples_per_channel, dp.pvol);
2270 jag 3011
        dp2.master (rout, aout.result, aout.samples_per_channel, dp2.pvol);
3012
        ret = dp.mixer.active + dp2.mixer.active;
2266 jag 3013
      }
1387 jag 3014
    } else {
2271 jag 3015
      di.nsr (lout, rout, aout.samples_per_channel, drone::MASTERVOLUME * di.fdr.amount * di.gab.amount);
1387 jag 3016
    }
964 jag 3017
  }
3018
 
2024 jag 3019
 
3020
  /*memcpy (aout.fdr1, lout, aout.samples_channel_size);
3021
 
3022
  for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
3023
    drone& di = *(*i);
3024
    float* lout = out0, *rout = out1;
3025
    if (di.is != drone::DRONE) {
2271 jag 3026
      di.nsr (lout, rout, aout.samples_per_channel, drone::MASTERVOLUME * di.fdr.amount * di.gab.amount);
2024 jag 3027
    }
3028
  }
3029
 
3030
  memcpy (aout.fdr2, aout.fdr1, aout.samples_channel_size);*/
3031
 
3032
  /*if (alignn) {
3033
    cons << "alignned!" << eol;
3034
    for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
3035
        drone& di = *(*i);
3036
        play& dp = di.player;
3037
        dp.x = 0;
3038
    }
3039
    alignn = 0;
3040
  } */
3041
 
964 jag 3042
  return ret;
3043
 
3044
}
3045
 
2024 jag 3046
 
3047
 
964 jag 3048
void din::rise_drones () {
3049
  if (rising) {
1657 jag 3050
    for (drone_iterator i = risers.begin(), j = risers.end (); i != j;) {
964 jag 3051
      drone* pdi = *i;
3052
      drone& di = *pdi;
3053
      di.fdr.eval ();
1657 jag 3054
      if (di.fdr.reached) {
964 jag 3055
        di.state = drone::ACTIVE;
1657 jag 3056
        di.update_pv = drone::EMPLACE;
3057
        i = risers.erase (i);
3058
        j = risers.end ();
964 jag 3059
        --rising;
3060
      } else {
1657 jag 3061
        di.update_pv = drone::INTERPOLATE;
964 jag 3062
        ++i;
3063
      }
3064
    }
1677 jag 3065
  }
964 jag 3066
}
3067
 
3068
void din::fall_drones () {
3069
  if (falling) {
1657 jag 3070
    for (drone_iterator i = fallers.begin(), j = fallers.end (); i != j;) {
964 jag 3071
      drone* pdi = *i;
3072
      drone& di = *pdi;
1888 jag 3073
      if (di.frozen == 0) {
1668 jag 3074
        di.fdr.eval ();
3075
        if (di.fdr.reached) {
1677 jag 3076
 
1668 jag 3077
          i = fallers.erase (i);
3078
          j = fallers.end ();
3079
          --falling;
1657 jag 3080
 
1687 jag 3081
          if (pdi->reincarnate) {
1677 jag 3082
            di.state = drone::RISING;
3083
            risers.push_back (pdi);
3084
            ++rising;
1828 jag 3085
            di.fdr.set (0.0f, 1.0f, 1, MENU.riset());
1990 jag 3086
            di.setlife (MENU.lifetime());
1761 jag 3087
            di.birth = ui_clk ();
1677 jag 3088
          } else {
3089
            remove_attractee (pdi);
3090
            remove_tracker (pdi);
1903 jag 3091
            if (dinfo.gravity.tracked_drone[0] == pdi) dinfo.gravity.tracked_drone[0] = 0;
3092
            if (dinfo.gravity.tracked_drone[1] == pdi) dinfo.gravity.tracked_drone[1] = 0;
1677 jag 3093
            if (di.launcher) erase (launchers, pdi);
3094
            if (di.attractor) {
3095
              erase (attractors, pdi);
3096
              list<attractee>& lae = di.attractees;
3097
              for (list<attractee>::iterator iter = lae.begin (), jter = lae.end(); iter != jter; ++iter) {
3098
                attractee& ae = *iter;
3099
                drone& de = *ae.d;
3100
                de.orbiting = 0;
3101
              }
1668 jag 3102
            }
1677 jag 3103
            if (di.gravity) {
3104
              erase (gravitated, pdi);
3105
              erase (satellites, pdi);
3106
            }
3107
            remove_drone_from_targets (pdi);
3108
            remove_drone_from_selection (pdi);
3109
            remove_drone_from_pre_mesh (pdi);
3110
            remove_drone_from_mesh (pdi);
1657 jag 3111
 
1677 jag 3112
            remove_connections (pdi);
1657 jag 3113
 
1677 jag 3114
            remove_from_groups (pdi);
1657 jag 3115
 
1677 jag 3116
            if (ec == pdi) ec = 0;
1657 jag 3117
 
1677 jag 3118
            gab.erase (pdi);
1005 jag 3119
 
1677 jag 3120
            --num_drones;
1814 jag 3121
            print_num_drones ();
1656 jag 3122
 
1690 jag 3123
            if (pdi->chuck.yes) pdi->chuck.de ();
3124
 
1677 jag 3125
            erase (drones, pdi);
3126
            delete pdi;
1690 jag 3127
 
1677 jag 3128
          }
1657 jag 3129
 
1668 jag 3130
        } else {
3131
          ++i;
3132
          di.update_pv = drone::INTERPOLATE;
3133
        }
3134
      }
3135
      else
3136
        ++i;
964 jag 3137
    }
3138
  }
3139
}
3140
 
3141
 
3142
void din::height_changed (int r, int dh) {
3143
  if (r == -1) {
3144
    for (int i = 0; i < num_ranges; ++i) ranges[i].change_height (dh);
1402 jag 3145
    refresh_all_drones ();
964 jag 3146
  } else {
3147
    ranges[r].change_height (dh);
1402 jag 3148
    refresh_drones (r);
964 jag 3149
  }
3150
}
3151
 
3152
void din::toggle_this (int& what, checkbutton& cb) {
3153
  what = !what;
3154
  cb.set_state (what);
3155
}
3156
 
3157
void din::change_drone_depth (int what, float delta) {
3158
  if (num_selected_drones) {
3159
    for (int i = 0; i < num_selected_drones; ++i) {
3160
      drone& ds = *selected_drones[i];
3161
      ds.change_depth (i, what, delta);
3162
    }
1473 jag 3163
  } else cons << RED_PSD << eol;
964 jag 3164
}
3165
 
1019 jag 3166
void din::change_drone_bpm (int what, float delta) {
1015 jag 3167
  if (num_selected_drones) {
3168
    for (int i = 0; i < num_selected_drones; ++i) {
3169
      drone& ds = *selected_drones[i];
1019 jag 3170
      ds.change_bpm (i, what, delta);
1015 jag 3171
    }
1473 jag 3172
  } else cons << RED_PSD << eol;
1015 jag 3173
}
3174
 
1019 jag 3175
void din::change_drone_depth (int what, spinner<float>& s) {
964 jag 3176
  if (num_selected_drones) {
3177
    for (int i = 0; i < num_selected_drones; ++i) {
3178
      drone& ds = *selected_drones[i];
1058 jag 3179
      float dv = s ();
1019 jag 3180
      ds.change_depth (i, what, dv);
964 jag 3181
    }
1473 jag 3182
  } else cons << RED_PSD << eol;
964 jag 3183
}
3184
 
1015 jag 3185
void din::change_drone_bpm (int what, spinner<float>& s) {
1005 jag 3186
  if (num_selected_drones) {
3187
    for (int i = 0; i < num_selected_drones; ++i) {
3188
      drone& ds = *selected_drones[i];
1657 jag 3189
      float dv = s ();
1017 jag 3190
      ds.change_bpm (i, what, dv);
1005 jag 3191
    }
1473 jag 3192
  } else cons << RED_PSD << eol;
1005 jag 3193
}
3194
 
1912 jag 3195
void din::change_drone_modpos (int what, spinner<float>& s) {
3196
  if (num_selected_drones) {
3197
    for (int i = 0; i < num_selected_drones; ++i) {
3198
      drone& ds = *selected_drones[i];
2016 jag 3199
      ds.change_modpos (i, what, s());
1912 jag 3200
    }
3201
  } else cons << RED_PSD << eol;
3202
}
3203
 
1913 jag 3204
void din::set_drone_am2fm2am_bpm (int what) {
3205
  if (num_selected_drones) {
3206
    static const char* str [] = {"Set AM BPM to FM BPM for " , "Set FM BPM to AM BPM for "};
3207
    for (int i = 0; i < num_selected_drones; ++i) {
3208
      drone& ds = *selected_drones[i];
3209
      mod_params* mp [] = {&ds.mod.am, &ds.mod.fm};
3210
      int s = what, t = !what;
3211
      float sb = mp[s]->bv.bpm;
3212
      mp[t]->bv.set_bpm (sb);
3213
    }
3214
    cons << GREEN << str[what] << num_selected_drones << " drones" << eol;
3215
  } else cons << RED_PSD << eol;
3216
 
3217
  TOGGLEMENU
3218
}
3219
 
964 jag 3220
void din::toggle_adding_drones () {
1674 jag 3221
  adding = !adding;
3222
  if (adding) {
964 jag 3223
    cons << GREEN << "Click to add drones. ESC to stop" << eol;
3224
  } else {
3225
    cons << RED << "Stopped adding drones!" << eol;
1495 jag 3226
    uis.add (this, &mkb_selector);
964 jag 3227
  }
3228
}
3229
 
3230
void din::start_moving_drones () {
1984 jag 3231
  SELECTED_DRONES_EXIST
3232
  set_moving_drones (1);
964 jag 3233
}
3234
 
3235
void din::toggle_moving_drones () {
3236
  if (moving_drones == 0) {
3237
    start_moving_drones ();
3238
  } else set_moving_drones (0);
3239
}
3240
 
3241
void din::set_moving_drones (int md) {
3242
  moving_drones = md;
1679 jag 3243
  if (moving_drones)
3244
    cons << GREEN << "Just move mouse to move drones, ESC or Click to stop!" << eol;
3245
  else
1280 jag 3246
    cons << YELLOW << "@ " << name << eol;
964 jag 3247
}
3248
 
3249
int din::finish_phrase_recording () {
3250
  if (phrasor0.state == phrasor::recording) {
3251
    if (phrasor0.validate ()) {
3252
      phrasor0.play ();
3253
      cons << GREEN << "Phrasor has stopped recording and started playing!" << eol;
3254
      return 1;
3255
    }
3256
  }
3257
  return 0;
3258
}
3259
 
3260
void din::do_phrase_recording () {
3261
  if (!finish_phrase_recording()) {
2148 jag 3262
    phrasor0.rec ();
964 jag 3263
    cons << GREEN << "Phrasor is recording. Click or press f to finish!" << eol;
3264
  }
3265
}
3266
 
1238 jag 3267
void din::clear_all_phrases () {
1447 jag 3268
  if (phrasor0.size != 0) {
3269
    phrasor0.clear ();
3270
    if (MENU.show == 0) find_current_range ();
3271
    MENU.s_phrase_position.set_val (0);
1677 jag 3272
    wanding = 0;
1447 jag 3273
    cons << RED << "Phrase cleared!" << eol;
3274
  }
964 jag 3275
}
3276
 
3277
 
3278
void din::set_key_to_pitch_at_cursor () {
2161 jag 3279
  find_current_range ();
3280
  tonex = win_mousex;
3281
  toney = win_mousey;
3282
  find_tone_and_volume ();
964 jag 3283
  float hz = step * SAMPLE_RATE;
3284
  set_tonic (this, hz);
3285
}
3286
 
1058 jag 3287
void din::change_drone_accel (spinner<float>& s) {
964 jag 3288
  if (num_selected_drones) {
3289
    cons << YELLOW;
2032 jag 3290
    int lim0 = MENU.accel0.state;
964 jag 3291
    for (int i = 0; i < num_selected_drones; ++i) {
3292
      drone& di = *selected_drones[i];
1058 jag 3293
      di.A += s ();
2032 jag 3294
      if (lim0) {if (di.A < 0.0f) di.A = 0.0f;}
964 jag 3295
      cons << "Drone: " << i << ", Acceleration = " << di.A << eol;
3296
    }
1473 jag 3297
  } else cons << RED_PSD << eol;
964 jag 3298
}
3299
 
1019 jag 3300
void din::change_drone_vel (spinner<float>& s) {
3301
  if (num_selected_drones) {
3302
    cons << YELLOW;
2032 jag 3303
    int lim0 = MENU.vel0.state;
1019 jag 3304
    for (int i = 0; i < num_selected_drones; ++i) {
3305
      drone& di = *selected_drones[i];
1575 jag 3306
      di.V += s ();
1884 jag 3307
      di.modv.val = di.V;
2032 jag 3308
      if (lim0) {if (di.V < 0.0f) di.V = 0.0f;}
1019 jag 3309
      cons << "Drone: " << i << ", Velocity = " << di.V << eol;
3310
    }
1473 jag 3311
  } else cons << RED_PSD << eol;
1019 jag 3312
}
3313
 
2077 jag 3314
 
2078 jag 3315
void din::rotate_drone_vec (int which, spinner<float>& s, int dir) {
1021 jag 3316
  if (num_selected_drones) {
3317
    cons << YELLOW;
2077 jag 3318
    static const char* str [] = {"Velocity", "Acceleration"};
1021 jag 3319
    for (int i = 0; i < num_selected_drones; ++i) {
3320
      drone& di = *selected_drones[i];
2077 jag 3321
      float* px [] = {&di.vx, &di.ax};
3322
      float* py [] = {&di.vy, &di.ay};
2078 jag 3323
      float deg = dir * s(), rad = deg * PI_BY_180;
2077 jag 3324
      rotate_vector (*px[which], *py[which], rad);
3325
      cons << "Drone: " << i << ", Rotated " << str[which] << " by " << deg << " degrees." << eol;
1021 jag 3326
    }
1473 jag 3327
  } else cons << RED_PSD << eol;
1021 jag 3328
}
3329
 
2007 jag 3330
void din::calc_drones_centroid () {
3331
  if (num_selected_drones) {
3332
    starthere:
3333
    dinfo.cen.x = dinfo.cen.y = 0.0f;
3334
    for (int i = 0; i < num_selected_drones; ++i) {
3335
      drone& di = *selected_drones [i];
3336
      dinfo.cen.x += di.cx; dinfo.cen.y += di.cy;
3337
    }
3338
    dinfo.cen.x /= num_selected_drones;
3339
    dinfo.cen.y /= num_selected_drones;
3340
  } else {
3341
    select_all_drones ();
3342
    if (num_selected_drones) goto starthere; else cons << RED_PSD << eol;
3343
  }
3344
}
3345
 
1430 jag 3346
void din::calc_xform_vectors (vector<point <float> >& V, int n) {
1012 jag 3347
  V.resize (n);
964 jag 3348
  for (int i = 0; i < n; ++i) {
3349
    drone& di = *selected_drones [i];
1012 jag 3350
    point<float>& vv = V[i];
1699 jag 3351
    if (di.chuck.yes && di.chuck.sun) {
3352
      direction<float> (vv.x, vv.y, di.chuck.sun->cx, di.chuck.sun->cy, di.cx, di.cy);
3353
    } else
3354
      direction<float> (vv.x, vv.y, dinfo.cen.x, dinfo.cen.y, di.cx, di.cy);
964 jag 3355
  }
3356
}
3357
 
1623 jag 3358
void din::calc_xform_vectors () {
3359
  if (xforming == SCALE) calc_xform_vectors (svec, num_selected_drones); else
3360
  if (xforming == ROTATE) calc_xform_vectors (rvec, num_selected_drones);
3361
}
3362
 
1435 jag 3363
void din::resize_xform_vectors () {
3364
  if (xforming == SCALE) svec.resize (num_selected_drones); else rvec.resize (num_selected_drones);
3365
}
3366
 
1430 jag 3367
int din::prep_rotate_drones () {
3368
  int n = num_selected_drones;
3369
  if (n) {
3370
    calc_xform_vectors (rvec, n);
3371
    angle = 0.0f;
1435 jag 3372
    xforming = ROTATE;
1430 jag 3373
    return n;
3374
  }
3375
  return 0;
964 jag 3376
}
3377
 
2007 jag 3378
int din::prep_scale_drones () {
3379
  int n = num_selected_drones;
3380
  if (n) {
3381
    calc_xform_vectors (svec, n);
3382
    scl = 1.0f;
3383
    xforming = SCALE;
3384
    return n;
3385
  }
3386
  return 0;
3387
}
3388
 
1281 jag 3389
void din::rotate_drones () {
1670 jag 3390
  float dx, dy, cx, cy;
1430 jag 3391
  for (int i = 0; i < num_selected_drones; ++i) {
3392
    drone& di = *selected_drones[i];
3393
    point<float> rv = rvec[i];
1700 jag 3394
    rotate_vector (rv.x, rv.y, angle);
1749 jag 3395
    if (!di.chuck.yes) {
3396
      cx = dinfo.cen.x;
3397
      cy = dinfo.cen.y;
3398
      dx = cx + rv.x;
3399
      dy = cy + rv.y;
3400
      di.set_center (dx, dy);
3401
    } else cons << RED << "Wont rotate chucked drone!" << eol;
964 jag 3402
  }
3403
}
3404
 
1281 jag 3405
void din::scale_drones () {
1616 jag 3406
  list<drone*> rm;
3407
  int nrm = 0;
964 jag 3408
  for (int i = 0; i < num_selected_drones; ++i) {
1616 jag 3409
    drone* pdi = selected_drones[i];
3410
    drone& di = *pdi;
1749 jag 3411
    if (!di.chuck.yes) {
3412
      point<float> sv = svec[i];
3413
      sv *= scl;
3414
      di.set_center (dinfo.cen.x + sv.x, dinfo.cen.y + sv.y, 0);
3415
      if (di.nconn) {
3416
        rm.push_back (pdi);
3417
        for (drone_iterator p = di.connections.begin (), q = di.connections.end (); p != q; ++p) rm.push_back (*p);
3418
        nrm = nrm + di.nconn + 1;
3419
      }
3420
    } else cons << RED << "Wont scale chucked drone!" << eol;
964 jag 3421
  }
1616 jag 3422
  if (nrm) for (drone_iterator p = rm.begin (), q = rm.end (); p != q; ++p) (*p)->remagconns ();
964 jag 3423
}
3424
 
1281 jag 3425
void din::scale_drones (float ds) {
1495 jag 3426
  if (CTRL) scl.x += ds;
3427
  else if (SHIFT) scl.y += ds;
1281 jag 3428
  else scl += ds;
3429
}
3430
 
1226 jag 3431
void din::change_drones_per_min (spinner<float>& s) {
964 jag 3432
  if (num_selected_drones) {
3433
    cons << YELLOW;
1226 jag 3434
    float dpm;
964 jag 3435
    for (int i = 0; i < num_selected_drones; ++i) {
3436
      drone* pds = selected_drones[i];
3437
      drone& ds = *pds;
1892 jag 3438
      dpm = ds.lpm + s ();
1226 jag 3439
      if (dpm > 0.0f) {
1892 jag 3440
        ds.lpm = dpm;
3441
        ds.launch_every.triggert = 60.0 / ds.lpm;
1860 jag 3442
      } else {
1892 jag 3443
        ds.lpm = 0.0f;
1860 jag 3444
        ds.launch_every.triggert = MILLION;
3445
      }
1892 jag 3446
      cons << "Drone: " << i << ", launches per minute = " << ds.lpm << eol;
964 jag 3447
    }
1473 jag 3448
  } else cons << RED_PSD << eol;
964 jag 3449
}
3450
 
1893 jag 3451
 
3452
void din::change_drones_per_launch (spinner<int>& s) {
3453
  if (num_selected_drones) {
3454
    cons << YELLOW;
3455
    int dpl;
3456
    for (int i = 0; i < num_selected_drones; ++i) {
3457
      drone* pds = selected_drones[i];
3458
      drone& ds = *pds;
3459
      dpl = ds.dpl + s();
3460
      if (dpl < 0) dpl = 0;
3461
      ds.dpl = dpl;
3462
      cons << "Drone: " << i << ", drones per launch = " << ds.dpl << eol;
3463
    }
3464
  } else cons << RED_PSD << eol;
3465
}
3466
 
964 jag 3467
void din::select_attractees () { // select the attractees of the selected drones or all drones
3468
 
3469
  if (num_selected_drones == 0) {
3470
    if (num_drones) {
3471
      select_all_drones ();
3472
    } else {
3473
      cons << RED << "No drones, so no attractees" << eol;
3474
      return;
3475
    }
3476
  }
3477
 
3478
  vector<drone*> new_selected_drones;
3479
  for (int i = 0; i < num_selected_drones; ++i) {
3480
    drone& di = *selected_drones[i];
3481
    if (di.attractor) {
3482
      list<attractee>& lae = di.attractees;
3483
      for (list<attractee>::iterator iter = lae.begin (), jter = lae.end(); iter != jter; ++iter) {
3484
        attractee& ae = *iter;
3485
        new_selected_drones.push_back (ae.d);
3486
      }
3487
    }
3488
  }
3489
 
3490
  int ns = new_selected_drones.size ();
3491
  if (ns) {
1434 jag 3492
    CLEAR_SELECTED_DRONES
964 jag 3493
    for (int i = 0; i < ns; ++i) {
3494
      drone* pd = new_selected_drones[i];
3495
      add_drone_to_selection (pd);
3496
    }
3497
    print_selected_drones ();
3498
  } else {
3499
    cons << RED << "Sorry, no attractees found!" << eol;
3500
  }
3501
 
3502
}
3503
 
3504
void din::select_attractors () { // select the attractors of selected drones
3505
  if (num_selected_drones) {
3506
    vector<drone*> selv (selected_drones);
3507
    int q = num_selected_drones;
1434 jag 3508
    CLEAR_SELECTED_DRONES
964 jag 3509
    for (drone_iterator i = attractors.begin(), j = attractors.end(); i != j; ++i) {
3510
      drone* pdi = *i;
3511
      drone& di = *pdi;
3512
      list<attractee>& lae = di.attractees;
3513
      for (list<attractee>::iterator iter = lae.begin (), jter = lae.end(); iter != jter; ++iter) {
3514
        attractee& ae = *iter;
3515
        for (int p = 0; p < q; ++p) {
3516
          drone* sd = selv [p];
3517
          if (sd == ae.d) {
3518
            add_drone_to_selection (pdi);
3519
            goto next_attractor;
3520
          }
3521
        }
3522
      }
3523
      next_attractor:
3524
        ;
3525
    }
3526
  } else {
3527
    for (drone_iterator i = attractors.begin(), j = attractors.end(); i != j; ++i) {
3528
      drone* pdi = *i;
1434 jag 3529
      pdi->sel = 1;
3530
      selected_drones.push_back (pdi);
964 jag 3531
    }
3532
  }
3533
  print_selected_drones ();
3534
}
3535
 
3536
void din::trail_drones () {
3537
  for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
3538
    drone& di = *(*i);
3539
    di.trail.add (di.sx, di.y);
3540
  }
3541
}
3542
 
1098 jag 3543
void din::toggle_create_this () {
3544
  if (dinfo.create_this) {
3545
    toggle_create_drone_pendulum ();
3546
  } else {
3547
    toggle_create_mesh ();
3548
  }
3549
}
3550
 
3551
void din::toggle_create_drone_pendulum () {
3552
  if (create_drone_pend) ;   
3553
  else {
3554
    cons << GREEN << "Click and drag a box to make a drone pendulum, ESC to cancel" << eol;
3555
    create_drone_pend = 1;
3556
  }
3557
}
3558
 
964 jag 3559
void din::toggle_create_mesh () {
1007 jag 3560
 
3561
  if (amd.active) {
3562
    cons << RED << "Already making a mesh, please wait for it to finish :)" << eol;
3563
    return;
3564
  }
3565
 
1438 jag 3566
  if (meshh.create) {
1005 jag 3567
    create_drone_mesh ();
1438 jag 3568
    meshh.create = 0;
1098 jag 3569
  } else {
1005 jag 3570
    cons << GREEN << "Click and drag a box to preview drone mesh, ESC to cancel" << eol;
1438 jag 3571
    meshh.create = 1;
1005 jag 3572
  }
1007 jag 3573
 
964 jag 3574
}
3575
 
3576
void din::stop_creating_mesh () {
1438 jag 3577
  meshh.create = 0;
1100 jag 3578
  mkb_selector.mesh = 0;
3579
  cons << RED << "Stopped creating mesh" << eol;
964 jag 3580
}
3581
 
1100 jag 3582
void din::stop_creating_drone_pendulum () {
3583
  create_drone_pend = 0;
3584
  cons << RED << "Stopped making drone pendulum" << eol;
3585
}
3586
 
1037 jag 3587
void din::bg () {
964 jag 3588
 
1693 jag 3589
  drone::proc_conn.clear ();
3590
  if (ec && !xforming) ec = ec->eval_conns ();
1499 jag 3591
 
1005 jag 3592
  if (phrasor0.state == phrasor::playing) {
3593
    phrasor0.get (tonex, toney);
2206 jag 3594
    if (uis.iscur (this) && MENU.track_phrase_position.state) {
3595
      const int margin = 10;
2201 jag 3596
      int dx = 0;
3597
      if (tonex < win.left)
2206 jag 3598
        dx = tonex - win.left - margin;
2201 jag 3599
      else if (tonex > win.right)
2206 jag 3600
        dx = tonex - win.right + margin;
2201 jag 3601
      scroll (dx, 0, 0);
2200 jag 3602
    }
1005 jag 3603
    phrasor0.next ();
3604
  }
964 jag 3605
 
1674 jag 3606
  if (wanding) {
3607
    if ((wand.x != tonex) || (wand.y != toney)) {
3608
      if (magnitude2 (wand.x, wand.y, tonex, toney) >= drone::wand.dist2) {
3609
        wand.x = tonex;
3610
        wand.y = toney;
1890 jag 3611
        if (SHIFT || CTRL)
1753 jag 3612
          ;
3613
        else
3614
          add_drone (wand.x, wand.y);
1656 jag 3615
      }
3616
    }
3617
  }
3618
 
1005 jag 3619
  if (amd.active && !amd.drop && amd (ui_clk())) {
1438 jag 3620
    create_drone:
1319 jag 3621
    if (amd.i < mkb_selector.rowcol) {
3622
        amd.p = mkb_selector.order [amd.i];
3623
        int p = 2 * amd.p;
3624
        int x = mkb_selector.meshp [p];
3625
        int y = mkb_selector.meshp [p + 1];
3626
        drone* d = add_drone (x, y);
3627
        mkb_selector.meshd[amd.p] = d;
1320 jag 3628
        if (dinfo.mesh_vars.apply_to.active) {
1576 jag 3629
          float a = ((amd.i % dinfo.mesh_vars.dpp) + 1) * 1. / dinfo.mesh_vars.dpp;
1477 jag 3630
          float bpm = a * dinfo.drone_pend.bpm;
1320 jag 3631
          d->mod.active = 1;
1764 jag 3632
          if (dinfo.mesh_vars.apply_to.am) d->mod.am.bv.set_bpm (bpm);
3633
          if (dinfo.mesh_vars.apply_to.fm) d->mod.fm.bv.set_bpm (bpm);
1320 jag 3634
        }
1814 jag 3635
        if (!dinfo.seloncre) {
3636
          d->sel = 1;
3637
          selected_drones.push_back (d);
1935 jag 3638
          print_selected_drones ();
1814 jag 3639
        }
1319 jag 3640
        amd.i++;
1438 jag 3641
        if (amd.triggert == 0.0) goto create_drone;
1005 jag 3642
    } else {
3643
      // assign drones to polygons of the mesh
3644
      mesh a_mesh;
1558 jag 3645
      a_mesh.r = rndr ();
3646
      a_mesh.g = rndg ();
3647
      a_mesh.b = rndb ();
1009 jag 3648
      for (int i = 0, j = mkb_selector.rows - 1; i < j; ++i) {
3649
        int ic = i * mkb_selector.cols;
3650
        for (int k = 0, l = mkb_selector.cols - 1; k < l; ++k) {
3651
          int d0i = ic + k, d1i = d0i + 1;
3652
          int d2i = d0i + mkb_selector.cols, d3i = d2i + 1;
1656 jag 3653
          drone* d0 = mkb_selector.get_mesh_drone(d0i), *d1 = mkb_selector.get_mesh_drone(d1i);
3654
          drone* d2 = mkb_selector.get_mesh_drone(d2i), *d3 = mkb_selector.get_mesh_drone(d3i);
1009 jag 3655
          a_mesh.add_poly (d0, d1, d3, d2); // each poly has 4 drones
1005 jag 3656
        }
3657
      }
1310 jag 3658
 
1005 jag 3659
      meshes.push_back (a_mesh);
1438 jag 3660
      ++meshh.num;
1814 jag 3661
      if (!dinfo.seloncre) print_selected_drones ();
1935 jag 3662
      cons << GREEN << "Created a " << dinfo.rows << " x " << dinfo.cols << " mesh with " << mkb_selector.rowcol << " drones" << eol;
1005 jag 3663
      amd.reset ();
1049 jag 3664
      mkb_selector.clear ();
1005 jag 3665
    }
3666
  } else {
3667
    if (amd.drop) {
3668
      cons << RED << "Aborted drone mesh" << eol;
3669
      amd.reset ();
3670
    }
3671
  }
964 jag 3672
 
1658 jag 3673
  fall_drones ();
3674
  rise_drones ();
3675
  if (quit == DONT) launch_drones ();
3676
  carry_satellites_to_orbit ();
3677
  attract_drones ();
1673 jag 3678
  track_drones ();
1690 jag 3679
  evalchuck ();
1658 jag 3680
  modulate_drones ();
1863 jag 3681
  evalgravity ();
1658 jag 3682
  move_drones_under_gravity ();
3683
  trail_drones ();
3684
  kill_old_drones ();
3685
  modulate_ranges ();
3686
  gab.eval ();
3687
 
1005 jag 3688
}
964 jag 3689
 
1693 jag 3690
void din::drawchuck () {
1748 jag 3691
  if (MENU.choutline.state) {
3692
    for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
3693
      drone& di = *(*i);
3694
      drone* sat = di.chuck.sat;
3695
      if (di.chuck.yes && sat) {
3696
        glBegin (GL_LINES);
3697
          glColor3f (di.r, di.g, di.b);
3698
          glVertex2f (di.sx, di.y);
3699
          glColor3f (sat->r, sat->g, sat->b);
3700
          glVertex2f (sat->sx, sat->y);
3701
        glEnd ();
3702
      }
1693 jag 3703
    }
3704
  }
3705
}
1670 jag 3706
 
1690 jag 3707
void din::evalchuck () {
1701 jag 3708
 
1695 jag 3709
  for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
3710
    drone& di = *(*i);
1702 jag 3711
    if (di.chuck.yes) {
3712
      di.chuck.cx = di.cx;
3713
      di.chuck.cy = di.cy;
3714
    }
1701 jag 3715
  }
3716
 
1916 jag 3717
  for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
1701 jag 3718
    drone& di = *(*i);
1707 jag 3719
    if (di.chuck.yes && di.chuck.sun) {
3720
      if (di.frozen) {
3721
        di.chuck.len = unit_vector (di.chuck.ux, di.chuck.uy, di.chuck.sun->chuck.cx, di.chuck.sun->chuck.cy, di.cx, di.cy);
3722
      } else {
1746 jag 3723
        rotate_vector (di.chuck.ux, di.chuck.uy, di.chuck.dir * di.chuck.speed * drone::chuckt::apt.rad);
1707 jag 3724
        di.set_center (di.chuck.sun->chuck.cx + di.chuck.len * di.chuck.ux, di.chuck.sun->chuck.cy + di.chuck.len * di.chuck.uy);
3725
      }
1670 jag 3726
    }
3727
  }
1707 jag 3728
 
1670 jag 3729
}
3730
 
1691 jag 3731
void din::changechuckspeed (spinner<float>& sp) {
1671 jag 3732
  if (num_selected_drones) {
1691 jag 3733
    for (int i = 0; i < num_selected_drones; ++i) {
3734
      drone& di = *selected_drones[i];
1745 jag 3735
      if (di.chuck.yes) {
3736
        float& speed = di.chuck.speed;
3737
        speed += sp ();
3738
        if (speed < 0.0f) speed = 0.0f;
3739
        cons << YELLOW << "Drone " << i << ", speed = " << speed << eol;
1749 jag 3740
        RESETCHUCKTRAILS(di)
1745 jag 3741
      }
1691 jag 3742
    }
1671 jag 3743
  } else {
3744
    cons << RED_PSD << eol;
3745
  }
3746
}
3747
 
1691 jag 3748
void din::changechucklength (spinner<float>& sp) {
1671 jag 3749
  if (num_selected_drones) {
1691 jag 3750
    for (int i = 0; i < num_selected_drones; ++i) {
3751
      drone& di = *selected_drones[i];
1745 jag 3752
      if (di.chuck.yes) {
3753
        float& len = di.chuck.len;
3754
        len += sp ();
3755
        if (len < 0.0f) len = 0.0f;
1749 jag 3756
        RESETCHUCKTRAILS(di)
1745 jag 3757
        cons << YELLOW << "Drone " << i << ", length = " << len << eol;
3758
      }
1691 jag 3759
    }
1671 jag 3760
  } else {
3761
    cons << RED_PSD << eol;
3762
  }
3763
}
3764
 
1672 jag 3765
void din::flipchuckspeed () {
3766
  if (num_selected_drones) {
3767
    for (int i = 0; i < num_selected_drones; ++i) {
1745 jag 3768
      drone& di = *selected_drones[i];
3769
      if (di.chuck.yes) di.chuck.dir = -di.chuck.dir;
1749 jag 3770
      RESETCHUCKTRAILS(di)
1672 jag 3771
    }
3772
  } else {
3773
    cons << RED_PSD << eol;
3774
  }
3775
}
1671 jag 3776
 
1697 jag 3777
void din::togchuckspeed () {
3778
  if (num_selected_drones) {
3779
    for (int i = 0; i < num_selected_drones; ++i) {
1745 jag 3780
      drone& di = *selected_drones[i];
3781
      if (di.chuck.yes) swap (di.chuck.speed, di.chuck.speed0);
1749 jag 3782
      RESETCHUCKTRAILS(di)
1697 jag 3783
    }
3784
  } else {
3785
    cons << RED_PSD << eol;
3786
  }
3787
}
3788
 
1745 jag 3789
void din::resetchucktrails (drone& d) {
3790
  d.trail.reset ();
3791
  if (d.chuck.sat) resetchucktrails (*d.chuck.sat);
3792
}
3793
 
1746 jag 3794
void din::resetallchucktrails () {
3795
  for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
3796
    drone& di = *(*i);
3797
    if (di.chuck.yes) di.trail.reset ();
3798
  }
3799
}
3800
 
1503 jag 3801
void din::update_drone_pendulum (drone_pendulum_group& g) {
1510 jag 3802
  float a = 0.0f, da = 1.0 / (g.n - 1);
1764 jag 3803
  for (int i = 0, j = g.n; i < j; ++i) {
1503 jag 3804
    drone* pd = g.drones[i];
3805
    drone& d = *pd;
3806
    mod_params* mods [] = {&d.mod.am, &d.mod.fm};
3807
    mod_params& mod = *mods[g.orient];
2107 jag 3808
    mod.depth = warp_depth (a) * uis.dpeu.depth.value;
3809
    mod.bv.set_bpm (warp_bpm (a)* uis.dpeu.bpm.value);
1503 jag 3810
    a += da;
3811
  }
3812
}
3813
 
3814
void din::update_drone_pendulums () {
3815
  map<group*, bool> updated;
3816
  for (int i = 0, j = drone_pendulums.size (); i < j; ++i) {
3817
    drone_pendulum_group* g = drone_pendulums[i];
3818
    drone_pendulum_group& gr = *g;
3819
    for (int m = 0, n = num_selected_drones; m < n; ++m) {
3820
      drone* ds = selected_drones[m];
3821
      if ((updated[g] == false) && gr.member (ds)) {
3822
        updated[g] = true;
3823
        update_drone_pendulum (gr);
3824
      }
3825
    }
3826
  }
3827
}
3828
 
1517 jag 3829
void din::remove_from_groups (drone* d) {
3830
  for (vector<drone_pendulum_group*>::iterator i = drone_pendulums.begin (), j = drone_pendulums.end (); i < j;) {
3831
    drone_pendulum_group& gi = *(*i);
3832
    if (gi.remove (d)) {
3833
      if (gi.n == 0) {
3834
        i = drone_pendulums.erase (i);
3835
        j = drone_pendulums.end ();
3836
      } else ++i;
3837
    } else ++i;
3838
  }
3839
}
3840
 
964 jag 3841
void din::remove_drone_from_mesh (drone* pd) {
1438 jag 3842
  if (meshh.num == 0) return;
964 jag 3843
  for (mesh_iterator i = meshes.begin (); i != meshes.end ();) {
3844
    mesh& mi = *i;
3845
    mi.remove_poly (pd);
3846
    if (mi.num_polys == 0) {
3847
      i = meshes.erase (i);
1438 jag 3848
      --meshh.num;
964 jag 3849
    } else ++i;
3850
  }
3851
}
3852
 
1005 jag 3853
void din::remove_drone_from_pre_mesh (drone* d) {
1049 jag 3854
  if (erase (mkb_selector.meshd, d)) amd.drop = 1;
1005 jag 3855
}
3856
 
964 jag 3857
drone* din::get_drone (int id) { // get drone given its unique id
3858
  for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
3859
    drone* pd = *i;
3860
    if (pd->id == id) return pd;
3861
  }
3862
  return 0;
3863
}
3864
 
1252 jag 3865
void din::load_selected_drones (ifstream& f) {
3866
  string ignore;
3867
  int n;
3868
  f >> ignore >> n;
3869
  if (n) {
3870
    int did;
3871
    selected_drones.resize (n);
3872
    for (int m = 0; m < n; ++m) {
3873
      f >> did;
3874
      drone* sd = get_drone (did);
1574 jag 3875
      sd->sel = 1;
3876
      selected_drones[m] = sd;
1252 jag 3877
    }
3878
    print_selected_drones ();
3879
  }
3880
  num_selected_drones = n;
3881
}
3882
 
3883
void din::save_selected_drones (ofstream& f) {
1694 jag 3884
  f << "selected_drones " << num_selected_drones << spc;
1252 jag 3885
  if (num_selected_drones) {
3886
    for (int i = 0; i < num_selected_drones; ++i) {
3887
      drone* pd = selected_drones[i];
1694 jag 3888
      f << pd->id << spc;
1252 jag 3889
    }
3890
  }
1461 jag 3891
  f << endl;
1252 jag 3892
}
3893
 
3894
 
964 jag 3895
void din::make_trackers () {
3896
  if (num_selected_drones < 1) {
1507 jag 3897
    cons << RED_A2D << eol;
3898
 
964 jag 3899
    return;
3900
  } else if (num_selected_drones == 1) { // toggle tracker
3901
    drone* pd = selected_drones[0];
3902
    if (pd->tracking) {
3903
      remove_tracker (pd);
3904
      cons << GREEN << "Selected drone no longer tracks another drone" << eol;
3905
      return;
3906
    }
3907
    cons << RED << "Drone is not tracking any other drone!" << eol;
3908
    return;
3909
  }
3910
  int last = num_selected_drones - 1;
3911
  drone* p_tracked_drone = selected_drones [last];
3912
  int nl = 0;
3913
  for (int i = 0; i < last; ++i) {
3914
    drone* pdi = selected_drones [i];
3915
    push_back (trackers, pdi);
3916
    pdi->tracking = 1;
3917
    pdi->tracked_drone = p_tracked_drone;
3918
    ++nl;
3919
  }
3920
  if (nl) cons << GREEN << "Number of drones tracking another drone = " << nl << eol;
3921
}
3922
 
1753 jag 3923
void din::track_drones () {
1741 jag 3924
 
964 jag 3925
  for (drone_iterator i = trackers.begin (), j = trackers.end (); i != j; ++i) {
3926
    drone* pdi = *i;
3927
    drone& di = *pdi;
3928
    drone& td = *di.tracked_drone;
1488 jag 3929
    if (di.tracking == drone::POINT) {
1564 jag 3930
      unit_vector (di.vx, di.vy, di.x, di.y, td.x, td.y);
1693 jag 3931
      di.ax = di.vy;
3932
      di.ay = -di.vx;
1488 jag 3933
    } else { // USE
3934
      di.vx = td.vx;
3935
      di.vy = td.vy;
1693 jag 3936
      di.ax = td.ax;
3937
      di.ay = td.ay;
1488 jag 3938
    }
964 jag 3939
  }
3940
 
1753 jag 3941
 
3942
}
3943
 
3944
void din::evalgravity () {
1840 jag 3945
  gravity_t& grav = dinfo.gravity;
2048 jag 3946
  if (grav.cmouse.state)
3947
    grav.pointt (win_mousex, win_mousey);
2047 jag 3948
  for (int i = 0; i < 2; ++i) {
3949
    drone* tdi = grav.tracked_drone[i];
3950
    if (tdi) {
3951
      int dwx = tdi->sx, dwy = tdi->y; // in window space
3952
      int& ldwxi = grav.ldwx[i];
3953
      int& ldwyi = grav.ldwy[i];
3954
      if (dwx != ldwxi || dwy != ldwyi) {
3955
        grav.track (i, dwx, dwy);
3956
        ldwxi = dwx;
3957
        ldwyi = dwy;
3958
      }
1903 jag 3959
    }
2047 jag 3960
  }
964 jag 3961
}
3962
 
3963
void din::select_tracked_drones () {
1434 jag 3964
  CLEAR_SELECTED_DRONES
964 jag 3965
  for (drone_iterator i = trackers.begin (), j = trackers.end (); i != j; ++i) {
3966
    drone* pdi = *i;
1435 jag 3967
    drone* ptd = pdi->tracked_drone;
3968
    if (ptd->sel == 0) {
3969
      ptd->sel = 1;
3970
      selected_drones.push_back (ptd);
3971
    }
964 jag 3972
  }
1435 jag 3973
  print_selected_drones ();
964 jag 3974
}
3975
 
3976
void din::remove_tracker (drone* ptd) {
3977
  for (drone_iterator i = trackers.begin (), j = trackers.end (); i != j;) {
3978
    drone* pdi = *i;
3979
    drone& di = *pdi;
3980
    if (pdi == ptd || di.tracked_drone == ptd) {
3981
      di.tracking = 0;
3982
      di.tracked_drone = 0;
3983
      i = trackers.erase (i);
3984
      j = trackers.end ();
3985
    } else ++i;
3986
  }
3987
}
3988
 
3989
void din::sync_drones () {
3990
  for (int i = 0; i < num_selected_drones; ++i) {
3991
    drone& ds = *selected_drones[i];
3992
    ds.player.x = ds.mod.am.bv.now = ds.mod.fm.bv.now = 0.0f;
3993
  }
3994
}
3995
 
2007 jag 3996
int din::toggle_freeze_drones () {
1429 jag 3997
  if (num_selected_drones) {
3998
    int nf = 0, nt = 0;
3999
    for (int i = 0; i < num_selected_drones; ++i) {
4000
      drone& ds = *selected_drones[i];
2011 jag 4001
      if (ds.frozen) nt += ds.thaw (); else nf += ds.freeze ();
1429 jag 4002
    }
2007 jag 4003
    int r = nf || nt;
4004
    if (r) cons << GREEN << "Froze " << nf << " drones, Thawed " << nt << s_drones << eol;
4005
    return r;
1888 jag 4006
  } else
4007
    cons << RED_PSD << eol;
2007 jag 4008
  return 0;
1429 jag 4009
}
4010
 
4011
int din::freeze_drones () {
4012
  if (num_selected_drones) {
4013
    int nf = 0;
4014
    for (int i = 0; i < num_selected_drones; ++i) {
4015
      drone& ds = *selected_drones[i];
2011 jag 4016
      if (!ds.frozen) nf += ds.freeze ();
964 jag 4017
    }
2007 jag 4018
    if (nf) cons << GREEN << "Froze " << nf << s_drones << eol;
1429 jag 4019
    return nf;
1473 jag 4020
  } else cons << RED_PSD << eol;
1429 jag 4021
  return 0;
964 jag 4022
}
4023
 
1429 jag 4024
int din::thaw_drones () {
4025
  if (num_selected_drones) {
4026
    int nt = 0;
4027
    for (int i = 0; i < num_selected_drones; ++i) {
4028
      drone& ds = *selected_drones[i];
1888 jag 4029
      if (ds.frozen) nt += ds.thaw ();
1429 jag 4030
    }
2007 jag 4031
    if (nt) cons << GREEN << "Thawed " << nt << s_drones << eol;
1429 jag 4032
    return nt;
1473 jag 4033
  } else cons << RED_PSD << eol;
1429 jag 4034
  return 0;
4035
}
964 jag 4036
 
1429 jag 4037
int din::freeze_orbiters () {
4038
  if (num_selected_drones) {
4039
    int nf = 0;
4040
    for (int i = 0; i < num_selected_drones; ++i) {
4041
      drone& ds = *selected_drones[i];
1888 jag 4042
      if (ds.orbiting && (ds.frozen == 0)) nf += ds.freeze ();
964 jag 4043
    }
1429 jag 4044
    return nf;
964 jag 4045
  }
1429 jag 4046
  return 0;
964 jag 4047
}
4048
 
1429 jag 4049
int din::thaw_orbiters () {
1435 jag 4050
  xforming = NONE;
1429 jag 4051
  if (num_selected_drones) {
4052
    int nt = 0;
4053
    for (int i = 0; i < num_selected_drones; ++i) {
4054
      drone& ds = *selected_drones[i];
1888 jag 4055
      if (ds.orbiting && ds.frozen) nt += ds.thaw ();
964 jag 4056
    }
1429 jag 4057
    return nt;
964 jag 4058
  }
1429 jag 4059
  return 0;
964 jag 4060
}
4061
 
4062
void din::region_begin () {
4063
  rgn.left = rgn.right = win_mousex;
4064
  rgn.bottom = rgn.top = win_mousey;
1438 jag 4065
  if (meshh.create) mkb_selector.set_mesh (meshh.create, dinfo.rows, dinfo.cols);
964 jag 4066
}
4067
 
1698 jag 4068
const box<float>& din::region_update () {
964 jag 4069
  rgn.right = win_mousex;
4070
  rgn.top = win_mousey;
1226 jag 4071
  if (mkb_selector.mesh) {
1451 jag 4072
    int s = SHIFT, c = CTRL, sc = s|c;
1226 jag 4073
    if (sc) { // equalise width/height
1698 jag 4074
      float w = rgn.right - rgn.left, h = rgn.top - rgn.bottom;
4075
      float aw = abs(w), ah = abs(h);
1226 jag 4076
      if (s) { // equalise to smaller of width, height
4077
        if (aw > ah) {
1698 jag 4078
          float dw = aw - ah;
1226 jag 4079
          int _ve = w < 0? 1:-1;
4080
          rgn.right += (_ve * dw);
4081
        } else {
1698 jag 4082
          float dh = ah - aw;
1226 jag 4083
          int _ve = h < 0? 1:-1;
4084
          rgn.top += (_ve * dh);
4085
        }
4086
      } else { // equalise to larger of width, height
4087
        if (aw > ah) {
1698 jag 4088
          float dw = aw - ah;
1226 jag 4089
          int _ve = h < 0? -1:1;
4090
          rgn.top += (_ve * dw);
4091
        } else {
1698 jag 4092
          float dh = ah - aw;
1226 jag 4093
          int _ve = w < 0? -1:1;
4094
          rgn.right += (_ve * dh);
4095
        }
1102 jag 4096
      }
1100 jag 4097
    }
1226 jag 4098
    mkb_selector.gen_mesh_pts (rgn);
1100 jag 4099
  }
964 jag 4100
  return rgn;
4101
}
4102
 
4103
void din::region_end () {
1037 jag 4104
  int swp = rgn.calc ();
1438 jag 4105
  if (meshh.create) {
1040 jag 4106
    if (swp) mkb_selector.gen_mesh_pts (rgn);
1005 jag 4107
    create_drone_mesh ();
1438 jag 4108
    meshh.create = 0;
1098 jag 4109
  } else if (create_drone_pend) {
4110
    create_drone_pendulum ();
4111
    create_drone_pend = 0;
1005 jag 4112
  }
964 jag 4113
  else
4114
    find_selected_drones (rgn);
4115
}
4116
 
1005 jag 4117
void din::region_abort () {
1438 jag 4118
  if (meshh.create) stop_creating_mesh ();
1100 jag 4119
  if (create_drone_pend) stop_creating_drone_pendulum ();
1005 jag 4120
}
4121
 
964 jag 4122
void din::modulate_ranges () {
1436 jag 4123
  int nw, nw_2, center, nl, nr, dl, dr, z;
4124
  nw = nw_2 = center = nl = nr = dl = dr = z = 0;
964 jag 4125
  for (int i = 0; i < num_ranges; ++i) {
4126
    range& ri = ranges[i];
4127
    if (ri.mod.active > 0) {
4128
      ri.mod.calc ();
4129
      // width modulation
1436 jag 4130
      nw = ri.mod.fm.initial + ri.mod.fm.result;
4131
      switch (ri.fixed) {
4132
        case range::LEFT:
4133
          dr = nw - ri.extents.width;
4134
          range_right_changed (i, dr, 0);
4135
          break;
4136
        case range::RIGHT:
4137
          dl = ri.extents.width - nw;
4138
          range_left_changed (i, dl, 0);
4139
          break;
4140
        default:
4141
          nw_2 = nw / 2;
4142
          center = (ri.extents.left + ri.extents.right) / 2;
4143
          nl = center - nw_2, nr = center + nw_2;
4144
          dl = nl - ri.extents.left;
4145
          dr = nr - ri.extents.right;
4146
          range_left_changed (i, dl, 0);
4147
          range_right_changed (i, dr, 0);
4148
          break;
4149
      }
964 jag 4150
      // height modulation
4151
      int nh = ri.mod.am.initial + ri.mod.am.result;
4152
      if (nh < 1) nh = 1;
4153
      ri.extents.top = BOTTOM + nh;
4154
      ri.extents.calc ();
4155
 
4156
      z = 1;
4157
    }
4158
  }
4159
  if (z) {
1402 jag 4160
    refresh_all_drones ();
964 jag 4161
    find_visible_ranges ();
4162
  }
4163
}
4164
 
4165
void din::set_ran_mod (int w) {
4166
  for (int i = 0; i < num_ranges; ++i) {
4167
    range& ri = ranges[i];
4168
    ri.mod.active = w;
4169
  }
4170
  MENU.cb_mod_ran.set_state (ranges[dinfo.sel_range].mod.active, 0);
4171
}
4172
 
4173
void din::pause_resume_ran_mod () {
4174
  for (int i = 0; i < num_ranges; ++i) {
4175
    range& ri = ranges[i];
4176
    ri.mod.active = -ri.mod.active;
4177
  }
4178
}
4179
 
4180
void din::toggle_ran_mod () {
4181
  for (int i = 0; i < num_ranges; ++i) {
4182
    range& ri = ranges[i];
4183
    ri.mod.active = !ri.mod.active;
4184
  }
1443 jag 4185
  MENU.cb_mod_ran.set_state (ranges[dinfo.sel_range].mod.active, 0);
964 jag 4186
}
4187
 
4188
void din::update_drone_mod_solvers (int w, multi_curve& mx) {
4189
  if (w == modulator::AM) {
4190
    for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
4191
      modulator& dm = (*i)->mod;
4192
      dm.am.bv.sol.update ();
4193
    }
4194
  } else {
4195
    for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
4196
      modulator& dm = (*i)->mod;
4197
      dm.fm.bv.sol.update ();
4198
    }
4199
  }
4200
}
4201
 
4202
void din::update_range_mod_solvers (int w, multi_curve& mx) {
4203
  if (w == modulator::AM) {
4204
    for (int i = 0; i < num_ranges; ++i) {
4205
      modulator& rm = ranges[i].mod;
1716 jag 4206
      rm.am.bv.sol.update (); // am for width
964 jag 4207
    }
4208
  } else {
4209
    for (int i = 0; i < num_ranges; ++i) {
4210
      modulator& rm = ranges[i].mod;
1716 jag 4211
      rm.fm.bv.sol.update (); // fm for height
964 jag 4212
    }
4213
  }
4214
}
4215
 
4216
void din::snap_drones (int v) {
4217
  if (num_selected_drones) {
4218
    int nt[2] = {0};
969 jag 4219
    static const char* what_str1 [] = {"Unsnapped ", "Snapped "};
964 jag 4220
    if (v == -1) { // toggle
4221
      for (int i = 0; i < num_selected_drones; ++i) {
4222
        drone* pdi = selected_drones[i];
4223
        pdi->snap = !pdi->snap;
4224
        ++nt[pdi->snap];
4225
      }
4226
      cons << "Snapped " << nt[1] << " drones, Unsnapped " << nt[0] << s_drones << eol;
4227
 
4228
    } else { // set
4229
      for (int i = 0; i < num_selected_drones; ++i) {
4230
        drone* pdi = selected_drones[i];
4231
        pdi->snap = v;
4232
      }
969 jag 4233
      cons << GREEN << what_str1[v] << num_selected_drones << " drones" << eol;
964 jag 4234
    }
4235
 
4236
  } else {
1473 jag 4237
    cons << RED_PSD << eol;
964 jag 4238
  }
4239
}
4240
 
1619 jag 4241
void din::pos_afx_vel (int v) {
964 jag 4242
  int nm [2] = {0};
4243
  if (num_selected_drones) {
4244
    if (v == -1) { // toggle
4245
      for (int i = 0; i < num_selected_drones; ++i) {
4246
        drone* pdi = selected_drones[i];
1615 jag 4247
        pdi->posafxvel.yes = !pdi->posafxvel.yes;
4248
        ++nm[pdi->posafxvel.yes];
964 jag 4249
      }
1615 jag 4250
      cons << GREEN << "Position affects velocity for " << nm[1] << " drones, Unset for " << nm[0] << s_drones << eol;
1694 jag 4251
    } else { // set
964 jag 4252
      for (int i = 0; i < num_selected_drones; ++i) {
4253
        drone* pdi = selected_drones[i];
1615 jag 4254
        pdi->posafxvel.yes = v;
964 jag 4255
      }
4256
      static const char* strs[] = {"Unset", "Set"};
1615 jag 4257
      cons << GREEN << strs[v] << " Position affects velocity for " << num_selected_drones << s_drones << eol;
964 jag 4258
 
4259
    }
4260
  } else {
1473 jag 4261
    cons << RED_PSD << eol;
964 jag 4262
  }
4263
}
4264
 
4265
void din::select_all_browsed_drones (int bd) {
4266
  selected_drones.resize (num_browsed_drones);
4267
  for (int i = 0; i < num_browsed_drones; ++i) {
4268
    drone* pdb = browsed_drones[i];
4269
    pdb->sel = 1;
4270
    selected_drones[i] = pdb;
4271
  }
4272
  print_selected_drones ();
4273
  browsed_drone = bd;
4274
  MENU.sp_browse_drone.set_value (browsed_drone);
4275
}
4276
 
4277
void din::browse_drone (int db) {
4278
  if (num_browsed_drones) {
987 jag 4279
    clear_selected_drones ();
964 jag 4280
    browsed_drone += db;
4281
    if (browsed_drone > last_browseable_drone) { // select all browsed drones
4282
      select_all_browsed_drones (-1);
4283
      return;
4284
    } else if (browsed_drone < 0) {
4285
      select_all_browsed_drones (num_browsed_drones);
4286
      return;
4287
    }
4288
    drone* pdb = browsed_drones [browsed_drone];
4289
    pdb->sel = 1;
4290
    num_selected_drones = 1;
4291
    selected_drones.resize (num_selected_drones);
4292
    selected_drones[0] = pdb;
1749 jag 4293
    sprintf (BUFFER, "Browsed drone %d of %d", browsed_drone+1, num_browsed_drones);
4294
    cons << GREEN << BUFFER;
4295
      drone::chuckt& chuck = pdb->chuck;
4296
      if (chuck.yes) chuck.print ();
4297
    cons << eol;
4298
    MENU.sp_browse_drone.set_value (browsed_drone);
987 jag 4299
  } else {
4300
    cons << RED << "No drones to browse, make a new selection" << eol;
964 jag 4301
  }
4302
}
4303
 
1302 jag 4304
void din::browse_range (int dr) {
4305
  dinfo.sel_range += dr;
4306
  clamp (0, dinfo.sel_range, last_range);
1308 jag 4307
  MENU.load_range (dinfo.sel_range);
1302 jag 4308
}
4309
 
1028 jag 4310
void din::all_ranges_width_changed () {
4311
  float a = 0.0f, da = 1.0f / last_range;
4312
  extern solver sol_ran_width;
4313
  int w = 0;
1031 jag 4314
  float s = 0.0f;
1028 jag 4315
  for (int i = 0; i < num_ranges; ++i) {
1031 jag 4316
    s = sol_ran_width (a);
4317
    w = s * WIDTH;
4318
    if (w < 1) w = 1;
1028 jag 4319
    set_range_width (i, w);
4320
    a += da;
4321
  }
4322
}
4323
 
4324
void din::all_ranges_height_changed () {
4325
  float a = 0.0f, da = 1.0f / last_range;
4326
  extern solver sol_ran_height;
4327
  int h = 0;
1031 jag 4328
  float s = 0.0f;
1028 jag 4329
  for (int i = 0; i < num_ranges; ++i) {
1031 jag 4330
    s = sol_ran_height (a);
4331
    h = s * HEIGHT;
4332
    if (h < 1) h = 1;
1028 jag 4333
    set_range_height (i, h);
4334
    a += da;
4335
  }
4336
}
1037 jag 4337
 
1651 jag 4338
void din::draw_vol_dist () {
4339
 
4340
  glEnable (GL_BLEND);
4341
  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4342
 
1107 jag 4343
  const float c = 1.0f, b = 0.9f;
1106 jag 4344
  float yb, yt;
4345
  int xl, xr;
4346
  float a, da;
4347
  float v, vc;
1651 jag 4348
  for (int i = visl, j = visr + 1; i < j; ++i) {
1106 jag 4349
    range& R = ranges[i];
1140 jag 4350
    const int dy = min (dinfo.dist.pix, R.extents.height);
1106 jag 4351
    yb = R.extents.bottom; yt = R.extents.top;
4352
    xl = R.extents.left; xr = R.extents.right;
4353
    a = 0.0f; da = dy * R.extents.height_1;
4354
    v = vc = 0.0f;
4355
    glBegin (GL_QUAD_STRIP);
4356
      while (yb < yt) {
4357
        v = warp_vol (a);
4358
        vc = v * c;
4359
        glColor4f (vc, 0, vc, b);
4360
        glVertex2f (xl, yb);
4361
        glVertex2f (xr, yb);
4362
        yb += dy;
4363
        a += da;
4364
      }
4365
      a = 1.0f;
1651 jag 4366
      v = warp_vol (a);
1106 jag 4367
      vc = v * c;
4368
      glColor4f (vc, 0, vc, b);
4369
      glVertex2f (xl, yt);
4370
      glVertex2f (xr, yt);
4371
    glEnd ();
4372
  }
1651 jag 4373
  glDisable (GL_BLEND);
1106 jag 4374
}
4375
 
1651 jag 4376
void din::draw_pitch_dist () {
4377
 
4378
  glEnable (GL_BLEND);
4379
  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4380
 
1106 jag 4381
  const float c = 1.0f, b = 0.5f;
4382
  float yb, yt;
4383
  int xl, xr;
4384
  float a, da;
4385
  float p, pc;
1651 jag 4386
  for (int i = visl, j = visr + 1; i < j; ++i) {
1106 jag 4387
    range& R = ranges[i];
1140 jag 4388
    const int dx = min (dinfo.dist.pix, R.extents.width);
1106 jag 4389
    yb = R.extents.bottom; yt = R.extents.top;
4390
    xl = R.extents.left; xr = R.extents.right;
4391
    a = 0.0f; da = dx * R.extents.width_1;
4392
    p = pc = 0.0f;
4393
    glBegin (GL_QUAD_STRIP);
4394
      while (xl < xr) {
4395
        p = warp_pitch (a);
4396
        pc = p * c;
4397
        glColor4f (0, pc, pc, b);
4398
        glVertex2f (xl, yb);
4399
        glVertex2f (xl, yt);
4400
        xl += dx;
4401
        a += da;
4402
      }
4403
      a = 1.0f;
1651 jag 4404
      p = warp_pitch (a);
1106 jag 4405
      pc = p * c;
4406
      glColor4f (0, pc, pc, b);
1122 jag 4407
      glVertex2f (xr, yb);
4408
      glVertex2f (xr, yt);
1106 jag 4409
    glEnd ();
4410
  }
1651 jag 4411
 
4412
  glDisable (GL_BLEND);
1106 jag 4413
}
4414
 
1404 jag 4415
void din::noise_interpolator_changed () {
4416
  for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
4417
    drone& di = *(*i);
4418
    di.nsr.warp (&noiser::interp);
4419
  }
4420
}
1460 jag 4421
 
1497 jag 4422
int din::can_connect (drone* d1, drone* d2) {
4423
  if (d1 == d2) return 0; // no self connection
1677 jag 4424
  if (d2->nconn)
1497 jag 4425
    for (drone_iterator p = d2->connections.begin (), q = d2->connections.end(); p != q; ++p)
4426
      if (d1 == *p) return 0; // already connected
4427
  return 1;
4428
}
4429
 
1511 jag 4430
void din::calc_stepz (const string& fld) {
1512 jag 4431
  nstepz = 0;
4432
  stepz.clear ();
1511 jag 4433
  int p;
4434
  map<int, bool> exists;
1463 jag 4435
  string str;
1511 jag 4436
  stringstream ss1 (fld);
1463 jag 4437
  while (ss1.eof() == 0) {
4438
    ss1 >> str;
4439
    stringstream ss2 (str);
4440
    ss2 >> p;
4441
    if (p > 0 && (exists[p] == false)) {
1511 jag 4442
      stepz.push_back (p);
4443
      ++nstepz;
1463 jag 4444
      exists[p] = true;
4445
    }
1462 jag 4446
  }
1511 jag 4447
}
1476 jag 4448
 
4449
void din::alloc_conns () {
4450
  if (totcon > con_size) {
4451
    if (con_pts) delete[] con_pts;
4452
    if (con_clr) delete[] con_clr;
4453
    con_pts = new float [totcon * 2 * 2];
4454
    con_clr = new float [totcon * 2 * 3];
4455
    con_size = totcon;
4456
  }
4457
}
4458
 
1507 jag 4459
int din::disconnect_drones () {
1508 jag 4460
  if (num_selected_drones) {
1802 jag 4461
    if (MENU.trackcon.state == 0) {
4462
      for (int i = 0; i < num_selected_drones; ++i) {
4463
        drone* pd = selected_drones[i];
4464
        remove_connections (pd);
4465
        if (pd->tracking) {
4466
          erase (trackers, pd);
4467
          pd->tracking = 0;
4468
          pd->tracked_drone = 0;
4469
        }
4470
      }
4471
 
4472
    } else {
4473
      for (int i = 0; i < num_selected_drones; ++i) remove_connections (selected_drones[i]);
4474
    }
1507 jag 4475
    return 1;
1508 jag 4476
  } else cons << RED_PSD << eol;
1507 jag 4477
  return 0;
1469 jag 4478
}
4479
 
1476 jag 4480
void din::remove_connections (drone* pd) {
4481
 
1491 jag 4482
  // remove connections to pd
1460 jag 4483
  for (drone_iterator i = drones.begin (), j = drones.end (); i != j; ++i) {
1476 jag 4484
    drone* pdi = *i;
4485
    drone& di = *pdi;
1677 jag 4486
    if (di.nconn && pdi != pd) {
1492 jag 4487
      list<double>::iterator mi = di.mags.begin ();
1477 jag 4488
      for (drone_iterator p = di.connections.begin (), q = di.connections.end(); p != q;) {
4489
        drone* pdp = *p;
4490
        if (pdp == pd) {
4491
          p = di.connections.erase (p);
4492
          q = di.connections.end ();
1492 jag 4493
          mi = di.mags.erase (mi);
1677 jag 4494
          --di.nconn;
1477 jag 4495
          --totcon;
1492 jag 4496
        } else {
1477 jag 4497
          ++p;
1492 jag 4498
          ++mi;
4499
        }
1476 jag 4500
      }
1462 jag 4501
    }
4502
  }
1476 jag 4503
 
1497 jag 4504
  // remove connections from pd
1677 jag 4505
  if (pd->nconn) {
4506
    totcon -= pd->nconn;
4507
    pd->nconn = 0;
1476 jag 4508
    pd->connections.clear ();
1492 jag 4509
    pd->mags.clear ();
1476 jag 4510
  }
4511
 
1491 jag 4512
  _2totcon = 2 * totcon;
1477 jag 4513
 
1491 jag 4514
  /*for (vector<connect>::iterator i = conns.begin (), j = conns.end (); i != j;) {
1487 jag 4515
    connect& ci = *i;
4516
    if (ci.d1 == pd || ci.d2 == pd) {
4517
      i = conns.erase (i);
4518
      j = conns.end ();
4519
    } else
4520
    ++i;
1491 jag 4521
  }*/
1487 jag 4522
 
1460 jag 4523
}
4524
 
1491 jag 4525
/*void din::dirty_connection (drone* d) {
1487 jag 4526
  for (int i = 0, j = conns.size (); i < j; ++i) {
4527
    connect& ci = conns[i];
4528
    if (ci.d1 == d || ci.d2 == d) ci.dirty = 1;
4529
  }
1492 jag 4530
}
4531
 
4532
void din::dirty_connections () {
4533
  for (int i = 0; i < num_selected_drones; ++i) {
4534
    drone* pdi = selected_drones[i];
4535
    dirty_connection (pdi);
4536
  }
1491 jag 4537
}*/
1487 jag 4538
 
1476 jag 4539
void din::draw_connections () {
4540
 
1491 jag 4541
  if (totcon == 0) return;
1476 jag 4542
 
4543
  int p = 0, q = 0;
4544
 
1511 jag 4545
  map<drone*, bool> drawn;
1463 jag 4546
  for (drone_iterator i = drones.begin (), j = drones.end (); i != j; ++i) {
1476 jag 4547
    drone& di = *(*i);
1677 jag 4548
    if (di.nconn) {
1476 jag 4549
      for (drone_iterator s = di.connections.begin (), t = di.connections.end(); s != t; ++s) {
4550
        con_clr[q++] = di.r;
4551
        con_clr[q++] = di.g;
4552
        con_clr[q++] = di.b;
4553
        drone& dj = *(*s);
4554
        con_clr[q++] = dj.r;
4555
        con_clr[q++] = dj.g;
4556
        con_clr[q++] = dj.b;
4557
        con_pts[p++]=di.sx;
4558
        con_pts[p++]=di.y;
4559
        con_pts[p++]=dj.sx;
4560
        con_pts[p++]=dj.y;
1463 jag 4561
      }
1460 jag 4562
    }
1463 jag 4563
  }
1476 jag 4564
 
4565
  glEnableClientState (GL_COLOR_ARRAY);
4566
  glColorPointer (3, GL_FLOAT, 0, con_clr);
4567
  glVertexPointer (2, GL_FLOAT, 0, con_pts);
4568
  glDrawArrays (GL_LINES, 0, _2totcon);
1491 jag 4569
  glDisableClientState (GL_COLOR_ARRAY);
1476 jag 4570
 
1460 jag 4571
}
1476 jag 4572
 
1514 jag 4573
void din::reset_drone_arrows () {
4574
  if (num_selected_drones) {
4575
    for (int i = 0; i < num_selected_drones; ++i) {
4576
      drone& ds = *selected_drones[i];
4577
      ds.arrow.reset ();
4578
    }
4579
  } else cons << RED_PSD << eol;
4580
}
1499 jag 4581
 
1552 jag 4582
void din::gabber::abort () {
1561 jag 4583
  for (drone_iterator i = drones.begin (), j = drones.end (); i != j; ++i) {
4584
    drone& di = *(*i);
4585
    di.tovol = di.gab.amount;
4586
  }
1552 jag 4587
  drones.clear ();
4588
  n = 0;
1561 jag 4589
  cons << RED << "Aborted " << what << eol;
1552 jag 4590
}
4591
 
1558 jag 4592
void din::gabber::set (din* dd, float t, const string& w, float tdiv, int fid) {
1819 jag 4593
  int ns = dd->num_selected_drones;
4594
  if (ns) {
1552 jag 4595
    if (n) abort ();
1819 jag 4596
    for (int i = 0; i < ns; ++i) {
1546 jag 4597
      drone* pds = dd->selected_drones[i];
4598
      drone& ds = *pds;
1999 jag 4599
      //if (!equals (ds.gab.amount, t)) {
1819 jag 4600
        ds.gab.set (ds.gab.amount, t * ds.tovol, 1, max (0.0f, MENU.gabt()) / tdiv);
4601
        ds.finl = drone::fins[fid];
1546 jag 4602
        drones.push_back (pds);
4603
        ++n;
1999 jag 4604
      //}
1546 jag 4605
    }
1547 jag 4606
    if (n) {
4607
      what = w;
1819 jag 4608
      cons << YELLOW << "Started " << what << spc << n << TOGO << eol;
1555 jag 4609
    }
1547 jag 4610
  } else {
4611
    cons << RED_PSD << eol;
1546 jag 4612
  }
4613
}
4614
 
4615
void din::gabber::eval () {
4616
  if (n) {
4617
    for (drone_iterator i = drones.begin (), j = drones.end (); i != j;) {
4618
      drone* pdi = *i;
4619
      drone& di = *pdi;
1558 jag 4620
      di.update_pv = drone::INTERPOLATE;
1546 jag 4621
      if (di.gab.eval () == 0) {
1561 jag 4622
        di.tovol = di.gab.start;
1546 jag 4623
        i = drones.erase (i);
4624
        j = drones.end ();
1558 jag 4625
        if (di.finl) di.finl->finished (din0, pdi);
1819 jag 4626
        if (--n == 0) cons << GREEN << "Finished " << what << eol; else cons << YELLOW << what << spc << n << TOGO << eol;
1553 jag 4627
      } else {
4628
        ++i;
4629
      }
1546 jag 4630
    }
4631
  }
4632
}
4633
 
4634
void din::gabber::erase (drone* d) {
4635
  if (::erase (drones, d)) --n;
4636
}
4637
 
1559 jag 4638
void din::gabber::setgabt () {
1547 jag 4639
  if (n)
4640
    for (drone_iterator i = drones.begin (), j = drones.end (); i != j; ++i)
1819 jag 4641
      (*i)->gab.delta_time = MENU.gabt();
1547 jag 4642
}
4643
 
1552 jag 4644
void din::setdronevol (spinner<float>& s) {
4645
  if (num_selected_drones) {
4646
    for (int i = 0; i < num_selected_drones; ++i) {
4647
      drone& ds = *selected_drones[i];
4648
      ds.gab.amount += s();
1561 jag 4649
      ds.tovol = ds.gab.amount;
1552 jag 4650
      ds.update_pv = drone::EMPLACE;
4651
      cons << "Drone " << i << " volume = " << ds.gab.amount << eol;
4652
    }
2104 jag 4653
  } else
4654
    cons << RED_PSD << eol;
1552 jag 4655
}
4656
 
1558 jag 4657
void din::drone2noise () {
4658
  gab.set (this, 0.0f, "Drone > Noise", 2.0f, 1);
4659
}
4660
 
4661
void din::noise2drone () {
4662
  gab.set (this, 0.0f, "Noise > Drone", 2.0f, 2);
4663
}
4664
 
4665
void drone::drone2noise::finished (din& mkb, drone* pdi) {
4666
  drone& di = *pdi;
1687 jag 4667
  di.is = drone::NOISE;
1558 jag 4668
  di.setnoise ();
1816 jag 4669
  di.r = di.g = di.b = 1.0f;
1819 jag 4670
  di.gab.set (di.gab.amount, 1.0f * di.tovol, 1, MENU.gabt() / 2.0f);
1558 jag 4671
  di.finl = 0;
4672
  mkb.gab.drones.push_back (pdi);
4673
  ++mkb.gab.n;
4674
}
4675
 
4676
void drone::noise2drone::finished (din& mkb, drone* pdi) {
4677
  drone& di = *pdi;
1687 jag 4678
  di.is = drone::DRONE;
1558 jag 4679
  di.setcolor ();
1819 jag 4680
  di.gab.set (di.gab.amount, 1.0f * di.tovol, 1, MENU.gabt() / 2.0f);
1558 jag 4681
  di.finl = 0;
4682
  mkb.gab.drones.push_back (pdi);
4683
  ++mkb.gab.n;
4684
}
4685
 
4686
void din::set_random_color () {
4687
  rndr.set (MENU.s_red_min (), MENU.s_red_max());
4688
  rndg.set (MENU.s_green_min (), MENU.s_green_max());
4689
  rndb.set (MENU.s_blue_min (), MENU.s_blue_max());
1557 jag 4690
}
4691
 
1612 jag 4692
void din::gotpoint () {
2068 jag 4693
  if (!SHIFT) dinfo.cen.x += delta_mousex;
4694
  if (!CTRL) dinfo.cen.y -= delta_mousey;
4695
  /*dinfo.cen.x = win_mousex;
4696
  dinfo.cen.y = win_mousey;*/
1611 jag 4697
}
4698
 
1619 jag 4699
void din::ranchkdro () {
4700
  for (drone_iterator i = drones.begin (), j = drones.end (); i != j; ++i) {
4701
    drone& di = *(*i);
4702
    clamp (0, di.range, last_range);
4703
  }
4704
}
4705
 
4706
void din::delselran () {
4707
  // delete selected range
4708
  if (num_ranges == 1) {
1620 jag 4709
    cons << RED << "Will not delete the only range!" << eol;
1619 jag 4710
    return;
4711
  }
4712
 
4713
  int& sr = dinfo.sel_range;
4714
  vector<range>::iterator rb = ranges.begin();
4715
  if (sr == 0 || sr == last_range)
4716
    ;
4717
  else {
4718
    int p = sr - 1, q = sr + 1;
4719
    range& rp = ranges[p];
4720
    range& rq = ranges[q];
4721
    range& rs = ranges[sr];
4722
    rp.notes[1] = rq.notes[0];
4723
    rp.intervals[1] = rq.intervals[0];
4724
    for (int i = sr + 1; i < num_ranges; ++i) {
4725
      range& ri = ranges[i];
4726
      ri.extents.move (-rs.extents.width, 0);
4727
    }
4728
  }
4729
 
4730
  ranges.erase (rb + sr);
4731
 
4732
  initranpar (num_ranges - 1);
4733
  ranchkdro ();
4734
  refresh_all_drones ();
4735
  find_current_range ();
4736
 
4737
}
4738
 
1618 jag 4739
mkb_selector_t::mkb_selector_t () : of_prox_far (proximity_orderer::FARTHEST) {
4740
  orderers[0]=&of_asc;
4741
  orderers[1]=&of_desc;
4742
  orderers[2]=&of_asc_cols;
4743
  orderers[3]=&of_desc_cols;
4744
  orderers[4]=&of_rnd;
4745
  orderers[5]=&of_prox_near;
4746
  orderers[6]=&of_prox_far;
4747
}
4748
 
1698 jag 4749
void mkb_selector_t::draw (const box<float>& region) {
1623 jag 4750
  if (din0.dinfo.cen.op) din0.dinfo.cen.draw ();
1620 jag 4751
  else {
4752
    if (mesh) {
4753
      glPointSize (4);
4754
      glVertexPointer (2, GL_FLOAT, 0, meshp);
4755
      glColor3f (1, 1, 1);
4756
      glDrawArrays (GL_POINTS, 0, rowcol);
4757
      glPointSize (1);
4758
    }
4759
    cross = din0.create_drone_pend | din0.meshh.create;
4760
    box_selector::draw (region);
4761
  }
1618 jag 4762
}
4763
 
1620 jag 4764
int mkb_selector_t::handle_input () {
1677 jag 4765
  if (lmb) {
1679 jag 4766
    if (lmb_clicked == 0) {
1992 jag 4767
      if (din0.wanding || din0.moving_drones || din0.phrasor0.isrecording()) {
1679 jag 4768
        lmb_clicked = 1;
4769
        return 1;
4770
      }
4771
    } else
1677 jag 4772
      return 1;
4773
  } else {
4774
    if (lmb_clicked) {
4775
      lmb_clicked = 0;
1835 jag 4776
      if (din0.moving_drones) din0.set_moving_drones (0);
4777
      din0.stopwanding ();
1992 jag 4778
      if (din0.phrasor0.isrecording()) din0.finish_phrase_recording ();
1679 jag 4779
      return 1;
1677 jag 4780
    }
4781
  }
2201 jag 4782
 
1623 jag 4783
  int r = din0.dinfo.cen.handle_input();
2202 jag 4784
  if (r == 0) {
4785
    if (MENU.cb_show_gravity.state)
4786
      r = din0.dinfo.gravity.handle_input2 ();
4787
    else
4788
      r = 0;
4789
  }
2201 jag 4790
  if (r == 0) r = box_selector::handle_input ();
4791
 
1891 jag 4792
  return r;
1620 jag 4793
}
4794
 
1767 jag 4795
void drone::setcolor () {
4796
  if (is == drone::NOISE)
1814 jag 4797
    r = g = b = 1;
1767 jag 4798
  else {
1814 jag 4799
    color& gc = MENU.colorer ();
4800
    r = gc.r;
1767 jag 4801
    g = gc.g;
4802
    b = gc.b;
4803
  }
4804
}
1657 jag 4805
 
1835 jag 4806
int din::stopwanding () {
1839 jag 4807
  if (wanding) {// && (phrasor0.state != phrasor::playing)) {
1835 jag 4808
    wanding = 0;
4809
    cons << RED << "Stopped wanding drones!" << eol;
4810
    return 1;
4811
  }
4812
  return 0;
4813
}
4814
 
1984 jag 4815
void din::rail (int dir, double scl) {
4816
  for (int i = 0; i < num_selected_drones; ++i) {
4817
    drone& di = *selected_drones[i];
4818
    di.set_center (di.cx + dir * scl * di.vx, di.cy + dir * scl * di.vy);
4819
  }
4820
}
4821
 
4822
void din::strafe (int dir, double scl) {
4823
  for (int i = 0; i < num_selected_drones; ++i) {
4824
    drone& di = *selected_drones[i];
4825
    di.set_center (di.cx + dir * scl * di.vy, di.cy - dir * scl * di.vx);
4826
  }
4827
}
4828
 
2031 jag 4829
void din::flip_drone_motion () {
4830
  if (num_selected_drones) {
4831
    for (int i = 0; i < num_selected_drones; ++i) {
4832
      drone& di = *selected_drones[i];
2083 jag 4833
      if (di.orbiting) {
4834
        di.vrev *= -1;
4835
      } else {
4836
        if (di.autorot.v.yes)
4837
          di.autorot.v.dir *= -1;
4838
        else {
4839
          di.vx = -di.vx;
4840
          di.vy = -di.vy;
4841
        }
4842
 
4843
        if (di.autorot.a.yes)
4844
          di.autorot.a.dir *= -1;
4845
        else {
4846
          di.ax = -di.ax;
4847
          di.ay = -di.ay;
4848
        }
4849
      }
2055 jag 4850
      di.mod.am.bv.reverse ();
4851
      di.mod.fm.bv.reverse ();
2089 jag 4852
      if (di.chuck.yes) {
4853
        di.chuck.dir = -di.chuck.dir;
4854
        RESETCHUCKTRAILS(di)
4855
      }
2031 jag 4856
    }
4857
  } else cons << RED_PSD << eol;
4858
}
4859
 
2060 jag 4860
void din::reverse_drone_modulation () {
4861
  if (num_selected_drones) {
4862
    if (dinfo.revmod == 0) {
4863
      for (int i = 0; i < num_selected_drones; ++i) {
4864
        drone& di = *selected_drones[i];
4865
        di.mod.am.bv.reverse ();
4866
        di.mod.fm.bv.reverse ();
4867
      }
4868
    } else {
4869
      for (int i = 0; i < num_selected_drones; ++i) {
4870
        drone& di = *selected_drones[i];
4871
        beat2value* bvi [] = {0, &di.mod.am.bv, &di.mod.fm.bv};
4872
        bvi[dinfo.revmod]->reverse ();
4873
      }
4874
    }
4875
  } else cons << RED_PSD << eol;
4876
}
4877
 
2287 jag 4878
/*void copyis (drone& t, drone& s) {
2271 jag 4879
  t.is = s.is;
4880
  if (s.is == drone::BINAURAL) {
4881
    t.sol2 (&din0.drone_wave);
4882
    t.player2.set_wave (&t.sol2);
4883
  }
2287 jag 4884
}*/
2271 jag 4885
 
2273 jag 4886
void din::change_drone_sep (spinner<float>& s) {
4887
  if (num_selected_drones) {
4888
    float dhz = 0.0f, dsep = 0.0f;
4889
    for (int i = 0; i < num_selected_drones; ++i) {
4890
      drone& ds = *selected_drones[i];
4891
      dhz = s();
4892
      hz2step (dhz, dsep);
4893
      ds.sep += dsep;
2276 jag 4894
      if (MENU.sep0.state && ds.sep < 0) ds.sep = 0;
2273 jag 4895
      step2hz (ds.sep, dhz);
2310 jag 4896
      cons << GREEN << "Drone: " << i << ", separation = " << dhz << " Hz" << eol;
2273 jag 4897
      ds.update_pv = drone::EMPLACE;
4898
    }
4899
  } else {
4900
    cons << RED_PSD << eol;
4901
  }
4902
}
4903
 
2327 jag 4904
void powbeat (beat2value& bv, float p) {
4905
  float b = bv.get_bpm () * p;
4906
  bv.set_bpm (b);
4907
  cons << GREEN << " bpm = " << b << eol;
2292 jag 4908
}
4909
 
4910
 
4911
 
2055 jag 4912
/*
4913
  if (num_selected_drones) {
4914
    for (int i = 0; i < num_selected_drones; ++i) {
4915
      drone& ds = *selected_drones[i];
2031 jag 4916
    }
2055 jag 4917
  } else cons << RED_PSD << eol;
2031 jag 4918
 
2055 jag 4919
*/