210 likes | 435 Views
FLUID. The Fast Light User Interface Designer, or FLUID, is a graphical editor that is used to produce FLTK source code Creates C++ code Compile . fl file into .cxx and . h Located in fltk -source/fluid/fluidd.exe We will create the CustomWidget using fluid. Timers.
E N D
FLUID • The Fast Light User Interface Designer, or FLUID, is a graphical editor that is used to produce FLTK source code • Creates C++ code • Compile .fl file into .cxx and .h • Located in fltk-source/fluid/fluidd.exe • We will create the CustomWidget using fluid
Timers • Not 100% accurate (don't measure time with them) • Single shot timeouts • void add_timeout(double t, Fl_Timeout_Handler, void* d) • call a function in t seconds • void remove_timeout(Fl_Timeout_Handler, void* d) • cancels a timeout (harmless if timer already triggered) • void repeat_timeout(double t, Fl_Timeout_Handler, void* d) • call a function t seconds after the last timeout triggered • can only be called from within a timer callback
Simple Timer Print "TICK" every second void callback(void*) { printf(“TICK\n"); Fl::repeat_timeout(1.0, callback); } int main() { …… Fl::add_timeout(1.0, callback); return Fl::run() }
Add Timer to Move CustomWidget Goal: Have slider slide back and forth • Use globals for all variables and widgets • Make customWidget global • Add variable to control direction • Callback • Setup repeat timer • Move widget in specified direction • Check if we have reached max or min and change direction • Main • Set initial direction • Initial timer call
int increasing; CustomWidget *customWidget; void timer(void*) { Fl::repeat_timeout(0.02, timer); if ( increasing ) { customWidget->value(customWidget->value() + 1); if ( customWidget->value() >= customWidget->maximum() ) increasing = 0; } else { customWidget->value(customWidget->value() - 1); if ( customWidget->value() <= customWidget->minimum() ) increasing = 1; } }
Idle • Similar to GLUT • add_idle(void (*cb)(void*), void *) • function to call whenever nothing else is happening • can have multiple callbacks • remove_timout(void (*cb)(void*), void *) • removes callback function if it exists
OpenGL Widget • Create a subclass of Fl_Gl_Window • #include <FL/Fl_Gl_Window.H> • #include <FL/gl.h> • Will include <GL/gl.h> • Need to implement draw function in subclass • Setup view port • valid() will return false if needed • Actual drawing
OpenGL Widget class OpenGLWindow : public Fl_Gl_Window {private: void draw() { if ( !valid() ) { // initialization } // draw };public:OpenGLWindow(int x, int y, int w, int h, const char* l = 0) : Fl_Gl_Window(x, y, w, h, l) { }; };
3D Gasket in FLTK • Put all code into subclass of Fl_Gl_Window • Copy triangle, tetra, and divide_tetra functions • Move colors into tetra and v into draw • All reference to width are height need to be replaced with w() and h() • Hard code number of sub divisions • Create a window and place OpenGL widget in it
Widget to Control Sub Divisions • OpenGL draw() now get value from slider widget • divide_tetra(v[0], v[1], v[2], v[3], • divisions->value()); • Add a slider (and label) for number of sub divisions divisions = new Fl_Slider(100, 480, 540,20); divisions->type(FL_HORIZONTAL); divisions->range(1, 20); divisions->step(1);
Need to tell FLTK/OpenGL Widget to update • call widget's redraw() • Need to redraw when we change slider (callback) void update(Fl_Widget*, void*){glwindow->redraw();} // when creating slider divisions->callback(update);
Assignment 1 Part 3 in FLTK • Will use toggle button instead of mouse clicks • Timer instead of idle • Create toggle button and start timer • spinning = new Fl_Button(545, 485, 90, 20, • "Spinning"); • spinning->type(FL_TOGGLE_BUTTON); • Fl::add_timeout(1, timer, 0); • spin = 0.0f;
Update spin and redraw if necessary void timer(void*){Fl::repeat_timeout(0.02, timer); if ( spinning->value() ) { spin += 1.0f; if ( spin > 360.0f ) spin -= 360.0f;glwindow->redraw(); }}
Events • Implement int handle(int event) • event is mouse click & drag, mouse wheel, keyboard presses & release, system events • Return 1 if event is used • Event consumed • Return 0 is unused • Event will continue to be passed around • Additional helper functions • Mouse: event_button() event_x() • Keyboard: event_key()
Spin Triangle with Mouse • Goal: mouse drags will rotate object • Filter out only used event • Pass rest to default handler • No previous mouse position with drag event (only current) • Initial click will seed last position • Need to hold current state
Spin Triangle with Mouse • Header: intoldX, oldY; float vRotation, hRotation; int handle(int event); • Constructor: vRotation = hRotation = 0.0f; • Draw: glRotatef(hRotation, 0.0f, 1.0f, 0.0f); glRotatef(vRotation, 1.0f, 0.0f, 0.0f);
Handle switch ( event ) { case FL_DRAG: hRotation += Fl::event_x() - oldX; vRotation += Fl::event_y() - oldY; redraw(); case FL_PUSH: oldX = Fl::event_x(); oldY = Fl::event_y(); return 1; default: return Fl_Gl_Window::handle(event); }
Assignment 1 Part 3 in FLUID • Keep class OpenGLWindow • In fluidd.exe • Add New->Code->class, set the name of the class ‘UI’ • Highlight class UI, New->Code->function/Method, add the constructor UI(), set it public • Highlight UI(), New->group->Window, under C++ tab, name it mainWindow • Highlight mainWindow, New->valuator->Slider. Change its label. Under tab C++, set it horizontal. Add extra code • divisions->range(0, 5); • divisions->step(1); • Add callback • glWindow->setDivision(divisions->value()); • glWindow->redraw();
Highlight mainWindow • New->Buttons->button. Change its label. Under tab C++, set it a toggle button, and set its name spinning. • New->others->box to add OpenGLWindow widget. Under tab C++, add extra code: #include"OpenGLWindow.h“ and name it glWindow. • Highlight class UI • New->Code->declaration, add a variable ‘float spin’