Subversion Repositories DIN Is Noise

Rev

Rev 2110 | Blame | Compare with Previous | Last modification | View Log | RSS feed


/*
* number.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 "number.h"
#include "vector2d.h"
#include "ui_list.h"
#include "multi_curve.h"
#include "tcl_interp.h"
#include <vector>
#include <fstream>

using namespace std;

extern ui_list uis;

number::number () : slw (255), slh (10), sl_red (0, slw, slh), sl_green (0, slw, slh), sl_blue (0, slw, slh) {
  name = "Number";
  uchar = 'A';
  short_ = 666;
  int_ = 1729;
  float_ = 3.141592;
  double_ = 2.71828183;
  ucolor.r = 128; ucolor.g = 128; ucolor.b = 255;
  type = CHAR;
  make_shapeform = 1;
  y[1]=1.0f;
  y[0]=0.0f;
}

number::~number () {
  widget_save ("d_number", ctrls);
  save_params ();
}

void number::load_params () {
  ifstream f (make_fname().c_str(), ios::in);
  string ignore;
  f >> ignore >> type;
  f >> ignore;
  slider<int>* sl [] = {&sl_red, &sl_green, &sl_blue};
  int s;
  for (int i = 0; i < 3; ++i) {f >> s; sl[i]->set_val (s);}
  f >> ignore >> double_;
  f >> ignore >> float_;
  f >> ignore >> int_;
  f >> ignore >> short_;
  f >> ignore >> uchar;
  float v;
  spinner<float>* sp[] = {&sp_0equals, &sp_1equals};
  for (int i = 0; i < 2; ++i) {
    f >> ignore >> v; sp[i]->set_value (v);
    y[i] = v;
  }
  f >> ignore >> v; sp_scale.set_value (v);
  f >> ignore >> make_shapeform; cb_make_shapeform.set_state (make_shapeform);
  int w; f >> ignore >> w; cb_wrap.set_state (w);
}

void number::save_params () {
  ofstream f (make_fname().c_str(), ios::out);
  f << "type " << type << endl;
  f << "color " << (int) ucolor.r << ' ' << (int) ucolor.g << ' ' << (int) ucolor.b << endl;
  f << "double " << double_ << endl;
  f << "float " << float_ << endl;
  f << "int " << int_ << endl;
  f << "short " << short_ << endl;
  f << "char " << (char) uchar << endl;
  f << "0_equals " << sp_0equals.value << endl;
  f << "1_equals " << sp_1equals.value << endl;
  f << "scale " << sp_scale.value << endl;
  f << "make_shapeform " << (int) cb_make_shapeform.state << endl;
  f << "wrap " << (int) cb_wrap.state << endl;
}

void number::setup () {

  plugin::setup ();

  ol_bitsof.set_listener (this);

  const char* const _types [] = {"char", "short", "int", "float", "double", "colour"};
  for (int i = 0, num_types = 6; i < num_types; ++i) types.push_back (_types[i]);

  widget* _ctrls [] = {&ol_bitsof, &lf_value, &sp_1equals, &sp_0equals, &sp_scale, &cb_make_shapeform, &bd_bits, &sl_red, &sl_green, &sl_blue, &b_flip, &b_left_shift, &b_right_shift, &cb_wrap};
  for (int i = 0; i < 14; ++i) ctrls.push_back (_ctrls[i]);
  num_ctrls = ctrls.size ();

  button* btn [] = {&b_flip, &b_left_shift, &b_right_shift};
  const char* const l[] = {"Flip", "<<", ">>"};
  for (int i = 0; i < 3; ++i) {
    button* bi = btn[i];
    bi->set_text (l[i]);
    bi->set_listener (this);
  }
  cb_wrap.set_text ("Rotate");
  b_left_shift.click_repeat = b_right_shift.click_repeat = 1;

  slider<int>* sl[] = {&sl_red, &sl_green, &sl_blue};
  for (int i = 0; i < 3; ++i) {
    slider<int>* si = sl[i];
    si->set_limits (0, 255);
    si->set_listener (this);
  }
  unsigned char c = 255, b = 0;
  sl_red.set_color (c, b, b);
  sl_green.set_color (b, c, b);
  sl_blue.set_color (b, b, c);

  lf_value.set_label ("Value");
  lf_value.set_listener (this);

  spinner<float>* spn [] = {&sp_1equals, &sp_0equals};
  const char* spnl [] = {"1 = ", "0 = "};
  float spnv [] = {1.0f, 0.1f};
  for (int i = 0; i < 2; ++i) {
    spinner<float>* spi = spn[i];
    spi->set (spnl[i], 0.01f, -MILLION, MILLION, this, 0);
    spi->set_value (spnv[i]);
  }
 
  cb_make_shapeform.set_text ("Make shapeform");

  sp_scale.set ("Scale", 0.01f, 0.0f, MILLION, this, 0);
  sp_scale.set_value (1.0f);

  widget_load ("d_number", ctrls);

  bd_bits.lsnr = this;

  load_params ();

  make_value_from_color ();
  set_type (type);

  cb_make_shapeform.set_listener (this);

}

void number::render () {
  shapeform = cb_make_shapeform.state;
  vector<unsigned char>& bits = bd_bits.bits;
  int num_bits = bd_bits.num_bits;
  points.clear ();
  float scale = sp_scale.value;
  float cx = 0.5, cy = 0;
  if (shapeform) {
    extern const float TWO_PI;
    float da = TWO_PI / num_bits, hda = da / 2.0;
    float pa = -hda, a = 0, na = hda;
    float cos_pa = cos(pa), sin_pa = sin(pa);
    float cos_na, sin_na;
    float cos_a, sin_a;
    int pbi = -1, b0 = bits[0], bl = bits[bd_bits.last_bit];
    for (int i = 0; i < num_bits; ++i) {
      int bi = bits[i];
      cos_a = cos(a);
      sin_a = sin(a);
      float R = scale * y[bi];
      float x = cx + R * cos_a;
      float y = cy + R * sin_a;
      cos_na = cos(na);
      sin_na = sin(na);
      float xn = cx + R * cos_na;
      float yn = cy + R * sin_na;
      if (bi != pbi) {
        float xp = cx + R * cos_pa;
        float yp = cy + R * sin_pa;
        points.push_back (point<float>(xp,yp));
      }
      cos_pa = cos_na;
      sin_pa = sin_na;
      points.push_back (point<float>(x, y));
      points.push_back (point<float>(xn, yn));
      a += da;
      na += da;
      pbi = bi;
    }
    if (b0 != bl) {
      point<float>& p0 = *points.begin ();
      points.push_back (p0);
    }
  } else {
    float beat_pos = 0.0f;
    float beat = scale / bd_bits.num_bits;
    float half_beat = beat / 2.0;
    point<float> p0;
    for (int i = 0, j = bd_bits.num_bits; i < j; ++i) {
      int bi = bits[i];
      points.push_back (point<float>(beat_pos, 0.0f));
      point<float> pi (beat_pos + half_beat, y[bi]);
      points.push_back (pi);
      beat_pos += beat;
    }
    points.push_back (point<float>(beat_pos, 0.0f));
  }

  ss.clear(); ss.str(""); ss << "number_" << lf_value.fld.text;
  gen_pts ();

}

void number::flip () {
  vector<unsigned char>& bits = bd_bits.bits;
  int num_bits = bd_bits.num_bits;
  for (int i = 0; i < num_bits; ++i) bits[i]=!bits[i];
  changed (bd_bits);
}

void number::shift (int i, int d) {
  vector<unsigned char>& bits = bd_bits.bits;
  int j = i;
  int n = bd_bits.last_bit;
  unsigned char w = bits[i];
  for (int m = 0; m < n; ++m) {
    int id = i + d;
    bits[i]=bits[id];
    i = id;
  }
  int wb = j + d * n;
  if (cb_wrap.state) bits[wb] = w; else bits[wb] = 0;
  changed (bd_bits);
}

void number::make_value_from_color () {
  ucolor.r = sl_red (); ucolor.g = sl_green (); ucolor.b = sl_blue ();
  if (type == COLOR) {
    ss.clear (); ss.str(""); ss << int(ucolor.r) << spc << int(ucolor.g) << spc << int(ucolor.b);
    lf_value.set_text (ss.str());
    bd_bits.set (&ucolor, 3);
  }
  bd_bits.set_color (ucolor.r, ucolor.g, ucolor.b);
}

void number::set_type (int t) {

  type = t;

  wrap<int> (CHAR, type, COLOR);

  ol_bitsof.set_text (" Bits of " + types[type]);
 
  lf_value.fld.expr = 1;
  if (type == COLOR) {
    make_value_from_color ();
    lf_value.fld.expr = 0;
  } else if (type == CHAR) {
    set_value (uchar);
    lf_value.fld.expr = 0;
  } else if (type == SHORT) {
    set_value (short_);
  } else if (type == INT) {
    set_value (int_);
  } else if (type == FLOAT) {
    set_value (float_);
  } else if (type == DOUBLE) {
    set_value (double_);
  }

  do_render ();

}

extern tcl_interp interpreter;

string eval_expression (const string& e) {
  string cmd ("expr "); cmd += e;
  interpreter (cmd);
  if (interpreter.result_status == TCL_OK) return interpreter.result; else return ("error");
}

void eval_expression (field& f) {
  f.set_text (eval_expression (f.text));
}

void number::reverse (unsigned char* reversed, unsigned char* original, int n) {
  for (int i = 0, j = n - 1; i < n; ++i, --j) reversed[i] = original[j];
}

void number::changed (slider<int>& s) {
  make_value_from_color ();
  do_render ();
}

void number::picked (label& lbl, int dir) {
  int t = type + dir;
  set_type (t);
}

void number::changed (field& f) {
  if (&f == &lf_value.fld) {
    if (type == INT) {
      eval_expression (f);
      int_ = int (f);
      int int__ = int_;
      set_bit_display (&int__);
    } else if (type == FLOAT) {
      eval_expression (f);
      float_ = float (f);
      float float__ = float_;
      set_bit_display (&float__);
    } else if (type == DOUBLE) {
      eval_expression (f);
      double_ = double (f);
      double double__ = double_;
      set_bit_display (&double__);
    } else if (type == CHAR) {
      if (f.text.length () == 0) {
        uchar = 'A';
        f.set_text (uchar);
      } else uchar = f.text[0];
      unsigned char uchar_ = uchar;
      set_bit_display (&uchar_);
    } else if (type == SHORT) {
      eval_expression (f);
      short_ = short (f);
      short short__ = short_;
      set_bit_display (&short__);
    } else if (type == COLOR) {
      ss.clear (); ss.str(""); ss << f.text;
      string comp[3];
      for (int i = 0; i < 3; ++i) {
        string& ci = comp[i];
        ss >> ci;
        ci = eval_expression (ci);
      }
      int sv = 0;
      slider<int>* sld[3] = {&sl_red, &sl_green, &sl_blue};
      for (int i = 0; i < 3; ++i) {
        ss.clear (); ss.str(""); ss << comp[i];
        ss >> sv;
        sld[i]->set_val (sv);  // set slider
      }
      make_value_from_color ();
    }
  } else if (&f == &sp_1equals.f_value) {
    y[1] = sp_1equals.value;
  } else if (&f == &sp_0equals.f_value) {
    y[0] = sp_0equals.value;
  }
  do_render ();
}


void number::changed (bit_display& bd) {
  if (type == COLOR) {
    bd.get_color (&ucolor);
    sl_red.set_val (ucolor.r); sl_green.set_val (ucolor.g); sl_blue.set_val (ucolor.b);
    make_value_from_color ();
  } else if (type == CHAR) {
    bd.get_data (&uchar);
    if (uchar > 31 && uchar < 127) set_value_ (uchar);
  } else if (type == SHORT) {
    bd.get_data (&short_);
    set_value_ (short_);
  } else if (type == INT) {
    bd.get_data (&int_);
    set_value_ (int_);
  } else if (type == FLOAT) {
    bd.get_data (&float_);
    set_value_ (float_);
  } else if (type == DOUBLE) {
    bd.get_data (&double_);
    set_value_ (double_);
  }
  do_render ();
}

void number::changed (checkbutton& cb) {
  if (&cb == &cb_make_shapeform) do_render ();
  else return plugin::changed (cb);
}

void number::clicked (button& b) {
  if (&b == &b_flip) {
    flip ();
  } else if (&b == &b_left_shift) {
    shift (0, +1);
  } else if (&b == &b_right_shift) {
    shift (bd_bits.last_bit, -1);
  } else plugin::clicked (b);
}