[fusion-commits] Animation plugin: Changes to 'master' (a86307e95caeed382811b2182d6355204b927fb8)

cornelius at server.beryl-project.org cornelius at server.beryl-project.org
Sun Aug 5 11:59:01 CEST 2007


New commits:
commit a86307e95caeed382811b2182d6355204b927fb8
Author: Erkin Bahceci <erkinbah at gmail.com>
Date:   Sun Aug 5 05:57:40 2007 -0400

    Better error message.

commit c6e72de450fcc28538f7a4c4108adb8500bba3ef
Author: Erkin Bahceci <erkinbah at gmail.com>
Date:   Sun Aug 5 05:53:17 2007 -0400

    Update first-effect-setting constant.

commit cea7f3e7297816ff53eda6ba25af6331e5f3fb0e
Author: Erkin Bahceci <erkinbah at gmail.com>
Date:   Sun Aug 5 05:50:13 2007 -0400

    Tweak Skewer defaults.

commit 53de240bba606239d3229d173a8ef21786faf15f
Author: Carlo Palma <carlopalma at salug.it>
Date:   Sun Aug 5 05:48:14 2007 -0400

    New effect: Airplane

commit ea343e1b89ddd08b1bc805fb2f27e89850afc2e0
Author: Tomasz Kolodziejski <tkolodziejski at gmail.com>
Date:   Sun Aug 5 04:23:14 2007 -0400

    New effects: Fold & Skewer


 airplane3d.c         |  972 ++++++++++++++++++++++++++++++++++++++++++++++++++
 animation-internal.h |  117 ++++++-
 animation.c          |   44 ++-
 animation.xml.in     |  439 +++++++++++++++++------
 fold3d.c             |  241 +++++++++++++
 options.c            |    2 +-
 skewer.c             |  225 ++++++++++++
 7 files changed, 1921 insertions(+), 119 deletions(-)
 create mode 100644 airplane3d.c
 create mode 100644 fold3d.c
 create mode 100644 skewer.c


Modified: fusion/plugins/animation/airplane3d.c
new file mode 100644
===================================================================
--- /dev/null
+++ fusion/plugins/animation/airplane3d.c
@@ -0,0 +1,972 @@
+/*
+ * Animation plugin for compiz/beryl
+ *
+ * airplane3d.c
+ *
+ * Copyright : (C) 2006 Erkin Bahceci
+ * E-mail    : erkinbah at gmail.com
+ *
+ * Based on Wobbly and Minimize plugins by
+ *           : David Reveman
+ * E-mail    : davidr at novell.com>
+ *
+ * Airplane added by : Carlo Palma
+ * E-mail            : carlopalma at salug.it
+ * Based on code originally written by Mark J. Kilgard
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "animation-internal.h"
+
+// Divide the window in 8 polygons (6 quadrilaters and 2 triangles (all of them draw as quadrilaters))
+// Based on tessellateIntoRectangles and tessellateIntoHexagons. Improperly called tessellation.
+static Bool
+tessellateIntoAirplane (CompWindow * w)
+{
+    ANIM_WINDOW (w);
+
+    PolygonSet *pset = aw->polygonSet;
+
+    if (!pset)
+	return FALSE;
+
+    float winLimitsX;		// boundaries of polygon tessellation
+    float winLimitsY;
+    float winLimitsW;
+    float winLimitsH;
+
+    if (pset->includeShadows)
+    {
+	winLimitsX = WIN_X (w);
+	winLimitsY = WIN_Y (w);
+	winLimitsW = WIN_W (w) - 1;	// avoid artifact on right edge
+	winLimitsH = WIN_H (w);
+    }
+    else
+    {
+	winLimitsX = BORDER_X (w);
+	winLimitsY = BORDER_Y (w);
+	winLimitsW = BORDER_W (w);
+	winLimitsH = BORDER_H (w);
+    }
+
+    int numpol = 8;
+    if (pset->nPolygons != numpol)
+    {
+	if (pset->nPolygons > 0)
+	    freePolygonObjects (pset);
+
+	pset->nPolygons = numpol;
+
+	pset->polygons = calloc (pset->nPolygons, sizeof (PolygonObject));
+	if (!pset->polygons)
+	{
+	    compLogMessage (w->screen->display, "animation",
+			    CompLogLevelError, "Not enough memory");
+	    pset->nPolygons = 0;
+	    return FALSE;
+	}
+    }
+
+    float thickness;
+    thickness = 1;
+    thickness /= w->screen->width;
+    pset->thickness = thickness;
+    pset->nTotalFrontVertices = 0;
+
+    float W = (float)winLimitsW;
+    float H2 = (float)winLimitsH / 2;
+    float H3 = (float)winLimitsH / 3;
+    float H6 = (float)winLimitsH / 6;
+    float halfThick = pset->thickness / 2;
+
+    /**
+     *
+     * These correspond to the polygons:
+     * based on GLUT sample origami.c code by Mark J. Kilgard
+     *                  
+     *       |-               W              -| 
+     *       |-    H2     -|
+     *
+     * - --  +----+--------+------------------+
+     * |     |    |       /                   |
+     *       |    | 6   /                     | 
+     *       | 7  |   /              5        |
+     *   H2  |    | +                         |
+     *       |    +--------+------------------+
+     *       |  /                 4           |
+     * H __  |/____________.__________________|
+     *       |\          center               |
+     *       |  \                 3           |
+     *       |    +--------+------------------+
+     *       |    | +                         |
+     *       | 0  |   \                       |
+     *       |    |  1  \            2        |  
+     * |     |    |       \                   |
+     * -     +----+--------+------------------+
+     *
+     *
+     */
+
+    PolygonObject *p = pset->polygons;
+    int i;
+
+    for (i = 0; i < 8; i++, p++)
+    {
+	float topRightY, topLeftY, bottomLeftY, bottomRightY;
+	float topLeftX, topRightX, bottomLeftX, bottomRightX;
+
+	float n6, n7, n9, n10, n12, n13, n15, n16;
+
+	p->centerPos.x = p->centerPosStart.x = winLimitsX + H2;
+	p->centerPos.y = p->centerPosStart.y = winLimitsY + H2;
+	p->centerPos.z = p->centerPosStart.z = -halfThick;
+	p->rotAngle = p->rotAngleStart = 0;
+
+	p->nSides = 4;
+	p->nVertices = 2 * 4;
+	pset->nTotalFrontVertices += 4;
+
+	switch (i)
+	{
+	case 0:
+	    topLeftX = -H2;
+	    topLeftY = 0;
+	    bottomLeftX = -H2;
+	    bottomLeftY = H2;
+	    bottomRightX = -H3;
+	    bottomRightY = H2;
+	    topRightX = -H3;
+	    topRightY = H6;
+	    n6 = -1;
+	    n7 = 0;
+	    n9 = 0;
+	    n10 = 1;
+	    n12 = 1;
+	    n13 = 0;
+	    n15 = 1 / sqrt (2);
+	    n16 = 1 / sqrt (2);
+	    break;
+	case 1:
+	    topLeftX = -H3;
+	    topLeftY = H6;
+	    bottomLeftX = -H3;
+	    bottomLeftY = H2;
+	    bottomRightX = 0;
+	    bottomRightY = H2;
+	    topRightX = 0;
+	    topRightY = H2;
+	    n6 = -1;
+	    n7 = 0;
+	    n9 = 0;
+	    n10 = 1;
+	    n12 = 1 / sqrt (2);
+	    n13 = 1 / sqrt (2);
+	    n15 = 1 / sqrt (2);
+	    n16 = 1 / sqrt (2);
+	    break;
+	case 2:
+	    topLeftX = -H3;
+	    topLeftY = H6;
+	    bottomLeftX = 0;
+	    bottomLeftY = H2;
+	    bottomRightX = W - H2;
+	    bottomRightY = H2;
+	    topRightX = W - H2;
+	    topRightY = H6;
+	    n6 = -1 / sqrt (2);
+	    n7 = 1 / sqrt (2);
+	    n9 = 0;
+	    n10 = 1;
+	    n12 = 1;
+	    n13 = 0;
+	    n15 = 0;
+	    n16 = -1;
+	    break;
+	case 3:
+	    topLeftX = -H2;
+	    topLeftY = 0;
+	    bottomLeftX = -H3;
+	    bottomLeftY = H6;
+	    bottomRightX = W - H2;
+	    bottomRightY = H6;
+	    topRightX = W - H2;
+	    topRightY = 0;
+	    n6 = -1 / sqrt (2);
+	    n7 = 1 / sqrt (2);
+	    n9 = 0;
+	    n10 = 1;
+	    n12 = 1;
+	    n13 = 0;
+	    n15 = 0;
+	    n16 = -1;
+	    break;
+	case 4:
+	    topLeftX = -H3;
+	    topLeftY = -H6;
+	    bottomLeftX = -H2;
+	    bottomLeftY = 0;
+	    bottomRightX = W - H2;
+	    bottomRightY = 0;
+	    topRightX = W - H2;
+	    topRightY = -H6;
+	    n6 = -1 / sqrt (2);
+	    n7 = -1 / sqrt (2);
+	    n9 = 0;
+	    n10 = 1;
+	    n12 = 1;
+	    n13 = 0;
+	    n15 = 0;
+	    n16 = -1;
+	    break;
+	case 5:
+	    topLeftX = 0;
+	    topLeftY = -H2;
+	    bottomLeftX = -H3;
+	    bottomLeftY = -H6;
+	    bottomRightX = W - H2;
+	    bottomRightY = -H6;
+	    topRightX = W - H2;
+	    topRightY = -H2;
+	    n6 = -1 / sqrt (2);
+	    n7 = -1 / sqrt (2);
+	    n9 = 0;
+	    n10 = 1;
+	    n12 = 1;
+	    n13 = 0;
+	    n15 = 0;
+	    n16 = -1;
+	    break;
+	case 6:
+	    topLeftX = -H3;
+	    topLeftY = -H2;
+	    bottomLeftX = -H3;
+	    bottomLeftY = -H6;
+	    bottomRightX = -H3;
+	    bottomRightY = -H6;
+	    topRightX = 0;
+	    topRightY = -H2;
+	    n6 = -1;
+	    n7 = 0;
+	    n9 = 1 / sqrt (2);
+	    n10 = 1 / sqrt (2);
+	    n12 = 1 / sqrt (2);
+	    n13 = 1 / sqrt (2);
+	    n15 = 0;
+	    n16 = -1;
+	    break;
+	default:
+	    topLeftX = -H2;
+	    topLeftY = -H2;
+	    bottomLeftX = -H2;
+	    bottomLeftY = 0;
+	    bottomRightX = -H3;
+	    bottomRightY = -H6;
+	    topRightX = -H3;
+	    topRightY = -H2;
+	    n6 = -1;
+	    n7 = 0;
+	    n9 = 1 / sqrt (2);
+	    n10 = 1 / sqrt (2);
+	    n12 = 1;
+	    n13 = 0;
+	    n15 = 0;
+	    n16 = -1;
+	    break;
+	}
+
+	// 4 front, 4 back vertices
+	if (!p->vertices)
+	{
+	    p->vertices = calloc (8 * 3, sizeof (GLfloat));
+	}
+	if (!p->vertices)
+	{
+	    compLogMessage (w->screen->display, "animation",
+			    CompLogLevelError, "Not enough memory");
+	    freePolygonObjects (pset);
+	    return FALSE;
+	}
+	GLfloat *pv = p->vertices;
+
+	// Determine 4 front vertices in ccw direction
+	pv[0] = topLeftX;
+	pv[1] = topLeftY;
+	pv[2] = halfThick;
+
+	pv[3] = bottomLeftX;
+	pv[4] = bottomLeftY;
+	pv[5] = halfThick;
+
+	pv[6] = bottomRightX;
+	pv[7] = bottomRightY;
+	pv[8] = halfThick;
+
+	pv[9] = topRightX;
+	pv[10] = topRightY;
+	pv[11] = halfThick;
+
+	// Determine 4 back vertices in cw direction
+	pv[12] = topRightX;
+	pv[13] = topRightY;
+	pv[14] = -halfThick;
+
+	pv[15] = bottomRightX;
+	pv[16] = bottomRightY;
+	pv[17] = -halfThick;
+
+	pv[18] = bottomLeftX;
+	pv[19] = bottomLeftY;
+	pv[20] = -halfThick;
+
+	pv[21] = topLeftX;
+	pv[22] = topLeftY;
+	pv[23] = -halfThick;
+
+	// 16 indices for 4 sides (for quad strip)
+	if (!p->sideIndices)
+	{
+	    p->sideIndices = calloc (4 * 4, sizeof (GLushort));
+	}
+	if (!p->sideIndices)
+	{
+	    compLogMessage (w->screen->display, "animation",
+			    CompLogLevelError, "Not enough memory");
+	    freePolygonObjects (pset);
+	    return FALSE;
+	}
+
+	GLushort *ind = p->sideIndices;
+	int id = 0;
+
+	ind[id++] = 0;
+	ind[id++] = 7;
+	ind[id++] = 6;
+	ind[id++] = 1;
+
+	ind[id++] = 1;
+	ind[id++] = 6;
+	ind[id++] = 5;
+	ind[id++] = 2;
+
+	ind[id++] = 2;
+	ind[id++] = 5;
+	ind[id++] = 4;
+	ind[id++] = 3;
+
+	ind[id++] = 3;
+	ind[id++] = 4;
+	ind[id++] = 7;
+	ind[id++] = 0;
+
+	// Surface normals
+	if (!p->normals)
+	{
+	    p->normals = calloc ((2 + 4) * 3, sizeof (GLfloat));
+	}
+	if (!p->normals)
+	{
+	    compLogMessage (w->screen->display, "animation",
+			    CompLogLevelError, "Not enough memory");
+	    freePolygonObjects (pset);
+	    return FALSE;
+	}
+
+	GLfloat *nor = p->normals;
+
+	// Front
+	nor[0] = 0;
+	nor[1] = 0;
+	nor[2] = -1;
+
+	// Back
+	nor[3] = 0;
+	nor[4] = 0;
+	nor[5] = 1;
+
+	// Sides
+	nor[6] = n6;
+	nor[7] = n7;
+	nor[8] = 0;
+
+	nor[9] = n9;
+	nor[10] = n10;
+	nor[11] = 0;
+
+	nor[12] = n12;
+	nor[13] = n13;
+	nor[14] = 0;
+
+	nor[15] = n15;
+	nor[16] = n16;
+	nor[17] = 0;
+
+	if (i < 4)
+	{
+	    p->boundingBox.x1 = p->centerPos.x + topLeftX;
+	    p->boundingBox.y1 = p->centerPos.y + topLeftY;
+	    p->boundingBox.x2 = ceil (p->centerPos.x + bottomRightX);
+	    p->boundingBox.y2 = ceil (p->centerPos.y + bottomRightY);
+	}
+	else
+	{
+	    p->boundingBox.x1 = p->centerPos.x + bottomLeftX;
+	    p->boundingBox.y1 = p->centerPos.y + topLeftY;
+	    p->boundingBox.x2 = ceil (p->centerPos.x + bottomRightX);
+	    p->boundingBox.y2 = ceil (p->centerPos.y + bottomLeftY);
+	}
+    }
+    return TRUE;
+}
+
+void
+fxAirplane3DInit (CompScreen * s, CompWindow * w)
+{
+    ANIM_SCREEN (s);
+    ANIM_WINDOW (w);
+
+    float airplanePathLength =
+	animGetF (as, aw, ANIM_SCREEN_OPTION_AIRPLANE_PATHLENGTH);
+
+    if (!tessellateIntoAirplane (w))
+	return;
+
+    PolygonSet *pset = aw->polygonSet;
+    PolygonObject *p = pset->polygons;
+
+    float winLimitsX;		// boundaries of polygon tessellation
+    float winLimitsY;
+    float winLimitsW;
+    float winLimitsH;
+
+    if (pset->includeShadows)
+    {
+	winLimitsX = WIN_X (w);
+	winLimitsY = WIN_Y (w);
+	winLimitsW = WIN_W (w) - 1;	// avoid artifact on right edge
+	winLimitsH = WIN_H (w);
+    }
+    else
+    {
+	winLimitsX = BORDER_X (w);
+	winLimitsY = BORDER_Y (w);
+	winLimitsW = BORDER_W (w);
+	winLimitsH = BORDER_H (w);
+    }
+
+    float H4 = (float)winLimitsH / 4;
+    float H6 = (float)winLimitsH / 6;
+
+    int i;
+    for (i = 0; i < pset->nPolygons; i++, p++)
+    {
+	if (!p->effectParameters)
+	{
+	    p->effectParameters = calloc (1, sizeof (AirplaneEffectParameters));
+	}
+	if (!p->effectParameters)
+	{
+	    compLogMessage (w->screen->display, "animation",
+			    CompLogLevelError, "Not enough memory");
+	    return;
+	}
+
+	AirplaneEffectParameters *aep = p->effectParameters;
+
+	p->moveStartTime = 0.00;
+	p->moveDuration = 0.19;
+
+	aep->moveStartTime2 = 0.19;
+	aep->moveDuration2 = 0.19;
+
+	aep->moveStartTime3 = 0.38;
+	aep->moveDuration3 = 0.19;
+
+	aep->moveStartTime4 = 0.58;
+	aep->moveDuration4 = 0.09;
+
+	aep->moveDuration5 = 0.41;
+
+	aep->flyFinalRotation.x = 90;
+	aep->flyFinalRotation.y = 10;
+
+	aep->flyTheta = 0;
+
+	aep->centerPosFly.x = 0;
+	aep->centerPosFly.y = 0;
+	aep->centerPosFly.z = 0;
+
+	aep->flyScale = 0;
+	aep->flyFinalScale = 6 * (winLimitsW / (w->screen->width / 2));
+
+	switch (i)
+	{
+	case 0:
+	    p->rotAxisOffset.x = -H4;
+	    p->rotAxisOffset.y = H4;
+
+	    p->rotAxis.x = 1.00;
+	    p->rotAxis.y = 1.00;
+	    p->rotAxis.z = 0.00;
+
+	    p->finalRotAng = 179.5;
+
+	    aep->rotAxisOffsetA.x = 0;
+	    aep->rotAxisOffsetA.y = 0;
+
+	    aep->rotAxisA.x = 1.00;
+	    aep->rotAxisA.y = 0.00;
+	    aep->rotAxisA.z = 0.00;
+
+	    aep->finalRotAngA = 84;
+
+	    aep->rotAxisOffsetB.x = 0;
+	    aep->rotAxisOffsetB.y = 0;
+
+	    aep->rotAxisB.x = 0.00;
+	    aep->rotAxisB.y = 0.00;
+	    aep->rotAxisB.z = 0.00;
+
+	    aep->finalRotAngB = 0;
+	    break;
+
+	case 1:
+	    p->rotAxisOffset.x = -H4;
+	    p->rotAxisOffset.y = H4;
+
+	    p->rotAxis.x = 1.00;
+	    p->rotAxis.y = 1.00;
+	    p->rotAxis.z = 0.00;
+
+	    p->finalRotAng = 179.5;
+
+	    aep->rotAxisOffsetA.x = 0;
+	    aep->rotAxisOffsetA.y = 0;
+
+	    aep->rotAxisA.x = 1.00;
+	    aep->rotAxisA.y = 0.00;
+	    aep->rotAxisA.z = 0.00;
+
+	    aep->finalRotAngA = 84;
+
+	    aep->rotAxisOffsetB.x = 0;
+	    aep->rotAxisOffsetB.y = H6;
+
+	    aep->rotAxisB.x = 1.00;
+	    aep->rotAxisB.y = 0.00;
+	    aep->rotAxisB.z = 0.00;
+
+	    aep->finalRotAngB = -84;
+	    break;
+
+	case 2:
+	    p->moveDuration = 0.00;
+
+	    p->rotAxisOffset.x = 0;
+	    p->rotAxisOffset.y = 0;
+
+	    p->rotAxis.x = 0.00;
+	    p->rotAxis.y = 0.00;
+	    p->rotAxis.z = 0.00;
+
+	    p->finalRotAng = 0;
+
+	    aep->rotAxisOffsetA.x = 0;
+	    aep->rotAxisOffsetA.y = 0;
+
+	    aep->rotAxisA.x = 1.00;
+	    aep->rotAxisA.y = 0.00;
+	    aep->rotAxisA.z = 0.00;
+
+	    aep->finalRotAngA = 84;
+
+	    aep->rotAxisOffsetB.x = 0;
+	    aep->rotAxisOffsetB.y = H6;
+
+	    aep->rotAxisB.x = 1.00;
+	    aep->rotAxisB.y = 0.00;
+	    aep->rotAxisB.z = 0.00;
+
+	    aep->finalRotAngB = -84;
+	    break;
+
+	case 3:
+	    p->moveDuration = 0.00;
+
+	    p->rotAxisOffset.x = 0;
+	    p->rotAxisOffset.y = 0;
+
+	    p->rotAxis.x = 0.00;
+	    p->rotAxis.y = 0.00;
+	    p->rotAxis.z = 0.00;
+
+	    p->finalRotAng = 0;
+
+	    aep->rotAxisOffsetA.x = 0;
+	    aep->rotAxisOffsetA.y = 0;
+
+	    aep->rotAxisA.x = 1.00;
+	    aep->rotAxisA.y = 0.00;
+	    aep->rotAxisA.z = 0.00;
+
+	    aep->finalRotAngA = 84;
+
+	    aep->moveDuration3 = 0.00;
+
+	    aep->rotAxisOffsetB.x = 0;
+	    aep->rotAxisOffsetB.y = 0;
+
+	    aep->rotAxisB.x = 0.00;
+	    aep->rotAxisB.y = 0.00;
+	    aep->rotAxisB.z = 0.00;
+
+	    aep->finalRotAngB = 0;
+	    break;
+
+	case 4:
+	    p->moveDuration = 0.00;
+
+	    p->rotAxisOffset.x = 0;
+	    p->rotAxisOffset.y = 0;
+
+	    p->rotAxis.x = 0.00;
+	    p->rotAxis.y = 0.00;
+	    p->rotAxis.z = 0.00;
+
+	    p->finalRotAng = 0;
+
+	    aep->rotAxisOffsetA.x = 0;
+	    aep->rotAxisOffsetA.y = 0;
+
+	    aep->rotAxisA.x = 1.00;
+	    aep->rotAxisA.y = 0.00;
+	    aep->rotAxisA.z = 0.00;
+
+	    aep->finalRotAngA = -84;
+
+	    aep->moveDuration3 = 0.00;
+
+	    aep->rotAxisOffsetB.x = 0;
+	    aep->rotAxisOffsetB.y = 0;
+
+	    aep->rotAxisB.x = 0.00;
+	    aep->rotAxisB.y = 0.00;
+	    aep->rotAxisB.z = 0.00;
+
+	    aep->finalRotAngB = 0;
+	    break;
+
+	case 5:
+	    p->moveDuration = 0.00;
+
+	    p->rotAxisOffset.x = 0;
+	    p->rotAxisOffset.y = 0;
+
+	    p->rotAxis.x = 0.00;
+	    p->rotAxis.y = 0.00;
+	    p->rotAxis.z = 0.00;
+
+	    p->finalRotAng = 0;
+
+	    aep->rotAxisOffsetA.x = 0;
+	    aep->rotAxisOffsetA.y = 0;
+
+	    aep->rotAxisA.x = 1.00;
+	    aep->rotAxisA.y = 0.00;
+	    aep->rotAxisA.z = 0.00;
+
+	    aep->finalRotAngA = -84;
+
+	    aep->rotAxisOffsetB.x = 0;
+	    aep->rotAxisOffsetB.y = -H6;
+
+	    aep->rotAxisB.x = 1.00;
+	    aep->rotAxisB.y = 0.00;
+	    aep->rotAxisB.z = 0.00;
+
+	    aep->finalRotAngB = 84;
+	    break;
+
+	case 6:
+	    p->rotAxisOffset.x = -H4;
+	    p->rotAxisOffset.y = -H4;
+
+	    p->rotAxis.x = 1.00;
+	    p->rotAxis.y = -1.00;
+	    p->rotAxis.z = 0.00;
+
+	    p->finalRotAng = -179.5;
+
+	    aep->rotAxisOffsetA.x = 0;
+	    aep->rotAxisOffsetA.y = 0;
+
+	    aep->rotAxisA.x = 1.00;
+	    aep->rotAxisA.y = 0.00;
+	    aep->rotAxisA.z = 0.00;
+
+	    aep->finalRotAngA = -84;
+
+	    aep->rotAxisOffsetB.x = 0;
+	    aep->rotAxisOffsetB.y = -H6;
+
+	    aep->rotAxisB.x = 1.00;
+	    aep->rotAxisB.y = 0.00;
+	    aep->rotAxisB.z = 0.00;
+
+	    aep->finalRotAngB = 84;
+	    break;
+
+	case 7:
+	    p->rotAxisOffset.x = -H4;
+	    p->rotAxisOffset.y = -H4;
+
+	    p->rotAxis.x = 1.00;
+	    p->rotAxis.y = -1.00;
+	    p->rotAxis.z = 0.00;
+
+	    p->finalRotAng = -179.5;
+
+	    aep->rotAxisOffsetA.x = 0;
+	    aep->rotAxisOffsetA.y = 0;
+
+	    aep->rotAxisA.x = 1.00;
+	    aep->rotAxisA.y = 0.00;
+	    aep->rotAxisA.z = 0.00;
+
+	    aep->finalRotAngA = -84;
+
+	    aep->rotAxisOffsetB.x = 0;
+	    aep->rotAxisOffsetB.y = 0;
+
+	    aep->rotAxisB.x = 0.00;
+	    aep->rotAxisB.y = 0.00;
+	    aep->rotAxisB.z = 0.00;
+
+	    aep->finalRotAngB = 0;
+	    break;
+	}
+    }
+
+    if (airplanePathLength >= 1)
+	pset->allFadeDuration = 0.30f / airplanePathLength;
+    else
+	pset->allFadeDuration = 0.30f;
+
+    pset->doDepthTest = TRUE;
+    pset->doLighting = TRUE;
+    pset->correctPerspective = CorrectPerspectivePolygon;
+
+    pset->extraPolygonTransformationFunc =
+	&AirplaneExtraPolygonTransformationFunc;
+
+    // Duration extension
+    aw->animTotalTime *= 2 + airplanePathLength;
+    aw->animRemainingTime = aw->animTotalTime;
+}
+
+void
+fxAirplane3DLinearAnimStepPolygon (CompWindow * w,
+				   PolygonObject * p,
+				   float forwardProgress)
+{
+    ANIM_SCREEN (w->screen);
+    ANIM_WINDOW (w);
+
+    float airplanePathLength =
+	animGetF (as, aw, ANIM_SCREEN_OPTION_AIRPLANE_PATHLENGTH);
+    Bool airplaneFly2TaskBar =
+	animGetB (as, aw, ANIM_SCREEN_OPTION_AIRPLANE_FLY2TOM);
+
+    AirplaneEffectParameters *aep = p->effectParameters;
+
+    /*  Phase1: folding: flaps, folding center, folding wings.
+     *  Phase2: rotate and fly.
+     */
+
+    if (forwardProgress > p->moveStartTime &&
+	forwardProgress < aep->moveStartTime4)
+	// Phase1: folding: flaps, center, wings.
+    {
+	float moveProgress1 = forwardProgress - p->moveStartTime;
+	if (p->moveDuration > 0)
+	    moveProgress1 /= p->moveDuration;
+	else
+	    moveProgress1 = 0;
+	if (moveProgress1 < 0)
+	    moveProgress1 = 0;
+	else if (moveProgress1 > 1)
+	    moveProgress1 = 1;
+
+	float moveProgress2 = forwardProgress - aep->moveStartTime2;
+	if (aep->moveDuration2 > 0)
+	    moveProgress2 /= aep->moveDuration2;
+	else
+	    moveProgress2 = 0;
+	if (moveProgress2 < 0)
+	    moveProgress2 = 0;
+	else if (moveProgress2 > 1)
+	    moveProgress2 = 1;
+
+	float moveProgress3 = forwardProgress - aep->moveStartTime3;
+	if (aep->moveDuration3 > 0)
+	    moveProgress3 /= aep->moveDuration3;
+	else
+	    moveProgress3 = 0;
+	if (moveProgress3 < 0)
+	    moveProgress3 = 0;
+	else if (moveProgress3 > 1)
+	    moveProgress3 = 1;
+
+	p->centerPos.x = p->centerPosStart.x;
+	p->centerPos.y = p->centerPosStart.y;
+	p->centerPos.z = p->centerPosStart.z;
+
+	p->rotAngle = moveProgress1 * p->finalRotAng;
+	aep->rotAngleA = moveProgress2 * aep->finalRotAngA;
+	aep->rotAngleB = moveProgress3 * aep->finalRotAngB;
+
+	aep->flyRotation.x = 0;
+	aep->flyRotation.y = 0;
+	aep->flyRotation.z = 0;
+	aep->flyScale = 0;
+    }
+    else if (forwardProgress >= aep->moveStartTime4)
+	// Phase2: rotate and fly 
+    {
+	float moveProgress4 = forwardProgress - aep->moveStartTime4;
+	if (aep->moveDuration4 > 0)
+	    moveProgress4 /= aep->moveDuration4;
+	if (moveProgress4 < 0)
+	    moveProgress4 = 0;
+	else if (moveProgress4 > 1)
+	    moveProgress4 = 1;
+
+	float moveProgress5 = forwardProgress - (aep->moveStartTime4 + .01);
+	if (aep->moveDuration5 > 0)
+	    moveProgress5 /= aep->moveDuration5;
+	if (moveProgress5 < 0)
+	    moveProgress5 = 0;
+	else if (moveProgress5 > 1)
+	    moveProgress5 = 1;
+
+
+	p->rotAngle = p->finalRotAng;
+	aep->rotAngleA = aep->finalRotAngA;
+	aep->rotAngleB = aep->finalRotAngB;
+
+	aep->flyRotation.x = moveProgress4 * aep->flyFinalRotation.x;
+	aep->flyRotation.y = moveProgress4 * aep->flyFinalRotation.y;
+
+	// flying path
+
+	float icondiffx = 0;
+	aep->flyTheta = moveProgress5 * -M_PI_2 * airplanePathLength;
+	aep->centerPosFly.x = w->screen->width * .4 * sin (2 * aep->flyTheta);
+
+	if (((aw->curWindowEvent == WindowEventMinimize ||
+	      aw->curWindowEvent == WindowEventUnminimize) &&
+	     airplaneFly2TaskBar) ||
+	    aw->curWindowEvent == WindowEventOpen ||
+	    aw->curWindowEvent == WindowEventClose)
+	{
+	    // flying path ends at icon/pointer
+	    icondiffx =
+		(((aw->icon.x + aw->icon.width / 2)
+		  - (p->centerPosStart.x +
+		     w->screen->width * .4 *
+		     sin (2 * -M_PI_2 * airplanePathLength))) *
+		 moveProgress5);
+	    aep->centerPosFly.y =
+		((aw->icon.y + aw->icon.height / 2) -
+		 p->centerPosStart.y) *
+		-sin (aep->flyTheta / airplanePathLength);
+	}
+	else
+	{
+	    if (p->centerPosStart.y < w->screen->height * .33 ||
+		p->centerPosStart.y > w->screen->height * .66)
+		aep->centerPosFly.y =
+		    w->screen->height * .6 * sin (aep->flyTheta / 3.4);
+	    else
+		aep->centerPosFly.y =
+		    w->screen->height * .4 * sin (aep->flyTheta / 3.4);
+	    if (p->centerPosStart.y < w->screen->height * .33)
+		aep->centerPosFly.y *= -1;
+	}
+
+	aep->flyFinalRotation.z =
+	    ((atan (2.0) + M_PI_2) * sin (aep->flyTheta) - M_PI_2) * 180 / M_PI;
+	aep->flyFinalRotation.z += 90;
+
+
+	if (aw->curWindowEvent == WindowEventMinimize ||
+	    aw->curWindowEvent == WindowEventClose)
+	{
+	    aep->flyFinalRotation.z *= -1;
+	}
+	else if (aw->curWindowEvent == WindowEventUnminimize ||
+		 aw->curWindowEvent == WindowEventOpen)
+	{
+	    aep->centerPosFly.x *= -1;
+	}
+
+	aep->flyRotation.z = aep->flyFinalRotation.z;
+
+	p->centerPos.x = p->centerPosStart.x + aep->centerPosFly.x + icondiffx;
+	p->centerPos.y = p->centerPosStart.y + aep->centerPosFly.y;
+	p->centerPos.z = p->centerPosStart.z + aep->centerPosFly.z;
+
+	aep->flyScale = moveProgress5 * aep->flyFinalScale;
+    }
+}
+
+void
+AirplaneExtraPolygonTransformationFunc (PolygonObject * p)
+{
+    AirplaneEffectParameters *aep = p->effectParameters;
+
+    glRotatef (aep->flyRotation.x, 1, 0, 0);	//rotate on axis X
+    glRotatef (-aep->flyRotation.y, 0, 1, 0);	// rotate on axis Y
+    glRotatef (aep->flyRotation.z, 0, 0, 1);	// rotate on axis Z
+
+    glScalef (1.0 / (1.0 + aep->flyScale),
+	      1.0 / (1.0 + aep->flyScale), 1.0 / (1.0 + aep->flyScale));
+
+    // Move by "rotation axis offset A"
+    glTranslatef (aep->rotAxisOffsetA.x, aep->rotAxisOffsetA.y,
+		  aep->rotAxisOffsetA.z);
+
+    // Rotate by desired angle A
+    glRotatef (aep->rotAngleA, aep->rotAxisA.x, aep->rotAxisA.y,
+	       aep->rotAxisA.z);
+
+    // Move back to center from  A
+    glTranslatef (-aep->rotAxisOffsetA.x, -aep->rotAxisOffsetA.y,
+		  -aep->rotAxisOffsetA.z);
+
+
+    // Move by "rotation axis offset B"
+    glTranslatef (aep->rotAxisOffsetB.x, aep->rotAxisOffsetB.y,
+		  aep->rotAxisOffsetB.z);
+
+    // Rotate by desired angle B
+    glRotatef (aep->rotAngleB, aep->rotAxisB.x, aep->rotAxisB.y,
+	       aep->rotAxisB.z);
+
+    // Move back to center from B
+    glTranslatef (-aep->rotAxisOffsetB.x, -aep->rotAxisOffsetB.y,
+		  -aep->rotAxisOffsetB.z);
+}

Modified: fusion/plugins/animation/animation-internal.h
===================================================================
--- fusion/plugins/animation/animation-internal.h
+++ fusion/plugins/animation/animation-internal.h
@@ -52,6 +52,48 @@ typedef struct _xyz_tuple
     float x, y, z;
 } Point3d, Vector3d;
 
+typedef struct _AirplaneEffectParameters
+{
+    /// added for airplane folding and flying
+    // airplane fold phase.
+
+    Vector3d rotAxisA;			// Rotation axis vector A
+    Vector3d rotAxisB;			// Rotation axis vector B
+
+    Point3d rotAxisOffsetA;		// Rotation axis translate amount A 
+    Point3d rotAxisOffsetB; 	        // Rotation axis translate amount B
+
+    float rotAngleA;			// Rotation angle A
+    float finalRotAngA;			// Final rotation angle A
+
+    float rotAngleB;			// Rotation angle B
+    float finalRotAngB;			// Final rotation angle B
+
+    // airplane fly phase:
+
+    Vector3d centerPosFly;	// center position (offset) during the flying phases
+
+    Vector3d flyRotation;	// airplane rotation during the flying phases
+    Vector3d flyFinalRotation;	// airplane rotation during the flying phases 
+
+    float flyScale;             // Scale for airplane flying effect 
+    float flyFinalScale;        // Final Scale for airplane flying effect 
+  
+    float flyTheta;		// Theta parameter for fly rotations and positions
+
+    float moveStartTime2;		// Movement starts at this time ([0-1] range)
+    float moveDuration2;		// Movement lasts this long     ([0-1] range)
+
+    float moveStartTime3;		// Movement starts at this time ([0-1] range)
+    float moveDuration3;		// Movement lasts this long     ([0-1] range)
+
+    float moveStartTime4;		// Movement starts at this time ([0-1] range)
+    float moveDuration4;		// Movement lasts this long     ([0-1] range)
+
+    float moveStartTime5;	        // Movement starts at this time ([0-1] range)
+    float moveDuration5;		// Movement lasts this long     ([0-1] range)
+} AirplaneEffectParameters;
+
 // This is intended to be a closed 3D piece of a window with convex polygon
 // faces and quad-strip sides. Since decoration texture is separate from
 // the window texture, it is more complicated than it would be with a single
@@ -282,6 +324,7 @@ typedef enum
 {
     AnimEffectNone = 0,
     AnimEffectRandom,
+    AnimEffectAirplane3D,
     AnimEffectBeamUp,
     AnimEffectBurn,
     AnimEffectCurvedFold,
@@ -291,6 +334,7 @@ typedef enum
     AnimEffectExplode3D,
     AnimEffectFade,
     AnimEffectFocusFade,
+    AnimEffectFold3D,
     AnimEffectGlide3D1,
     AnimEffectGlide3D2,
     AnimEffectHorizontalFolds,
@@ -299,6 +343,7 @@ typedef enum
     AnimEffectRazr3D,
     AnimEffectRollUp,
     AnimEffectSidekick,
+    AnimEffectSkewer,
     AnimEffectVacuum,
     AnimEffectWave,
     AnimEffectZoom,
@@ -314,13 +359,13 @@ typedef enum
    LAST_RANDOM_*_EFFECT always must be LAST_*_EFFECT - RANDOM_EFFECT_OFFSET
 */
 
-#define NUM_MINIMIZE_EFFECT 17
-#define LAST_MINIMIZE_EFFECT 16
-#define LAST_RANDOM_MINIMIZE_EFFECT 14
+#define NUM_MINIMIZE_EFFECT 20
+#define LAST_MINIMIZE_EFFECT 19
+#define LAST_RANDOM_MINIMIZE_EFFECT 17
 
-#define NUM_CLOSE_EFFECT 19
-#define LAST_CLOSE_EFFECT 18
-#define LAST_RANDOM_CLOSE_EFFECT 16
+#define NUM_CLOSE_EFFECT 22
+#define LAST_CLOSE_EFFECT 21
+#define LAST_RANDOM_CLOSE_EFFECT 19
 
 #define NUM_FOCUS_EFFECT 4
 #define LAST_FOCUS_EFFECT 3
@@ -405,6 +450,8 @@ typedef enum
     ANIM_SCREEN_OPTION_TIME_STEP,
     ANIM_SCREEN_OPTION_TIME_STEP_INTENSE,
     // Effect settings
+    ANIM_SCREEN_OPTION_AIRPLANE_PATHLENGTH,
+    ANIM_SCREEN_OPTION_AIRPLANE_FLY2TOM,
     ANIM_SCREEN_OPTION_BEAMUP_SIZE,
     ANIM_SCREEN_OPTION_BEAMUP_SPACING,
     ANIM_SCREEN_OPTION_BEAMUP_COLOR,
@@ -429,6 +476,9 @@ typedef enum
     ANIM_SCREEN_OPTION_FIRE_CONSTANT_SPEED,
     ANIM_SCREEN_OPTION_FIRE_SMOKE,
     ANIM_SCREEN_OPTION_FIRE_MYSTICAL,
+    ANIM_SCREEN_OPTION_FOLD3D_GRIDSIZE_X,
+    ANIM_SCREEN_OPTION_FOLD3D_GRIDSIZE_Y,
+    ANIM_SCREEN_OPTION_FOLD3D_DIR,
     ANIM_SCREEN_OPTION_GLIDE1_AWAY_POS,
     ANIM_SCREEN_OPTION_GLIDE1_AWAY_ANGLE,
     ANIM_SCREEN_OPTION_GLIDE1_THICKNESS,
@@ -450,6 +500,12 @@ typedef enum
     ANIM_SCREEN_OPTION_SIDEKICK_NUM_ROTATIONS,
     ANIM_SCREEN_OPTION_SIDEKICK_SPRINGINESS,
     ANIM_SCREEN_OPTION_SIDEKICK_ZOOM_FROM_CENTER,
+    ANIM_SCREEN_OPTION_SKEWER_GRIDSIZE_X,
+    ANIM_SCREEN_OPTION_SKEWER_GRIDSIZE_Y,
+    ANIM_SCREEN_OPTION_SKEWER_THICKNESS,
+    ANIM_SCREEN_OPTION_SKEWER_DIRECTION,
+    ANIM_SCREEN_OPTION_SKEWER_TESS,
+    ANIM_SCREEN_OPTION_SKEWER_ROTATION,
     ANIM_SCREEN_OPTION_VACUUM_MOVING_END,
     ANIM_SCREEN_OPTION_VACUUM_GRID_RES,
     ANIM_SCREEN_OPTION_VACUUM_OPEN_START_WIDTH,
@@ -461,8 +517,9 @@ typedef enum
     ANIM_SCREEN_OPTION_NUM
 } AnimScreenOptions;
 
-// This must have the value of the first "effect option" in AnimScreenOptions
-#define NUM_NONEFFECT_OPTIONS ANIM_SCREEN_OPTION_BEAMUP_SIZE
+// This must have the value of the first "effect setting" above
+// in AnimScreenOptions
+#define NUM_NONEFFECT_OPTIONS ANIM_SCREEN_OPTION_AIRPLANE_PATHLENGTH
 
 typedef struct _AnimScreen
 {
@@ -595,6 +652,10 @@ typedef struct _AnimWindow
     CompWindow *dodgeChainNext;	// for dodging windows
     Bool skipPostPrepareScreen;
     Bool drawnOnHostSkip;
+ 
+    // for airplane
+    float airplanePathLength;
+    Bool airplaneFly2TaskBar;
 } AnimWindow;
 
 typedef struct _AnimEffectProperties
@@ -730,6 +791,26 @@ animDrawWindowGeometry(CompWindow * w);
 Bool
 getMousePointerXY(CompScreen * s, short *x, short *y);
 
+
+/* airplane3d.c */
+
+void
+fxAirplane3DInit (CompScreen *s,
+		  CompWindow *w);
+
+void
+fxAirplane3DLinearAnimStepPolygon (CompWindow * w,
+				   PolygonObject * p, 
+				   float forwardProgress);
+
+void 
+fxAirplane3DDrawCustomGeometry (CompScreen * s,
+				CompWindow * w);
+
+void 
+AirplaneExtraPolygonTransformationFunc (PolygonObject * p);
+
+
 /* beamup.c */
 
 void
@@ -832,6 +913,16 @@ fxFocusFadeUpdateWindowAttrib (AnimScreen *as,
 			       CompWindow * w,
 			       WindowPaintAttrib *wAttrib);
 
+/* fold3d.c */
+
+void
+fxFold3DInit (CompScreen * s, CompWindow * w);
+
+void
+fxFold3dAnimStepPolygon (CompWindow * w,
+			 PolygonObject * p,
+			 float forwardProgress);
+
 
 /* glide.c */
 
@@ -1036,6 +1127,16 @@ void fxRollUpInitGrid (AnimScreen *as,
  
 void fxRollUpAnimInit(CompScreen * s, CompWindow * w);
 
+/* skewer.c */
+
+void
+fxSkewerInit (CompScreen * s, CompWindow * w);
+
+void
+fxSkewerAnimStepPolygon (CompWindow * w,
+			 PolygonObject * p,
+			 float forwardProgress);
+
 /* wave.c */
  
 Bool

Modified: fusion/plugins/animation/animation.c
===================================================================
--- fusion/plugins/animation/animation.c
+++ fusion/plugins/animation/animation.c
@@ -1,4 +1,4 @@
-/*
+/**
  * Animation plugin for compiz/beryl
  *
  * animation.c
@@ -10,15 +10,22 @@
  *           : David Reveman
  * E-mail    : davidr at novell.com>
  *
- * Particle system added by : (C) 2006 Dennis Kasprzyk
- * E-mail                   : onestone at beryl-project.org
+ * Airplane added by : Carlo Palma
+ * E-mail            : carlopalma at salug.it
+ * Based on code originally written by Mark J. Kilgard
  *
  * Beam-Up added by : Florencio Guimaraes
  * E-mail           : florencio at nexcorp.com.br
  *
+ * Fold and Skewer added by : Tomasz Kolodziejski
+ * E-mail                   : tkolodziejski at gmail.com
+ *
  * Hexagon tessellator added by : Mike Slegeir
  * E-mail                       : mikeslegeir at mail.utexas.edu>
  *
+ * Particle system added by : (C) 2006 Dennis Kasprzyk
+ * E-mail                   : onestone at beryl-project.org
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
@@ -32,7 +39,7 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
+ **/
 
 /*
  * TODO:
@@ -90,6 +97,7 @@ CompMetadata animMetadata;
 static AnimEffect minimizeEffects[] = {
     AnimEffectNone,
     AnimEffectRandom,
+    AnimEffectAirplane3D,
     AnimEffectBeamUp,
     AnimEffectBurn,
     AnimEffectCurvedFold,
@@ -97,6 +105,7 @@ static AnimEffect minimizeEffects[] = {
     AnimEffectDream,
     AnimEffectExplode3D,
     AnimEffectFade,
+    AnimEffectFold3D,
     AnimEffectGlide3D1,
     AnimEffectGlide3D2,
     AnimEffectHorizontalFolds,
@@ -104,12 +113,14 @@ static AnimEffect minimizeEffects[] = {
     AnimEffectMagicLamp,
     AnimEffectRazr3D,
     AnimEffectSidekick,
+    AnimEffectSkewer,
     AnimEffectZoom
 };
 
 static AnimEffect closeEffects[] = {
     AnimEffectNone,
     AnimEffectRandom,
+    AnimEffectAirplane3D,
     AnimEffectBeamUp,
     AnimEffectBurn,
     AnimEffectCurvedFold,
@@ -117,6 +128,7 @@ static AnimEffect closeEffects[] = {
     AnimEffectDream,
     AnimEffectExplode3D,
     AnimEffectFade,
+    AnimEffectFold3D,
     AnimEffectGlide3D1,
     AnimEffectGlide3D2,
     AnimEffectHorizontalFolds,
@@ -124,6 +136,7 @@ static AnimEffect closeEffects[] = {
     AnimEffectMagicLamp,
     AnimEffectRazr3D,
     AnimEffectSidekick,
+    AnimEffectSkewer,
     AnimEffectVacuum,
     AnimEffectWave,
     AnimEffectZoom
@@ -530,6 +543,10 @@ AnimEffectProperties animEffectProperties[AnimEffectNum] = {
     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
     // AnimEffectRandom
     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+    // AnimEffectAirplane3D
+    {0, polygonsPrePaintWindow, polygonsPostPaintWindow, polygonsAnimStep,
+     fxAirplane3DInit, 0, polygonsStoreClips, polygonsDrawCustomGeometry, 0,
+     fxAirplane3DLinearAnimStepPolygon, 0, 0, 0},
     // AnimEffectBeamUp
     {fxBeamupUpdateWindowAttrib, 0, drawParticleSystems, fxBeamUpModelStep,
      fxBeamUpInit, 0, 0, 0, 1, 0, 0, 0, 0},
@@ -562,6 +579,10 @@ AnimEffectProperties animEffectProperties[AnimEffectNum] = {
     // AnimEffectFocusFade
     {fxFocusFadeUpdateWindowAttrib, 0, 0, defaultAnimStep, defaultAnimInit,
      0, 0, 0, 0, 0, defaultLetOthersDrawGeoms, 0, 0},
+    // AnimEffectFold3D
+    {0, polygonsPrePaintWindow, polygonsPostPaintWindow, polygonsAnimStep,
+    fxFold3DInit, 0, polygonsStoreClips, polygonsDrawCustomGeometry, 0,
+    fxFold3dAnimStepPolygon, 0, 0, 0},
     // AnimEffectGlide3D1
     {fxGlideUpdateWindowAttrib, fxGlidePrePaintWindow,
      fxGlidePostPaintWindow, fxGlideAnimStep,
@@ -596,6 +617,10 @@ AnimEffectProperties animEffectProperties[AnimEffectNum] = {
     {fxZoomUpdateWindowAttrib, 0, 0, defaultAnimStep, fxSidekickInit,
      0, 0, 0, 1, 0, defaultLetOthersDrawGeoms, fxZoomUpdateWindowTransform,
      0},
+    // AnimEffectSkewer
+    {0, polygonsPrePaintWindow, polygonsPostPaintWindow, polygonsAnimStep,
+    fxSkewerInit, 0, polygonsStoreClips, polygonsDrawCustomGeometry, 0,
+    fxSkewerAnimStepPolygon, 0, 0, 0},
     // AnimEffectVacuum
     {0, 0, 0, fxMagicLampModelStep, fxMagicLampInit,
      fxVacuumInitGrid, 0, 0, 0, 0, 0, 0, 0},
@@ -797,6 +822,8 @@ static const CompMetadataOptionInfo animScreenOptionInfo[] = {
     { "time_step", "int", "<min>1</min>", 0, 0 },
     { "time_step_intense", "int", "<min>1</min>", 0, 0 },
     // Effect settings
+    { "airplane_path_length", "float", "<min>0.2</min>", 0, 0 },
+    { "airplane_fly_to_taskbar", "bool", 0, 0, 0 },
     { "beam_size", "float", "<min>0.1</min>", 0, 0 },
     { "beam_spacing", "int", "<min>1</min>", 0, 0 },
     { "beam_color", "color", 0, 0, 0 },
@@ -821,6 +848,9 @@ static const CompMetadataOptionInfo animScreenOptionInfo[] = {
     { "fire_constant_speed", "bool", 0, 0, 0 },
     { "fire_smoke", "bool", 0, 0, 0 },
     { "fire_mystical", "bool", 0, 0, 0 },
+    { "fold_gridx", "int", "<min>1</min>", 0, 0 },
+    { "fold_gridy", "int", "<min>1</min>", 0, 0 },
+    { "fold_dir", "int", "<min>0</min>", 0, 0 },
     { "glide1_away_position", "float", 0, 0, 0 },
     { "glide1_away_angle", "float", 0, 0, 0 },
     { "glide1_thickness", "float", "<min>0</min>", 0, 0 },
@@ -842,6 +872,12 @@ static const CompMetadataOptionInfo animScreenOptionInfo[] = {
     { "sidekick_num_rotations", "float", "<min>0</min>", 0, 0 },
     { "sidekick_springiness", "float", "<min>0</min><max>1</max>", 0, 0 },
     { "sidekick_zoom_from_center", "int", RESTOSTRING (0, LAST_ZOOM_FROM_CENTER), 0, 0 },
+    { "skewer_gridx", "int", "<min>1</min>", 0, 0 },
+    { "skewer_gridy", "int", "<min>1</min>", 0, 0 },
+    { "skewer_thickness", "float", "<min>1</min>", 0, 0 },
+    { "skewer_direction", "int", "<min>0</min>", 0, 0 },
+    { "skewer_tessellation", "int", RESTOSTRING (0, LAST_POLYGON_TESS), 0, 0 },
+    { "skewer_rotation", "int", 0, 0, 0 },
     { "vacuum_moving_end", "bool", 0, 0, 0 },
     { "vacuum_grid_res", "int", "<min>4</min>", 0, 0 },
     { "vacuum_open_start_width", "int", "<min>0</min>", 0, 0 },

Modified: fusion/plugins/animation/animation.xml.in
===================================================================
--- fusion/plugins/animation/animation.xml.in
+++ fusion/plugins/animation/animation.xml.in
@@ -26,11 +26,11 @@
 	    <_long>The animation effect shown when closing a window.</_long>
 	    <type>int</type>
 	    <min>0</min>
-	    <max>18</max>
+	    <max>21</max>
 	    <default>
-	      <value>18</value>
-	      <value>8</value>
-	      <value>8</value>
+	      <value>21</value>
+	      <value>9</value>
+	      <value>9</value>
 	    </default>
 	    <desc>
 	      <value>0</value>
@@ -42,70 +42,82 @@
 	    </desc>
 	    <desc>
 	      <value>2</value>
-	      <_name>Beam Up</_name>
+	      <_name>Airplane</_name>
 	    </desc>
 	    <desc>
 	      <value>3</value>
-	      <_name>Burn</_name>
+	      <_name>Beam Up</_name>
 	    </desc>
 	    <desc>
 	      <value>4</value>
-	      <_name>Curved Fold</_name>
+	      <_name>Burn</_name>
 	    </desc>
 	    <desc>
 	      <value>5</value>
-	      <_name>Domino</_name>
+	      <_name>Curved Fold</_name>
 	    </desc>
 	    <desc>
 	      <value>6</value>
-	      <_name>Dream</_name>
+	      <_name>Domino</_name>
 	    </desc>
 	    <desc>
 	      <value>7</value>
-	      <_name>Explode</_name>
+	      <_name>Dream</_name>
 	    </desc>
 	    <desc>
 	      <value>8</value>
-	      <_name>Fade</_name>
+	      <_name>Explode</_name>
 	    </desc>
 	    <desc>
 	      <value>9</value>
-	      <_name>Glide 1</_name>
+	      <_name>Fade</_name>
 	    </desc>
 	    <desc>
 	      <value>10</value>
-	      <_name>Glide 2</_name>
+	      <_name>Fold</_name>
 	    </desc>
 	    <desc>
 	      <value>11</value>
-	      <_name>Horizontal Folds</_name>
+	      <_name>Glide 1</_name>
 	    </desc>
 	    <desc>
 	      <value>12</value>
-	      <_name>Leaf Spread</_name>
+	      <_name>Glide 2</_name>
 	    </desc>
 	    <desc>
 	      <value>13</value>
-	      <_name>Magic Lamp</_name>
+	      <_name>Horizontal Folds</_name>
 	    </desc>
 	    <desc>
 	      <value>14</value>
-	      <_name>Razr</_name>
+	      <_name>Leaf Spread</_name>
 	    </desc>
 	    <desc>
 	      <value>15</value>
-	      <_name>Sidekick</_name>
+	      <_name>Magic Lamp</_name>
 	    </desc>
 	    <desc>
 	      <value>16</value>
-	      <_name>Vacuum</_name>
+	      <_name>Razr</_name>
 	    </desc>
 	    <desc>
 	      <value>17</value>
-	      <_name>Wave</_name>
+	      <_name>Sidekick</_name>
 	    </desc>
 	    <desc>
 	      <value>18</value>
+	      <_name>Skewer</_name>
+	    </desc>
+	    <desc>
+	      <value>19</value>
+	      <_name>Vacuum</_name>
+	    </desc>
+	    <desc>
+	      <value>20</value>
+	      <_name>Wave</_name>
+	    </desc>
+	    <desc>
+	      <value>21</value>
 	      <_name>Zoom</_name>
 	    </desc>
 	  </option>
@@ -150,7 +162,7 @@
 	    <_long>Pool of effects to be chosen from if Random effect is selected. Click reset to restore full list.</_long>
 	    <type>int</type>
 	    <min>0</min>
-	    <max>16</max>
+	    <max>19</max>
 	    <default>
 	      <value>0</value>
 	      <value>1</value>
@@ -169,73 +181,88 @@
 	      <value>14</value>
 	      <value>15</value>
 	      <value>16</value>
+	      <value>17</value>
+	      <value>18</value>
+	      <value>19</value>
 	    </default>
 	    <desc>
 	      <value>0</value>
-	      <_name>Beam Up</_name>
+	      <_name>Airplane</_name>
 	    </desc>
 	    <desc>
 	      <value>1</value>
-	      <_name>Burn</_name>
+	      <_name>Beam Up</_name>
 	    </desc>
 	    <desc>
 	      <value>2</value>
-	      <_name>Curved Fold</_name>
+	      <_name>Burn</_name>
 	    </desc>
 	    <desc>
 	      <value>3</value>
-	      <_name>Domino</_name>
+	      <_name>Curved Fold</_name>
 	    </desc>
 	    <desc>
 	      <value>4</value>
-	      <_name>Dream</_name>
+	      <_name>Domino</_name>
 	    </desc>
 	    <desc>
 	      <value>5</value>
-	      <_name>Explode</_name>
+	      <_name>Dream</_name>
 	    </desc>
 	    <desc>
 	      <value>6</value>
-	      <_name>Fade</_name>
+	      <_name>Explode</_name>
 	    </desc>
 	    <desc>
 	      <value>7</value>
-	      <_name>Glide 1</_name>
+	      <_name>Fade</_name>
 	    </desc>
 	    <desc>
 	      <value>8</value>
-	      <_name>Glide 2</_name>
+	      <_name>Fold</_name>
 	    </desc>
 	    <desc>
 	      <value>9</value>
-	      <_name>Horizontal Folds</_name>
+	      <_name>Glide 1</_name>
 	    </desc>
 	    <desc>
 	      <value>10</value>
-	      <_name>Leaf Spread</_name>
+	      <_name>Glide 2</_name>
 	    </desc>
 	    <desc>
 	      <value>11</value>
-	      <_name>Magic Lamp</_name>
+	      <_name>Horizontal Folds</_name>
 	    </desc>
 	    <desc>
 	      <value>12</value>
-	      <_name>Razr</_name>
+	      <_name>Leaf Spread</_name>
 	    </desc>
 	    <desc>
 	      <value>13</value>
-	      <_name>Sidekick</_name>
+	      <_name>Magic Lamp</_name>
 	    </desc>
 	    <desc>
 	      <value>14</value>
-	      <_name>Vacuum</_name>
+	      <_name>Razr</_name>
 	    </desc>
 	    <desc>
 	      <value>15</value>
-	      <_name>Wave</_name>
+	      <_name>Sidekick</_name>
 	    </desc>
 	    <desc>
 	      <value>16</value>
+	      <_name>Skewer</_name>
+	    </desc>
+	    <desc>
+	      <value>17</value>
+	      <_name>Vacuum</_name>
+	    </desc>
+	    <desc>
+	      <value>18</value>
+	      <_name>Wave</_name>
+	    </desc>
+	    <desc>
+	      <value>19</value>
 	      <_name>Zoom</_name>
 	    </desc>
 	  </option>
@@ -253,11 +280,11 @@
 	    <_long>The animation effect shown when creating a window.</_long>
 	    <type>int</type>
 	    <min>0</min>
-	    <max>18</max>
+	    <max>21</max>
 	    <default>
-	      <value>18</value>
-	      <value>8</value>
-	      <value>8</value>
+	      <value>21</value>
+	      <value>9</value>
+	      <value>9</value>
 	    </default>
 	    <desc>
 	      <value>0</value>
@@ -269,70 +296,82 @@
 	    </desc>
 	    <desc>
 	      <value>2</value>
-	      <_name>Beam Up</_name>
+	      <_name>Airplane</_name>
 	    </desc>
 	    <desc>
 	      <value>3</value>
-	      <_name>Burn</_name>
+	      <_name>Beam Up</_name>
 	    </desc>
 	    <desc>
 	      <value>4</value>
-	      <_name>Curved Fold</_name>
+	      <_name>Burn</_name>
 	    </desc>
 	    <desc>
 	      <value>5</value>
-	      <_name>Domino</_name>
+	      <_name>Curved Fold</_name>
 	    </desc>
 	    <desc>
 	      <value>6</value>
-	      <_name>Dream</_name>
+	      <_name>Domino</_name>
 	    </desc>
 	    <desc>
 	      <value>7</value>
-	      <_name>Explode</_name>
+	      <_name>Dream</_name>
 	    </desc>
 	    <desc>
 	      <value>8</value>
-	      <_name>Fade</_name>
+	      <_name>Explode</_name>
 	    </desc>
 	    <desc>
 	      <value>9</value>
-	      <_name>Glide 1</_name>
+	      <_name>Fade</_name>
 	    </desc>
 	    <desc>
 	      <value>10</value>
-	      <_name>Glide 2</_name>
+	      <_name>Fold</_name>
 	    </desc>
 	    <desc>
 	      <value>11</value>
-	      <_name>Horizontal Folds</_name>
+	      <_name>Glide 1</_name>
 	    </desc>
 	    <desc>
 	      <value>12</value>
-	      <_name>Leaf Spread</_name>
+	      <_name>Glide 2</_name>
 	    </desc>
 	    <desc>
 	      <value>13</value>
-	      <_name>Magic Lamp</_name>
+	      <_name>Horizontal Folds</_name>
 	    </desc>
 	    <desc>
 	      <value>14</value>
-	      <_name>Razr</_name>
+	      <_name>Leaf Spread</_name>
 	    </desc>
 	    <desc>
 	      <value>15</value>
-	      <_name>Sidekick</_name>
+	      <_name>Magic Lamp</_name>
 	    </desc>
 	    <desc>
 	      <value>16</value>
-	      <_name>Vacuum</_name>
+	      <_name>Razr</_name>
 	    </desc>
 	    <desc>
 	      <value>17</value>
-	      <_name>Wave</_name>
+	      <_name>Sidekick</_name>
 	    </desc>
 	    <desc>
 	      <value>18</value>
+	      <_name>Skewer</_name>
+	    </desc>
+	    <desc>
+	      <value>19</value>
+	      <_name>Vacuum</_name>
+	    </desc>
+	    <desc>
+	      <value>20</value>
+	      <_name>Wave</_name>
+	    </desc>
+	    <desc>
+	      <value>21</value>
 	      <_name>Zoom</_name>
 	    </desc>
 	  </option>
@@ -377,7 +416,7 @@
 	    <_long>Pool of effects to be chosen from if Random effect is selected. Click reset to restore full list.</_long>
 	    <type>int</type>
 	    <min>0</min>
-	    <max>16</max>
+	    <max>19</max>
 	    <default>
 	      <value>0</value>
 	      <value>1</value>
@@ -396,73 +435,88 @@
 	      <value>14</value>
 	      <value>15</value>
 	      <value>16</value>
+	      <value>17</value>
+	      <value>18</value>
+	      <value>19</value>
 	    </default>
 	    <desc>
 	      <value>0</value>
-	      <_name>Beam Up</_name>
+	      <_name>Airplane</_name>
 	    </desc>
 	    <desc>
 	      <value>1</value>
-	      <_name>Burn</_name>
+	      <_name>Beam Up</_name>
 	    </desc>
 	    <desc>
 	      <value>2</value>
-	      <_name>Curved Fold</_name>
+	      <_name>Burn</_name>
 	    </desc>
 	    <desc>
 	      <value>3</value>
-	      <_name>Domino</_name>
+	      <_name>Curved Fold</_name>
 	    </desc>
 	    <desc>
 	      <value>4</value>
-	      <_name>Dream</_name>
+	      <_name>Domino</_name>
 	    </desc>
 	    <desc>
 	      <value>5</value>
-	      <_name>Explode</_name>
+	      <_name>Dream</_name>
 	    </desc>
 	    <desc>
 	      <value>6</value>
-	      <_name>Fade</_name>
+	      <_name>Explode</_name>
 	    </desc>
 	    <desc>
 	      <value>7</value>
-	      <_name>Glide 1</_name>
+	      <_name>Fade</_name>
 	    </desc>
 	    <desc>
 	      <value>8</value>
-	      <_name>Glide 2</_name>
+	      <_name>Fold</_name>
 	    </desc>
 	    <desc>
 	      <value>9</value>
-	      <_name>Horizontal Folds</_name>
+	      <_name>Glide 1</_name>
 	    </desc>
 	    <desc>
 	      <value>10</value>
-	      <_name>Leaf Spread</_name>
+	      <_name>Glide 2</_name>
 	    </desc>
 	    <desc>
 	      <value>11</value>
-	      <_name>Magic Lamp</_name>
+	      <_name>Horizontal Folds</_name>
 	    </desc>
 	    <desc>
 	      <value>12</value>
-	      <_name>Razr</_name>
+	      <_name>Leaf Spread</_name>
 	    </desc>
 	    <desc>
 	      <value>13</value>
-	      <_name>Sidekick</_name>
+	      <_name>Magic Lamp</_name>
 	    </desc>
 	    <desc>
 	      <value>14</value>
-	      <_name>Vacuum</_name>
+	      <_name>Razr</_name>
 	    </desc>
 	    <desc>
 	      <value>15</value>
-	      <_name>Wave</_name>
+	      <_name>Sidekick</_name>
 	    </desc>
 	    <desc>
 	      <value>16</value>
+	      <_name>Skewer</_name>
+	    </desc>
+	    <desc>
+	      <value>17</value>
+	      <_name>Vacuum</_name>
+	    </desc>
+	    <desc>
+	      <value>18</value>
+	      <_name>Wave</_name>
+	    </desc>
+	    <desc>
+	      <value>19</value>
 	      <_name>Zoom</_name>
 	    </desc>
 	  </option>
@@ -480,9 +534,9 @@
 	    <_long>The animation effect shown when minimizing a window.</_long>
 	    <type>int</type>
 	    <min>0</min>
-	    <max>16</max>
+	    <max>19</max>
 	    <default>
-	      <value>13</value>
+	      <value>15</value>
 	    </default>
 	    <desc>
 	      <value>0</value>
@@ -494,62 +548,74 @@
 	    </desc>
 	    <desc>
 	      <value>2</value>
-	      <_name>Beam Up</_name>
+	      <_name>Airplane</_name>
 	    </desc>
 	    <desc>
 	      <value>3</value>
-	      <_name>Burn</_name>
+	      <_name>Beam Up</_name>
 	    </desc>
 	    <desc>
 	      <value>4</value>
-	      <_name>Curved Fold</_name>
+	      <_name>Burn</_name>
 	    </desc>
 	    <desc>
 	      <value>5</value>
-	      <_name>Domino</_name>
+	      <_name>Curved Fold</_name>
 	    </desc>
 	    <desc>
 	      <value>6</value>
-	      <_name>Dream</_name>
+	      <_name>Domino</_name>
 	    </desc>
 	    <desc>
 	      <value>7</value>
-	      <_name>Explode</_name>
+	      <_name>Dream</_name>
 	    </desc>
 	    <desc>
 	      <value>8</value>
-	      <_name>Fade</_name>
+	      <_name>Explode</_name>
 	    </desc>
 	    <desc>
 	      <value>9</value>
-	      <_name>Glide 1</_name>
+	      <_name>Fade</_name>
 	    </desc>
 	    <desc>
 	      <value>10</value>
-	      <_name>Glide 2</_name>
+	      <_name>Fold</_name>
 	    </desc>
 	    <desc>
 	      <value>11</value>
-	      <_name>Horizontal Folds</_name>
+	      <_name>Glide 1</_name>
 	    </desc>
 	    <desc>
 	      <value>12</value>
-	      <_name>Leaf Spread</_name>
+	      <_name>Glide 2</_name>
 	    </desc>
 	    <desc>
 	      <value>13</value>
-	      <_name>Magic Lamp</_name>
+	      <_name>Horizontal Folds</_name>
 	    </desc>
 	    <desc>
 	      <value>14</value>
-	      <_name>Razr</_name>
+	      <_name>Leaf Spread</_name>
 	    </desc>
 	    <desc>
 	      <value>15</value>
-	      <_name>Sidekick</_name>
+	      <_name>Magic Lamp</_name>
 	    </desc>
 	    <desc>
 	      <value>16</value>
+	      <_name>Razr</_name>
+	    </desc>
+	    <desc>
+	      <value>17</value>
+	      <_name>Sidekick</_name>
+	    </desc>
+	    <desc>
+	      <value>18</value>
+	      <_name>Skewer</_name>
+	    </desc>
+	    <desc>
+	      <value>19</value>
 	      <_name>Zoom</_name>
 	    </desc>
 	  </option>
@@ -588,7 +654,7 @@
 	    <_long>Pool of effects to be chosen from if Random effect is selected. Click reset to restore full list.</_long>
 	    <type>int</type>
 	    <min>0</min>
-	    <max>14</max>
+	    <max>17</max>
 	    <default>
 	      <value>0</value>
 	      <value>1</value>
@@ -605,65 +671,80 @@
 	      <value>12</value>
 	      <value>13</value>
 	      <value>14</value>
+	      <value>15</value>
+	      <value>16</value>
+	      <value>17</value>
 	    </default>
 	    <desc>
 	      <value>0</value>
-	      <_name>Beam Up</_name>
+	      <_name>Airplane</_name>
 	    </desc>
 	    <desc>
 	      <value>1</value>
-	      <_name>Burn</_name>
+	      <_name>Beam Up</_name>
 	    </desc>
 	    <desc>
 	      <value>2</value>
-	      <_name>Curved Fold</_name>
+	      <_name>Burn</_name>
 	    </desc>
 	    <desc>
 	      <value>3</value>
-	      <_name>Domino</_name>
+	      <_name>Curved Fold</_name>
 	    </desc>
 	    <desc>
 	      <value>4</value>
-	      <_name>Dream</_name>
+	      <_name>Domino</_name>
 	    </desc>
 	    <desc>
 	      <value>5</value>
-	      <_name>Explode</_name>
+	      <_name>Dream</_name>
 	    </desc>
 	    <desc>
 	      <value>6</value>
-	      <_name>Fade</_name>
+	      <_name>Explode</_name>
 	    </desc>
 	    <desc>
 	      <value>7</value>
-	      <_name>Glide 1</_name>
+	      <_name>Fade</_name>
 	    </desc>
 	    <desc>
 	      <value>8</value>
-	      <_name>Glide 2</_name>
+	      <_name>Fold</_name>
 	    </desc>
 	    <desc>
 	      <value>9</value>
-	      <_name>Horizontal Folds</_name>
+	      <_name>Glide 1</_name>
 	    </desc>
 	    <desc>
 	      <value>10</value>
-	      <_name>Leaf Spread</_name>
+	      <_name>Glide 2</_name>
 	    </desc>
 	    <desc>
 	      <value>11</value>
-	      <_name>Magic Lamp</_name>
+	      <_name>Horizontal Folds</_name>
 	    </desc>
 	    <desc>
 	      <value>12</value>
-	      <_name>Razr</_name>
+	      <_name>Leaf Spread</_name>
 	    </desc>
 	    <desc>
 	      <value>13</value>
-	      <_name>Sidekick</_name>
+	      <_name>Magic Lamp</_name>
 	    </desc>
 	    <desc>
 	      <value>14</value>
+	      <_name>Razr</_name>
+	    </desc>
+	    <desc>
+	      <value>15</value>
+	      <_name>Sidekick</_name>
+	    </desc>
+	    <desc>
+	      <value>16</value>
+	      <_name>Skewer</_name>
+	    </desc>
+	    <desc>
+	      <value>17</value>
 	      <_name>Zoom</_name>
 	    </desc>
 	  </option>
@@ -827,6 +908,23 @@
 	<_short>Effect Settings</_short>
 
 	<subgroup>
+	  <_short>Airplane</_short>
+	  <option name="airplane_path_length" type="float">
+	    <_short>Airplane Flying Path Length</_short>
+	    <_long>Length of airplane's flying path.</_long>
+	    <default>1</default>
+	    <min>0.5</min>
+	    <max>3</max>
+	    <precision>0.1</precision>
+	  </option>
+	  <option name="airplane_fly_to_taskbar" type="bool">
+	    <_short>Fly to TaskBar on Minimize</_short>
+	    <_long>Whether the window should fly to taskbar when minimized with Airplane effect.</_long>
+	    <default>true</default>
+	  </option>
+	</subgroup>
+
+	<subgroup>
 	  <_short>Fire</_short>
 	  <option name="fire_particles" type="int">
 	    <_short>Number Of Fire Particles</_short>
@@ -1354,7 +1452,7 @@
 	  </option>
 	  <option name="explode_thickness" type="float">
 	    <_short>Thickness of Exploding Polygons</_short>
-	    <_long>Thickness (in pixels) of exploding window pieces.</_long>
+	    <_long>Thickness of exploding window pieces (in pixels).</_long>
 	    <default>15</default>
 	    <min>1</min>
 	    <max>100</max>
@@ -1377,6 +1475,135 @@
 	  </option>
 	</subgroup>
 
+	<subgroup>
+	  <_short>Fold</_short>
+	  <option name="fold_gridx" type="int">
+	    <_short>Window Grid Width</_short>
+	    <_long>The animated window will be split into pieces along a grid. Specify the number of grid cells along the width of the window.</_long>
+	    <default>3</default>
+	    <min>1</min>
+	    <max>100</max>
+	  </option>
+	  <option name="fold_gridy" type="int">
+	    <_short>Window Grid Height</_short>
+	    <_long>The animated window will be split into pieces along a grid. Specify the number of grid cells along the height of the window.</_long>
+	    <default>3</default>
+	    <min>1</min>
+	    <max>100</max>
+	  </option>
+	  <option name="fold_dir" type="int">
+	    <_short>Fold Direction</_short>
+	    <_long>Window folding direction.</_long>
+	    <default>0</default>
+	    <min>0</min>
+	    <max>1</max>
+	    <desc>
+	      <value>0</value>
+	      <_name>In</_name>
+	    </desc>
+	    <desc>
+	      <value>1</value>
+	      <_name>Out</_name>
+	    </desc>
+	  </option>
+	</subgroup>
+
+	<subgroup>
+	  <_short>Skewer</_short>
+	  <option name="skewer_direction" type="int">
+	    <_short>Skewer Direction</_short>
+	    <_long>Movement direction(s) for window pieces.</_long>
+	    <default>8</default>
+	    <min>0</min>
+	    <max>9</max>
+	    <desc>
+	      <value>0</value>
+	      <_name>Left</_name>
+	    </desc>
+	    <desc>
+	      <value>1</value>
+	      <_name>Right</_name>
+	    </desc>
+	    <desc>
+	      <value>2</value>
+	      <_name>Left-right</_name>
+	    </desc>
+	    <desc>
+	      <value>3</value>
+	      <_name>Up</_name>
+	    </desc>
+	    <desc>
+	      <value>4</value>
+	      <_name>Down</_name>
+	    </desc>
+	    <desc>
+	      <value>5</value>
+	      <_name>Up-down</_name>
+	    </desc>
+	    <desc>
+	      <value>6</value>
+	      <_name>In</_name>
+	    </desc>
+	    <desc>
+	      <value>7</value>
+	      <_name>Out</_name>
+	    </desc>
+	    <desc>
+	      <value>8</value>
+	      <_name>In-out</_name>
+	    </desc>
+	    <desc>
+	      <value>9</value>
+	      <_name>Random</_name>
+	    </desc>
+	  </option>
+	  <option name="skewer_tessellation" type="int">
+	    <_short>Tessellation Type</_short>
+	    <_long>Tessellation type for window pieces.</_long>
+	    <default>0</default>
+	    <min>0</min>
+	    <max>1</max>
+	    <desc>
+	      <value>0</value>
+	      <_name>Rectangular</_name>
+	    </desc>
+	    <desc>
+	      <value>1</value>
+	      <_name>Hexagonal</_name>
+	    </desc>
+	  </option>
+ 	  <option name="skewer_gridx" type="int">
+	    <_short>Window Grid Width</_short>
+	    <_long>The animated window will be split into pieces along a grid. Specify the number of grid cells along the width of the window.</_long>
+	    <default>6</default>
+	    <min>1</min>
+	    <max>100</max>
+	  </option>
+	  <option name="skewer_gridy" type="int">
+	    <_short>Window Grid Height</_short>
+	    <_long>The animated window will be split into pieces along a grid. Specify the number of grid cells along the height of the window.</_long>
+	    <default>4</default>
+	    <min>1</min>
+	    <max>100</max>
+	  </option>
+	  <option name="skewer_thickness" type="float">
+	    <_short>Thickness of Animated Polygons</_short>
+            <_long>Thickness of animated window pieces (in pixels).</_long>
+	    <default>1</default>
+	    <min>1</min>
+	    <max>100</max>
+	    <precision>1</precision>
+	  </option>
+	  <option name="skewer_rotation" type="int">
+	    <_short>Rotation Angle</_short>
+	    <_long>Rotation angle of animated window pieces (in degrees).</_long>
+	    <default>0</default>
+	    <min>-720</min>
+	    <max>720</max>
+	    <precision>10</precision>
+	  </option>
+	</subgroup>
+
 	<option name="all_random" type="bool">
 	  <_short>Random Animations For All Events</_short>
 	  <_long>All effects are chosen randomly, ignoring the selected effect. If None is selected for an event, that event won't be animated.</_long>

Modified: fusion/plugins/animation/fold3d.c
new file mode 100644
===================================================================
--- /dev/null
+++ fusion/plugins/animation/fold3d.c
@@ -0,0 +1,241 @@
+/**
+ * Animation plugin for compiz/beryl
+ *
+ * animation.c
+ *
+ * Copyright : (C) 2006 Erkin Bahceci
+ * E-mail    : erkinbah at gmail.com
+ *
+ * Based on Wobbly and Minimize plugins by
+ *           : David Reveman
+ * E-mail    : davidr at novell.com>
+ *
+ * Fold and Skewer added by : Tomasz Kołodziejski
+ * E-mail                   : tkolodziejski at gmail.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ **/
+
+#include "animation-internal.h"
+
+// ratio of perceived length of animation compared to real duration
+// to make it appear to have the same speed with other animation effects
+#define FOLD_PERCEIVED_T 0.55f
+
+void
+fxFold3DInit (CompScreen * s, CompWindow * w)
+{
+    ANIM_WINDOW (w);
+    ANIM_SCREEN (s);
+
+    aw->animTotalTime /= FOLD_PERCEIVED_T;
+    aw->animRemainingTime = aw->animTotalTime;
+
+    int gridSizeX = animGetI (as, aw, ANIM_SCREEN_OPTION_FOLD3D_GRIDSIZE_X);
+    int gridSizeY = animGetI (as, aw, ANIM_SCREEN_OPTION_FOLD3D_GRIDSIZE_Y);
+
+    if (!tessellateIntoRectangles (w, gridSizeX, gridSizeY, 1.0f))
+	return;
+
+    PolygonSet *pset = aw->polygonSet;
+    PolygonObject *p = pset->polygons;
+
+    // handle other non-zero values
+    int fold_in = animGetI (as, aw, ANIM_SCREEN_OPTION_FOLD3D_DIR) == 0 ? 1 : 0;
+
+    float rows_duration;
+    float fduration;
+
+    if (gridSizeY == 1)
+    {
+	fduration = 1.0f / (float)(gridSizeY + 2 * ceil (gridSizeX / 2));
+	rows_duration = 0;
+    }
+    else
+    {
+	fduration =
+	    1.0f / (float)(gridSizeY + 2 * ceil (gridSizeX / 2) + 1 + fold_in);
+	rows_duration = (gridSizeY - 1 + fold_in) * fduration;
+    }
+
+    float duration = fduration * 2;
+    float start;
+    int i;
+    int j = 0;
+    int k = 0;
+
+    for (i = 0; i < pset->nPolygons; i++, p++)
+    {
+	if (i > pset->nPolygons - gridSizeX - 1)
+	{
+	    // bottom row polygons
+	    if (j < gridSizeX / 2)
+	    {
+		// the left ones
+		start = rows_duration + duration * j++;
+
+		p->rotAxis.y = -180;
+		p->finalRotAng = 180;
+
+		p->fadeStartTime = start + fduration;
+		p->fadeDuration = fduration;
+	    }
+	    else if (j == gridSizeX / 2)
+	    {
+		// the middle one
+		start = rows_duration + j * duration;
+
+		p->rotAxis.y = 90;
+		p->finalRotAng = 90;
+
+		p->fadeStartTime = start + fduration;
+		p->fadeDuration = fduration;
+		j++;
+	    }
+	    else
+	    {
+		// the right ones
+		start = rows_duration + (j - 2) * duration + duration * k--;
+
+		p->rotAxis.y = 180;
+		p->finalRotAng = 180;
+
+		p->fadeStartTime = start + fduration;
+		p->fadeDuration = fduration;
+	    }
+	}
+	else
+	{
+	    // main rows
+	    int row = i / gridSizeX;	// [0; gridSizeY-1]
+
+	    start = row * fduration;
+	    p->rotAxis.x = 180;
+	    p->finalRelPos.y = row; // number of row, not finalRelPos!!
+	    p->finalRotAng = 180;
+
+	    p->fadeDuration = fduration;
+	    p->fadeStartTime = start;
+
+	    if (row < gridSizeY - 2 || fold_in)
+		p->fadeStartTime += fduration;
+	}
+	p->moveStartTime = start;
+	p->moveDuration = duration;
+    }
+    pset->doDepthTest = TRUE;
+    pset->doLighting = TRUE;
+    pset->correctPerspective = CorrectPerspectiveWindow;
+}
+
+void
+fxFold3dAnimStepPolygon (CompWindow * w, PolygonObject * p,
+			 float forwardProgress)
+{
+    ANIM_SCREEN (w->screen);
+    ANIM_WINDOW (w);
+
+    int dir = animGetI (as, aw, ANIM_SCREEN_OPTION_FOLD3D_DIR) == 0 ? 1 : -1;
+
+    int gridSizeX = animGetI (as, aw, ANIM_SCREEN_OPTION_FOLD3D_GRIDSIZE_X);
+    int gridSizeY = animGetI (as, aw, ANIM_SCREEN_OPTION_FOLD3D_GRIDSIZE_Y);
+
+    float moveProgress = forwardProgress - p->moveStartTime;
+
+    if (p->moveDuration > 0)
+	moveProgress /= p->moveDuration;
+    if (moveProgress < 0)
+	moveProgress = 0;
+    else if (moveProgress > 1)
+	moveProgress = 1;
+
+    float const_x = BORDER_W (w) / (float)gridSizeX;	//  width of single piece
+    float const_y = BORDER_H (w) / (float)gridSizeY;	// height of single piece
+
+    p->rotAngle = dir * moveProgress * p->finalRotAng;
+
+    if (p->rotAxis.x == 180)
+    {
+	if (p->finalRelPos.y == gridSizeY - 2)
+	{
+	    // it means the last row
+	    p->centerPos.y =
+		p->centerPosStart.y + const_y / 2.0f -
+		cos (p->rotAngle * M_PI / 180.0f) * const_y / 2.0f;
+	    p->centerPos.z =
+		p->centerPosStart.z +
+		1.0f / w->screen->width * (sin (-p->rotAngle * M_PI / 180.0f) *
+					   const_y / 2.0f);
+	}
+	else
+	{
+	    // rows
+	    if (fabs (p->rotAngle) < 90)
+	    {
+		// 1. rotate 90
+		p->centerPos.y =
+		    p->centerPosStart.y + const_y / 2.0f -
+		    cos (p->rotAngle * M_PI / 180.0f) * const_y / 2.0f;
+		p->centerPos.z =
+		    p->centerPosStart.z +
+		    1.0f / w->screen->width *
+		    (sin (-p->rotAngle * M_PI / 180.0f) * const_y / 2.0f);
+	    }
+	    else
+	    {
+		// 2. rotate faster 180
+		float alpha = p->rotAngle - dir * 90;	// [0 - 45]
+		float alpha2 = 2 * alpha;	// [0 - 90]
+
+		p->rotAngle = (p->rotAngle - dir * 90) * 2 + dir * 90;
+
+		p->centerPos.y =
+		    p->centerPosStart.y + const_y / 2.0f + const_y -
+		    cos (alpha * M_PI / 180.0f) * const_y + dir *
+		    sin (alpha2 * M_PI / 180.0f) * const_y / 2.0f;
+
+		p->centerPos.z =
+		    p->centerPosStart.z +
+		    1.0f / w->screen->width *
+		    (-sin (alpha * M_PI / 180.0f) * const_y - dir *
+		     cos (alpha2 * M_PI / 180.0f) * const_y / 2.0f);
+	    }
+	}
+    }
+    else if (p->rotAxis.y == -180)
+    {
+	// simple blocks left
+	p->centerPos.x =
+	    p->centerPosStart.x + const_x / 2.0f -
+	    cos (p->rotAngle * M_PI / 180.0f) * const_x / 2.0f;
+
+	p->centerPos.z =
+	    p->centerPosStart.z -
+	    1.0f / w->screen->width * (sin (p->rotAngle * M_PI / 180.0f) *
+				       const_x / 2.0f);
+    }
+    else if (p->rotAxis.y == 180)
+    {
+	// simple blocks right
+	p->centerPos.x =
+	    p->centerPosStart.x - const_x / 2.0f +
+	    cos (-p->rotAngle * M_PI / 180.0f) * const_x / 2.0f;
+
+	p->centerPos.z =
+	    p->centerPosStart.z +
+	    1.0f / w->screen->width * (sin (-p->rotAngle * M_PI / 180.0f) *
+				       const_x / 2.0f);
+    }
+}

Modified: fusion/plugins/animation/options.c
===================================================================
--- fusion/plugins/animation/options.c
+++ fusion/plugins/animation/options.c
@@ -313,7 +313,7 @@ updateOptionSet(CompScreen *s, OptionSet *os, char *optNamesValuesOrig)
 	    break;
 	case 5:
 	    compLogMessage (s->display, "animation", CompLogLevelError,
-			    "Option \"%s\" cannot be changed like this.",
+			    "Option \"%s\" cannot be changed in option strings.",
 			    nameTrimmed);
 	    break;
 	case 6:

Modified: fusion/plugins/animation/skewer.c
new file mode 100644
===================================================================
--- /dev/null
+++ fusion/plugins/animation/skewer.c
@@ -0,0 +1,225 @@
+/**
+ * Animation plugin for compiz/beryl
+ *
+ * animation.c
+ *
+ * Copyright : (C) 2006 Erkin Bahceci
+ * E-mail    : erkinbah at gmail.com
+ *
+ * Based on Wobbly and Minimize plugins by
+ *           : David Reveman
+ * E-mail    : davidr at novell.com>
+ *
+ * Hexagon tessellator added by : Mike Slegeir
+ * E-mail                       : mikeslegeir at mail.utexas.edu>
+ *
+ * Fold and Skewer added by : Tomasz Kołodziejski
+ * E-mail                   : tkolodziejski at gmail.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. 
+ **/
+
+#include "animation-internal.h"
+
+// ratio of perceived length of animation compared to real duration
+// to make it appear to have the same speed with other animation effects
+#define SKEWER_PERCEIVED_T 0.6f
+
+static void
+getDirection (int *dir, int *c, int direction)
+{
+    switch (direction)
+    {
+    case 0:
+	// left
+	dir[(*c)++] = 0;
+	break;
+    case 1:
+	// right
+	dir[(*c)++] = 1;
+	break;
+    case 2:
+	// left-right   
+	dir[(*c)++] = 0;
+	dir[(*c)++] = 1;
+	break;
+    case 3:
+	// up
+	dir[(*c)++] = 2;
+	break;
+    case 4:
+	// downs
+	dir[(*c)++] = 3;
+	break;
+    case 5:
+	// up-down
+	dir[(*c)++] = 2;
+	dir[(*c)++] = 3;
+	break;
+    case 6:
+	// in
+	dir[(*c)++] = 4;
+	break;
+    case 7:
+	// out
+	dir[(*c)++] = 5;
+	break;
+    case 8:
+	// in-out
+	dir[(*c)++] = 4;
+	dir[(*c)++] = 5;
+	break;
+    case 9:
+	// random
+	getDirection (dir, c, floor (RAND_FLOAT () * 8));
+	break;
+    }
+}
+
+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;
+}
+
+void
+fxSkewerAnimStepPolygon (CompWindow * w,
+			 PolygonObject * p,
+			 float forwardProgress)
+{
+    float moveProgress = forwardProgress - p->moveStartTime;
+
+    if (p->moveDuration > 0)
+	moveProgress /= p->moveDuration;
+    if (moveProgress < 0)
+	moveProgress = 0;
+    else if (moveProgress > 1)
+	moveProgress = 1;
+
+    p->centerPos.x =
+	p->centerPosStart.x + pow (moveProgress, 2) * p->finalRelPos.x;
+
+    p->centerPos.y =
+	p->centerPosStart.y + pow (moveProgress, 2) * p->finalRelPos.y;
+
+    p->centerPos.z =
+	p->centerPosStart.z +
+	pow (moveProgress, 2) * p->finalRelPos.z * 1.0f / w->screen->width;
+
+    // rotate
+    p->rotAngle = pow (moveProgress, 2) * p->finalRotAng + p->rotAngleStart;
+}


More information about the commits mailing list