void Particle::draw() { glColor3fv(&color.red); float diam = 2*radius*view.relscale(); // set diameter in screen space if (diam<1.5) diam = 1.5; // don't let them disappear glPointSize(diam); // sets diameter in screen space units, not world space glBegin(GL_POINTS); glVertex2f(pos[0], pos[1]); // draw point glEnd(); }
Particle *World::pick_particle(int sx, int sy, View &view) { Vec2 q = view.screen_to_world(sx, sy); // transform screen space (sx,sy) to world space q Real thresh_world = thresh_screen/view.viewport.width/view.relscale(); // threshold distance in world space int i; Real d, min = HUGE; Particle *nearest = NULL; for (i=0; i<n; i++) { d = sqrlen(pt[i].pos-q); // distance squared if (d<min) { min = d; nearest = &pt[i]; } } if (sqrt(min) > thresh_world) nearest = NULL; printf("World::pick_particle %d\n", nearest==NULL ? -1 : nearest-pt); return nearest; }
void handle_event(XEvent *event) { /* see /usr/include/X11/X.h for definitions of X Windows event types */ // you won't want to leave these printf's in here for your finished program, // but they should help you get started and debug. static int xprev, yprev, xstart, ystart; switch (event->type) { case ButtonPress: /* button press */ printf(" ButtonPress. button %d at (%d, %d)\n", event->xbutton.button, event->xbutton.x, event->xbutton.y); switch (event->xbutton.button) { case 1: world.curp = world.pick_particle(event->xbutton.x, event->xbutton.y, view); if (!world.curp) break; if (is_key_pressed(pane.display, XK_Shift_L) || is_key_pressed(pane.display, XK_Shift_R)) { world.delete_particle(world.curp); world.curp = NULL; } else fl_set_slider_value(ui->mass_slider, world.curp->mass); // set slider to show the mass of this particle break; case 2: { Vec2 p = view.screen_to_world(event->xbutton.x, event->xbutton.y); world.curp = world.insert_particle(p[0], p[1], 0, 0, fl_get_slider_value(ui->mass_slider)); } break; case 3: // save these for later use when MotionNotify event comes xstart = xprev = event->xbutton.x; ystart = yprev = event->xbutton.y; break; } world.draw(); break; case ButtonRelease: /* button release */ printf(" ButtonRelease. button %d\n", event->xbutton.button); break; case MotionNotify: /* mouse pointer moved */ printf(" MotionNotify at (%d, %d) state=%d=(%s %s %s)\n", event->xmotion.x, event->xmotion.y, event->xmotion.state, event->xmotion.state&Button1Mask ? "button1" : ".", event->xmotion.state&Button2Mask ? "button2" : ".", event->xmotion.state&Button3Mask ? "button3" : "."); if (world.curp && ( event->xmotion.state & (Button1Mask|Button2Mask))) { /* printf("moving particle %d\n", world.curp-world.pt); */ world.curp->pos = view.screen_to_world(event->xmotion.x, event->xmotion.y); } else if (event->xmotion.state & Button3Mask) { if (is_key_pressed(pane.display, XK_Shift_L) || is_key_pressed(pane.display, XK_Shift_R)) { float s = 1. + (event->xmotion.x - xprev)/100.; /* printf("s=%g\n", s); */ Vec2 pos = view.screen_to_world(xstart, ystart); // scale view around the point where user moused down glTranslatef(pos[0], pos[1], 0.); glScalef(s, s, 1.); glTranslatef(-pos[0], -pos[1], 0.); } else { float t = view.viewport.width*view.relscale(); glTranslatef((event->xmotion.x - xprev)/t, -(event->xmotion.y - yprev)/t, 0.); } view.update(); xprev = event->xmotion.x; yprev = event->xmotion.y; } world.draw(); break; case EnterNotify: /* mouse pointer entered window */ printf(" EnterNotify.\n"); break; case LeaveNotify: /* mouse pointer left window */ printf(" LeaveNotify.\n"); break; case KeyPress: /* key pressed */ case KeyRelease: /* key released */ { char buf[10]; int n; KeySym keysym; printf(event->type==KeyPress ? " KeyPress." : " KeyRelease."); n = XLookupString(&event->xkey, buf, sizeof buf - 1, &keysym, 0); buf[n] = 0; /* print key as ascii and in hexadecimal */ /* see /usr/include/X11/keysymdef.h for key codes */ printf(" key=(%c)=0x%x\n", keysym, keysym); } break; case Expose: /* window just uncovered */ printf(" Expose.\n"); world.draw(); break; case VisibilityNotify: /* window occluded or exposed */ printf(" VisibilityNotify.\n"); break; default: printf(" unknown event type.\n"); break; } }