/* * Tool for building movies of objects. */ #include #include #include "X11/Intrinsic.h" #include "X11/StringDefs.h" #include "X11/Shell.h" #include "X11/Xaw/Command.h" #include "X11/Xaw/Label.h" #include "X11/Xaw/Box.h" #include "X11/Xaw/Cardinals.h" #include "X11/Xaw/Dialog.h" #include #include #include #include #include #include "Bitmaps/dot.b" #define FALSE 0 #define TRUE 1 #define DIM 20 /* Image is DIMxDIM (was 10). */ #define N 100 /* Max number of units allowed in net */ #define X_OFF 370 /* X offset from scene window border */ #define Y_OFF 250 /* Y offset from scene window border */ #define LM_X_OFF 10 /* X offset from LM window border */ #define LM_Y_OFF 250 /* Y offset from LM window border */ #define TR_X_OFF 170 /* X offset from TR window border */ #define TR_Y_OFF 250 /* Y offset from TR window border */ #define N_OBJS 27 /* Number of objects */ #define MAXFRAMES 100 /* Max number of frames in a movie. */ /* X-related global variables */ Display *disptr; Window win; XEvent event; GC gc; XFontStruct *font; XGCValues values; XWindowAttributes attr; XSetWindowAttributes set_attr; XImage img, *subimg; XColor Grey[256]; /* Grey scale */ Pixmap pmap; int Window_width; int Window_height; int CreatedNewFile; int ScreenInitialized; /* Object specification */ int ChoseCurObj; char TRfname[80]; char LMfname[80]; int TRx[MAXFRAMES],TRy[MAXFRAMES],LMx,LMy; char CurObjfname[80]; static XImage CurObjimage = { 0, 0, /* width, height */ 0, XYBitmap, NULL, /* xoffset, format, data */ LSBFirst, 8, /* byte-order, bitmap-unit */ LSBFirst, 8, 1 /* bitmap-bit-order, bitmap-pad, depth */ }; static XImage TRimage = { 0, 0, /* width, height */ 0, XYBitmap, NULL, /* xoffset, format, data */ LSBFirst, 8, /* byte-order, bitmap-unit */ LSBFirst, 8, 1 /* bitmap-bit-order, bitmap-pad, depth */ }; static XImage LMimage = { 0, 0, /* width, height */ 0, XYBitmap, NULL, /* xoffset, format, data */ LSBFirst, 8, /* byte-order, bitmap-unit */ LSBFirst, 8, 1 /* bitmap-bit-order, bitmap-pad, depth */ }; XImage Objimage[N_OBJS]; char Objfname[N_OBJS][80]; char SCfname[80]; /* Name of scene file */ extern void exit(); static Arg button_args[] = /* ripped off from xfig code */ { /* 0 */ { XtNlabel, (XtArgVal)" " }, /* 1 */ { XtNwidth, (XtArgVal) 0 }, /* 2 */ { XtNheight, (XtArgVal) 0 }, /* 3 */ { XtNbackgroundPixmap, (XtArgVal)NULL }, /* 4 */ { XtNresizable, (XtArgVal) False }, /* 5 */ { XtNborderWidth, (XtArgVal) 1 }, /* 6 */ { XtNresize, (XtArgVal) False }, /* this last keeps the damned buttons from being resized when there are not a multiple of three of them */ }; static XrmOptionDescRec options[] = { {"-hspace", "*Box.hSpace", XrmoptionSepArg, NULL}, {"-vspace", "*Box.vSpace", XrmoptionSepArg, NULL}, }; Pixmap grid_pmap, p; int NumFrames; /* In the movie */ int JustReadLM; int GridDrawn; int Window_width; int Window_height; Widget toplevel, box, q_cmd, sq_cmd, cl_cmd, rs_cmd, tr_cmd, lm_cmd, obj_cmd[N_OBJS]; main(argc, argv) int argc; char **argv; { int ing; /* Needed for command line parsing */ extern char *optarg; /* Needed for command line parsing */ int old_argc; char **old_argv; float f; float UnitScreen(); char inc; int read_ok; int WriteFile; int bitmap_size; int cmd_line_TR; int cmd_line_LM; int status, x,y, i,j; static XtCallbackProc SelectObject(); static XtCallbackProc Quit(); static XtCallbackProc SaveAndQuit(); static XtCallbackProc StartMovie(); static XtCallbackProc RepaintScreen(); static XtCallbackProc MakeTR(); static XtCallbackProc MakeLM(); XtAppContext app_con; DIR *dirp, *opendir(); struct dirent *entryp, *readdir(); old_argc = argc; old_argv = argv; ChoseCurObj = FALSE; CreatedNewFile = FALSE; ScreenInitialized = FALSE; SCfname[0] = '*'; TRfname[0] = '*'; LMfname[0] = '*'; cmd_line_TR = FALSE; cmd_line_LM = FALSE; NumFrames = 0; /* Read in options */ while ((ing = getopt(old_argc,old_argv,"t:l:m:f:")) != EOF) switch (ing) { case 't': cmd_line_TR = TRUE; strcpy(TRfname, optarg); break; case 'l': cmd_line_LM = TRUE; strcpy(LMfname, optarg); break; case 'm': strcpy(SCfname, optarg); break; case 'f': NumFrames = atoi(optarg); break; } sprintf(argv[2], "Movie Editor"); /* Hack-o-rama. Dunno why this works. */ toplevel = XtAppInitialize(&app_con, "Xbuttonbox", options, XtNumber(options), &argc, argv, NULL, NULL, ZERO); if (SCfname[0] == '*') { printf (">> Error: No movie file specified. Use -m .\n"); exit(1); } else /* This will supply TR, LM. */ read_ok = ReadScreenFile(SCfname, cmd_line_TR, cmd_line_LM); /* Read in both the TR and the LM */ if (cmd_line_TR == TRUE) { status = ReadBitmapFile (TRfname,&TRimage); if (status != BitmapSuccess) { printf (">> Error: Could not read trajector object file.\n"); exit(1); } } else if (TRfname[0] == '*') { /* printf (">> Error: No trajector specified. Use -t .\n"); exit(1); */ } if (cmd_line_LM == TRUE) { status = ReadBitmapFile (LMfname,&LMimage); if (status != BitmapSuccess) { printf (">> Error: Could not read landmark object file.\n"); exit(1); } } else if (LMfname[0] == '*') { /* printf (">> Error: No landmark specified. Use -l .\n"); exit(1); */ } /* Create a Box widget and put all children in that box widget. */ box = XtCreateManagedWidget("box", boxWidgetClass, toplevel, NULL, ZERO); /* Put save, quit, start-movie, repaint command widgets in the box. */ q_cmd = XtCreateManagedWidget("Quit", commandWidgetClass, box, NULL, ZERO); XtAddCallback(q_cmd, XtNcallback, Quit, NULL); sq_cmd = XtCreateManagedWidget("Save and quit", commandWidgetClass, box, NULL, ZERO); XtAddCallback(sq_cmd, XtNcallback, SaveAndQuit, NULL); cl_cmd = XtCreateManagedWidget("Start Movie", commandWidgetClass, box, NULL, ZERO); XtAddCallback(cl_cmd, XtNcallback, StartMovie, NULL); rs_cmd = XtCreateManagedWidget("Repaint Screen", commandWidgetClass, box, NULL, ZERO); XtAddCallback(rs_cmd, XtNcallback, RepaintScreen, NULL); /* Put LM and TR widgets in the box. */ lm_cmd = XtCreateManagedWidget("Landmark", commandWidgetClass, box, NULL, ZERO); XtAddCallback(lm_cmd, XtNcallback, MakeLM, NULL); tr_cmd = XtCreateManagedWidget("Trajector", commandWidgetClass, box, NULL, ZERO); XtAddCallback(tr_cmd, XtNcallback, MakeTR, NULL); Window_width = 150; /* Subwindow to draw in */ Window_height = 150; /* Subwindow to draw in */ XtResizeWidget(toplevel, 550,450, 5); XtRealizeWidget(toplevel); disptr = XtDisplay(box); win = XtWindow(box); gc = DefaultGC(disptr, 0); XSetForeground(disptr,gc,BlackPixel(disptr,0)); XSetBackground(disptr,gc,WhitePixel(disptr,0)); /* Set up object bitmap buttons */ XGetWindowAttributes(disptr,win, &attr); i = 0; dirp = opendir("Objects"); entryp = (struct dirent *) 32; while ((entryp != NULL) && (i < N_OBJS)) { entryp = readdir(dirp); if ((entryp != NULL) && (entryp->d_name[0] != '.')) { Objimage[i].width = 0; Objimage[i].height = 0; Objimage[i].xoffset = 0; Objimage[i].format = XYBitmap; Objimage[i].data = NULL; Objimage[i].byte_order = LSBFirst; Objimage[i].bitmap_unit = 8; Objimage[i].bitmap_bit_order = LSBFirst; Objimage[i].bitmap_pad = 8; Objimage[i].depth = attr.depth; sprintf (Objfname[i], "Objects/%s", entryp->d_name); status = ReadBitmapFile (Objfname[i],&Objimage[i]); if (status == BitmapSuccess) /* Ignore non-bitmaps */ { p = XCreatePixmapFromBitmapData(disptr, win, Objimage[i].data, Objimage[i].width, Objimage[i].height, BlackPixel(disptr,0), WhitePixel(disptr,0), attr.depth); button_args[1].value = Objimage[i].width; button_args[2].value = Objimage[i].height; button_args[3].value = (XtArgVal)p; obj_cmd[i] = XtCreateManagedWidget("object", commandWidgetClass, box, button_args, XtNumber(button_args)); XtAddCallback(obj_cmd[i], XtNcallback, SelectObject, NULL); XtSetValues(obj_cmd[i], &button_args[3], 1); i++; } } } closedir(dirp); /* Wait until window exposed, then initialize screen. */ XSelectInput(disptr, win, ExposureMask); event.type = KeyPress; while (event.type != Expose) XNextEvent(disptr, &event); if (LMfname[0] == '*') { strcpy(LMfname,Objfname[0]); LMimage = Objimage[0]; } if (TRfname[0] == '*') { strcpy(TRfname,Objfname[1]); TRimage = Objimage[1]; } InitializeScreen(); if (read_ok) /* Read in screen file successfully */ PaintScreen(); XtAppMainLoop(app_con); } /* * Initialize screen for input. */ InitializeScreen() { int i; char dfname[80]; XClearArea(disptr,win,0,LM_Y_OFF-50, 550,450-(LM_Y_OFF-50)+1,FALSE); /* Draw rectangles for LM, TR, and scene as a whole. */ XDrawRectangle(disptr,win,gc, X_OFF,Y_OFF, Window_width, Window_width); XDrawRectangle(disptr,win,gc, LM_X_OFF,LM_Y_OFF, Window_width, Window_width); XDrawRectangle(disptr,win,gc, TR_X_OFF,TR_Y_OFF, Window_width, Window_width); /* Titles */ XDrawString(disptr,win,gc,LM_X_OFF+45,LM_Y_OFF-15,"Landmark",8); XDrawString(disptr,win,gc,TR_X_OFF+45,TR_Y_OFF-15,"Trajector",9); XDrawString(disptr,win,gc,X_OFF+55,Y_OFF-15,"Scene",5); sprintf(dfname, "File: %s ", SCfname); XDrawString(disptr,win,gc,TR_X_OFF-15,TR_Y_OFF+180,dfname,88); ScreenInitialized = TRUE; } /* * Start the movie: user moves the TR. */ static XtCallbackProc StartMovie(w, call_data, client_data) Widget w; XtPointer call_data, client_data; { Pixmap pmap; XEvent event; XEvent leave_event; int i,j, virgin, frame; int x,y, old_x, old_y; int xc[8], yc[8]; float UnitScreen(); /* double rint();*/ /* Paint TR source and LM in main scene, and in their boxes. */ InitializeScreen(); /* ok like this? */ if (ChoseCurObj) { TRimage = CurObjimage; strcpy(TRfname, CurObjfname); } PaintObject(TRimage,TRx[0]+X_OFF,TRy[0]+Y_OFF); PaintObject(LMimage,LMx+X_OFF,LMy+Y_OFF); PaintObject(TRimage,TRx[0]+TR_X_OFF,TRy[0]+TR_Y_OFF); PaintObject(LMimage,LMx+LM_X_OFF,LMy+LM_Y_OFF); if (NumFrames > 0) { XSelectInput(disptr, win, ButtonPressMask | PointerMotionMask ); PaintObject(TRimage,TRx[0]+X_OFF,TRy[0]+Y_OFF); PaintObject(TRimage,TRx[0]+TR_X_OFF,TRy[0]+TR_Y_OFF); frame = 0; while (frame < NumFrames) { virgin = TRUE; event.type = KeyPress; while (event.type != ButtonPress) { XWindowEvent(disptr, win, ButtonPressMask | PointerMotionMask, &event); x = event.xbutton.x; y = event.xbutton.y; if (x >= X_OFF && y >= Y_OFF && x <= X_OFF+Window_width && y <= Y_OFF+Window_height) { if ( ! virgin && event.type == MotionNotify ) PaintObject(TRimage, old_x,old_y); /* Erase old one */ PaintObject(TRimage,x,y); old_x = x; old_y = y; virgin = FALSE; } } PaintObject(TRimage,x,y); TRx[frame] = x-X_OFF; TRy[frame] = y-Y_OFF; PaintObject(TRimage, TRx[frame]+TR_X_OFF,TRy[frame]+TR_Y_OFF); if (frame > 0) { XSetLineAttributes(disptr,gc, 0, LineOnOffDash, CapButt, JoinMiter); XDrawLine(disptr,win,gc, TRx[frame-1]+X_OFF, TRy[frame-1]+Y_OFF, TRx[frame]+X_OFF, TRy[frame]+Y_OFF); XDrawLine(disptr,win,gc, TRx[frame-1]+TR_X_OFF, TRy[frame-1]+TR_Y_OFF, TRx[frame]+TR_X_OFF, TRy[frame]+TR_Y_OFF); XSetLineAttributes(disptr,gc, 0, LineSolid, CapButt, JoinMiter); } frame++; } /* Mark the final TR position w/ a centered dot. */ XGetWindowAttributes(disptr,win, &attr); pmap = XCreatePixmapFromBitmapData(disptr,win, dot_bits, dot_width, dot_height, BlackPixel(disptr,0), WhitePixel(disptr,0), attr.depth); XCopyArea(disptr, pmap, win, gc, 0,0, dot_width,dot_height, x-(dot_width/2), y-(dot_height/2)); XCopyArea(disptr, pmap, win, gc, 0,0, dot_width,dot_height, (x-X_OFF)+TR_X_OFF-(dot_width/2), (y-Y_OFF)+TR_Y_OFF-(dot_height/2)); XFreePixmap(disptr,pmap); } } /* * Make a landmark. */ static XtCallbackProc MakeLM(w, call_data, client_data) Widget w; XtPointer call_data, client_data; { XEvent event; XEvent leave_event; int i,j, virgin; int x,y, old_x, old_y; int xc[8], yc[8]; float UnitScreen(); /* double rint();*/ if (! ScreenInitialized) InitializeScreen(); if (! ((LMx==0) && (LMy==0))) { PaintObject(LMimage, LMx+X_OFF,LMy+Y_OFF); /* Erase old LM */ PaintObject(LMimage, LMx+LM_X_OFF,LMy+LM_Y_OFF); /* Erase old LM */ } if (ChoseCurObj) { LMimage = CurObjimage; strcpy(LMfname, CurObjfname); } XSelectInput(disptr, win, ButtonPressMask | PointerMotionMask ); virgin = TRUE; event.type = KeyPress; while (event.type != ButtonPress) { XWindowEvent(disptr, win, ButtonPressMask | PointerMotionMask, &event); x = event.xbutton.x; y = event.xbutton.y; if (x >= X_OFF && y >= Y_OFF && x <= X_OFF+Window_width && y <= Y_OFF+Window_height) { if ( ! virgin && event.type == MotionNotify ) PaintObject(LMimage, old_x,old_y); /* Erase old one */ PaintObject(LMimage,x,y); old_x = x; old_y = y; virgin = FALSE; } } PaintObject(LMimage,x,y); LMx = x-X_OFF; LMy = y-Y_OFF; PaintObject(LMimage, LMx+LM_X_OFF,LMy+LM_Y_OFF); } /* * Make a trajector. */ static XtCallbackProc MakeTR(w, call_data, client_data) Widget w; XtPointer call_data, client_data; { XEvent event; XEvent leave_event; int i,j, virgin; int x,y, old_x, old_y; int xc[8], yc[8]; float UnitScreen(); /*double rint();*/ if (! ScreenInitialized) InitializeScreen(); if (! ((TRx[0]==0) && (TRy[0]==0))) { PaintObject(TRimage, TRx[0]+X_OFF,TRy[0]+Y_OFF); /* Erase old TR */ PaintObject(TRimage, TRx[0]+TR_X_OFF,TRy[0]+TR_Y_OFF); /* Erase old TR */ } if (ChoseCurObj) { TRimage = CurObjimage; strcpy(TRfname, CurObjfname); } XSelectInput(disptr, win, ButtonPressMask | PointerMotionMask ); virgin = TRUE; event.type = KeyPress; while (event.type != ButtonPress) { XWindowEvent(disptr, win, ButtonPressMask | PointerMotionMask, &event); x = event.xbutton.x; y = event.xbutton.y; if (x >= X_OFF && y >= Y_OFF && x <= X_OFF+Window_width && y <= Y_OFF+Window_height) { if ( ! virgin && event.type == MotionNotify ) /* Erase old one */ PaintObject(TRimage, old_x, old_y); PaintObject(TRimage,x,y); old_x = x; old_y = y; virgin = FALSE; } } PaintObject(TRimage,x,y); TRx[0] = x-X_OFF; TRy[0] = y-Y_OFF; PaintObject(TRimage, TRx[0]+TR_X_OFF,TRy[0]+TR_Y_OFF); } /* * Paint the object on the screen. */ PaintObject(image,x,y) XImage image; int x,y; { XSetState (disptr, gc, BlackPixel(disptr,0), WhitePixel(disptr,0), GXxor, AllPlanes); /* These two lines start causing trouble. */ /* XGetWindowAttributes(disptr,win, &attr); image.depth = attr.depth; */ XPutImage (disptr, win, gc, &image, 0, 0, x-(image.width/2), y-(image.height/2), image.width, image.height); XSetState (disptr, gc, BlackPixel(disptr,0), WhitePixel(disptr,0), GXcopy, AllPlanes); } /* * Repaint the screen. */ static XtCallbackProc RepaintScreen(w, call_data, client_data) Widget w; XtPointer call_data, client_data; { InitializeScreen(); PaintScreen(); } /* * Paint the TR and LM on the screen. */ PaintScreen() { int i, x,y; Pixmap pmap; /* Paint LM. */ PaintObject(LMimage,LMx+LM_X_OFF,LMy+LM_Y_OFF); PaintObject(LMimage,LMx+X_OFF,LMy+Y_OFF); /* Paint TR frames, and connect. */ for (i=0; i 0) { XSetLineAttributes(disptr,gc, 0, LineOnOffDash, CapButt, JoinMiter); XDrawLine(disptr,win,gc, TRx[i-1]+X_OFF, TRy[i-1]+Y_OFF, TRx[i]+X_OFF, TRy[i]+Y_OFF); XDrawLine(disptr,win,gc, TRx[i-1]+TR_X_OFF, TRy[i-1]+TR_Y_OFF, TRx[i]+TR_X_OFF, TRy[i]+TR_Y_OFF); XSetLineAttributes(disptr,gc, 0, LineSolid, CapButt, JoinMiter); } } /* Mark the final TR position w/ a centered dot. */ x = TRx[NumFrames-1] + X_OFF; y = TRy[NumFrames-1] + Y_OFF; XGetWindowAttributes(disptr,win, &attr); pmap = XCreatePixmapFromBitmapData(disptr,win, dot_bits, dot_width, dot_height, BlackPixel(disptr,0), WhitePixel(disptr,0), attr.depth); XCopyArea(disptr, pmap, win, gc, 0,0, dot_width,dot_height, x-(dot_width/2), y-(dot_height/2)); XCopyArea(disptr, pmap, win, gc, 0,0, dot_width,dot_height, (x-X_OFF)+TR_X_OFF-(dot_width/2), (y-Y_OFF)+TR_Y_OFF-(dot_height/2)); XFreePixmap(disptr,pmap); } /* * Read in a screen file. */ int ReadScreenFile (fname,cmd_line_TR,cmd_line_LM) char *fname; int cmd_line_TR, cmd_line_LM; { FILE *infile, *fopen(); char c; int i,j; char junk[80]; int status, success; infile = fopen(fname, "r"); success = (infile != NULL); /* If TR and/or LM was specified on cmd line, that overrides this. */ if (success) { fscanf (infile, "LM: %s %d %d\n", LMfname, &LMx, &LMy); status = ReadBitmapFile (LMfname,&LMimage); if (status != BitmapSuccess) { printf (">> Error: Could not read landmark object file.\n"); exit(1); } fscanf (infile, "TR: %s\n", TRfname); status = ReadBitmapFile (TRfname,&TRimage); if (status != BitmapSuccess) { printf (">> Error: Could not read trajector object file.\n"); exit(1); } fscanf (infile, "%d", &NumFrames); for (i=0; idepth = attr.depth; */ image->width = width; image->height = height; image->data = (char *) data; image->bytes_per_line = (image->width + 7) / 8; return BitmapSuccess; } /* * Converts an x- or y- coord to a float representing the same coords * on the unit screen. */ float UnitScreen(x) int x; { return ( (float) x / (float) Window_width ); } /* * Given an x- or y-coord (0.0 to 1.0), this rounds that to the nearest * fraction compatible with the DIMxDIM tesselation. */ float Nearest(x) float x; { /* float rint();*/ return( rint((float) x * (float) DIM) / (float) DIM ); } /* * Displays a pixmap, centered at x,y (0.0 <= x,y <= 1.0). */ CenterPixmap(fx,fy, pmap, size) float fx,fy; /* coords to center the pixmap at */ Pixmap pmap; int size; /* Width, height (assumed equal) of pmap */ { int x,y; x = (int) (fx * (float) Window_width); y = (int) (fy * (float) Window_height); XCopyArea(disptr, pmap, win, gc, 0,0, size,size, x-(size/2), y-(size/2)); } /* * Select object. */ static XtCallbackProc SelectObject(w, call_data, client_data) Widget w; XtPointer call_data, client_data; { int i,found; found = FALSE; for (i=0; ((i < N_OBJS) && (found == FALSE)); i++) if (w == obj_cmd[i]) { found = TRUE; strcpy(CurObjfname,Objfname[i]); CurObjimage.width = Objimage[i].width; CurObjimage.height = Objimage[i].height; CurObjimage.data = (char *) Objimage[i].data; CurObjimage.bytes_per_line = (Objimage[i].width + 7) / 8; ChoseCurObj = TRUE; } } /* * Quit the program. */ static XtCallbackProc Quit(w, call_data, client_data) Widget w; XtPointer call_data, client_data; { XtDestroyApplicationContext(XtWidgetToApplicationContext(w)); exit(0); } /* * Save data, then quit the program. */ static XtCallbackProc SaveAndQuit(w, call_data, client_data) Widget w; XtPointer call_data, client_data; { FILE *outfile, *fopen(); char header[80]; char htemplate[80]; char cmdstring[80]; int i,j; outfile = fopen(SCfname, "w"); fprintf(outfile, "LM: %s %d %d\n", LMfname, LMx, LMy); fprintf(outfile, "TR: %s\n", TRfname); fprintf(outfile, " %d\n", NumFrames); for (i=0; i