Subversion Repositories DIN Is Noise

Rev

Rev 1166 | Rev 1174 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
* point_modulator.cc
* DIN Is Noise is copyright (c) 2006-2019 Jagannathan Sampath
* For more information, please visit http://dinisnoise.org/
*/


#include "point_modulator.h"
#include "ui_list.h"
#include "console.h"
#include "audio.h"
#include <map>
using namespace std;

#define NUM_WIDGETS 12
#define NUM_WIDGETS_1 (NUM_WIDGETS - 1)
#define DECLARE_WIDGET_ARRAY_wa widget* wa [] = {&title, &all, &none, &invert, &play, &kill, &plus, &fold, &x.depth, &x.bpm, &y.depth, &y.bpm};

extern audio_out aout;

void point_modulator::setup (curve_editor* _ed) {

  ed = _ed;

  DECLARE_WIDGET_ARRAY_wa
  const char* texts [] = {"Point Modulator", "All", "None", "Invert"};
  for (int i = 0; i < 4; ++i)  {
    label* l = dynamic_cast<label*>(wa[i]);
    l->set_text (texts[i]);
  }

  for (int i = 1; i < 8; ++i) dynamic_cast<button*>(wa[i])->set_listener (this);

  make_family (&title, &wa[1], NUM_WIDGETS_1);
  /*make_hierarchy (&wa[1], 3);
  make_hierarchy (&wa[4], 2);*/

  for (int i = 4; i < 7; ++i) {
    button* wi = dynamic_cast<button*>(wa [i]);
    wi->set_size (16);
  }

  title.set_moveable (1);
  title.movlis = this;
  /*for (int i = 0; i < NUM_WIDGETS; ++i) {
    widget* wi = wa[i];
    wi->set_moveable (1);
  }*/


  fold.set_dir (arrow_button::down);
  play.set_dir (arrow_button::right);

  widget_load ("d_point_modulator", wa, NUM_WIDGETS);


  x.depth.set_text ("X depth");
  x.depth.set_value (0);
  x.depth.set_delta (ed->obj_chunk.x);

  x.depth.set_listener (this);
  x.bpm.set_text ("X BPM");
  x.bpm.set_delta (1);
  x.bpm.set_value (0);
  x.bpm.set_listener (this);

  y.depth.set_text ("Y depth");
  y.depth.set_value (0);
  y.depth.set_delta (ed->obj_chunk.y);
  y.depth.set_listener (this);

  y.bpm.set_text ("Y BPM");
  y.bpm.set_delta (1);
  y.bpm.set_value (0);
  y.bpm.set_listener (this);

  folded = 0;
  moved ();

}

extern multi_curve ran_mod_width_crv, ran_mod_height_crv;
mod_dat::mod_dat (hit_t& h, state_button* _sb, float _bpm) : hit (h), sb (_sb), mod (&ran_mod_width_crv, &ran_mod_height_crv), init (h.get()) {
  mod.active = 1;
  mod.am.bv.set_bpm (_bpm, aout.samples_per_channel);
  mod.fm.bv.set_bpm (_bpm, aout.samples_per_channel);
}

state_button* point_modulator::add (hit_t& h) {
#ifdef __EVALUATION__
  if (nlst == 1) {
    cons << RED << "Can add more point modulators in the Licensed Version of DIN Is Noise" << eol;
    return 0;
  }
#endif
  on_lst (_desel);
  state_button* sb = new state_button;
  sb->set_pos (sbx, sby);
  sbx += state_button::SIZE2;
  title.add_child (sb);
  const float bpm = 10;
  mod_dat md (h, sb, bpm);
  lst.push_back (md);
  ++nlst;
  sb->set_state (1);
  return sb;
}

point_modulator::point_modulator () {
  ++ref;
}

point_modulator::~point_modulator () {
  for (list<mod_dat>::iterator i = lst.begin (), j = lst.end(); i != j; ++i) {
    mod_dat& md = *i;
    state_button* sb = md.sb;
    delete sb;
  }

  if (--ref == 0) {
    DECLARE_WIDGET_ARRAY_wa
    widget_save ("d_point_modulator", wa, NUM_WIDGETS);
  }
}

int point_modulator::handle_input () {

  if (folded == 0) {
    for (list<mod_dat>::iterator i = lst.begin (), j = lst.end(); i != j; ++i) {
      state_button* sb = (*i).sb;
      if (sb->handle_input()) return 1;
    }
    DECLARE_WIDGET_ARRAY_wa
    for (int i = 0; i < NUM_WIDGETS; ++i) {
      widget* wi = wa[i];
      if (wi->handle_input()) return 1;
    }
  } else {
    if (fold.handle_input ()) return 1;
    else return title.handle_input ();
  }

  return 0;

}

/*void point_modulator::remove () {
  int p = nlst;
  for (list<mod_dat>::iterator i = lst.begin (), j = lst.end(); i != j;) {
    mod_dat& md = *i;
    state_button* sb = md.sb;
    if (sb->state) {
      title.remove_child (sb);
      delete sb;
      i = lst.erase (i);
      j = lst.end ();
      --nlst;
    } else ++i;
  }
  rearrange ();
  int q = p - nlst;
  if (q) cons << RED << "Removed " << q << " point modulations" << eol;
}*/


void point_modulator::remove (const hit_t& h) {
  int p = nlst;
  for (list<mod_dat>::iterator i = lst.begin (), j = lst.end(); i != j;) {
    mod_dat& md = *i;
    state_button* sb = md.sb;
    int s = 0; if (h()) s = md.hit.matched_id (h); else s = sb->state;
    if (s) {
      title.remove_child (sb);
      delete sb;
      i = lst.erase (i);
      j = lst.end ();
      --nlst;
    } else ++i;
  }
  rearrange ();
  int q = p - nlst;
  if (q) cons << RED << "Removed " << q << " point modulations" << eol;
}

void point_modulator::rearrange () {
  int sx = title.extents.left;
  for (list<mod_dat>::iterator i = lst.begin (), j = lst.end(); i != j; ++i) {
    mod_dat& md = *i;
    state_button* sb = md.sb;
    sb->set_pos (sx, sby);
    sx += state_button::SIZE2;
  }
  sbx = sx;
}

void point_modulator::on_lst (const op_cap& op) {
  for (list<mod_dat>::iterator i = lst.begin (), j = lst.end(); i != j; ++i) {
    mod_dat& md = *i;
    state_button* sb = md.sb;
    sb->set_state (op (sb->state));
  }
}

void point_modulator::changed (field& f) {
  if (&f == &x.depth.f_value) {
    for (list<mod_dat>::iterator i = lst.begin (), j = lst.end(); i != j; ++i) {
      mod_dat& md = *i;
      if (md.sb->state) {
        md.mod.fm.depth += x.depth.dir_delta();
      }
    }
  } else if (&f == &y.depth.f_value) {
    for (list<mod_dat>::iterator i = lst.begin (), j = lst.end(); i != j; ++i) {
      mod_dat& md = *i;
      if (md.sb->state) {
        md.mod.am.depth += y.depth.dir_delta();
      }
    }
  } else if (&f == &x.bpm.f_value) {
    for (list<mod_dat>::iterator i = lst.begin (), j = lst.end(); i != j; ++i) {
      mod_dat& md = *i;
      if (md.sb->state) {
        md.mod.fm.bv.set_bpm (md.mod.fm.bv.bpm + x.bpm.dir_delta(), aout.samples_per_channel);
      }
    }
  } else if (&f == &y.bpm.f_value) {
    for (list<mod_dat>::iterator i = lst.begin (), j = lst.end(); i != j; ++i) {
      mod_dat& md = *i;
      if (md.sb->state) {
        md.mod.am.bv.set_bpm (md.mod.am.bv.bpm + y.bpm.dir_delta(), aout.samples_per_channel);
      }
    }
  }
}

void point_modulator::bg () {
  map<multi_curve*, int> eval;
  for (list<mod_dat>::iterator i = lst.begin (), j = lst.end(); i != j; ++i) {
    mod_dat& md = *i;
    modulator& mod = md.mod;
    if (mod.active) {
      mod.calc ();
      ed->move (md.hit, md.init.x + mod.fm.result, md.init.y + mod.am.result, 0);
      eval[md.hit.crv] = md.hit.crv_id;
    }
  }
  for (map<multi_curve*, int>::iterator i = eval.begin (), j = eval.end (); i != j; ++i) {
    pair<multi_curve*, int> e = *i;
    curve_info& ci = ed->curveinfo [e.second];
    multi_curve* crv = e.first;
    crv->evaluate ();
    ci.lisner->edited (ed, e.second);
  }
}

void point_modulator::clicked (button& b) {
  if (&b == &plus) {
    CRVED->modulate_point ();
  } else if (&b == &kill) {
    remove ();
  } else if (&b == &play) {
    for (list<mod_dat>::iterator i = lst.begin (), j = lst.end(); i != j; ++i) {
      mod_dat& md = *i;
      modulator& mod = md.mod;
      if (md.sb->state) mod.active = !mod.active;
    }
  } else if (&b == &all) {
    on_lst (_sel);
  } else if (&b == &invert) {
    on_lst (_togg);
  } else if (&b == &none) {
    on_lst (_desel);
  } else if (&b == &fold) {
    if (fold.dir == arrow_button::down) {
      title.hide (widget::only_children);
      fold.show ();
      fold.set_dir (arrow_button::right);
      folded = 1;
    } else {
      title.show ();
      fold.set_dir (arrow_button::down);
      folded = 0;
    }
  }
}

void point_modulator::draw () {
  if (folded == 0) {
    DECLARE_WIDGET_ARRAY_wa
    for (int i = 0; i < NUM_WIDGETS; ++i) {
      widget* wi = wa[i];
      if (wi->visible) wi->draw ();
    }
    for (list<mod_dat>::iterator i = lst.begin (), j = lst.end(); i != j; ++i) {
      mod_dat& md = *i;
      state_button* sb = md.sb;
      if (sb->visible) sb->draw ();
    }
    glEnable (GL_LINE_STIPPLE);
    glLineStipple (1, 0xf00f);
    for (list<mod_dat>::iterator i = lst.begin (), j = lst.end(); i != j; ++i) {
      mod_dat& md = *i;
      state_button* sb = md.sb;
      const point<float>& p = md.hit.get ();
      int vx, vy; ed->obj2view (p.x, p.y, vx, vy);
      if (sb->state) glColor3f (0, 1, 0); else glColor3f (1, 0, 0);
      glBegin (GL_LINES);
        glVertex2i (vx, vy);
        glVertex2i (sb->extents.midx, sb->extents.midy);
      glEnd ();
    }
    glDisable (GL_LINE_STIPPLE);
  } else {
    fold.draw ();
    title.draw ();
  }

}

void point_modulator::moved () {
  sbx = title.extents.left + nlst * state_button::SIZE2;
  sby = title.extents.bottom - title.extents.height;
}