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); }
Bool fxGlideLetOthersDrawGeoms(CompScreen *s, CompWindow *w) { ANIM_SCREEN(s); ANIM_WINDOW(w); return !fxGlideIsPolygonBased(as, aw); }
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; }
void fxGlideUpdateBB(CompOutput *output, CompWindow *w) { ANIM_SCREEN(w->screen); ANIM_WINDOW(w); if (fxGlideIsPolygonBased (as, aw)) polygonsUpdateBB (output, w); else compTransformUpdateBB (output, w); }
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); }
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); }
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); }
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); }
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; }
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; } }
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; }