Esempio n. 1
0
File: dream.c Progetto: Elive/ecomp
Bool
fxDreamModelStep(CompScreen *s, CompWindow *w, float time)
{
   if (!defaultAnimStep(s, w, time))
     return FALSE;

   ANIM_SCREEN(s);
   ANIM_WINDOW(w);

   Model *model = aw->model;

   float forwardProgress;
   if ((aw->curWindowEvent == WindowEventMinimize ||
        aw->curWindowEvent == WindowEventUnminimize) &&
       animGetB(as, aw, ANIM_SCREEN_OPTION_DREAM_Z2TOM))
     {
        float dummy;
        fxZoomAnimProgress(as, aw, &forwardProgress, &dummy, TRUE);
     }
   else
     forwardProgress = defaultAnimProgress(aw);

   int i;
   for (i = 0; i < model->numObjects; i++)
     fxDreamModelStepObject(w,
                            model,
                            &model->objects[i], forwardProgress);

   return TRUE;
}
void
updateOptionSets (CompScreen *s,
		  AnimEvent e)
{
    ANIM_SCREEN (s);

    OptionSets *oss = &as->eventOptionSets[e];
    CompListValue *listVal = &as->opt[customOptionOptionIds[e]].value.list;
    int n = listVal->nValue;

    if (oss->sets)
	freeSingleEventOptionSets(oss);

    oss->sets = calloc(n, sizeof(OptionSet));
    if (!oss->sets)
    {
	compLogMessage ("animation", CompLogLevelError,
			"Not enough memory");
	return;
    }
    oss->nSets = n;

    int i;
    for (i = 0; i < n; i++)
	updateOptionSet(s, &oss->sets[i], listVal->value[i].s);
}
Esempio n. 3
0
File: glide.c Progetto: Elive/ecomp
Bool
fxGlideLetOthersDrawGeoms(CompScreen *s, CompWindow *w)
{
   ANIM_SCREEN(s);
   ANIM_WINDOW(w);

   return !fxGlideIsPolygonBased(as, aw);
}
Esempio n. 4
0
File: glide.c Progetto: Elive/ecomp
void
fxGlideInit(CompScreen *s, CompWindow *w)
{
   ANIM_SCREEN(s);
   ANIM_WINDOW(w);

   if (fxGlideZoomToTaskBar(as, aw))
     {
        aw->animTotalTime /= ZOOM_PERCEIVED_T;
        aw->animRemainingTime = aw->animTotalTime;
     }

   if (!fxGlideIsPolygonBased(as, aw))
     {
        defaultAnimInit (s, w);
        return; // we're done with CompTransform-based glide initialization
     }

   // for polygon-based glide effect

   float finalDistFac;
   float finalRotAng;
   float thickness;

   fxGlideGetParams(as, aw, &finalDistFac, &finalRotAng, &thickness);

   PolygonSet *pset = aw->polygonSet;

   pset->includeShadows = (thickness < 1e-5);

   if (!tessellateIntoRectangles(w, 1, 1, thickness))
     return;

   PolygonObject *p = pset->polygons;

   int i;

   for (i = 0; i < pset->nPolygons; i++, p++)
     {
        p->rotAxis.x = 1;
        p->rotAxis.y = 0;
        p->rotAxis.z = 0;

        p->finalRelPos.x = 0;
        p->finalRelPos.y = 0;
        p->finalRelPos.z = finalDistFac * 0.8 * DEFAULT_Z_CAMERA * s->width;

        p->finalRotAng = finalRotAng;
     }
   pset->allFadeDuration = 1.0f;
   pset->backAndSidesFadeDur = 0.2f;
   pset->doLighting = TRUE;
   pset->correctPerspective = CorrectPerspectivePolygon;
}
Esempio n. 5
0
File: glide.c Progetto: Elive/ecomp
void
fxGlideUpdateBB(CompOutput *output,
                CompWindow *w)
{
   ANIM_SCREEN(w->screen);
   ANIM_WINDOW(w);

   if (fxGlideIsPolygonBased (as, aw))
     polygonsUpdateBB (output, w);
   else
     compTransformUpdateBB (output, w);
}
Esempio n. 6
0
File: glide.c Progetto: Elive/ecomp
void
fxGlidePostPaintWindow(CompScreen *s, CompWindow *w)
{
   ANIM_SCREEN(s);
   ANIM_WINDOW(w);

   if (fxGlideIsPolygonBased(as, aw))
     polygonsPostPaintWindow(s, w);
   else if (90 < aw->glideModRotAngle &&
            aw->glideModRotAngle < 270)
     glCullFace(GL_BACK);
}
Esempio n. 7
0
File: glide.c Progetto: Elive/ecomp
static void
applyGlideTransform(CompWindow *w, CompTransform *transform)
{
   ANIM_SCREEN(w->screen);
   ANIM_WINDOW(w);

   float finalDistFac;
   float finalRotAng;
   float thickness;

   fxGlideGetParams(as, aw, &finalDistFac, &finalRotAng, &thickness);

   float forwardProgress;
   if (fxGlideZoomToTaskBar(as, aw))
     {
        float dummy;
        fxZoomAnimProgress(as, aw, &forwardProgress, &dummy, TRUE);
     }
   else
     forwardProgress = fxGlideAnimProgress(aw);

   float finalz = finalDistFac * 0.8 * DEFAULT_Z_CAMERA *
     w->screen->width;

   Vector3d rotAxis = {1, 0, 0};
   Point3d rotAxisOffset =
   {WIN_X(w) + WIN_W(w) / 2.0f,
    WIN_Y(w) + WIN_H(w) / 2.0f,
    0};
   Point3d translation = {0, 0, finalz * forwardProgress};

   float rotAngle = finalRotAng * forwardProgress;
   aw->glideModRotAngle = fmodf(rotAngle + 720, 360.0f);

   // put back to window position
   matrixTranslate (transform, rotAxisOffset.x, rotAxisOffset.y, 0);

   resetAndPerspectiveDistortOnZ (transform, -1.0 / w->screen->width);

   // animation movement
   matrixTranslate (transform, translation.x, translation.y, translation.z);

   // animation rotation
   matrixRotate (transform, rotAngle, rotAxis.x, rotAxis.y, rotAxis.z);

   // intentional scaling of z by 0 to prevent weird opacity results and
   // flashing that happen when z coords are between 0 and 1 (bug in ecomp?)
   matrixScale (transform, 1.0f, 1.0f, 0.0f);

   // place window rotation axis at origin
   matrixTranslate (transform, -rotAxisOffset.x, -rotAxisOffset.y, 0);
}
Esempio n. 8
0
File: glide.c Progetto: Elive/ecomp
void
fxGlideUpdateWindowTransform(CompScreen    *s,
                             CompWindow    *w,
                             CompTransform *wTransform)
{
   ANIM_SCREEN(s);
   ANIM_WINDOW(w);

   if (fxGlideIsPolygonBased (as, aw))
     return;

   // apply the transform
   matmul4 (wTransform->m, wTransform->m, aw->transform.m);
}
Esempio n. 9
0
File: dream.c Progetto: Elive/ecomp
void
fxDreamAnimInit(CompScreen *s, CompWindow *w)
{
   ANIM_SCREEN(s);
   ANIM_WINDOW(w);

   if (animZoomToIcon(as, aw))
     aw->animTotalTime /= ZOOM_PERCEIVED_T;
   else
     aw->animTotalTime /= DREAM_PERCEIVED_T;

   aw->animRemainingTime = aw->animTotalTime;

   defaultAnimInit(s, w);
}
Esempio n. 10
0
File: glide.c Progetto: Elive/ecomp
Bool
fxGlideAnimStep(CompScreen *s, CompWindow *w, float time)
{
   ANIM_SCREEN(s);
   ANIM_WINDOW(w);

   if (fxGlideIsPolygonBased(as, aw))
     return polygonsAnimStep(s, w, time);
   else
     {
        if (!defaultAnimStep(s, w, time))
          return FALSE;

        applyGlideTransform (w, &aw->transform);

        return TRUE;
     }
}
CompOptionValue *
animGetPluginOptVal (CompWindow *w,
		     ExtensionPluginInfo *pluginInfo,
		     int optionId)
{
    ANIM_WINDOW (w);
    ANIM_SCREEN (w->screen);

    OptionSet *os =
	&as->eventOptionSets[win2AnimEventMap[aw->com.curWindowEvent]].
	sets[aw->curAnimSelectionRow];
    IdValuePair *pair = os->pairs;

    int i;
    for (i = 0; i < os->nPairs; i++, pair++)
	if (pair->pluginInfo == pluginInfo &&
	    pair->optionId == optionId)
	    return &pair->value;
    return &pluginInfo->effectOptions[optionId].value;
}
Esempio n. 12
0
Bool
fxCurvedFoldModelStep(CompScreen *s, CompWindow *w, float time)
{
    if (!defaultAnimStep(s, w, time))
        return FALSE;

    ANIM_SCREEN(s);
    ANIM_WINDOW(w);

    Model *model = aw->model;

    float forwardProgress;
    if ((aw->curWindowEvent == WindowEventMinimize ||
            aw->curWindowEvent == WindowEventUnminimize) &&
            animGetB(as, aw, ANIM_SCREEN_OPTION_CURVED_FOLD_Z2TOM))
    {
        float dummy;
        fxZoomAnimProgress(as, aw, &forwardProgress, &dummy, TRUE);
    }
    else
        forwardProgress = defaultAnimProgress(aw);

    float curveMaxAmp =
        animGetF(as, aw, ANIM_SCREEN_OPTION_CURVED_FOLD_AMP) * WIN_W(w) *
        pow(WIN_H(w) / (s->height * 1.2f), 0.7);
    int i;
    for (i = 0; i < model->numObjects; i++)
        fxCurvedFoldModelStepObject
        (w,
         model,
         &model->objects[i],
         forwardProgress,
         curveMaxAmp);

    return TRUE;
}
static void
updateOptionSet(CompScreen *s, OptionSet *os, char *optNamesValuesOrig)
{
    ANIM_SCREEN(s);
    int len = strlen(optNamesValuesOrig);
    char *optNamesValues = calloc(len + 1, 1);

    // Find the first substring with no spaces in it
    sscanf(optNamesValuesOrig, " %s ", optNamesValues);
    if (strlen(optNamesValues) == 0)
    {
	free(optNamesValues);
	return;
    }
    // Backup original, since strtok is destructive
    strcpy(optNamesValues, optNamesValuesOrig);

    char *name;
    char *nameTrimmed = calloc(len + 1, 1);
    char *valueStr = NULL;
    char *betweenPairs = ",";
    char *betweenOptVal = "=";

    // Count number of pairs
    char *pairToken = optNamesValuesOrig;
    int nPairs = 1;
	
    while ((pairToken = strchr(pairToken, betweenPairs[0])))
    {
	pairToken++; // skip delimiter
	nPairs++;
    }

    if (os->pairs)
	free(os->pairs);
    os->pairs = calloc(nPairs, sizeof(IdValuePair));
    if (!os->pairs)
    {
	os->nPairs = 0;
	free(optNamesValues);
	free(nameTrimmed);
	compLogMessage ("animation", CompLogLevelError,
			"Not enough memory");
	return;
    }
    os->nPairs = nPairs;

    // Tokenize pairs
    name = strtok(optNamesValues, betweenOptVal);

    IdValuePair *pair = &os->pairs[0];
    int errorNo = -1;
    int i;
    for (i = 0; name && i < nPairs; i++, pair++)
    {
	errorNo = 0;
	if (strchr(name, betweenPairs[0])) // handle "a, b=4" case
	{
	    errorNo = 1;
	    break;
	}

	sscanf(name, " %s ", nameTrimmed);
	if (strlen(nameTrimmed) == 0)
	{
	    errorNo = 2;
	    break;
	}
	valueStr = strtok(NULL, betweenPairs);
	if (!valueStr)
	{
	    errorNo = 3;
	    break;
	}

	// TODO: Fix: Convert to "pluginname:option_name" format
	// Warning: Assumes that option names in different extension plugins
	// will be different.
	Bool matched = FALSE;
	const ExtensionPluginInfo *extensionPluginInfo;
	CompOption *o;
	int optId;
	int k;
	for (k = 0; k < as->nExtensionPlugins; k++)
	{
	    extensionPluginInfo = as->extensionPlugins[k];
	    unsigned int nOptions = extensionPluginInfo->nEffectOptions;
	    o = extensionPluginInfo->effectOptions;
	    for (optId = 0; optId < nOptions; optId++, o++)
	    {
		if (strcasecmp(nameTrimmed, o->name) == 0)
		{
		    matched = TRUE;
		    break;
		}
	    }
	    if (matched)
		break;
	}
	if (!matched)
	{
	    errorNo = 4;
	    break;
	}
	CompOptionValue v;

	pair->pluginInfo = extensionPluginInfo;
	pair->optionId = optId;
	int valueRead = -1;
	switch (o->type)
	{
	case CompOptionTypeBool:
	    valueRead = sscanf(valueStr, " %d ", &pair->value.b);
	    break;
	case CompOptionTypeInt:
	    valueRead = sscanf(valueStr, " %d ", &v.i);
	    if (valueRead > 0)
	    {
		// Store option's original value
		int backup = o->value.i;
		if (compSetIntOption (o, &v))
		    pair->value = v;
		else
		    errorNo = 7;
		// Restore value
		o->value.i = backup;
	    }
	    break;
	case CompOptionTypeFloat:
	    valueRead = sscanf(valueStr, " %f ", &v.f);
	    if (valueRead > 0)
	    {
		// Store option's original value
		float backup = o->value.f;
		if (compSetFloatOption (o, &v))
		    pair->value = v;
		else
		    errorNo = 7;
		// Restore value
		o->value.f = backup;
	    }
	    break;
	case CompOptionTypeString:
	    v.s = calloc (strlen(valueStr) + 1, 1); // TODO: not freed
	    if (!v.s)
	    {
		compLogMessage ("animation", CompLogLevelError,
				"Not enough memory");
		return;
	    }
	    strcpy(v.s, valueStr);
	    valueRead = 1;
	    break;
	case CompOptionTypeColor:
	{
	    unsigned int c[4];
	    valueRead = sscanf (valueStr, " #%2x%2x%2x%2x ",
				&c[0], &c[1], &c[2], &c[3]);
	    if (valueRead == 4)
	    {
		CompOptionValue * pv = &pair->value;
		int j;
		for (j = 0; j < 4; j++)
		    pv->c[j] = c[j] << 8 | c[j];
	    }
	    else
		errorNo = 6;
	    break;
	}
	default:
	    break;
	}
	if (valueRead == 0)
	    errorNo = 6;
	if (errorNo > 0)
	    break;
	// If valueRead is -1 here, then it must be a
	// non-(int/float/string) option, which is not supported yet.
	// Such an option doesn't currently exist anyway.

	errorNo = -1;
	name = strtok(NULL, betweenOptVal);
    }

    if (i < nPairs)
    {
	switch (errorNo)
	{
	case -1:
	case 2:
	    compLogMessage ("animation", CompLogLevelError,
			    "Option name missing in \"%s\"",
			    optNamesValuesOrig);
	    break;
	case 1:
	case 3:
	    compLogMessage ("animation", CompLogLevelError,
			    "Option value missing in \"%s\"",
			    optNamesValuesOrig);
	    break;
	case 4:
	    compLogMessage ("animation", CompLogLevelError,
			    "Unknown option \"%s\" in \"%s\"",
			    nameTrimmed, optNamesValuesOrig);
	    break;
	case 6:
	    compLogMessage ("animation", CompLogLevelError,
			    "Invalid value \"%s\" in \"%s\"",
			    valueStr, optNamesValuesOrig);
	    break;
	case 7:
	    compLogMessage ("animation", CompLogLevelError,
			    "Value \"%s\" out of range in \"%s\"",
			    valueStr, optNamesValuesOrig);
	    break;
	default:
	    break;
	}
	free(os->pairs);
	os->pairs = 0;
	os->nPairs = 0;
    }
    free(optNamesValues);
    free(nameTrimmed);
}
// Returns FALSE if the subject is destroyed or if there was an error when
// calculating the dodge box
static Bool
fxDodgeFindDodgeBox (CompWindow *w, XRectangle *dodgeBox)
{
    ANIM_SCREEN(w->screen);
    ANIM_WINDOW(w);

    if (!aw->dodgeSubjectWin)  // if the subject is destroyed
	return FALSE;

    // Find the box to be dodged, it can contain multiple windows
    // when there are dialog/utility windows of subject windows
    // (stacked in the moreToBePaintedNext chain)
    // Then this would be a bounding box of the subject windows
    // intersecting with dodger.
    Region wRegion = XCreateRegion();
    if (!wRegion)
	return FALSE;

    Region dodgeRegion = XCreateRegion();
    if (!dodgeRegion)
    {
	XDestroyRegion (wRegion);
	return FALSE;
    }

    XRectangle rect;
    rect.x = WIN_X(w);
    rect.y = WIN_Y(w);
    rect.width = WIN_W(w);
    rect.height = WIN_H(w);

    int dodgeMaxAmount = (int)aw->dodgeMaxAmount;

    // to compute if subject(s) intersect with dodger w,
    // enlarge dodger window's box so that it encloses all of the covered
    // region during dodge movement. This corrects the animation when
    // there are >1 subjects (a window with its dialog/utility windows).
    switch (aw->dodgeDirection)
    {
    case 0:
	rect.y += dodgeMaxAmount;
	rect.height -= dodgeMaxAmount;
	break;
    case 1:
	rect.height += dodgeMaxAmount;
	break;
    case 2:
	rect.x += dodgeMaxAmount;
	rect.width -= dodgeMaxAmount;
	break;
    case 3:
	rect.width += dodgeMaxAmount;
	break;
    }
    XUnionRectWithRegion(&rect, &emptyRegion, wRegion);

    AnimWindow *awCur;
    CompWindow *wCur = aw->dodgeSubjectWin;
    for (; wCur; wCur = awCur->moreToBePaintedNext)
    {
	fxDodgeProcessSubject(wCur, wRegion, dodgeRegion,
			      wCur == aw->dodgeSubjectWin);
	awCur = GET_ANIM_WINDOW(wCur, as);
	if (!awCur)
	    break;
    }

    AnimWindow *awSubj = GET_ANIM_WINDOW(aw->dodgeSubjectWin, as);
    wCur = awSubj->moreToBePaintedPrev;
    for (; wCur; wCur = awCur->moreToBePaintedPrev)
    {
	fxDodgeProcessSubject(wCur, wRegion, dodgeRegion, FALSE);
	awCur = GET_ANIM_WINDOW(wCur, as);
	if (!awCur)
	    break;
    }

    XClipBox(dodgeRegion, dodgeBox);

    XDestroyRegion (wRegion);
    XDestroyRegion (dodgeRegion);

    return TRUE;
}
void
fxDodgePostPreparePaintScreen (CompWindow *w)
{
    ANIM_SCREEN(w->screen);
    ANIM_WINDOW(w);

    // Only dodge subjects should be processed here
    if (!aw->isDodgeSubject)
	return;

    if (!aw->restackInfo)
	return;

    if (aw->skipPostPrepareScreen)
	return;

    // Dodgy window
    CompWindow *dw;
    AnimWindow *adw = NULL;
    for (dw = aw->dodgeChainStart; dw; dw = adw->dodgeChainNext)
    {
	adw = GET_ANIM_WINDOW(dw, as);
	if (!adw)
	    break;
	// find the first dodging window that hasn't yet
	// reached 50% progress yet. The subject window should be
	// painted right behind that one (or right in front of it if
	// the subject window is being lowered).
	if (!(adw->com.transformProgress > 0.5f))
	    break;
    }
    AnimWindow *awOldHost = NULL;
	
    if (aw->restackInfo->raised &&
	dw != aw->winThisIsPaintedBefore) // w's host is changing
    {
	if (aw->winThisIsPaintedBefore)
	{
	    // Clear old host
	    awOldHost = GET_ANIM_WINDOW(aw->winThisIsPaintedBefore, as);			
	    awOldHost->winToBePaintedBeforeThis = NULL;
	}
	if (dw && adw) // if a dodgy win. is still at <0.5 progress
	{
	    // Put subject right behind adw (new host)
	    adw->winToBePaintedBeforeThis = w;
	}
	// otherwise all dodgy win.s have passed 0.5 progress

	CompWindow *wCur = w;
	while (wCur)
	{
	    AnimWindow *awCur = GET_ANIM_WINDOW(wCur, as);
	    awCur->winThisIsPaintedBefore = dw; // dw can be null, which is ok
	    wCur = awCur->moreToBePaintedNext;
	}
    }
    else if (!aw->restackInfo->raised)
    {
	// Put subject right in front of dw
	// But we need to find the dodgy window above dw
	// (since we need to put subject *behind* another one)

	CompWindow *wDodgeChainAbove = NULL;

	if (dw && adw) // if a dodgy win. is still at <0.5 progress
	{
	    if (adw->dodgeChainPrev)
		wDodgeChainAbove = adw->dodgeChainPrev;
	    else
		wDodgeChainAbove = aw->restackInfo->wOldAbove;

	    if (!wDodgeChainAbove)
		compLogMessage ("animation", CompLogLevelError,
				"%s: error at line %d", __FILE__, __LINE__);
	    else if (aw->winThisIsPaintedBefore !=
		     wDodgeChainAbove) // w's host is changing
	    {
		AnimWindow *adw2 = GET_ANIM_WINDOW(wDodgeChainAbove, as);

		// Put subject right behind adw2 (new host)
		adw2->winToBePaintedBeforeThis = w;
	    }
	}
	if (aw->winThisIsPaintedBefore &&
	    aw->winThisIsPaintedBefore != wDodgeChainAbove)
	{
	    awOldHost = GET_ANIM_WINDOW(aw->winThisIsPaintedBefore, as);

	    // Clear old host
	    awOldHost->winToBePaintedBeforeThis = NULL;
	}
	// otherwise all dodgy win.s have passed 0.5 progress

	// wDodgeChainAbove can be null, which is ok
	aw->winThisIsPaintedBefore = wDodgeChainAbove;
    }
}
Esempio n. 16
0
File: skewer.c Progetto: Elive/ecomp
void
fxSkewerInit(CompScreen *s, CompWindow *w)
{
   ANIM_SCREEN (s);
   ANIM_WINDOW (w);

   aw->animTotalTime /= SKEWER_PERCEIVED_T;
   aw->animRemainingTime = aw->animTotalTime;

   float thickness = animGetF (as, aw, ANIM_SCREEN_OPTION_SKEWER_THICKNESS);
   int rotation = animGetI (as, aw, ANIM_SCREEN_OPTION_SKEWER_ROTATION);
   int gridSizeX = animGetI (as, aw, ANIM_SCREEN_OPTION_SKEWER_GRIDSIZE_X);
   int gridSizeY = animGetI (as, aw, ANIM_SCREEN_OPTION_SKEWER_GRIDSIZE_Y);

   int dir[2]; // directions array
   int c = 0; // number of directions

   getDirection (dir, &c,
                 animGetI (as, aw, ANIM_SCREEN_OPTION_SKEWER_DIRECTION));

   if (animGetI (as, aw, ANIM_SCREEN_OPTION_SKEWER_TESS) == PolygonTessHex)
     {
        if (!tessellateIntoHexagons (w, gridSizeX, gridSizeY, thickness))
          return;
     }
   else
     {
        if (!tessellateIntoRectangles (w, gridSizeX, gridSizeY, thickness))
          return;
     }

   PolygonSet *pset = aw->polygonSet;
   PolygonObject *p = pset->polygons;

   int times[pset->nPolygons];
   int last_time = pset->nPolygons - 1;

   int i;
   for (i = 0; i < pset->nPolygons; i++)
     times[i] = i;

   for (i = 0; i < pset->nPolygons; i++, p++)
     {
        if (c > 0)
          {
             switch (dir[(int)floor (RAND_FLOAT () * c)])
               {
                case 0:
     // left
                  p->finalRelPos.x = -s->width;
                  p->rotAxis.x = rotation;
                  break;

                case 1:
     // right
                  p->finalRelPos.x = s->width;
                  p->rotAxis.x = rotation;
                  break;

                case 2:
     // up
                  p->finalRelPos.y = -s->height;
                  p->rotAxis.y = rotation;
                  break;

                case 3:
     // down
                  p->finalRelPos.y = s->height;
                  p->rotAxis.y = rotation;
                  break;

                case 4:
     // in
                  p->finalRelPos.z = -.8 * DEFAULT_Z_CAMERA * s->width;
                  p->rotAxis.x = rotation;
                  p->rotAxis.y = rotation;
                  break;

                case 5:
     // out
                  p->finalRelPos.z = .8 * DEFAULT_Z_CAMERA * s->width;
                  p->rotAxis.x = rotation;
                  p->rotAxis.y = rotation;
                  break;
               }

             p->finalRotAng = rotation;
          }
        // if no direction is set - just fade

        // choose random start_time
        int rand_time = floor (RAND_FLOAT () * last_time);

        p->moveStartTime = 0.8 / (float)pset->nPolygons * times[rand_time];
        p->moveDuration = 1 - p->moveStartTime;

        p->fadeStartTime = p->moveStartTime + 0.2;
        p->fadeDuration = 1 - p->fadeStartTime;

        times[rand_time] = times[last_time];    // copy last one over times[rand_time]
        last_time--; //descrease last_time
     }

   pset->doDepthTest = TRUE;
   pset->doLighting = TRUE;
   pset->correctPerspective = CorrectPerspectiveWindow;
}