1 /*
2 * drone.cc
3 * DIN Is Noise is copyright (c) 2006-2021 Jagannathan Sampath
4 * DIN Is Noise is released under GNU Public License 2.0
5 * For more information, please visit https://dinisnoise.org/
6 */
7 
8 #include "din.h"
9 #include "drone.h"
10 #include "console.h"
11 #include "audio.h"
12 #include "utils.h"
13 #include "vector2d.h"
14 #include <math.h>
15 using namespace std;
16 
17 extern multi_curve drone_mod_am_crv, drone_mod_fm_crv;
18 extern solver warp_vol, warp_pitch;
19 extern const char spc;
20 
21 extern void get (float& g, float& gx, float& gy, defvelaccel& dva);
22 extern int gethandlesize ();
23 extern int gettrailsize ();
24 extern const float TWO_PI;
25 
setis()26 void drone::setis () {
27   if (IS == DRONE_OR_NOISE) is = get_rand_bit (); else is = IS;
28 }
29 
drone(float bottom)30 drone::drone (float bottom) : mod (&drone_mod_fm_crv, &drone_mod_am_crv) {
31 
32   setis ();
33   step = vol = 0;
34   range = 0;
35   pos = 0.0f;
36   r = g = b = 0.5f;
37   cx = cy = 0;
38 	x = y = 0;
39   dy = 0;
40   xv = x; yv = y;
41   xa = x; ya = y;
42 	sx = 0;
43   sel = 0;
44   state = DEAD;
45 	frozen = 0;
46 	froze_at = 0;
47   handle_size = gethandlesize ();
48   trail.set (gettrailsize());
49 	id = ++UID;
50   get (V, vx, vy, v0);
51 	v_mult = 1.0f;
52   get (A, ax, ay, a0);
53   gravity = 0;
54   attractor = 0;
55 	orbiting = 0;
56   launcher = 0;
57   tracking = 0;
58   tracked_drone = 0;
59   dpm = 60;
60 	++ref;
61   launched_by = 0;
62   reincarnate = 0;
63   switch (ARE) {
64     case IMMORTAL:
65       birth = -1;
66       break;
67     case MORTAL:
68       birth = ui_clk ();
69       break;
70     case REINCARNATE:
71       birth = ui_clk ();
72       reincarnate = 1;
73       break;
74   }
75 	life = LIFETIME;
76 	insert = INSERTTIME;
77 	target = 0;
78 	cur_target = 0;
79 	num_targets = 0;
80   update_pv = UNSET;
81 	snap = 0;
82 	nconn = 0;
83 	type = CHAIN;
84   gab.set (1.0f, 0.0f, 0, 1.0f);
85   tovol = 0.0f;
86   finl = 0;
87   note_num = -1;
88 }
89 
~drone()90 drone::~drone () {
91 	--ref;
92 }
93 
94 
move_center()95 void drone::move_center () {
96 	cx += (x - xi);
97 	cy += (y - yi);
98 }
99 
eval_conns()100 drone* drone::eval_conns () {
101 	if (nconn) {
102 		int n = 0;
103 		proc_conn [this] = true;
104 		list<double>::iterator mi = mags.begin();
105 		drone_iterator p = connections.begin ();
106 		drone* c0 = *p;
107 		for (drone_iterator q = connections.end (); p != q; ++p, ++mi) {
108 			drone* pdc = *p;
109 			if (proc_conn[pdc] == false) {
110 				proc_conn [pdc] = true;
111 				drone& dc = *pdc;
112 				double now = magnitude (cx, cy, dc.cx, dc.cy);
113 				double org = *mi;
114         if (now > org) {
115           double lead = STIFFNESS * (now - org);
116           float ux, uy; unit_vector<float, int> (ux, uy, dc.cx, dc.cy, cx, cy);
117           dc.set_center (dc.cx + lead * ux, dc.cy + lead * uy);
118           ++n;
119         }
120 			}
121 		}
122 		if (n) return this; else return c0;
123 	}
124 	return 0;
125 }
126 
remagconns()127 void drone::remagconns () {
128   list<double>::iterator mi = mags.begin();
129   drone_iterator p = connections.begin ();
130   for (drone_iterator q = connections.end (); p != q; ++p, ++mi) {
131     drone* pd = *p;
132     *mi = magnitude<double> (cx, cy, pd->cx, pd->cy);
133   }
134 }
135 
set_center(float xx,float yy,int e)136 void drone::set_center (float xx, float yy, int e) {
137 	cx = xx;
138 	cy = yy;
139 	if (frozen) set_pos (cx + mod.fm.result, cy + mod.am.result);
140 	if (e) eval_conns ();
141 }
142 
set_pos(float xx,float yy)143 void drone::set_pos (float xx, float yy) {
144 
145 	// position
146 	x = xx;
147 	y = yy;
148 
149   // position affects velocity?
150   if (posafxvel.yes && !autorot.v.yes && !gravity && !tracking && !orbiting) {
151     double mag = magnitude (posafxvel.pt.x, posafxvel.pt.y, x, y);
152     if (mag > posafxvelt::minmag) {
153       direction (vx, vy, posafxvel.pt.x, posafxvel.pt.y, x, y);
154       vx /= mag;
155       vy /= mag;
156       posafxvel.pt.x = x;
157       posafxvel.pt.y = y;
158     }
159   }
160 
161   // locate range on microtonal-keyboard
162   range = din0.find_range (x, range);
163   ::range& dr = din0.ranges[range];
164 
165   // pitch position in range
166   int delta_left = x - dr.extents.left;
167   pos = delta_left * 1.0f / dr.extents.width;
168   if (pos < 0 || pos > 1.0f) ; else pos = warp_pitch (pos);
169 
170   // pitch snap
171   if (snap) {
172     if (pos < din0.dinfo.snap.left)
173       note_num = 0;
174     else if (pos > din0.dinfo.snap.right)
175       note_num = 1;
176     else
177       goto normal;
178     if (note_num) {
179       pos = 1;
180       sx = dr.extents.right;
181     } else {
182       pos = 0;
183       sx = dr.extents.left;
184     }
185   } else {
186     normal:
187     note_num = -1;
188     sx = x;
189   }
190 
191 	calc_handle ();
192 
193   update_pv = EMPLACE; // update pitch volume b4 rendering drones
194 
195 }
196 
calc_handle()197 void drone::calc_handle () {
198   //handle (sx - handle_size, round(y) - handle_size, sx + handle_size, round(y) + handle_size);
199   handle (sx - handle_size, y - handle_size, sx + handle_size, y + handle_size);
200 }
201 
update_pitch_volume()202 void drone::update_pitch_volume () {
203 
204   ::range& dr = din0.ranges[range];
205   dy = y - BOTTOM;
206   float iv = dy * 1.0f / dr.extents.height;
207   if (dy < 0) vol = -warp_vol (-iv); else vol = warp_vol (iv);
208 
209   if (note_num == -1) {
210     float n0step = dr.notes[0].step, n1step = dr.notes[1].step;
211     float nstep = n0step + pos * (n1step - n0step);
212     if (nstep > 0) step = nstep;
213   } else {
214     step = dr.notes[note_num].step;
215   }
216 
217   if (is == DRONE) {
218     float v = fdr.amount * mastervolume * gab.amount * vol;
219     player.set_interpolated_pitch_volume (step, v);
220   } else
221     setnoise ();
222 
223   --update_pv;
224 
225 }
226 
227 
setnoise()228 void drone::setnoise () {
229   nsr.set_samples (1.0f / step);
230   nsr.set_spread ( fabs(vol) );
231 }
232 
233 
234 
change_bpm(mod_params & mp,float delta)235 void drone::change_bpm (mod_params& mp, float delta) {
236 	mp.bv.set_bpm (mp.bv.bpm + delta);
237 }
238 
change_bpm(int i,int what,float delta)239 void drone::change_bpm (int i, int what, float delta) {
240   if (what == modulator::FM) {
241     change_bpm (mod.fm, delta);
242     cons << "drone: " << i << ", FM bpm = " << mod.fm.bv.bpm << eol;
243   } else {
244     change_bpm (mod.am, delta);
245     cons << "drone: " << i << ", AM bpm = " << mod.am.bv.bpm << eol;
246   }
247 }
248 
change_depth(int i,int what,float delta)249 void drone::change_depth (int i, int what, float delta) {
250   if (what == modulator::FM) {
251     mod.fm.depth += delta;
252     cons << "drone: " << i << ", FM depth = " << mod.fm.depth << eol;
253   } else {
254     mod.am.depth += delta;
255     cons << "drone: " << i << ", AM depth = " << mod.am.depth << eol;
256   }
257 }
258 
clear_targets()259 void drone::clear_targets () {
260 	targets.clear ();
261 	cur_target = 0;
262 	num_targets = 0;
263 }
264 
handle_time_pass()265 void drone::handle_time_pass () {
266 	double tp = ui_clk() - froze_at;
267   mod.t += tp;
268   if (autorot.v.autoflip.yes) autorot.v.tik.startt += tp;
269   if (autorot.a.autoflip.yes) autorot.a.tik.startt += tp;
270   fdr.start_time += tp;
271 	if (birth != -1) birth += tp;
272 	if (launcher) launch_every.startt += tp;
273 }
274 
freeze()275 int drone::freeze () {
276 	++frozen;
277 	froze_at = ui_clk ();
278 	update_pv = drone::EMPLACE;
279   if (chuck.yes && chuckt::autoresettrails && chuck.sat) chuck.resettrail (chuck.sat);
280 	return 1;
281 }
282 
thaw()283 int drone::thaw () {
284 	if (--frozen < 1) {
285 		frozen = 0;
286 		handle_time_pass ();
287     if (chuck.yes && chuckt::autoresettrails && chuck.sat) chuck.resettrail (chuck.sat);
288 		return 1;
289 	}
290 	return 0;
291 }
292 
group(std::vector<drone * > mem,int _n)293 group::group (std::vector<drone*> mem, int _n) {
294 	n = _n;
295 	if (n) {
296 		drones.resize (n);
297 		for (int i = 0; i < n; ++i) drones[i] = mem[i];
298 	}
299 }
300 
operator <<(std::ostream & f,drone::arrowt & aw)301 std::ostream& operator<< (std::ostream& f, drone::arrowt& aw) {
302 	f << aw.u << spc << aw.v << spc << aw.t << spc << aw.cap;
303 	return f;
304 }
305 
operator >>(std::istream & f,drone::arrowt & aw)306 std::istream& operator>> (std::istream& f, drone::arrowt& aw) {
307   f >> aw.u >> aw.v >> aw.t >> aw.cap;
308   return f;
309 }
310 
operator <<(std::ostream & f,drone::chuckt & ch)311 std::ostream& operator<< (std::ostream& f, drone::chuckt& ch) {
312   f << ch.len << spc << ch.speed << spc << ch.dir << spc << ch.ux << spc << ch.uy << spc;
313   if (ch.sun) f << ch.sun->id << spc; else f << 0 << spc;
314   if (ch.sat) f << ch.sat->id; else f << 0;
315   return f;
316 }
317 
operator >>(std::istream & f,drone::chuckt & ch)318 std::istream& operator>> (std::istream& f, drone::chuckt& ch) {
319   f >> ch.len >> ch.speed >> ch.dir >> ch.ux >> ch.uy;
320   uintptr_t sun; f >> sun; ch.sun = (drone*) sun;
321   uintptr_t sat; f >> sat; ch.sat = (drone*) sat;
322   return f;
323 }
324 
re(drone & p)325 void drone::chuckt::re (drone& p) {
326   if (sun) p.chuck.len = unit_vector (p.chuck.ux, p.chuck.uy, sun->cx, sun->cy, p.cx, p.cy);
327 }
328 
print()329 void drone::chuckt::print () {
330   stringstream ss;
331   ss << " || Speeds: This = " << speed;
332   if (sun) {
333     ss << ", Previous = " << sun->chuck.speed;
334   } else ss << ", Previous = none";
335   if (sat) {
336     ss << ", Next = " << sat->chuck.speed;
337   } else
338     ss << ", Next = none";
339   cons << ss.str ();
340 }
341 
resettrail(drone * d)342 void drone::chuckt::resettrail (drone* d) {
343   d->trail.reset ();
344   drone* sat = d->chuck.sat;
345   if (sat) sat->chuck.resettrail (sat);
346 }
347 
348 
operator <<(std::ostream & f,anglet & a)349 std::ostream& operator<< (std::ostream& f, anglet& a) {
350   f << a.deg;
351   return f;
352 }
353 
operator >>(std::istream & f,anglet & a)354 std::istream& operator>> (std::istream& f, anglet& a) {
355   f >> a.deg;
356   a.torad ();
357   return f;
358 }
359 
360 /*connect::connect (drone* _d1, drone* _d2) {
361 	dirty = 1;
362 	d1 = _d1;
363 	d2 = _d2;
364 	mag = magnitude (d1->cx, d1->cy, d2->cx, d2->cy);
365 	p1.x = d1->cx; p1.y = d1->cy;
366 	p2.x = d2->cx; p2.y = d2->cy;
367 	align_vel ();
368 }
369 
370 void connect::align_vel () {
371 	unit_vector<float,float>(d1->vx, d1->vy, d1->cx, d1->cy, d2->cx, d2->cy);
372 	//d2->vx = d1->vx;
373 	//d2->vy = d1->vy;
374 }
375 
376 int connect::eval (drone** ret) {
377 	double magnew = magnitude (d1->cx, d1->cy, d2->cx, d2->cy);
378 	if (magnew > mag) {
379 		float ux, uy; unit_vector (ux, uy, d1->cx, d1->cy, d2->cx, d2->cy);
380 		double lead = magnew - mag;
381 		int d1mov = ((p1.x != d1->cx) || (p1.y != d1->cy));
382 		int d2mov = ((p2.x != d2->cx) || (p2.y != d2->cy));
383 		int d12mov = d1mov && d2mov;
384 		if (d12mov) {
385 			lead /= 2.0;
386 			d1->set_center (d1->cx + lead * ux, d1->cy + lead * uy);
387 			d2->set_center (d2->cx - lead * ux, d2->cy - lead * uy);
388 			ret[0] = d1;
389 			ret[1] = d2;
390 		} else {
391 			if (d1mov) {
392 				d2->set_center (d2->cx - lead * ux, d2->cy - lead * uy);
393 				ret[0] = d2;
394 				ret[1] = 0;
395 			} else if (d2mov) {
396 				d1->set_center (d1->cx + lead * ux, d1->cy + lead * uy);
397 				ret[0] = d1;
398 				ret[1] = 0;
399 			}
400 		}
401 		align_vel ();
402 		p1.x = d1->cx; p1.y = d1->cy;
403 		p2.x = d2->cx; p2.y = d2->cy;
404 		dirty = 0;
405 		return 1;
406 	}
407 	dirty = 0;
408 	return 0;
409 }
410 
411 void connect::draw () {
412 	glBegin (GL_LINES);
413 		glColor3f (d1->r, d1->g, d1->b);
414 		glVertex2i (d1->cx, d1->cy);
415 		glColor3f (d2->r, d2->g, d2->b);
416 		glVertex2i (d2->cx, d2->cy);
417 	glEnd ();
418 }*/
419