Rev 2097 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
* gravity.cc
* DIN Is Noise is copyright (c) 2006-2025 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;
#define NUDGEUP(W) W.set_pos (W.extents.left, W.extents.bottom + 3);
#define DECLW \
widget* w [] = {\
&lbl, &fold, \
&zero, &left, &right, &up, &down, \
&base2manual, &base2drone, \
&tip2manual, &tip2drone, \
&selbase, &seltip, &selboth, \
&here, &size,\
&cpoint, &cmouse,\
0\
};
#define NW 18
gravity_t::gravity_t () {
handlesize = 6;
strength = 0;
hitt = NOTHING;
lmb_clicked = 0;
mag0 = 50;
mag = 0;
DECLW
makefam (&lbl, &w[1], NW-1);
const char* txt [] = {
"Gravity", "", "0", "", "", "", "",
"Base to manual", "Base to drone",
"Tip to manual", "Tip to drone",
"Select base", "Select tip", "Select both",
"Here!", "Change size",
"Tip -> drone", "Tip -> mouse"
};
for (int i = 0; i < NW; ++i) {
label* lbl = dynamic_cast<label*>(w[i]);
lbl->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(&presetl);
}
LISTEN(zero,&presetl)
LISTEN(fold,this)
LISTEN(size, &sizel)
LISTEN(base2manual, &b2ml)
LISTEN(base2drone, &b2dl)
LISTEN(tip2manual, &t2ml)
LISTEN(tip2drone, &t2dl)
LISTEN(selbase, &sell)
LISTEN(seltip, &sell)
LISTEN(selboth, &sell)
LISTEN(here,&herel)
base2manual.id = base2drone.id = selbase.id = 0;
tip2manual.id = tip2drone.id = seltip.id = 1;
selboth.id = 2;
MOVE(lbl)
}
int gravity_t::handle_input () {
if (keydown(SDLK_KP_PLUS)) chgmag (+1);
else if (keydown(SDLK_KP_MINUS)) chgmag (-1);
HANDLEINPUT(fold)
else if (unfolded()) {
DECLW
for (widget** p = w; *p != 0; ++p) if ((*p)->handle_input ()) break;
}
return 1;
}
int gravity_t::handle_input2 () {
HANDLEINPUT(lbl)
if (is_lmb (this)) {
if (lmb_clicked == 0) {
lmb_clicked = 1;
if (hitt != NOTHING) {
hitt = NEXT_TO_NOTHING;
} else {
if (hit (tip, din0.win_mousex, din0.win_mousey)) {
hitt = TIP;
is_lmb.tie = this;
} else
if (hit (base, din0.win_mousex, din0.win_mousey)) {
hitt = BASE;
is_lmb.tie = this;
}
}
}
} else {
if (hitt == NOTHING) ;
else
if (hitt == NEXT_TO_NOTHING) {
stop_editing ();
} else if (hitt == TIP) {
set (tip, din0.win_mousex, din0.win_mousey);
ldwx [1] = ldwy[1] = -1;
} else if (hitt == BASE) {
set (base, din0.win_mousex, din0.win_mousey);
ldwx [0] = ldwy[0] = -1;
}
lmb_clicked = 0;
}
return hitt;
}
void gravity_t::draw () {
fold.draw ();
lbl.draw ();
if (unfolded()) {
DECLW
for (widget** p = w; *p != 0; ++p) (*p)->draw ();
}
}
void gravity_t::drawrrow () {
glColor3f (1, 0.6, 0.4);
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::calcbase2tip () {
direction (base2tip, base, tip);
perpendicular (p_base2tip, base2tip);
gx = strength * base2tip.x;
gy = strength * base2tip.y;
}
void gravity_t::calcvisual () {
bottomleft (base.x - handlesize, base.y - handlesize);
topright (base.x + handlesize, base.y + handlesize);
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);
}
void gravity_t::calc (int calc_mag) {
calcbase2tip ();
calcvisual ();
if (calc_mag) mag = magnitude (base2tip);
}
void gravity_t::calcui () {
win2view (base.x, base.y, textpos.x, textpos.y, din0.win, view);
if (!view.inside (textpos.x, textpos.y)) {
textpos.x = view.midx;
textpos.y = view.midy;
}
static const int ds = 15, ds2 = ds / 2;
textpos.x += ds;
fold.set_pos (textpos.x, textpos.y - ds2);
lbl.set_pos (fold.extents.right + ds2, fold.extents.bottom);
int xx = textpos.x, yy = fold.extents.bottom - line_height;
{
widget* w [] = {&zero, &left, &right, &up, &down, &here, &size, 0};
for (widget** p = w; *p != 0; ++p) {
widget* wi = *p;
wi->set_pos (xx, yy);
xx = wi->extents.right + ds;
}
}
{
widget* w[] = {&left, &right, &up, &down, 0};
for (widget** p = w; *p != 0; ++p) {
widget& wp = **p;
NUDGEUP (wp);
}
}
yy -= line_height;
base2drone.set_pos (textpos.x, yy);
base2manual.set_pos (base2drone.extents.right + ds, yy);
tip2drone.set_pos (textpos.x, yy -= line_height);
tip2manual.set_pos (tip2drone.extents.right + ds, yy);
{
xx = textpos.x;
yy -= line_height;
widget* w[] = {&selbase, &seltip, &selboth, 0};
for (widget** p = w; *p != 0; ++p) {
widget& wp = **p;
wp.set_pos (xx, yy);
xx = wp.extents.right + ds;
}
}
{
xx = textpos.x;
yy -= line_height;
cpoint.set_pos (xx, yy);
cmouse.set_pos (cpoint.extents.right + ds, yy);
}
}
void gravity_t::set (point<float>& what, float mx, float my, int calc_mag) {
what.x = mx;
what.y = my;
calc (calc_mag);
}
void gravity_t::move (float tox, float toy) {
base.x = tox;
base.y = toy;
tip.x = tox + base2tip.x;
tip.y = toy + base2tip.y;
calcvisual ();
}
int gravity_t::hit (const point<float>& what, float mx, float my) {
double m = magnitude (what.x, what.y, mx, my);
return !(m > handlesize);
}
void gravity_t::load (ifstream& file) {
string ignore;
float bx, by, tx, ty;
file >> ignore >> bx >> by >> tx >> ty;
set (base, bx, by);
set (tip, tx, ty);
file >> strength >> visible;
}
void gravity_t::save (ofstream& file) {
file << "gravity " << base.x << spc << base.y << spc << tip.x << spc << tip.y << spc << strength << spc << visible << endl;
}
void gravity_t::preset (int id) {
float xx [] = {base.x, float (base.x - mag), float(base.x + mag), base.x, base.x};
float yy [] = {base.y, base.y, base.y, float(base.y + mag), float(base.y - mag)};
tip.x = xx [id];
tip.y = yy [id];
calc (0);
}
void gravity_t::track (int i, float vx, float vy) {
point<float>* pta [] = {&base, &tip};
point<float>& pt = *pta[i];
if (i == 1) {
if (cpoint.state) {
pointt (vx, vy);
return;
}
}
set (pt, vx, vy);
}
void gravity_t::pointt (float vx, float vy) {
float ux, uy;
unit_vector (ux, uy, base.x, base.y, vx, vy);
set (tip, base.x + mag * ux, base.y + mag * uy);
}
void gravity_t::chgmag (float amt) {
mag += amt;
if (mag > 0) {
point<float> u;
unit_vector (u, base2tip);
tip.x = base.x + mag * u.x;
tip.y = base.y + mag * u.y;
calc (0);
}
}
void gravity_t::moused (int dir, double scl) {chgmag (dir*scl);}
int gravity_t::stop_editing () {
if (hitt != NOTHING) {
hitt = NOTHING;
is_lmb.clear (this);
return 1;
}
return 0;
}
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);
}
}
}
int gravity_t::unfolded () {return fold.dir == arrow_button::down;}
CLICKED_BUTTON (gravity_t, drolis) {
din& d = din0;
gravity_t& g = d.dinfo.gravity;
if (d.num_selected_drones) {
g.tracked_drone[b.id] = d.selected_drones[0];
g.ldwx[b.id] = g.ldwy[b.id] = -1;
} else
cons << RED_PSD << eol;
}
CLICKED_BUTTON (gravity_t, manlis) {
gravity_t& g = din0.dinfo.gravity;
g.tracked_drone[b.id] = 0;
g.ldwx[b.id] = g.ldwy[b.id] = -1;
}
CLICKED_BUTTON (gravity_t, sellis) {
din& d = din0;
gravity_t& g = d.dinfo.gravity;
if (SHIFT || CTRL) ; else d.clear_selected_drones ();
if (b.id == 2) {
drone* td0 = g.tracked_drone[0], *td1 = g.tracked_drone[1];
if (td0 && td1) {
d.add_drone_to_selection (td0);
d.add_drone_to_selection (td1);
}
} else {
drone* td = g.tracked_drone[b.id];
if (td) d.add_drone_to_selection (td);
}
d.print_selected_drones ();
}
CLICKED_BUTTON (gravity_t, herelis) {
din& d = din0;
gravity_t& g = d.dinfo.gravity;
int vx = g.fold.extents.left, vy = g.fold.extents.top;
float wx, wy;
view2win (vx, vy, wx, wy, view, d.win);
static const int h3 = 3 * g.handlesize;
float dg = (g.base2tip.x < 0) ? -g.base2tip.x : g.base2tip.x;
wx = wx - dg - h3;
g.move (wx, wy);
}
CLICKED_BUTTON (gravity_t, presetlis) {
din& d = din0;
gravity_t& g = d.dinfo.gravity;
g.preset (b.id);
}
CLICKED_BUTTON (gravity_t, sizelis) {
gravity_t* g = &din0.dinfo.gravity;
mouse_slider0.add (g);
activate_mouse_slider ();
}