/* * Copyright (C) Keith Whitwell 1996 */ #include #include #include #include #include #include #include #include #include #include #include "interface.h" typedef void Callback(Widget, XtPointer, XtPointer); typedef void Action(Widget, XEvent *, String *, Cardinal *); typedef Boolean WorkProc(XtPointer); Callback register_widget; Callback create_filetype_choices; Callback select_filetype; Callback fix_parent_height; Callback fix_parent_fraction_width; Callback manage; Callback file_select_cb; Callback popdown_cb; Callback shell_dialog_cb; Callback motif_dialog_cb; Callback display_cb; Callback quit_cb; Callback print; Callback toggle_ortho; Callback toggle_debug; Callback resize_notify; Callback expose_notify; Callback set_smooth; Callback set_wire; Callback set_flat; Callback set_texture; WorkProc animate; Action arcball; Action move_camera_xy; Action move_camera_xz; MrmHierarchy hierarchy; Cardinal status; MrmType class_code; XtAppContext app_context; Widget toplevel; Widget text_output; Widget drawing_output; static String uid_files[] = { "viewer", "menubar", "dialogs" }; typedef enum { FILE_OPEN, FILE_SAVE, FILE_EXIT, FILE_CLOSE } FileOp; static MrmRegisterArg callback_list[] = { { "register_widget", (XtPointer) register_widget }, { "create_filetype_choices", (XtPointer) create_filetype_choices }, { "fix_parent_height", (XtPointer) fix_parent_height }, { "fix_parent_fraction_width", (XtPointer) fix_parent_fraction_width }, { "manage", (XtPointer) manage }, { "motif_dialog_cb", (XtPointer) motif_dialog_cb }, { "shell_dialog_cb", (XtPointer) shell_dialog_cb }, { "display_cb", (XtPointer) display_cb }, { "file_select_cb", (XtPointer) file_select_cb }, { "popdown_cb", (XtPointer) popdown_cb }, { "quit_cb", (XtPointer) quit_cb }, { "print", (XtPointer) print }, { "toggle_ortho", (XtPointer) toggle_ortho }, { "toggle_debug", (XtPointer) toggle_debug }, { "resize_notify", (XtPointer) resize_notify }, { "expose_notify", (XtPointer) expose_notify }, { "set_smooth", (XtPointer) set_smooth }, { "set_wire", (XtPointer) set_wire }, { "set_flat", (XtPointer) set_flat }, { "set_texture", (XtPointer) set_texture }, }; static MrmRegisterArg widget_list[] = { { "w_drawing_output", (XtPointer) &drawing_output }, { "w_text_output", (XtPointer) &text_output }, }; typedef enum { DIALOG_ERROR, DIALOG_OPEN, DIALOG_SAVE, DIALOG_LIGHT, DIALOG_MAX } DialogId; typedef struct { DialogId id; char *name; Widget widget; } Dialog; Dialog dialogs[DIALOG_MAX] = { { DIALOG_ERROR, "error_dialog", 0 }, { DIALOG_OPEN, "open_dialog", 0 }, { DIALOG_SAVE, "save_dialog", 0 }, { DIALOG_LIGHT, "light_panes", 0 }, }; XtActionsRec actions[] = { { "arcball", arcball }, { "move_camera_xy", move_camera_xy }, { "move_camera_xz", move_camera_xz }, }; void setText(char *format, ...); void clearText(void); void bell(void); void showError(char *format, ...); void motif_dialog(DialogId); void shell_dialog(DialogId); void process_args(int, char *[]); static int debug = 0; static int filetype = 0; int main(int argc, char *argv[]) { Widget main_window; XtSetLanguageProc (NULL, NULL, NULL); MrmInitialize(); toplevel = XtVaAppInitialize(&app_context, "Demos", NULL, 0, &argc, argv, NULL, NULL); XtAppAddActions(app_context, actions, XtNumber(actions)); if (MrmOpenHierarchyPerDisplay(XtDisplay(toplevel), XtNumber(uid_files), uid_files, NULL, &hierarchy) != MrmSUCCESS) { XtAppError(app_context, "Couldn't open uid files.\n"); exit(1); } if (MrmRegisterNames(callback_list, XtNumber(callback_list)) != MrmSUCCESS) { XtAppError(app_context, "Couldn't register callback functions.\n"); exit(1); } if (MrmRegisterNames(widget_list, XtNumber(widget_list)) != MrmSUCCESS) { XtAppError(app_context, "Couldn't register callback functions.\n"); exit(1); } if (MrmFetchWidget(hierarchy, "main_window", toplevel, &main_window, &class_code) != MrmSUCCESS) { XtAppError(app_context, "Couldn't create interface from UID file.\n"); exit(1); } XtManageChild (main_window); XtRealizeWidget (toplevel); initialize(drawing_output); /* Start up 3d. */ process_args(argc, argv); /* XtAppAddWorkProc(app_context, animate, NULL); */ XtAppMainLoop (app_context); } void process_args(int argc, char *argv[]) { if (argc == 2) { if (load_model(argv[1], FiletypeNff) == 0) { showError("Failed to load %s as NFF", basename(argv[1])); } render(); } } void showError(char *format, ...) { static char buf[256]; static Widget dialog; XmString s; if (dialog == NULL) { MrmFetchWidget(hierarchy, "error_dialog", toplevel, &dialog, &class_code); if (dialog == NULL || ! XmIsMessageBox (dialog)) { XtAppError (app_context, "Creation of error dialog failed."); exit (1); } } { va_list ap; va_start(ap, format); vsprintf(buf, format, ap); va_end(ap); } s = XmStringCreateLocalized(buf); XtVaSetValues(dialog, XmNmessageString, s, NULL); XmStringFree(s); XtManageChild(dialog); } /* * Callback routine for "OK" button in FileSelectionDialogs */ void file_select_cb (Widget dialog, XtPointer client_data, XtPointer call_data) { char *filename = NULL; char *text = NULL; FILE *fp = NULL; long len; FileOp reason = *((FileOp *) client_data); XmFileSelectionBoxCallbackStruct *cbs = (XmFileSelectionBoxCallbackStruct *) call_data; setText(""); if (!XmStringGetLtoR (cbs->value, XmFONTLIST_DEFAULT_TAG, &filename)) return; if (*filename == '\0') { XtFree(filename); setText("Choose a file."); bell(); return; } switch (reason) { case FILE_OPEN: setText("open nff file %s", basename(filename)); if (load_model(filename, FiletypeNff) == 0) { showError("Failed to load %s as NFF", basename(filename)); } render(); break; case FILE_SAVE: setText("save file %s", filename); if (!renderToFile(filetype, filename)) { showError("Failed to save to file %s\n", filename); } break; } /* free all allocated space. */ if (fp) fclose(fp); XtFree(text); XtFree(filename); XtUnmanageChild(dialog); } void shell_dialog_cb(Widget w, XtPointer client_data, XtPointer call_data) { DialogId d = * (DialogId *) client_data; shell_dialog(d); } void motif_dialog_cb(Widget w, XtPointer client_data, XtPointer call_data) { DialogId d = * (DialogId *) client_data; motif_dialog(d); } void popdown_cb(Widget w, XtPointer client_data, XtPointer call_data) { XtUnmanageChild (w); } void register_widget(Widget w, XtPointer client_data, XtPointer call_data) { Widget *w_ptr = (Widget *) client_data; *w_ptr = w; } void create_filetype_choices(Widget w, XtPointer client_data, XtPointer call_data) { int i, nr; const char **ptr; Widget child; ptr = getFileTypeArray( &nr ); for ( i = 0 ; i < nr ; i++ ) { child = XtVaCreateManagedWidget(ptr[i], xmPushButtonGadgetClass, w, NULL); XtAddCallback(child, XmNactivateCallback, select_filetype, (XtPointer) i); } } void select_filetype(Widget w, XtPointer client_data, XtPointer call_data) { printf("Selected filetype %d\n", (int) client_data); } void fix_parent_height(Widget w, XtPointer client_data, XtPointer call_data) { Dimension h; XtVaGetValues(w, XmNheight, &h, NULL); printf("Height: %d\n", h); XtVaSetValues(XtParent(w), XmNpaneMaximum, h, XmNpaneMinimum, h, NULL); } void fix_parent_fraction_width(Widget w, XtPointer client_data, XtPointer call_data) { Dimension wid, parent_wid, desired; Cardinal fb, left, right; XtVaGetValues(w, XmNwidth, &wid, XmNleftPosition, &left, XmNrightPosition, &right, NULL); XtVaGetValues(XtParent(w), XmNfractionBase, &fb, XmNwidth, &parent_wid, NULL); desired = fb * wid / (right-left) + 1; printf("current: %d desired: %d\n", parent_wid, desired); if (desired > parent_wid) { XtVaSetValues(XtParent(XtParent(w)), XmNwidth, desired, NULL); } } void manage(Widget w, XtPointer client_data, XtPointer call_data) { XtManageChild(w); } void quit_cb(Widget w, XtPointer client_data, XtPointer call_data) { MrmCloseHierarchy (hierarchy); shutdown(); exit (0); } void print(Widget w, XtPointer client_data, XtPointer call_data) { puts((char *)client_data); } void display_cb(Widget w, XtPointer client_data, XtPointer call_data) { printf("Display op: %d\n", *(int *)client_data); } void set_smooth(Widget w, XtPointer client_data, XtPointer call_data) { setPipeline(1); render(); } void set_wire(Widget w, XtPointer client_data, XtPointer call_data) { setPipeline(3); render(); } void set_flat(Widget w, XtPointer client_data, XtPointer call_data) { setPipeline(0); render(); } void set_texture(Widget w, XtPointer client_data, XtPointer call_data) { setPipeline(2); render(); } void toggle_ortho(Widget w, XtPointer client_data, XtPointer call_data) { static int ortho = 0; ortho = ((XmToggleButtonCallbackStruct *)call_data)->set; printf("Ortho: %s\n", ortho ? "on" : "off"); } void toggle_debug(Widget w, XtPointer client_data, XtPointer call_data) { /* * Should also set lib3d debugging. */ debug = ((XmToggleButtonCallbackStruct *)call_data)->set; printf("Debug: %s\n", debug ? "on" : "off"); } void resize_notify(Widget w, XtPointer client_data, XtPointer call_data) { if (w == drawing_output) { if (debug) printf("resize\n"); notifyResize(); render(); } } void expose_notify(Widget w, XtPointer client_data, XtPointer call_data) { if (w == drawing_output) { XExposeEvent *xev = (XExposeEvent *) ((XmDrawingAreaCallbackStruct *)call_data)->event; if (debug) printf("expose\n"); notifyExpose(xev->x, xev->y, xev->x+xev->width, xev->y+xev->height); } } void arcball(Widget w, XEvent *ev, String *args, Cardinal *num) { static Position x, y, state = 0; XButtonEvent *bev = (XButtonEvent *)ev; if (debug) printf("arcball\n"); if (*num != 1) { XtError("Wrong number of args for draw() action."); } if (strcmp(args[0], "up") == 0) { state = 0; } else if (strcmp(args[0], "down") == 0) { state = 1; } else { arcBall(bev->x - x, bev->y - y); render(); } x = bev->x; y = bev->y; } void move_camera_xz(Widget w, XEvent *ev, String *args, Cardinal *num) { static Position x, y; XButtonEvent *bev = (XButtonEvent *)ev; if (debug) printf("camera_xz\n"); if (*num != 1) { XtError("Wrong number of args for draw() action."); } if (strcmp(args[0], "down") != 0) { moveCamera(bev->x - x, 0, bev->y - y); /* Move in X and Z */ render(); } x = bev->x; y = bev->y; } void move_camera_xy(Widget w, XEvent *ev, String *args, Cardinal *num) { static Position x, y; XButtonEvent *bev = (XButtonEvent *)ev; if (debug) printf("camera_xy\n"); if (*num != 1) { XtError("Wrong number of args for draw() action."); } if (strcmp(args[0], "down") != 0) { moveCamera(bev->x - x, bev->y - y, 0); /* Move in X and Y */ render(); } x = bev->x; y = bev->y; } Boolean animate(XtPointer data) { XEvent dummy; if (debug) printf("work\n"); render(); /* * Try to minimize cpu usage. */ XPeekEvent(XtDisplay(drawing_output), &dummy); return False; } void shell_dialog(DialogId d) { clearText(); if (dialogs[d].widget == NULL) { Widget tmp; dialogs[d].widget = XtVaCreatePopupShell("", xmDialogShellWidgetClass, toplevel, XmNdeleteResponse, XmUNMAP, NULL); MrmFetchWidget(hierarchy, dialogs[d].name, dialogs[d].widget, &tmp, &class_code); if (tmp == NULL) { showError("Error: Creation of %s failed.", dialogs[d].name); XtDestroyWidget(dialogs[d].widget); dialogs[d].widget = NULL; return; } XtManageChild(tmp); } printf("popping up\n"); /* XtRealizeWidget (toplevel); */ XtPopup (dialogs[d].widget, XtGrabNone); } void motif_dialog(DialogId d) { clearText(); if (dialogs[d].widget == NULL) { MrmFetchWidget(hierarchy, dialogs[d].name, toplevel, &dialogs[d].widget, &class_code); if (dialogs[d].widget == NULL) { setText("Error: Creation of %s failed.", dialogs[d].name); return; } } XtManageChild(dialogs[d].widget); } void setText(char *format, ...) { static char buf[256]; va_list ap; va_start(ap, format); vsprintf(buf, format, ap); XmTextSetString (text_output, buf); va_end(ap); } void bell() { XBell(XtDisplay(text_output), 50); } void clearText(void) { XmTextSetString(text_output, NULL); }