Subversion Repositories DIN Is Noise

Rev

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

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



#include "main.h"
#include "levels.h"
#include "viewwin.h"
#include "input.h"
#include "console.h"
#include "utils.h"
#include "font.h"
#include "log.h"

#include <fstream>
#include <iostream>

using namespace std;

extern string user_data_dir;
extern int mousex, mousey, wheel, mouseyy, prev_mousey;
extern char BUFFER [];
extern int line_height;

levels::levels (const string& n) {
  name = n;
  lis = 0;
  editing = lmb_clicked = paint = nsel = 0;
  wrap = 1;
  selection = 0;
  load ();
}

levels::~levels () {
  save ();
  if (selection) delete[] selection;
}

void levels::load () {

  string ignore;
  int left, bottom;

  ifstream file ((user_data_dir + name).c_str(), ios::in);
  if (!file) {
    dlog << "!!! cant read settings for " << name << ", using defaults. !!!" << endl;
    nlev = 10;
    elem_width = 10;
    height = 100;
    left = 0;
    bottom = 0;
    editable = 0;
    saveable = 0;
    wrap = 1;
  } else {
    file >> ignore >> nlev;
    lastlev = nlev - 1;
    file >> ignore >> left >> bottom;
    file >> ignore >> elem_width;
    file >> ignore >> height;
    file >> ignore >> editable;
    file >> ignore >> saveable;
    file >> ignore >> wrap;
    dlog << "+++ loaded " << name << " +++" << endl;
  }

  a = 0.7;
  a0 = a / 4;
  extents (left, bottom, left + nlev * elem_width, bottom + height);

  values.resize (nlev);
  heights.resize (nlev);

  selection = new bool [nlev];
  sel_sz = sizeof (bool) * nlev;
  memset (selection, 0, sel_sz);

  if (saveable) {
    int savings;
    file >> ignore >> savings;
    for (int i = 0; i < savings; ++i) {
      float h; file >> h >> selection[i];
      heights[i] = h;
      values[i] =  h * extents.height_1;
    }
    file >> nsel;
  }

  editing = edited = 0;

}

void levels::save () {
  ofstream file ((user_data_dir+name).c_str(), ios::out);
  if (file) {
    file << "num_levels " << nlev << endl;
    file << "lower_corner " << extents.left << SPC << extents.bottom << endl;
    file << "element_width " << elem_width << endl;
    file << "height " << height << endl;
    file << "editable " << editable << endl;
    file << "saveable " << saveable << endl;
    file << "wrap " << wrap << endl;
    if (saveable) {
      file << "savings " << nlev << SPC;
      for (int i = 0; i < nlev; ++i) file << heights[i] << SPC << selection[i] << SPC;
      file << nsel << endl;
    } else {
      file << "savings 0" << endl;
    }
  } else dlog << "!!! couldnt save levels !!!" << endl;
}

int levels::stop_editing () {
  if (editing == FINISH) {
    editing = 0;
    /*if (nsel) {
      memset (selection, 0, sel_sz);
      nsel = 0;
    }*/

    return 1;
  }
  return 0;
}

int levels::handle_input () {

  prev_mousey = mousey;

  widget::handle_input ();

  int hne = hover && !editing;
  if (hne) calc_lev ();

  if (editable) {
    if (lmb) {
      if (lmb_clicked == 0) {
        if (stop_editing () == 0) {
          if (hne) {
            if (SHIFT) {
              bool& k = selection [lev];
              k = !k;
              if (k) ++nsel; else --nsel;
            } else {
              editing = STARTED;
              widget::focus = this;
            }
          }
        }
      }
      lmb_clicked = 1;
    } else {
      lmb_clicked = 0;
      if (editing) { // just mouse mov

        if (wheel) {
          mousey -= wheel;
          warp_mouse (mousex, mousey);
        }

        if (paint) calc_lev ();

        calc_hgt_val ();

        int dh = set (lev, val, hgt);
        int uml = 0;
        if (selection[lev] && !SHIFT ) uml = update_mul_lev (dh);
        if (lis && (dh || uml)) lis->changed (*this);

        editing = FINISH;
        edited = 1;

      } else {
        if (widget::focus == this) widget::focus = 0;
      }
    }
  }

  return edited;

}

int levels::update_mul_lev (int dh) {
  float dv = dh * extents.height_1;

  /*float vj [nlev];
  int hj [nlev];*/


  int ret = 0;
  for (int i = 0; i < nlev; ++i) {
    if ((i != lev) && selection[i]) {
      int& hi = heights[i];
      float& vi = values[i];
      int hji = hi + dh;
      float vji = vi + dv;

      if (hji < 0) hji = 0; else if (hji > extents.height) hji = extents.height;
      if (vji < 0.0f) vji = 0.0f; else if (vji > 1.0f) vji = 1.0f;
      hi = hji;
      vi = vji;
      ret = 1;

      /*if (!inrange (0, hji, extents.height)) return 0;
      hj[i] = hji;
      vj[i] = vji;*/


    }
  }

  /*ret = 1;
  for (int i = 0; i < nlev; ++i) {
    if ((i != lev) && selection[i]) {
      int& hi = heights[i];
      float& vi = values[i];
      hi = hj[i];
      vi = vj[i];
    }
  }*/

  return ret;


}

void levels::calc_lev () {
  lev =  (mousex - extents.left) / elem_width;
  if (lev > lastlev || lev < 0) lev = -1;
}

void levels::calc_hgt_val () {
  hgt = mouseyy - extents.bottom;
  clamp<int> (0, hgt, extents.height);
  val = hgt * extents.height_1;
}

void levels::clear_hgt_val () {
  for (int i = 0; i < nlev; ++i) values[i] = heights[i] = 0;
}

void levels::draw () {

  glEnable (GL_BLEND);
  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    int i = 0, x = extents.left, ds = elem_width - 2;
    if (extents.left < 0) {
      i = -extents.left / elem_width;
      x = 0;
    }
    for (;i < nlev; ++i) {
      int l = x + 1, r = x + ds;
      glColor4f (clr.r, clr.g, clr.b, a0);
        glRecti (l, extents.bottom, r, extents.top);

      float dc = selection[i] * 0.5;
      glColor4f (clr.r, clr.g + dc, clr.b, a);
        glRecti (l, extents.bottom, r, extents.bottom + heights[i]);
      x += elem_width;
      extern viewport view;
      if (x > view.xmax) break;
    }
  glDisable (GL_BLEND);

  sprintf (BUFFER, "%d/%.3f", lev+1, lev > -1? values[lev]:-1);
  draw_string (BUFFER, extents.left, extents.bottom - line_height, 0);
}

int levels::change (int i, float dv) {
  if (i > -1 && i < nlev) {
    float& vi = values[i];
    vi += dv;
    int result = clamp<float> (0, vi, 1);
    heights[i] = (int) (vi * extents.height + 0.5);
    return result;
  }
  return 0;
}

void levels::set_only (int i, float v) {
  if (i > -1 && i < nlev) {
    clamp<float> (0, v, 1);
    values[i] = v;
    heights[i] = (int)(v * extents.height + 0.5);
  }
}

int levels::set (int i, float v, int h) { // from ui
  if (i > -1 && i < nlev) {
    int& hi = heights[i];
    int dh = h - hi;
    hi = h;
    float& vi = values[i];
    if (vi != v) { // bcos from ui
      vi = v;
      // if (lis) lis->changed (*this);
    }
    return dh;
  }
  return 0;
}

void levels::update () {
  if (lis) lis->changed (*this);
}

void levels::chkpos () {
  extern viewport view;
  if (!view.inside (extents.left, extents.bottom)) extents.lower_corner (0, 0);
}

void levels::reheight () {
  for (int i = 0; i < nlev; ++i) {
    float v = values[i];
    int h = v * height + 0.5;
    heights[i] = h;
  }
}

int levels::lshift () {

  float v0 = values[0];
  int h0 = heights[0];

  if (wrap == 0) {
    if (heights[0]) return 0;
  }

  for (int i = 0, j = 1; i < lastlev; ++i, ++j) {
    values[i] = values[j];
    heights[i] = heights[j];
  }

  if (wrap) {
    values[lastlev] = v0;
    heights[lastlev] = h0;
  } else {
    values[lastlev] = heights[lastlev] = 0;
  }

  return 1;

}

int levels::rshift () {
  float vl = values[lastlev];
  int hl = heights[lastlev];

  if (wrap == 0) {
    if (hl) return 0;
  }

  for (int j = lastlev, i = lastlev - 1; j > 0; --j, --i) {
    values[j]=values[i];
    heights[j]=heights[i];
  }

  if (wrap) {
    values[0]=vl;
    heights[0]=hl;
  } else {
    values[0]=heights[0]= 0;
  }

  return 1;

}