Newer
Older
/*
* Main program for FLTK-based 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 <stdio.h>
#include <stdlib.h>
#include "config.h"
#ifdef WIN32
# include "winjunk.h"
#endif
#include "Gview.H"
#include "partiview.H"
#include "shmem.h"
#include <string.h>
#include <stdarg.h>
#include <math.h>
#include <errno.h>
#include "findfile.h"
# include <FL/Fl.H>
# include <FL/fl_draw.H>
# include "genericslider.H" //steven marx: generic slider introduced version 0.7.02
# include <FL/Fl_Tooltip.H> //steven marx: version 0.7.02 now using fltk-1.1.2
# if HAVE_OLD_FILE_CHOOSER_H
# include <FL/fl_file_chooser.H> /* fltk 1.0.* and 1.1.rcX for X<6 */
# else
# include <FL/Fl_File_Chooser.H> /* fltk 1.1.0rc6 and later */
# endif
#include <FL/glut.H> // for GLUT_MULTISAMPLE if fltk knows it
#ifdef EMBEDHACK
# include "pview_funcs.h"
#endif
extern "C" { extern void plugin_init(); }
struct stuff *stuffs[MAXSTUFF];
static int specks_commandstr( struct stuff **stp, const char *str ) {
if(stp == NULL || *stp == NULL || str == NULL)
return 0;
#define MAXARGS 128
char *av[MAXARGS];
int ac;
char *txt = (char *)alloca( strlen(str) + 1 );
char *s = txt;
strcpy(txt, str);
for(ac = 0; ac < MAXARGS-1; ac++) {
av[ac] = strtok(s, " \t\n");
if(av[ac] == NULL) break;
s = NULL;
}
av[ac] = NULL;
return specks_parse_args( stp, ac,av);
}
int specks_commandfmt( struct stuff **stp, const char *fmt, ... ) {
int ok;
va_list args;
va_start(args, fmt);
vsprintf(cmd, fmt, args);
va_end(args);
for(cp = cmd; isspace(*cp); cp++)
;
if(*cp == '\0') return 1; // accept null command implicitly
ok = specks_commandstr( stp, cmd );
if(ok) parti_redraw();
else msg("Unrecognized control command: %s", cmd);
return ok;
}
/* =================================================================== */
void pp_clk_init() {
ppui.clk = NewN( SClock, 1 );
clock_init( ppui.clk );
clock_set_speed( ppui.clk, 1.0 );
ppui.clk->continuous = 1; // is this used?
ppui.clk->walltimed = 1;
}
void pp_ui_postinit() {
parti_set_timebase( ppui.st, 0.0 );
parti_set_timestep( ppui.st, 0.0 );
parti_set_running( ppui.st, 0 );
parti_set_fwd( ppui.st, 1 );
ppui.stepspeed->logstyle( FL_LOG_LINEAR );
ppui.stepspeed->truebounds( 1.0e-6, 10.0 );
ppui.stepspeed->truevalue( clock_speed( ppui.clk ) );
if(ppui.detached) {
char code[2] = { ppui.detached, '\0' };
parti_detachview(code);
}
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#ifdef FLHACK
void ppui_refresh()
{ }
#else /* !FLHACK */
void pp_nav_init(Fl_Menu_Button *);
int pp_viewevent_cb( Fl_Gview *, int ev );
int gensliderchg = 0; //steven marx: generic slider introduced version 0.7.02
void pp_ui_init() {
pp_nav_init(ppui.nav);
pp_sldtype_init(ppui.sldtype); //steven marx: version 0.7.02
genericslider_initparam(); //steven marx: version 0.7.02
/* ppui.cmd->handle_cb = pp_cmd_handle_cb; No, this doesn't work yet */
ppui.view->eventhook = pp_viewevent_cb;
parti_inertia( 1 );
if(getenv("CMDFONT"))
ppui.cmdhist->scaletext( atoi( getenv("CMDFONT") ) );
ppui.freewin = NULL;
ppui.boundwin = ppui.view;
ppui.detached = 0;
#ifdef DEFAULT_ELUMENS
ppui.detached = 'f';
#endif
}
void pp_cmd_cb( HistInput* inp, void * ) {
if(inp->hist())
inp->hist()->addline( inp->value(), 0 );
const char *cp;
for(cp = inp->value(); isspace(*cp); cp++)
;
if(*cp == '\0')
return; // accept null command implicitly
int ok = specks_commandstr( &ppui.st, inp->value() );
if(!ok)
msg("Unrecognized control command: %s", inp->value());
parti_redraw();
genericslider_setparam(); //steven marx version 0.7.02 update generic slider
}
static enum Gv_Nav codes[] = { GV_FLY, GV_ORBIT, GV_ROTATE, GV_TRANSLATE };
static char *navtitles[] = {"[f]ly","[o]rbit","[r]ot","[t]ran"};
void pp_nav_init(Fl_Menu_Button *m) {
m->add("[f]ly|[o]rbit|[r]ot|[t]ran");
for(int i = m->size(); --i >= 0; )
(((Fl_Menu_Item *)(m->menu()))[i]).labelcolor( m->labelcolor() );
}
void pp_nav_cb(Fl_Menu_Button* m, struct stuff **vst) {
int v = m->value();
if(v >= 0 && v < COUNT(codes))
ppui.view->nav( codes[v] );
}
void pp_obj_cb(Fl_Menu_Button* m, void *) {
parti_object( m->text(), &ppui.st, 0 );
}
void pp_objtog_cb(Fl_Button* b, void *) {
int objno = 1;
sscanf(b->label(), "g%d", &objno);
if(objno<0||objno>=MAXSTUFF||stuffs[objno]==NULL)
return;
//================ marx added version 0.7.04 to support 1 button mac mouse ======================
#ifndef __APPLE__
#else
if( (Fl::event_button() == FL_RIGHT_MOUSE) || ((Fl::event_button() == FL_LEFT_MOUSE) && Fl::event_alt()) ) {
#endif
//================ end 1 button mac mouse =======================================================
parti_object( b->label(), &ppui.st, 0 );
b->value(1);
} else {
stuffs[objno]->useme = !stuffs[objno]->useme;
}
parti_redraw();
void pp_genericslider_cb(Fl_Value_Slider* sl, void*) { //steven marx: version 0.7.02
gensliderchg = 1;
genericslider_setparam();
gensliderchg = 0;
}
void pp_slum_cb(Fl_Value_Slider* sl, struct stuff ** ) {
struct stuff *st = ppui.st;
int cd = st->curdata, by = st->sizedby;
if((unsigned int)cd >= MAXFILES) cd = 0;
if((unsigned int)by >= MAXVAL+1) by = 0;
struct valdesc *vd = &st->vdesc[cd][by];
vd->lum = pow(10., sl->value());
ppui.view->redraw();
}
double sign = reinterpret_cast<long>(stepsign);
switch(Fl::event_button()) {
case FL_RIGHT_MOUSE: sign *= 10; break;
case FL_MIDDLE_MOUSE: sign *= 0.1; break;
}
clock_step( ppui.st->clk, sign );
parti_redraw();
clock_set_fwd( ppui.st->clk, reinterpret_cast<long>(stepsign) );
parti_set_running( ppui.st, runbtn->value() );
parti_set_timestep( ppui.st, v + ppui.timebasetime );
parti_redraw();
}
}
void pp_timebaseinput_cb( Fl_Input *inp, void * ) {
double newbase;
}
}
void pp_jog_cb( Fl_Roller *rol, void * ) {
static double lastrol;
double v = rol->value();
specks_set_timestep( ppui.st );
parti_set_timestep( ppui.st, clock_time( ppui.st->clk ) );
parti_redraw();
void pp_feed_cb( Fl_Light_Button *, void * ) {
msg("can't feed yet...");
}
void pp_settrip_cb( Fl_Button *, void * ) {
char str[32];
ppui.timebasetime = clock_time( ppui.st->clk );
ppui.timestep->value( "0" );
sprintf(str, "%.16lg", ppui.timebasetime);
ppui.timebase->value(str);
}
void pp_backtrip_cb( Fl_Button *, void * ) {
clock_set_time( ppui.st->clk, ppui.timebasetime );
ppui.timestep->value( "0" );
parti_redraw();
}
void pp_stepspeed_cb( Fl_Log_Slider *spd, void * ) {
double speed = spd->truevalue();
clock_set_speed( ppui.st->clk, speed );
void pp_rdata_cb( Fl_Button *, struct stuff ** ) {
const char *result;
result = fl_file_chooser("Choose virdir .wf path", "*.wf", NULL);
if (result)
}
void pp_playframe_cb( Fl_Counter *counter, struct stuff ** ) {
if(ppui.playing)
parti_play( "stop" );
parti_setframe( (int)counter->value() );
}
void pp_playtime_cb( Fl_Value_Slider *slider, struct stuff ** ) {
struct wfpath *path = &ppui.path;
if(ppui.playing)
parti_play( "stop" );
parti_setframe( (int) (slider->value() * path->fps + path->frame0) );
}
void pp_play_cb( Fl_Button *play, struct stuff ** ) {
if(Fl::event_state(FL_BUTTON3)) {
ppui.playmenu->popup();
} else {
play->value() ? NULL /*play at default speed*/
: "stop"
);
}
}
int pp_viewevent_cb( Fl_Gview *view, int ev ) {
char snapinfo[1024];
int fno;
double bump;
struct stuff *st = ppui.st;
if(ev == FL_KEYBOARD || ev == FL_SHORTCUT) {
if(ppui.cmdhist && ppui.cmdhist->handle_nav(ev))
return 1;
switch(Fl::event_key()) {
case FL_Print:
if(view->num.has) {
ppui.snapfno = view->num.value();
view->num.has = 0;
}
fno = parti_snapshot(snapinfo);
if(fno >= 0)
msg("Snapped %s", snapinfo);
return 1;
}
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
case '\t':
if(!ppui.cmdhist || !ppui.cmdhist->input())
return 0;
ppui.cmdhist->input()->take_focus();
return 1;
case 'S':
if(view->num.has) {
float v = view->num.fvalue();
if(v == 0) {
parti_stereo("off");
} else {
if(fabs(v) < 1) /* plausible? */
view->stereosep( v );
parti_stereo("on");
}
view->num.has = 0;
} else {
parti_stereo( view->stereo()==GV_MONO ? "on" : "off" );
}
msg("stereo %s (focallen %g)",
parti_stereo(NULL), view->focallen());
return 1;
case '>': bump = 1; goto step;
case '<': bump = -1;
step:
parti_redraw();
case '~':
if(clock_running(st->clk)) {
} else {
int fwd = -clock_fwd( st->clk );
clock_set_fwd( st->clk, fwd );
parti_set_fwd( st, fwd );
case 'z':
case 'Z':
if(view->num.has) {
specks_set_speed( st, view->num.fvalue() );
view->num.has = 0;
} else {
specks_set_speed( st,
clock_speed(st->clk) * (key=='z' ? .5 : 2) );
}
clock_set_step( st->clk, 0.1 * clock_speed(st->clk) );
return 1;
case CTRL('K'):
if(view->num.has) {
ppui.cmdhist->scaletext( view->num.fvalue() );
view->num.has = 0;
}
return 1;
case CTRL('T'):
msg("%.4g fps", ppui.view->fps());
return 1;
}
}
return 0;
}
static void fitlabel( Fl_Widget *w, int excess = 4 ) {
#ifdef __APPLE__
int width = (int)fl_width( w->label(), strlen(w->label()) ) + excess; //marx added the strlen param
w->hide();
w->size( width, w->h() );
w->show();
#else
int ofont = fl_font(), osize = fl_size();
fl_font( w->labelfont(), w->labelsize() );
int width = (int)fl_width( w->label()) + excess; //marx added the strlen param
w->hide();
w->size( width, w->h() );
w->show();
fl_font(ofont, osize);
void ppui_refresh( struct stuff *st ) {
if(ppui.view == NULL) return;
/* Possibly switch selected object */
int targ = ppui.view->target();
if(targ >= 0 && targ < MAXSTUFF && stuffs[targ] != NULL && stuffs[targ] != ppui.st) {
st = ppui.st = stuffs[targ];
}
enum Gv_Nav nav = ppui.view->nav();
for(int navcode = 0; navcode < COUNT(codes); navcode++) {
if(codes[navcode] == nav) {
ppui.nav->value( navcode );
if(strcmp(ppui.nav->label(), navtitles[navcode])) {
ppui.nav->label( navtitles[navcode] );
ppui.toprow->parent()->redraw();
if(ppui.view->inertia()) ppui.inertiaon->set();
else ppui.inertiaon->clear();
for(tno = 0; tno < MAXSTUFF; tno++) {
struct stuff *tst = stuffs[tno];
if(tst == NULL) continue;
maxobject = tno;
if(!timeshown && tst->clk->tmin != tst->clk->tmax) {
ppui.steprow->show();
ppui.steprow->parent()->hide(); // force top-level Pack to be redraw()n
ppui.steprow->parent()->show(); // for some reason just ->redraw() doesn't.
if(ppui.st == stuffs[tno]) {
char oname[12];
Fl_Font lfont = ppui.view->movingtarget()
? FL_HELVETICA_BOLD_ITALIC
: FL_HELVETICA;
sprintf(oname, "[g%d]", tno);
if(strcmp(ppui.obj->label(), oname) || lfont != ppui.obj->labelfont()) {
ppui.obj->label( strdup( oname ) );
// Iff we might actually move the target object,
// display its [gN] title in BOLD ITALICs.
ppui.obj->labelfont( lfont );
ppui.obj->parent()->redraw();
}
}
}
if(st == NULL)
return;
if(ppui.objgroup->active() != st->useme) {
if(st->useme) ppui.objgroup->activate();
else ppui.objgroup->deactivate();
}
// objtogs is wrapped in a Group which is invisible by default.
if(!ppui.objtogs->parent()->visible() && maxobject > 1) {
ppui.objtogs->parent()->show();
ppui.steprow->parent()->hide(); // force top-level Pack to be redraw()n
ppui.steprow->parent()->show(); // for some reason just ->redraw() doesn't.
}
if(ppui.objtogs->visible()) {
Fl_Button *b, *b0 = (Fl_Button *)ppui.objtogs->child(0);
for(tno = 0; tno <= maxobject; tno++) {
if(tno >= ppui.objtogs->children()) {
char name[8];
sprintf(name, "g%d", tno);
b = new Fl_Button( b0->x(),b0->y(),b0->w(),b0->h(), strdup(name) );
b->labelcolor( b0->labelcolor() );
b->labelfont( b0->labelfont() );
b->labelsize( b0->labelsize() );
b->color( b0->color() );
b->selection_color( b0->selection_color() );
b->down_box( b0->down_box() );
b->type( b0->type() );
b->callback( (Fl_Callback*)pp_objtog_cb );
b->when(FL_WHEN_RELEASE_ALWAYS); //marx: release 0.7.06 - allows data group buttons callback to respond when inflight
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
ppui.objtogs->add( b );
}
b = (Fl_Button *)ppui.objtogs->child(tno);
if(stuffs[tno] == NULL) {
if(b->visible()) b->hide();
} else {
if((b->value() != 0) != stuffs[tno]->useme)
b->value( stuffs[tno]->useme );
if(!b->visible()) b->show();
}
}
}
ppui.point->value( st->usepoint );
ppui.poly->value( st->usepoly );
ppui.label->value( st->usetext );
ppui.texture->value( st->usetextures );
ppui.box->value( st->useboxes!=0 );
int boxcolor = ( st->useboxes==2 ? 1/*red*/ : 2/*green*/ );
if(boxcolor != ppui.box->color2()) {
ppui.box->color2( boxcolor );
ppui.box->redraw();
}
int cd = st->curdata, by = st->sizedby;
if((unsigned int)cd >= MAXFILES) cd = 0;
if((unsigned int)by >= MAXVAL+1) by = 0;
struct valdesc *vd = &st->vdesc[cd][by];
float lum = vd->lum;
if(lum <= 0) lum = 1;
ppui.slum->value( log10( lum ) );
char slumlabel[50], *ep = slumlabel;
if(parti_get_alias(st)[0]) {
ep = slumlabel + sprintf(slumlabel, "[%.17s] ", parti_get_alias(st));
}
if(by == CONSTVAL) {
sprintf( ep, "logslum %g", vd->lmin );
} else if(st->vdesc[cd][by].name[0]) {
sprintf( ep, "logslum %.10s", vd->name );
} else {
sprintf( ep, "logslum(field%d)", by );
}
if(strcmp(ppui.slum->label(), slumlabel)) {
static char slumlab[50];
strcpy(slumlab, slumlabel);
ppui.slum->label(slumlab);
ppui.slum->parent()->redraw();
//steve marx version 0.7.02 support for generic slider. provides update to generic slider label upon data group change
int menunum = ppui.sldtype->value();
if(menunum >= 0 && menunum < NUMSLD && menunum != SLUM)
genericslider_setparam();
}
}
void pp_viewchanged( Fl_Gview *gview, void *st ) {
ppui_refresh( ppui.st );
void pp_hrdiag_on_cb( Fl_Menu_ *menu, void * ) {
const Fl_Menu_Item *item = menu->mvalue();
if(ppui.hrdiag == NULL || ppui.hrdiagwin == NULL) return;
parti_hrdiag_on( item->value() );
void pp_inertia_on_cb( Fl_Menu_ *menu, void * ) {
const Fl_Menu_Item *item = menu->mvalue();
ppui.view->inertia( item->value() );
msg("inertia %s", ppui.view->inertia() ? "on" : "off");
int pp_read( struct stuff **, int argc, char *argv[], char *fromfname, void * ) {
if(!strcmp( argv[0], "subcam")) {
if(argc == 3 && 0==strcmp(argv[1],"-tilt")) {
ppui.sctilt = atof(argv[2]);
return 1;
}
if(argc >= 9) {
parti_make_subcam( argv[1], argc-2, argv+2 );
} else {
msg("subcam: expected <name> <az> <el> <rol> <L> <R> <B> <T>, or -tilt <degrees>. What's \"%s\"",
rejoinargs( 1, argc, argv ));
}
return 1;
}
return 0;
}
static int whichobjname( const char *str ) {
if(str == NULL) return -1;
if(str[0] == '[') str++;
int objno = -1;
sscanf(str, "g%d", &objno);
return objno;
}
void parti_set_alias( struct stuff *st, CONST char *alia ) {
if(alia == NULL) alia = "";
char *alias = strdup(alia);
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
if(st->alias) free(st->alias);
st->alias = alias;
#ifndef FLHACK
int slotno, menuno, btno;
for(slotno = 0; slotno < MAXSTUFF; slotno++) {
if(stuffs[slotno] == st) {
char lbl[32];
sprintf(lbl, "[g%d]%.24s", slotno, alias);
for(menuno = ppui.obj->size()-1; --menuno >= 0; ) {
if(whichobjname( ppui.obj->text(menuno) ) == slotno) {
ppui.obj->replace( menuno, strdup(lbl) );
break;
}
}
sprintf(lbl, alias[0]=='\0' ? "g%d" : "g%d=%.24s", slotno, alias);
for(btno = ppui.objtogs->children(); --btno >= 0; ) {
Fl_Button *btn = (Fl_Button *)(ppui.objtogs->child(btno));
if(btn && whichobjname( btn->label() ) == slotno) {
btn->label( strdup(lbl) );
fitlabel( btn, 8 );
break;
}
}
}
}
#endif /*!FLHACK*/
}
int vmsg( const char *fmt, va_list args ) {
#ifdef HAVE_SNPRINTF
vsnprintf(str, sizeof(str), fmt, args);
#else
vsprintf(str, fmt, args);
#ifndef FLHACK
if(gensliderchg) //steven marx: version 0.7.02 - we don't want voluminous generic slider output
return 0;
if(ppui.cmdhist)
ppui.cmdhist->addline( str, 1 );
return printf("%s\n", str);
#elif defined(EMBEDHACK)
_pviewmsg = _pviewmsg + str + "\n";
return 1;
#else
return 1; /* FLHACK but not EMBEDHACK */
#endif /*FLHACK*/
va_list args;
va_start(args, fmt);
val = vmsg( fmt, args );
va_end(args);
return val;
}
void warn( const char *fmt, ... ) {
va_list args;
static char avoid[] = "X_ChangeProperty: "; /* ignore spurious X errors */
if(0==strncmp(fmt, avoid, sizeof(avoid)-1))
return;
va_start(args, fmt);
vmsg(fmt, args);
void parti_lighting() {
static GLuint lightlist = 0;
if(lightlist > 0) {
glCallList( lightlist );
return;
}
lightlist = glGenLists( 1 );
glNewList( lightlist, GL_COMPILE_AND_EXECUTE );
static GLfloat lmambient[] = { 0.1, 0.1, 0.1, 1.0 };
static GLfloat amblight[] = { 0.1, 0.1, 0.1, 1.0 };
static GLfloat whitelight[] = { 1, 1, 1, 1 };
static GLfloat Ce[] = { 0, 0, 0, 1 };
static GLfloat Ca[] = { 1, 1, 1, 1 };
static GLfloat Cd[] = { 1, 1, 1, 1 };
static GLfloat Cs[] = { 1, 1, 1, 1 };
static GLfloat lightpos[3][4] = {
{ 0, 0, -1, 0 },
{ 1, 0, -.5, 0 },
{ 0, 1, 0, 0 },
};
glShadeModel( GL_SMOOTH );
glLightModeli( GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE );
glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE );
glLightModelfv( GL_LIGHT_MODEL_AMBIENT, lmambient );
glDisable( GL_LIGHTING );
int i;
for(i = 0; i < 8; i++)
glDisable( GL_LIGHT0+i );
glLightfv( GL_LIGHT0+i, GL_AMBIENT, amblight );
glLightfv( GL_LIGHT0+i, GL_SPECULAR, whitelight );
glLightfv( GL_LIGHT0+i, GL_DIFFUSE, whitelight );
glLightfv( GL_LIGHT0+i, GL_POSITION, lightpos[i] );
glEnable( GL_LIGHT0+i );
}
glMaterialfv( GL_FRONT_AND_BACK, GL_EMISSION, Ce );
glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT, Ca );
glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, Cd );
glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, Cs );
glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, 32.0 );
glColorMaterial( GL_FRONT_AND_BACK, GL_DIFFUSE );
glDisable( GL_COLOR_MATERIAL );
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glDisable( GL_BLEND );
glEndList();
}
void drawjunk(Fl_Gview *view, void *obj, void *arg) {
static Point xyz[3] = {{1,0,0}, {0,1,0}, {0,0,1}};
static Point nxyz[3] = {{-1,0,0}, {0,-1,0}, {0,0,-1}};
static Point zero = {0,0,0};
static float white[3] = {1,1,1};
float censize = parti_getcensize();
int i;
if(ppui.drawtrace)
(*ppui.drawtrace)();
parti_lighting();
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
glDisable(GL_LIGHTING);
if(censize > 0) {
glPushMatrix();
glScalef(censize,censize,censize);
glBegin(GL_LINES);
for(i = 0; i < 3; i++) {
glColor3fv(xyz[i].x);
glVertex3fv(xyz[i].x);
glVertex3f(0,0,0);
}
glEnd();
glPopMatrix();
}
if(censize != 0) {
censize = fabs(censize);
glPushMatrix();
const Point *cen = view->center();
glTranslatef(cen->x[0],cen->x[1],cen->x[2]);
glScalef(censize, censize, censize);
glBegin(GL_LINES);
for(i = 0; i < 3; i++) {
glColor3fv(white);
glVertex3fv(nxyz[i].x);
glVertex3fv(zero.x);
glColor3fv(xyz[i].x);
glVertex3fv(zero.x);
glVertex3fv(xyz[i].x);
}
glEnd();
glPopMatrix();
}
}
void readrc( struct stuff **stp ) {
char *rc = findfile( NULL, "~/.partiviewrc" );
if(rc) specks_read( stp, rc );
rc = findfile( NULL, "./.partiviewrc" );
if(rc) specks_read( stp, rc );
}
static int cmdargs(int argc, char **argv, int & optind) {
char *arg = argv[optind];
if(!strcmp("-c", arg)) {
char *t = NewA(char, strlen(arg)+1);
char *av[128];
int ac = tokenize(arg, t, 128, av, NULL);
specks_parse_args( &ppui.st, ac, av );
optind += 2;
return 1;
}
if(!strcmp("-hideui", arg)) {
ppui.detached = 'h';
optind++;
return 1;
}
if(!strcmp("-geom", arg) || !strcmp("-geometry", arg)) {
ppui.reqwinsize = NULL; /* override any initial "winsize" */
/* but let fltk parse it anyway */
return 0;
int pp_parse_args( struct stuff **, int argc, char *argv[], char *fromfname, void * ) {
if(argc < 1) return 0;
int i;
if(!strcmp( argv[0], "exit" )) {
exit(0);
} else if(!strcmp( argv[0], "stereo" )) {
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
for(i = 1; i < argc; i++)
parti_stereo( argv[i] );
msg("stereo %s", parti_stereo(NULL));
} else if(!strcmp( argv[0], "winsize" )) {
msg("winsize %s", parti_winsize( rejoinargs( 1, argc, argv ) ) );
} else if(!strncmp( argv[0], "snapset", 7 ) || !strcmp( argv[0], "snapshot" )) {
char *frameno = NULL, *basename = NULL;
char *size = NULL;
int now = (0 == strcmp(argv[0], "snapshot"));
while(argc > 2) {
if(!strcmp(argv[1], "-w")) {
size = argv[2];
} else if(!strcmp(argv[1], "-n")) {
frameno = argv[2];
} else
break;
argc -= 2, argv += 2;
}
if(argc > 1)
basename = rejoinargs( 1, argc, argv );
parti_snapset( basename, frameno, size );
if(now) {
char snapinfo[1024];
if(parti_snapshot(snapinfo) >= 0)
msg("Snapped %s", snapinfo);
}
} else if(!strcmp( argv[0], "clip" )) {
msg("%s", parti_clip( argv[1], argc>2?argv[2]:NULL ) );
} else if(!strcmp( argv[0], "ortho" )) {
#ifdef NOTYET
int ortho = parti_ortho( argc>1 ? argv[1] : NULL);
float fov = parti_fov(NULL);
msg(ortho ? "ortho on (fov %g units)" : "ortho off (fov %g degrees)");
#endif
} else if(!strcmp( argv[0], "pickrange" )) {
float pickrange = parti_pickrange( argv[1] );
} else if(!strcmp( argv[0], "fov" ) || !strcmp( argv[0], "fovy" )) {
float fovy = parti_fovy( (argc>1) ? argv[1] : NULL );
msg("fovy %g", fovy);
} else if(!strcmp( argv[0], "subcam")) {
int index;
if(argc > 1) {
if(!strcmp(argv[1], "-") || !strcmp(argv[1], "off")) {
parti_select_subcam(0);
} else if(0==strcmp(argv[1],"-tilt")) {
if(argc > 2)
sscanf(argv[2], "%f", &ppui.sctilt);
msg("subcam -tilt %g", ppui.sctilt);
index = parti_make_subcam( argv[1], argc-2, argv+2 );
if(index > 0) {
parti_select_subcam(index);
} else {
char *what = parti_subcam_list();
msg(what[0]=='\0' ? "No subcams defined yet" :
"Known subcams: %s", what);
}
}
}
index = parti_current_subcam();
if(index > 0) {
char params[100];
char *name = parti_get_subcam( index, params );
msg("subcam %s %s # az el rol L R B T // subcam -tilt %g", name, params, ppui.sctilt);
} else {
int wx, wy;
float hx, hy = .5 * parti_fovy(NULL);
sscanf( parti_winsize(NULL), "%d%*c%d", &wx, &wy );
if(wy == 0) wy = 1;
hx = atan( tan(hy*(M_PI/180))*wx / wy ) * (180/M_PI);
msg("subcam off 0 0 0 %g %g %g %g # a e r L R B T (default)",
hx, hx, hy, hy);
}
float focallen = parti_focal( (argc>1) ? argv[1] : NULL );
msg("focallength %g", focallen);
} else if(!strcmp( argv[0], "focalpoint" )) {
/* args:
* on/off
* x y z [minfocallen]
*/
Point fpt;
float minlen;
int ison = parti_focalpoint( argc-1, (argv+1), &fpt, &minlen );
msg(ison ? "focalpoint %g %g %g %g # pointxyz minfocallen"
: "focalpoint off # %g %g %g %g # pointxyz minfocallen",
fpt.x[0],fpt.x[1],fpt.x[2], minlen);
} else if(!strncmp( argv[0], "jump", 4 )) {
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
Point xyz;
float aer[3];
static int stupid[3] = {1,0,2}; /* aer -> rx ry rz */
Matrix c2w;
parti_getc2w( &c2w );
tfm2xyzaer( &xyz, aer, &c2w );
if(argc>1) {
for(i=1; i<argc && i<4+3; i++) {
if(i-1<3) xyz.x[i-1] = getfloat(argv[i], xyz.x[i-1]);
else aer[stupid[i-4]] = getfloat(argv[i], aer[stupid[i-4]]);
}
xyzaer2tfm( &c2w, &xyz, aer );
parti_setc2w( &c2w );
}
msg("jump %g %g %g %g %g %g (XYZ RxRyRz)",
xyz.x[0],xyz.x[1],xyz.x[2],
aer[1],aer[0],aer[2]);
} else if(!strncmp( argv[0], "home", 4 )) {//marx version 0.7.03
Point xyz;
float aer[3];
static int stupid[3] = {1,0,2}; /* aer -> rx ry rz */
Matrix c2w;
parti_getc2w( &c2w );
tfm2xyzaer( &xyz, aer, &c2w );
if(argc>1) {
for(i=1; i<argc && i<4+3; i++) {
if(i-1<3) xyz.x[i-1] = getfloat(argv[i], xyz.x[i-1]);
else aer[stupid[i-4]] = getfloat(argv[i], aer[stupid[i-4]]);
}
xyzaer2tfm( &c2w, &xyz, aer );
parti_setc2w( &c2w );
ppui.home[0] = xyz.x[0]; ppui.home[1] = xyz.x[1]; ppui.home[2] = xyz.x[2];
//ppui.home[3] = aer[0]; ppui.home[4] = aer[1]; ppui.home[5] = aer[2]; bug in releases >= 0.7.03
ppui.home[3] = aer[1]; ppui.home[4] = aer[0]; ppui.home[5] = aer[2]; //version 0.7.05 fix for the line above
}
msg("home %g %g %g %g %g %g (XYZ RxRyRz)", ppui.home[0], ppui.home[1], ppui.home[2], ppui.home[3], ppui.home[4], ppui.home[5]);
} else if(!strncmp(argv[0], "inertia", 5)) {
if(argc > 1)
ppui.view->inertia( getbool( argv[1], ppui.view->inertia() ) );
msg("inertia %s", ppui.view->inertia() ? "on":"off");
} else if((!strcmp( argv[0], "rdata" ) || !strcmp(argv[0], "readpath"))
&& argc>1) {
char *tfname = argv[1];
char *realfile = findfile( fromfname, tfname );
if(realfile == NULL) {
tfname = (char *)alloca(strlen(argv[1]) + 32);
sprintf(tfname, "data/record/%s%s", argv[1],
strstr(argv[1], ".wf") ? "" : ".wf");
realfile = findfile( NULL, tfname+12 );
}
if(realfile == NULL)
realfile = findfile( fromfname, tfname );
if(realfile)
parti_readpath( realfile );
else
msg("%s: can't find \"%s\" nor data/record/... nor ...wf",
argv[0],argv[1]);
} else if(!strcmp( argv[0], "play" )) {
parti_play( argc>1 ? rejoinargs(1, argc, argv) : NULL );
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
} else if(!strcmp( argv[0], "frame" )) {
CONST struct wfpath *pp;
i = parti_frame( argv[1], &pp );
msg("frame %d (of %d..%d)", pp->curframe,
pp->frame0, pp->nframes + pp->frame0 - 1);
} else if(!strcmp( argv[0], "interest") || !strcmp( argv[0], "int" ) ||
!strcmp( argv[0], "center" ) ||
!strcmp( argv[0], "cen" )) {
Point cen;
float censize = parti_getcensize();
parti_getcenter( &cen );
if(argc > 1) {
sscanf(argv[1], "%f%*c%f%*c%f%*c%f",
&cen.x[0],&cen.x[1],&cen.x[2], &censize);
if(argc > 3)
for(i=0;i<3;i++)
cen.x[i] = getfloat(argv[i+1], cen.x[i]);
if(argc == 3 || argc == 5)
sscanf(argv[argc-1], "%f", &censize);
parti_center( &cen );
if(censize != parti_getcensize())
parti_censize( censize );
}
msg("center %g %g %g %g(radius)", cen.x[0],cen.x[1],cen.x[2], censize);
} else if(!strcmp( argv[0], "censize" )) {
if(argc>1)
parti_censize( getfloat(argv[1], parti_getcensize()));
msg("censize %g (interest-marker size)", parti_getcensize());
} else if(!strcmp( argv[0], "detach" )) { /* "detach" or "detach f" or "detach f +50+100" */
parti_detachview( rejoinargs( (argc>1 ? 1 : 0), argc, argv ));
} else {
return 0;
}
return 1;
}
int main(int argc, char *argv[])
{
static GLuint pickbuffer[20480];
extern char partiview_version[];
static Point black = {0,0,0};
ppui.view->bgcolor( &black );
ppui.view->dspcontext( 0 ); /* assign a display context, so texture code can track window changes */
char title[64];
sprintf(title, "partiview %.10s", partiview_version);
ppui.mainwin->label( title );
/* make_window() sets ppui.view, etc. */
parti_add_commands( pp_parse_args, "partiview", NULL );
parti_add_reader( pp_read, "partiview", NULL );
pp_ui_init();
ppui.view->add_drawer( drawjunk, NULL, NULL, NULL, 0 );
ppui.view->pickbuffer( COUNT(pickbuffer), pickbuffer );
ppui.view->zspeed = 5;
ppui.view->farclip( 2500 );
ppui.censize = 1.0;
ppui.view->movingtarget( 0 );
ppui.view->msg = msg;
if(ppui.hrdiag) {
ppui.hrdiag->msg = msg;
ppui.playspeed = 1;
ppui.playframe->lstep(10);
initShaderStuff( false ); // prepare to load shader programs (later)
parti_object( "g1", NULL, 1 );
readrc( &ppui.st );
int i = 0;
if(Fl::args(argc, argv, i, cmdargs) == 0) {
fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
exit(1);
}
for( ; i < argc; i++) {
specks_read( &ppui.st, argv[i] );
}
ppui.view->notifier( pp_viewchanged, ppui.st );
ppui_refresh( ppui.st );
if(ppui.detached == 'h')
ppui.mainwin->hide();
else
ppui.mainwin->show(argc, argv);
#ifdef GLUT_MULTISAMPLE // if multisampling known to FLTK
parti_stereo( parti_stereo(NULL) ); // side effect: enables multisampling
#endif
ppui.view->make_current(); // to allow shader stuff to work
initShaderStuff( true );
//marx version 0.7.03 process any pending events followed by simulation user pressing enter key
//this appears to properly initialize the steprow group
/*
for(i = 1; i < 11; i++) //11 is arbitrary probably only need 5
Fl::wait(.1);
pp_cmd_cb( ppui.cmd, NULL );
*/
//replaces the above in release because the above seemed to stop working in 0.7.06
//in effect i am replacing a software emulation of pressing the enter key with software simulation of a mouse click
smarx
committed
int cnt = 0;
while(double v = Fl::wait(.1)){
if(v < 0) //error
break;
if(cnt++ > 5) //because in windows wait(time) will not return 0 if time > 0
break;
}
ppui_refresh(NULL);
//end of replaces the above ...
#if 0 /* was: #ifdef __APPLE__ */
Fl_Window* mw = ppui.mainwin;
Fl::wait(.1);
ppui.mainwin->resize(mw->x()+1, mw->y()+1, mw->w()+1, mw->h()+1); //marx: version 0.7.04
//the resize compensates for bug that appears under os x only - damage to widgets does not cause redraw but resize seems to cause the needed redraw
// this bug appears to be fixed (by fltk 1.1.10, probably earlier),
// and doing this causes the main window to be non-resizable,
// so let's toss it. Thanks to Jonathan Strawn <jonnyflash@gmail.com>,
// UNM ARTS Lab, for figuring this out. -slevy
if(ppui.reqwinsize != NULL) {
parti_update();
parti_winsize( ppui.reqwinsize );
ppui.reqwinsize = NULL;
}
Fl::visible_focus(0); //marx: version 0.7.02 - keep the pre fltk-1.1.x old style of only text widgets to get keyboard focus
Fl_Tooltip::delay(.5); //marx: version 0.7.02
Fl_Tooltip::font(FL_HELVETICA_BOLD); //marx: version 0.7.02
Fl_Tooltip::color(68); //marx: version 0.7.02
return Fl::run();
}