Skip to content
Snippets Groups Projects
partibrains.c 189 KiB
Newer Older
teuben's avatar
teuben committed
  } else if(!strncmp( argv[0], "color", 5 )) {
	struct valdesc *vd;
	if(argc>1) {
	    if(!specks_set_byvariable( st, argv[1], &st->coloredby ))
		st->coloredby = CONSTVAL;
	}
	vd = &st->vdesc[st->curdata][st->coloredby];
	if(argc>2 && (!strncmp(argv[2], "int", 3) ||
		      !strncmp(argv[2], "exact", 5))) {
	    vd->call = 0;
	    vd->cexact = 1;
	    vd->cmin = 0;
	    argc--, argv++;
	}
	if(argc>2 && (!strncmp(argv[2], "cont", 4) || !strcmp(argv[2], "-exact"))) {
	   vd->cexact = 0;
	   argc--, argv++;
	}
	if(argc>2 && sscanf(argv[2], "%f", &vd->cmin))
	    vd->call = 0;
	if(argc>3 && sscanf(argv[3], "%f", &vd->cmax))
	    vd->call = 0;
	if((vd->cmin == vd->cmax && vd->cmin == 0) ||
	   (argc>2 && (!strcmp(argv[2],"-") || !strcmp(argv[2],"all")))) {

	    vd->cmin = vd->min, vd->cmax = vd->max, vd->call = 1;
	}
	if(argc>4 && st->coloredby == CONSTVAL) sscanf(argv[4], "%f", &vd->mean);
	if(st->coloredby == CONSTVAL) {
	    msg("coloring-by rgb %.3f %.3f %.3f",
		vd->cmin, vd->cmax, vd->mean);
	} else if(vd->cexact) {
	    msg("coloring-by %d(%s) exactly (cindex=data+%g; data %g..%g, cmap 0..%d)",
		st->coloredby, vd->name, vd->cmin,
		vd->min,vd->max, st->ncmap-1);
	} else {
	    if(vd->min == vd->cmin && vd->max == vd->cmax || vd->nsamples==0) {
		msg("coloring-by %d(%s) %g.. %g mean %.3g]",
		    st->coloredby, vd->name,
		    vd->cmin, vd->cmax, vd->mean);
	    } else {
		msg("coloring-by %d(%s) %g.. %g (data %g..%g mean %.3g)",
		    st->coloredby, vd->name,
		    vd->cmin, vd->cmax, vd->min, vd->max, vd->mean);
	    }
	}
	if(argc>1)
	    st->colorseq++;

  } else if(!strcmp( argv[0], "datavar" ) || !strcmp( argv[0], "dv" )) {
	int min = 0, max = CONSTVAL-1;
	if(argc>1 && specks_set_byvariable( st, argv[1], &min ))
	    max = min;
	if(st->ndata>1)
	    msg("In dataset %d %s:", st->curdata, st->dataname[st->curdata]);
	for(i = min; i <= max; i++) {
	    struct valdesc *vd = &st->vdesc[st->curdata][i];
	    if(max>min && vd->name[0] == '\0' && vd->max == vd->min)
		continue;
	    msg("datavar %d %s  %g.. %g mean %g%s%s",
		i, vd->name[0]=='\0'?"\"\"" : vd->name,
		vd->min, vd->max, vd->mean,
		st->sizedby==i ? "[lum]" : "",
		st->coloredby==i ? "[color]" : "");
	}

  } else if(!strcmp( argv[0], "datawait" )) {
	if(argc>1) {
	    switch(i = getbool(argv[1],-1)) {
	    case 0:
	    case 1:
		st->datasync = i;
		break;
	    }
	    msg("datawait %s", st->datasync ? "on" : "off");
	}
	specks_datawait(st);

  } else if(!strncmp(argv[0], "ghost", 5)) {
	if(argc > 1) st->nghosts = getbool(argv[1], st->nghosts);
	msg("ghosts %d", st->nghosts);

teuben's avatar
teuben committed
  } else if(!strncmp( argv[0], "lum", 3 )) {
	struct valdesc *vd;
	if(argc>1) {
	    if(!specks_set_byvariable( st, argv[1], &st->sizedby ))
		st->sizedby = CONSTVAL;
	}
	vd = &st->vdesc[st->curdata][st->sizedby];
	if(argc>2) vd->lall = 0, vd->lmin = getfloat(argv[2], vd->lmin);
	if(argc>3) vd->lall = 0, vd->lmax = getfloat(argv[3], vd->lmax);
	if(vd->lmin == vd->lmax && vd->lmin == 0 ||
	       argc>2 && (!strcmp(argv[2],"-") || !strcmp(argv[2],"all"))) {
	    vd->lmin = vd->min, vd->lmax = vd->max, vd->lall = 1;
	}
	if(st->sizedby == CONSTVAL) {
	    msg("lum-by constant %g", vd->lmin);
	} else {
	    msg("lum-by %d (%s) [%g..%g mean %.3g]", st->sizedby,
		vd->name, vd->lmin, vd->lmax, vd->mean);
	}
	if(argc>1)
	    st->sizeseq++;

  } else if(!strcmp( argv[0], "cmap" ) || !strcmp( argv[0], "boxcmap" )
					|| !strcmp( argv[0], "textcmap" )) {
teuben's avatar
teuben committed
	char *tfname = argv[1];
	char *realfile = findfile( NULL, argv[1] );
	if(argc != 2) {
	    msg("Usage: %s <ascii-file-of-RGB-triples>", argv[0]);
	} else {
	    if(argc > 1 && realfile == NULL) {
		tfname = (char *)alloca( strlen(argv[1]) + 6 );
		sprintf(tfname, "%s.cmap", argv[1]);
		realfile = findfile( NULL, tfname );
	    }
	    if(realfile != NULL) {
		if(argv[0][0] == 'b') {
		    specks_read_cmap( st, realfile, &st->boxncmap, &st->boxcmap );
		} else if(argv[0][0] == 't') {
		    specks_read_cmap( st, realfile, &st->textncmap, &st->textcmap );
teuben's avatar
teuben committed
		} else {
		    specks_read_cmap( st, realfile, &st->ncmap, &st->cmap );
teuben's avatar
teuben committed
		    st->colorseq++; /* Must recompute particle coloring */
		}
	    } else {
		msg("%s: can't find \"%s\" nor ....cmap", argv[0], argv[1]);
	    }
	}

  } else if(!strcmp( argv[0], "vcmap" )) {
	int k = 1;
	int coloredby = st->coloredby;
	char *tfname, *realfile;
	struct valdesc *vd;
	if(argc > 3 && !strcmp( argv[1], "-v" )) {
	    if(!specks_set_byvariable( st, argv[2], &coloredby )) {
		msg("vcmap -v %s: unknown colorby-variable", argv[2]);
		return -1;
	    }
	    k = 3;
	}
	vd = &st->vdesc[st->curdata][coloredby];
	if(coloredby < 0 || coloredby >= MAXVAL) {
	    msg("vcmap: bad colorby-variable %d", coloredby);
	    return -1;
	}
	if(argc != k+1) {
	    msg("Usage: vcmap [-v varname] <ascii-file-of-RGB-triples>", argv[0]);
	} else {
	    tfname = argv[k];
	    realfile = findfile( NULL, tfname );
	    if(realfile == NULL) {
		tfname = (char *)alloca( strlen(argv[k]) + 6 );
		sprintf(tfname, "%s.cmap", argv[k]);
		realfile = findfile( NULL, tfname );
	    }
	    if(realfile != NULL) {
		specks_read_cmap( st, realfile, &vd->vncmap, &vd->vcmap );
		st->colorseq++; /* Must recompute particle coloring */
	    } else {
		msg("vcmap: can't find \"%s\" nor ....cmap", argv[k]);
	    }
	}

  } else if(!strncmp( argv[0], "cment", 5 ) || !strncmp( argv[0], "boxcment", 8 )
		|| !strncmp( argv[0], "textcment", 6 )) {
teuben's avatar
teuben committed
	int i, r,g,b;
	unsigned char *cvp;
	char *prefix = "";
	int ncmap = st->ncmap;
	struct cment *cmap = st->cmap;

	switch(argv[0][0]) {
	case 'b': prefix = "box"; ncmap = st->boxncmap; cmap = st->boxcmap; break;
	case 't': prefix = "text"; ncmap = st->textncmap; cmap = st->textcmap; break;
	}
teuben's avatar
teuben committed

	if(argc>1 && argv[1][0] != '?') {
teuben's avatar
teuben committed
	    i = atoi(argv[1]);
	    if(i < 0 || i > ncmap) {
		msg("cment: %d out of range (must be 0..%d)", i, ncmap-1);
teuben's avatar
teuben committed
	    } else {
		if(argc>2) {
		    char *colorstr = rejoinargs( 2, argc, argv );
		    editcmap( st, ncmap, cmap, argv[1], argv[0], colorstr );
teuben's avatar
teuben committed
		    if(st->sl) st->colorseq++;	/* force recolor */
		}
		cvp = (unsigned char *)&cmap[i].raw;
		msg( "%scment %d  %.3f %.3f %.3f  (of cmap 0..%d",
			prefix,
teuben's avatar
teuben committed
			i, cvp[0]/255., cvp[1]/255., cvp[2]/255.,
teuben's avatar
teuben committed
	    }
	} else {
	    msg("Usage: %scment colorindex [r g b]  -or-  c1-c2,c3,c4  r g b -or- c1-c2,... = cindex", prefix);
	    msg(" (no blanks around commas for color ranges)");
teuben's avatar
teuben committed
	}

  } else if(!strncmp( argv[0], "only", 4 )) {
	int plus = !strcmp(argv[0], "only+");
	int minus = !strcmp(argv[0], "only-");
	int exact = !strcmp(argv[0], "only=");
	int total = 0, chosen = 0, waschosen = 0;
	int tvar = -1;
	int all = 0;
	int k;
	int nspecks, nvisible, needthresh;
	struct specklist *sl;
	struct speck *sp;

	if(argc>1) {
	    if(!strcmp(argv[1], "all") || !strcmp(argv[1], "*")) all = 1;
	    if(!strcmp(argv[1], "none")) all = -1;
	}
	if(!all && ((!plus && !minus && !exact) ||
		!specks_set_byvariable( st, argv[1], &tvar))) {
	    msg("only+/only-/only=  \"all\"|\"none\"|varname value minvalue-maxvalue ...");
	}

	plus |= exact;

teuben's avatar
teuben committed
	if(exact || all) {
	    /* preset all values */
	    int wipebit = (plus && all>0) ? 0 : THRESHBIT;
	    SelMask selbit = (plus && all>0) ? 0 : SELMASK(SEL_THRESH);
teuben's avatar
teuben committed
	    for(sl = st->sl; sl != NULL; sl = sl->next) {
		SelMask *sel = sl->sel;
teuben's avatar
teuben committed
		if((sp = sl->specks) == NULL || sl->text != NULL)
		    continue;
		for(k = sl->nspecks; --k >= 0; sp = NextSpeck(sp, sl, 1)) {
teuben's avatar
teuben committed
		    sp->rgba = (sp->rgba & ~THRESHBIT) | wipebit;
		    sel[k] = (sel[k] & ~SELMASK(SEL_THRESH)) | selbit;
		}
		sl->selseq = st->selseq;
teuben's avatar
teuben committed
	    }
	}

	/*
	 * If a thresh variable is given, use "plus" to choose
	 * whether to make that speck visible.
	 * NOTE that specks with THRESHBIT on are *invisible*!
	 */
	for(i = 2; i < argc; i++) {
	    float vmin = -1e38, vmax = 1e38;

	    if(argv[i][0] == '<') vmax = atof(argv[i]+1);
	    else if(argv[i][0] == '>') vmin = atof(argv[i]+1);
	    else {
		switch(sscanf(argv[i], "%f%*c%f", &vmin, &vmax)) {
		case 1: vmax = vmin; break;
		case 2: break;
		default:
		    msg("%s: \"%s\": expected N or <N or >N or N-M",
			argv[0], argv[i]);
		    return -1;
		}
	    }

	    for(sl = st->sl; sl != NULL; sl = sl->next) {
		SelMask *sel = sl->sel;
teuben's avatar
teuben committed
		if((sp = sl->specks) == NULL || sl->text != NULL || tvar<0
			|| SMALLSPECKSIZE(tvar+1) > sl->bytesperspeck)
		    continue;
		for(k = sl->nspecks; --k >= 0; sp = NextSpeck(sp, sl, 1)) {
		    if(sp->val[tvar]>=vmin && sp->val[tvar]<=vmax) {
teuben's avatar
teuben committed
			sp->rgba = plus ? sp->rgba & ~THRESHBIT
					: sp->rgba | THRESHBIT;
			sel[k] = plus ? sel[k] | SELMASK(SEL_THRESH)
			    	      : sel[k] & ~SELMASK(SEL_THRESH);
		    }
teuben's avatar
teuben committed
		}
		sl->selseq = st->selseq;
teuben's avatar
teuben committed
	    }
	}

	nspecks = nvisible = 0;
	for(sl = st->sl; sl != NULL; sl = sl->next) {
	    if((sp = sl->specks) == NULL || sl->text != NULL)
		continue;
	    nspecks += sl->nspecks;
	    for(k = sl->nspecks; --k >= 0; sp = NextSpeck(sp, sl, 1)) {
		if(!(sp->rgba & THRESHBIT))
		    nvisible++;
	    }
	}

	needthresh = (st->usethresh&P_USETHRESH)==0 && nvisible < nspecks;
	if(needthresh)
	    st->usethresh |= P_USETHRESH;
	msg("only %d visible of %d%s", nvisible, nspecks,
		needthresh ? " (selecting \"thresh on\")" : "");

  } else if(!strncmp( argv[0], "thresh", 6 )) {
	int i, expect = -1;
	float v;
	char smin[16], smax[16], *arg;
	char chosen[40];
teuben's avatar
teuben committed
	int changed = 0;
	char *selstr = NULL;
teuben's avatar
teuben committed
	for(i = 1; i < argc; i++) {
	    arg = argv[i];
	    if(!strcmp(arg,"-s")) {
		selstr = argv[++i];
	    } else if(!strcmp(arg,"off"))
teuben's avatar
teuben committed
		st->usethresh &= ~P_USETHRESH, expect = -1;
	    else if(!strcmp(arg,"on"))
		st->usethresh |= P_USETHRESH, expect = -1;
	    else if(expect<0 && specks_set_byvariable(st, arg, &st->threshvar)) {
		expect = 0;
		st->usethresh = P_USETHRESH;	/* neither MIN nor MAX set */
		changed = 1;
	    } else if(!strcmp(arg,"min") || !strcmp(arg, ">"))
		expect = 0;
	    else if(!strcmp(arg,"max") || !strcmp(arg, "<"))
		expect = 1;
	    else if(!strcmp(arg,"="))
		expect = 2;
	    else if(!strcmp(arg, "-")) {
		st->usethresh &= expect ? ~P_THRESHMAX : ~P_THRESHMIN;
		expect = 1;
	    } else if(sscanf(arg, "%f", &v) > 0) {
		if(expect != 1) {	/* -1, 0, or 2 */
		    st->thresh[0] = v;
		    st->usethresh |= P_THRESHMIN | P_USETHRESH;
		    changed = 1;
		}
		if(expect >= 1) {	/* 1 or 2 */
		    st->thresh[1] = v;
		    st->usethresh |= P_THRESHMAX | P_USETHRESH;
		    changed = 1;
		}
		expect = 1;
	    } else if(sscanf(arg, ">%f", &st->thresh[0]) > 0) {
		st->usethresh |= P_THRESHMIN | P_USETHRESH;
		changed = 1;
	    } else if(sscanf(arg, "<%f", &st->thresh[1]) > 0) {
		st->usethresh |= P_THRESHMAX | P_USETHRESH;
		changed = 1;
	    } else if(sscanf(arg, "=%f", &st->thresh[0]) > 0) {
		st->thresh[1] = st->thresh[0];
		st->usethresh |= P_THRESHMIN | P_THRESHMAX | P_USETHRESH; 
		changed = 1;
	    }
	}
	if(changed) {
	    struct specklist *sl;
	    st->threshseq++;
	    if(!parse_selexpr( st, selstr ? selstr : "thresh", NULL, &st->threshsel, NULL )) {
		msg("thresh -s %s: expected selection variable name", selstr);
		return 1;
	    }

	    /* "thresh" with no -s implies also "see thresh" */
	    if(selstr == NULL && st->seesel.wanted == 0)
		st->seesel = st->threshsel;

	}
	chosen[0] = '\0';
	sprintf(chosen, " (%s selected)", selcounts( st, st->sl, &st->threshsel ));
teuben's avatar
teuben committed
	sprintf(smin, st->usethresh&P_THRESHMIN ? "%g" : "-", st->thresh[0]);
	sprintf(smax, st->usethresh&P_THRESHMAX ? "%g" : "-", st->thresh[1]);
teuben's avatar
teuben committed
	msg(st->usethresh == 0 ? "thresh off"
		: "thresh%s%s%s %d(%s) min %s max %s%s",
		selstr ? " -s " : "",
		selstr ? selstr : "",
teuben's avatar
teuben committed
		st->usethresh&P_USETHRESH ? "" : " off ",
		st->threshvar, st->vdesc[st->curdata][st->threshvar].name,
		smin, smax, chosen);
teuben's avatar
teuben committed
	
  } else if(!strcmp( argv[0], "rawdump" )) {
	FILE *f = argc>1 ? fopen(argv[1], "w") : NULL;
	struct specklist *sl;
	int i, j, nmine, net;
	if(f == NULL) {
	    msg("%s: can't create", argv[1]);
	} else {
	    fprintf(f, "# from dataset %d \"%s\" timestep %d\n",
		st->curdata, st->fname[st->curdata][st->curtime], st->curtime);
	    for(i = 0; st->vdesc[st->curdata][i].name[0] != '\0'; i++) {
		fprintf(f, "%s\t", st->vdesc[st->curdata][i].name);
	    }
	    fprintf(f, "\n");
	    nmine = i;
	    net = 0;
	    sl = specks_timespecks( st, st->curdata, st->curtime );
	    if(sl == NULL && st->ntimes <= 1)
		sl = st->sl;
	    for(; sl != NULL; sl = sl->next) {
		for(j = 0; j < sl->nspecks; j++) {
		    for(i = 0; i < nmine; i++)
			fprintf(f, "%g\t", (NextSpeck(sl->specks, sl, j)->val[i]));
		    fprintf(f, "\n");
		    net++;
		}
	    }
	    fclose(f);
	    msg("Wrote %d particles (%d fields each) to %s",
		net, nmine, argv[1]);
	}
	
  } else if(!strncmp( argv[0], "slum", 3 ) || !strcmp( argv[0], "scale-lum" )) {
	float v, *lp;
	int by = st->sizedby, cd = st->curdata;
	if(argc>1) {
	    if(argc>2) specks_set_byvariable( st, argv[2], &by );
	    if(argc>3) sscanf(argv[3], "%d", &cd);
	    if((unsigned int)cd >= MAXFILES) cd = 0;
	    lp = &st->vdesc[cd][by].lum;
	    *lp = getfloat( argv[1], *lp!=0 ? *lp : 1 );
	}
	msg("slum scaling %g (var %d %s dataset %s (%d))",
	    st->vdesc[cd][by].lum, by, st->vdesc[cd][by].name,
	    st->dataname[cd], cd);

  } else if(!strcmp( argv[0], "seedata" )) {
teuben's avatar
teuben committed
	if(argc>1) {
	    int v = -1, len = strlen(argv[1]);
		/* search st->dataname[] array! XXX */
	    if(sscanf(argv[1], "%d", &v) > 0) {
		/* fine */
	    } else {
		for(v = st->ndata; --v >= 0; ) {
		    if(!strncasecmp( argv[1], st->dataname[v], len ))
			break;
		}
		if(v < 0) {
		    char msgstr[2048];
		    sprintf(msgstr,
			"Never heard of dataset \"%s\"; we have these %d:",
			argv[1], st->ndata);
		    for(v = 0; v < st->ndata; v++)
			sprintf(msgstr+strlen(msgstr), " \"%s\"(%d) ", st->dataname[v], v);
		    msg(msgstr);
		    v = -1;
		}
	    }
	    if(v >= 0 && v < st->ndata)
		st->curdata = v;
	}
	msg("showing dataset %d (%s)", st->curdata,
		st->dataname[st->curdata]);

  } else if(!strncmp( argv[0], "seesel", 3 )) {
    if(argc>1)
	parse_selexpr( st, rejoinargs( 1, argc, argv ), NULL, &st->seesel, "see" );
    msg("see %s (%s)", show_selexpr( st, NULL, &st->seesel ),
	    	selcounts( st, st->sl, &st->seesel ));

  } else if(!strcmp( argv[0], "emph" )) {
    struct specklist *sl;
    if(argc>2 && !strcmp(argv[1], "-f"))
	st->emphfactor = getfloat( argv[2], st->useemph ),
        argc -= 2, argv += 2;
    if(argc>1) {
	if(!strcmp(argv[1], "on")) st->useemph = 1;
	else if(!strcmp(argv[1], "off")) st->useemph = 0;
	else {
	    parse_selexpr( st, rejoinargs( 1, argc, argv ), NULL, &st->emphsel, "emph" );
	    st->useemph = 1;
	}
    }
    if(st->useemph) {
	st->sizeseq++;
	msg("emph -f %g  %s (%s emphasized)", st->emphfactor,
	    	show_selexpr( st, NULL, &st->emphsel ),
		selcounts( st, st->sl, &st->emphsel ));
    } else {
	msg("emph off");
    }

  } else if(!strcmp( argv[0], "sel" )) {
    SelOp src, dest;
    char *rest = rejoinargs( 1, argc, argv );

    /*
     * sel a = b -c d  (existing names, or "see" or "emph" or maybe "thresh")
     * sel a = [all|none]
     */
    if(strchr(rest, '=')) {
	if(parse_selexpr( st, rest, &dest, &src, "sel" )) {
	    struct specklist *sl;
	    /* Is this the right place to look?  Do we want to update more than st->sl? */
	    int selcount = 0, totalcount = 0;
	    st->selseq++;
	    for(sl = st->sl; sl != NULL; sl = sl->next) {
		int k, ns = sl->nspecks;
		SelMask *sel = sl->sel;
		if(sl->text != NULL || sl->nsel < ns) continue;
		for(k = 0; k < ns; k++) {
		    if(src.use != SEL_NONE && SELECTED(sel[k], &src)) {
			SELSET(sel[k], &dest);
			selcount++;
		    }
		if(st->useemph)
		    specks_resize( st, sl, sl->sizedby );  /* XXX could anything else depend on this? */
		sl->selseq = st->selseq;
	    msg("sel %s : %d of %d selected",
		show_selexpr(st, &dest, &src), selcount, specks_count(st->sl));
	}
    } else {
	/* No '=' -- just asking how many match some pattern */
	if(parse_selexpr( st, rest, NULL, &src, "sel")) {
	    msg("sel %s : %s matched", show_selexpr( st, NULL, &src ),
		    	selcounts(st, st->sl, &src));
	}
    }

  } else if(!strcmp( argv[0], "pick" )) {
    /* pick [-a] [note|center|sel <name>] */
    /* kira pick track */
      msg("pick not yet implemented XXX");

teuben's avatar
teuben committed
  } else if(!strcmp( argv[0], "show" ) || !strcmp( argv[0], "hide" )
	  || !strncasecmp( argv[0], "showbox", 7 )
	  || !strncasecmp( argv[0], "hidebox", 7 )) {
	int doshow = argv[0][0] == 's';
	int i, level, mask = 0;
	if(doshow) st->useboxes = 1;
	for(i = 1; i < argc; i++) {
	    level = getbool( argv[i], -2 );
	    if(level == -1)
		mask = ~0;
	    else if(level >= 0)
		mask |= (1 << level);
	}
	if(doshow) st->boxlevelmask |= mask;
	else st->boxlevelmask &= ~mask;
	/* st->boxlevelmask &= (1 << st->boxlevels) - 1;
	 *  Don't do this -- we want "show all" to apply to levels that
	 *  we haven't read in yet.
	 */
#if CAVEMENU
	for(i = 0; i < st->boxlevels && i < COUNT(ment.boxlevel); i++) {
	    struct boxleveler blr;
	    blr.st = st;
	    blr.level = i;
	    if(ment.boxlevel[i])
		set_boxlevel( 0, ment.boxlevel[i], &blr );
	}
#endif

  } else if(!strcmp( argv[0], "box" ) || !strcmp( argv[0], "boxes" )) {
	st->useboxes = getbool( argv[1], (st->useboxes+1)%3 );
	msg("boxes %s", st->useboxes==2 ? "ONLY"
				: st->useboxes ? "ON" : "off");

  } else if(!strncmp( argv[0], "boxlabel", 6 )) {
	if(argc>1) st->boxlabels = getbool( argv[1], !st->boxlabels );
	else st->boxlabels = !st->boxlabels;
	msg("boxlabels %s", st->boxlabels?"on":"off");

  } else if(!strncmp( argv[0], "boxaxes", 5 )) {
	if(argc>1) st->boxaxes = getbool( argv[1], !st->boxaxes );
	else st->boxaxes = !st->boxaxes;
	msg("boxaxes %s", st->boxaxes?"on":"off");

  } else if(!strcmp(argv[0], "boxscale")) {
	char buf[512];
	int from, to;
	if(argc>1) {
	    float v = atof(argv[1]);
	    from = getbool(argc>2?argv[2]:NULL, 0);
	    to = getbool(argc>3?argv[3]:NULL, MAXBOXLEV-1);
	    if(from<0) from = 0;
	    if(to>MAXBOXLEV-1) to=MAXBOXLEV-1;
	    while(from<=to)
		st->boxscale[from++] = v;
	}
	sprintf(buf, "boxscales:");
	for(to=MAXBOXLEV-1; to>1 && st->boxscale[to]==st->boxscale[to-1]; to--)
	    ;
	for(from = 0; from <= to; from++)
	    sprintf(buf+strlen(buf), " %g", st->boxscale[from]);
	msg("%s", buf);

  } else if(!strcmp( argv[0], "go" ) || !strcmp( argv[0], "gobox" )) {
	int boxno = getbool( argv[1], -1 );
	if(boxno < 0) {
	    msg("Usage: gobox <boxnumber> -- sets POI and jumps to view that AMR box");
	} else {
	    specks_gobox( st, boxno, argc-2, argv+2 );
	}

  } else if(!strcmp( argv[0], "goboxscale" )) {
	if(argc>1) sscanf(argv[1], "%f", &st->goboxscale);
	msg("goboxscale %g  (\"gobox\" sets scale to %g * box diagonal; 0 => leave scale intact)",
		st->goboxscale, st->goboxscale);

  } else if(!strcmp( argv[0], "psize" ) || !strcmp(argv[0], "pointsize")) {
	if(argc>1) {
	    st->psize = getfloat( argv[1], st->psize );
	    IFMENU( set_psize( st->psize, ment.psize, st ) );
	}
	msg("pointsize %g pixels (times scale-lum value)", st->psize );

  } else if(!strcmp( argv[0], "polysize" )) {
	if(argc>1) {
	    st->polysize = getfloat(argv[1], st->polysize);
	    IFMENU( set_polysize( st->polysize, ment.polysize, st ) );
	}
	if(argc>2) {
	    if(argv[2][0] == 'a' || argv[2][0] == 's') st->polyarea = 1;
	    else if(argv[2][0] == 'r') st->polyarea = 0;
	}
	msg("polysize %g%s", st->polysize, st->polyarea ? " area":"" );

  } else if(!strncmp( argv[0], "polylum", 7 )) {
	char *area = "";
	if(argc>1) {
	    if(!specks_set_byvariable( st, argv[1], &st->polysizevar ))
		if(!strcmp(argv[1], "-1") ||
		   !strcmp(argv[1], "point-size") ||
		   !strcmp(argv[1], "pointsize"))
		    st->polysizevar = -1;
	    if(st->polysizevar == CONSTVAL)
		st->polysizevar = -1;	/* Can't do const */
	}
	if(argc>2)
	    sscanf(argv[2], "%f", &st->polysize);
	switch(argv[argc-1][0]) {
	    case 'r':
	    case 'd':
	    case 's': st->polyarea = 0; break;
	    case 'a': st->polyarea = 1; break;
	}
	if(st->polyarea) area = " area";
	if(st->polysizevar < 0)
	    msg("polylumvar point-size%s", area);
	else
	    msg("polylumvar %d(%s)%s", st->polysizevar,
		st->vdesc[st->curdata][st->polysizevar].name,
		area);

  } else if(!strncmp( argv[0], "polyminpixels", 7 )) {
	if(argc>1) st->polymin = getfloat(argv[1], st->polymin);
	if(argc>2) st->polymax = getfloat(argv[2], st->polymax);
	msg("polyminpixels %g %g (minpixels maxpixels)", st->polymin, st->polymax );

  } else if(!strncmp( argv[0], "labelminpixels", 7 )) {
	st->textmin = getfloat(argv[1], st->textmin);
	msg("labelminpixels %g", st->textmin );


  } else if(!strcmp( argv[0], "labelsize" ) || !strcmp(argv[0], "lsize")) {
	st->textsize = getfloat(argv[1], st->textsize);
	msg("labelsize %g", st->textsize);

  } else if(!strcmp( argv[0], "point" ) || !strcmp( argv[0], "points" )) {
	st->usepoint = getbool( argv[1], !st->usepoint );
	IFMENU( set_point( st->usepoint, ment.point, st ) );
	msg("points %s", st->usepoint ? "on":"off");

  } else if(!strcmp( argv[0], "poly" ) || !strncmp( argv[0], "polygon", 7 )) {
	st->usepoly = getbool( argv[1], !st->usepoly );
	IFMENU( set_poly( st->usepoly, ment.poly, st ) );
	msg("polygons %s", st->usepoly ? "on":"off");

  } else if(!strncmp( argv[0], "texture", 7 ) || !strcmp( argv[0], "tx" )) {
	if(argc > 1 && !strcmp(argv[1], "preload")) {
	    msg("Preloading textures...");
	    for(i = 0; i < st->ntextures; i++)
		if(st->textures[i]) txload( st->textures[i] );
	} else if(argc > 1 && !strncmp(argv[1], "report", 3)) {
	    if(argc == 2) {
		for(i = 0; i < st->ntextures; i++)
			if(st->textures[i]) st->textures[i]->report = ~0;
	    } else {
		for(i = 2; i < argc; i++) {
		    int t = atoi(argv[i]);
		    if(t >= 0 && t < st->ntextures && st->textures[t])
			st->textures[t]->report = ~0;
		}
	    }
teuben's avatar
teuben committed
	} else {
	    st->usetextures = getbool( argv[1], !st->usetextures );
	    msg("textures %s", st->usetextures ? "on":"off");
	}

  } else if(!strcmp( argv[0], "txscale" )) {
	if(argc>1) sscanf(argv[1], "%f", &st->txscale);
	msg("txscale %.3f", st->txscale);

  } else if(!strncmp( argv[0], "polyorivar", 10)) {
	if(argc>1) st->polyorivar0 = getbool(argv[1], -1);
	msg(st->polyorivar0 >= 0
	  ? "polyorivar %d : polygon orientations from var %d..%d"
	  : "polyorivar %d : polygon orientations parallel to screen",
	  st->polyorivar0, st->polyorivar0, st->polyorivar0+5);

  } else if(!strcmp( argv[0], "texturevar")) {
	if(argc>1) st->texturevar = getbool(argv[1], -1);
	msg("texturevar %d", st->texturevar);

  } else if(!strncmp( argv[0], "ellipsoids", 5 )) {
	st->useellipsoids = getbool(argv[1], !st->useellipsoids);
	msg("ellipsoids %s", st->useellipsoids ? "on":"off");
	
  } else if(!strncmp( argv[0], "meshes", 4 )) {
	st->usemeshes = getbool(argv[1], !st->usemeshes);
	msg("meshes %s", st->usemeshes ? "on":"off");

teuben's avatar
teuben committed
  } else if(!strcmp( argv[0], "label" ) || !strcmp( argv[0], "labels" )) {
	st->usetext = getbool( argv[1], !st->usetext );
	IFMENU( set_label( st->usetext, ment.label, st ) );
	msg("labels %s", st->usetext ? "on":"off");

  } else if(!strcmp( argv[0], "laxes" )) {
	st->usetextaxes = getbool(argv[1], !st->usetextaxes);
	msg("laxes %s  (axes on each label)", st->usetextaxes ? "on":"off");

  } else if(!strncmp( argv[0], "polyside", 8 )) {
	if(argc>1) sscanf(argv[1], "%d", &st->npolygon);
	msg("polysides %d (polygons drawn with %d sides)",
		st->npolygon,st->npolygon);

  } else if(!strcmp( argv[0], "gamma" )) {
	if(argc>1) sscanf(argv[1], "%f", &st->gamma);
	msg("gamma %g", st->gamma);

slevy's avatar
 
slevy committed
  } else if(!strncmp( argv[0], "cgamma", 4 ) || !strncmp(argv[0], "setgamma", 6)) {
	float *p = NULL;
slevy's avatar
 
slevy committed
	int any = 0;
slevy's avatar
 
slevy committed
	for(i = 1; i < argc; i++) {
	    if(!strcmp(argv[i], "-b")) i++, p = &st->rgbright[0];
	    else if(!strcmp(argv[i], "-g")) i++, p = &st->rgbgamma[0];
	    else if(i == argc-1) p = &st->rgbgamma[0];
	    else continue;
slevy's avatar
 
slevy committed
	    switch(sscanf(argv[i], "%f%*c%f%*c%f", &p[0],&p[1],&p[2])) {
slevy's avatar
 
slevy committed
	    case 1: p[1] = p[2] = p[0];  /* and fall into... */
	    case 3: any = 1; break;
	    default: msg("setgamma [-b BRIGHT] [-g GAMMA]: want 1 or 3 floats not %s", argv[i]);
	    }
	}
	msg("setgamma -b %g,%g,%g  -g %g,%g,%g",
		st->rgbright[0],st->rgbright[1],st->rgbright[2],
		st->rgbgamma[0],st->rgbgamma[1],st->rgbgamma[2]);
	if(any)
	    specks_rgbremap( st );

teuben's avatar
teuben committed
  } else if(!strcmp( argv[0], "alpha" )) {
	if(argc>1)
	    st->alpha = getfloat(argv[1], st->alpha);
teuben's avatar
teuben committed
	IFMENU( set_alpha( st->alpha, ment.alpha, st ) );
	msg("alpha %g", st->alpha);

  } else if(!strncmp( argv[0], "fast", 4 )) {
	st->fast = getbool(argv[1], !st->fast);
	if(argc > 2) sscanf(argv[2], "%f", &st->pfaint);
	if(argc > 3) sscanf(argv[3], "%f", &st->plarge);
	msg("fast %s  (ptsize %.3g %.3g (faintest largest))",
teuben's avatar
teuben committed
		st->fast ? "on" : "off (better rendering)",
		st->pfaint, st->plarge);

  } else if(!strncmp( argv[0], "ptsize", 6 )) {
	if(argc > 1) sscanf(argv[1], "%f", &st->pfaint);
	if(argc > 2) sscanf(argv[2], "%f", &st->plarge);
	msg("ptsize  %.3g %.3g  (faintest largest)", st->pfaint, st->plarge);

teuben's avatar
teuben committed
  } else if(!strcmp( argv[0], "fog" ) && argc > 1) {
	IFMENU( set_fog( st->fog, ment.fog, st ) );

  } else if(!strcmp( argv[0], "menu" ) || !strcmp( argv[0], "fmenu" )) {
#if CAVEMENU
	if(argc == 4 && !strncmp(argv[1], "pos", 3)) {
	    menu_setpos( pmenu, atof(argv[2]), atof(argv[3]) );

	} else if(argc == 3 && !strcmp(argv[1], "wall")) {
	    menu_onwall( pmenu, atoi(argv[2]) );
	    menu_onwall( stubmenu, atoi(argv[2]) );

	} else if(argc >= 2 && !strncmp(argv[1], "hid", 3)) {
	    st->hidemenu = argc>2 ? getbool( argv[2], st->hidemenu ) :
			 st->hidemenu ? 0 : -1;
	    msg("fmenu hide %s", st->hidemenu ? "on" : "off");

	} else if(argc >= 2 && !strcmp(argv[1], "show")) {
	    st->hidemenu = argc>2 ? getbool( argv[2], st->hidemenu ) :
			st->hidemenu ? 0 : -1;
	    msg("fmenu show %s", st->hidemenu ? "off" : "on");

	} else if(argc >= 2 && !strncmp(argv[1], "h", 1)) {
	    if(argc>2) menu_setheight( pmenu, atof(argv[2]) );
	    msg("fmenu height %g", pmenu->yspan);

	} else if(argc >= 2 && !strncmp(argv[1], "demandfps", 6)) {
	    if(argc == 3) sscanf(argv[2], "%f", &st->menudemandfps);
	    msg("fmenu demandfps %g", st->menudemandfps);

	} else if(argc > 1 && argc <= 3 && !strncmp(argv[1], "font", 4)) {
	    if(argc > 2) {
		menu_setfont( pmenu, argv[2] );
		menu_setfont( stubmenu, argv[2] );
	    }
	    msg("fmenu font %s", menu_getfont(pmenu));

	} else if(argc == 2 && atof(argv[1]) != 0) {
	    menu_setheight( pmenu, atof(argv[1]) );

	} else if(argc == 3) {
	    menu_setpos( pmenu, atof(argv[1]), atof(argv[2]) );

	} else if(argc <= 1 || argv[1][0] == '?' || !strncmp(argv[1],"help",4)) {
	    msg("\"fmenu ?\" for help");
	    msg("fmenu pos %.3f %.3f (xpos ypos, in pixels)", pmenu->x0, pmenu->y0);
	    msg("fmenu height %.3f (fraction of screen height; negative = inverted)", pmenu->yspan);
	    msg("fmenu wall %d (cave.h wall number)", pmenu->cavewall);
	    msg("fmenu hide [on|off]");
	    msg("fmenu font %s (X font name)", menu_getfont(pmenu));
	    msg("fmenu demandfps %g (hide scene if FPS too low)", st->menudemandfps);
	} else {
	    msg("fmenu: expected \"pos\" or \"height\" or \"hide\" or \"font\" or \"wall\".");
	    msg("Try just \"fmenu\" for help.");
	}
#endif

  } else if(!strcmp( argv[0], "datascale" ) && argc>1) {
	float s, v = atof(argv[1]);
	if(v!=0) {
	    struct specklist *sl;
	    struct speck *p;
	    int i;
	    for(sl = st->sl; sl != NULL; sl = sl->next) {
		s = v / sl->scaledby;
		for(i = 0, p = sl->specks; i < sl->nspecks; i++, p = NextSpeck(p, sl, 1)) {
		    p->p.x[0] *= s; p->p.x[1] *= s; p->p.x[2] *= s;
		}
		sl->scaledby = v;
	    }
	}
  } else if(!strcmp( argv[0], "where" ) || !strcmp( argv[0], "w" )) {
	tellwhere(st);

  } else if(!strcmp( argv[0], "version" )) {
	extern char partiview_version[];
	char *cp = strchr(local_id, ',');	/* ... partibrains.c,v N.NN */
	if(cp) {
	    cp += 3;
	    msg("version %s (brains %.*s)", partiview_version, strcspn(cp, " "), cp);
	}
teuben's avatar
teuben committed
  }
  else
    return 0;

  *stp = st;	/* in case it changed, e.g. because of an "object" cmd */
  return 1;
}