curvedraw
changeset 0:8e524989c904
getting there
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Tue, 15 Dec 2015 07:15:53 +0200 |
parents | |
children | 7dcd0f6113e5 |
files | .hgignore Makefile src/app.cc src/app.h src/curve.cc src/curve.h src/main.cc src/opengl.h src/widgets.cc src/widgets.h |
diffstat | 10 files changed, 737 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/.hgignore Tue Dec 15 07:15:53 2015 +0200 1.3 @@ -0,0 +1,4 @@ 1.4 +\.o$ 1.5 +\.d$ 1.6 +\.swp$ 1.7 +^curvedraw$
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/Makefile Tue Dec 15 07:15:53 2015 +0200 2.3 @@ -0,0 +1,45 @@ 2.4 +PREFIX = /usr/local 2.5 + 2.6 +src = $(wildcard src/*.cc) 2.7 +obj = $(src:.cc=.o) 2.8 +dep = $(obj:.o=.d) 2.9 +bin = curvedraw 2.10 + 2.11 +CXXFLAGS = -pedantic -Wall -g 2.12 +LDFLAGS = $(libgl) -lvmath -ldrawtext -lm 2.13 + 2.14 +sys := $(shell uname -s | sed 's/MINGW.*/win32/') 2.15 + 2.16 +ifeq ($(sys), Darwin) 2.17 + libgl = -framework OpenGL -framework GLUT 2.18 +else ifeq ($(sys), win32) 2.19 + libgl = -lopengl32 -lglut32 2.20 +else 2.21 + libgl = -lGL -lglut 2.22 +endif 2.23 + 2.24 +$(bin): $(obj) 2.25 + $(CXX) -o $@ $(obj) $(LDFLAGS) 2.26 + 2.27 +-include $(dep) 2.28 + 2.29 +%.d: %.cc 2.30 + @$(CPP) $(CXXFLAGS) $< -MM -MT $(@:.d=.o) >$@ 2.31 + 2.32 + 2.33 +.PHONY: clean 2.34 +clean: 2.35 + rm -f $(obj) $(bin) 2.36 + 2.37 +.PHONY: cleandep 2.38 +cleandep: 2.39 + rm -f $(dep) 2.40 + 2.41 +.PHONY: install 2.42 +install: $(bin) 2.43 + mkdir -p $(DESTDIR)$(PREFIX)/bin 2.44 + cp $(bin) $(DESTDIR)$(PREFIX)/bin/$(bin) 2.45 + 2.46 +.PHONY: uninstall 2.47 +uninstall: 2.48 + rm -f $(DESTDIR)$(PREFIX)/bin/$(bin)
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/src/app.cc Tue Dec 15 07:15:53 2015 +0200 3.3 @@ -0,0 +1,292 @@ 3.4 +#include <stdlib.h> 3.5 +#include <float.h> 3.6 +#include <vector> 3.7 +#include <algorithm> 3.8 +#include "opengl.h" 3.9 +#include "app.h" 3.10 +#include "curve.h" 3.11 +#include "widgets.h" 3.12 + 3.13 +static void draw_grid(float sz, float sep, float alpha = 1.0f); 3.14 +static void draw_curve(const Curve *curve); 3.15 +static void on_click(int bn, float u, float v); 3.16 + 3.17 +static int win_width, win_height; 3.18 +static float win_aspect; 3.19 + 3.20 +static float view_pan_x, view_pan_y; 3.21 +static float view_scale = 1.0f; 3.22 + 3.23 +static std::vector<Curve*> curves; 3.24 +static Curve *sel_curve, *new_curve; 3.25 +static int sel_pidx = -1; 3.26 + 3.27 +static Label *weight_label; 3.28 + 3.29 + 3.30 +bool app_init(int argc, char **argv) 3.31 +{ 3.32 + glEnable(GL_MULTISAMPLE); 3.33 + glEnable(GL_CULL_FACE); 3.34 + return true; 3.35 +} 3.36 + 3.37 +void app_cleanup() 3.38 +{ 3.39 + for(size_t i=0; i<curves.size(); i++) { 3.40 + delete curves[i]; 3.41 + } 3.42 + curves.clear(); 3.43 +} 3.44 + 3.45 +void app_draw() 3.46 +{ 3.47 + glClearColor(0.16, 0.16, 0.16, 1); 3.48 + glClear(GL_COLOR_BUFFER_BIT); 3.49 + 3.50 + glMatrixMode(GL_MODELVIEW); 3.51 + glLoadIdentity(); 3.52 + glTranslatef(-view_pan_x, -view_pan_y, 0); 3.53 + glScalef(view_scale, view_scale, view_scale); 3.54 + 3.55 + draw_grid(std::max(win_aspect, 1.0f / win_aspect), 0.1); 3.56 + 3.57 + for(size_t i=0; i<curves.size(); i++) { 3.58 + draw_curve(curves[i]); 3.59 + } 3.60 + if(new_curve) { 3.61 + // TODO special drawing with more feedback 3.62 + draw_curve(new_curve); 3.63 + } 3.64 + if(weight_label) { 3.65 + weight_label->draw(); 3.66 + } 3.67 +} 3.68 + 3.69 +static void draw_grid(float sz, float sep, float alpha) 3.70 +{ 3.71 + float x = 0.0f; 3.72 + 3.73 + glLineWidth(1.0); 3.74 + glBegin(GL_LINES); 3.75 + glColor4f(0.6, 0.3, 0.2, alpha); 3.76 + glVertex2f(-sz, 0); 3.77 + glVertex2f(sz, 0); 3.78 + glColor4f(0.2, 0.3, 0.6, alpha); 3.79 + glVertex2f(0, -sz); 3.80 + glVertex2f(0, sz); 3.81 + glColor4f(0.4, 0.4, 0.4, alpha); 3.82 + while(x < sz) { 3.83 + x += sep; 3.84 + glVertex2f(-sz, x); 3.85 + glVertex2f(sz, x); 3.86 + glVertex2f(-sz, -x); 3.87 + glVertex2f(sz, -x); 3.88 + glVertex2f(x, -sz); 3.89 + glVertex2f(x, sz); 3.90 + glVertex2f(-x, -sz); 3.91 + glVertex2f(-x, sz); 3.92 + } 3.93 + glEnd(); 3.94 +} 3.95 + 3.96 +static void draw_curve(const Curve *curve) 3.97 +{ 3.98 + int numpt = curve->get_point_count(); 3.99 + int segm = numpt * 16.0f; 3.100 + 3.101 + glBegin(GL_LINE_STRIP); 3.102 + if(curve == sel_curve) { 3.103 + glLineWidth(3.0); 3.104 + glColor3f(0.2, 0.8, 0.3); 3.105 + } else { 3.106 + glLineWidth(2.0); 3.107 + glColor3f(0.8, 0.75, 0.3); 3.108 + } 3.109 + for(int i=0; i<segm; i++) { 3.110 + float t = (float)i / (float)(segm - 1); 3.111 + Vector2 v = curve->interpolate(t); 3.112 + glVertex2f(v.x, v.y); 3.113 + } 3.114 + glEnd(); 3.115 + glLineWidth(1.0); 3.116 + 3.117 + glPointSize(5.0); 3.118 + glBegin(GL_POINTS); 3.119 + glColor3f(1.0, 0.5, 0.2); 3.120 + for(int i=0; i<numpt; i++) { 3.121 + Vector2 pt = curve->get_point(i); 3.122 + glVertex2f(pt.x, pt.y); 3.123 + } 3.124 + glEnd(); 3.125 + glPointSize(1.0); 3.126 +} 3.127 + 3.128 +void app_reshape(int x, int y) 3.129 +{ 3.130 + win_width = x; 3.131 + win_height = y; 3.132 + win_aspect = (float)x / (float)y; 3.133 + 3.134 + glViewport(0, 0, x, y); 3.135 + glMatrixMode(GL_PROJECTION); 3.136 + glLoadIdentity(); 3.137 + glOrtho(-win_aspect, win_aspect, -1, 1, -1, 1); 3.138 +} 3.139 + 3.140 +void app_keyboard(int key, bool pressed) 3.141 +{ 3.142 + if(pressed) { 3.143 + switch(key) { 3.144 + case 27: 3.145 + exit(0); 3.146 + 3.147 + case 'l': 3.148 + case 'L': 3.149 + if(sel_curve) { 3.150 + sel_curve->set_type(CURVE_LINEAR); 3.151 + post_redisplay(); 3.152 + } 3.153 + break; 3.154 + 3.155 + case 'b': 3.156 + case 'B': 3.157 + if(sel_curve) { 3.158 + sel_curve->set_type(CURVE_BSPLINE); 3.159 + post_redisplay(); 3.160 + } 3.161 + break; 3.162 + 3.163 + case 'h': 3.164 + case 'H': 3.165 + if(sel_curve) { 3.166 + sel_curve->set_type(CURVE_HERMITE); 3.167 + post_redisplay(); 3.168 + } 3.169 + break; 3.170 + } 3.171 + } 3.172 +} 3.173 + 3.174 +static Vector2 pixel_to_uv(int x, int y) 3.175 +{ 3.176 + float u = win_aspect * (2.0 * (float)x / (float)win_width - 1.0); 3.177 + float v = 1.0 - 2.0 * (float)y / (float)win_height; 3.178 + return Vector2(u, v); 3.179 +} 3.180 + 3.181 +static int prev_x, prev_y; 3.182 +static int click_pos[8][2]; 3.183 +static unsigned int bnstate; 3.184 + 3.185 +#define BNBIT(x) (1 << (x)) 3.186 + 3.187 +void app_mouse_button(int bn, bool pressed, int x, int y) 3.188 +{ 3.189 + prev_x = x; 3.190 + prev_y = y; 3.191 + if(pressed) { 3.192 + bnstate |= BNBIT(bn); 3.193 + } else { 3.194 + bnstate &= ~BNBIT(bn); 3.195 + } 3.196 + 3.197 + if(pressed) { 3.198 + click_pos[bn][0] = x; 3.199 + click_pos[bn][1] = y; 3.200 + } else { 3.201 + int dx = x - click_pos[bn][0]; 3.202 + int dy = y - click_pos[bn][1]; 3.203 + 3.204 + if(abs(dx) + abs(dy) < 3) { 3.205 + Vector2 uv = pixel_to_uv(x, y); 3.206 + on_click(bn, uv.x, uv.y); 3.207 + } 3.208 + 3.209 + if(!(bnstate & BNBIT(2))) { 3.210 + delete weight_label; 3.211 + weight_label = 0; 3.212 + post_redisplay(); 3.213 + } 3.214 + } 3.215 +} 3.216 + 3.217 +static void hover(int x, int y) 3.218 +{ 3.219 + float thres = pixel_to_uv(5, 0).x - pixel_to_uv(0, 0).x; 3.220 + 3.221 + Vector2 uv = pixel_to_uv(x, y); 3.222 + for(size_t i=0; i<curves.size(); i++) { 3.223 + int pidx = curves[i]->nearest_point(uv); 3.224 + if(pidx == -1) continue; 3.225 + 3.226 + Vector2 cp = curves[i]->get_point(pidx); 3.227 + if((cp - uv).length_sq() < thres * thres) { 3.228 + sel_curve = curves[i]; 3.229 + sel_pidx = pidx; 3.230 + return; 3.231 + } 3.232 + } 3.233 + 3.234 + sel_curve = 0; 3.235 + sel_pidx = -1; 3.236 +} 3.237 + 3.238 +void app_mouse_motion(int x, int y) 3.239 +{ 3.240 + int dx = x - prev_x; 3.241 + int dy = y - prev_y; 3.242 + prev_x = x; 3.243 + prev_y = y; 3.244 + 3.245 + if(!dx && !dy) return; 3.246 + 3.247 + if(!new_curve && !bnstate) { 3.248 + hover(x, y); 3.249 + post_redisplay(); 3.250 + } 3.251 + 3.252 + if(sel_curve && sel_pidx != -1) { 3.253 + if(bnstate & BNBIT(0)) { 3.254 + float w = sel_curve->get_weight(sel_pidx); 3.255 + sel_curve->set_point(sel_pidx, pixel_to_uv(x, y), w); 3.256 + post_redisplay(); 3.257 + } 3.258 + 3.259 + if(bnstate & BNBIT(2)) { 3.260 + float w = sel_curve->get_weight(sel_pidx); 3.261 + w -= dy * 0.1; 3.262 + if(w < FLT_MIN) w = FLT_MIN; 3.263 + sel_curve->set_weight(sel_pidx, w); 3.264 + 3.265 + if(!weight_label) { 3.266 + weight_label = new Label; 3.267 + } 3.268 + weight_label->set_position(pixel_to_uv(x, y)); 3.269 + weight_label->set_textf("w=%g", w); 3.270 + post_redisplay(); 3.271 + } 3.272 + } 3.273 +} 3.274 + 3.275 +static void on_click(int bn, float u, float v) 3.276 +{ 3.277 + switch(bn) { 3.278 + case 0: 3.279 + if(!new_curve) { 3.280 + new_curve = new Curve; 3.281 + } 3.282 + new_curve->add_point(Vector2(u, v)); 3.283 + post_redisplay(); 3.284 + break; 3.285 + 3.286 + case 2: 3.287 + curves.push_back(new_curve); 3.288 + new_curve = 0; 3.289 + post_redisplay(); 3.290 + break; 3.291 + 3.292 + default: 3.293 + break; 3.294 + } 3.295 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/src/app.h Tue Dec 15 07:15:53 2015 +0200 4.3 @@ -0,0 +1,15 @@ 4.4 +#ifndef APP_H_ 4.5 +#define APP_H_ 4.6 + 4.7 +bool app_init(int argc, char **argv); 4.8 +void app_cleanup(); 4.9 + 4.10 +void app_draw(); 4.11 +void app_reshape(int x, int y); 4.12 +void app_keyboard(int key, bool pressed); 4.13 +void app_mouse_button(int bn, bool pressed, int x, int y); 4.14 +void app_mouse_motion(int x, int y); 4.15 + 4.16 +void post_redisplay(); // in main.cc 4.17 + 4.18 +#endif // APP_H_
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/src/curve.cc Tue Dec 15 07:15:53 2015 +0200 5.3 @@ -0,0 +1,144 @@ 5.4 +#include <float.h> 5.5 +#include "curve.h" 5.6 + 5.7 +Curve::Curve(CurveType type) 5.8 +{ 5.9 + this->type = type; 5.10 +} 5.11 + 5.12 +void Curve::set_type(CurveType type) 5.13 +{ 5.14 + this->type = type; 5.15 +} 5.16 + 5.17 +CurveType Curve::get_type() const 5.18 +{ 5.19 + return type; 5.20 +} 5.21 + 5.22 +void Curve::add_point(const Vector2 &p, float weight) 5.23 +{ 5.24 + cp.push_back(Vector3(p.x, p.y, weight)); 5.25 +} 5.26 + 5.27 +bool Curve::remove_point(int idx) 5.28 +{ 5.29 + if(idx < 0 || idx >= (int)cp.size()) { 5.30 + return false; 5.31 + } 5.32 + cp.erase(cp.begin() + idx); 5.33 + return true; 5.34 +} 5.35 + 5.36 +int Curve::nearest_point(const Vector2 &p) 5.37 +{ 5.38 + int res = -1; 5.39 + float bestsq = FLT_MAX; 5.40 + 5.41 + for(size_t i=0; i<cp.size(); i++) { 5.42 + float d = (get_point(i) - p).length_sq(); 5.43 + if(d < bestsq) { 5.44 + bestsq = d; 5.45 + res = i; 5.46 + } 5.47 + } 5.48 + 5.49 + return res; 5.50 +} 5.51 + 5.52 +int Curve::get_point_count() const 5.53 +{ 5.54 + return (int)cp.size(); 5.55 +} 5.56 + 5.57 +const Vector3 &Curve::get_homo_point(int idx) const 5.58 +{ 5.59 + return cp[idx]; 5.60 +} 5.61 + 5.62 +Vector2 Curve::get_point(int idx) const 5.63 +{ 5.64 + return Vector2(cp[idx].x, cp[idx].y); 5.65 +} 5.66 + 5.67 +float Curve::get_weight(int idx) const 5.68 +{ 5.69 + return cp[idx].z; 5.70 +} 5.71 + 5.72 +bool Curve::set_point(int idx, const Vector2 &p, float weight) 5.73 +{ 5.74 + if(idx < 0 || idx >= (int)cp.size()) { 5.75 + return false; 5.76 + } 5.77 + cp[idx] = Vector3(p.x, p.y, weight); 5.78 + return true; 5.79 +} 5.80 + 5.81 +bool Curve::set_weight(int idx, float weight) 5.82 +{ 5.83 + if(idx < 0 || idx >= (int)cp.size()) { 5.84 + return false; 5.85 + } 5.86 + cp[idx].z = weight; 5.87 + return true; 5.88 +} 5.89 + 5.90 +Vector2 Curve::interpolate(float t, CurveType type) const 5.91 +{ 5.92 + int num_cp = (int)cp.size(); 5.93 + if(!num_cp) { 5.94 + return Vector2(0, 0); 5.95 + } 5.96 + if(num_cp == 1) { 5.97 + return Vector2(cp[0].x, cp[0].y); 5.98 + } 5.99 + 5.100 + Vector3 res; 5.101 + int idx0 = (int)floor(t * (num_cp - 1)); 5.102 + int idx1 = idx0 + 1; 5.103 + 5.104 + float dt = 1.0 / (float)(num_cp - 1); 5.105 + float t0 = (float)idx0 * dt; 5.106 + float t1 = (float)idx1 * dt; 5.107 + 5.108 + t = (t - t0) / (t1 - t0); 5.109 + if(t < 0.0) t = 0.0; 5.110 + if(t > 1.0) t = 1.0; 5.111 + 5.112 + if(type == CURVE_LINEAR || num_cp <= 2) { 5.113 + res = lerp(cp[idx0], cp[idx1], t); 5.114 + } else { 5.115 + int idx_prev = idx0 <= 0 ? idx0 : idx0 - 1; 5.116 + int idx_next = idx1 >= num_cp - 1 ? idx1 : idx1 + 1; 5.117 + 5.118 + if(type == CURVE_HERMITE) { 5.119 + res = catmull_rom_spline(cp[idx_prev], cp[idx0], cp[idx1], cp[idx_next], t); 5.120 + } else { 5.121 + res = bspline(cp[idx_prev], cp[idx0], cp[idx1], cp[idx_next], t); 5.122 + if(res.z != 0.0f) { 5.123 + res.x /= res.z; 5.124 + res.y /= res.z; 5.125 + } 5.126 + } 5.127 + } 5.128 + 5.129 + return Vector2(res.x, res.y); 5.130 +} 5.131 + 5.132 +Vector2 Curve::interpolate(float t) const 5.133 +{ 5.134 + return interpolate(t, type); 5.135 +} 5.136 + 5.137 +Vector2 Curve::operator ()(float t) const 5.138 +{ 5.139 + return interpolate(t); 5.140 +} 5.141 + 5.142 +float Curve::map_param(float x) const 5.143 +{ 5.144 + if(x < 0.0f) x = 0.0f; 5.145 + if(x >= 1.0f) x = 1.0f; 5.146 + return x * ((float)cp.size() - 1); 5.147 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/src/curve.h Tue Dec 15 07:15:53 2015 +0200 6.3 @@ -0,0 +1,44 @@ 6.4 +#ifndef CURVE_H_ 6.5 +#define CURVE_H_ 6.6 + 6.7 +#include <vector> 6.8 +#include <vmath/vmath.h> 6.9 + 6.10 +enum CurveType { 6.11 + CURVE_LINEAR, 6.12 + CURVE_HERMITE, 6.13 + CURVE_BSPLINE 6.14 +}; 6.15 + 6.16 +class Curve { 6.17 +private: 6.18 + std::vector<Vector3> cp; 6.19 + CurveType type; 6.20 + 6.21 + float map_param(float x) const; 6.22 + 6.23 +public: 6.24 + Curve(CurveType type = CURVE_HERMITE); 6.25 + 6.26 + void set_type(CurveType type); 6.27 + CurveType get_type() const; 6.28 + 6.29 + void add_point(const Vector2 &p, float weight = 1.0f); 6.30 + bool remove_point(int idx); 6.31 + 6.32 + int nearest_point(const Vector2 &p); 6.33 + 6.34 + int get_point_count() const; 6.35 + const Vector3 &get_homo_point(int idx) const; // homogeneous point 6.36 + Vector2 get_point(int idx) const; 6.37 + float get_weight(int idx) const; 6.38 + 6.39 + bool set_point(int idx, const Vector2 &p, float weight = 1.0f); 6.40 + bool set_weight(int idx, float weight); 6.41 + 6.42 + Vector2 interpolate(float t, CurveType type) const; 6.43 + Vector2 interpolate(float t) const; 6.44 + Vector2 operator ()(float t) const; 6.45 +}; 6.46 + 6.47 +#endif // CURVE_H_
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/src/main.cc Tue Dec 15 07:15:53 2015 +0200 7.3 @@ -0,0 +1,68 @@ 7.4 +#include <stdio.h> 7.5 +#include <stdlib.h> 7.6 +#ifdef __APPLE__ 7.7 +#include <GLUT/glut.h> 7.8 +#else 7.9 +#include <GL/glut.h> 7.10 +#endif 7.11 +#include "app.h" 7.12 + 7.13 +static void display(); 7.14 +static void keydown(unsigned char key, int x, int y); 7.15 +static void keyup(unsigned char key, int x, int y); 7.16 +static void mouse(int bn, int st, int x, int y); 7.17 + 7.18 +int main(int argc, char **argv) 7.19 +{ 7.20 + glutInit(&argc, argv); 7.21 + glutInitWindowSize(1280, 720); 7.22 + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_MULTISAMPLE); 7.23 + glutCreateWindow("Curve Draw"); 7.24 + 7.25 + glutDisplayFunc(display); 7.26 + glutReshapeFunc(app_reshape); 7.27 + glutKeyboardFunc(keydown); 7.28 + glutKeyboardUpFunc(keyup); 7.29 + glutMouseFunc(mouse); 7.30 + glutMotionFunc(app_mouse_motion); 7.31 + glutPassiveMotionFunc(app_mouse_motion); 7.32 + 7.33 + if(!app_init(argc, argv)) { 7.34 + return 1; 7.35 + } 7.36 + atexit(app_cleanup); 7.37 + 7.38 + glutMainLoop(); 7.39 + return 0; 7.40 +} 7.41 + 7.42 +void post_redisplay() 7.43 +{ 7.44 + glutPostRedisplay(); 7.45 +} 7.46 + 7.47 +static void display() 7.48 +{ 7.49 + app_draw(); 7.50 + glutSwapBuffers(); 7.51 +} 7.52 + 7.53 +static void reshape(int x, int y) 7.54 +{ 7.55 + app_reshape(x, y); 7.56 +} 7.57 + 7.58 +static void keydown(unsigned char key, int x, int y) 7.59 +{ 7.60 + app_keyboard(key, true); 7.61 +} 7.62 + 7.63 +static void keyup(unsigned char key, int x, int y) 7.64 +{ 7.65 + app_keyboard(key, false); 7.66 +} 7.67 + 7.68 +static void mouse(int bn, int st, int x, int y) 7.69 +{ 7.70 + app_mouse_button(bn - GLUT_LEFT_BUTTON, st == GLUT_DOWN, x, y); 7.71 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/src/opengl.h Tue Dec 15 07:15:53 2015 +0200 8.3 @@ -0,0 +1,14 @@ 8.4 +#ifndef OPENGL_H_ 8.5 +#define OPENGL_H_ 8.6 + 8.7 +#ifdef WIN32 8.8 +#include <windows.h> 8.9 +#endif 8.10 + 8.11 +#ifdef __APPLE__ 8.12 +#include <OpenGL/gl.h> 8.13 +#else 8.14 +#include <GL/gl.h> 8.15 +#endif 8.16 + 8.17 +#endif // OPENGL_H_
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/src/widgets.cc Tue Dec 15 07:15:53 2015 +0200 9.3 @@ -0,0 +1,81 @@ 9.4 +#include <stdio.h> 9.5 +#include <stdlib.h> 9.6 +#include <string.h> 9.7 +#include <stdarg.h> 9.8 +#include <drawtext.h> 9.9 +#include "opengl.h" 9.10 +#include "widgets.h" 9.11 + 9.12 +static dtx_font *font; 9.13 + 9.14 +static void init_font() 9.15 +{ 9.16 + if(font) return; 9.17 + 9.18 + if(!(font = dtx_open_font("data/droid_sans.ttf", 16))) { 9.19 + fprintf(stderr, "failed to load font\n"); 9.20 + abort(); 9.21 + } 9.22 + dtx_use_font(font, 16); 9.23 +} 9.24 + 9.25 +Widget::Widget() 9.26 +{ 9.27 + text = 0; 9.28 +} 9.29 + 9.30 +Widget::~Widget() 9.31 +{ 9.32 + delete [] text; 9.33 +} 9.34 + 9.35 +void Widget::set_position(const Vector2 &p) 9.36 +{ 9.37 + pos = p; 9.38 +} 9.39 + 9.40 +const Vector2 &Widget::get_position() const 9.41 +{ 9.42 + return pos; 9.43 +} 9.44 + 9.45 +void Widget::set_text(const char *str) 9.46 +{ 9.47 + text = new char[strlen(str) + 1]; 9.48 + strcpy(text, str); 9.49 +} 9.50 + 9.51 +void Widget::set_textf(const char *str, ...) 9.52 +{ 9.53 + va_list ap; 9.54 + int sz = strlen(str) * 4; 9.55 + char *buf = (char*)alloca(sz); 9.56 + 9.57 + va_start(ap, str); 9.58 + vsnprintf(buf, sz - 1, text, ap); 9.59 + va_end(ap); 9.60 + 9.61 + set_text(buf); 9.62 +} 9.63 + 9.64 +const char *Widget::get_text() const 9.65 +{ 9.66 + return text; 9.67 +} 9.68 + 9.69 +// ---- label ---- 9.70 + 9.71 +void Label::draw() const 9.72 +{ 9.73 + init_font(); 9.74 + 9.75 + glMatrixMode(GL_MODELVIEW); 9.76 + glPushMatrix(); 9.77 + glTranslatef(pos.x, pos.y, 0); 9.78 + glScalef(0.1, 0.1, 1); 9.79 + 9.80 + dtx_string(text); 9.81 + dtx_flush(); 9.82 + 9.83 + glPopMatrix(); 9.84 +}
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/src/widgets.h Tue Dec 15 07:15:53 2015 +0200 10.3 @@ -0,0 +1,30 @@ 10.4 +#ifndef WIDGETS_H_ 10.5 +#define WIDGETS_H_ 10.6 + 10.7 +#include <vmath/vmath.h> 10.8 + 10.9 +class Widget { 10.10 +protected: 10.11 + Vector2 pos; 10.12 + char *text; 10.13 + 10.14 +public: 10.15 + Widget(); 10.16 + virtual ~Widget(); 10.17 + 10.18 + virtual void set_position(const Vector2 &p); 10.19 + virtual const Vector2 &get_position() const; 10.20 + 10.21 + virtual void set_text(const char *str); 10.22 + virtual void set_textf(const char *str, ...); 10.23 + virtual const char *get_text() const; 10.24 + 10.25 + virtual void draw() const = 0; 10.26 +}; 10.27 + 10.28 +class Label : public Widget { 10.29 +public: 10.30 + virtual void draw() const; 10.31 +}; 10.32 + 10.33 +#endif // WIDGETS_H_