/*---------------------------------------------------------------------------- * input.c * * This file contains the routines to handle user input via the mouse and * menus. The routines farm out the users requests to appropriate input * handler routines if necessary. *---------------------------------------------------------------------------- */ #include #include #include "defs.h" #include "ds.h" #include "menu.h" #include "input.h" get_input () { struct IntuiMessage *message ; extern struct IntuiMessage *GetMsg() ; ULONG class ; USHORT code ; APTR address ; /*--------------------------------------------------------------------------- * The program waits for user input from the mouse. The Wait() function * puts the program to sleep while waiting. The Class and Code field of the * IntuiMessage contains the information required to decide what the user * request was. * Input is in 2 major classes, menu selections and requester gadget * selections. All the requester gadget selections are sent to * "handle_gadget()" in the req.c file. *--------------------------------------------------------------------------- */ LOOP_FOREVER { Wait (1 << window->UserPort->mp_SigBit) ; while (message = GetMsg (window->UserPort)) { class = message->Class ; /* store message info */ code = message->Code ; /* before replying */ address = message->IAddress ; ReplyMsg (message) ; switch (class) { case MENUPICK: execute_menu_selection (code) ; break ; case GADGETUP: handle_gadget ((struct Gadget *) address) ; break ; default: close_down ("Error: Bad Intuition message\n") ; break ; } } } } execute_menu_selection (menu_num) USHORT menu_num ; { struct MenuItem *item ; extern struct MenuItem *ItemAddress() ; /*--------------------------------------------------------------------------- * The user has requested a menu function. The MENUNUM macro extracts the * menu selected by the user. * The NextSelect field of the selected menu items data structure will point * to a valid menu item (or subitem) if the user has selected more than one * menu function, before releasing the left mouse button.. *--------------------------------------------------------------------------- */ while (menu_num != MENUNULL) { switch (MENUNUM (menu_num)) { case ANIMATE_MENU: animate (menu_num) ; break ; case GOAL_MENU: set_goal (menu_num) ; break ; case ROTATE_MENU: rotate (menu_num) ; break ; case VIEW_MENU: set_view (menu_num) ; break ; case PROJECT_MENU: project (menu_num) ; break ; default: close_down ("Error: Bad menu number\n") ; break ; } item = ItemAddress (first_menu, menu_num) ; menu_num = item->NextSelect ; } } animate (menu_num) USHORT menu_num ; { int restore_ref_axes = NO ; ; /*--------------------------------------------------------------------------- * The user has selected an Animate menu function. The ITEMNUM macro * extracts the menu item selected by the user. * The "arm" menu item animates the arm using the joint settings specified * with the "set all joints" menu item. The window is closed down and the * the double buffered screen is used to display the animation. See the * anim.c file for the details. * The "flypast" menu item does a flypast of the current arm position * using a set of viewing transformations pre-calculated and stored in * "flypast_trans[][][]". See the fly.c file for the details. * The "both" menu item is not yet implemented. It will do both of the * above at the same time. *--------------------------------------------------------------------------- */ switch (ITEMNUM (menu_num)) { case ARM_ITEM: if (SPCmp (rot_info.max_angle_change, ffp.zero.i) == 0) Request (&no_change, window) ; else { if (menu_choices.ref_axes == ON) { restore_ref_axes = YES ; menu_choices.ref_axes = OFF ; } ClearMenuStrip (window) ; CloseWindow (window) ; open_db_screen_for_animation () ; make_window () ; setup_window_temporary_draw_area () ; if (restore_ref_axes) menu_choices.ref_axes = ON ; update_joint_transformations () ; transform_links () ; set_screen_coords () ; draw_image (window->RPort) ; if (menu_choices.viewtype != PARALLEL) change_persp_option (ON, YES) ; } menu_choices.goaltype = ROTATE ; break ; case FLYPAST_ITEM: if (menu_choices.ref_axes == ON) { restore_ref_axes = YES ; menu_choices.ref_axes = OFF ; } ClearMenuStrip (window) ; CloseWindow (window) ; open_db_screen_for_flypast () ; make_window () ; setup_window_temporary_draw_area () ; if (restore_ref_axes) menu_choices.ref_axes = ON ; transform_links () ; set_screen_coords () ; draw_image (window->RPort) ; if (menu_choices.viewtype != PARALLEL) change_persp_option (ON, YES) ; break ; case BOTH_ITEM: /* not yet implemented */ dummy_ack ("Both") ; break ; default: close_down ("Error: Bad menu item number\n") ; break ; } } set_goal (menu_num) USHORT menu_num ; { /*--------------------------------------------------------------------------- * The user has selected a Goal menu function. The ITEMNUM macro * extracts the menu item selected by the user. *--------------------------------------------------------------------------- */ switch (ITEMNUM (menu_num)) { case SET_ALL_JOINTS_ITEM: if (menu_choices.goaltype == SET_ALL_JOINTS) Request (&anim_cancel_set, window) ; else { menu_choices.goaltype = SET_ALL_JOINTS ; Request (&get_shoulder_angles, window) ; } break ; case DISTAL_GOAL_ITEM: /* not yet implemented */ dummy_ack ("Distal") ; break ; case PLACE_OBSTACLES_ITEM: /* not yet implemented */ dummy_ack ("Place") ; break ; default: close_down ("Error: Bad menu item number\n") ; break ; } } rotate (menu_num) USHORT menu_num ; { /*--------------------------------------------------------------------------- * The user has selected a Rotate menu function. The ITEMNUM macro * extracts the menu item selected by the user. * One of the joints has been selected for rotation. A requester is * presented for the users joint settings input. *--------------------------------------------------------------------------- */ switch (ITEMNUM (menu_num)) { case SHOULDER_ITEM: if (menu_choices.goaltype == SET_ALL_JOINTS) Request (&anim_cancel_rot, window) ; else Request (&get_shoulder_angles, window) ; break ; case ELBOW_ITEM: if (menu_choices.goaltype == SET_ALL_JOINTS) Request (&anim_cancel_rot, window) ; else Request (&get_elbow_angle, window) ; break ; case WRIST_ITEM: if (menu_choices.goaltype == SET_ALL_JOINTS) Request (&anim_cancel_rot, window) ; else Request (&get_wrist_angles, window) ; break ; default: close_down ("Error: Bad menu item number\n") ; break ; } } set_view (menu_num) USHORT menu_num ; { /*--------------------------------------------------------------------------- * The user has selected a View menu function. The ITEMNUM macro * extracts the menu item selected by the user. * The user may select the rendering type (wire frame or solid view with * hidden surfaces removed), whether the reference axes are to be displayed, * the viewpoint, and a choice of parallel or perspective view. *--------------------------------------------------------------------------- */ switch (ITEMNUM (menu_num)) { case WIRE_FRAME_ITEM: if (menu_choices.render == SOLID_VIEW) { menu_choices.render = WIRE_FRAME ; draw_image (window->RPort) ; } break ; case SOLID_VIEW_ITEM: if (menu_choices.render == WIRE_FRAME) { menu_choices.render = SOLID_VIEW ; draw_image (window->RPort) ; } break ; case REF_AXES_ITEM: adjust_ref_axes (menu_num) ; break ; case VIEWPOINT_ITEM: change_viewpoint (menu_num) ; break ; case PERSPECTIVE_ITEM: set_perspective (menu_num) ; break ; default: close_down ("Error: Bad menu item number\n") ; break ; } } set_perspective (menu_num) USHORT menu_num ; { short draw_persp = NO ; /*--------------------------------------------------------------------------- * The user has selected a a Perspective subitem from the View menu. * The SUBNUM macro extracts the menu subitem selected by the user. * The choices are parallel, wide angle or telephoto views. *------------------ --------------------------------------------------------- */ switch (SUBNUM (menu_num)) { case PARALLEL_SUBITEM: if (menu_choices.viewtype != PARALLEL) { menu_choices.viewtype = PARALLEL ; change_persp_option (ON, NO) ; SetRast (window->RPort, COLOR0) ; transform_links () ; set_screen_coords () ; draw_image (window->RPort) ; } break ; case WIDE_ANGLE_SUBITEM: if (menu_choices.viewtype == PARALLEL) { draw_persp = YES ; menu_choices.viewtype = WIDE_ANGLE ; SetRast (window->RPort, COLOR0) ; perspective_transformation (ffp.wide_angle_aperture.i) ; } break ; case TELEPHOTO_SUBITEM: if (menu_choices.viewtype == PARALLEL) { draw_persp = YES ; menu_choices.viewtype = TELEPHOTO ; SetRast (window->RPort, COLOR0) ; perspective_transformation (ffp.telephoto_aperture.i) ; } break ; default: close_down ("Error: Bad menu sub item number\n") ; break ; } if (draw_persp) { set_screen_coords () ; draw_image (window->RPort) ; change_persp_option (OFF, NO) ; } } change_viewpoint (menu_num) USHORT menu_num ; { int change = NO ; /*--------------------------------------------------------------------------- * The user has selected a a Viewpoint subitem from the View menu. * The SUBNUM macro extracts the menu subitem selected by the user. * The viewpoints are front, side, top and 3 angled views. *------------------ --------------------------------------------------------- */ switch (SUBNUM (menu_num)) { case FRONT_SUBITEM: if (menu_choices.viewpoint != FRONT_VIEW) { menu_choices.viewpoint = FRONT_VIEW ; rot_info.curr_view_trans = (int *)&view_trans.front ; change = YES ; } break ; case SIDE_SUBITEM: if (menu_choices.viewpoint != SIDE_VIEW) { menu_choices.viewpoint = SIDE_VIEW ; rot_info.curr_view_trans = (int *)&view_trans.side ; change = YES ; } break ; case TOP_SUBITEM: if (menu_choices.viewpoint != TOP_VIEW) { menu_choices.viewpoint = TOP_VIEW ; rot_info.curr_view_trans = (int *)&view_trans.top ; change = YES ; } break ; case ANGLE1_SUBITEM: if (menu_choices.viewpoint != ANGLE1_VIEW) { menu_choices.viewpoint = ANGLE1_VIEW ; rot_info.curr_view_trans = (int *)&view_trans.angle1 ; change = YES ; } break ; case ANGLE2_SUBITEM: if (menu_choices.viewpoint != ANGLE2_VIEW) { menu_choices.viewpoint = ANGLE2_VIEW ; rot_info.curr_view_trans = (int *)&view_trans.angle2 ; change = YES ; } break ; case ANGLE3_SUBITEM: if (menu_choices.viewpoint != ANGLE3_VIEW) { menu_choices.viewpoint = ANGLE3_VIEW ; rot_info.curr_view_trans = (int *)&view_trans.angle3 ; change = YES ; } break ; default: close_down ("Error: Bad menu sub item number\n") ; break ; } if (change) { change_persp_option (ON, YES) ; SetRast (window->RPort, COLOR0) ; transform_links () ; set_screen_coords () ; draw_image (window->RPort) ; } } adjust_ref_axes (menu_num) USHORT menu_num ; { static short first_time = YES ; /*--------------------------------------------------------------------------- * Turn the reference axes on or off. *--------------------------------------------------------------------------- */ switch (SUBNUM (menu_num)) { case ON_SUBITEM: if (menu_choices.ref_axes != ON) { if (first_time) { first_time = NO ; Request (&req_rot_info, window) ; } menu_choices.ref_axes = ON ; draw_ref_axes (window->RPort) ; } break ; case OFF_SUBITEM: if (menu_choices.ref_axes != OFF) { menu_choices.ref_axes = OFF ; SetRast (window->RPort, COLOR0) ; transform_links () ; set_screen_coords () ; draw_image (window->RPort) ; } break ; default: close_down ("Error: Bad menu sub item number\n") ; break ; } } project (menu_num) USHORT menu_num ; { /*--------------------------------------------------------------------------- * The user has selected a Project menu function. The ITEMNUM macro * extracts the menu item selected by the user. * The choices available are to quit the program, change the color * settings, on screen help, information on yours truly, or to start over. *--------------------------------------------------------------------------- */ switch (ITEMNUM (menu_num)) { case QUIT_ITEM: close_down (NORMAL_EXIT) ; break ; case COLORS_ITEM: set_colors (menu_num) ; break ; case HELP_ITEM: /* not yet implemented */ dummy_ack ("Help") ; break ; case AUTHOR_ITEM: Request (&author_info, window) ; break ; case NEW_ITEM: start_over () ; break ; default: close_down ("Error: Bad menu item number\n") ; break ; } } set_colors (menu_num) USHORT menu_num ; { /*--------------------------------------------------------------------------- * The user has selected a Colors subitem from the Project menu. * The SUBNUM macro extracts the menu subitem selected by the user. * There is a choice of 4 color settings, each using colors selected * from the 4096 available. *--------------------------------------------------------------------------- */ switch (SUBNUM (menu_num)) { case DEFAULT_SUBITEM: LoadRGB4 (&screen->ViewPort, colortable.start, NUM_COLORS) ; menu_choices.colors = START ; break ; case SET1_SUBITEM: LoadRGB4 (&screen->ViewPort, colortable.set1, NUM_COLORS) ; menu_choices.colors = SET1 ; break ; case SET2_SUBITEM: LoadRGB4 (&screen->ViewPort, colortable.set2, NUM_COLORS) ; menu_choices.colors = SET2 ; break ; case SET3_SUBITEM: LoadRGB4 (&screen->ViewPort, colortable.set3, NUM_COLORS) ; menu_choices.colors = SET3 ; break ; default: close_down ("Error: Bad menu sub item number\n") ; break ; } } change_persp_option (turn_on, alter_flags) short turn_on, alter_flags ; { /*--------------------------------------------------------------------------- * Turn the wide angle and telephoto perspective options off if the user * selects one. The menu items will be ghosted. * Turn them back on if a change of viewpoint or joint rotation is * specified. Reset the perspective item checkmark accordingly. *--------------------------------------------------------------------------- */ if (alter_flags) { menu_choices.viewtype = PARALLEL ; ClearMenuStrip (window) ; wide_angle_subitem.Flags = CHECKIT | ITEMTEXT | HIGHCOMP | ITEMENABLED ; telephoto_subitem.Flags = CHECKIT | ITEMTEXT | HIGHCOMP | ITEMENABLED ; parallel_subitem.Flags = CHECKIT | CHECKED | ITEMTEXT | HIGHCOMP | ITEMENABLED ; SetMenuStrip (window, first_menu) ; } if (turn_on) { OnMenu (window, 0x0881) ; OnMenu (window, 0x1081) ; } else { OffMenu (window, 0x0881) ; OffMenu (window, 0x1081) ; } } dummy_ack (message) UBYTE *message ; /*---------------------------------------------------------------------------- * Used when the dummy menu tester below is not in use. *---------------------------------------------------------------------------- */ { message++ ; } /*---------------------------------------------------------------------------- dummy_ack (message) UBYTE *message ; { struct IntuiText test ; static int yoffset = -5 ; static int xoffset = 540 ; struct RastPort *r ; r = window->RPort ; test.FrontPen = COLOR1 ; test.BackPen = COLOR5 ; test.DrawMode = JAM1 ; test.LeftEdge = 0 ; test.TopEdge = 0 ; test.ITextFont = &prog_font ; test.IText = message ; test.NextText = NULL ; yoffset = yoffset + 10 ; if (yoffset > 170) { yoffset = 5 ; xoffset = xoffset - 100 ; } PrintIText (r, &test, xoffset, yoffset) ; } *----------------------------------------------------------------------------- */