Subversion Repositories DIN Is Noise

Rev

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

/*
* morpher.cc
* DIN Is Noise is copyright (c) 2006-2024 Jagannathan Sampath
* DIN Is Noise is released under GNU Public License 2.0
* For more information, please visit https://dinisnoise.org/
*/



#include "morpher.h"
#include "ui_list.h"
#include "console.h"
#include <fstream>
using namespace std;

morpher::morpher () : sl_amount (1, 192, 12), sl_src_start (0, 64, 12), sl_tar_start (0, 64, 12)  {
  name = "Morpher";
  amount = 0.0f;
  src.crv.load ("morph_source.crv");
  tar.crv.load ("morph_target.crv");
  load_params ();
}

morpher::~morpher () {
  save_params ();
  widget_save ("d_morpher", ctrls);
  src.crv.save ("morph_source.crv");
  tar.crv.save ("morph_target.crv");
}

void morpher::load_params () {
  ifstream f (make_fname().c_str(), ios::in);
  string ignore;
  f >> ignore >> num_points;
}

void morpher::save_params () {
  ofstream f (make_fname().c_str(), ios::out);
  f << "num_points " << num_points << endl;
}

void morpher::setup () {

  plugin::setup ();

  /*widget* _ctrls [] = {
    &l_source, &l_target, &cd_source, &cd_target, &b_source, &b_target, &sl_amount, &sp_points, &sl_src_start, &sl_tar_start};
  */

  widget* _ctrls [] = {
    &src.lbl, &tar.lbl, &src.cd, &tar.cd, &src.get, &tar.get, &sl_amount, &sp_points, &sl_src_start, &sl_tar_start
  };

  for (int i = 0; i < 10; ++i) {
    widget* ci = _ctrls[i];
    ctrls.push_back (ci);
  }
  num_ctrls = ctrls.size ();

  src.lbl.set_text ("From");
  tar.lbl.set_text ("To");
  src.get.set_text ("Get");
  tar.get.set_text ("Get");
  src.get.set_listener (this);
  tar.get.set_listener (this);

  /*slider<float>* slr [] = {&sl_amount, &sl_src_start, &sl_tar_start};
  for (int i = 0; i < 3; ++i) {
    slider<float>* sl = slr[i];
    sl->set_val (0.5f);
    sl->set_limits (0.0f, 1.0f);
    sl->set_listener (this);
  }*/


  sl_amount.set_limits (0.0f, 1.0f);
  sl_amount.set_listener (this);
  sl_src_start.set_limits (0.0f, 1.0f);
  sl_tar_start.set_limits (0.0f, 1.0f);

  sp_points.set ("Points", 1, 1, MILLION, this, 0);
  sp_points.set_value (num_points);

  const int sx = 64, sy = 64;
  src.cd.set_size (sx, sy);
  tar.cd.set_size (sx, sy);
  sl_src_start.set_size (sx);
  sl_tar_start.set_size (sx);
 
  widget_load ("d_morpher", ctrls);

  assign_curve (src.crv, src.sol, src.cd);
  assign_curve (tar.crv, tar.sol, tar.cd);
  make_points ();
  render ();

}

void morpher::make_classic_pts (vector< point<float> >& pts, solver& sol) {
  pts.clear ();
  int last_point = num_points - 1;
  float x = 0.0f;
  float dx = 1.0f / last_point;
  for (int i = 0; i < num_points; ++i) {
    float y = sol (x);
    pts.push_back (point<float>(x, y));
    x += dx;
  }
}

void morpher::make_shapeform_pts (vector< point<float> >& pts, solver& sol, multi_curve& crv) {
  float px, py, dummy;
  pts.clear ();
  int last_point = num_points - 1;
  float x = 0.0f;
  float dx = 1.0f / last_point;
  for (int i = 0; i < num_points; ++i) {
    py = sol (x);
    crv.get_xy (x, px, dummy);
    pts.push_back (point<float>(px, py));
    x += dx;
  }
}

void morpher::render () {
  amount = sl_amount ();
  if (equals(amount, 0.0f) || equals(amount, 1.0f)) return;
  shapeform = src.crv.shapeform;
  int last_point = num_points - 1;
  src.start = sl_src_start () * last_point;
  tar.start = sl_tar_start () * last_point;
  src.cur = src.start;
  tar.cur = tar.start;
  points.resize (num_points);
  for (int i = 0; i < num_points; ++i) {
    point<float>& psrc = src.pts[src.cur];
    point<float>& ptar = tar.pts[tar.cur];
    if (++src.cur > last_point) src.cur = 0;
    if (++tar.cur > last_point) tar.cur = 0;
    point<float> pblend ( (1 - amount) * psrc.x + amount * ptar.x, (1 - amount) * psrc.y + amount * ptar.y);
    points[i] = pblend;
  }
  gen_pts ();
}

int morpher::apply (multi_curve& crv) {
  if (equals(amount, 0.0f)) {
    crv = src.crv;
  } else if (equals(amount, 1.0f)) {
    crv = tar.crv;
  } else
  return
    plugin::apply (crv);
  return 1;
}

void morpher::make_points () {
  src.total = src.crv.get_total_points ();
  tar.total = tar.crv.get_total_points ();
  if (src.total < 2 || tar.total < 2) return;
  num_points = max (max (src.total, tar.total), sp_points.value);
  if (src.crv.shapeform) make_shapeform_pts (src.pts, src.sol, src.crv); else make_classic_pts (src.pts, src.sol);
  if (tar.crv.shapeform) make_shapeform_pts (tar.pts, tar.sol, tar.crv); else make_classic_pts (tar.pts, tar.sol);
}

void morpher::assign_curve (multi_curve& crv, solver& sol, curve_display& crvdis) {
  sol (&crv);
  crvdis.crv = &crv;
  crvdis.calc_bbox ();
}

void morpher::clicked (button& b) {
  if (&b == &src.get) {
    src.crv = *uis.crved->get_picked_curve ();
    assign_curve (src.crv, src.sol, src.cd);
    sl_amount.set_val (0.0f);
    changed (sp_points.f_value);
  } else if (&b == &tar.get) {
    tar.crv = *uis.crved->get_picked_curve ();
    assign_curve (tar.crv, tar.sol, tar.cd);
    sl_amount.set_val (1.0f);
    changed (sp_points.f_value);
  } else plugin::clicked (b);
}

void morpher::changed (slider<float>& s) {
  plugin::changed (sp_points.f_value);
}

void morpher::changed (field& f) {
  make_points ();
  plugin::changed (f);
}