Subversion Repositories DIN Is Noise

Rev

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

Rev Author Line No. Line
1528 jag 1
/*
2
* mondrian.h
3
* inspired by the works of Piet Mondrian
1713 jag 4
* DIN Is Noise is released under GNU Public License 2.0
2008 jag 5
* DIN Is Noise is copyright (c) 2006-2023 Jagannathan Sampath
1528 jag 6
* For more information, please visit https://dinisnoise.org/
7
*/
8
 
9
#ifndef __mondrian__
10
#define __mondrian__
11
 
12
#include "point.h"
13
#include "viewwin.h"
14
#include "ui.h"
15
#include "box_selector.h"
16
#include "textboard.h"
17
#include "triggered_note.h"
18
#include "listeners.h"
19
#include "curve_editor.h"
20
#include "help.h"
21
#include "instrument.h"
22
#include "rect.h"
23
#include "ball.h"
24
#include "slit.h"
25
#include "alarm.h"
26
#include "spinner.h"
27
#include <string>
28
#include <vector>
29
 
30
typedef std::list<ball*>::iterator balls_iterator;
31
 
32
struct draw_ball_t {
33
  int position;
34
  int heading;
35
  int trails;
36
  draw_ball_t () { position = heading = trails = 1;}
37
};
38
 
2049 jag 39
struct field;
40
struct mondrian : instrument, scale_listener, region_listener, split_listener, typing_listener {
1528 jag 41
 
42
  mondrian ();
43
  ~mondrian ();
44
 
45
  void enter ();
46
  void leave ();
2049 jag 47
  void typing (field& f);
1528 jag 48
 
49
  multi_curve wave; // waveform shared by all balls
50
  curve_editor waved;  // waveform editor
51
  wave_listener wavlis;
52
  void update_waveform (multi_curve& crv);
53
 
54
  multi_curve attack, decay; // attack and decay curves shared by all balls
55
  curve_editor attacked, decayed; // attack and decay curve editors
56
  attack_listener attacklis;
57
  decay_listener decaylis;
58
  void update_attack ();
59
  void update_decay ();
60
  float delta_attack_time, delta_decay_time;
61
 
62
  window win; // edit window
63
  // object space <> window space mapping
64
  //
65
  point<int> win_chunk;
66
  point<float> obj_chunk;
67
  point<float> win_per_obj;
68
  point<float> obj_per_win;
69
  float win_resolution;
70
  float obj_resolution;
71
  void obj2win (const point<float>& p, float& wx, float& wy);
72
  void obj2win (const float& ox, const float& oy, float& wx, float& wy);
73
  void win2obj (const float& dx, const float& dy, float& cx, float& cy);
74
 
75
  int pan, zoom;
76
  void do_panx (int dir);
77
  void do_pany (int dir);
78
  void do_zoom (int dir);
79
 
80
  void calc_win_mouse ();
81
  int lmb_clicked;
82
 
83
  //
84
  // file
85
  void load_settings ();
86
  void load_settings (std::ifstream& file);
87
  void save_settings (std::ofstream& file);
88
  box_from_disk_t get_box_from_disk (std::list<box_from_disk_t>& boxes, const std::string& id);
89
  void load_boxes_and_balls ();
90
  void save_boxes (std::ofstream& f, rect* R, std::string& id);
91
  void save_balls (std::ofstream& f);
92
 
93
  void setup ();
94
 
95
  int handle_input ();
96
 
97
  // draw
98
  //
99
 
100
  int draw__boxes;
101
  int fill_boxes;
102
  int label_notes;
103
  int label_hz_vol;
104
  int draw__notes;
105
  int draw_slit_cutter;
106
  draw_ball_t draw_ball;
107
 
108
  void draw_rect (rect* which);
109
  void draw_leaves ();
110
  void draw_balls ();
111
  void draw_notes ();
112
  void draw ();
113
 
114
  // boxes
115
  //
116
 
117
  rect* root; // the main box
118
  std::list <rect*> leaves; // boxes that dont have children and can bear slits
119
  rect* get_sibling (rect* R); // return sibling of R
120
  void find (rect* R, float x, float y, finding& f); // find box where x,y is found. starting with R and down
121
  rect* box_under_cursor ();
122
  finding make_finding (rect* R); // R and its sibling
123
  int bad_rect (rect* R) { return R == 0 || R == root; }
124
 
125
  // box splitting
126
  //
127
 
128
  rect* split_rect (int type, float where, rect* B = 0); // split box [type = horizontal or vertical]
129
  int num_boxes;
130
  int get_note_ids (std::pair<int, int>& nids, rect* R, int type);
131
  void get_note_ids_from_intervals (std::pair<int, int>& idp, const std::pair<float, float>& ip);
132
  int multi_split_rect (split_data& sd);
133
  void multi_split_rect (int n, int type, rect* B = 0, std::list<rect*> *pr = 0, split_listener* sl = 0); // split B [or current] into n boxes
134
  void multi_split_rect (int type, rect* B = 0, std::list<rect*> *lr = 0, split_listener* sl = 0); // split B [or current] at note intervals
135
  int splitting_rects;
136
  std::list<split_data> lsd;
137
  void split_over (split_data& sd);
138
  std::list<rect*> columns;
139
  void make_note_grid (); // split the root box both horizontally and vertically at the notes of the scale 
140
  void make_nxn_grid (); // split the root box into a N x N grid of boxes
141
 
142
  int nleaves;
143
  void add_leaf (rect* L); // splitting a box makes 2 leaves
144
  void remove_leaf (rect* L);
145
 
146
  rect* earliest_leaf ();
147
  rect* latest_leaf ();
148
  rect* rnd_leaf ();
149
  rect* biggest_leaf ();
150
  rect* balled_leaf ();
151
  rect* pick_leaf (int& what);
152
  int split_leaf, delete_leaf;
153
 
154
  void recreate_slits (rect* b); // to recreate slits of a just deleted box in its two children ie leaves
155
 
156
  int delete_rect (const finding& f); // delete found box
157
  void delete_current_rect (); // delete box under cursor
158
  void update_children (rect* R); // update extents of children of box R
159
  void delete_children (rect* R); // delete children of box R
160
  void update_parent (rect* C); // update parent (and ancestors) of box C 
161
  int delete_all_rects; // when active, once every frame
162
 
163
  alarm_t auto_del_rect; // auto delete box?
164
  alarm_t auto_split_rect; // auto split box?
165
 
166
  int auto_split_orient;
167
  int auto_split_at;
168
  int auto_split_which;
169
 
170
 
171
  rect* hit; // box hit when clicked
172
  int edge; // edge hit
173
  void set_edge (rect* R, int e, float x, float y); // set vertical (using x) or horizontal edge (using y) of box R
174
 
175
  int sel_tar; // selection target
176
  enum {SELECT_SLITS = 0, SELECT_BALLS};
177
 
178
  // balls
179
  //
1562 jag 180
  std::list<ball*> balls;
1528 jag 181
  int num_balls;
182
 
183
  int adding_balls;
184
  int added_ball_type;
185
  int started_making_ball;
186
  ball* new_ball;
187
  void do_add_balls (int _type = ball::BOUNCER);
188
 
189
  void split_balls (rect* P, rect* C1, rect* C2); // split balls among children C1 and C2 when parent P is deleted
190
 
191
  void delete_ball (ball* b);
192
  void delete_all_balls ();
193
  void delete_selected_balls ();
194
 
195
  float delta_speed;
196
  void change_speed (spinner<float>& s, float d);
197
 
198
  // ball selection
199
  //
200
  std::list<ball*> selected_balls;
201
  int num_selected_balls;
1698 jag 202
  void select_balls (const box<float>& rgn);
1528 jag 203
  void select_box_balls ();
204
  void after_selection ();
205
  void select_type (int t);
206
  struct browse_t {
207
    int which, last, n;
208
    std::vector<ball*> balls;
209
    browse_t ();
210
    void clear ();
211
  } browse;
212
  void browse_ball (int i);
213
 
214
  std::list<ball*>& get_box_balls ();
215
  std::list<ball*>& get_balls ();
216
  std::list<ball*>& get_balls (int);
217
  ball* get_one_selected_ball ();
218
  void switch_balls_type ();
219
 
220
  // freeze and thaw
221
  void freeze_thaw_balls (std::list<ball*>& _balls);
222
  void freeze_balls (std::list<ball*>& _balls);
223
  void thaw_balls (std::list<ball*>& _balls);
224
  void freeze_all_balls ();
225
 
226
  void clear_modulations (std::list<ball*>& _balls);
227
 
228
  // ball movement
229
  int moving_balls;
230
  void move_balls (float dx, float dy);
231
  void do_move_balls ();
232
  void locate_ball (ball* b);
233
 
234
  // ball course
235
  float delta_rotate_velocity;
236
  void rotate_velocity (int dir);
237
  void toggle_auto_rotate (int ar);
238
  void set_auto_rotate (int ar);
239
  void flip_velocity ();
240
  void change_ball_dtheta (int dir);
241
 
242
  // ball misc
243
  void set_ball_param (int what, float value);
244
  void change_ball_vol_mult (spinner<float>& s);
245
  void clone_ball (ball* b);
246
  void toggle_triggered_sound ();
247
 
248
  // slits
249
  //
250
 
251
  enum {NOTHING, JUST_SLIT, ANIMATE_SLIT};
252
  int slitting;
253
  fader fdr; // for animating slit
254
 
255
  int num_slits;
256
  std::list<slit*> slits; // all slits
257
  std::list<slit*> selected_slits;
258
  int num_selected_slits;
259
 
260
  void load_slits (std::ifstream& f, std::list<box_from_disk_t>& boxes);
261
  void save_slits (std::ofstream& f);
262
  int get_index_of_slit (slit* s);
263
  slit* get_slit_from_index (int q);
264
 
265
  rect* bxs[2]; // a slit can only be on 2 boxes 
266
 
267
  int find_hit_slit (float x, float y); // under cursor
268
 
269
  slit_lip_t slit_lip;
270
  int editing_slit;
271
  int editing_edge;
272
 
273
  void start_slitting ();
274
  int try_slitting ();
275
  int add_remove_slit (float x, float y, fader* fdr = 0, float sz = slit::HALF_SIZE);
276
  void change_slit_size (spinner<float>& s);
277
  void change_slit_anim_time (spinner<float>& s);
278
  void remove_all_slits ();
279
  void remove_selected_slits ();
280
  void remove_slit (slit* s);
281
  void remove_slits (rect* R);
282
  void remove_slits_on_edge (rect* R, int e);
283
  void remove_slits_on_current_edge ();
284
  void remove_slits_on_current_box ();
285
  void remove_slits_on_boxes_with_balls ();
286
  void select_box_slits ();
287
  void toggle_slit_anim ();
288
  void remove_slit_anim ();
289
  void start_slit_anim ();
290
 
291
  void clear_selected_targets ();
292
  void select_all_targets ();
293
  void select_box_targets ();
294
  void invert_selected_targets ();
295
  void delete_selected_targets ();
296
  void delete_all_targets ();
297
 
298
  // visual
299
  //
300
  int n_pts;
301
  float* pts; // balls are points
302
  float* pts_d; // ball direction are lines
303
  float* pts_clr; // ball colors
304
  int n_mrk;
305
  float* mrk;
306
  float crsr [8];
307
  int cursor;
308
  textboard tb, tb_hz_vol;
309
  void make_notes ();
310
  void calc_visual_params ();
311
  void randomise_box_color (); // of the box under cursor
312
  void toggle_flag (int& flag, const std::string& poz, const std::string& neg = "");
313
 
2049 jag 314
  static unsigned char patbuf [1024];
315
  static std::string patstr;
2050 jag 316
  static int patstep, patlen;
2049 jag 317
  void fillpatbuf ();
318
 
1528 jag 319
  slit_drawer slit_drawerr;
320
 
321
  static const float gutter, gutter2; // for edge selection & slit making
322
  static float min_split_size; // for auto box splitting
323
 
324
  struct poly_t {
325
    std::vector<float> coss, sinn;
326
    int points;
327
    float radius;
328
    float delta_radius;
329
    poly_t () {
330
      radius = 0;
331
      delta_radius = 0;
332
      points = 0;
333
    }
334
  } poly;
335
  int set_note_poly_points (int p);
336
  int set_note_poly_radius (float r);
337
 
338
  // notes
339
  float note_volume;
340
  int voices;
341
  int min_voices;
342
  int auto_adjust_voices;
343
  note N;
344
  int num_triggered_notes;
345
  std::list<triggered_note> triggered_notes;
346
  std::list<ball*> triggering_balls;
347
  void launch_note (ball* _ball, float t, float t0, float dt, const std::pair<float, float>& invl);
348
  void remove_finished_notes ();
349
  void print_num_triggered_notes ();
350
  int change_param (float& param, float value, float& recent);
351
  void change_attack_time_kb (spinner<float>& s); // using kb shortcut
352
  void change_decay_time_kb (spinner<float>& s);
353
  void change_trail_size (spinner<int>& s);
354
  void change_min_voices (int d);
355
 
356
  // others
357
  //
358
 
359
  int stop_editing_slit ();
360
  int stop_editing_edge ();
361
  int stop_adding_balls ();
362
  int stop_moving_balls ();
363
  int stop_slitting ();
364
  int stop_doing_stuff ();
365
  int recting () {return editing_edge || editing_slit || splitting_rects; }
366
 
367
  void scale_changed ();
368
  void scale_loaded ();
369
  void tonic_changed ();
370
 
371
  int modulate_balls (int p);
372
 
373
  void toggle_balls_type (int _type);
374
 
375
  int render_audio (float* L, float* R);
376
 
377
  void bg ();
378
 
379
  void mark_selected_slits ();
380
 
1698 jag 381
  box<float> rgn;
1528 jag 382
  void region_begin ();
383
  void region_end ();
1698 jag 384
  const box<float>& region_update ();
1528 jag 385
 
386
  help _help;
387
 
388
};
389
 
390
int edge_on_root (rect* root, rect** boxes, int* edges);
391
void draw_slit_cutter (int yesno);
392
 
393
extern mondrian mondrian0;
394
 
1723 jag 395
template<class T> void clear_selected (list<T*>& targets, int& num_targets, int aft_sel = 1) {
396
  for (typename list<T*>::iterator p = targets.begin (), q = targets.end (); p != q; ++p) {
397
    T* t = *p;
398
    t->select = 0;
399
  }
400
  targets.clear ();
401
  num_targets = 0;
402
  if (aft_sel) mondrian0.after_selection ();
403
}
404
 
405
template <class T> void select_all (list<T*>& items, list<T*>& selection, int& num_selected) {
406
  clear_selected<T> (selection, num_selected);
407
  for (typename list<T*>::iterator p = items.begin (), q = items.end (); p != q; ++p) {
408
    T* t = *p;
409
    t->select = 1;
410
    selection.push_back (t);
411
    ++num_selected;
412
  }
413
  mondrian0.after_selection ();
414
}
415
 
416
template <class T> void invert_selection (list<T*>& items, list<T*>& selection, int& num_selected) {
417
  num_selected = 0;
418
  selection.clear ();
419
  for (typename list<T*>::iterator p = items.begin(), q = items.end(); p != q; ++p) {
420
    T* b = *p;
421
    b->select = !b->select;
422
    if (b->select) {
423
      selection.push_back (b);
424
      ++num_selected;
425
    }
426
  }
427
  mondrian0.after_selection ();
428
}
429
 
430
template <class T> void select_using_modifiers (T* b, int ctrl, list<T*>& selection, int& num_selected) {
431
  typename list<T*>::iterator se = selection.end (), f = ::find (selection.begin (), se, b);
432
  if (f == se) {
433
    sel:
434
    b->select = 1;
435
    push_back (selection, b);
436
    ++num_selected;
437
  } else {
438
    if (ctrl) {
439
      if (b->select) {
440
        b->select = 0;
441
        selection.erase (f);
442
        --num_selected;
443
      } else
444
        goto sel;
445
    }
446
  }
447
}
448
 
449
 
1528 jag 450
#endif