Rev 2324 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
* basic_editor.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 <fstream>
#include <iostream>
#include "main.h"
#include "input.h"
#include "font.h"
#include "console.h"
#include "basic_editor.h"
#include "solver.h"
#include "widget.h"
#include "ui_list.h"
using namespace std;
extern std::string user_data_dir;
extern viewport view;
extern char BUFFER [];
extern int wheel;
extern int can_wheel ();
basic_editor::basic_editor () {
edit_sustain = 0;
kbkb_attack_editor = 0;
lmb_clicked = 0;
pan = zoom = 1;
ed = ++ref;
nx = ny = nx2 = ny2 = 0;
undo_redo_win = 1;
}
basic_editor::~basic_editor () {
if (--ref == 0) {
if (gl_pts) {
dlog << "cleared basic_editor::gl_pts @ " << gl_pts << endl;
delete[] gl_pts;
}
if (gl_clr) {
delete[] gl_clr;
}
}
}
void basic_editor::save (ofstream& file) {
file << "editor " << name << endl;
file << "window&undo_redo_win " << win.left << spc << win.bottom << spc << win.right << spc << win.top << spc << undo_redo_win << endl;
file << "win.chunk " << win_chunk.x << spc << win_chunk.y << endl;
file << "obj.chunk " << obj_chunk.x << spc << obj_chunk.y << endl;
file << "snap_axis+draw:snaps+guide " << snapaxis.x << spc << snapaxis.y << spc << draww.snaps << spc << draww.guide << endl;
file << "win.res+mouse.last " << win_resolution << spc << prev_mousex << spc << prev_mousey << endl;
}
void basic_editor::load (ifstream& file) {
std::string ignore;
file >> ignore >> name;
float l, b, r, t;
file >> ignore >> l >> b >> r >> t >> undo_redo_win;
win.set (l, b, r, t);
file >> ignore >> win_chunk.x >> win_chunk.y;
file >> ignore >> obj_chunk.x >> obj_chunk.y;
win_per_obj (win_chunk.x / obj_chunk.x, win_chunk.y / obj_chunk.y);
obj_per_win (obj_chunk.x / win_chunk.x , obj_chunk.y / win_chunk.y);
file >> ignore >> snapaxis.x >> snapaxis.y >> draww.snaps >> draww.guide;
file >> ignore >> win_resolution >> prev_mousex >> prev_mousey;
}
void basic_editor::load (const std::string& fname) {
ifstream file ((user_data_dir + fname).c_str (), ios::in);
if (!file) return;
load (file);
}
void basic_editor::calc_win_mouse () {
win.update_mouse ();
}
int basic_editor::handle_input () {
if (kbkb_attack_editor) {
if (lmb) {
if (lmb_clicked == 0) {
if (edit_sustain) edit_sustain = 0;
else {if (inbox (susbox, win.mousex, win.mousey)) edit_sustain = 1;}
lmb_clicked = 1;
}
} else {
if (edit_sustain) {
float sx, sy; snap (sx, sy);
float cx, cy; win2obj (sx, sy, cx, cy);
_gotog.set (cx);
}
lmb_clicked = 0;
}
}
// mouse capture
if (mocap0.state == mocap::capturing) mocap0.add (win.mousex, win.mousey);
// movement
//
if (can_wheel ()) do_zoom (-wheel * zoom);
double pan_rept = window::PAN_REPEAT, zoom_rept = window::ZOOM_REPEAT;
if (keypressedd (SDLK_a, pan_rept, pan_rept)) do_panx (-pan);
else if (keypressedd (SDLK_d, pan_rept, pan_rept)) do_panx (+pan);
else if (keypressedd (SDLK_w, pan_rept, pan_rept)) do_pany (+pan);
else if (keypressedd (SDLK_s, pan_rept, pan_rept)) do_pany (-pan);
else if (keypressed (SDLK_g)) {
MENU.drawcursor.toggle ();
}
// snap
else if (keypressed (SDLK_x)) set_snap (1, 0);
else if (keypressed (SDLK_y)) set_snap (0, 1);
else if (keypressed (SDLK_b)) set_snap (1, 1);
else if (keypressed (SDLK_n)) set_snap (0, 0);
else if (keypressed (SDLK_QUOTE)) {
MENU.drawsnaps.toggle ();
}
/*else if (keypressedd (SDLK_F5)) {
if (SHIFT) set_win_chunk (win_chunk.x, --win_chunk.y); else set_win_chunk (--win_chunk.x, win_chunk.y);
} else if (keypressedd (SDLK_F6)) {
if (SHIFT) set_win_chunk (win_chunk.x, ++win_chunk.y); else set_win_chunk (++win_chunk.x, win_chunk.y);
}*/
else if (keypressed (SDLK_F7)) {
toggle_mouse_capture ();
}
/*
// custom guides
if (keypressed (SDLK_UP)) {
sprintf (BUFFER, "%.3f", cursor.ox);
tb.add (text(BUFFER, cursor.ox, cursor.oy, 0.5f, 0.5f, 0.5f, text::session, text::vline));
calc_visual_params ();
} else if (keypressed(SDLK_RIGHT)) {
sprintf (BUFFER, "%.3f", cursor.oy);
tb.add (text(BUFFER, cursor.ox, cursor.oy, 0.5f, 0.5f, 0.5f, text::session, text::hline));
calc_visual_params ();
} else if (keypressed (SDLK_LEFT)) {
if (SHIFT)
tb.delallguides (text::hline);
else
tb.delnearestguide (text::hline, cursor.vx, cursor.vy);
} else if (keypressed (SDLK_DOWN)) {
if (SHIFT)
tb.delallguides (text::vline);
else
tb.delnearestguide (text::vline, cursor.vx, cursor.vy);
}
*/
if (!mouse_slider0.active) {
if (keypressedd (SDLK_q, zoom_rept, zoom_rept)) do_zoom (+zoom);
else if (keypressedd (SDLK_e, zoom_rept, zoom_rept)) do_zoom (-zoom);
cursor.calc (this);
}
return 1;
}
void basic_editor::set_win_chunk (int x, int y) {
if (x < 1) x = 1;
if (y < 1) y = 1;
win_chunk.x = x;
win_chunk.y = y;
float wx = win_chunk.x / obj_chunk.x, wy = win_chunk.y / obj_chunk.y;
win_per_obj (wx, wy);
obj_per_win (1.0f/wx, 1.0f/wy);
}
void basic_editor::snap (float& x, float& y) {
x = win.mousex;
y = win.mousey;
if (SHIFT) { // fixed x
if (shft_clk.noted == 0) {
do_snapx (x);
shft_clk.note (x, y);
}
x = shft_clk.pt.x;
do_snapy (y);
ctrl_clk.noted = 0;
} else if (CTRL) { // fixed y
if (ctrl_clk.noted == 0) {
do_snapy (y);
ctrl_clk.note (x, y);
}
y = ctrl_clk.pt.y;
do_snapx (x);
shft_clk.noted = 0;
} else { // snap x, y
do_snapx (x);
do_snapy (y);
ctrl_clk.noted = 0;
shft_clk.noted = 0;
}
}
void basic_editor::do_snap (float& v, int a, float n, float d) {
if (a) {
float s = n / d;
if (s < 0) s -= 0.5; else s += 0.5;
v = (int) s * d;
}
}
void basic_editor::do_snapx (float& x) {
do_snap (x, snapaxis.x, win.mousex, win_chunk.x);
}
void basic_editor::do_snapy (float& y) {
do_snap (y, snapaxis.y, win.mousey, win_chunk.y);
}
void basic_editor::project () {
glMatrixMode (GL_PROJECTION);
glPushMatrix ();
glLoadIdentity ();
glOrtho (win.left, win.right, win.bottom, win.top, -1, 1);
glMatrixMode (GL_MODELVIEW);
glPushMatrix ();
glLoadIdentity ();
}
void basic_editor::unproject () {
glMatrixMode (GL_MODELVIEW);
glPopMatrix ();
glMatrixMode (GL_PROJECTION);
glPopMatrix ();
}
void basic_editor::draw () {
if (draww.snaps) draw_snaps (); // must be wrapped by project, unproject
}
void basic_editor::draw_cursor () {
glMatrixMode (GL_PROJECTION);
glPushMatrix ();
glLoadIdentity ();
glOrtho (0, view.xmax, 0, view.ymax, 0, 1);
#define SPACING 12
int vx = cursor.vx, vy = cursor.vy;
int vxs = vx + SPACING;
if (draww.guide) {
glColor3f (0.5f, 0.5f, 0.5f);
gl_pts[0]=0; gl_pts[1]=vy;
gl_pts[2]=vx - SPACING; gl_pts[3]=vy;
gl_pts[4]=vxs; gl_pts[5]=vy;
gl_pts[6]=view.xmax; gl_pts[7]=vy;
gl_pts[8]=vx; gl_pts[9]=0;
gl_pts[10]=vx; gl_pts[11]=vy - SPACING;
gl_pts[12]=vx; gl_pts[13]=vy + SPACING;
gl_pts[14]=vx; gl_pts[15]=view.ymax;
glVertexPointer (2, GL_FLOAT, 0, gl_pts);
glDrawArrays (GL_LINES, 0, 8);
}
if (hide_cursor == 0) {
glColor3f (1, 1, 1);
sprintf (BUFFER, "%.3f, %.3f", cursor.ox, cursor.oy);
draw_string (BUFFER, vxs, vy);
if (cursor.yesmesg) {
glColor3f (1, 1, 0.5);
vy -= line_height;
draw_string (cursor.mesg, vx, vy);
}
}
extern int line_height;
if (edit_sustain) {
vy -= line_height;
extern gotog _gotog;
sprintf (BUFFER, " sustain @ %.3f", _gotog.g);
draw_string (BUFFER, vx, vy);
}
glPopMatrix ();
}
void basic_editor::set_snap (int x, int y) {
snapaxis.x = x;
snapaxis.y = y;
update_snaps ();
}
void basic_editor::update_snaps () {
int l, b, r, t;
int p, n;
if (snapaxis.x) {
l = int (win.left / win_chunk.x);
startx = l * win_chunk.x;
r = int (win.right / win_chunk.x);
endx = r * win_chunk.x;
p = (endx - startx) / win_chunk.x;
n = 4 * p;
nx2 = n / 2;
if (n > nx) {
xlines.reserve (n);
nx = n;
}
for (int i = 0, j = 0; i < p; ++i) {
xlines[j++]=startx;
xlines[j++]=win.bottom;
xlines[j++]=startx;
xlines[j++]=win.top;
startx += win_chunk.x;
}
}
if (snapaxis.y) {
b = int (win.bottom / win_chunk.y);
starty = b * win_chunk.y;
t = int (win.top / win_chunk.y);
endy = t * win_chunk.y;
p = (endy - starty) / win_chunk.y;
n = 4 * p;
ny2 = n / 2;
if (n > ny) {
ylines.reserve (n);
ny = n;
}
for (int i = 0, j = 0; i < p; ++i) {
ylines[j++]=win.left;
ylines[j++]=starty;
ylines[j++]=win.right;
ylines[j++]=starty;
starty += win_chunk.y;
}
}
}
void basic_editor::draw_snaps () {
static const float sr = 0.2f, sg = sr, sb = sg; // snap color
glColor3f (sr, sg, sb);
if (snapaxis.x) { // lines along y
glVertexPointer (2, GL_INT, 0, xlines.data ());
glDrawArrays (GL_LINES, 0, nx2);
}
if (snapaxis.y) { // lines along x
glVertexPointer (2, GL_INT, 0, ylines.data ());
glDrawArrays (GL_LINES, 0, ny2);
}
}
void basic_editor::calc_visual_params () {
if (kbkb_attack_editor) susbox (susx - win.handle_radius, win.top - win.sus_handle_radius, susx + win.handle_radius, win.top);
tb.refresh (this);
update_snaps ();
}
void basic_editor::do_panx (int dir) {
win.panx (dir);
calc_visual_params ();
}
void basic_editor::do_pany (int dir) {
win.pany (dir);
calc_visual_params ();
}
void basic_editor::do_zoom (int dir) {
win.zoom (dir);
calc_visual_params ();
}
void basic_editor::update_sustain (float f) {
float ox = f, oy = 0;
obj2win (ox, oy, susx, susy);
calc_visual_params ();
}
void basic_editor::start_mouse_capture () {
mocap0.clear ();
mocap0.state = mocap::capturing;
cons << GREEN << "Capturing mouse" << eol;
}
void basic_editor::stop_mouse_capture () {
if (mocap0.state == mocap::capturing) {
mocap0.finish (this);
cons << GREEN << "Captured mouse!" << eol;
}
}
void basic_editor::toggle_mouse_capture () {
if (mocap0.state != mocap::capturing) start_mouse_capture (); else stop_mouse_capture ();
}
void basic_editor::obj2win (const float& ox, const float& oy, float& wx, float& wy) {
wx = win_per_obj.x * ox;
wy = win_per_obj.y * oy;
}
void basic_editor::obj2win (float* oxa, float* oya, float* wxa, float* wya, int n) {
for (int i = 0; i < n; ++i) {
wxa[i] = win_per_obj.x * oxa[i];
wya[i] = win_per_obj.y * oya[i];
}
}
void basic_editor::objx2winx (float& ox, float& wx) {
wx = win_per_obj.x * ox;
}
void basic_editor::obj2win (const point<float>& v, float& wx, float& wy) {
obj2win (v.x, v.y, wx, wy);
}
void basic_editor::win2obj (const float& wx, const float& wy, float& ox, float& oy) {
ox = obj_per_win.x * wx;
oy = obj_per_win.y * wy;
}
void basic_editor::obj2view (const float& ox, const float& oy, int& vx, int& vy) {
float wx, wy;
obj2win (ox, oy, wx, wy);
win2view (wx, wy, vx, vy, win, view);
}
void basic_editor::view2obj (const int& vx, const int& vy, float& ox, float& oy) {
float wx, wy;
view2win (vx, vy, wx, wy, view, win);
win2obj (wx, wy, ox, oy);
}
void basic_editor::obj2mouse (const float& ox, const float& oy) {
int vx, vy;
obj2view (ox, oy, vx, vy);
warp_mouse (vx, view.ymax - vy);
}
click_point_t::click_point_t () : noted (0) {}
void click_point_t::note (float x, float y) {
pt.x = x;
pt.y = y;
noted = 1;
}
basic_editor::snapaxist::snapaxist () { x = y = 0;}