Subversion Repositories DIN Is Noise

Rev

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

/*
* levels.cc
* DIN Is Noise is copyright (c) 2006-2019 Jagannathan Sampath
* For more information, please visit http://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;
extern char BUFFER [];
extern int line_height;

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

levels::~levels () {
  save ();
}

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;
    binary = 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);

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

  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;
      file << endl;
    } else {
      file << "savings 0" << endl;
    }
  } else dlog << "!!! couldnt save levels !!!" << endl;
}

int levels::stop_editing () {
  if (editing == FINISH) {
    editing = 0;
    return 1;
  }
  return 0;
}

int levels::handle_input () {

  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 (binary) { // toggle on/off
              float v = values [lev];
              if (v <= 0.5) v = 1; else v = 0;
              set (lev, v, -1);
              editing = 0;
            } 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 ();
        set (lev, val, hgt);
        editing = FINISH;
        edited = 1;
      } else {
        if (widget::focus == this) widget::focus = 0;
      }
    }
  }

  return edited;

}

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);
      glColor4f (clr.r, clr.g, 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);
  }
}

void levels::set (int i, float v, int h) { // from ui
  if (i > -1 && i < nlev) {
    if (h == -1)
      heights[i] = (int) (v * extents.height + 0.5);
    else
      heights[i] = h;
    float& vi = values[i];
    if (vi != v) { // bcos from ui
      vi = v;
      if (lis) lis->changed (*this);
    }
  }
}

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;

}