Rev 2334 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
* din.cc
* DIN Is Noise is copyright (c) 2006-2025 Jagannathan Sampath
* DIN Is Noise is released under GNU Public License 2.0
* For more information, please visit https://dinisnoise.org/
*/
#include "main.h"
#include "din.h"
#include "console.h"
#include "solver.h"
#include "container.h"
#include "utils.h"
#include "input.h"
#include "color.h"
#include "random.h"
#include "command.h"
#include "delay.h"
#include "chrono.h"
#include "delay.h"
#include "tcl_interp.h"
#include "font.h"
#include "scale_info.h"
#include "ui_list.h"
#include "vector2d.h"
#include "keyboard_keyboard.h"
#include "defvelaccel.h"
#include "log.h"
#include <sstream>
#include <algorithm>
#define ENDER -1
#define LAUNCHLATER 1
extern string user_data_dir; // user data directory
extern console cons; // console
extern viewport view; // viewport
extern int mousex, mousey, mouseyy; // mouse pos
extern int lmb, rmb, mmb; // mouse button state
extern int LEFT, BOTTOM, RIGHT, TOP; // microtonal keyboard extents
extern int HEIGHT; // default number of volumes on the microtonal keyboard
extern int WIDTH; // default number of microtones in a range
extern int NUM_OCTAVES; // number of octaves the board spans
extern map<string, int> NOTE_POS; // interval name -> value, 1 - 1, 1# - 2, 2 - 3 etc
extern int SAMPLE_RATE; // sampling rate
extern map<string, float> INTERVALS; // interval name -> value
extern audio_out aout; // audio output
extern tcl_interp interpreter; // integrated tcl interpreter
extern int TRAILSIZE; // drone trail size (== number of trail points)
extern audio_clock clk; // audio clock
extern din din0; // microtonal-keyboard
extern float VOLUME; // volume of voice on microtonal-keyboard
extern curve_library wav_lib; // waveform library
extern float FRAME_TIME; // time per frame in seconds
extern int quit; // user wants to quit?
extern int line_height; // of text
extern keyboard_keyboard keybd2; // keyboard-keyboard
extern int IPS; // inputs per second
extern beat2value octave_shift; // octave shift over bpm
extern const float PI_BY_180;
extern const float PI;
extern mouse_slider mouse_slider0;
extern const char* s_drones;
extern float VOICE_VOLUME;
typedef std::list<mesh>::iterator mesh_iterator;
extern int doublebpm;
extern float BPM_MULT;
extern int BEATER;
// din::din () in eval.cc
void din::setup () {
dinfo.load ();
droneed.add (&drone_wave, &dronelis);
droneed.attach_library (&wav_lib);
wavsol (&wave);
wavplay.set_wave (&wavsol);
waved.add (&wave, &wavlis);
waved.attach_library (&wav_lib);
moded.attach_library (&gatlib);
gatr.setup ();
gatr.setswing (swing);
gatr.setaccent (accent);
BEATER = gated.ed;
gated.attach_library (&gatlib);
gated.add (gatr.crv, &gatrlis);
gated.add (&swing, &gatrlis);
gated.add (&accent, &gatrlis);
gated.bv.push_back (&gatr);
am_depth = 0;
fm_depth = 0;
fm.setup ();
am.setup ();
moded.add (fm.crv, &fmlis);
moded.add (am.crv, &amlis);
moded.bv.push_back (&fm);
moded.bv.push_back (&am);
fmlis.set (&fm);
amlis.set (&am);
gatrlis.set (&gatr);
dinfo.gravity.calc ();
}
void din::scale_loaded () {
int load_drones_too = 1, load_ranges_too = 1;
load_scale (load_drones_too, load_ranges_too);
}
void din::scale_changed () {
reset_all_ranges ();
}
void din::load_scale (int _load_drones_, int _load_ranges_) {
setup_ranges (NUM_OCTAVES, _load_ranges_);
if (_load_drones_) load_drones ();
refresh_all_drones ();
}
int din::load_ranges () {
string fname = user_data_dir + scaleinfo.name + ".ranges";
dlog << "<< loading ranges from: " << fname;
ifstream file (fname.c_str(), ios::in);
if (!file) {
dlog << "!!! couldnt load range pos from " << fname << ", will use defaults +++" << endl;
return 0;
}
string ignore;
file >> ignore >> NUM_OCTAVES;
int n; file >> ignore >> n;
create_ranges (n);
int l = LEFT, r, w, h;
for (int i = 0; i < num_ranges; ++i) {
range& R = ranges[i];
file >> w >> h;
r = l + w;
R.extents (l, BOTTOM, r, BOTTOM + h);
l = r;
file >> R.mod.active >>
R.fixed >>
R.mod.am.depth >> R.mod.am.bv.bpm >> R.mod.am.bv.now >> R.mod.am.bv.bps >> R.mod.am.initial >>
R.mod.fm.depth >> R.mod.fm.bv.bpm >> R.mod.fm.bv.now >> R.mod.fm.bv.bps >> R.mod.fm.initial;
R.notes[0].load (file) >> R.intervals[0];
R.notes[1].load (file) >> R.intervals[1];
R.fixed = range::CENTER;
}
dlog << ", done >>>" << endl;
return 1;
}
void din::save_ranges () {
string fname = user_data_dir + scaleinfo.name + ".ranges";
ofstream file (fname.c_str(), ios::out);
if (file) {
file << "num_octaves " << NUM_OCTAVES << endl;
file << "num_ranges " << num_ranges << endl;
for (int i = 0; i < num_ranges; ++i) {
range& r = ranges[i];
file << r.extents.width << spc << r.extents.height << spc << r.mod.active << spc
<< r.fixed << spc
<< 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
<< 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;
r.notes[0].save (file) << r.intervals[0] << spc;
r.notes[1].save (file) << r.intervals[1] << spc;
}
dlog << "+++ saved ranges in " << fname << " +++" << endl;
}
}
void din::setup_ranges (int last_num_octaves, int load) {
if (load) {
load_ranges ();
} else {
int last_num_ranges = num_ranges;
int ht = lastr->extents.height;
create_ranges (NUM_OCTAVES * scaleinfo.num_ranges);
set_range_width (last_num_ranges, last_range, WIDTH);
set_range_height (last_num_ranges, last_range, ht);
init_range_mod (last_num_ranges, last_range);
if (last_num_octaves < NUM_OCTAVES) calc_added_range_notes (last_num_octaves, last_num_ranges);
}
find_current_range ();
}
void din::reset_all_ranges () {
int lr = last_range;
int r0 = lr + 1;
create_ranges (NUM_OCTAVES * scaleinfo.num_ranges);
int r1 = last_range;
if (r1 > r0) {
set_range_width (r0, r1, WIDTH);
set_range_height (r0, r1, ranges[lr].extents.height);
init_range_mod (r0, r1);
}
calc_added_range_notes (0, 0);
find_current_range ();
find_visible_ranges ();
refresh_all_drones ();
}
void din::create_ranges (int n) {
ranges.resize (n);
initranpar (n);
}
void din::initranpar (int n) {
num_ranges = n;
last_range = max (0, num_ranges - 1);
firstr = &ranges [0];
lastr = &ranges [last_range];
clamp<int> (0, dinfo.sel_range, last_range);
MENU.sp_range.set_limits (0, last_range);
}
void din::calc_added_range_notes (int p, int r) {
int rn = r;
for (; p < NUM_OCTAVES; ++p) {
for (int i = 0, j = 1; i < scaleinfo.num_ranges; ++i, ++j) {
range& R = ranges[r++];
note& n0 = R.notes[0];
note& n1 = R.notes[1];
n0.scale_pos = i;
n1.scale_pos = j;
n0.octave = n1.octave = p;
string& i0 = R.intervals[0];
string& i1 = R.intervals[1];
i0 = scaleinfo.notes[i];
i1 = scaleinfo.notes[j];
R.calc (scaleinfo);
n0.set_name (i0, scaleinfo.western);
n1.set_name (i1, scaleinfo.western);
}
}
if (rn) {
range &R1 = ranges[rn-1], &R = ranges[rn];
// last note of existing ranges should be = to first note of first new range
if (!equals (R.notes[0].hz, R1.notes[1].hz)) {
R.notes[0]=R1.notes[1];
R.intervals[0]=R1.intervals[1];
R.delta_step = R.notes[1].step - R.notes[0].step;
}
}
}
void din::init_range_mod (int s, int t) {
for (int i = s; i <= t; ++i) ranges[i].init_mod ();
}
void din::set_range_width (int ran, int sz) {
range& R = ranges[ran];
int delta = sz - R.extents.width;
R.extents (R.extents.left, R.extents.bottom, R.extents.left + sz, R.extents.top);
R.mod.fm.initial = R.extents.width;
R.mod.fm.bv.now = 0;
for (int i = ran + 1; i < num_ranges; ++i) {
range& Ri = ranges[i];
Ri.extents (Ri.extents.left + delta, Ri.extents.bottom, Ri.extents.right + delta, Ri.extents.top);
}
refresh_drones (ran, last_range);
find_visible_ranges ();
}
void din::set_range_width (int s, int t, int sz) {
int r, l;
if (s < 1) r = LEFT; else r = ranges[s-1].extents.right;
for (int i = s; i <= t; ++i) {
l = r;
r = l + sz;
range& R = ranges[i];
R.extents (l, R.extents.bottom, r, R.extents.top);
R.mod.fm.initial = R.extents.width;
R.mod.fm.bv.now = 0;
}
refresh_drones (s, t);
find_visible_ranges ();
}
void din::set_range_height (int s, int t, int h) {
for (int i = s; i <= t; ++i) {
range& R = ranges[i];
R.extents (R.extents.left, BOTTOM, R.extents.right, BOTTOM+h);
R.mod.am.initial = h;
R.mod.am.bv.now = 0;
}
refresh_drones (s, t);
}
void din::set_range_height (int r, int h) {
range& R = ranges[r];
R.extents (R.extents.left, BOTTOM, R.extents.right, BOTTOM + h);
R.mod.am.initial = h;
R.mod.am.bv.now = 0;
refresh_drones (r);
}
void din::default_range_to_all (int h) {
extern multi_curve ran_width_crv, ran_height_crv;
if (h) {
set_range_height (0, last_range, HEIGHT);
ran_height_crv.load ("range-height.crv.default");
}
else {
set_range_width (0, last_range, WIDTH);
ran_width_crv.load ("range-width.crv.default");
}
}
void din::selected_range_to_all (int h) {
if (h)
set_range_height (0, last_range, ranges[dinfo.sel_range].extents.height);
else
set_range_width (0, last_range, ranges[dinfo.sel_range].extents.width);
}
void din::default_range_to_selected (int h) {
if (h)
set_range_height (dinfo.sel_range, HEIGHT);
else
set_range_width (dinfo.sel_range, WIDTH);
}
int din::range_left_changed (int r, int dx, int mr) {
int valid = 0;
range& R = ranges [r];
int oldleft = R.extents.left;
if (dx != 0) {
int newleft = oldleft + dx;
valid = newleft < R.extents.right ? 1 : 0;
if (valid) {
if (adjustranges.others) {
R.extents (newleft, R.extents.bottom, R.extents.right, R.extents.top);
for (int i = 0; i < r; ++i) {
range& ir = ranges [i];
ir.extents (ir.extents.left + dx, ir.extents.bottom, ir.extents.right + dx, ir.extents.top);
}
} else {
int j = r - 1;
if (j > -1) {
range& rl = ranges[j];
box<int>& rle = rl.extents;
if (rle.left < newleft) {
R.extents (newleft, R.extents.bottom, R.extents.right, R.extents.top);
rle (rle.left, rle.bottom, R.extents.left, rle.top);
}
} else {
R.extents (newleft, R.extents.bottom, R.extents.right, R.extents.top);
}
}
if (mr) { // reset modulation
R.mod.fm.initial = R.extents.width;
R.mod.fm.bv.now = 0;
}
if (R.mod.active == 0) R.print_hz_per_pixel ();
}
LEFT = ranges[0].extents.left;
}
return valid;
}
int din::range_right_changed (int r, int dx, int mr) {
int valid = 0;
range& R = ranges [r];
int oldright = R.extents.right;
if (dx != 0) {
int newright = oldright + dx;
valid = newright > R.extents.left ? 1 : 0;
if (valid) {
if (adjustranges.others) {
R.extents (R.extents.left, R.extents.bottom, newright, R.extents.top);
for (int i = r + 1; i < num_ranges; ++i) {
range& ir = ranges [i];
ir.extents (ir.extents.left + dx, ir.extents.bottom, ir.extents.right + dx, ir.extents.top);
}
} else {
int j = r + 1;
if (j < num_ranges) {
range& rr = ranges[j];
box<int>& rre = rr.extents;
if (newright < rre.right) {
R.extents (R.extents.left, R.extents.bottom, newright, R.extents.top);
rre (newright, rre.bottom, rre.right, rre.top);
}
} else {
R.extents (R.extents.left, R.extents.bottom, newright, R.extents.top);
}
}
if (mr) { // reset modulation
R.mod.fm.initial = R.extents.width;
R.mod.fm.bv.now = 0;
}
if (R.mod.active == 0) R.print_hz_per_pixel ();
}
}
return valid;
}
void din::calc_all_range_notes () {
int r = 0;
for (int i = 0; i < num_ranges; ++i) ranges[r++].calc (scaleinfo);
}
void din::tonic_changed () {
all_notes.set_tonic (scaleinfo.tonic);
calc_all_range_notes ();
refresh_all_drones ();
notate_all_ranges ();
}
void din::notate_all_ranges () {
extern int NOTATION;
int western = scaleinfo.western;
switch (NOTATION) {
case WESTERN:
extern const char* WESTERN_FLAT [];
for (int i = 0; i < num_ranges; ++i) {
range& ri = ranges [i];
string i0 = ri.intervals[0], i1 = ri.intervals[1];
int ii0 = NOTE_POS[i0], ii1 = NOTE_POS[i1];
int kii0 = (western + ii0) % 12;
int kii1 = (western + ii1) % 12;
ri.notes[0].set_name (WESTERN_FLAT[kii0]);
ri.notes[1].set_name (WESTERN_FLAT[kii1]);
}
break;
case NUMERIC:
for (int i = 0; i < num_ranges; ++i) {
range& ri = ranges [i];
ri.notes[0].set_name (ri.intervals[0]);
ri.notes[1].set_name (ri.intervals[1]);
}
break;
default:
extern map<string, string> INT2IND;
for (int i = 0; i < num_ranges; ++i) {
range& ri = ranges [i];
ri.notes[0].set_name (INT2IND[ri.intervals[0]]);
ri.notes[1].set_name (INT2IND[ri.intervals[1]]);
}
}
}
void din::mouse2tonic () {
// set mouse at tonic
range& r = ranges[scaleinfo.notes.size () - 1]; // range of middle tonic
int wx = r.extents.left;
if (wx >= 0 && wx <= view.xmax) {
warp_mouse (wx, mousey);
MENU.screen_mousex = wx;
MENU.screen_mousey = mousey;
}
}
float din::get_note_value (const string& s) {
return scaleinfo.intervals[s];
}
void din::tuning_changed () {
scaleinfo.intervals = INTERVALS;
calc_all_range_notes ();
refresh_all_drones ();
}
void din::save () {
save_ranges ();
save_drones ();
wave.save ("microtonal-keyboard-waveform.crv");
swing.save ("swing.crv");
accent.save ("accent.crv");
scaleinfo.save_scale ();
dinfo.save ();
}
din::~din () {
if (dvap) delete[] dvap;
if (dap) delete[] dap;
if (dcol) delete[] dcol;
if (con_pts) delete[] con_pts;
if (con_clr) delete[] con_clr;
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) delete *i;
for (int i = 0, j = drone_pendulums.size (); i < j; ++i) {
group* grp = drone_pendulums[i];
if (grp) delete grp;
}
dlog << "--- destroyed microtonal-keyboard ---" << endl;
}
void din::sample_rate_changed () {
for (int i = 0; i < num_ranges; ++i) ranges[i].sample_rate_changed ();
beat2value* bv [] = {&fm, &am, &gatr, &octave_shift};
for (int i = 0; i < 4; ++i) bv[i]->set_bpm (bv[i]->bpm);
select_all_drones ();
change_drone_bpm (modulator::FM, 0);
change_drone_bpm (modulator::AM, 0);
update_drone_tone ();
}
void din::samples_per_channel_changed () {
wavplay.realloc ();
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone& di = *(*i);
di.player.realloc ();
di.update_pv = drone::EMPLACE;
}
}
void din::load_drones () {
string fdrone = user_data_dir + scaleinfo.name + ".drone";
ifstream file (fdrone.c_str(), ios::in);
drones.clear ();
rising = falling = 0;
if (!file) return; else {
string ignore;
num_drones = 0;
file >> ignore >> drone::UID;
file >> ignore >> num_drones;
print_num_drones ();
file >> ignore >> drone::MASTERVOLUME;
dlog << "<<< loading " << num_drones << " drones from: " << fdrone;
int T = 0;
for (int i = 0; i < num_drones; ++i) {
drone* pdi = new drone;
drone& di = *pdi;
file >> ignore >> di.id;
file >> ignore >> di.is;
file >> ignore >> di.cx >> di.cy >> di.posafxvel.pt.x >> di.posafxvel.pt.y >> di.posafxvel.yes;
file >> ignore >> di.player.x >> di.vol;
file >> ignore >> di.r >> di.g >> di.b;
//file >> ignore >> di.arrow.u >> di.arrow.v;
file >> ignore >> di.arrow;
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;
di.mod.am.calcdir (di);
di.mod.fm.calcdir (di);
file >> ignore >> di.trail.total; if (T < di.trail.total) T = di.trail.total;
file >> di.handle_size;
file >> ignore >> di.orbiting;
file >> ignore >> di.V >> di.A >> di.vx >> di.vy >> di.vrev >> di.ax >> di.ay;
di.modv.val = di.V;
file >> ignore >> di.attractor;
if (di.attractor) {
int n = di.attractor;
for (int i = 0; i < n; ++i) {
attractee ae;
file >> ae.id;
di.attractees.push_back (ae);
}
attractors.push_back (pdi);
}
file >> ignore >> di.launcher;
if (di.launcher) {
float tt; file >> tt >> di.lpm >> di.dpl >> di.gen;
di.launch_every.triggert = tt;
di.launch_every.startt = ui_clk ();
launchers.push_back (pdi);
} else {
extern void initlaunch (drone*);
initlaunch (pdi);
}
file >> ignore >> di.num_targets;
if (di.num_targets) {
file >> ignore >> di.cur_target;
vector<drone*>& targets = di.targets;
targets.clear ();
for (int i = 0; i < di.num_targets; ++i) {
uintptr_t pt; file >> pt;
targets.push_back ((drone*) pt);
}
}
file >> ignore >> di.tracking;
if (di.tracking) {
uintptr_t id; file >> id;
di.tracked_drone = (drone *) id;
trackers.push_back (pdi);
}
file >> ignore >> di.gravity;
if (di.gravity) gravitated.push_back (pdi);
uintptr_t pt; file >> ignore >> pt;
di.target = (drone *) pt;
if (di.target) satellites.push_back (pdi);
file >> ignore >> di.reincarnate;
file >> ignore >> di.birth;
if (di.birth != -1) {
float elapsed = di.birth;
di.birth = ui_clk () - elapsed;
}
file >> ignore >> di.life;
file >> ignore >> di.insert;
file >> ignore >> di.snap;
file >> ignore >> di.frozen;
if (di.frozen) {
di.frozen = 1;
di.froze_at = ui_clk ();
di.set_pos (di.cx + di.mod.fm.result, di.cy + di.mod.am.result);
} else {
di.set_pos (di.cx, di.cy);
di.froze_at = -1;
}
drones.push_back (pdi);
di.state = drone::RISING;
risers.push_back (pdi);
++rising;
di.fdr.set (0.0f, 1.0f, 1, MENU.riset());
float smp, spr;
file >> ignore >> smp >> spr;
di.nsr.set_samples (smp);
di.nsr.set_spread (spr);
file >> ignore;
drone::proc_conn [pdi] = false;
long long cd;
double mag;
while (file.eof () == 0) {
file >> cd;
if (cd == ENDER)
break;
else {
di.connections.push_back ((drone *)cd);
file >> mag; di.mags.push_back (mag);
++di.nconn;
++totcon;
}
}
{
float start, end, amount;
file >> ignore >> start >> end >> amount;
di.gab.set (start, end);
di.gab.amount = amount;
}
{
file >> ignore >> di.chuck.yes;
if (di.chuck.yes) file >> di.chuck;
}
} // load complete
trail_t::alloc (T);
_2totcon = 2 * totcon;
alloc_conns ();
// load the meshes
//
map<int, drone*> dmap;
file >> ignore >> meshh.num;
if (meshh.num) {
for (int m = 0; m < meshh.num; ++m) {
mesh a_mesh;
file >> ignore >> a_mesh.r >> a_mesh.g >> a_mesh.b;
int num_polys;
file >> ignore >> num_polys;
for (int i = 0; i < num_polys; ++i) {
drone* drones[4] = {0}; // 4 drones to a poly
file >> ignore;
for (int p = 0; p < 4; ++p) {
int id; file >> id;
drone* did = dmap [id];
if (did == 0) {
did = get_drone (id);
dmap[id] = did;
}
drones[p] = did;
}
a_mesh.add_poly (drones[0], drones[1], drones[2], drones[3]);
}
meshes.push_back (a_mesh);
}
}
file >> ignore >> meshh.draw;
// load drone tracked by gravity
gravity_t& grav = dinfo.gravity;
int bid = 0, tid = 0;
file >> ignore >> bid >> tid;
if (bid) grav.tracked_drone[0] = get_drone (bid);
if (tid) grav.tracked_drone[1] = get_drone (tid);
load_selected_drones (file);
load_drone_pendulum_groups (file);
// convert attractees
for (drone_iterator i = attractors.begin (), j = attractors.end(); i != j; ++i) {
drone& di = *(*i);
for (list<attractee>::iterator iter = di.attractees.begin (), jter = di.attractees.end (); iter != jter; ++iter) {
attractee& ae = *iter;
ae.d = get_drone (ae.id);
}
}
// convert tracked drone
for (drone_iterator i = trackers.begin (), j = trackers.end(); i != j; ++i) {
drone& di = *(*i);
di.tracked_drone = get_drone ((uintptr_t) di.tracked_drone);
}
// convert targets and connections
for (drone_iterator i = drones.begin (), j = drones.end (); i != j; ++i) {
drone& di = *(*i);
if (di.num_targets) for (int i = 0; i < di.num_targets; ++i) di.targets[i] = get_drone ((uintptr_t) di.targets[i]);
if (di.nconn) for (drone_iterator p = di.connections.begin (), q = di.connections.end (); p != q; ++p) *p = get_drone ((uintptr_t) *p);
if (di.chuck.yes) {
if (di.chuck.sun) di.chuck.sun = get_drone ((uintptr_t) di.chuck.sun);
if (di.chuck.sat) di.chuck.sat = get_drone ((uintptr_t) di.chuck.sat);
}
}
// convert satellites
for (drone_iterator i = satellites.begin (), j = satellites.end (); i != j; ++i) {
drone& di = *(*i);
di.target = get_drone ((uintptr_t) di.target);
}
update_drone_players ();
dlog << ", done. >>>" << endl;
}
}
void din::save_drones () {
drone_wave.save ("drone.crv");
string drone_file = user_data_dir + scaleinfo.name + ".drone";
ofstream file (drone_file.c_str(), ios::out);
if (file) {
file << "uid " << drone::UID << endl;
file << "num_drones " << num_drones << endl;
file << "master_volume " << drone::MASTERVOLUME << endl;
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone& di = *(*i);
file << "id " << di.id << endl;
file << "is " << di.is << endl;
file << "positon " << di.cx << spc << di.cy << spc << di.posafxvel.pt.x << spc << di.posafxvel.pt.y << spc << di.posafxvel.yes << endl;
file << "wavepos " << di.player.x << spc << di.vol << endl;
file << "color " << di.r << spc << di.g << spc << di.b << endl;
file << "arrow " << di.arrow << endl;
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;
file << "trail+handle " << di.trail.total << spc << di.handle_size << endl;
file << "orbiting " << di.orbiting << endl;
file << "vel+accel " << di.V << spc << di.A << spc << di.vx << spc << di.vy << spc << di.vrev << spc << di.ax << spc << di.ay << endl;
file << "attractor " << di.attractor;
if (di.attractor) { // save attractees
for (list<attractee>::iterator iter = di.attractees.begin (), jter = di.attractees.end (); iter != jter; ++iter) {
attractee& ae = *iter;
file << spc << ae.id; // only save unique id, rebuild on load
}
}
file << endl;
file << "launcher " << di.launcher;
if (di.launcher)
file << spc << di.launch_every.triggert << spc << di.lpm << spc << di.dpl << spc << di.gen << endl;
else
file << endl;
file << "launcher_targets " << di.num_targets << endl;
if (di.num_targets) {
file << "cur_target " << di.cur_target;
for (int t = 0; t < di.num_targets; ++t) {
drone* pdt = di.targets[t];
file << spc << pdt->id;
}
file << endl;
}
file << "tracking " << di.tracking;
if (di.tracking) file << spc << di.tracked_drone->id << endl; else file << endl;
file << "gravity " << di.gravity << endl;
if (di.target) {
file << "satellite_target " << di.target->id << endl;
} else file << "satellite_target 0" << endl;
file << "reincarnate " << di.reincarnate << endl;
if (di.birth != -1)
file << "birth " << (ui_clk() - di.birth) << endl;
else
file << "birth -1" << endl;
file << "life-time " << di.life << endl;
file << "insert-time " << di.insert << endl;
file << "snap " << di.snap << endl;
file << "frozen " << di.frozen << endl;
file << "noiser ";
file << di.nsr << endl;
file << "connections ";
if (di.nconn) {
list<double>::iterator mi = di.mags.begin ();
for (drone_iterator p = di.connections.begin(), q = di.connections.end(); p != q; ++p, ++mi) {
file << (*p)->id << spc << *mi << spc;
}
}
file << ENDER << endl;
file << "gab " << di.gab.start << spc << di.gab.end << spc << di.gab.amount << endl;
file << "chuck " << di.chuck.yes << spc;
if (di.chuck.yes) file << di.chuck << endl; else file << endl;
}
file << "num_meshes " << meshh.num << endl;
if (meshh.num) {
for (mesh_iterator m = meshes.begin (), n = meshes.end(); m != n; ++m) { // save meshes
mesh& mi = *m;
file << "color " << mi.r << spc << mi.g << spc << mi.b << endl;
file << "num_polys " << mi.num_polys << endl;
for (poly_iterator p = mi.polys.begin (), q = mi.polys.end (); p != q; ++p) { // save polys
poly& pp = *p;
file << "poly";
for (int r = 0; r < 4; ++r) file << spc << pp.drones[r]->id; // save drone id, on reload we will point to right drone
file << endl;
}
}
}
file << "draw_meshes " << meshh.draw << endl;
gravity_t& grav = dinfo.gravity;
file << "drone_tracked_by_gravity " ;
drone* basedrone = grav.tracked_drone[0]; if (basedrone) file << basedrone->id << spc; else file << "0 ";
drone* tipdrone = grav.tracked_drone[1]; if (tipdrone) file << tipdrone->id << endl; else file << '0' << endl;
save_selected_drones (file);
save_drone_pendulum_groups (file);
dlog << "+++ saved " << num_drones << " drones in: " << drone_file << " +++" << endl;
}
}
void din::save_drone_pendulum_groups (ofstream& file) {
int ng = drone_pendulums.size ();
file << "groups " << ng << spc;
for (int i = 0; i < ng; ++i) {
drone_pendulum_group& dpg = *drone_pendulums[i];
file << dpg.n << spc << dpg.orient << spc << dpg.depth << spc;
vector<drone*> dpgd = dpg.drones;
for (int j = 0, k = dpg.n; j < k; ++j) {
drone* dj = dpgd[j];
file << dj->id << spc;
}
}
file << endl;
}
void din::load_drone_pendulum_groups (ifstream& file) {
string ignore;
int ng; file >> ignore >> ng;
if (ng) {
drone_pendulums.resize (ng);
for (int i = 0; i < ng; ++i) {
drone_pendulum_group* pdpg = new drone_pendulum_group ();
drone_pendulum_group& dpg = *pdpg;
drone_pendulums[i] = pdpg;
file >> dpg.n >> dpg.orient >> dpg.depth;
vector<drone*>& dpgd = dpg.drones;
dpgd.resize (dpg.n);
int did;
for (int j = 0, k = dpg.n; j < k; ++j) {
file >> did;
dpgd[j] = get_drone (did);
}
}
}
}
void din::update_drone_tone () {
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone& di = *(*i);
range& r = ranges[di.range];
di.step = (1 - di.pos) * r.notes[0].step + di.pos * r.notes[1].step;
di.update_pv = drone::EMPLACE;
}
}
void din::refresh_all_drones () {
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone& di = *(*i);
di.set_pos (di.x, di.y);
}
}
void din::refresh_drones (int r1, int r2) {
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone& di = *(*i);
if ((di.range >= r1) && (di.range <= r2)) di.set_pos (di.x, di.y);
}
}
void din::refresh_drones (int r) {
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone& di = *(*i);
if (di.range == r) di.set_pos (di.x, di.y);
}
}
void din::update_drone_ranges () {
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone& di = *(*i);
if (di.range > last_range) di.range = last_range;
}
}
void din::set_drone (drone& dd, float wx, float wy) {
// create drone at position
dd.cx = dd.posafxvel.pt.x = wx;
dd.cy = dd.posafxvel.pt.y = wy;
// install waveform, pitch and volume
//
dd.sol (&drone_wave);
dd.player.set_wave (&dd.sol);
if (dd.binaural) {
dd.sol2 (&drone_wave);
dd.player2.set_wave (&dd.sol2);
}
// prep to rise the drones
dd.fdr.set (0.0f, 1.0f, 1, MENU.riset());
dd.set_pos (dd.cx, dd.cy);
dd.state = drone::RISING;
risers.push_back (&dd);
++rising;
drone::proc_conn [&dd] = false;
dd.setcolor ();
}
void din::movedrone (drone& dd) {
float cx = dd.cx, cy = dd.cy;
if (!SHIFT) cx += delta_mousex;
if (!CTRL) cy -= delta_mousey;
dd.set_center (cx, cy);
dd.update_pv = drone::EMPLACE;
if (dd.chuck.yes) RESETCHUCKTRAILS(dd)
ec = ⅆ
}
void din::color_selected_drones () {
if (num_selected_drones) {
int last = num_selected_drones - 1;
float _1bylast = 1.0f / last;
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
get_color::data.p = i * _1bylast;
ds.setcolor ();
}
} else cons << RED_PSD << eol;
}
void din::mortalize_drones (int reincarnate) {
if (num_selected_drones) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
ds.birth = ui_clk ();
ds.reincarnate = reincarnate;
}
} else cons << RED_PSD << eol;
}
void din::immortalize_drones () {
if (num_selected_drones) {
for (int i = 0; i < num_selected_drones; ++i) {
drone* pds = selected_drones[i];
pds->birth = -1;
pds->reincarnate = 0;
if (pds->gravity) {
pds->gravity = 0;
erase (gravitated, pds);
erase (satellites, pds);
}
}
} else cons << RED_PSD << eol;
}
void din::delete_drone (drone& ds) {
drone* pds = &ds;
if (ds.state == drone::RISING) if (erase (risers, pds)) --rising;
if (push_back (fallers, pds)) {
++falling;
ds.state = drone::FALLING;
ds.fdr.set (ds.fdr.alpha, 0.0f, 1, MENU.fallt());
}
}
void din::delete_selected_drones () {
if (num_selected_drones) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
if (ds.reincarnate) ds.reincarnate = 0;
if (ds.state == drone::FALLING)
ds.fdr.retime (MENU.fallt());
else
delete_drone (ds);
}
} else cons << RED_PSD << eol;
}
int din::select_all_drones () {
clear_selected_drones ();
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone* pdi = *i;
pdi->sel = 1;
selected_drones.push_back (pdi);
}
print_selected_drones ();
return 1;
}
int din::delete_all_drones () {
select_all_drones ();
thaw_drones ();
delete_selected_drones ();
return 1;
}
int din::select_launchers () {
CLEAR_SELECTED_DRONES
for (drone_iterator i = launchers.begin(), j = launchers.end(); i != j; ++i) {
drone* pdi = *i;
add_drone_to_selection (pdi);
}
print_selected_drones ();
return 1;
}
void din::clear_selected_drones () {
for (int i = 0; i < num_selected_drones; ++i) selected_drones[i]->sel = 0;
selected_drones.clear ();
num_selected_drones = 0;
}
void din::orbit_selected_drones () { // attach selected drones to attractor
if (num_selected_drones > 1) {
int last = num_selected_drones - 1;
drone* p_att = selected_drones [last]; // last selected drone is attractor
push_back (attractors, p_att);
drone& att = *p_att;
list<attractee>& lae = att.attractees;
for (int i = 0; i < last; ++i) { // other drones are attractees
drone* pae = selected_drones [i];
if (!pae->orbiting) {
attractee ae (pae->id, pae);
if (push_back (lae, ae)) {
++att.attractor;
pae->orbiting = 1;
}
} else {
cons << RED << "Drone orbits already, ignored!" << eol;
}
}
} else cons << RED_A2D << ". Drones will orbit around the last drone!" << eol;
}
void din::remove_attractee (drone* d) {
for (drone_iterator i = attractors.begin(); i != attractors.end();) { // run thru list of attractors
drone* p_att = *i;
drone& att = *p_att;
list<attractee>& lae = att.attractees;
int erased = 0;
for (list<attractee>::iterator iter = lae.begin (); iter != lae.end();) { // run thru list of attractees
attractee& ae = *iter;
if (ae.d != d)
++iter;
else { // remove attractee
lae.erase (iter);
if (--att.attractor == 0) {
i = attractors.erase (i);
erased = 1;
}
break;
}
}
if (!erased) ++i;
}
}
void din::set_drones_under_gravity () {
if (num_selected_drones) {
for (int i = 0; i < num_selected_drones; ++i) {
drone* pdg = selected_drones[i];
if (pdg->y < BOTTOM) pdg->gravity = -1; else pdg->gravity = 1;
push_back (gravitated, pdg);
pdg->birth = ui_clk ();
}
} else cons << RED_PSD << eol;
}
void din::move_drones_under_gravity () {
float modv = 1.0f;
for (drone_iterator i = gravitated.begin(), j = gravitated.end(); i != j; ++i) { // run thru list of drones driven by gravity
drone* pdi = *i;
drone& di = *pdi; // get the ith drone
if (di.frozen == 0) {
// current position
di.xi = di.x;
di.yi = di.y;
// calculate new position along its velocity
modv = di.modv ();
di.set_pos (di.x + modv * di.vx, di.y + modv * di.vy);
// acceleration is due to gravity!
di.ax = dinfo.gravity.gx;
di.ay = di.gravity * dinfo.gravity.gy; // reverse gravity effect if drone launched below 0 volume line
// update velocity ie we accelerate
di.vx += di.ax;
di.vy += di.ay;
// bounce when reached bottom line of microtonal keyboard
di.bounces.max = MENU.sp_bounces ();
if ((di.bounces.max != -1) && (di.target == 0) && ((di.gravity == 1 && di.y <= BOTTOM) || (di.gravity == -1 && di.y >= BOTTOM)) ) {
if (++di.bounces.n > di.bounces.max) {
delete_drone (di);
} else {
float dx = di.x - di.xi;
if (dx == 0.0f) { // slope is infinite
di.set_pos (di.x, BOTTOM);
} else { // slope is available
float dy = di.y - di.yi;
if (dy == 0.0f)
di.set_pos (di.x, BOTTOM);
else {
float m = dy * 1.0f / dx;
di.set_pos (di.xi + (BOTTOM - di.yi) / m, BOTTOM);
}
}
float reduction = MENU.sp_rebound() / 100.0;
int style = dinfo.bounce.style;
if (style == din_info::bouncet::RANDOM) style = get_rand_bit ();
if (style == din_info::bouncet::BACK) di.vx *= -reduction;
di.vy *= -reduction;
}
}
di.move_center ();
}
}
}
void din::set_targets () {
if (num_selected_drones == 0) {
cons << RED << "Select a launcher and drones to target" << eol;
return;
}
drone* d0 = selected_drones[0];
if (d0->launcher == 0) make_launcher (d0); // first drone is launcher
d0->clear_targets ();
if (num_selected_drones == 1) {
d0->targets.push_back (d0);
d0->num_targets = d0->targets.size ();
cons << GREEN << "Selected drone is a launcher and the target too!" << eol;
return;
}
for (int i = 1; i < num_selected_drones; ++i) { // make other drones in selection the targets
drone* di = selected_drones[i];
vector<drone*> targets = d0->targets;
vector<drone*>::iterator te = targets.end ();
vector<drone*>::iterator f = find (targets.begin (), targets.end (), di);
if (f == te) d0->targets.push_back (di);
}
d0->num_targets = d0->targets.size ();
cons << GREEN << "First drone is launcher, it targets " << d0->num_targets << " other drones" << eol;
}
void din::remove_drone_from_targets (drone* T) {
for (drone_iterator i = satellites.begin(), j = satellites.end(); i != j;) { // remove satellites going towards T
drone* pdi = *i;
drone& di = *pdi;
if (di.target == T) {
di.target = 0;
i = satellites.erase (i);
j = satellites.end ();
} else ++i;
}
for (drone_iterator i = launchers.begin(), j = launchers.end (); i != j; ++i) { // remove target from launcher
drone* pdi = *i;
vector<drone*>& targets = pdi->targets;
vector<drone*>::iterator te = targets.end (), f = find (targets.begin (), te, T);
if (f != te) {
targets.erase (f);
pdi->num_targets = targets.size ();
clamp (0, pdi->cur_target, pdi->num_targets - 1);
}
}
}
void din::clear_targets () {
int n = 0;
for (int i = 0; i < num_selected_drones; ++i) {
drone* pdi = selected_drones[i];
if (pdi->num_targets) {
pdi->clear_targets ();
++n;
}
}
if (n) cons << GREEN << "Cleared targets of " << n << s_drones << eol; else cons << RED << "No targets found!" << eol;
}
void din::kill_old_drones () {
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone& di = *(*i);
if ((di.birth != -1) && !di.frozen && (di.state != drone::FALLING)) {
double elapsed = ui_clk() - di.birth;
if (elapsed >= di.life) delete_drone (di);
}
}
}
void din::carry_satellites_to_orbit () { // satellites is a bunch of drones to be inserted into orbit around another drone
for (drone_iterator i = satellites.begin(), j = satellites.end(); i != j;) { // run thru satellites to be inserted into circular orbit
drone* pdi = *i;
drone& di = *pdi;
if (di.frozen == 0) {
drone& dt = *di.target; // the target we want the satellite to orbit
unit_vector (di.ax, di.ay, dt.sx - di.x, dt.y - di.y); // centripetal acceleration ie unit vector joining satellite & target
float pvx = -di.ay, pvy = di.ax; // velocity to insert into orbit (just perpendicular to centripetal acceleration so its centrifugal velocity)
double now = ui_clk(), delta = now - di.birth;
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!
int insertnow = 0;
if (alpha >= 1.0f) {
alpha = 1.0f;
insertnow = 1;
}
float ivx = di.vx + alpha * (pvx - di.vx);
float ivy = di.vy + alpha * (pvy - di.vy); // interpolate current velocity and insertion velocity
di.vx = ivx + dinfo.gravity.gx;
di.vy = ivy + di.gravity * dinfo.gravity.gy;
di.modv.val = di.V;
float newx = di.x + di.V * di.vx + di.A * di.ax;
float newy = di.y + di.V * di.vy + di.A * di.ay; // update drone position
di.xi = di.x;
di.yi = di.y;
di.set_pos (newx, newy);
di.move_center ();
if (insertnow) { // insert drone into orbit now!
list<attractee>& lae = dt.attractees;
lae.push_back (attractee (pdi->id, pdi));
push_back (attractors, di.target);
di.target = 0; // inserted into orbit, so clear
++dt.attractor;
i = satellites.erase (i); j = satellites.end (); // no longer a satellite we need to insert
}
++i;
} else ++i;
}
}
void din::toggle_launchers () {
if (num_selected_drones == 0) {
cons << RED_PSD << eol;
return;
}
int nl = 0, nd = 0;
for (int i = 0; i < num_selected_drones; ++i) {
drone* pdi = selected_drones[i];
drone& di = *pdi;
di.launcher = !di.launcher;
if (di.launcher) {
di.launch_every.start (di.launch_every.triggert); // instant launch
launchers.push_back (pdi);
++nl;
} else {
erase (launchers, pdi);
++nd;
}
}
cons << GREEN << "Launching from " << nl << " drones, Stopped Launching from " << nd << s_drones << eol;
}
void din::make_launcher (drone* pl, int l8r) {
pl->launcher = 1;
launchers.push_back (pl);
alarm_t& le = pl->launch_every;
if (l8r)
le.start ();
else
le.start (le.triggert);
}
void din::make_launchers () {
if (num_selected_drones == 0) {
cons << RED_PSD << eol;
return;
}
int nl = 0;
for (int i = 0; i < num_selected_drones; ++i) {
drone* pdi = selected_drones[i];
if (pdi->launcher == 0) {
make_launcher (pdi);
++nl;
}
}
cons << GREEN << "Made " << nl << " launchers" << eol;
}
void din::destroy_launchers () {
if (num_selected_drones == 0) {
cons << RED_PSD << eol;
return;
}
int nl = 0;
for (int i = 0; i < num_selected_drones; ++i) {
drone* pdi = selected_drones[i];
drone& di = *pdi;
if (di.launcher) {
di.launcher = 0;
erase (launchers, pdi);
if (di.tracking) {
di.tracking = 0;
di.tracked_drone = 0;
erase (trackers, pdi);
}
++nl;
}
}
if (nl) cons << GREEN << "Stopped launching from " << nl << s_drones << eol; else cons << RED << "No drone launchers found!" << eol;
}
void din::seloncre (drone* d) {
if (dinfo.seloncre) {
d->sel = 1;
selected_drones.push_back (d);
print_selected_drones ();
}
}
drone* din::add_drone (float wx, float wy, int fromlauncher) {
drone* newdrone = new drone (wy);
seloncre (newdrone);
drones.push_back (newdrone);
++num_drones;
print_num_drones ();
set_drone (*newdrone, wx, wy);
if (!fromlauncher && !drone::anchored) balloon (newdrone);
return newdrone;
}
void din::balloon (drone* d) {
d->reincarnate = 0;
d->setlife (MENU.lifetime());
if (d->y < BOTTOM) d->gravity = -1; else d->gravity = 1;
gravitated.push_back (d);
d->birth = ui_clk ();
}
void din::launch_drones () {
list<drone*> l2;
int n2 = 0;
static const int nega [] = {1, -1};
for (drone_iterator i = launchers.begin(), j = launchers.end(); i != j; ++i) {
drone* pdi = *i;
drone& di = *pdi;
if (!di.frozen && di.launch_every (ui_clk())) { // time to launch a drone
for (int p = 0, q = di.dpl; p < q; ++p) {
#define CALLEDFROMLAUNCHER 1
drone* newdronep = add_drone (di.x, di.y, CALLEDFROMLAUNCHER);
drone& newdrone = *newdronep;
newdrone.launched_by = pdi;
if (newdrone.y < BOTTOM)
newdrone.gravity = -1;
else
newdrone.gravity = 1; // reverse gravity vector if launched below microtonal keyboard
newdrone.is = di.is;
// copyis (newdrone, di);
newdrone.setcolor (di, 0.5f);
// init velocity/speed
if (drone::v0.mag.rndrd) newdrone.V = drone::v0.mag.rd () * di.V; else newdrone.V = di.V;
int dir = nega [MENU.dva.neg.state];
newdrone.vx = dir * di.vx;
newdrone.vy = dir * di.vy;
if (drone::v0.rndrot) rotate_vector (newdrone.vx, newdrone.vy, drone::v0.rotrd());
// init acceleration
if (drone::a0.mag.rndrd) newdrone.A = drone::a0.mag.rd () * di.V; else newdrone.A = di.A;
newdrone.ax = di.ax;
newdrone.ay = di.ay;
if (drone::a0.rndrot) rotate_vector (newdrone.ax, newdrone.ay, drone::a0.rotrd());
newdrone.handle_size = di.handle_size;
newdrone.trail.total = di.trail.total;
newdrone.snap = di.snap;
newdrone.arrow = di.arrow;
int num_targets = di.num_targets;
if (num_targets) { // launch a satellite
newdrone.insert = di.insert;
int& cur_target = di.cur_target;
newdrone.target = di.targets [cur_target];
if (++cur_target >= num_targets) cur_target = 0;
satellites.push_back (newdronep);
newdrone.orbiting = 1;
} else {
gravitated.push_back (newdronep);
}
newdrone.reincarnate = 0;
newdrone.setlife (getval<float, double> (MENU.lifetime, di.life));
newdrone.birth = ui_clk();
newdrone.gen.n = pdi->gen.n;
if (++newdrone.gen.n < newdrone.gen.max) {
newdrone.lpm = getval (MENU.ddpm, di.lpm);
newdrone.launch_every.triggert = ppm2t (newdrone.lpm);
newdrone.dpl = getval (MENU.ddpl, di.dpl);
l2.push_back (newdronep);
++n2;
}
}
}
}
if (n2) for (drone_iterator i = l2.begin(), j = l2.end(); i != j; ++i) make_launcher (*i, LAUNCHLATER);
}
void din::attract_drones () {
for (drone_iterator i = attractors.begin(), j = attractors.end(); i != j; ++i) {
drone* pda = *i;
drone& da = *pda;
list<attractee>& lae = da.attractees;
for (list<attractee>::iterator iter = lae.begin (), jter = lae.end(); iter != jter; ++iter) { // run thru list of attractees
attractee& ae = *iter;
drone& de = *ae.d;
unit_vector<float> (de.ax, de.ay, da.sx - de.x, da.y - de.y); // centripetal acceleration
de.vx = de.vrev * -de.ay; de.vy = de.vrev * de.ax; // centrifugal velocity is just perpendacular to centripetal acceleration
if (de.frozen == 0) {
/*// calculate position of the drones
de.xi = de.x;
de.yi = de.y;
de.x = de.xi + de.V * de.vx + de.A * de.ax;
de.y = de.yi + de.V * de.vy + de.A * de.ay;
de.move_center ();
de.set_pos (de.x, de.y);*/
float x = de.x + de.V * de.vx + de.A * de.ax;
float y = de.y + de.V * de.vy + de.A * de.ay;
de.set_center (x, y);
de.set_pos (x, y);
}
}
}
}
void din::add_drone_to_selection (drone* pd) {
int& sel = pd->sel;
if (CTRL) {
if (sel) {
remove_drone_from_selection (pd);
return;
}
}
if (sel) ; else {
pd->sel = 1;
selected_drones.push_back (pd);
}
}
int din::get_selected_drone_id (drone* d) {
for (int i = 0; i < num_selected_drones; ++i) {
if (selected_drones[i] == d) return i;
}
return -1;
}
void din::remove_drone_from_selection (drone* pd) {
pd->sel = 0;
if (xforming) {
int id = get_selected_drone_id (pd);
if (id != -1) {
if (xforming == SCALE)
erase_id (svec, id);
else
erase_id (rvec, id);
}
}
if (erase (selected_drones, pd)) --num_selected_drones;
if (erase (browsed_drones, pd)) {
--num_browsed_drones;
last_browseable_drone = num_browsed_drones - 1;
}
}
void din::update_drone_players () {
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone& di = *(*i);
di.sol (&drone_wave);
di.player.set_wave (&di.sol);
if (di.binaural) {
di.sol2 (&drone_wave);
di.player2.set_wave (&di.sol2);
}
}
}
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) {
// make arrow
//
float ak2, ak3, ak2t, ak3t;
// base to neck
A[k]=x;
A[k+1]=y;
A[k+2] = ak2 = x + ux;
A[k+3] = ak3 = y + uy;
ak2t = x + t * ux;
ak3t = y + t * uy;
float arx = x + u * ux, ary = y + u * uy;
float vvx = v * vx, vvy = v * vy;
// flank1 to neck
float ak4, ak5;
ak4 = A[k+4] = arx + vvx;
ak5 = A[k+5] = ary + vvy;
A[k+6] = ak2t;
A[k+7] = ak3t;
// flank2 to neck
float ak8, ak9;
ak8 = A[k+8]= arx - vvx;
ak9 = A[k+9]= ary - vvy;
A[k+10]= ak2t;
A[k+11]= ak3t;
if (cap) {
A[k+12]=ak4;
A[k+13]=ak5;
A[k+14]=ak2;
A[k+15]=ak3;
A[k+16]=ak2;
A[k+17]=ak3;
A[k+18]=ak8;
A[k+19]=ak9;
n = 20;
} else n = 12;
}
void din::draw_drones () {
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
draw_connections ();
drawchuck ();
if (meshh.num && meshh.draw)
for (mesh_iterator i = meshes.begin (), j = meshes.end(); i != j; ++i) (*i).draw ();
// drone trails
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone& di = *(*i);
glColor4f (di.r, di.g, di.b, di.fdr.amount);
di.trail.draw ();
}
// hilite selected drone
static int dhp [12] = {0};
glVertexPointer (2, GL_INT, 0, dhp);
if (num_selected_drones == 1) {
drone& ds = *selected_drones[0];
glEnable (GL_LINE_STIPPLE);
glLineStipple (1, 0xffff);
glColor3f (ds.r, ds.g, ds.b);
dhp[0]=ds.sx;dhp[1]=win.top;
dhp[2]=ds.sx;dhp[3]=win.bottom;
dhp[4]=win.left;dhp[5]=ds.y;
dhp[6]=win.right;dhp[7]=ds.y;
glDrawArrays (GL_LINES, 0, 4);
glDisable (GL_LINE_STIPPLE);
}
// draw drone handles
if (dinfo.show_pitch_volume.drones) tb_hz_vol.clear ();
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone& di = *(*i);
if (inbox<int> (win, di.x, di.y)) {
const float gr = di.r, gg = di.g, gb = di.b;
glColor4f (gr, gg, gb, di.fdr.amount);
if (dinfo.show_pitch_volume.drones && di.sel) {
if (di.binaural) {
sprintf (
BUFFER, " L %0.3f + %0.3f R %0.3f @ %0.3f", di.step * SAMPLE_RATE,
di.sep * SAMPLE_RATE, (di.step + di.sep) * SAMPLE_RATE, di.vol * di.gab.amount);
} else {
sprintf (
BUFFER,
"%0.3f @ %0.3f",
di.step * SAMPLE_RATE, di.vol * di.gab.amount
); // draw pitch/volume
}
tb_hz_vol.add (
text (
BUFFER, di.handle.right, di.handle.top,
di.r, di.g, di.b, text::once, text::floating,
di.handle.right - win.left, di.handle.top - win.bottom
)
);
}
dhp[0]=di.sx; dhp[1]=di.handle.bottom; dhp[2]=di.handle.right;dhp[3]=di.y;
dhp[4]=di.sx; dhp[5]=di.handle.top; dhp[6]=di.handle.left; dhp[7]=di.y;
int s = di.sel;
const float ra[2] = {gr, 0}, ga[2] = {di.g, 1}, ba[2] = {di.b, 0};
const float rs = ra[s], gs = ga[s], bs = ba[s];
glColor4f (gr, gg, gb, di.fdr.amount);
glDrawArrays (GL_QUADS, 0, 4);
glColor4f (rs, gs, bs, di.fdr.amount);
glDrawArrays (GL_LINE_LOOP, 0, 4);
}
}
if (dinfo.anchor) { // draw drone anchors
if (n_dap < num_drones) {
if (dap) delete[] dap;
dap = new float [4 * 2 * num_drones]; // n * xy * num_drones
n_dap = num_drones;
}
if (n_dcol < num_drones) {
if (dcol) delete[] dcol;
dcol = new float [4 * 4 * num_drones]; // n points * rgba * num_drones
n_dcol = num_drones;
}
glEnableClientState (GL_COLOR_ARRAY);
glColorPointer (4, GL_FLOAT, 0, dcol);
glVertexPointer (2, GL_FLOAT, 0, dap);
int ai = 0, c = 0;
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone& di = *(*i);
if (di.range < visl || di.range > visr)
;
else {
dap[ai++] = di.sx;
dap[ai++] = win.top;
dap[ai++] = di.sx;
dap[ai++] = win.bottom;
dap[ai++] = win.left;
dap[ai++] = di.y;
dap[ai++] = win.right;
dap[ai++] = di.y;
float clrs [] = {di.r, di.g, di.b, drone::anchoropacity};
for (int s = 0; s < 4; ++s) {
for (int t = 0; t < 4; ++t) {
dcol[c++]=clrs[t];
}
}
}
}
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDrawArrays (GL_LINES, 0, ai / 2);
glDisableClientState (GL_COLOR_ARRAY);
glDisable (GL_BLEND);
}
// draw velocity and acceleration vectors
if (num_drones && (dinfo.vel || dinfo.accel)) {
static const int v_size = 4, a_size = 8 * v_size;
int nn_dvap = 20 * num_drones;
if (n_dvap < nn_dvap) {
if (dvap) delete[] dvap;
if (dcol) delete[] dcol;
dvap = new float [nn_dvap];
dcol = new float [2 * nn_dvap];
n_dvap = nn_dvap;
}
int v = 0, nv = 0;
if (dinfo.vel) {
int ci = 0;
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone& di = *(*i);
if (di.range < visl || di.range > visr)
;
else {
float vl = di.modv.val * v_size, vdx = vl * di.vx, vdy = vl * di.vy, pvdx = -vdy, pvdy = vdx;
int dv = 12;
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);
di.xv = di.sx + vdx; di.yv = di.y + vdy;
v += dv;
//color dic (di.r * di.gab.amount, di.g * di.gab.amount, di.b * di.gab.amount);
color dic (di.r, di.g, di.b);
for (int s = 0, t = dv / 2; s < t; ++s) {
dcol[ci++] = dic.r;
dcol[ci++] = dic.g;
dcol[ci++] = dic.b;
dcol[ci++] = 1.0f;
}
++nv;
}
}
if (nv) {
glEnableClientState (GL_COLOR_ARRAY);
glColorPointer (4, GL_FLOAT, 0, dcol);
glVertexPointer (2, GL_FLOAT, 0, dvap);
glDrawArrays (GL_LINES, 0, v / 2);
glDisableClientState (GL_COLOR_ARRAY);
}
}
if (dinfo.accel) {
int a = 0, na = 0;
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone& di = *(*i);
if (di.range < visl || di.range > visr) ; else {
float al = di.A * a_size, adx = al * di.ax, ady = al * di.ay, padx = -ady, pady = adx;
int da = 12;
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);
di.xa = di.sx + adx; di.ya = di.y + ady;
a += da;
++na;
}
}
if (na) {
glColor4f (1, 0.25, 0.5, 1);
glVertexPointer (2, GL_FLOAT, 0, dvap);
glDrawArrays (GL_LINES, 0, a / 2);
}
}
}
if (dinfo.show_pitch_volume.drones) tb_hz_vol.draw ();
glDisable (GL_BLEND);
}
void din::setdronemastervolume (float d) {
if (MENU.masvol0.state && d < 0) {
d = 0;
MENU.sp_drone_master_vol.set_value (0.0f);
}
drone::MASTERVOLUME = d;
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone& di = *(*i);
di.update_pv = drone::EMPLACE;
}
sprintf (BUFFER, "Drone master volume = %0.3f", d);
cons << YELLOW << BUFFER << eol;
}
void din::update_drone_solvers (multi_curve& crv) {
static const char* dw = "drone-waveform";
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone& di = *(*i);
di.sol.update ();
if (di.binaural) di.sol2.update ();
if (crv.num_vertices) {
di.player.set_mix (crv, dw);
if (di.binaural) di.player2.set_mix (crv, dw);
}
}
}
void din::update_drone_modv_solvers () {
for (drone_iterator i = gravitated.begin(), j = gravitated.end(); i != j; ++i) {
drone& di = *(*i);
di.modv.sol.update ();
}
}
string din::get_selected_drones () {
stringstream ss;
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone& di = *(*i);
if (di.sel) ss << di.id << spc;
}
return ss.str();
}
void din::set_drone_volume (int i, float v) {
drone* pd = get_drone (i);
if (pd) {
pd->xi = pd->x; pd->yi = pd->y;
int x = pd->x, y = (int) (BOTTOM + v * HEIGHT + 0.5f);
pd->set_pos (x, y);
pd->move_center ();
}
}
void din::calc_win_mouse () {
if (MENU.show == 0) {
delta_mousex = mousex - prev_mousex;
delta_mousey = mousey - prev_mousey;
prev_mousex = mousex;
prev_mousey = mousey;
prev_win_mousex = win_mousex;
prev_win_mousey = win_mousey;
win_mousex += delta_mousex;
win_mousey -= delta_mousey;
tonex = win_mousex;
toney = win_mousey;
}
}
int din::is_drone_hit (drone& di, const box<float>& rgn) {
float x [] = {di.handle.midx, di.handle.left, di.handle.right};
float y [] = {di.handle.midy, di.handle.bottom, di.handle.top};
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j)
if (inbox<float> (rgn, x[i], y[j])) return 1;
return 0;
}
void din::calc_selector_range (const box<float>& rgn, int& left, int& right) {
float xl = rgn.left, xr = rgn.right;
left = right = 0;
for (int i = 0; i < num_ranges; ++i) {
range& ri = ranges[i];
if (xl >= ri.extents.left) left = max (0, i - 1);
if (xr >= ri.extents.right) right = min (last_range, i + 1);
}
}
void din::find_selected_drones (const box<float>& rgn) {
// select drones that lie inside selected region
// supports ctrl & shift keys
int sell, selr; calc_selector_range (rgn, sell, selr);
CLEAR_SELECTED_DRONES
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone* pdi = *i;
drone& di = *pdi;
if ((di.state > drone::DEAD) && (di.range >= sell) && (di.range <= selr) && is_drone_hit (di, rgn))
add_drone_to_selection (pdi);
}
print_selected_drones ();
}
void din::invert_selected_drones () {
selected_drones.clear ();
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone* pdi = *i;
drone& di = *pdi;
if (di.sel)
di.sel = 0;
else {
di.sel = 1;
selected_drones.push_back (pdi);
}
}
print_selected_drones ();
}
void din::print_selected_drones () {
num_selected_drones = selected_drones.size ();
if (num_selected_drones) {
if (num_selected_drones != 1) {
browsed_drones = selected_drones;
num_browsed_drones = num_selected_drones;
last_browseable_drone = num_browsed_drones - 1;
browsed_drone = -1;
MENU.sp_browse_drone.set_listener (MENUP.brwdl);
MENU.sp_browse_drone.set_value (browsed_drone);
} else {
MENU.sp_browse_drone.set_listener (0);
ec = selected_drones[0];
}
cons << GREEN;
if (uis.current == this) {
MENU.next_tab = MENUP.cb_mkb_drone_params;
MENU.next_tab_instr = this;
}
if (xforming) resize_xform_vectors ();
} else {
cons << RED;
browsed_drones.clear ();
num_browsed_drones = 0;
browsed_drone = last_browseable_drone = -1;
ec = 0;
}
cons << "Selected " << num_selected_drones << s_drones << eol;
}
int din::handle_input () {
static const double reptf = 1./7, repts = 1./64.;
static const double first_repeat_time = 0.3, other_repeat_time = 0.05;
static double start_time, repeat_time = first_repeat_time;
static int lmb_clicked = 0, mmbclk = 0;
// mov
if (keypressedd (SDLK_a, dinfo.scroll.rept, dinfo.scroll.rept)) scroll (-dinfo.scroll.dx, 0); else
if (keypressedd (SDLK_d, dinfo.scroll.rept, dinfo.scroll.rept)) scroll (+dinfo.scroll.dx, 0); else
if (keypressedd (SDLK_w, dinfo.scroll.rept, dinfo.scroll.rept)) scroll (0, +dinfo.scroll.dy); else
if (keypressedd (SDLK_s, dinfo.scroll.rept, dinfo.scroll.rept)) scroll (0, -dinfo.scroll.dy);
if (wheel && !MENU.show && !mouse_slider0.active) { // move board view
if (SHIFT)
scroll (0, wheel * dinfo.scroll.dy);
else
scroll (-wheel * dinfo.scroll.dx, 0);
}
if (mmb) { // drone xform center to mouse cursor
if (!mmbclk) {
mmbclk = 1;
dinfo.cen.x = tonex;
dinfo.cen.y = toney;
}
} else {
mmbclk = 0;
}
if (lmb) {
if (lmb_clicked == 0) {
lmb_clicked = 1;
if (adding) {
add_drone (win_mousex, win_mousey);
start_time = ui_clk();
}
} else {
if (adding) {
// for spraying drones
double delta_time = ui_clk() - start_time;
if (delta_time >= repeat_time) { // click repeat
lmb_clicked = 0;
repeat_time = other_repeat_time;
}
}
}
} else {
lmb_clicked = 0;
repeat_time = first_repeat_time;
}
if (phrasor0.state == phrasor::recording) { // record mouse pos for playback l8r
static point<int> pt;
pt.x = win_mousex; pt.y = win_mousey;
phrasor0.add (pt);
++phrasor0.size;
}
// octave shift / double beater bpm
if (keypressed (SDLK_z)) {
modulate_down ();
}
else if (keypressed (SDLK_x)) {
modulate_up ();
}
else if (keypressed (SDLK_e)) {
if (!mouse_slider0.active) {
if (moving_drones) set_moving_drones (0); // stop moving
else if (!MENU.show) start_moving_drones (); // start moving
}
}
else if (moving_drones) {
if (num_selected_drones) {
if (prev_win_mousex != win_mousex || prev_win_mousey != win_mousey) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& di = *selected_drones[i];
movedrone (di);
}
}
return 1;
} else {
cons << RED_PSD << eol;
}
}
else if (keypressedd (SDLK_r)) {
if (xforming == ROTATE) {
mouse_slider0.deactivate ();
} else {
if (xforming) mouse_slider0.deactivate ();
MENU.brdl.clicked (MENU.b_rotate_drones);
}
}
else if (keypressedd (SDLK_t)) {
if (xforming == SCALE)
mouse_slider0.deactivate ();
else {
if (xforming) mouse_slider0.deactivate ();
MENU.bsdl.clicked (MENU.b_scale_drones);
}
}
else if (keypressed (SDLK_c)) delete_selected_drones ();
else if (keypressed (SDLK_y)) {
MENU.sp_dam_depth.lbl.toggle ();
} else if (keypressed (SDLK_u)) {
MENU.sp_dam_bpm.lbl.toggle ();
} else if (keypressed (SDLK_o)) {
MENU.sp_dfm_depth.lbl.toggle ();
} else if (keypressed (SDLK_p)) {
if (CTRL)
toggle_this (dinfo.accel, MENU.cb_show_accel);
else
MENU.sp_dfm_bpm.lbl.toggle ();
}
else if (keypressed (SDLK_SPACE)) {
if (adjustranges.active) {
adjustranges.others = !adjustranges.others;
if (adjustranges.others) cons << GREEN << "Adjust other ranges too" << eol; else cons << YELLOW << "Adjusting this range only" << eol;
}
else {
if (SHIFT) freeze_drones ();
else if (CTRL) thaw_drones ();
else toggle_freeze_drones();
}
}
else if (keypressedd (SDLK_k)) {
if (SHIFT)
snap_drones (1);
else if (CTRL)
snap_drones (0);
else
snap_drones (-1); // toggle
}
else if (keypressed (SDLK_SLASH)) {
MENU.sp_drone_master_vol.lbl.toggle ();
}
else if (keypressed (SDLK_f)) {
if (SHIFT) {
dinfo.sel_range = current_range;
MENU.load_range (current_range);
MENU.next_tab = MENUP.cb_mkb_ranges;
MENU.next_tab_instr = this;
} else if (CTRL) {
MENU.cnol.picked (MENU.ol_change_note.option, 0);
print_range_info (ranges[dinfo.sel_range]);
} else {
if (uis.cb_voice.state)
do_phrase_recording ();
else
calc_drones_centroid ();
}
}
else if (keypressed (SDLK_v)) {
if (SHIFT) {
MENU.rwl.clicked (MENU.b_adjust_range_both); // adjust range left and right
} else if (CTRL) {
MENU.cnb.clicked (MENU.b_change_note_both); // change both notes of range
} else { // phrase play/pause
if (phrasor0.state == phrasor::playing) {
if (MENU.show == 0) {
phrasor0.state = phrasor::paused;
find_current_range ();
cons << YELLOW << "phrasor has PAUSED." << eol;
} else cons << RED << "Close menu!" << eol;
} else {
if (phrasor0.validate ()) {
phrasor0.play ();
if (phrasor0.state == phrasor::playing) cons << GREEN << "Phrasor is PLAYING" << eol;
} else {
pos_afx_vel (-1);
}
}
}
}
else if (keypressed (SDLK_g)) { // phrase clear
if (SHIFT) {
MENU.rwl.clicked (MENU.b_adjust_range_left); // adjust range left
} else if (CTRL) {
MENU.cnl.clicked (MENU.b_change_note_left); // change range left note
} else {
clear_all_phrases ();
}
}
else if (keypressed (SDLK_h)) {
if (SHIFT) {
MENU.rwl.clicked (MENU.b_adjust_range_right); // adjust range right
} else
if (CTRL) {
MENU.cnr.clicked (MENU.b_change_note_right); // change range right note
}
else
toggle_launchers (); // start/stop launching drones
}
else if (keypressedd (SDLK_q)) {
if (!mouse_slider0.active) {
if (SHIFT) {
MENU.picked (MENU.ol_drone_is.option, 0);
} else {
if (dinfo.wand) {
if (wanding)
stopwanding ();
else
MENU.dcl.startwanding ();
}
else
add_drone (win_mousex, win_mousey);
}
}
}
else if (keypressed (SDLK_l)) {
if (SHIFT)
select_launchers ();
else
select_all_drones ();
}
else if (keypressed (SDLK_i)) {
if (SHIFT) {
dinfo.show_pitch_volume.board = !dinfo.show_pitch_volume.board;
justset (uis.cb_show_pitch_volume_board, dinfo.show_pitch_volume.board);
}
else
invert_selected_drones ();
}
else if (keypressedd (SDLK_LEFT)) {
if (SHIFT) browse_range (-1); else browse_drone (-1);
} else if (keypressedd (SDLK_RIGHT)) {
if (SHIFT) browse_range (+1); else browse_drone (+1);
}
else if (keypressed (SDLK_SEMICOLON)) select_attractors ();
else if (keypressed (SDLK_QUOTE)) select_attractees ();
else if (keypressedd (SDLK_LEFTBRACKET, reptf, repts)) {
MENU.sp_change_drone_accel.lbl.toggle ();
}
else if (keypressedd (SDLK_RIGHTBRACKET, reptf, repts)) {
if (CTRL)
toggle_this (dinfo.vel, MENU.cb_show_vel);
else
MENU.sp_change_drone_vel.lbl.toggle ();
}
else if (keypressedd (SDLK_EQUALS)) MENU.sp_change_drone_trail_length.lbl.toggle ();
else if (keypressedd (SDLK_MINUS)) MENU.sp_change_drone_handle_size.lbl.toggle ();
else if (keypressedd (SDLK_n)) {
clear_selected_drones ();
cons << GREEN << "Cleared drone selection" << eol;
} else if (keypressed (SDLK_b)) uis.cb_gater.toggle ();
else if (keypressed (SDLK_j)) {
if (SHIFT) {
dinfo.show_pitch_volume.drones = !dinfo.show_pitch_volume.drones;
justset (uis.cb_show_pitch_volume_drones, dinfo.show_pitch_volume.drones);
} else
flip_drone_motion ();
}
else if (keypressed (SDLK_F4)) {
if (SHIFT) {
++doublebpm;
Tcl_UpdateLinkedVar (interpreter.interp, "doublebpm");
} else {
powbeat ("beater", din0.gatr, BPM_MULT);
}
} else if (keypressed (SDLK_F3)) {
if (SHIFT) {
--doublebpm;
Tcl_UpdateLinkedVar (interpreter.interp, "doublebpm");
} else
powbeat ("beater", din0.gatr, 1. / BPM_MULT);
}
else if (keypressed (SDLK_PERIOD)) set_key_to_pitch_at_cursor ();
else if (keypressed (SDLK_F1)) helptext();
return 1;
}
#ifdef __SVG__
void din::write_trail () {
dlog << "<svg>" << endl;
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
ds.trail.write ();
}
dlog << "</svg>" << endl;
}
#endif
void din::change_drone_lifetime (spinner<float>& s) {
if (num_selected_drones) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
ds.setlife (ds.life + s());
cons << GREEN << "Drone: " << i << ", lifetime = " << ds.life << " secs" << eol;
}
} else {
cons << RED_PSD << eol;
}
}
void din::change_orbit_insertion_time (spinner<float>& s) {
if (num_selected_drones) {
int nl = 0;
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
if (ds.launcher) {
++nl;
ds.insert += s ();
if (ds.insert < 0) ds.insert = 0;
cons << "Drone: " << i << ", orbit insertion time = " << ds.insert << " secs" << eol;
}
}
if (!nl) cons << RED << "Please select some drone launchers!" << eol;
} else {
cons << RED_PSD << eol;
}
}
void din::change_drone_trail_points (spinner<int>& s) {
if (num_selected_drones) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
ds.trail.change (s());
cons << GREEN << "Drone: " << i << ", trail points = " << ds.trail.total << eol;
}
} else cons << RED_PSD << eol;
}
void din::change_drone_handle_size (spinner<int>& s) {
if (num_selected_drones) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
ds.handle_size += s();
if (ds.handle_size < 0) ds.handle_size = 0;
cons << GREEN << "Drone " << i << ", handle size = " << ds.handle_size << eol;
}
update_drone_anchors ();
} else cons << RED_PSD << eol;
}
void din::update_drone_anchors () {
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone& di = *(*i);
di.calc_handle ();
}
}
void din::change_drone_arrow (spinner<float>& s, int w) {
static const char* str [] = {"Shoulder position = ", "Shoulder width = ", "Neck = "};
if (num_selected_drones) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
drone::arrowt& ar = ds.arrow;
float* wa [] = {&ar.u, &ar.v, &ar.t};
float& ww = *wa[w];
ww += s ();
cons << GREEN << str[w] << ww << eol;
}
} else cons << RED_PSD << eol;
}
void din::capdronearrows (int c) {
if (num_selected_drones) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
ds.arrow.cap = c;
}
} else cons << RED_PSD << eol;
}
void din::scroll (int dx, int dy, int warp_mouse) {
mousex -= dx;
prev_mousex -= dx;
mousey += dy;
prev_mousey += dy;
win (win.left + dx, win.bottom + dy, win.right + dx, win.top + dy);
find_visible_ranges (dx);
if (warp_mouse) {
if ((mousex > 0 && mousex < view.width) && (mousey > 0 && mousey < view.height)) SDL_WarpMouse (mousex, mousey);
}
dinfo.gravity.ldwx[0] = dinfo.gravity.ldwy[0] = -1; // see din::evalgravity ()
}
void din::find_current_range () {
// find the range where mouse is found
if (win_mousex <= ranges[0].extents.left) current_range = 0; else
if (win_mousex >= ranges[last_range].extents.right) current_range = last_range; else
for (int i = 0; i < num_ranges; ++i) {
range& curr = ranges[i];
box<int>& e = curr.extents;
if ( (win_mousex >= e.left) && (win_mousex <= e.right)) {
current_range = i;
break;
}
}
find_visible_ranges ();
}
void din::find_visible_ranges (int dir) {
// we only draw visible ranges
if (dir > 0) {
while ((visr < last_range) && (ranges[visr].extents.right < win.right)) ++visr;
while ((visl < last_range) && (ranges[visl].extents.right < win.left)) ++visl;
} else if (dir < 0) {
while ((visl > 0) && (ranges[visl].extents.left > win.left)) --visl;
while ((visr > 0) && (ranges[visr].extents.left > win.right)) --visr;
} else {
visl = current_range;
visr = current_range;
while ( (visl > 0) && (win.left < ranges[visl].extents.left) ) --visl;
while ( (visr < last_range) && (ranges[visr].extents.right < win.right) ) ++visr;
}
}
int din::find_range (float x, int r) {
while (1) {
range& curr = ranges [r];
float deltax = x - curr.extents.left;
if (deltax > curr.extents.width) {
if (++r < num_ranges); else {
r = last_range;
break; // drone in last range
}
}
else if (deltax < 0) {
if (--r < 0) {
r = 0; // drone in first range
break;
}
}
else
break; // drone in current range
}
return r;
}
int din::find_tone_and_volume () {
// locate current tone
range* curr = &ranges [current_range];
int deltax = tonex - curr->extents.left;
if (deltax >= curr->extents.width) { // tone in range to the right
++current_range;
if (current_range == num_ranges) { // snap to last range
current_range = last_range;
curr = lastr;
} else {
curr = &ranges [current_range];
}
} else if (deltax < 0) { // tone in range to the left
--current_range;
if (current_range < 0) { // snap to first range
curr = firstr;
current_range = 0;
} else {
curr = &ranges [current_range];
}
}
// located tone so find frequency
//
deltax = tonex - curr->extents.left;
delta = warp_pitch (deltax * curr->extents.width_1);
step = curr->notes[0].step + delta * curr->delta_step; // step determines frequency see note.h
// find VOLUME
static const int if_uniq = 1;
int dv = toney - BOTTOM;
float iv = dv * 1.0f / ranges[current_range].extents.height;
float fin_vol = 1.0f;
if (dv < 0) { // below keyboard, silence voice
fin_vol = 0.0f;
wavplay.set_interpolated_pitch_volume (step, fin_vol, if_uniq);
am_vol = 0;
VOLUME = -warp_vol (-iv);
} else {
VOLUME = warp_vol (iv);
float fdr_vol = uis.fdr_voice.amount * VOLUME;
fin_vol = fdr_vol * VOICE_VOLUME;
wavplay.set_interpolated_pitch_volume (step, fin_vol, if_uniq);
am_vol = fdr_vol * am_depth;
}
if (dinfo.voice_is_voice == 0) {
nsr.set_spread (fin_vol);
nsr.set_samples (1.0f / step);
}
Tcl_UpdateLinkedVar (interpreter.interp, "volume"); // VOLUME is accessible in Tcl interpreter as variable volume
if (dinfo.show_pitch_volume.board) {
sprintf (BUFFER, "%0.3f @ %0.3f", (step * SAMPLE_RATE), VOLUME);
pitch_volume_info = BUFFER;
}
return 1;
}
void din::draw () {
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glOrtho (win.left, win.right, win.bottom, win.top, -1, 1);
glMatrixMode (GL_MODELVIEW);
if (UI_OFF == 0) {
if (dinfo.dist.vol) draw_vol_dist ();
if (dinfo.dist.pitch) draw_pitch_dist ();
// label visible ranges
//
for (int i = visl; i < visr; ++i) ranges[i].draw_labels (range::LEFT, dinfo.show_pitch_volume.board);
ranges[visr].draw_labels (range::BOTH, dinfo.show_pitch_volume.board);
// mark selected range?
if (dinfo.mark_sel_range && !(dinfo.sel_range < visl || dinfo.sel_range > visr)) {
range& cr = ranges[dinfo.sel_range];
box<int>& cre = cr.extents;
glLineWidth (1);
/*glEnable (GL_LINE_STIPPLE);
glLineStipple (1, 0x0f0f);*/
glColor3f (0.2f, 1.0f, 1.0f);
// glColor3f (1, 1, 1);
gl_pts[0]=cre.left; gl_pts[1]=cre.bottom;
gl_pts[2]=cre.right; gl_pts[3]=cre.bottom;
gl_pts[4]=cre.right; gl_pts[5]=cre.top;
gl_pts[6]=cre.left; gl_pts[7]=cre.top;
glVertexPointer (2, GL_INT, 0, gl_pts);
glDrawArrays (GL_LINE_LOOP, 0, 4);
glLineWidth (1);
//glDisable (GL_LINE_STIPPLE);*/
}
// phrasor marker
phrasor0.draw (win);
// draw cursor info
int cursorx = tonex + 8, cursory = toney;
if (dinfo.show_pitch_volume.board && !basic_editor::hide_cursor) {
glColor3f (0.75f, 0.75f, 0.75f);
draw_string (pitch_volume_info, cursorx, cursory);
if (rising || falling) {
cursory += line_height;
draw_string (num_drones_info, cursorx, cursory);
}
}
// drones xform center
dinfo.cen.draw ();
// draw guide for positioning drones
//if (dinfo.voice == 0) {
/*glEnable (GL_LINE_STIPPLE);
glLineStipple (1, 0xfffc);*/
glColor3f (0.3, 0.3, 0.3);
glVertexPointer (2, GL_INT, 0, gl_pts);
gl_pts[0]=win.left;gl_pts[1]=win_mousey; //toney;
gl_pts[2]=win.right;gl_pts[3]=win_mousey; //toney;
gl_pts[4]=win_mousex;gl_pts[5]=win.bottom;
gl_pts[6]=win_mousex;gl_pts[7]=win.top;
glDrawArrays (GL_LINES, 0, 4);
//glDisable (GL_LINE_STIPPLE);
//}
// draw selector
mkb_selector.draw (rgn);
}
draw_drones ();
if (MENU.cb_show_gravity.state) dinfo.gravity.drawrrow ();
}
void din::enter () {
ui::enter ();
if (phrasor0.state == phrasor::playing)
return;
else {
win_mousex = win.left + mousex;
win_mousey = win.bottom + mouseyy;
}
}
void din::window_resized (int w, int h) {
clear_all_phrases ();
win (win.left, win.bottom, win.left + w, win.bottom + h);
warp_mouse (prev_mousex, prev_mousey);
win_mousex = win.left + mousex;
win_mousey = win.bottom + mouseyy;
find_current_range ();
}
void din::change_depth (int i, float d) {
if (i == 1) {
fm_depth += d;
hz2step (fm_depth, fm_step);
cons << YELLOW << "Voice FM depth = " << fm_depth << eol;
MENU.sp_fm_depth.set_value (fm_depth);
} else {
am_depth += d;
cons << YELLOW << "Voice AM depth = " << am_depth << eol;
MENU.sp_am_depth.set_value (am_depth);
}
}
void din::modulate_drones () {
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone& di = *(*i);
if (di.frozen == 0) {
modulator& dm = di.mod;
dm.calc ();
di.autorot.calc (dm.dt);
// AM along a direction vector, FM along a direction vector
float x = di.cx + dm.fm.result * (*dm.fm.dirx) + dm.am.result * (*dm.am.dirx);
float y = di.cy + dm.fm.result * (*dm.fm.diry) + dm.am.result * (*dm.am.diry);
if (di.autorot.v.yess()) rotate_vector (di.vx, di.vy, di.autorot.v.angle.theta);
if (di.autorot.a.yess()) rotate_vector (di.ax, di.ay, di.autorot.a.angle.theta);
if ( ! (equals (x, di.x) && equals (y, di.y) ) ) di.set_pos (x, y);
}
}
}
void din::setvelaccel (int w, int id, int neg, int perp) {
if (num_selected_drones) {
float xx[5], yy[5];
int negs[2] = {1, -1};
xx[0] = 0; yy[0] = 0;
xx[1] = 0; yy[1] = 1;
xx[2] = 1; yy[2] = 0;
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
xx[3]=ds.vx;
yy[3]=ds.vy;
xx[4]=ds.ax;
yy[4]=ds.ay;
float* wx[2] = {&ds.vx, &ds.ax};
float* wy[2] = {&ds.vy, &ds.ay};
float* aft [2] = {&ds.autorot.v.autoflip.total, &ds.autorot.a.autoflip.total};
alarm_t* art [2] = {&ds.autorot.v.tik, &ds.autorot.a.tik};
int negg = negs[neg];
float xxx = negg * xx[id];
float yyy = negg * yy[id];
if (perp) {
float o = xxx;
xxx = yyy;
yyy = -o;
}
if (w == 2) {
ds.vx = ds.ax = xxx;
ds.vy = ds.ay = yyy;
ds.autorot.v.autoflip.total = ds.autorot.a.autoflip.total = 0.0f;
ds.autorot.v.tik.start ();
ds.autorot.a.tik.start ();
} else {
*wx[w] = xxx;
*wy[w] = yyy;
*aft[w] = 0.0f;
art[w]->start ();
}
}
} else cons << RED_PSD << eol;
}
void din::setmoddir (int w, int id) {
if (num_selected_drones) {
const char* dirs [] = {"Vertical", "Horizontal", "Velocity", "Acceleration"};
const char* whats [] = {"AM", "FM"};
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
mod_params* modp [] = {&ds.mod.am, &ds.mod.fm};
mod_params* modpw = modp[w];
modpw->id = id;
modpw->calcdir (ds);
}
cons << "Set " << whats[w] << " direction of " << num_selected_drones << " drones to " << dirs[id] << eol;
} else cons << RED_PSD << eol;
}
void din::setautorot (int what, int state, int tog) {
if (what == menu::autorott::BOTH) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
int amst [] = {state, !ds.autorot.v.yes};
int fmst [] = {state, !ds.autorot.a.yes};
ds.autorot.v.setyes (amst[tog]);
ds.autorot.a.setyes (fmst[tog]);
}
} else {
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
autorotator& ar = *ds.autorot.arr[what];
int states[] = {state, !ar.yes};
ar.setyes (states[tog]);
}
}
TOGGLEMENU
}
void din::setautoflip (int what, int state, int tog) {
if (num_selected_drones) {
if (what == menu::autorott::BOTH) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
int amst [] = {state, !ds.autorot.v.autoflip.yes};
int fmst [] = {state, !ds.autorot.a.autoflip.yes};
ds.autorot.v.autoflip.yes = amst[tog];
ds.autorot.a.autoflip.yes = fmst[tog];
ds.autorot.v.autoflip.total = 0.0f;
ds.autorot.a.autoflip.total = 0.0f;
}
} else {
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
autoflipt& af = ds.autorot.arr[what]->autoflip;
af.total = 0.0f;
int& yes = af.yes;
int states[] = {state, !yes};
yes = states[tog];
}
}
} else
cons << RED_PSD << eol;
TOGGLEMENU
}
void din::setautopause (int what, int state, int tog) {
if (num_selected_drones) {
if (what == menu::autorott::BOTH) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
int amst [] = {state, !ds.autorot.v.autopause.yes};
int fmst [] = {state, !ds.autorot.a.autopause.yes};
ds.autorot.v.autopause.setyes (amst[tog], ds.autorot.v);
ds.autorot.a.autopause.setyes (fmst[tog], ds.autorot.a);
}
} else {
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
autorotator& ar = *ds.autorot.arr[what];
autopauset& ap = ar.autopause;
int states[] = {state, !ap.yes};
ap.setyes (states[tog], ar);
}
}
} else
cons << RED_PSD << eol;
TOGGLEMENU
}
void din::setrndflipause (int what, int which, int state, int tog) {
if (num_selected_drones) {
if (what == menu::autorott::BOTH) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
int* vw [] = {&ds.autorot.v.autoflip.rndang, &ds.autorot.v.autopause.rndt[0],&ds.autorot.v.autopause.rndt[1]};
int* aw [] = {&ds.autorot.a.autoflip.rndang, &ds.autorot.a.autopause.rndt[0],&ds.autorot.a.autopause.rndt[1]};
int& dsvw = *vw[which];
int& dsaw = *aw[which];
int vst [] = {state, !dsvw};
int ast [] = {state, !dsaw};
dsvw = vst[tog];
dsaw = ast[tog];
}
} else {
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
autorotator& ar = *ds.autorot.arr[what];
int* w [] = {&ar.autoflip.rndang, &ar.autopause.rndt[0], &ar.autopause.rndt[1]};
int& wv = *w[which];
int states[] = {state, !wv};
wv = states[tog];
}
}
} else
cons << RED_PSD << eol;
TOGGLEMENU
}
void din::setautorotparam (int which, int what) {
if (which == menu::autorott::BOTH) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
autorotator &var = ds.autorot.v, &aar = ds.autorot.a;
var.setyes (1);
aar.setyes (1);
if (what == menu::autorott::RPM) {
var.mov = aar.mov = autorotator::SMOOTH;
var.set_rpm (ds.autorot.v.rpm + MENU.autorotate.rpm());
aar.set_rpm (ds.autorot.a.rpm + MENU.autorotate.rpm());
cons << "Drone : " << i << " Velocity RPM = " << var.rpm << " Acceleration RPM = " << aar.rpm << eol;
} else if (what == menu::autorott::DEG) {
var.mov = aar.mov = autorotator::TICK;
var.chgdeg (MENU.autorotate.deg());
aar.chgdeg (MENU.autorotate.deg());
cons << "Drone : " << i << " Velocity Degrees per Tick = " << var.deg << ", Acceleration Degrees per Tick = " << aar.deg << eol;
} else if (what == menu::autorott::TPS) {
var.mov = aar.mov = autorotator::TICK;
var.chgtps (MENU.autorotate.tps());
aar.chgtps (MENU.autorotate.tps());
cons << "Drone : " << i << " Velocity Ticks per Second = " << var.tps << ", Acceleration Ticks per Second = " << aar.tps << eol;
} else {
var.mov = aar.mov = MENU.autorotate.mov.id;
if (MENU.autorotate.mov.id == autorotator::SMOOTH) {
var.set_rpm (var.rpm);
aar.set_rpm (aar.rpm);
} else {
var.settps (var.tps);
var.setdeg (var.deg);
aar.settps (aar.tps);
aar.setdeg (aar.deg);
alarm_t& vart = var.tik;
alarm_t& aart = aar.tik;
vart.start (vart.triggert);
aart.start (aart.triggert);
}
}
}
} else {
const char* strs[2] = {" Velocity", " Acceleration"};
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
autorotator& ar = *ds.autorot.arr[which];
ar.yes = 1;
if (what == menu::autorott::RPM) {
ar.mov = autorotator::SMOOTH;
ar.set_rpm (ar.rpm + MENU.autorotate.rpm());
cons << "Drone : " << i << strs[which] << " RPM = " << ar.rpm << eol;
} else if (what == menu::autorott::DEG) {
ar.mov = autorotator::TICK;
ar.chgdeg (MENU.autorotate.deg());
cons << "Drone : " << i << strs[which] << " Degrees per Tick = " << ar.deg << spc << ", Ticks per Second = " << ar.tps << eol;
} else if (what == menu::autorott::TPS) {
ar.mov = autorotator::TICK;
ar.chgtps (MENU.autorotate.tps());
cons << "Drone : " << i << strs[which] << " Degrees per Tick = " << ar.deg << spc << ", Ticks per Second = " << ar.tps << eol;
} else {
ar.mov = MENU.autorotate.mov.id;
if (MENU.autorotate.mov.id == autorotator::SMOOTH) {
ar.set_rpm (ar.rpm);
} else {
ar.settps (ar.tps);
ar.tik.start ();
ar.setdeg (ar.deg);
}
}
}
}
}
void din::setautorotdir (int what, int dir) {
if (num_selected_drones) {
if (what == menu::autorott::BOTH) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
ds.autorot.v.dir = dir;
ds.autorot.a.dir = dir;
}
} else {
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
ds.autorot.arr[what]->dir = dir;
}
}
TOGGLEMENU
} else
cons << RED_PSD << eol;
}
void din::setautopauseparam (int what, int which) {
static const char* pl [] = {"Every", "For"};
spinner<float>* sp [] = {MENUP.autorotate.autopause.every, MENUP.autorotate.autopause.f0r};
if (what == menu::autorott::BOTH) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
autopauset &vp = ds.autorot.v.autopause, &ap = ds.autorot.a.autopause;
spinner<float>& spw = *sp[which];
double* vapp [] = {&vp.every, &vp.f0r};
double* aapp [] = {&ap.every, &ap.f0r};
double& dv = *vapp[which];
double& da = *aapp[which];
dv += spw();
if (dv < 0) dv = 0.0;
da += spw();
if (da < 0) da = 0.0;
cons << "Drone : " << i << " Velocity Auto pause " << pl[which] << spc << dv << " seconds, Acceleration Auto pause " << pl[which] \
<< da << eol;
}
} else {
const char* strs[2] = {" Velocity", " Acceleration"};
spinner<float>& spw = *sp[which];
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
autopauset& ap = ds.autorot.arr[what]->autopause;
double* app [] = {&ap.every, &ap.f0r};
double& dp = *app[which];
dp += spw ();
if (dp < 0) dp = 0.0;
cons << "Drone : " << i << strs[what] << " Auto pause " << pl[which] << spc << dp << " seconds" << eol;
}
}
}
void din::setautoflipangle (int what) {
if (what == menu::autorott::BOTH) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
autoflipt &amaf = ds.autorot.v.autoflip, &fmaf = ds.autorot.a.autoflip;
amaf.total = fmaf.total = 0.0f;
amaf.set (amaf.angle.deg + MENU.autorotate.autoflip.angle());
fmaf.set (fmaf.angle.deg + MENU.autorotate.autoflip.angle());
cons << "Drone : " << i << " Velocity Auto flip angle = " << amaf.angle.deg << " Acceleration Auto flip angle = " << fmaf.angle.deg << eol;
}
} else {
const char* strs[2] = {" Velocity", " Acceleration"};
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
autoflipt& af = ds.autorot.arr[what]->autoflip;
af.total = 0.0f;
af.set (af.angle.deg + MENU.autorotate.autoflip.angle());
cons << "Drone : " << i << strs[what] << " Auto flip angle = " << af.angle.deg << eol;
}
}
}
int din::calc_am_fm_gater () {
int ret = 0;
// AM
/*memcpy (aout.bufL, wavplay.pvol, aout.samples_channel_size);
multiply (aout.bufL, aout.samples_per_channel, am_depth);
ret += am.modulate_and_mix (aout.ams, aout.mix, aout.mixa, aout.samples_per_channel, aout.bufL);*/
ret += am.modulate_and_mix (aout.ams, aout.mix, aout.mixa, aout.samples_per_channel, am_depth);
// FM
ret += fm.modulate_and_mix (aout.fms, aout.mix, aout.mixa, aout.samples_per_channel, fm_step);
// beater
ret += gatr.gen_and_mix (aout.gatr, aout.mix, aout.mixa, aout.samples_per_channel);
return ret;
}
int din::render_audio (float* out0, float* out1) {
int ret = 0;
find_tone_and_volume ();
ret = calc_am_fm_gater (); // compute voice AM & FM & beater over bpm
float *lout = out0, *rout = out1;
if (dinfo.voice_is_voice) {
wavplay.gen_wav_fm_am_mix (lout, aout.samples_per_channel);
ret += wavplay.mixer.active;
} else { // voice is noise
nsr (lout, rout, aout.samples_per_channel, 1.0f);
ret = 1;
}
// gater on voice
lout = out0;
rout = out1;
if (uis.fdr_gater.on) {
memcpy (aout.result, lout, aout.samples_channel_size); // voice
multiply (lout, aout.gatr, aout.samples_per_channel); // voice * gater
fill (aout.bufR, fdr_gater_prev_amount, uis.fdr_gater.amount, aout.samples_per_channel);
fdr_gater_prev_amount = uis.fdr_gater.amount;
tween (lout, aout.result, aout.samples_per_channel, aout.bufR); // voice > voice*gater
} else {
if (dinfo.gater) multiply (lout, aout.gatr, aout.samples_per_channel); // voice * gater
}
memcpy (rout, lout, aout.samples_channel_size); // copy left -> right
// render drones
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone& di = *(*i);
float* lout = out0, *rout = out1;
if (di.update_pv) di.update_pitch_volume ();
if (di.is < drone::NOISE) {
play& dp = di.player;
if (di.is == drone::DRONE) {
dp.master (lout, rout, aout.result, aout.samples_per_channel, dp.pvol);
ret += dp.mixer.active;
} else {
play& dp2 = di.player2;
dp.master (lout, aout.result, aout.samples_per_channel, dp.pvol);
dp2.master (rout, aout.result, aout.samples_per_channel, dp2.pvol);
ret = dp.mixer.active + dp2.mixer.active;
}
} else {
di.nsr (lout, rout, aout.samples_per_channel, drone::MASTERVOLUME * di.fdr.amount * di.gab.amount);
}
}
/*memcpy (aout.fdr1, lout, aout.samples_channel_size);
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone& di = *(*i);
float* lout = out0, *rout = out1;
if (di.is != drone::DRONE) {
di.nsr (lout, rout, aout.samples_per_channel, drone::MASTERVOLUME * di.fdr.amount * di.gab.amount);
}
}
memcpy (aout.fdr2, aout.fdr1, aout.samples_channel_size);*/
/*if (alignn) {
cons << "alignned!" << eol;
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone& di = *(*i);
play& dp = di.player;
dp.x = 0;
}
alignn = 0;
} */
return ret;
}
void din::rise_drones () {
if (rising) {
for (drone_iterator i = risers.begin(), j = risers.end (); i != j;) {
drone* pdi = *i;
drone& di = *pdi;
di.fdr.eval ();
if (di.fdr.reached) {
di.state = drone::ACTIVE;
di.update_pv = drone::EMPLACE;
i = risers.erase (i);
j = risers.end ();
--rising;
} else {
di.update_pv = drone::INTERPOLATE;
++i;
}
}
}
}
void din::fall_drones () {
if (falling) {
for (drone_iterator i = fallers.begin(), j = fallers.end (); i != j;) {
drone* pdi = *i;
drone& di = *pdi;
if (di.frozen == 0) {
di.fdr.eval ();
if (di.fdr.reached) {
i = fallers.erase (i);
j = fallers.end ();
--falling;
if (pdi->reincarnate) {
di.state = drone::RISING;
risers.push_back (pdi);
++rising;
di.fdr.set (0.0f, 1.0f, 1, MENU.riset());
di.setlife (MENU.lifetime());
di.birth = ui_clk ();
} else {
remove_attractee (pdi);
remove_tracker (pdi);
if (dinfo.gravity.tracked_drone[0] == pdi) dinfo.gravity.tracked_drone[0] = 0;
if (dinfo.gravity.tracked_drone[1] == pdi) dinfo.gravity.tracked_drone[1] = 0;
if (di.launcher) erase (launchers, pdi);
if (di.attractor) {
erase (attractors, pdi);
list<attractee>& lae = di.attractees;
for (list<attractee>::iterator iter = lae.begin (), jter = lae.end(); iter != jter; ++iter) {
attractee& ae = *iter;
drone& de = *ae.d;
de.orbiting = 0;
}
}
if (di.gravity) {
erase (gravitated, pdi);
erase (satellites, pdi);
}
remove_drone_from_targets (pdi);
remove_drone_from_selection (pdi);
remove_drone_from_pre_mesh (pdi);
remove_drone_from_mesh (pdi);
remove_connections (pdi);
remove_from_groups (pdi);
if (ec == pdi) ec = 0;
gab.erase (pdi);
--num_drones;
print_num_drones ();
if (pdi->chuck.yes) pdi->chuck.de ();
erase (drones, pdi);
delete pdi;
}
} else {
++i;
di.update_pv = drone::INTERPOLATE;
}
}
else
++i;
}
}
}
void din::height_changed (int r, int dh) {
if (r == -1) {
for (int i = 0; i < num_ranges; ++i) ranges[i].change_height (dh);
refresh_all_drones ();
} else {
ranges[r].change_height (dh);
refresh_drones (r);
}
}
void din::toggle_this (int& what, checkbutton& cb) {
what = !what;
cb.set_state (what);
}
void din::change_drone_depth (int what, float delta) {
if (num_selected_drones) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
ds.change_depth (i, what, delta);
}
} else cons << RED_PSD << eol;
}
void din::change_drone_bpm (int what, float delta) {
if (num_selected_drones) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
ds.change_bpm (i, what, delta);
}
} else cons << RED_PSD << eol;
}
void din::change_drone_depth (int what, spinner<float>& s) {
if (num_selected_drones) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
float dv = s ();
ds.change_depth (i, what, dv);
}
} else cons << RED_PSD << eol;
}
void din::change_drone_bpm (int what, spinner<float>& s) {
if (num_selected_drones) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
float dv = s ();
ds.change_bpm (i, what, dv);
}
} else cons << RED_PSD << eol;
}
void din::change_drone_modpos (int what, spinner<float>& s) {
if (num_selected_drones) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
ds.change_modpos (i, what, s());
}
} else cons << RED_PSD << eol;
}
void din::set_drone_am2fm2am_bpm (int what) {
if (num_selected_drones) {
static const char* str [] = {"Set AM BPM to FM BPM for " , "Set FM BPM to AM BPM for "};
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
mod_params* mp [] = {&ds.mod.am, &ds.mod.fm};
int s = what, t = !what;
float sb = mp[s]->bv.bpm;
mp[t]->bv.set_bpm (sb);
}
cons << GREEN << str[what] << num_selected_drones << " drones" << eol;
} else cons << RED_PSD << eol;
TOGGLEMENU
}
void din::toggle_adding_drones () {
adding = !adding;
if (adding) {
cons << GREEN << "Click to add drones. ESC to stop" << eol;
} else {
cons << RED << "Stopped adding drones!" << eol;
uis.add (this, &mkb_selector);
}
}
void din::start_moving_drones () {
SELECTED_DRONES_EXIST
set_moving_drones (1);
}
void din::toggle_moving_drones () {
if (moving_drones == 0) {
start_moving_drones ();
} else set_moving_drones (0);
}
void din::set_moving_drones (int md) {
moving_drones = md;
if (moving_drones)
cons << GREEN << "Just move mouse to move drones, ESC or Click to stop!" << eol;
else
cons << YELLOW << "@ " << name << eol;
}
int din::finish_phrase_recording () {
if (phrasor0.state == phrasor::recording) {
if (phrasor0.validate ()) {
phrasor0.play ();
cons << GREEN << "Phrasor has stopped recording and started playing!" << eol;
return 1;
}
}
return 0;
}
void din::do_phrase_recording () {
if (!finish_phrase_recording()) {
phrasor0.rec ();
cons << GREEN << "Phrasor is recording. Click or press f to finish!" << eol;
}
}
void din::clear_all_phrases () {
if (phrasor0.size != 0) {
phrasor0.clear ();
if (MENU.show == 0) find_current_range ();
MENU.s_phrase_position.set_val (0);
wanding = 0;
cons << RED << "Phrase cleared!" << eol;
}
}
void din::set_key_to_pitch_at_cursor () {
find_current_range ();
tonex = win_mousex;
toney = win_mousey;
find_tone_and_volume ();
float hz = step * SAMPLE_RATE;
set_tonic (this, hz);
}
void din::change_drone_accel (spinner<float>& s) {
if (num_selected_drones) {
cons << YELLOW;
int lim0 = MENU.accel0.state;
for (int i = 0; i < num_selected_drones; ++i) {
drone& di = *selected_drones[i];
di.A += s ();
if (lim0) {if (di.A < 0.0f) di.A = 0.0f;}
cons << "Drone: " << i << ", Acceleration = " << di.A << eol;
}
} else cons << RED_PSD << eol;
}
void din::change_drone_vel (spinner<float>& s) {
if (num_selected_drones) {
cons << YELLOW;
int lim0 = MENU.vel0.state;
for (int i = 0; i < num_selected_drones; ++i) {
drone& di = *selected_drones[i];
di.V += s ();
di.modv.val = di.V;
if (lim0) {if (di.V < 0.0f) di.V = 0.0f;}
cons << "Drone: " << i << ", Velocity = " << di.V << eol;
}
} else cons << RED_PSD << eol;
}
void din::rotate_drone_vec (int which, spinner<float>& s, int dir) {
if (num_selected_drones) {
cons << YELLOW;
static const char* str [] = {"Velocity", "Acceleration"};
for (int i = 0; i < num_selected_drones; ++i) {
drone& di = *selected_drones[i];
float* px [] = {&di.vx, &di.ax};
float* py [] = {&di.vy, &di.ay};
float deg = dir * s(), rad = deg * PI_BY_180;
rotate_vector (*px[which], *py[which], rad);
cons << "Drone: " << i << ", Rotated " << str[which] << " by " << deg << " degrees." << eol;
}
} else cons << RED_PSD << eol;
}
void din::calc_drones_centroid () {
if (num_selected_drones) {
starthere:
dinfo.cen.x = dinfo.cen.y = 0.0f;
for (int i = 0; i < num_selected_drones; ++i) {
drone& di = *selected_drones [i];
dinfo.cen.x += di.cx; dinfo.cen.y += di.cy;
}
dinfo.cen.x /= num_selected_drones;
dinfo.cen.y /= num_selected_drones;
} else {
select_all_drones ();
if (num_selected_drones) goto starthere; else cons << RED_PSD << eol;
}
}
void din::calc_xform_vectors (vector<point <float> >& V, int n) {
V.resize (n);
for (int i = 0; i < n; ++i) {
drone& di = *selected_drones [i];
point<float>& vv = V[i];
if (di.chuck.yes && di.chuck.sun) {
direction<float> (vv.x, vv.y, di.chuck.sun->cx, di.chuck.sun->cy, di.cx, di.cy);
} else
direction<float> (vv.x, vv.y, dinfo.cen.x, dinfo.cen.y, di.cx, di.cy);
}
}
void din::calc_xform_vectors () {
if (xforming == SCALE) calc_xform_vectors (svec, num_selected_drones); else
if (xforming == ROTATE) calc_xform_vectors (rvec, num_selected_drones);
}
void din::resize_xform_vectors () {
if (xforming == SCALE) svec.resize (num_selected_drones); else rvec.resize (num_selected_drones);
}
int din::prep_rotate_drones () {
int n = num_selected_drones;
if (n) {
calc_xform_vectors (rvec, n);
angle = 0.0f;
xforming = ROTATE;
return n;
}
return 0;
}
int din::prep_scale_drones () {
int n = num_selected_drones;
if (n) {
calc_xform_vectors (svec, n);
scl = 1.0f;
xforming = SCALE;
return n;
}
return 0;
}
void din::rotate_drones () {
float dx, dy, cx, cy;
for (int i = 0; i < num_selected_drones; ++i) {
drone& di = *selected_drones[i];
point<float> rv = rvec[i];
rotate_vector (rv.x, rv.y, angle);
if (!di.chuck.yes) {
cx = dinfo.cen.x;
cy = dinfo.cen.y;
dx = cx + rv.x;
dy = cy + rv.y;
di.set_center (dx, dy);
} else cons << RED << "Wont rotate chucked drone!" << eol;
}
}
void din::scale_drones () {
list<drone*> rm;
int nrm = 0;
for (int i = 0; i < num_selected_drones; ++i) {
drone* pdi = selected_drones[i];
drone& di = *pdi;
if (!di.chuck.yes) {
point<float> sv = svec[i];
sv *= scl;
di.set_center (dinfo.cen.x + sv.x, dinfo.cen.y + sv.y, 0);
if (di.nconn) {
rm.push_back (pdi);
for (drone_iterator p = di.connections.begin (), q = di.connections.end (); p != q; ++p) rm.push_back (*p);
nrm = nrm + di.nconn + 1;
}
} else cons << RED << "Wont scale chucked drone!" << eol;
}
if (nrm) for (drone_iterator p = rm.begin (), q = rm.end (); p != q; ++p) (*p)->remagconns ();
}
void din::scale_drones (float ds) {
if (CTRL) scl.x += ds;
else if (SHIFT) scl.y += ds;
else scl += ds;
}
void din::change_drones_per_min (spinner<float>& s) {
if (num_selected_drones) {
cons << YELLOW;
float dpm;
for (int i = 0; i < num_selected_drones; ++i) {
drone* pds = selected_drones[i];
drone& ds = *pds;
dpm = ds.lpm + s ();
if (dpm > 0.0f) {
ds.lpm = dpm;
ds.launch_every.triggert = 60.0 / ds.lpm;
} else {
ds.lpm = 0.0f;
ds.launch_every.triggert = MILLION;
}
cons << "Drone: " << i << ", launches per minute = " << ds.lpm << eol;
}
} else cons << RED_PSD << eol;
}
void din::change_drones_per_launch (spinner<int>& s) {
if (num_selected_drones) {
cons << YELLOW;
int dpl;
for (int i = 0; i < num_selected_drones; ++i) {
drone* pds = selected_drones[i];
drone& ds = *pds;
dpl = ds.dpl + s();
if (dpl < 0) dpl = 0;
ds.dpl = dpl;
cons << "Drone: " << i << ", drones per launch = " << ds.dpl << eol;
}
} else cons << RED_PSD << eol;
}
void din::select_attractees () { // select the attractees of the selected drones or all drones
if (num_selected_drones == 0) {
if (num_drones) {
select_all_drones ();
} else {
cons << RED << "No drones, so no attractees" << eol;
return;
}
}
vector<drone*> new_selected_drones;
for (int i = 0; i < num_selected_drones; ++i) {
drone& di = *selected_drones[i];
if (di.attractor) {
list<attractee>& lae = di.attractees;
for (list<attractee>::iterator iter = lae.begin (), jter = lae.end(); iter != jter; ++iter) {
attractee& ae = *iter;
new_selected_drones.push_back (ae.d);
}
}
}
int ns = new_selected_drones.size ();
if (ns) {
CLEAR_SELECTED_DRONES
for (int i = 0; i < ns; ++i) {
drone* pd = new_selected_drones[i];
add_drone_to_selection (pd);
}
print_selected_drones ();
} else {
cons << RED << "Sorry, no attractees found!" << eol;
}
}
void din::select_attractors () { // select the attractors of selected drones
if (num_selected_drones) {
vector<drone*> selv (selected_drones);
int q = num_selected_drones;
CLEAR_SELECTED_DRONES
for (drone_iterator i = attractors.begin(), j = attractors.end(); i != j; ++i) {
drone* pdi = *i;
drone& di = *pdi;
list<attractee>& lae = di.attractees;
for (list<attractee>::iterator iter = lae.begin (), jter = lae.end(); iter != jter; ++iter) {
attractee& ae = *iter;
for (int p = 0; p < q; ++p) {
drone* sd = selv [p];
if (sd == ae.d) {
add_drone_to_selection (pdi);
goto next_attractor;
}
}
}
next_attractor:
;
}
} else {
for (drone_iterator i = attractors.begin(), j = attractors.end(); i != j; ++i) {
drone* pdi = *i;
pdi->sel = 1;
selected_drones.push_back (pdi);
}
}
print_selected_drones ();
}
void din::trail_drones () {
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone& di = *(*i);
di.trail.add (di.sx, di.y);
}
}
void din::toggle_create_this () {
if (dinfo.create_this) {
toggle_create_drone_pendulum ();
} else {
toggle_create_mesh ();
}
}
void din::toggle_create_drone_pendulum () {
if (create_drone_pend) ;
else {
cons << GREEN << "Click and drag a box to make a drone pendulum, ESC to cancel" << eol;
create_drone_pend = 1;
}
}
void din::toggle_create_mesh () {
if (amd.active) {
cons << RED << "Already making a mesh, please wait for it to finish :)" << eol;
return;
}
if (meshh.create) {
create_drone_mesh ();
meshh.create = 0;
} else {
cons << GREEN << "Click and drag a box to preview drone mesh, ESC to cancel" << eol;
meshh.create = 1;
}
}
void din::stop_creating_mesh () {
meshh.create = 0;
mkb_selector.mesh = 0;
cons << RED << "Stopped creating mesh" << eol;
}
void din::stop_creating_drone_pendulum () {
create_drone_pend = 0;
cons << RED << "Stopped making drone pendulum" << eol;
}
void din::bg () {
drone::proc_conn.clear ();
if (ec && !xforming) ec = ec->eval_conns ();
if (phrasor0.state == phrasor::playing) {
phrasor0.get (tonex, toney);
if (uis.iscur (this) && MENU.track_phrase_position.state) {
const int margin = 10;
int dx = 0;
if (tonex < win.left)
dx = tonex - win.left - margin;
else if (tonex > win.right)
dx = tonex - win.right + margin;
scroll (dx, 0, 0);
}
phrasor0.next ();
}
if (wanding) {
if ((wand.x != tonex) || (wand.y != toney)) {
if (magnitude2 (wand.x, wand.y, tonex, toney) >= drone::wand.dist2) {
wand.x = tonex;
wand.y = toney;
if (SHIFT || CTRL)
;
else
add_drone (wand.x, wand.y);
}
}
}
if (amd.active && !amd.drop && amd (ui_clk())) {
create_drone:
if (amd.i < mkb_selector.rowcol) {
amd.p = mkb_selector.order [amd.i];
int p = 2 * amd.p;
int x = mkb_selector.meshp [p];
int y = mkb_selector.meshp [p + 1];
drone* d = add_drone (x, y);
mkb_selector.meshd[amd.p] = d;
if (dinfo.mesh_vars.apply_to.active) {
float a = ((amd.i % dinfo.mesh_vars.dpp) + 1) * 1. / dinfo.mesh_vars.dpp;
float bpm = a * dinfo.drone_pend.bpm;
d->mod.active = 1;
if (dinfo.mesh_vars.apply_to.am) d->mod.am.bv.set_bpm (bpm);
if (dinfo.mesh_vars.apply_to.fm) d->mod.fm.bv.set_bpm (bpm);
}
if (!dinfo.seloncre) {
d->sel = 1;
selected_drones.push_back (d);
print_selected_drones ();
}
amd.i++;
if (amd.triggert == 0.0) goto create_drone;
} else {
// assign drones to polygons of the mesh
mesh a_mesh;
a_mesh.r = rndr ();
a_mesh.g = rndg ();
a_mesh.b = rndb ();
for (int i = 0, j = mkb_selector.rows - 1; i < j; ++i) {
int ic = i * mkb_selector.cols;
for (int k = 0, l = mkb_selector.cols - 1; k < l; ++k) {
int d0i = ic + k, d1i = d0i + 1;
int d2i = d0i + mkb_selector.cols, d3i = d2i + 1;
drone* d0 = mkb_selector.get_mesh_drone(d0i), *d1 = mkb_selector.get_mesh_drone(d1i);
drone* d2 = mkb_selector.get_mesh_drone(d2i), *d3 = mkb_selector.get_mesh_drone(d3i);
a_mesh.add_poly (d0, d1, d3, d2); // each poly has 4 drones
}
}
meshes.push_back (a_mesh);
++meshh.num;
if (!dinfo.seloncre) print_selected_drones ();
cons << GREEN << "Created a " << dinfo.rows << " x " << dinfo.cols << " mesh with " << mkb_selector.rowcol << " drones" << eol;
amd.reset ();
mkb_selector.clear ();
}
} else {
if (amd.drop) {
cons << RED << "Aborted drone mesh" << eol;
amd.reset ();
}
}
fall_drones ();
rise_drones ();
if (quit == DONT) launch_drones ();
carry_satellites_to_orbit ();
attract_drones ();
track_drones ();
evalchuck ();
modulate_drones ();
evalgravity ();
move_drones_under_gravity ();
trail_drones ();
kill_old_drones ();
modulate_ranges ();
gab.eval ();
}
void din::drawchuck () {
if (MENU.choutline.state) {
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone& di = *(*i);
drone* sat = di.chuck.sat;
if (di.chuck.yes && sat) {
glBegin (GL_LINES);
glColor3f (di.r, di.g, di.b);
glVertex2f (di.sx, di.y);
glColor3f (sat->r, sat->g, sat->b);
glVertex2f (sat->sx, sat->y);
glEnd ();
}
}
}
}
void din::evalchuck () {
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone& di = *(*i);
if (di.chuck.yes) {
di.chuck.cx = di.cx;
di.chuck.cy = di.cy;
}
}
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone& di = *(*i);
if (di.chuck.yes && di.chuck.sun) {
if (di.frozen) {
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);
} else {
rotate_vector (di.chuck.ux, di.chuck.uy, di.chuck.dir * di.chuck.speed * drone::chuckt::apt.rad);
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);
}
}
}
}
void din::changechuckspeed (spinner<float>& sp) {
if (num_selected_drones) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& di = *selected_drones[i];
if (di.chuck.yes) {
float& speed = di.chuck.speed;
speed += sp ();
if (speed < 0.0f) speed = 0.0f;
cons << YELLOW << "Drone " << i << ", speed = " << speed << eol;
RESETCHUCKTRAILS(di)
}
}
} else {
cons << RED_PSD << eol;
}
}
void din::changechucklength (spinner<float>& sp) {
if (num_selected_drones) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& di = *selected_drones[i];
if (di.chuck.yes) {
float& len = di.chuck.len;
len += sp ();
if (len < 0.0f) len = 0.0f;
RESETCHUCKTRAILS(di)
cons << YELLOW << "Drone " << i << ", length = " << len << eol;
}
}
} else {
cons << RED_PSD << eol;
}
}
void din::flipchuckspeed () {
if (num_selected_drones) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& di = *selected_drones[i];
if (di.chuck.yes) di.chuck.dir = -di.chuck.dir;
RESETCHUCKTRAILS(di)
}
} else {
cons << RED_PSD << eol;
}
}
void din::togchuckspeed () {
if (num_selected_drones) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& di = *selected_drones[i];
if (di.chuck.yes) swap (di.chuck.speed, di.chuck.speed0);
RESETCHUCKTRAILS(di)
}
} else {
cons << RED_PSD << eol;
}
}
void din::resetchucktrails (drone& d) {
d.trail.reset ();
if (d.chuck.sat) resetchucktrails (*d.chuck.sat);
}
void din::resetallchucktrails () {
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone& di = *(*i);
if (di.chuck.yes) di.trail.reset ();
}
}
void din::update_drone_pendulum (drone_pendulum_group& g) {
float a = 0.0f, da = 1.0 / (g.n - 1);
for (int i = 0, j = g.n; i < j; ++i) {
drone* pd = g.drones[i];
drone& d = *pd;
mod_params* mods [] = {&d.mod.am, &d.mod.fm};
mod_params& mod = *mods[g.orient];
mod.depth = warp_depth (a) * uis.dpeu.depth.value;
mod.bv.set_bpm (warp_bpm (a)* uis.dpeu.bpm.value);
a += da;
}
}
void din::update_drone_pendulums () {
map<group*, bool> updated;
for (int i = 0, j = drone_pendulums.size (); i < j; ++i) {
drone_pendulum_group* g = drone_pendulums[i];
drone_pendulum_group& gr = *g;
for (int m = 0, n = num_selected_drones; m < n; ++m) {
drone* ds = selected_drones[m];
if ((updated[g] == false) && gr.member (ds)) {
updated[g] = true;
update_drone_pendulum (gr);
}
}
}
}
void din::remove_from_groups (drone* d) {
for (vector<drone_pendulum_group*>::iterator i = drone_pendulums.begin (), j = drone_pendulums.end (); i < j;) {
drone_pendulum_group& gi = *(*i);
if (gi.remove (d)) {
if (gi.n == 0) {
i = drone_pendulums.erase (i);
j = drone_pendulums.end ();
} else ++i;
} else ++i;
}
}
void din::remove_drone_from_mesh (drone* pd) {
if (meshh.num == 0) return;
for (mesh_iterator i = meshes.begin (); i != meshes.end ();) {
mesh& mi = *i;
mi.remove_poly (pd);
if (mi.num_polys == 0) {
i = meshes.erase (i);
--meshh.num;
} else ++i;
}
}
void din::remove_drone_from_pre_mesh (drone* d) {
if (erase (mkb_selector.meshd, d)) amd.drop = 1;
}
drone* din::get_drone (int id) { // get drone given its unique id
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone* pd = *i;
if (pd->id == id) return pd;
}
return 0;
}
void din::load_selected_drones (ifstream& f) {
string ignore;
int n;
f >> ignore >> n;
if (n) {
int did;
selected_drones.resize (n);
for (int m = 0; m < n; ++m) {
f >> did;
drone* sd = get_drone (did);
sd->sel = 1;
selected_drones[m] = sd;
}
print_selected_drones ();
}
num_selected_drones = n;
}
void din::save_selected_drones (ofstream& f) {
f << "selected_drones " << num_selected_drones << spc;
if (num_selected_drones) {
for (int i = 0; i < num_selected_drones; ++i) {
drone* pd = selected_drones[i];
f << pd->id << spc;
}
}
f << endl;
}
void din::make_trackers () {
if (num_selected_drones < 1) {
cons << RED_A2D << eol;
return;
} else if (num_selected_drones == 1) { // toggle tracker
drone* pd = selected_drones[0];
if (pd->tracking) {
remove_tracker (pd);
cons << GREEN << "Selected drone no longer tracks another drone" << eol;
return;
}
cons << RED << "Drone is not tracking any other drone!" << eol;
return;
}
int last = num_selected_drones - 1;
drone* p_tracked_drone = selected_drones [last];
int nl = 0;
for (int i = 0; i < last; ++i) {
drone* pdi = selected_drones [i];
push_back (trackers, pdi);
pdi->tracking = 1;
pdi->tracked_drone = p_tracked_drone;
++nl;
}
if (nl) cons << GREEN << "Number of drones tracking another drone = " << nl << eol;
}
void din::track_drones () {
for (drone_iterator i = trackers.begin (), j = trackers.end (); i != j; ++i) {
drone* pdi = *i;
drone& di = *pdi;
drone& td = *di.tracked_drone;
if (di.tracking == drone::POINT) {
unit_vector (di.vx, di.vy, di.x, di.y, td.x, td.y);
di.ax = di.vy;
di.ay = -di.vx;
} else { // USE
di.vx = td.vx;
di.vy = td.vy;
di.ax = td.ax;
di.ay = td.ay;
}
}
}
void din::evalgravity () {
gravity_t& grav = dinfo.gravity;
if (grav.cmouse.state)
grav.pointt (win_mousex, win_mousey);
for (int i = 0; i < 2; ++i) {
drone* tdi = grav.tracked_drone[i];
if (tdi) {
int dwx = tdi->sx, dwy = tdi->y; // in window space
int& ldwxi = grav.ldwx[i];
int& ldwyi = grav.ldwy[i];
if (dwx != ldwxi || dwy != ldwyi) {
grav.track (i, dwx, dwy);
ldwxi = dwx;
ldwyi = dwy;
}
}
}
}
void din::select_tracked_drones () {
CLEAR_SELECTED_DRONES
for (drone_iterator i = trackers.begin (), j = trackers.end (); i != j; ++i) {
drone* pdi = *i;
drone* ptd = pdi->tracked_drone;
if (ptd->sel == 0) {
ptd->sel = 1;
selected_drones.push_back (ptd);
}
}
print_selected_drones ();
}
void din::remove_tracker (drone* ptd) {
for (drone_iterator i = trackers.begin (), j = trackers.end (); i != j;) {
drone* pdi = *i;
drone& di = *pdi;
if (pdi == ptd || di.tracked_drone == ptd) {
di.tracking = 0;
di.tracked_drone = 0;
i = trackers.erase (i);
j = trackers.end ();
} else ++i;
}
}
void din::sync_drones () {
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
ds.player.x = ds.mod.am.bv.now = ds.mod.fm.bv.now = 0.0f;
}
}
int din::toggle_freeze_drones () {
if (num_selected_drones) {
int nf = 0, nt = 0;
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
if (ds.frozen) nt += ds.thaw (); else nf += ds.freeze ();
}
int r = nf || nt;
if (r) cons << GREEN << "Froze " << nf << " drones, Thawed " << nt << s_drones << eol;
return r;
} else
cons << RED_PSD << eol;
return 0;
}
int din::freeze_drones () {
if (num_selected_drones) {
int nf = 0;
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
if (!ds.frozen) nf += ds.freeze ();
}
if (nf) cons << GREEN << "Froze " << nf << s_drones << eol;
return nf;
} else cons << RED_PSD << eol;
return 0;
}
int din::thaw_drones () {
if (num_selected_drones) {
int nt = 0;
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
if (ds.frozen) nt += ds.thaw ();
}
if (nt) cons << GREEN << "Thawed " << nt << s_drones << eol;
return nt;
} else cons << RED_PSD << eol;
return 0;
}
int din::freeze_orbiters () {
if (num_selected_drones) {
int nf = 0;
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
if (ds.orbiting && (ds.frozen == 0)) nf += ds.freeze ();
}
return nf;
}
return 0;
}
int din::thaw_orbiters () {
xforming = NONE;
if (num_selected_drones) {
int nt = 0;
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
if (ds.orbiting && ds.frozen) nt += ds.thaw ();
}
return nt;
}
return 0;
}
void din::region_begin () {
rgn.left = rgn.right = win_mousex;
rgn.bottom = rgn.top = win_mousey;
if (meshh.create) mkb_selector.set_mesh (meshh.create, dinfo.rows, dinfo.cols);
}
const box<float>& din::region_update () {
rgn.right = win_mousex;
rgn.top = win_mousey;
if (mkb_selector.mesh) {
int s = SHIFT, c = CTRL, sc = s|c;
if (sc) { // equalise width/height
float w = rgn.right - rgn.left, h = rgn.top - rgn.bottom;
float aw = abs(w), ah = abs(h);
if (s) { // equalise to smaller of width, height
if (aw > ah) {
float dw = aw - ah;
int _ve = w < 0? 1:-1;
rgn.right += (_ve * dw);
} else {
float dh = ah - aw;
int _ve = h < 0? 1:-1;
rgn.top += (_ve * dh);
}
} else { // equalise to larger of width, height
if (aw > ah) {
float dw = aw - ah;
int _ve = h < 0? -1:1;
rgn.top += (_ve * dw);
} else {
float dh = ah - aw;
int _ve = w < 0? -1:1;
rgn.right += (_ve * dh);
}
}
}
mkb_selector.gen_mesh_pts (rgn);
}
return rgn;
}
void din::region_end () {
int swp = rgn.calc ();
if (meshh.create) {
if (swp) mkb_selector.gen_mesh_pts (rgn);
create_drone_mesh ();
meshh.create = 0;
} else if (create_drone_pend) {
create_drone_pendulum ();
create_drone_pend = 0;
}
else
find_selected_drones (rgn);
}
void din::region_abort () {
if (meshh.create) stop_creating_mesh ();
if (create_drone_pend) stop_creating_drone_pendulum ();
}
void din::modulate_ranges () {
int nw, nw_2, center, nl, nr, dl, dr, z;
nw = nw_2 = center = nl = nr = dl = dr = z = 0;
for (int i = 0; i < num_ranges; ++i) {
range& ri = ranges[i];
if (ri.mod.active > 0) {
ri.mod.calc ();
// width modulation
nw = ri.mod.fm.initial + ri.mod.fm.result;
switch (ri.fixed) {
case range::LEFT:
dr = nw - ri.extents.width;
range_right_changed (i, dr, 0);
break;
case range::RIGHT:
dl = ri.extents.width - nw;
range_left_changed (i, dl, 0);
break;
default:
nw_2 = nw / 2;
center = (ri.extents.left + ri.extents.right) / 2;
nl = center - nw_2, nr = center + nw_2;
dl = nl - ri.extents.left;
dr = nr - ri.extents.right;
range_left_changed (i, dl, 0);
range_right_changed (i, dr, 0);
break;
}
// height modulation
int nh = ri.mod.am.initial + ri.mod.am.result;
if (nh < 1) nh = 1;
ri.extents.top = BOTTOM + nh;
ri.extents.calc ();
z = 1;
}
}
if (z) {
refresh_all_drones ();
find_visible_ranges ();
}
}
void din::set_ran_mod (int w) {
for (int i = 0; i < num_ranges; ++i) {
range& ri = ranges[i];
ri.mod.active = w;
}
MENU.cb_mod_ran.set_state (ranges[dinfo.sel_range].mod.active, 0);
}
void din::pause_resume_ran_mod () {
for (int i = 0; i < num_ranges; ++i) {
range& ri = ranges[i];
ri.mod.active = -ri.mod.active;
}
}
void din::toggle_ran_mod () {
for (int i = 0; i < num_ranges; ++i) {
range& ri = ranges[i];
ri.mod.active = !ri.mod.active;
}
MENU.cb_mod_ran.set_state (ranges[dinfo.sel_range].mod.active, 0);
}
void din::update_drone_mod_solvers (int w, multi_curve& mx) {
if (w == modulator::AM) {
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
modulator& dm = (*i)->mod;
dm.am.bv.sol.update ();
}
} else {
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
modulator& dm = (*i)->mod;
dm.fm.bv.sol.update ();
}
}
}
void din::update_range_mod_solvers (int w, multi_curve& mx) {
if (w == modulator::AM) {
for (int i = 0; i < num_ranges; ++i) {
modulator& rm = ranges[i].mod;
rm.am.bv.sol.update (); // am for width
}
} else {
for (int i = 0; i < num_ranges; ++i) {
modulator& rm = ranges[i].mod;
rm.fm.bv.sol.update (); // fm for height
}
}
}
void din::snap_drones (int v) {
if (num_selected_drones) {
int nt[2] = {0};
static const char* what_str1 [] = {"Unsnapped ", "Snapped "};
if (v == -1) { // toggle
for (int i = 0; i < num_selected_drones; ++i) {
drone* pdi = selected_drones[i];
pdi->snap = !pdi->snap;
++nt[pdi->snap];
}
cons << "Snapped " << nt[1] << " drones, Unsnapped " << nt[0] << s_drones << eol;
} else { // set
for (int i = 0; i < num_selected_drones; ++i) {
drone* pdi = selected_drones[i];
pdi->snap = v;
}
cons << GREEN << what_str1[v] << num_selected_drones << " drones" << eol;
}
} else {
cons << RED_PSD << eol;
}
}
void din::pos_afx_vel (int v) {
int nm [2] = {0};
if (num_selected_drones) {
if (v == -1) { // toggle
for (int i = 0; i < num_selected_drones; ++i) {
drone* pdi = selected_drones[i];
pdi->posafxvel.yes = !pdi->posafxvel.yes;
++nm[pdi->posafxvel.yes];
}
cons << GREEN << "Position affects velocity for " << nm[1] << " drones, Unset for " << nm[0] << s_drones << eol;
} else { // set
for (int i = 0; i < num_selected_drones; ++i) {
drone* pdi = selected_drones[i];
pdi->posafxvel.yes = v;
}
static const char* strs[] = {"Unset", "Set"};
cons << GREEN << strs[v] << " Position affects velocity for " << num_selected_drones << s_drones << eol;
}
} else {
cons << RED_PSD << eol;
}
}
void din::select_all_browsed_drones (int bd) {
selected_drones.resize (num_browsed_drones);
for (int i = 0; i < num_browsed_drones; ++i) {
drone* pdb = browsed_drones[i];
pdb->sel = 1;
selected_drones[i] = pdb;
}
print_selected_drones ();
browsed_drone = bd;
MENU.sp_browse_drone.set_value (browsed_drone);
}
void din::browse_drone (int db) {
if (num_browsed_drones) {
clear_selected_drones ();
browsed_drone += db;
if (browsed_drone > last_browseable_drone) { // select all browsed drones
select_all_browsed_drones (-1);
return;
} else if (browsed_drone < 0) {
select_all_browsed_drones (num_browsed_drones);
return;
}
drone* pdb = browsed_drones [browsed_drone];
pdb->sel = 1;
num_selected_drones = 1;
selected_drones.resize (num_selected_drones);
selected_drones[0] = pdb;
sprintf (BUFFER, "Browsed drone %d of %d", browsed_drone+1, num_browsed_drones);
cons << GREEN << BUFFER;
drone::chuckt& chuck = pdb->chuck;
if (chuck.yes) chuck.print ();
cons << eol;
MENU.sp_browse_drone.set_value (browsed_drone);
} else {
cons << RED << "No drones to browse, make a new selection" << eol;
}
}
void din::browse_range (int dr) {
dinfo.sel_range += dr;
clamp (0, dinfo.sel_range, last_range);
MENU.load_range (dinfo.sel_range);
}
void din::all_ranges_width_changed () {
float a = 0.0f, da = 1.0f / last_range;
extern solver sol_ran_width;
int w = 0;
float s = 0.0f;
for (int i = 0; i < num_ranges; ++i) {
s = sol_ran_width (a);
w = s * WIDTH;
if (w < 1) w = 1;
set_range_width (i, w);
a += da;
}
}
void din::all_ranges_height_changed () {
float a = 0.0f, da = 1.0f / last_range;
extern solver sol_ran_height;
int h = 0;
float s = 0.0f;
for (int i = 0; i < num_ranges; ++i) {
s = sol_ran_height (a);
h = s * HEIGHT;
if (h < 1) h = 1;
set_range_height (i, h);
a += da;
}
}
void din::draw_vol_dist () {
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
const float c = 1.0f, b = 0.9f;
float yb, yt;
int xl, xr;
float a, da;
float v, vc;
for (int i = visl, j = visr + 1; i < j; ++i) {
range& R = ranges[i];
const int dy = min (dinfo.dist.pix, R.extents.height);
yb = R.extents.bottom; yt = R.extents.top;
xl = R.extents.left; xr = R.extents.right;
a = 0.0f; da = dy * R.extents.height_1;
v = vc = 0.0f;
glBegin (GL_QUAD_STRIP);
while (yb < yt) {
v = warp_vol (a);
vc = v * c;
glColor4f (vc, 0, vc, b);
glVertex2f (xl, yb);
glVertex2f (xr, yb);
yb += dy;
a += da;
}
a = 1.0f;
v = warp_vol (a);
vc = v * c;
glColor4f (vc, 0, vc, b);
glVertex2f (xl, yt);
glVertex2f (xr, yt);
glEnd ();
}
glDisable (GL_BLEND);
}
void din::draw_pitch_dist () {
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
const float c = 1.0f, b = 0.5f;
float yb, yt;
int xl, xr;
float a, da;
float p, pc;
for (int i = visl, j = visr + 1; i < j; ++i) {
range& R = ranges[i];
const int dx = min (dinfo.dist.pix, R.extents.width);
yb = R.extents.bottom; yt = R.extents.top;
xl = R.extents.left; xr = R.extents.right;
a = 0.0f; da = dx * R.extents.width_1;
p = pc = 0.0f;
glBegin (GL_QUAD_STRIP);
while (xl < xr) {
p = warp_pitch (a);
pc = p * c;
glColor4f (0, pc, pc, b);
glVertex2f (xl, yb);
glVertex2f (xl, yt);
xl += dx;
a += da;
}
a = 1.0f;
p = warp_pitch (a);
pc = p * c;
glColor4f (0, pc, pc, b);
glVertex2f (xr, yb);
glVertex2f (xr, yt);
glEnd ();
}
glDisable (GL_BLEND);
}
void din::noise_interpolator_changed () {
for (drone_iterator i = drones.begin(), j = drones.end(); i != j; ++i) {
drone& di = *(*i);
di.nsr.warp (&noiser::interp);
}
}
int din::can_connect (drone* d1, drone* d2) {
if (d1 == d2) return 0; // no self connection
if (d2->nconn)
for (drone_iterator p = d2->connections.begin (), q = d2->connections.end(); p != q; ++p)
if (d1 == *p) return 0; // already connected
return 1;
}
void din::calc_stepz (const string& fld) {
nstepz = 0;
stepz.clear ();
int p;
map<int, bool> exists;
string str;
stringstream ss1 (fld);
while (ss1.eof() == 0) {
ss1 >> str;
stringstream ss2 (str);
ss2 >> p;
if (p > 0 && (exists[p] == false)) {
stepz.push_back (p);
++nstepz;
exists[p] = true;
}
}
}
void din::alloc_conns () {
if (totcon > con_size) {
if (con_pts) delete[] con_pts;
if (con_clr) delete[] con_clr;
con_pts = new float [totcon * 2 * 2];
con_clr = new float [totcon * 2 * 3];
con_size = totcon;
}
}
int din::disconnect_drones () {
if (num_selected_drones) {
if (MENU.trackcon.state == 0) {
for (int i = 0; i < num_selected_drones; ++i) {
drone* pd = selected_drones[i];
remove_connections (pd);
if (pd->tracking) {
erase (trackers, pd);
pd->tracking = 0;
pd->tracked_drone = 0;
}
}
} else {
for (int i = 0; i < num_selected_drones; ++i) remove_connections (selected_drones[i]);
}
return 1;
} else cons << RED_PSD << eol;
return 0;
}
void din::remove_connections (drone* pd) {
// remove connections to pd
for (drone_iterator i = drones.begin (), j = drones.end (); i != j; ++i) {
drone* pdi = *i;
drone& di = *pdi;
if (di.nconn && pdi != pd) {
list<double>::iterator mi = di.mags.begin ();
for (drone_iterator p = di.connections.begin (), q = di.connections.end(); p != q;) {
drone* pdp = *p;
if (pdp == pd) {
p = di.connections.erase (p);
q = di.connections.end ();
mi = di.mags.erase (mi);
--di.nconn;
--totcon;
} else {
++p;
++mi;
}
}
}
}
// remove connections from pd
if (pd->nconn) {
totcon -= pd->nconn;
pd->nconn = 0;
pd->connections.clear ();
pd->mags.clear ();
}
_2totcon = 2 * totcon;
/*for (vector<connect>::iterator i = conns.begin (), j = conns.end (); i != j;) {
connect& ci = *i;
if (ci.d1 == pd || ci.d2 == pd) {
i = conns.erase (i);
j = conns.end ();
} else
++i;
}*/
}
/*void din::dirty_connection (drone* d) {
for (int i = 0, j = conns.size (); i < j; ++i) {
connect& ci = conns[i];
if (ci.d1 == d || ci.d2 == d) ci.dirty = 1;
}
}
void din::dirty_connections () {
for (int i = 0; i < num_selected_drones; ++i) {
drone* pdi = selected_drones[i];
dirty_connection (pdi);
}
}*/
void din::draw_connections () {
if (totcon == 0) return;
int p = 0, q = 0;
map<drone*, bool> drawn;
for (drone_iterator i = drones.begin (), j = drones.end (); i != j; ++i) {
drone& di = *(*i);
if (di.nconn) {
for (drone_iterator s = di.connections.begin (), t = di.connections.end(); s != t; ++s) {
con_clr[q++] = di.r;
con_clr[q++] = di.g;
con_clr[q++] = di.b;
drone& dj = *(*s);
con_clr[q++] = dj.r;
con_clr[q++] = dj.g;
con_clr[q++] = dj.b;
con_pts[p++]=di.sx;
con_pts[p++]=di.y;
con_pts[p++]=dj.sx;
con_pts[p++]=dj.y;
}
}
}
glEnableClientState (GL_COLOR_ARRAY);
glColorPointer (3, GL_FLOAT, 0, con_clr);
glVertexPointer (2, GL_FLOAT, 0, con_pts);
glDrawArrays (GL_LINES, 0, _2totcon);
glDisableClientState (GL_COLOR_ARRAY);
}
void din::reset_drone_arrows () {
if (num_selected_drones) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
ds.arrow.reset ();
}
} else cons << RED_PSD << eol;
}
void din::gabber::abort () {
for (drone_iterator i = drones.begin (), j = drones.end (); i != j; ++i) {
drone& di = *(*i);
di.tovol = di.gab.amount;
}
drones.clear ();
n = 0;
cons << RED << "Aborted " << what << eol;
}
void din::gabber::set (din* dd, float t, const string& w, float tdiv, int fid) {
int ns = dd->num_selected_drones;
if (ns) {
if (n) abort ();
for (int i = 0; i < ns; ++i) {
drone* pds = dd->selected_drones[i];
drone& ds = *pds;
//if (!equals (ds.gab.amount, t)) {
ds.gab.set (ds.gab.amount, t * ds.tovol, 1, max (0.0f, MENU.gabt()) / tdiv);
ds.finl = drone::fins[fid];
drones.push_back (pds);
++n;
//}
}
if (n) {
what = w;
cons << YELLOW << "Started " << what << spc << n << TOGO << eol;
}
} else {
cons << RED_PSD << eol;
}
}
void din::gabber::eval () {
if (n) {
for (drone_iterator i = drones.begin (), j = drones.end (); i != j;) {
drone* pdi = *i;
drone& di = *pdi;
di.update_pv = drone::INTERPOLATE;
if (di.gab.eval () == 0) {
di.tovol = di.gab.start;
i = drones.erase (i);
j = drones.end ();
if (di.finl) di.finl->finished (din0, pdi);
if (--n == 0) cons << GREEN << "Finished " << what << eol; else cons << YELLOW << what << spc << n << TOGO << eol;
} else {
++i;
}
}
}
}
void din::gabber::erase (drone* d) {
if (::erase (drones, d)) --n;
}
void din::gabber::setgabt () {
if (n)
for (drone_iterator i = drones.begin (), j = drones.end (); i != j; ++i)
(*i)->gab.delta_time = MENU.gabt();
}
void din::setdronevol (spinner<float>& s) {
if (num_selected_drones) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
ds.gab.amount += s();
ds.tovol = ds.gab.amount;
ds.update_pv = drone::EMPLACE;
cons << "Drone " << i << " volume = " << ds.gab.amount << eol;
}
} else
cons << RED_PSD << eol;
}
void din::drone2noise () {
gab.set (this, 0.0f, "Drone > Noise", 2.0f, 1);
}
void din::noise2drone () {
gab.set (this, 0.0f, "Noise > Drone", 2.0f, 2);
}
void drone::drone2noise::finished (din& mkb, drone* pdi) {
drone& di = *pdi;
di.is = drone::NOISE;
di.setnoise ();
di.r = di.g = di.b = 1.0f;
di.gab.set (di.gab.amount, 1.0f * di.tovol, 1, MENU.gabt() / 2.0f);
di.finl = 0;
mkb.gab.drones.push_back (pdi);
++mkb.gab.n;
}
void drone::noise2drone::finished (din& mkb, drone* pdi) {
drone& di = *pdi;
di.is = drone::DRONE;
di.setcolor ();
di.gab.set (di.gab.amount, 1.0f * di.tovol, 1, MENU.gabt() / 2.0f);
di.finl = 0;
mkb.gab.drones.push_back (pdi);
++mkb.gab.n;
}
void din::set_random_color () {
rndr.set (MENU.s_red_min (), MENU.s_red_max());
rndg.set (MENU.s_green_min (), MENU.s_green_max());
rndb.set (MENU.s_blue_min (), MENU.s_blue_max());
}
void din::gotpoint () {
if (!SHIFT) dinfo.cen.x += delta_mousex;
if (!CTRL) dinfo.cen.y -= delta_mousey;
/*dinfo.cen.x = win_mousex;
dinfo.cen.y = win_mousey;*/
}
void din::ranchkdro () {
for (drone_iterator i = drones.begin (), j = drones.end (); i != j; ++i) {
drone& di = *(*i);
clamp (0, di.range, last_range);
}
}
void din::delselran () {
// delete selected range
if (num_ranges == 1) {
cons << RED << "Will not delete the only range!" << eol;
return;
}
int& sr = dinfo.sel_range;
vector<range>::iterator rb = ranges.begin();
if (sr == 0 || sr == last_range)
;
else {
int p = sr - 1, q = sr + 1;
range& rp = ranges[p];
range& rq = ranges[q];
range& rs = ranges[sr];
rp.notes[1] = rq.notes[0];
rp.intervals[1] = rq.intervals[0];
for (int i = sr + 1; i < num_ranges; ++i) {
range& ri = ranges[i];
ri.extents.move (-rs.extents.width, 0);
}
}
ranges.erase (rb + sr);
initranpar (num_ranges - 1);
ranchkdro ();
refresh_all_drones ();
find_current_range ();
}
mkb_selector_t::mkb_selector_t () : of_prox_far (proximity_orderer::FARTHEST) {
orderers[0]=&of_asc;
orderers[1]=&of_desc;
orderers[2]=&of_asc_cols;
orderers[3]=&of_desc_cols;
orderers[4]=&of_rnd;
orderers[5]=&of_prox_near;
orderers[6]=&of_prox_far;
}
void mkb_selector_t::draw (const box<float>& region) {
if (din0.dinfo.cen.op) din0.dinfo.cen.draw ();
else {
if (mesh) {
glPointSize (4);
glVertexPointer (2, GL_FLOAT, 0, meshp);
glColor3f (1, 1, 1);
glDrawArrays (GL_POINTS, 0, rowcol);
glPointSize (1);
}
cross = din0.create_drone_pend | din0.meshh.create;
box_selector::draw (region);
}
}
int mkb_selector_t::handle_input () {
if (lmb) {
if (lmb_clicked == 0) {
if (din0.wanding || din0.moving_drones || din0.phrasor0.isrecording()) {
lmb_clicked = 1;
return 1;
}
} else
return 1;
} else {
if (lmb_clicked) {
lmb_clicked = 0;
if (din0.moving_drones) din0.set_moving_drones (0);
din0.stopwanding ();
if (din0.phrasor0.isrecording()) din0.finish_phrase_recording ();
return 1;
}
}
int r = din0.dinfo.cen.handle_input();
if (r == 0) {
if (MENU.cb_show_gravity.state)
r = din0.dinfo.gravity.handle_input2 ();
else
r = 0;
}
if (r == 0) r = box_selector::handle_input ();
return r;
}
void drone::setcolor () {
if (is == drone::NOISE)
r = g = b = 1;
else {
color& gc = MENU.colorer ();
r = gc.r;
g = gc.g;
b = gc.b;
}
}
int din::stopwanding () {
if (wanding) {// && (phrasor0.state != phrasor::playing)) {
wanding = 0;
cons << RED << "Stopped wanding drones!" << eol;
return 1;
}
return 0;
}
void din::rail (int dir, double scl) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& di = *selected_drones[i];
di.set_center (di.cx + dir * scl * di.vx, di.cy + dir * scl * di.vy);
}
}
void din::strafe (int dir, double scl) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& di = *selected_drones[i];
di.set_center (di.cx + dir * scl * di.vy, di.cy - dir * scl * di.vx);
}
}
void din::flip_drone_motion () {
if (num_selected_drones) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& di = *selected_drones[i];
if (di.orbiting) {
di.vrev *= -1;
} else {
if (di.autorot.v.yes)
di.autorot.v.dir *= -1;
else {
di.vx = -di.vx;
di.vy = -di.vy;
}
if (di.autorot.a.yes)
di.autorot.a.dir *= -1;
else {
di.ax = -di.ax;
di.ay = -di.ay;
}
}
di.mod.am.bv.reverse ();
di.mod.fm.bv.reverse ();
if (di.chuck.yes) {
di.chuck.dir = -di.chuck.dir;
RESETCHUCKTRAILS(di)
}
}
} else cons << RED_PSD << eol;
}
void din::reverse_drone_modulation () {
if (num_selected_drones) {
if (dinfo.revmod == 0) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& di = *selected_drones[i];
di.mod.am.bv.reverse ();
di.mod.fm.bv.reverse ();
}
} else {
for (int i = 0; i < num_selected_drones; ++i) {
drone& di = *selected_drones[i];
beat2value* bvi [] = {0, &di.mod.am.bv, &di.mod.fm.bv};
bvi[dinfo.revmod]->reverse ();
}
}
} else cons << RED_PSD << eol;
}
/*void copyis (drone& t, drone& s) {
t.is = s.is;
if (s.is == drone::BINAURAL) {
t.sol2 (&din0.drone_wave);
t.player2.set_wave (&t.sol2);
}
}*/
void din::change_drone_sep (spinner<float>& s) {
if (num_selected_drones) {
float dhz = 0.0f, dsep = 0.0f;
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
dhz = s();
hz2step (dhz, dsep);
ds.sep += dsep;
if (MENU.sep0.state && ds.sep < 0) ds.sep = 0;
step2hz (ds.sep, dhz);
cons << GREEN << "Drone: " << i << ", separation = " << dhz << " Hz" << eol;
ds.update_pv = drone::EMPLACE;
}
} else {
cons << RED_PSD << eol;
}
}
/*
if (num_selected_drones) {
for (int i = 0; i < num_selected_drones; ++i) {
drone& ds = *selected_drones[i];
}
} else cons << RED_PSD << eol;
*/