Newer
Older
/*
* UI-related glue functions for partiview.
* Stuart Levy, slevy@ncsa.uiuc.edu
* National Center for Supercomputing Applications,
* University of Illinois 2001.
* This file is part of partiview, released under the
* Illinois Open Source License; see the file LICENSE.partiview for details.
#include "config.h"
#include "winjunk.h"
#endif
#ifdef __APPLE__
#include <OpenGL/gl.h>
#else
#include <GL/gl.h> /* for GLuint */
#endif
#include "geometry.h"
#include "shmem.h"
#include <string.h>
#include <stdarg.h>
#include <math.h>
#include <errno.h>
#include <signal.h>
#include <png.h>
#include "specks.h"
#include "partiview.H"
#include "partiviewc.h"
slevy
committed
#ifndef FLHACK
# include <FL/glut.H> /* for GLUT_STEREO if FLTK knows it */
#endif
#ifndef GLUT_STEREO
# if unix
# include <FL/x.H> /* otherwise, need GLX symbols for X-specific stereo */
# include <GL/glx.h>
# endif
#endif
#include <ctype.h>
#undef isspace /* hack for irix 6.5 */
slevy
committed
#ifdef FLHACK
extern void _pview_pickmsg( const char *fmt, ... );
#endif
void specks_picker( Fl_Gl_Window *junk, int nhits, int nents, GLuint *hitbuf, void *vview )
{
Fl_Gview *view = (Fl_Gview *)vview;
struct stuff *st;
unsigned int bestz = ~0u;
struct stuff *bestst = NULL;
struct specklist *bestsl;
int bestspeckno;
int id, bestid = -1;
Point bestpos, wpos, cpos;
int centerit = Fl::event_state(FL_SHIFT);
for(id = 0; id < MAXSTUFF; id++) {
if((st = stuffs[id]) == NULL) continue;
if(specks_partial_pick_decode( st, id, nhits, nents, hitbuf,
&bestz, &bestsl, &bestspeckno, &bestpos )) {
bestst = st;
bestid = id;
}
}
if(bestst) {
char fmt[1024], wpostr[80];
char attrs[1024];
vtfmpoint( &wpos, &bestpos, view->To2w( bestid ) );
if(memcmp( &wpos, &bestpos, sizeof(wpos) )) {
Stuart Levy
committed
snprintf(wpostr, sizeof(wpostr), " (w%g %g %g)", wpos.x[0],wpos.x[1],wpos.x[2]);
vtfmpoint( &cpos, &wpos, view->Tw2c() );
Stuart Levy
committed
strncpy(fmt, bestsl->bytesperspeck <= SMALLSPECKSIZE(MAXVAL)
? "[g%d]%sPicked %g %g %g%s%.0s @%g (of %d)%s"
Stuart Levy
committed
: "[g%d]%sPicked %g %g %g%s \"%s\" @%g (of %d)%s", sizeof(fmt));
fmt[sizeof(fmt)-1] = '\0';
attrs[0] = '\0';
struct speck *sp = NextSpeck( bestsl->specks, bestsl, bestspeckno);
if(bestsl->text == NULL && bestst->vdesc[bestst->curdata][0].name[0] != '\0') {
strcpy(attrs, ";");
for(int i = 0; i < MAXVAL && bestst->vdesc[bestst->curdata][i].name[0]; i++) {
int pos = strlen(attrs);
snprintf(attrs+pos, sizeof(attrs)-pos, " %s %g",
bestst->vdesc[bestst->curdata][i].name, sp->val[i]);
}
if(bestsl->text != NULL) {
snprintf(attrs+strlen(attrs), sizeof(attrs)-strlen(attrs),
" \"%s\"", bestsl->text);
slevy
committed
#ifdef FLHACK
_pview_pickmsg(fmt, bestid, centerit?"*":"",
bestpos.x[0],bestpos.x[1],bestpos.x[2], wpostr,
bestsl->text ? bestsl->text : sp->title,
vlength( &cpos ), nhits,
attrs );
#else
slevy
committed
bestpos.x[0],bestpos.x[1],bestpos.x[2], wpostr,
bestsl->text ? bestsl->text : sp->title,
vlength( &cpos ), nhits,
slevy
committed
#endif
view->center( &wpos );
if(ppui.censize > 0) view->redraw();
slevy
committed
#ifdef FLHACK
_pview_pickmsg("Picked nothing (%d hits)", nhits);
#else
slevy
committed
#endif
}
}
void draw_specks( Fl_Gview *view, void *vst, void *junk ) {
struct stuff *st = (struct stuff *)vst;
if(st->useme) {
specks_set_timestep( st );
specks_current_frame( st, st->sl );
st->inpick = view->inpick();
drawspecks( st );
st->inpick = 0;
}
void parti_allobjs( int argc, char *argv[], int verbose ) {
struct stuff *st = stuffs[0];
if(parti_parse_args( &st, argc, argv, NULL ))
return;
st = stuffs[i];
const char *onoff = st->useme ? "on" : "off";
if(verbose) {
if(st->alias) msg("g%d=%s: (%s)", i, st->alias, onoff);
else msg("g%d: (%s)", i, onoff);
}
void parti_redraw() {
if(ppui.view) ppui.view->redraw();
slevy
committed
#ifndef FLHACK
if(ppui.hrdiag->visible_r()) ppui.hrdiag->redraw();
slevy
committed
#endif
void parti_update() {
if(ppui.view)
while(ppui.view->damage())
Fl::wait(.1);
}
void parti_censize( float newsize ) {
if(newsize != ppui.censize) ppui.view->redraw();
ppui.censize = newsize;
}
float parti_getcensize() {
return ppui.censize;
}
char *parti_bgcolor( const char *rgb ) {
Point bgcolor;
bgcolor = *ppui.view->bgcolor();
if(rgb) {
if(1 == sscanf(rgb, "%f%*c%f%*c%f", &bgcolor.x[0], &bgcolor.x[1], &bgcolor.x[2]))
bgcolor.x[1] = bgcolor.x[2] = bgcolor.x[0];
ppui.view->bgcolor( &bgcolor );
}
Stuart Levy
committed
snprintf(bgc, sizeof(bgc), "%.3f %.3f %.3f", bgcolor.x[0],bgcolor.x[1],bgcolor.x[2]);
{
view->dspcontext( (detached ? 2 : 0) + (view->stereo() == GV_QUADBUFFERED ? 1 : 0) );
}
#ifdef GLUT_STEREO
static int stereo_mode = FL_STEREO | FL_RGB | FL_DOUBLE | FL_DEPTH | FL_MULTISAMPLE;
int try_quad_stereo()
return(Fl_Gl_Window::can_do( stereo_mode ));
}
#else /* backward compatibility -- quadbuffered stereo under Unix/X only */
static int *stereo_mode = NULL;
slevy
committed
#if defined(unix) && !defined(FLHACK)
#ifdef GLX_SAMPLE_BUFFERS_SGIS
GLX_SAMPLE_BUFFERS_SGIS, 1,
GLX_SAMPLES_SGIS, 4,
#endif
GLX_STEREO,
GLX_RGBA,
GLX_DOUBLEBUFFER,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_DEPTH_SIZE, 1,
None
int try_quad_stereo()
{
stereo_mode = attrs;
if(Fl_Gl_Window::can_do( stereo_mode ))
return 1;
stereo_mode += 4;
if(Fl_Gl_Window::can_do( stereo_mode ))
return 1;
return 0;
}
slevy
committed
#else /* win32 or FLHACK */
int try_quad_stereo() { return 0; }
#endif
char *parti_stereo( const char *ster )
{
static char rslt[28];
static enum Gv_Stereo stereotype = GV_MONO;
static const char *sternames[] = { "mono", "redcyan", "crosseyed", "glasses", "left", "right" };
int smode = -1;
if(stereotype == GV_MONO) {
quadmode = try_quad_stereo();
stereotype = (quadmode!=0) ? GV_QUADBUFFERED : GV_REDCYAN;
if(cp && sscanf(cp+1, "%d", &pixoff)) {
ppui.view->stereooffset(pixoff);
smode = stereotype;
}
ppui.view->stereosep(v);
smode = stereotype;
}
if(strstr(ster,"on"))
smode = stereotype;
if(strstr(ster,"off"))
smode = GV_MONO;
if(strstr(ster, "red"))
smode = stereotype = GV_REDCYAN;
if(strstr(ster, "quad") || strstr(ster, "gla") ||
strstr(ster, "hard") || strstr(ster, "hw")) {
smode = stereotype = GV_QUADBUFFERED;
} else {
msg("Can't do quadbuffered/hardware stereo");
smode = GV_MONO;
}
}
else if(strstr(ster, "left"))
smode = stereotype = GV_LEFTEYE;
else if(strstr(ster, "right"))
smode = stereotype = GV_RIGHTEYE;
msg("stereo: [on|off|redcyan|glasses|crosseyed|left|right] [stereosep[@pixeloffset]]");
msg(" Try stereosep values from 0.02 to 0.1, or -.02 .. -.1 to swap eyes");
}
}
if(smode >= 0) {
if(smode == (int)GV_QUADBUFFERED)
slevy
committed
ppui.view->glmode( stereo_mode );
slevy
committed
ppui.view->glmode( FL_RGB | FL_DOUBLE | FL_DEPTH | FL_MULTISAMPLE );
set_wanted_dspcontext( ppui.view, (ppui.view == ppui.freewin)/*detached*/ );
Stuart Levy
committed
snprintf(rslt, sizeof(rslt), "%g %s",
ppui.view->stereosep(),
(smode<=0||smode>=COUNT(sternames)) ? "off" : sternames[smode]);
Stuart Levy
committed
snprintf(rslt+strlen(rslt), sizeof(rslt)-strlen(rslt), "@%d", pixoff);
int y_root( Fl_Widget *w ) {
if(w == NULL) return -1;
int y = w->y();
Fl_Window *pa;
for(pa = w->window(); pa != NULL; pa = pa->window())
y += pa->y();
return y;
}
Fl_Gview *make_view_window() {
if(ppui.freewin == NULL) {
Fl_Group::current( NULL );
Fl_Double_Window *o = new Fl_Double_Window(512, 512);
ppui.freewin = new Fl_Gview(0, 0, 512, 512);
o->add( ppui.freewin );
Fl_Group::current( NULL );
}
return ppui.freewin;
}
void parti_detachview( const char *how ) {
int seeui = 1;
if(how == NULL) how = "fullscreen";
Fl_Gview *w = ppui.view;
//fprintf(stderr, "detach(%s)\n", how);
switch(how[0]) {
case 'h': /* full screen, hidden UI */
seeui = 0;
case 'f': /* fullscreen detached window */
w = make_view_window();
ppui.freemain->fullscreen();
parti_update();
w->resize( 0, 0, ppui.freemain->w(), ppui.freemain->h() );
break;
case 'd': /* ordinary detached window */
w = make_view_window();
if(ppui.view && ppui.view->w() * ppui.view->h() > 0) {
ppui.freemain->fullscreen_off(50, 50, ppui.view->w(), ppui.view->h());
} else {
ppui.freemain->fullscreen_off(50, 50, 512, 512);
}
ppui.freemain->show();
if(w->window() && w->window()->visible()) w->show();
msg("detach: huh? expected \"detach fullscreen\" or \"detach hide\" or just \"detach\"");
if(w != NULL) {
int mainy0 = y_root( ppui.mainwin );
int viewy0 = y_root( ppui.cmd ) + ppui.cmd->h();
int mainheight = viewy0 - mainy0;
Fl_Widget *resiz = ppui.maintile->resizable();
if(resiz && resiz != ppui.maintile) {
ppui.maintile->resizable(ppui.maintile);
ppui.maintile->remove( resiz );
}
ppui.mainwin->size( ppui.mainwin->w(), mainheight );
ppui.mainwin->init_sizes();
ppui.maintile->init_sizes();
ppui.maintile->redraw();
if(w != ppui.view) {
w->initfrom( ppui.view );
ppui.view = w;
set_wanted_dspcontext( ppui.view, 1 );
/* Fix up dangling references to old view */
ppui.view->picker( specks_picker, ppui.view );
if(ppui.hrdiag) ppui.hrdiag->picker( specks_picker, ppui.view );
}
ppui.detached = how[0]; // 'h' or 'f' or 'd'
parti_redraw();
ppui.boundwin->hide();
if(seeui) {
ppui.mainwin->set_non_modal();
ppui.mainwin->show(); // pop control strip to top
ppui.mainwin->redraw();
} else {
ppui.view->show();
ppui.mainwin->hide();
}
ppui.view->redraw();
/* Is there a main-window-position spec included in our param? */
const char *cp;
for(cp = how; *cp; cp++) {
if(*cp == '-' || *cp == '+') {
char cx[2], cy[2];
int xpos, ypos;
if(4 == sscanf(cp, "%1[-+]%d%1[-+]%d", cx, &xpos, cy, &ypos)) {
Fl_Window *mw = ppui.mainwin;
mw->position( cx[0]=='+' ? xpos : Fl::w() - xpos - mw->w(),
cy[0]=='+' ? ypos : Fl::h() - ypos - mw->h() );
break;
}
}
}
char *parti_winsize( CONST char *newsize ) {
static char cursize[24];
slevy
committed
#ifdef FLHACK
Stuart Levy
committed
snprintf(cursize, sizeof(cursize), "-1x-1");
slevy
committed
#else
int posx = 0, posy = 0, has_pos = 0;
//fprintf(stderr, "winsize(%s)\n", newsize);
Fl_Window *top = (ppui.freewin != NULL) ?
ppui.freemain : ppui.mainwin;
int ox = ppui.view->w(), oy = ppui.view->h();
ox = oy = -1;
}
posx = top->x();
posy = top->y();
if(posp != newsize && sscanf(newsize, "%d%*c%d", &nx, &ny) == 1)
if(posp && 4 == sscanf(posp, "%1[-+]%d%1[-+]%d", cx, &posx, cy, &posy)) {
if(cx[0] == '-') posx = Fl::w() - nx - posx;
if(ox < 0) { /* Not yet available -- remember for later */
strncpy(cursize, newsize, sizeof(cursize)-1);
ppui.reqwinsize = cursize;
return cursize;
}
if(nx != ox || ny != oy || has_pos) {
parti_detachview( ppui.detached=='h' ? "hide" : "detach" );
if(has_pos) top->position( posx, posy );
if(has_pos)
top->position( posx, posy );
top->size( top->w() + nx - ox,
top->h() + ny - oy );
if(top->visible())
ppui.view->show();
parti_update();
return parti_winsize(NULL);
}
}
Stuart Levy
committed
snprintf(cursize, sizeof(cursize), has_pos ? "%dx%d+%d+%d" : "%dx%d", ox, oy, posx, posy);
slevy
committed
#endif
char *parti_clip( const char *nearclip, const char *farclip ) {
float n, f;
int changed = 0;
if(nearclip != NULL && sscanf(nearclip, "%f", &n) > 0) {
changed = 1;
}
if(farclip != NULL && sscanf(farclip, "%f", &f) > 0) {
changed = 1;
}
if(changed && ppui.subcam != 0)
parti_select_subcam( ppui.subcam ); /* recompute subcam projection */
Stuart Levy
committed
snprintf(why, sizeof(why), "clip %.4g %.4g", ppui.view->nearclip(), ppui.view->farclip());
return why;
}
int parti_move( const char *onoffobj, struct stuff **newst ) {
int objno = -1;
if(onoffobj) {
if(!strcmp(onoffobj, "off"))
ppui.view->movingtarget(0);
else if(!strcmp(onoffobj, "on"))
ppui.view->movingtarget(1);
else if(sscanf(onoffobj, "g%d", &objno) > 0 ||
sscanf(onoffobj, "%d", &objno) > 0) {
ppui.view->movingtarget(1);
objno = parti_object( onoffobj, newst, 0 );
} else {
msg("move {on|off|g<N>} -- select whether navigation can move sub-objects");
}
}
return ppui.view->movingtarget() ? ppui.view->target() : -1;
}
float parti_pickrange( char *newrange ) {
if(newrange) {
if(sscanf(newrange, "%f", &ppui.pickrange))
ppui.view->picksize( 4*ppui.pickrange, 4*ppui.pickrange );
}
return ppui.pickrange;
}
static int endswith(const char *str, const char *suf) {
if(str==NULL || suf==NULL) return 0;
int len = strlen(str);
int suflen = strlen(suf);
return suflen <= len && memcmp(suf, str+len-suflen, suflen)==0;
}
int parti_snapset( char *fname, char *frameno, char *imgsize )
#ifdef HAVE_PNG_H
static char suf[] = ".%04d.png";
#elif unix
static char suf[] = ".%04d.ppm.gz";
#else /* WIN32 */
static char suf[] = ".%04d.ppm";
int needsuf;
if(fname) {
len = strlen(fname);
needsuf = strchr(fname, '%')!=NULL || fname[0] == '|'
|| endswith(fname, ".tif") || endswith(fname, ".tiff")
|| endswith(fname, ".sgi") || endswith(fname, ".png")
|| endswith(fname, ".jpeg") || endswith(fname, ".jpg")
|| endswith(fname, ".ppm") || endswith(fname, ".gz")
? 0 : sizeof(suf)-1;
if(ppui.snapfmt) Free(ppui.snapfmt);
ppui.snapfmt = NewN(char, len+needsuf+1);
Stuart Levy
committed
snprintf(ppui.snapfmt, len+needsuf+1, needsuf ? "%s%s" : "%s", fname, suf);
}
if(frameno)
sscanf(frameno, "%d", &ppui.snapfno);
return ppui.snapfno;
}
slevy
committed
#ifdef HAVE_JPEGLIB_H
/* jpeg image snapshotting */
#ifdef WIN32
typedef unsigned char boolean;
#endif
slevy
committed
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
extern "C" {
#include <jpeglib.h>
};
static struct jpeg_compress_struct cinfo;
static struct jpeg_error_mgr jerr;
struct my_error_mgr {
struct jpeg_error_mgr pub; /* "public" fields */
jmp_buf setjmp_buffer; /* for return to caller */
};
typedef struct my_error_mgr * my_error_ptr;
static struct my_error_mgr myjerr;
static void snapjpegerr(j_common_ptr cinfo)
{
my_error_ptr myerr = reinterpret_cast<my_error_ptr>(cinfo->err);
/* Return control to the setjmp point */
longjmp(myerr->setjmp_buffer, 1);
}
static int snapjpeg( char *outfname, int xsize, int ysize, char *rgbbuf )
{
FILE *outf = fopen(outfname, "wb");
if(outf == 0) {
msg("Can't open output image %s", outfname);
return 1;
}
cinfo.err = jpeg_std_error(reinterpret_cast<jpeg_error_mgr*>(&myjerr));
jpeg_create_compress(&cinfo);
cinfo.image_width = xsize; /* image width and height, in pixels */
cinfo.image_height = ysize;
cinfo.input_components = 3; /* # of color components per pixel */
cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, ppui.jpegqual, TRUE/*force_baseline*/);
cinfo.err = jpeg_std_error(&myjerr.pub);
myjerr.pub.error_exit = snapjpegerr;
/* Establish the setjmp return context for my_error_exit to use. */
if (setjmp(myjerr.setjmp_buffer)) {
/* If we get here, the JPEG code has signaled an error.
* We need to clean up the JPEG object, close the input file, and return.
*/
/* Display the error message too. */
(*cinfo.err->output_message) (reinterpret_cast<jpeg_common_struct*>(&cinfo));
jpeg_destroy_compress(&cinfo);
fclose(outf);
return 1;
}
jpeg_stdio_dest(&cinfo, outf);
jpeg_start_compress(&cinfo, TRUE);
while(cinfo.next_scanline < cinfo.image_height) {
JSAMPROW rowptr[1];
rowptr[0] = reinterpret_cast<JSAMPROW>(&rgbbuf[(cinfo.image_height - 1 - cinfo.next_scanline) * xsize*3]);
slevy
committed
jpeg_write_scanlines(&cinfo, rowptr, 1);
}
jpeg_finish_compress(&cinfo);
int iook;
iook = fclose(outf);
jpeg_destroy_compress(&cinfo);
return iook ? 1 : 0; /* return 1 if fclose() reported error, 0 if success */
}
#endif /*HAVE_JPEGLIB_H*/
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
#ifdef HAVE_PNG_H
/* png image snapshotting */
static png_structp png_ptr = NULL;
static png_infop info_ptr = NULL;
static void failpng() {
png_destroy_write_struct(&png_ptr, &info_ptr);
msg("snapshot: error writing png header");
}
/* returns 0 on success, nonzero on failure */
static int snappng( char *outfname, int xsize, int ysize, char *rgbbuf )
{
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr)
info_ptr = png_create_info_struct(png_ptr);
if(!info_ptr) {
msg("snapshot: can't init png library");
return 1;
}
if(setjmp(png_jmpbuf(png_ptr))) {
failpng();
return 1;
}
FILE *outf = fopen( outfname, "wb" );
if(outf == 0) {
return 1;
}
png_init_io( png_ptr, outf );
png_set_IHDR( png_ptr, info_ptr,
xsize, ysize, 8,/*bit depth*/
PNG_COLOR_TYPE_RGB,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
/* Don't really know that we're in sRGB color space, but let's say so anyway. */
Stuart Levy
committed
// png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, PNG_INFO_sRGB);
png_write_info( png_ptr, info_ptr );
png_bytep *rowps = new png_bytep[ysize];
for(int k = 0; k < ysize; k++)
png_write_image( png_ptr, rowps );
Stuart Levy
committed
delete[] rowps;
png_write_end(png_ptr, info_ptr);
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(outf);
return 0;
}
#endif /* HAVE_PNG_H */
Stuart Levy
committed
int parti_snapshot( char *snapinfo, int room )
char tfcmd1[10240], tfcmd2[10240], *tftail;
slevy
committed
enum imtype { AS_PNG, AS_JPEG, AS_OTHER } astype = AS_OTHER;
#if defined(HAVE_PNG_H) || !WIN32
static char defsnap[] = "snap.%04d.png";
#else
static char defsnap[] = "snap.%04d.ppm";
#endif
#if !WIN32 /* if unix */
static char prefix[] = "|convert ppm:- ";
static char gzprefix[] = "|gzip >";
#else
static char prefix[] = "";
#endif
if(snapinfo) snapinfo[0] = '\0';
if(ppui.snapfmt == NULL) {
ppui.snapfmt = NewN(char, sizeof(defsnap)+1);
if(ppui.snapfmt[0] == '|' || endswith(ppui.snapfmt, ".ppm")) {
tfcmd1[0] = '\0';
#ifdef HAVE_PNG_H
} else if(endswith(ppui.snapfmt, ".png")) {
/* use built-in libpng writer if available */
slevy
committed
astype = AS_PNG;
tfcmd1[0] = '\0';
slevy
committed
#endif
#ifdef HAVE_JPEGLIB_H
} else if(endswith(ppui.snapfmt, ".jpeg") || endswith(ppui.snapfmt, ".jpg")) {
/* use built-in libjpeg writer if available */
astype = AS_JPEG;
tfcmd1[0] = '\0';
#endif
} else if(endswith(ppui.snapfmt, ".ppm.gz")) {
strcpy(tfcmd1, gzprefix);
strcpy(tfcmd1, prefix);
tftail = tfcmd1+strlen(tfcmd1);
Stuart Levy
committed
snprintf(tftail, tftail+sizeof(tfcmd1)-tftail, ppui.snapfmt, ppui.snapfno);
if(!ppui.view || !ppui.view->visible_r()) {
msg("snapshot: no visible graphics window?");
return -2;
}
Fl_Widget *pa;
for(pa = ppui.view; pa->parent(); pa = pa->parent())
;
bool snapstereo = (strchr(tfcmd1, '@') != NULL);
enum Gv_Stereo stereowas = ppui.view->stereo();
char *tfcmd = snapstereo ? tfcmd2 : tfcmd1;
int y, h = ppui.view->h(), w = ppui.view->w();
char *buf = (char *)malloc(w*h*3);
for(int eye = 0; eye < (snapstereo ? 2 : 1); eye++) {
char eyech = 'L';
if(snapstereo) {
ppui.view->stereo( eye==0 ? GV_LEFTEYE : GV_RIGHTEYE );
strcpy(tfcmd, tfcmd1);
// replace all instances of "@" with "L" or "R"
char eyech = eye==0 ? 'L' : 'R';
for(char *s = tfcmd; (s = strchr(s, '@')) != NULL; s++)
*s = eyech;
}
// Ensure window's image is up-to-date
parti_update();
if(!ppui.view->snapshot( 0, 0, w, h, buf )) {
free(buf);
msg("snapshot: couldn't read from graphics window?");
fail = -2;
break;
}
switch(astype) {
case AS_PNG:
#ifdef HAVE_PNG_H
fail = snappng( tfcmd, w, h, buf );
#endif
break;
slevy
committed
#ifdef HAVE_JPEGLIB_H
case AS_JPEG:
fail = snapjpeg( tfcmd, w, h, buf );
break;
slevy
committed
#endif
default:
/* write ppm stream/file */
FILE *p;
void (*oldpipe)(int) = 0;
int popened = tfcmd[0] == '|';
if(popened) {
oldpipe = signal(SIGPIPE, SIG_IGN);
p = popen(tfcmd+1, "w");
} else {
p = fopen(tfcmd, "wb");
}
fprintf(p, "P6\n%d %d\n255\n", w, h);
for(y = h; --y >= 0 && fwrite(&buf[w*3*y], w*3, 1, p) > 0; )
;
fflush(p);
fail = ferror(p) || y >= 0;
if(popened) {
pclose(p);
signal(SIGPIPE, oldpipe);
}
else
fclose(p);
slevy
committed
#else /* win32 */
p = fopen(tfcmd, "wb");
slevy
committed
fprintf(p, "P6\n%d %d\n255\n", w, h);
for(y = h; --y >= 0 && fwrite(&buf[w*3*y], w*3, 1, p) > 0; )
;
fflush(p);
fail = ferror(p) || y >= 0;
fclose(p);
/* end of "write ppm" case */
break;
}
if(fail) {
msg("snapshot: Error writing to %s", tfcmd);
break;
}
if(snapstereo) // restore changed stereo setting
ppui.view->stereo( stereowas );
if(snapinfo) {
if(fail)
Stuart Levy
committed
snprintf(snapinfo, room, "failed snapping %.900s", tftail);
else if(snapstereo)
Stuart Levy
committed
snprintf(snapinfo, room, "%.1000s [%dx%d] @ => stereo L,R", tftail, w, h);
else
Stuart Levy
committed
snprintf(snapinfo, room, "%.1000s [%dx%d]", tftail, w, h);
return fail ? -1 : ppui.snapfno++;
const char *parti_get_alias( struct stuff *st ) {
return st && st->alias ? st->alias : "";
}
/*
* This is how new objects get created -- via "object g<N>" command.
*/
int parti_object( const char *objname, struct stuff **newst, int create ) {
int gname = 0;
if(newst)
*newst = ppui.st;
if(objname == NULL) {
if(!strcmp(objname, "c") || !strcmp(objname, "c0")) {
ppui.view->target( GV_ID_CAMERA );
c = '=';
if(( /* accept gN or gN=... or N or N=... or [gN] */
((sscanf(objname, "g%d%c", &i, &c) > 0 || sscanf(objname, "%d%c", &i, &c) > 0) && c == '=')
gname = 1;
} else {
for(i = MAXSTUFF; --i >= 0; ) {
if(stuffs[i] && stuffs[i]->alias && !strcmp(stuffs[i]->alias, objname))
break;
}
}
if(i == -1 && create && !gname) {
for(i = 1; i < MAXSTUFF && stuffs[i]; i++)
;
}
if(i >= MAXSTUFF) {
msg("Oops, can only have objects g1..g%d", MAXSTUFF-1);
}
if(i > 0) {
if(stuffs[i] == NULL) {
stuffs[i] = specks_init( 0, NULL );
ppui.view->add_drawer( draw_specks, stuffs[i], NULL, NULL, i );
ppui.view->picker( specks_picker, ppui.view );
Stuart Levy
committed
snprintf(tname, sizeof(tname), "[g%d]", i);
int me = ppui.obj->add( strdup(tname) );
((Fl_Menu_Item *)ppui.obj->menu())[me].labelcolor( ppui.obj->labelcolor() );
if(!gname)
parti_set_alias(stuffs[i], (char *)objname);
}
ppui.st = stuffs[i];
ppui.view->target( i );
ppui_refresh( ppui.st );
if(newst) *newst = stuffs[i];
return i;
}
msg("Don't understand object name \"%s\"", objname);
int parti_idof( struct stuff *st ) {
for(int i = 0; i < MAXSTUFF; i++)
if(stuffs[i] == st) return i;
float parti_focal( CONST char *newfocal ) {
float focallen;
if(newfocal && sscanf(newfocal, "%f", &focallen) > 0)
ppui.view->focallen( focallen );
return ppui.view->focallen();
}
int parti_focalpoint( int argc, char **argv, Point *focalpoint, float *minfocallen )
{
int ison;
Point fpt;
float mlen;
int changed = 0;
ison = ppui.view->focalpoint( &fpt, &mlen );
if(argc > 0) {
if(isalpha(argv[0][0])) {
int nowon = getbool(argv[0], -1);
if(nowon < 0)
argc = 0;
else {
ison = nowon;
changed = 1;
argc--;
argv++;
}
}
if(getfloats( &fpt.x[0], 3, 0, argc, argv ) ||
getfloats( &mlen, 1, 3, argc, argv ) ||
changed)