curvedraw

diff src/app.cc @ 15:37ab3a4c02f8

merged
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 20 Dec 2015 09:06:04 +0200
parents b625f0575d66 4da693339d99
children 7f795f7fecd6
line diff
     1.1 --- a/src/app.cc	Thu Dec 17 16:41:42 2015 +0200
     1.2 +++ b/src/app.cc	Sun Dec 20 09:06:04 2015 +0200
     1.3 @@ -7,6 +7,7 @@
     1.4  #include "app.h"
     1.5  #include "curve.h"
     1.6  #include "widgets.h"
     1.7 +#include "curvefile.h"
     1.8  
     1.9  enum SnapMode {
    1.10  	SNAP_NONE,
    1.11 @@ -29,21 +30,24 @@
    1.12  static float grid_size = 1.0;
    1.13  static SnapMode snap_mode;
    1.14  
    1.15 +static bool show_bounds;
    1.16 +
    1.17  static std::vector<Curve*> curves;
    1.18  static Curve *sel_curve;	// selected curve being edited
    1.19  static Curve *new_curve;	// new curve being entered
    1.20  static Curve *hover_curve;	// curve the mouse is hovering over (click to select)
    1.21 -static int sel_pidx = -1;	// selected point of the selected or hovered-over curve
    1.22 +static int sel_pidx = -1;	// selected point of the selected curve
    1.23 +static int hover_pidx = -1;	// hovered over point
    1.24  
    1.25  static Label *weight_label;	// floating label for the cp weight
    1.26  
    1.27 -#ifdef DRAW_MOUSE_POINTER
    1.28  static Vector2 mouse_pointer;
    1.29 -#endif
    1.30  
    1.31  
    1.32  bool app_init(int argc, char **argv)
    1.33  {
    1.34 +	glewInit();
    1.35 +
    1.36  	glEnable(GL_MULTISAMPLE);
    1.37  	glEnable(GL_CULL_FACE);
    1.38  
    1.39 @@ -148,6 +152,20 @@
    1.40  	int numpt = curve->size();
    1.41  	int segm = numpt * 16;
    1.42  
    1.43 +	if(show_bounds) {
    1.44 +		Vector3 bmin, bmax;
    1.45 +		curve->get_bbox(&bmin, &bmax);
    1.46 +
    1.47 +		glLineWidth(1.0);
    1.48 +		glColor3f(0, 1, 0);
    1.49 +		glBegin(GL_LINE_LOOP);
    1.50 +		glVertex2f(bmin.x, bmin.y);
    1.51 +		glVertex2f(bmax.x, bmin.y);
    1.52 +		glVertex2f(bmax.x, bmax.y);
    1.53 +		glVertex2f(bmin.x, bmax.y);
    1.54 +		glEnd();
    1.55 +	}
    1.56 +
    1.57  	glLineWidth(curve == hover_curve ? 4.0 : 2.0);
    1.58  	if(curve == sel_curve) {
    1.59  		glColor3f(0.3, 0.4, 1.0);
    1.60 @@ -159,7 +177,7 @@
    1.61  	glBegin(GL_LINE_STRIP);
    1.62  	for(int i=0; i<segm; i++) {
    1.63  		float t = (float)i / (float)(segm - 1);
    1.64 -		Vector2 v = curve->interpolate(t);
    1.65 +		Vector3 v = curve->interpolate(t);
    1.66  		glVertex2f(v.x, v.y);
    1.67  	}
    1.68  	glEnd();
    1.69 @@ -180,10 +198,23 @@
    1.70  				glColor3f(0.2, 1.0, 0.2);
    1.71  			}
    1.72  		}
    1.73 -		Vector2 pt = curve->get_point(i);
    1.74 +		Vector2 pt = curve->get_point2(i);
    1.75  		glVertex2f(pt.x, pt.y);
    1.76  	}
    1.77  	glEnd();
    1.78 +
    1.79 +	// draw the projected mouse point on the selected curve
    1.80 +	/*
    1.81 +	if(curve == sel_curve) {
    1.82 +		Vector3 pp = curve->proj_point(Vector3(mouse_pointer.x, mouse_pointer.y, 0.0));
    1.83 +
    1.84 +		glPointSize(5.0);
    1.85 +		glBegin(GL_POINTS);
    1.86 +		glColor3f(1, 0.8, 0.2);
    1.87 +		glVertex2f(pp.x, pp.y);
    1.88 +		glEnd();
    1.89 +	}
    1.90 +	*/
    1.91  	glPointSize(1.0);
    1.92  }
    1.93  
    1.94 @@ -215,40 +246,64 @@
    1.95  			}
    1.96  			break;
    1.97  
    1.98 -		case 'l':
    1.99 -		case 'L':
   1.100 +		case '1':
   1.101 +		case '2':
   1.102 +		case '3':
   1.103  			if(sel_curve) {
   1.104 -				sel_curve->set_type(CURVE_LINEAR);
   1.105 +				sel_curve->set_type((CurveType)((int)CURVE_LINEAR + key - '1'));
   1.106  				post_redisplay();
   1.107  			}
   1.108  			if(new_curve) {
   1.109 -				new_curve->set_type(CURVE_LINEAR);
   1.110 +				new_curve->set_type((CurveType)((int)CURVE_LINEAR + key - '1'));
   1.111  				post_redisplay();
   1.112  			}
   1.113  			break;
   1.114  
   1.115  		case 'b':
   1.116  		case 'B':
   1.117 +			show_bounds = !show_bounds;
   1.118 +			post_redisplay();
   1.119 +			break;
   1.120 +
   1.121 +		case 'n':
   1.122 +		case 'N':
   1.123  			if(sel_curve) {
   1.124 -				sel_curve->set_type(CURVE_BSPLINE);
   1.125 -				post_redisplay();
   1.126 -			}
   1.127 -			if(new_curve) {
   1.128 -				new_curve->set_type(CURVE_BSPLINE);
   1.129 +				sel_curve->normalize();
   1.130  				post_redisplay();
   1.131  			}
   1.132  			break;
   1.133  
   1.134 -		case 'h':
   1.135 -		case 'H':
   1.136 -			if(sel_curve) {
   1.137 -				sel_curve->set_type(CURVE_HERMITE);
   1.138 -				post_redisplay();
   1.139 +		case 'e':
   1.140 +		case 'E':
   1.141 +			// TODO: GUI for filename at least
   1.142 +			if(!save_curves("test.curves", &curves[0], (int)curves.size())) {
   1.143 +				fprintf(stderr, "failed to export curves\n");
   1.144  			}
   1.145 -			if(new_curve) {
   1.146 -				new_curve->set_type(CURVE_HERMITE);
   1.147 -				post_redisplay();
   1.148 +			printf("exported %d curves\n", (int)curves.size());
   1.149 +			break;
   1.150 +
   1.151 +		case 'l':
   1.152 +		case 'L':
   1.153 +			{
   1.154 +				std::list<Curve*> clist = load_curves("test.curves");
   1.155 +				if(clist.empty()) {
   1.156 +					fprintf(stderr, "failed to import curves\n");
   1.157 +				}
   1.158 +
   1.159 +				for(size_t i=0; i<curves.size(); i++) {
   1.160 +					delete curves[i];
   1.161 +				}
   1.162 +				curves.clear();
   1.163 +
   1.164 +				int num = 0;
   1.165 +				std::list<Curve*>::iterator it = clist.begin();
   1.166 +				while(it != clist.end()) {
   1.167 +					curves.push_back(*it++);
   1.168 +					++num;
   1.169 +				}
   1.170 +				printf("imported %d curves\n", num);
   1.171  			}
   1.172 +			post_redisplay();
   1.173  			break;
   1.174  		}
   1.175  	}
   1.176 @@ -335,7 +390,7 @@
   1.177  		int pidx = curves[i]->nearest_point(pos);
   1.178  		if(pidx == -1) continue;
   1.179  
   1.180 -		Vector2 cp = curves[i]->get_point(pidx);
   1.181 +		Vector2 cp = curves[i]->get_point2(pidx);
   1.182  		if((cp - pos).length_sq() < thres * thres) {
   1.183  			*curveret = curves[i];
   1.184  			*pidxret = pidx;
   1.185 @@ -347,6 +402,28 @@
   1.186  	return false;
   1.187  }
   1.188  
   1.189 +static bool hit_test(const Vector2 &pos, Curve **curveret, int *pidxret)
   1.190 +{
   1.191 +	float thres = 0.02 / view_scale;
   1.192 +
   1.193 +	if(point_hit_test(pos, curveret, pidxret)) {
   1.194 +		return true;
   1.195 +	}
   1.196 +
   1.197 +	Vector3 pos3 = Vector3(pos.x, pos.y, 0.0f);
   1.198 +	for(size_t i=0; i<curves.size(); i++) {
   1.199 +		float x;
   1.200 +		if((x = curves[i]->distance_sq(pos3)) < thres * thres) {
   1.201 +			*curveret = curves[i];
   1.202 +			*pidxret = -1;
   1.203 +			return true;
   1.204 +		}
   1.205 +	}
   1.206 +	*curveret = 0;
   1.207 +	*pidxret = -1;
   1.208 +	return false;
   1.209 +}
   1.210 +
   1.211  static Vector2 snap(const Vector2 &p)
   1.212  {
   1.213  	switch(snap_mode) {
   1.214 @@ -407,10 +484,8 @@
   1.215  	if(!dx && !dy) return;
   1.216  
   1.217  	Vector2 uv = pixel_to_uv(x, y);
   1.218 -#ifdef DRAW_MOUSE_POINTER
   1.219  	mouse_pointer = uv;
   1.220 -	post_redisplay();
   1.221 -#endif
   1.222 +	//post_redisplay();
   1.223  
   1.224  	/* when entering a new curve, have the last (extra) point following
   1.225  	 * the mouse until it's entered by a click (see on_click).
   1.226 @@ -422,7 +497,10 @@
   1.227  
   1.228  	if(!new_curve && !bnstate) {
   1.229  		// not dragging, highlight curve under mouse
   1.230 -		point_hit_test(uv, &hover_curve, &sel_pidx);
   1.231 +		hit_test(uv, &hover_curve, &hover_pidx);
   1.232 +		if(hover_curve == sel_curve) {
   1.233 +			sel_pidx = hover_pidx;
   1.234 +		}
   1.235  		post_redisplay();
   1.236  
   1.237  	} else {
   1.238 @@ -482,6 +560,7 @@
   1.239  		if(hover_curve) {
   1.240  			// if we're hovering: click selects
   1.241  			sel_curve = hover_curve;
   1.242 +			sel_pidx = hover_pidx;
   1.243  			hover_curve = 0;
   1.244  		} else if(sel_curve) {
   1.245  			// if we have a selected curve: click adds point (enter new_curve mode)
   1.246 @@ -520,9 +599,11 @@
   1.247  			// in selected curve mode: delete control point or unselect
   1.248  			Curve *hit_curve;
   1.249  			int hit_pidx;
   1.250 -			if(point_hit_test(uv, &hit_curve, &hit_pidx) && hit_curve == sel_curve) {
   1.251 -				hit_curve->remove_point(hit_pidx);
   1.252 -				sel_pidx = -1;
   1.253 +			if(hit_test(uv, &hit_curve, &hit_pidx) && hit_curve == sel_curve) {
   1.254 +				if(hit_pidx != -1) {
   1.255 +					hit_curve->remove_point(hit_pidx);
   1.256 +					sel_pidx = -1;
   1.257 +				}
   1.258  			} else {
   1.259  				sel_curve = 0;
   1.260  				sel_pidx = -1;