// minimal project 2 phase 1 // // Written by Mike Gleicher, while on a plane from MKE to EWR // this was written as fast as possible, and designed to be // as simple as possible but still meet the minimal requirements // // Changed by Yoh Suzuki to use the mouse // // do not look at this for an example of good code! // its just to see how quickly i could through together an // answer to the project #include #include #include #include #include #include // the FlTk headers have lots of warnings - these are bad, but there's not // much we can do about them #pragma warning(push) #pragma warning(disable:4311) // convert void* to long #pragma warning(disable:4312) // convert long to void* #include #include #include #include #include #pragma comment (lib, "opengl32.lib") #pragma comment (lib, "glut32.lib") #pragma comment (lib, "glu32.lib") #pragma warning(pop) // i'll just keep everything as global variables, and use STL (not objects) // again, this is for simplicity, not for "best practices" std::vector< std::pair > points; size_t selected=0; bool running = false; bool dragging = false; int mousedownx, mousedowny; // i'm putting the sliders here where Simple2D can see them Fl_Value_Slider* xslider; Fl_Value_Slider* yslider; void setslidersfromselectedpoint() { if (selected < points.size()) { xslider->value(points[selected].first); yslider->value(points[selected].second); } } void setselectedpointfromsliders() { if (selected < points.size()) { points[selected].first = (float)xslider->value(); points[selected].second = (float)yslider->value(); } } // we need to make our own version of a window so we can redefine draw and handle class Simple2D : public Fl_Gl_Window { public: Simple2D() : Fl_Gl_Window(0,0,600,600,"Simple2D"), angle(0){} float angle; private: // draw each point. if its selected, draw it in red void drawpoint(size_t which) { if (selected == which) glColor3f(1.0f,0,0); else glColor3f(1.0,1.0,1.0); glRectf(points[which].first-20,points[which].second-20,points[which].first+20,points[which].second+20); } // draw the squares - this assumes that the window is 500x500 // and doesn't change (not a good thing to assume, but again, for // simplicity) void draw() { glClearColor(0,0,0,0); glClear(GL_COLOR_BUFFER_BIT); glLoadIdentity(); // in practice, we should set up the coordinate system based on the actual // window size glOrtho(0,600,0,600,-1,1); // draw each point for(size_t i=0; i0) { //printf("Mouse at (%d,%d) hit object number %d!\n",x,y,buf[3]-1); selected = buf[3]-1; setslidersfromselectedpoint(); if( Fl::event_button() == 3 ) { if(points.size()>1 && selected < points.size()) { points.erase(points.begin()+selected); selected = (selected) % points.size(); setslidersfromselectedpoint(); } } else { dragging = true; } } else { // otherwise add a new point under the mouse dragging = false; points.push_back(std::pair((float)x,(float)y)); selected = points.size()-1; setslidersfromselectedpoint(); } // get everything ready to draw normally again glViewport(0,0,600,600); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-1,1,-1,1,-1.0f,1.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); damage(1); return 1; break; case FL_KEYDOWN: { int c = Fl::event_key(); switch(c) { case 'd': // delete the selected square (if there's more than 1 left) if(points.size()>1 && selected < points.size()) { points.erase(points.begin()+selected); selected = (selected) % points.size(); setslidersfromselectedpoint(); } break; case 'n': // select the next square selected = (selected + 1) % points.size(); setslidersfromselectedpoint(); break; case 'a': // add a new square (at the center) points.push_back(std::pair(300,300)); selected = points.size()-1; setslidersfromselectedpoint(); break; case FL_Right: // move selected to the right if (selected < points.size()) points[selected].first += 10; setslidersfromselectedpoint(); break; case FL_Left: // move selected to the left if (selected < points.size()) points[selected].first -= 10; setslidersfromselectedpoint(); break; case FL_Up: // move selected up if (selected < points.size()) points[selected].second += 10; setslidersfromselectedpoint(); break; case FL_Down: // move selected down if (selected < points.size()) points[selected].second -= 10; setslidersfromselectedpoint(); break; case 's': // switch the running state running = !running; break; default: // any other key? pass along to the parent return Fl_Gl_Window::handle(e); }; }; damage(1); return 1; default: // we only handle keypresses - send everything else to the parent return Fl_Gl_Window::handle(e); }; return 1; }; }; Simple2D* theWindow; Fl_Double_Window* wind; // idle call back - assume the parameter is a Simple2D (window) // advance the angle if we're running void idleCB(void* w) { if (running) { ((Simple2D*)w)->angle += 5; ((Simple2D*)w)->damage(1); } } // button callbacks void Select_Next_Callback(Fl_Widget *w) { selected = (selected + 1) % points.size(); setslidersfromselectedpoint(); theWindow->damage(1); } void Add_Callack(Fl_Widget *w) { points.push_back(std::pair(300,300)); selected = points.size()-1; setslidersfromselectedpoint(); theWindow->damage(1); } void Animate_Callack(Fl_Widget *w) { running = !running; } void Remove_Callack(Fl_Widget *w) { if(points.size()>1 && selected < points.size()) { points.erase(points.begin()+selected); selected = (selected) % points.size(); setslidersfromselectedpoint(); theWindow->damage(1); } } // slider callback void Slider_Callback(Fl_Widget *w) { setselectedpointfromsliders(); theWindow->damage(1); } // main - set up the window and let FlTk do its thing int main(int, char**) { points.push_back(std::pair(200,200)); points.push_back(std::pair(500,500)); wind = new Fl_Double_Window(100,100,600,775,"Simple 2D - Using FLTK Buttons and Scrollbars, and the Mouse!"); wind->begin(); theWindow = new Simple2D(); Fl_Button* select_next = new Fl_Button(10, 610, 110, 35, "Select Next"); select_next->callback(Select_Next_Callback); Fl_Button* add = new Fl_Button(10, 650, 110, 35, "Add"); add->callback(Add_Callack); Fl_Button* animate = new Fl_Button(10, 690, 110, 35, "Animate"); animate->callback(Animate_Callack); Fl_Button* remove = new Fl_Button(10, 730, 110, 35, "Remove"); remove->callback(Remove_Callack); xslider = new Fl_Value_Slider(180, 650, 370, 35); xslider->type(FL_HOR_SLIDER); xslider->bounds(0, 599); xslider->value(0); xslider->callback(Slider_Callback); xslider->show(); yslider = new Fl_Value_Slider(180, 690, 370, 35); yslider->type(FL_HOR_SLIDER); yslider->bounds(0, 599); yslider->value(0); yslider->callback(Slider_Callback); yslider->show(); setslidersfromselectedpoint(); wind->end(); wind->show(); Fl::add_idle(idleCB,&(*theWindow)); Fl::run(); }