Subversion Repositories DIN Is Noise

Rev

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

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


#include "gravity.h"
#include "font.h"
#include "vector2d.h"
#include "drone.h"
#include "console.h"
#include "din.h"

#include <fstream>

using namespace std;

extern int mousex, mouseyy;

#define NUDGEDOWN(W) W.set_pos (W.extents.left, W.extents.bottom - 3);


gravity_t::gravity_t () {

  mouse_slider_listener::name = "Gravity";
  handlesize = 5;
  strength = 0;
  hitt = NOTHING;
  lmb_clicked = 0;
  tracked_drone = 0;
  forcetrack = 0;
  mag0 = 50;
  mag = 0;
  keep_size = 0;
  button* bt [] = {&zero, &reset, &keepsize, &mouse, &dron, &changesize};
  const char* txt [] = {"0", "Reset", "Keep size", "Mouse", "Drone", "Change size"};
  for (int i = 0; i < 6; ++i) bt[i]->set_text (txt[i]);
  arrow_button* ab [] = {&left, &right, &up, &down};
  int dirr [] = {arrow_button::left, arrow_button::right, arrow_button::up, arrow_button::down};
  for (int i = 0, j = 1; i < 4; ++i, ++j) {
    arrow_button* abi = ab[i];
    abi->id = j;
    abi->set_dir (dirr[i]);
    abi->set_listener(this);
  }
  LISTEN(fold,this)
  LISTEN(zero,this)
  LISTEN(reset,this)
  LISTEN(changesize,this)
  LISTEN(mouse,&ml)
}

int gravity_t::handle_input () {

  HANDLEINPUT(fold)
  else if (fold.dir == arrow_button::down) {
    button* bt[] = {&zero, &left, &right, &up, &down, &reset, &keepsize, &mouse, &dron, &changesize};
    for (int i = 0; i < 10; ++i) if (bt[i]->handle_input()) break;
  }

  if (is_lmb (this)) {
    if (lmb_clicked == 0) {
      lmb_clicked = 1;
      if (hitt != NOTHING) {
        hitt = NEXT_TO_NOTHING;
      } else {
        if (hit (tip, mousex, mouseyy)) {
          hitt = TIP; // edit tip
          is_lmb.tie = this;
        } else
        if (hit (base, mousex, mouseyy)) {
          hitt = BASE; // edit base
          is_lmb.tie = this;
        }
      }
    }
  } else {
    if (hitt == NOTHING) {
    }
    else
    if (hitt == NEXT_TO_NOTHING) {
      stop_editing ();
    } else if (hitt == TIP) { // update tip
      set (tip, mousex, mouseyy);
    } else if (hitt == BASE) { // update base
      set (tip, mousex + base2tip.x, mouseyy + base2tip.y, 0);
      set (base, mousex, mouseyy, 0);
      calcui ();
    }
    lmb_clicked = 0;
  }
  return hitt;
}

void gravity_t::draw () {
  fold.draw ();
  if (fold.dir == arrow_button::down) {
    button* b [] = {&zero, &reset, &left, &right, &up, &down, &keepsize, &mouse, &dron, &changesize};
    for (int i = 0; i < 10; ++i) b[i]->draw ();
  }
  glColor3f (1, 0.6, 0.5);
  draw_string ("Gravity", textpos.x, textpos.y);
  glVertexPointer (2, GL_INT, 0, gl_base);
  glDrawArrays (GL_LINE_LOOP, 0, 4);
  glVertexPointer (2, GL_FLOAT, 0, gl_arrow);
  glDrawArrays (GL_LINES, 0, 6);
}


void gravity_t::calc (int calc_mag) {
  direction (base2tip, base, tip);
  perpendicular (p_base2tip, base2tip);
  bottomleft (base.x - handlesize, base.y - handlesize);
  topright (base.x + handlesize, base.y + handlesize);
  gx = strength * base2tip.x; gy = strength * base2tip.y;
  gl_base[0]=bottomleft.x; gl_base[1]=bottomleft.y;
  gl_base[2]=topright.x; gl_base[3]=gl_base[1];
  gl_base[4]=gl_base[2];gl_base[5]=topright.y;
  gl_base[6]=gl_base[0];gl_base[7]=gl_base[5];
  int cap = 0;
  int da = 0;
  make_arrow (gl_arrow, 0, cap, da, base.x, base.y, base2tip.x, base2tip.y, p_base2tip.x, p_base2tip.y, 0.6f, 0.2f);
  if (calc_mag) mag = magnitude (base2tip);
}

void gravity_t::calcui () {
  fold.set_pos (topright.x + 5, bottomleft.y);
  textpos (fold.extents.right + 5, bottomleft.y - 3);
  button* bt [] = {&zero, &left, &right, &up, &down, &mouse, &dron};
  int xx = textpos.x, yy = textpos.y - line_height;
  int ds = 10;
  for (int i = 0; i < 7; ++i) {
    button* bti = bt[i];
    bti->set_pos (xx, yy);
    xx = bti->extents.right + ds;
  }
  NUDGEDOWN (zero);
  NUDGEDOWN (mouse);
  NUDGEDOWN (dron);
  reset.set_pos (textpos.x, zero.extents.bottom - line_height);
  keepsize.set_pos (reset.extents.right + ds, reset.extents.bottom);
  changesize.set_pos (textpos.x, reset.extents.bottom - line_height);
}

void gravity_t::set (point<int>& what, int mx, int my, int calc_mag) {
  what.x = mx;
  what.y = my;
  calc (calc_mag);
}

int gravity_t::hit (const point<int>& what, int mx, int my) {
  double m = magnitude (what.x, what.y, mx, my);
  if (m <= handlesize) return 1; else return 0;
}


void gravity_t::load (ifstream& file) {
  string ignore;
  int bx, by, tx, ty; file >> ignore >> bx >> by >> tx >> ty;
  set (base, bx, by);
  set (tip, tx, ty);
  file >> strength >> visible >> keep_size >> maos >> dronn;
}

void gravity_t::save (ofstream& file) {
  file << "gravity " << base.x << spc << base.y << spc << tip.x << spc << tip.y << spc << strength << spc << visible << spc << keep_size << spc << mouse.state << spc << dron.state << endl;
}

void gravity_t::doreset (int ks) {
  keep_size = ks;
  if (!keep_size) mag = mag0;
  preset (down.id);
}

void gravity_t::preset (int id) {
  if (!id) {
    mag = 0;
  } else {
    if (mag == 0) mag = mag0;
  }
  int xx [] = {base.x, int (base.x - mag), int (base.x + mag), base.x, base.x};
  int yy [] = {base.y, base.y, base.y, int(base.y + mag), int(base.y - mag)};
  tip.x = int (xx [id]);
  tip.y = int (yy [id]);
  calc (0);
}

void gravity_t::track (int vx, int vy) {
  float ux, uy; unit_vector (ux, uy, base.x, base.y, vx, vy);
  vx = base.x + mag * ux;
  vy = base.y + mag * uy;
  set (tip, vx, vy, 0);
  forcetrack = 0;
}

int gravity_t::stop_editing () {
  if (hitt != NOTHING) {
    hitt = NOTHING;
    is_lmb.clear (this);
    return 1;
  }
  return 0;
}

static double ux, uy;

void gravity_t::clicked (button& b) {
  if (&b == &fold) {
    if (fold.dir == arrow_button::right) {
      fold.set_dir(arrow_button::down);
    } else {
      fold.set_dir(arrow_button::right);
    }
  } else {
    if (&b == &reset) {
      doreset (keepsize.state);
    } else if (&b == &changesize) {
      unit_vector<double> (ux, uy, base2tip.x, base2tip.y);
      mouse_slider0.add (this);
      activate_mouse_slider ();
    } else {
      preset (b.id);
    }
  }
}

void gravity_t::moused (int dir, double scl) {
  mag += (sign(dir) * scl);
  if (mag < 0) mag = 0;
  tip.x = base.x + mag * ux;
  tip.y = base.y + mag * uy;
  #define BUTDONTCALCMAG 0
  calc (BUTDONTCALCMAG);
}


int gravity_t::unfolded () {return fold.dir == arrow_button::down;}

CLICKED_CHECKBUTTON (gravity_t, mousel) {
  if (cb.state) din0.dinfo.gravity.track (mousex, mouseyy);
}