// NOTE: To run, it is recommended not to be in Compiz or Beryl, they have shown some instability. // Needs: libwxgtk2.8-dev // g++ main.cpp -o run `wx-config --libs --cxxflags --gl-libs` #include #include #include #include #include #ifndef WIN32 #include // FIXME: ¿This work/necessary in Windows? //Not necessary, but if it was, it needs to be replaced by process.h AND io.h #endif typedef enum { LINES = 0, POLYGON = 1 } Style; /* * Left: place point * Right: remove previous point * Middle: invisible line. (no line) */ class Point { public: Point(float x, float y) { this->x = x; this->y = y; } float x; float y; }; class PolyLine { public: void addPoint(Point point); void removeLastPoint(); void clear(); void draw(); unsigned int size(); void setStyle(Style style); private: std::vector points; Style style; }; void PolyLine::setStyle(Style style) { this->style = style; } unsigned int PolyLine::size() { return points.size(); } void PolyLine::addPoint(Point point) { points.push_back(point); } void PolyLine::removeLastPoint() { if (points.size() >= 1) points.erase(points.end()); } void PolyLine::clear() { points.clear(); } void PolyLine::draw() { std::vector::const_iterator iter; glPushMatrix (); if (style == LINES) glBegin (GL_LINE_STRIP); else if (style == POLYGON) glBegin (GL_POLYGON); for (iter = points.begin(); iter != points.end(); iter++) glVertex3f ((*iter).x, (*iter).y, 0.0f); glEnd (); glPopMatrix (); } class Manager { public: void addPoint(Point point); void addPolyLine(Point point); void removeLastPoint(); void draw(); void clear(); void setStyle(Style style); private: std::vector lines; unsigned int current; Style style; }; void Manager::setStyle(Style style) { this->style = style; } void Manager::addPoint(Point point) { if (lines.size() == 0) { lines.push_back(PolyLine()); current = 0; } lines[current].addPoint(point); } void Manager::addPolyLine(Point point) { lines.push_back(PolyLine()); current++; lines[current].addPoint(point); } void Manager::removeLastPoint() { // TODO: return bool if (lines.size() > 0) { if (lines[current].size() == 0) if (current == 0) lines.clear(); else { lines.erase(lines.end()); current--; } else lines[current].removeLastPoint(); } } void Manager::draw() { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glDisable (GL_TEXTURE_2D); glEnable(GL_LINE_SMOOTH); glLineWidth(3.0f); glDisable (GL_LIGHTING); glColor3f (0.2f, 1.0f, 0.2f); std::vector::iterator iter; for (iter = lines.begin(); iter != lines.end(); iter++) { (*iter).setStyle(style); (*iter).draw(); } } void Manager::clear() { lines.clear(); } void draw_marquee(float x, float y) { const int length = 30; const int distance = 10; glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glDisable (GL_TEXTURE_2D); glEnable(GL_LINE_SMOOTH); glLineWidth(3.0f); glDisable (GL_LIGHTING); glColor3f (1.0f, 0.0f, 0.0f); glBegin(GL_LINES); glVertex3f(x - (length + distance), y, 0.0f); glVertex3f(x - distance, y, 0.0f); glEnd(); glBegin(GL_LINES); glVertex3f(x + (length + distance), y, 0.0f); glVertex3f(x + distance, y, 0.0f); glEnd(); glBegin(GL_LINES); glVertex3f(x, y - (length + distance), 0.0f); glVertex3f(x, y - distance, 0.0f); glEnd(); glBegin(GL_LINES); glVertex3f(x, y + (length + distance), 0.0f); glVertex3f(x, y + distance, 0.0f); glEnd(); } class MyCanvas: public wxGLCanvas { void Render(); public: MyCanvas(wxFrame* parent); void Paintit(wxPaintEvent& event); protected: DECLARE_EVENT_TABLE() private: void OnMouseEvent (wxMouseEvent& event); void setup_polyline (); Manager manager; float mousex; float mousey; }; BEGIN_EVENT_TABLE(MyCanvas, wxGLCanvas) EVT_PAINT (MyCanvas::Paintit) EVT_MOUSE_EVENTS(MyCanvas::OnMouseEvent) END_EVENT_TABLE() MyCanvas::MyCanvas(wxFrame *parent) :wxGLCanvas(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, wxT("GLCanvas")) { int argc = 1; char* argv[1] = { wxString((wxTheApp->argv)[0]).char_str() }; } void MyCanvas::Paintit(wxPaintEvent& WXUNUSED(event)) { Render(); } void MyCanvas::OnMouseEvent(wxMouseEvent& event) { //printf("x=%d y=%d LeftIsDown=%d\n", event.GetX(), event.GetY(), (int) event.LeftIsDown()); bool should_render = false; Point point = Point(mousex, mousey); mousex = (float) event.GetX(); mousey = (float) event.GetY(); should_render = true; if (event.LeftIsDown()) { manager.addPoint(point); should_render = true; } else if (event.RightIsDown()) { // FIXME manager.removeLastPoint(); manager.removeLastPoint(); should_render = true; } else if (event.MiddleIsDown()) { manager.addPolyLine(point); should_render = true; manager.setStyle(POLYGON); } else { manager.removeLastPoint(); manager.addPoint(point); should_render = true; } if (should_render) Render(); } void MyCanvas::setup_polyline() { manager.clear(); } void MyCanvas::Render() { static bool polyline_is_set = false; SetCurrent(); wxPaintDC(this); if (! polyline_is_set) { setup_polyline(); polyline_is_set = true; } glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); glViewport(0, 0, (GLint) GetSize().x, (GLint) GetSize().y); glMatrixMode (GL_PROJECTION); glLoadIdentity (); glOrtho ( 0.0f, (float) GetSize().x, // left, right (float) GetSize().y, 0.0f, // bottom, top -1.0, 1.0f); glMatrixMode (GL_MODELVIEW); glLoadIdentity (); // FIXME? is this needed here? manager.draw(); draw_marquee(mousex, mousey); glFlush(); SwapBuffers(); } class MyApp: public wxApp { private: virtual bool OnInit(); MyCanvas * MyGLCanvas; }; IMPLEMENT_APP(MyApp) bool MyApp::OnInit() { wxFrame *frame = new wxFrame((wxFrame *) NULL, -1, wxT("LibreMapping - PolyLine Prototype"), wxPoint(50, 50), wxSize(640, 480)); //frame->SetWindowStyle(wxWANTS_CHARS); MyGLCanvas = new MyCanvas(frame); frame->Show(TRUE); return TRUE; }