2
* Animation plugin for compiz/beryl
6
* Copyright : (C) 2006 Erkin Bahceci
7
* E-mail : erkinbah@gmail.com
9
* Based on Wobbly and Minimize plugins by
11
* E-mail : davidr@novell.com>
13
* Particle system added by : (C) 2006 Dennis Kasprzyk
14
* E-mail : onestone@beryl-project.org
16
* Beam-Up added by : Florencio Guimaraes
17
* E-mail : florencio@nexcorp.com.br
19
* Hexagon tessellator added by : Mike Slegeir
20
* E-mail : mikeslegeir@mail.utexas.edu>
22
* This program is free software; you can redistribute it and/or
23
* modify it under the terms of the GNU General Public License
24
* as published by the Free Software Foundation; either version 2
25
* of the License, or (at your option) any later version.
27
* This program is distributed in the hope that it will be useful,
28
* but WITHOUT ANY WARRANTY; without even the implied warranty of
29
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30
* GNU General Public License for more details.
32
* You should have received a copy of the GNU General Public License
33
* along with this program; if not, write to the Free Software
34
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
39
// ===================== Effect: Magic Lamp =========================
42
MagicLampAnim::initGrid ()
45
mGridHeight = optValI (AnimationOptions::MagicLampGridRes);
49
MagicLampWavyAnim::initGrid ()
52
mGridHeight = optValI (AnimationOptions::MagicLampWavyGridRes);
55
MagicLampAnim::MagicLampAnim (CompWindow *w,
56
WindowEvent curWindowEvent,
58
const AnimEffect info,
59
const CompRect &icon) :
60
Animation::Animation (w, curWindowEvent, duration, info, icon),
61
GridAnim::GridAnim (w, curWindowEvent, duration, info, icon)
63
CompRect outRect (mAWindow->savedRectsValid () ?
64
mAWindow->savedOutRect () :
67
mTargetTop = ((outRect.y () + outRect.height () / 2) >
68
(icon.y () + icon.height () / 2));
73
MagicLampWavyAnim::MagicLampWavyAnim (CompWindow *w,
74
WindowEvent curWindowEvent,
76
const AnimEffect info,
77
const CompRect &icon) :
78
Animation::Animation (w, curWindowEvent, duration, info, icon),
79
MagicLampAnim::MagicLampAnim (w, curWindowEvent, duration, info, icon)
81
unsigned int maxWaves;
82
float waveAmpMin, waveAmpMax;
85
maxWaves = (unsigned) optValI (AnimationOptions::MagicLampWavyMaxWaves);
86
waveAmpMin = optValF (AnimationOptions::MagicLampWavyAmpMin);
87
waveAmpMax = optValF (AnimationOptions::MagicLampWavyAmpMax);
89
if (waveAmpMax < waveAmpMin)
90
waveAmpMax = waveAmpMin;
94
CompRect outRect (mAWindow->savedRectsValid () ?
95
mAWindow->savedOutRect () :
98
distance = outRect.y () + outRect.height () - mIcon.y ();
100
distance = mIcon.y () - outRect.y ();
103
1 + (float)maxWaves *distance / ::screen->height ();
105
mWaves = new WaveParam[mNumWaves];
107
// Compute wave parameters
109
int ampDirection = (RAND_FLOAT () < 0.5 ? 1 : -1);
110
float minHalfWidth = 0.22f;
111
float maxHalfWidth = 0.38f;
113
for (unsigned int i = 0; i < mNumWaves; i++)
116
ampDirection * (waveAmpMax - waveAmpMin) *
117
rand () / RAND_MAX + ampDirection * waveAmpMin;
118
mWaves[i].halfWidth =
119
RAND_FLOAT () * (maxHalfWidth - minHalfWidth) + minHalfWidth;
121
// avoid offset at top and bottom part by added waves
122
float availPos = 1 - 2 * mWaves[i].halfWidth;
123
float posInAvailSegment = 0;
127
(availPos / mNumWaves) * RAND_FLOAT ();
131
i * availPos / mNumWaves +
132
mWaves[i].halfWidth);
134
// switch wave direction
139
MagicLampWavyAnim::~MagicLampWavyAnim ()
144
/// Makes sure the window gets fully damaged with
145
/// effects that possibly have models that don't cover
146
/// the whole window (like in MagicLampAnim with menus).
147
MagicLampAnim::~MagicLampAnim ()
149
if (mCurWindowEvent == WindowEventOpen ||
150
mCurWindowEvent == WindowEventUnminimize ||
151
mCurWindowEvent == WindowEventUnshade)
153
mAWindow->expandBBWithWindow ();
158
MagicLampWavyAnim::hasMovingEnd ()
160
return optValB (AnimationOptions::MagicLampWavyMovingEnd);
164
MagicLampAnim::hasMovingEnd ()
166
return optValB (AnimationOptions::MagicLampMovingEnd);
169
/// Applies waves (at each step of the animation).
171
MagicLampWavyAnim::filterTargetX (float &targetX, float x)
173
for (unsigned int i = 0; i < mNumWaves; i++)
175
float cosx = ((x - mWaves[i].pos) /
176
mWaves[i].halfWidth);
177
if (cosx < -1 || cosx > 1)
179
targetX += (mWaves[i].amp * mModel->scale ().x () *
180
(cos (cosx * M_PI) + 1) / 2);
185
MagicLampAnim::step ()
187
if ((curWindowEvent () == WindowEventOpen ||
188
curWindowEvent () == WindowEventClose) &&
192
// Update icon position
193
AnimScreen::get (::screen)->getMousePointerXY (&x, &y);
197
float forwardProgress = progressLinear ();
202
float winVisibleCloseEndY;
204
CompRect inRect (mAWindow->savedRectsValid () ?
205
mAWindow->savedInRect () :
206
mWindow->borderRect ());
207
CompRect outRect (mAWindow->savedRectsValid () ?
208
mAWindow->savedOutRect () :
209
mWindow->outputRect ());
210
CompWindowExtents outExtents (mAWindow->savedRectsValid () ?
211
mAWindow->savedOutExtents () :
214
float iconShadowLeft =
215
((float)(outRect.x () - inRect.x ())) *
216
mIcon.width () / mWindow->width ();
217
float iconShadowRight =
218
((float)(outRect.x2 () - inRect.x2 ())) *
219
mIcon.width () / mWindow->width ();
221
float sigmoid0 = sigmoid (0);
222
float sigmoid1 = sigmoid (1);
224
float winw = outRect.width ();
225
float winh = outRect.height ();
229
iconFarEndY = mIcon.y ();
230
iconCloseEndY = mIcon.y () + mIcon.height ();
231
winFarEndY = outRect.y () + winh;
232
winVisibleCloseEndY = outRect.y ();
233
if (winVisibleCloseEndY < iconCloseEndY)
234
winVisibleCloseEndY = iconCloseEndY;
238
iconFarEndY = mIcon.y () + mIcon.height ();
239
iconCloseEndY = mIcon.y ();
240
winFarEndY = outRect.y ();
241
winVisibleCloseEndY = outRect.y () + winh;
242
if (winVisibleCloseEndY > iconCloseEndY)
243
winVisibleCloseEndY = iconCloseEndY;
246
float preShapePhaseEnd = 0.22f;
247
float preShapeProgress = 0;
248
float postStretchProgress = 0;
249
float stretchProgress = 0;
250
float stretchPhaseEnd =
251
preShapePhaseEnd + (1 - preShapePhaseEnd) *
253
winVisibleCloseEndY) / ((iconCloseEndY - winFarEndY) +
254
(iconCloseEndY - winVisibleCloseEndY));
255
if (stretchPhaseEnd < preShapePhaseEnd + 0.1)
256
stretchPhaseEnd = preShapePhaseEnd + 0.1;
258
if (forwardProgress < preShapePhaseEnd)
260
preShapeProgress = forwardProgress / preShapePhaseEnd;
262
// Slow down "shaping" toward the end
263
preShapeProgress = 1 - progressDecelerate (1 - preShapeProgress);
266
if (forwardProgress < preShapePhaseEnd)
268
stretchProgress = forwardProgress / stretchPhaseEnd;
272
if (forwardProgress < stretchPhaseEnd)
274
stretchProgress = forwardProgress / stretchPhaseEnd;
278
postStretchProgress =
279
(forwardProgress - stretchPhaseEnd) / (1 - stretchPhaseEnd);
283
// The other objects are squeezed into a horizontal line behind the icon
284
int topmostMovingObjectIdx = -1;
285
int bottommostMovingObjectIdx = -1;
287
unsigned int n = mModel->numObjects ();
289
GridModel::GridObject *object = mModel->objects ();
290
for (unsigned int i = 0; i < n; i++, object++)
292
Point3d &objPos = object->position ();
293
float objGridX = object->gridPosition ().x ();
295
if (i % 2 == 0) // object is at the left side
297
float objGridY = object->gridPosition ().y ();
299
float origY = (mWindow->y () +
300
(winh * objGridY - outExtents.top) *
301
mModel->scale ().y ());
302
float iconY = (mIcon.y () + mIcon.height () * objGridY);
306
stretchedPos = objGridY * origY + (1 - objGridY) * iconY;
308
stretchedPos = (1 - objGridY) * origY + objGridY * iconY;
310
// Compute current y position
311
if (forwardProgress < preShapePhaseEnd)
313
objPos.setY ((1 - stretchProgress) * origY +
314
stretchProgress * stretchedPos);
318
if (forwardProgress < stretchPhaseEnd)
320
objPos.setY ((1 - stretchProgress) * origY +
321
stretchProgress * stretchedPos);
325
objPos.setY ((1 - postStretchProgress) * stretchedPos +
326
postStretchProgress *
327
(stretchedPos + (iconCloseEndY - winFarEndY)));
333
// pick the first one that is below icon's bottom (close) edge
334
if (objPos.y () > iconCloseEndY &&
335
topmostMovingObjectIdx < 0)
336
topmostMovingObjectIdx = (int)i;
338
if (objPos.y () < iconFarEndY)
339
objPos.setY (iconFarEndY);
343
// pick the first one that is below icon's top (close) edge
344
if (objPos.y () > iconCloseEndY &&
345
bottommostMovingObjectIdx < 0)
346
bottommostMovingObjectIdx = (int)i;
348
if (objPos.y () > iconFarEndY)
349
objPos.setY (iconFarEndY);
352
fx = ((iconCloseEndY - objPos.y ()) /
353
(iconCloseEndY - winFarEndY));
355
else // object is at the right side
357
// Set y position to the y position of the object at the left
358
// on the same row (previous object)
359
objPos.setY ((object - 1)->position ().y ());
362
float origX = (mWindow->x () +
363
(winw * objGridX - outExtents.left) *
364
mModel->scale ().x ());
366
(mIcon.x () - iconShadowLeft) +
367
(mIcon.width () + iconShadowLeft + iconShadowRight) * objGridX;
369
// Compute "target shape" x position
370
float fy = ((sigmoid (fx) - sigmoid0) /
371
(sigmoid1 - sigmoid0));
372
float targetX = fy * (origX - iconX) + iconX;
374
filterTargetX (targetX, fx);
376
// Compute current x position
377
if (forwardProgress < preShapePhaseEnd)
378
objPos.setX ((1 - preShapeProgress) * origX +
379
preShapeProgress * targetX);
381
objPos.setX (targetX);
383
// No need to set objPos.z () to 0, since they won't be used
384
// due to modelAnimIs3D being false for magic lamp.
387
if (stepRegionUsed ())
389
// Pick objects that will act as the corners of rectangles subtracted
390
// from this step's damaged region
392
const float topCornerRowRatio =
393
(mTargetTop ? 0.55 : 0.35);// 0.46 0.42; // rectangle corner row ratio
394
const float bottomCornerRowRatio =
395
(mTargetTop ? 0.65 : 0.42);// 0.46 0.42; // rectangle corner row ratio
397
if (topmostMovingObjectIdx < 0)
398
topmostMovingObjectIdx = 0;
399
if (bottommostMovingObjectIdx < 0)
400
bottommostMovingObjectIdx = (int)n - 2;
402
int nRows = (bottommostMovingObjectIdx - topmostMovingObjectIdx) / 2;
403
int firstMovingRow = topmostMovingObjectIdx / 2;
404
mTopLeftCornerObject = &mModel->objects ()
405
[(int)(firstMovingRow + topCornerRowRatio * nRows) * 2];
406
mBottomLeftCornerObject = &mModel->objects ()
407
[(int)(firstMovingRow + bottomCornerRowRatio * nRows) * 2];
412
MagicLampAnim::updateBB (CompOutput &output)
414
// Just consider the corner objects
416
GridModel::GridObject *objects = mModel->objects ();
417
unsigned int n = mModel->numObjects ();
418
for (unsigned int i = 0; i < n; i++)
420
Point3d &objPos = objects[i].position ();
421
mAWindow->expandBBWithPoint (objPos.x () + 0.5,
424
// skip to the last row after considering the first row
425
// (each row has 2 objects)
430
// Subtract a rectangle from each bounding box corner left empty by
433
mAWindow->resetStepRegionWithBB ();
434
BoxPtr BB = mAWindow->BB ();
435
CompRegion ®ion = mAWindow->stepRegion ();
438
if (objects[0].position ().x () >
439
objects[n-2].position ().x ())
441
// Top-left corner is empty
443
// Position of grid object to pick as the corner of the subtracted rect.
444
Point3d &objPos = mTopLeftCornerObject->position ();
445
region -= CompRect (BB->x1,
447
objPos.x () - BB->x1,
448
objPos.y () - BB->y1);
450
else // Bottom-left corner is empty
452
// Position of grid object to pick as the corner of the subtracted rect.
453
Point3d &objPos = mBottomLeftCornerObject->position ();
454
region -= CompRect (BB->x1,
456
objPos.x () - BB->x1,
461
if (objects[1].position ().x () <
462
objects[n-1].position ().x ())
464
// Top-right corner is empty
466
// Position of grid object to pick as the corner of the subtracted rect.
467
Point3d &objPos = (mTopLeftCornerObject + 1)->position ();
468
region -= CompRect (objPos.x (),
471
objPos.y () - BB->y1);
473
else // Bottom-right corner is empty
475
// Position of grid object to pick as the corner of the subtracted rect.
476
Point3d &objPos = (mBottomLeftCornerObject + 1)->position ();
477
region -= CompRect (objPos.x (),
485
MagicLampWavyAnim::updateBB (CompOutput &output)
487
GridAnim::updateBB (output);
491
MagicLampAnim::adjustPointerIconSize ()
493
mIcon.setWidth (MAX (4, optValI
494
(AnimationOptions::MagicLampOpenStartWidth)));
496
// Adjust position so that the icon is centered at the original position.
497
mIcon.setX (mIcon.x () - mIcon.width () / 2);
501
MagicLampWavyAnim::adjustPointerIconSize ()
503
mIcon.setWidth (MAX (4, optValI
504
(AnimationOptions::MagicLampWavyOpenStartWidth)));
506
// Adjust position so that the icon is centered at the original position.
507
mIcon.setX (mIcon.x () - mIcon.width () / 2);