Subversion Repositories DIN Is Noise

Rev

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

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



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

extern ui_list uis;
extern ofstream dlog;
extern int MILLION;

morpher::morpher () : sl_amount (164, 12), sl_src_start (64, 12), sl_tar_start (64, 12), source ("morph_source.crv"), target ("morph_target.crv") {
  name = "Morpher";
  amount = 0.0f;
  src_start = tar_start = 0;
  load_params ();
}

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

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};
  for (int i = 0; i < 8 /*10*/; ++i) {
    widget* ci = _ctrls[i];
    ctrls.push_back (ci);
  }
  num_ctrls = ctrls.size ();

  l_source.set_text ("From:");
  l_target.set_text ("To:");
  b_source.set_text ("Get");
  b_target.set_text ("Get");
  b_source.set_listener (this);
  b_target.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_moveable (1);
    sl->set_listener (this);
  }

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

  const int sx = 64, sy = 64;
  cd_source.set_size (sx, sy);
  cd_target.set_size (sx, sy);
 
  widget_load ("d_morpher", ctrls);

  assign_curve (source, source_sol, cd_source);
  assign_curve (target, target_sol, cd_target);
  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 (amount == 0.0f || amount == 1.0f) return;
  shapeform = source.shapeform;
  int last_point = num_points - 1;
  src_start = sl_src_start () * last_point;
  tar_start = sl_tar_start () * last_point;
  int src_cur = src_start, tar_cur = tar_start;
  points.resize (num_points);
  for (int i = 0; i < num_points; ++i) {
    point<float>& psrc = source_pts[src_cur];
    point<float>& ptar = target_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 (amount == 0.0f) {
    crv = source;
  } else if (amount == 1.0f) {
    crv = target;
  } else return plugin::apply (crv);
  return 1;
}

void morpher::make_points () {
  int source_total = source.get_total_points ();
  int target_total = target.get_total_points ();
  if (source_total < 2 || target_total < 2) return;
  num_points = max (max (source_total, target_total), int (sp_points.f_value));
  if (source.shapeform) make_shapeform_pts (source_pts, source_sol, source); else make_classic_pts (source_pts, source_sol);
  if (target.shapeform) make_shapeform_pts (target_pts, target_sol, target); else make_classic_pts (target_pts, target_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 == &b_source) {
    source = *uis.crved->get_picked_curve ();
    assign_curve (source, source_sol, cd_source);
    sl_amount.set_val (0.0f);
    changed (sp_points.f_value);
  } else if (&b == &b_target) {
    target = *uis.crved->get_picked_curve ();
    assign_curve (target, target_sol, cd_target);
    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);
}