summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSam Spilsbury <smspillaz@gmail.com>2010-07-17 22:57:40 -0700
committerSam Spilsbury <smspillaz@gmail.com>2010-07-17 22:58:23 -0700
commit0ab1010697895dd01c98bba343991ffb805e3fc7 (patch)
tree1fed6cb97d076086808337225e068ed4a937edd8 /src
parenta8042a93fdea53591ec864118667103472f70840 (diff)
downloadmousetrails-master.tar.gz
mousetrails-master.tar.bz2
Initial C++ portHEADmaster
Diffstat (limited to 'src')
-rw-r--r--src/mousetrails.cpp731
-rw-r--r--src/mousetrails.h198
2 files changed, 929 insertions, 0 deletions
diff --git a/src/mousetrails.cpp b/src/mousetrails.cpp
new file mode 100644
index 0000000..21cbaee
--- /dev/null
+++ b/src/mousetrails.cpp
@@ -0,0 +1,731 @@
+/*
+ *
+ * Compiz mouse cursor trails plugin
+ *
+ * mousetrails.c
+ *
+ * Copyright : (C) 2008 by Erik Johnson
+ *
+ * From code originally written by Dennis Kasprzyk
+ *
+ * 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.
+ *
+ */
+
+#include <cmath>
+#include <cstring>
+
+#include "mousetrails.h"
+
+COMPIZ_PLUGIN_20090315 (mousetrails, MousetrailsPluginVTable)
+
+void
+ParticleSystem::initParticles (int numParticles)
+{
+
+ if (mParticles)
+ free(mParticles);
+ //mParticles = calloc(numParticles, sizeof(Particle));
+ mParticles = (Particle *) calloc(TEXTURES_SIZE, sizeof(Particle));
+
+ mNumParticles = numParticles;
+ mNumDisplayedParticles = 0;
+ mSlowdown = 1;
+ mActive = FALSE;
+ mLastx = 0;
+ mLasty = 0;
+ mLastGen = 0;
+ mInitialAlpha = 1;
+ mSizeFactor = 10;
+ mColorcounter = 0;
+ mX = 0;
+ mY = 0;
+ mSkip = 1;
+ mAtSkip = 0;
+ mSpeed = 1;
+ mUseMousepoll = 1;
+
+ mLastTextureFilled = -1;
+ mLastCursorIndex = 0;
+ mLastCursorSerial = 0;
+
+ // Initialize cache
+ mVertices_cache = NULL;
+ mColors_cache = NULL;
+ mCoords_cache = NULL;
+ mVertex_cache_count = 0;
+ mColor_cache_count = 0;
+ mCoords_cache_count = 0;
+
+ Particle *part = mParticles;
+ int i;
+ for (i = 0; i < TEXTURES_SIZE; i++, part++){
+ part->a = 0.0f;
+ part->r = 0.0f;
+ part->g = 0.0f;
+ part->b = 0.0f;
+ }
+
+
+ for (i = 0; i < TEXTURES_SIZE; i++){
+ mCursors[i].cursor_serial = 0;
+ mCursors[i].xhot = 0;
+ mCursors[i].yhot = 0;
+ mCursors[i].width = 0;
+ mCursors[i].height = 0;
+ }
+
+ for (i = 0; i < TEXTURES_SIZE; i++) glGenTextures(1, &mCursors[i].texture);
+
+}
+
+
+void
+ParticleSystem::drawParticles ()
+{
+ if (mNumDisplayedParticles == 0) return;
+
+ glEnable(GL_BLEND);
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glBlendFunc(GL_SRC_ALPHA, mBlendMode);
+ glEnable(GL_TEXTURE_2D);
+
+
+ // Check that the caches are correct size
+
+ if (mVertex_cache_count != 1)
+ {
+ mVertices_cache =
+ (GLfloat *) realloc(mVertices_cache,
+ 4 * 3 * sizeof(GLfloat));
+ mVertex_cache_count = 1;
+ }
+
+ if (mCoords_cache_count != 1)
+ {
+ mCoords_cache =
+ (GLfloat *) realloc(mCoords_cache,
+ 4 * 2 * sizeof(GLfloat));
+ mCoords_cache_count = 1;
+ }
+
+ if (mColor_cache_count != 1)
+ {
+ mColors_cache =
+ (GLfloat *) realloc(mColors_cache,
+ 4 * 4 * sizeof(GLfloat));
+ mColor_cache_count = 1;
+ }
+
+
+ GLfloat *vertices = mVertices_cache;
+ GLfloat *coords = mCoords_cache;
+ GLfloat *colors = mColors_cache;
+
+ int cornersSize = sizeof (GLfloat) * 8;
+ int colorSize = sizeof (GLfloat) * 4;
+
+ GLfloat cornerCoords[8] = {0.0, 0.0,
+ 0.0, 1.0,
+ 1.0, 1.0,
+ 1.0, 0.0};
+
+ int numActive = 0;
+
+ Particle *part = mParticles;
+ int i;
+ for (i = 0; i < mNumParticles; i++, part++)
+ {
+ //if (part->life > 0.0f)
+ if (part->fade > 0.001f)
+ {
+ numActive += 4;
+
+ float w = part->width / 2;
+ float h = part->height / 2;
+
+ w += (w * part->w_mod) * (1- part->a);
+ h += (h * part->h_mod) * (1- part->a);
+
+ vertices[0] = part->x - w;
+ vertices[1] = part->y - h;
+ vertices[2] = part->z;
+
+ vertices[3] = part->x - w;
+ vertices[4] = part->y + h;
+ vertices[5] = part->z;
+
+ vertices[6] = part->x + w;
+ vertices[7] = part->y + h;
+ vertices[8] = part->z;
+
+ vertices[9] = part->x + w;
+ vertices[10] = part->y - h;
+ vertices[11] = part->z;
+
+ //vertices += 12;
+
+ memcpy (coords, cornerCoords, cornersSize);
+
+ //coords += 8;
+
+ colors[0] = part->r;
+ colors[1] = part->g;
+ colors[2] = part->b;
+ colors[3] = part->a;
+ memcpy (colors + 4, colors, colorSize);
+ memcpy (colors + 8, colors, colorSize);
+ memcpy (colors + 12, colors, colorSize);
+
+ //colors += 16;
+
+ if (mCursors[part->cursorIndex].texture)
+ {
+ glPushMatrix();
+
+ glBindTexture(GL_TEXTURE_2D, mCursors[part->cursorIndex].texture);
+
+ glTexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), mCoords_cache);
+ glVertexPointer(3, GL_FLOAT, 3 * sizeof(GLfloat), mVertices_cache);
+ glColorPointer(4, GL_FLOAT, 4 * sizeof(GLfloat), mColors_cache);
+
+ // draw particles
+ glDrawArrays(GL_QUADS, 0, numActive);
+
+ glPopMatrix();
+ }
+
+ }
+
+ }
+
+
+ glDisableClientState(GL_COLOR_ARRAY);
+ glColor4usv(defaultColor);
+ GLScreen::get(screen)->setTexEnvMode (GL_REPLACE);
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_BLEND);
+
+}
+
+void
+ParticleSystem::updateParticles (float time)
+{
+ int i;
+ Particle *part;
+ float speed = (time / 5000.0);
+
+ mActive = FALSE;
+
+ part = mParticles;
+
+ int numDisplayedParticles = 0;
+
+ for (i = 0; i < mNumParticles; i++, part++)
+ {
+ if (part->a > 0.001f)
+ {
+ // modify opacity
+ part->a -= 50 * part->a * part->fade * speed;
+ mActive = TRUE;
+
+ numDisplayedParticles++;
+ }
+ }
+ mNumDisplayedParticles = numDisplayedParticles;
+}
+
+void
+ParticleSystem::finiParticles ()
+{
+ free(mParticles);
+ if (mVertices_cache)
+ free(mVertices_cache);
+ if (mColors_cache)
+ free(mColors_cache);
+ if (mCoords_cache)
+ free(mCoords_cache);
+
+ int i;
+ for (i = 0; i < TEXTURES_SIZE; i++) glDeleteTextures(1, &mCursors[i].texture);
+
+}
+
+
+/*
+Window root_return;
+Window child_return;
+int rootX, rootY;
+int winX, winY;
+unsigned int maskReturn;
+Bool status;*/
+
+void
+ParticleSystem::genNewParticles (int time)
+{
+ MOUSETRAILS_SCREEN (screen);
+
+
+ mSkip = ss->optionGetSkip () ;
+ mAtSkip = (mAtSkip + 1) % mSkip;
+ if (mAtSkip != 0) return;
+
+ Bool rColor = ss->optionGetRandom ();
+ //float life = ss->optionGetLife ();
+ int sizeFactor = mSizeFactor;
+ //float lifeNeg = 1 - life;
+ //float fadeExtra = 0.05f * (1.01 - life);
+ int cursorIndex = 0;
+
+ unsigned short *c = ss->optionGetColor ();
+
+ float colr1 = (float)c[0] / 0xffff;
+ float colg1 = (float)c[1] / 0xffff;
+ float colb1 = (float)c[2] / 0xffff;
+ //float cola = (float)c[3] / 0xffff;
+
+ float partw = mCursors[mLastCursorIndex].width;
+ float parth = mCursors[mLastCursorIndex].height;
+
+ float partoffw = mCursors[mLastCursorIndex].xhot;
+ float partoffh = mCursors[mLastCursorIndex].yhot;
+
+ int livex;
+ int livey;
+
+ // get x cursor position (rootX and rootY)
+ /*if (!mUseMousepoll){
+ status = XQueryPointer (s->display->display, s->root,
+ &root_return, &child_return,
+ &rootX, &rootY, &winX, &winY, &maskReturn);
+
+ livex = rootX;
+ livey = rootY;
+ }
+ else
+ {*/
+ livex = ss->mPosX;
+ livey = ss->mPosY;
+ //}
+
+ int deltax = livex - mX;
+ int deltay = livey - mY;
+ int delta = deltax * deltax + deltay * deltay;
+ mX = livex;
+ mY = livey;
+ //if (delta < threshold * threshold) return;
+ if (delta < 1 ) return;
+
+ int newx = (float)(mX + partw/2 - partoffw);
+ int newy = (float)(mY + parth/2 - partoffh);
+
+
+ Particle *part = mParticles;
+ int i;
+
+ // possibly crashy
+ if (ss->optionGetNumParticles() != mNumParticles){
+ //initParticles(ss->optionGetNumParticles (), ss->ps);
+ mNumParticles = ss->optionGetNumParticles();
+ mLastGen = -1;
+ /*ps->slowdown = ss->optionGetSlowdown ();
+ mInitialAlpha = ss->optionGetAlpha () ;
+ mSizeFactor = ss->optionGetSize () ;
+ mThreshold = ss->optionGetThreshold () ;
+ mColorrate = ss->optionGetColorrate () ;*/
+ for (i = 0; i < mNumParticles; i++, part++){
+ part->a = 0.0f;
+ part->r = 0.0f;
+ part->g = 0.0f;
+ part->b = 0.0f;
+ }
+ }
+
+
+ //if (delta > threshold * threshold) max_new = 1;
+
+ int nextGen = (mLastGen + 1) % mNumParticles;
+
+ for (i = 0; i < mNumParticles; i++, part++)
+ {
+ if (i == nextGen)
+ {
+ // record the particle number being generated
+ mLastGen = i;
+
+ cursorIndex = ss->cursorUpdate ();
+
+ mSlowdown = ss->optionGetSlowdown ();
+ mInitialAlpha = ss->optionGetAlpha () ;
+ mSizeFactor = ss->optionGetSize () ;
+ mThreshold = ss->optionGetThreshold () ;
+ mColorrate = ss->optionGetColorrate () ;
+
+ // set the cursor array index
+ part->cursorIndex = mLastCursorIndex = cursorIndex;
+
+ part->fade = mSlowdown / 10.0;
+
+ // set size
+ part->width = partw;
+ part->height = parth;
+ part->w_mod = part->h_mod = ((float)sizeFactor - 10.0) / 10.0;
+
+ // set direction
+ part->xd = newx - mLastx;
+ part->yd = newy - mLasty;
+
+ // set position
+ part->x = newx;
+ part->y = newy;
+ mLastx = newx;
+ mLasty = newy;
+ part->z = 0.0;
+
+
+ if (rColor)
+ {
+ float value;
+ // linear smoothing
+ value = mColorcounter;
+ // sinwave smoothing - nothing spectacular
+ //value = (float)mColorrate - ((float)mColorrate / 2) * (1 + cos (3.14159 * (float)mColorcounter / (float)mColorrate));
+
+ if (mColorcounter == 0)
+ {
+ mR2 = (float)(random() & 0xff) / 255;
+ mG2 = (float)(random() & 0xff) / 255;
+ mB2 = (float)(random() & 0xff) / 255;
+ }
+ mR = ((float)mColorrate - value)/(float)mColorrate * mR + value/(float)mColorrate * mR2;
+ mG = ((float)mColorrate - value)/(float)mColorrate * mG + value/(float)mColorrate * mG2;
+ mB = ((float)mColorrate - value)/(float)mColorrate * mB + value/(float)mColorrate * mB2;
+ part->r = mR;
+ part->g = mG;
+ part->b = mB;
+ mColorcounter = (mColorcounter + 1) % mColorrate;
+ }
+ else
+ {
+ part->r = colr1;
+ part->g = colg1;
+ part->b = colb1;
+ }
+ // set transparancy
+ //part->a = mInitialAlpha;
+ float thresholdfactor = 1.0;
+ if (delta < mThreshold) thresholdfactor = (float)delta / (float)mThreshold;
+ part->a = mInitialAlpha * thresholdfactor;
+
+ mActive = TRUE;
+ }
+ }
+}
+
+// damageRegion() seems to cause blockiness or jitters on the background window when scrolling, like on a webpage
+
+void
+MousetrailsScreen::damageRegion ()
+{
+ int i;
+ Particle *p;
+ float w, h, x1, x2, y1, y2;
+
+ if (mPs->mNumDisplayedParticles == 0) return;
+
+ if (!mPs)
+ return;
+
+ x1 = screen->width ();
+ x2 = 0;
+ y1 = screen->height ();
+ y2 = 0;
+
+ p = mPs->mParticles;
+
+ for (i = 0; i < mPs->mNumParticles; i++, p++)
+ {
+ if (p->a > 0.001f){
+ w = p->width / 2;
+ h = p->height / 2;
+
+ w += (w * p->w_mod) * p->a;
+ h += (h * p->h_mod) * p->a;
+
+ x1 = MIN (x1, p->x - w);
+ x2 = MAX (x2, p->x + w);
+ y1 = MIN (y1, p->y - h);
+ y2 = MAX (y2, p->y + h);
+ }
+ }
+
+ CompRegion r (floor (x1), floor (y1), ceil (x2) - floor (x1),
+ ceil (y2) - floor (y1));
+
+ cScreen->damageRegion (r);
+}
+
+int
+MousetrailsScreen::cursorUpdate ()
+{
+
+ Display * dpy = screen->dpy ();
+ XFixesCursorImage *ci = XFixesGetCursorImage(dpy);
+
+ /* Hack to avoid changing to an invisible (bugged)cursor image.
+ * Example: The animated firefox cursors.
+ */
+ if (ci->width <= 1 && ci->height <= 1)
+ {
+ XFree (ci);
+ return mPs->mLastCursorIndex;
+ }
+
+ // only update cursor if necessary (instead of all the time)
+ if (ci->cursor_serial == mPs->mLastCursorSerial)
+ {
+ XFree (ci);
+ return mPs->mLastCursorIndex;
+ }
+
+ // see if cursor already exists in textures
+ int i;
+ for (i = 0; i < TEXTURES_SIZE; i++){
+ if (ci->cursor_serial == mPs->mCursors[i].cursor_serial){
+ mPs->mLastCursorSerial = ci->cursor_serial;
+ XFree (ci);
+ return i;
+ }
+ }
+
+ // otherwise grab the new cursor into textures
+ int fillTexture = (mPs->mLastTextureFilled + 1) % TEXTURES_SIZE;
+
+ unsigned char *pixels = (unsigned char *) malloc(ci->width * ci->height * 4);
+
+ for (i = 0; i < ci->width * ci->height; i++)
+ {
+ unsigned long pix = ci->pixels[i];
+ pixels[i * 4] = pix & 0xff;
+ pixels[(i * 4) + 1] = (pix >> 8) & 0xff;
+ pixels[(i * 4) + 2] = (pix >> 16) & 0xff;
+ pixels[(i * 4) + 3] = (pix >> 24) & 0xff;
+ }
+
+ glBindTexture(GL_TEXTURE_2D, mPs->mCursors[fillTexture].texture);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ci->width, ci->height, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ // save data for this cursor
+ mPs->mCursors[fillTexture].cursor_serial = mPs->mLastCursorSerial = ci->cursor_serial;
+ mPs->mCursors[fillTexture].xhot = ci->xhot;
+ mPs->mCursors[fillTexture].yhot = ci->yhot;
+ mPs->mCursors[fillTexture].width = ci->width;
+ mPs->mCursors[fillTexture].height = ci->height;
+ mPs->mLastTextureFilled = fillTexture;
+
+ XFree (ci);
+ free (pixels);
+
+ return fillTexture;
+}
+
+
+void
+MousetrailsScreen::positionUpdate (const CompPoint &p)
+{
+ int x = p.x ();
+ int y = p.y ();
+
+ mPosX = x;
+ mPosY = y;
+}
+
+
+
+void
+MousetrailsScreen::preparePaint (int time)
+{
+ //Bool useMousepoll = optionGetMousepoll ();
+
+ if (mActive && !mPollHandle.active ())
+ {
+ CompPoint p = mPollHandle.getCurrentPosition ();
+ mPosX = p.x ();
+ mPosY = p.y ();
+ mPollHandle.start ();
+ }
+
+ if (mActive && !mPs)
+ {
+ mPs = (ParticleSystem *) calloc(1, sizeof(ParticleSystem));
+ if (!mPs)
+ {
+ cScreen->preparePaint (time);;
+ return;
+ }
+ mPs->initParticles(optionGetNumParticles ());
+
+ mPs->mSlowdown = optionGetSlowdown ();
+ mPs->mInitialAlpha = optionGetAlpha () ;
+ mPs->mThreshold = optionGetThreshold () ;
+ mPs->mColorrate = optionGetColorrate () ;
+ mPs->mSizeFactor = optionGetSize () ;
+ mPs->mSkip = optionGetSkip () ;
+ mPs->mBlendMode = GL_ONE_MINUS_SRC_ALPHA;
+ //mPs->useMousepoll = optionGetMousepoll ();
+
+ cursorUpdate ();
+
+ }
+
+
+ if (mPs && mPs->mActive)
+ {
+ mPs->updateParticles (time);
+ damageRegion ();
+ }
+
+ if (mPs && mActive)
+ mPs->genNewParticles (time);
+
+ cScreen->preparePaint (time);
+
+}
+
+void
+MousetrailsScreen::donePaint ()
+{
+
+ if (mActive || (mPs && mPs->mActive))
+ damageRegion ();
+
+ if (!mActive && mPollHandle.active () && mPs->mUseMousepoll)
+ {
+ mPollHandle.stop ();
+ }
+
+ if (!mActive && mPs && !mPs->mActive)
+ {
+ mPs->finiParticles ();
+ free (mPs);
+ mPs = NULL;
+ }
+
+ cScreen->donePaint ();
+}
+
+bool
+MousetrailsScreen::glPaintOutput (const GLScreenPaintAttrib &attrib,
+ const GLMatrix &transform,
+ const CompRegion &region,
+ CompOutput *output,
+ unsigned int mask)
+{
+ bool status;
+ GLMatrix sTransform (transform);
+
+ status = gScreen->glPaintOutput (attrib, transform, region, output, mask);
+
+ if (!mPs || !mPs->mActive)
+ return status;
+
+// this doesn't seem to work
+// if (mask & PAINT_SCREEN_TRANSFORMED_MASK) return FALSE;
+
+ sTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
+
+ glPushMatrix ();
+ glLoadMatrixf (sTransform.getMatrix ());
+
+ mPs->drawParticles ();
+
+ glPopMatrix();
+
+ glColor4usv (defaultColor);
+
+ return status;
+}
+
+bool
+MousetrailsScreen::terminate (CompAction *action,
+ CompAction::State state,
+ CompOption::Vector options)
+{
+ mActive = false;
+ damageRegion ();
+
+ return true;
+}
+
+bool
+MousetrailsScreen::initiate (CompAction *action,
+ CompAction::State state,
+ CompOption::Vector &options)
+{
+
+ if (mActive)
+ return terminate (action, state, options);
+
+ mActive = true;
+
+ return true;
+}
+
+MousetrailsScreen::MousetrailsScreen (CompScreen *screen) :
+ PluginClassHandler <MousetrailsScreen, CompScreen> (screen),
+ cScreen (CompositeScreen::get (screen)),
+ gScreen (GLScreen::get (screen)),
+ mPosX (0),
+ mPosY (0),
+ mActive (false),
+ mPs (NULL)
+{
+ CompositeScreenInterface::setHandler (cScreen);
+ GLScreenInterface::setHandler (gScreen);
+
+ mPollHandle.setCallback (boost::bind (&MousetrailsScreen::positionUpdate, this, _1));
+
+ optionSetInitiateInitiate (boost::bind (&MousetrailsScreen::initiate, this, _1, _2, _3));
+ optionSetInitiateTerminate (boost::bind (&MousetrailsScreen::terminate, this, _1, _2, _3));
+}
+
+MousetrailsScreen::~MousetrailsScreen ()
+{
+ if (mPollHandle.active ())
+ mPollHandle.stop ();
+
+ if (mPs && mPs->mActive)
+ {
+ mPs->finiParticles ();
+ free (mPs);
+ cScreen->damageScreen ();
+ }
+}
+
+bool
+MousetrailsPluginVTable::init ()
+{
+ if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION) ||
+ !CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI) ||
+ !CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI) ||
+ !CompPlugin::checkPluginABI ("mousepoll", COMPIZ_MOUSEPOLL_ABI))
+ return false;
+
+ return true;
+}
diff --git a/src/mousetrails.h b/src/mousetrails.h
new file mode 100644
index 0000000..c554184
--- /dev/null
+++ b/src/mousetrails.h
@@ -0,0 +1,198 @@
+/*
+ *
+ * Compiz mouse cursor trails plugin
+ *
+ * mousetrails.h
+ *
+ * Copyright : (C) 2008 by Erik Johnson
+ *
+ * From code originally written by Dennis Kasprzyk
+ *
+ * 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.
+ *
+ */
+
+#include <cmath>
+
+#include <core/core.h>
+#include <composite/composite.h>
+#include <opengl/opengl.h>
+#include <mousepoll/mousepoll.h>
+
+#include "mousetrails_options.h"
+
+// in theory the texture array size should be >= trail size
+#define TEXTURES_SIZE 51
+
+class Particle
+{
+ public:
+ //float life; // particle life
+ float fade; // fade speed
+ float width; // particle width
+ float height; // particle height
+ float w_mod; // particle size modification during life
+ float h_mod; // particle size modification during life
+ float r; // red value
+ float g; // green value
+ float b; // blue value
+ float a; // alpha value
+ float x; // X position
+ float y; // Y position
+ float z; // Z position
+ float xd;
+ float yd;
+ int cursorIndex; // array index of cursor serial number
+};
+
+class MouseCursor
+{
+ public:
+ GLuint texture;
+ unsigned long cursor_serial;
+ unsigned short xhot;
+ unsigned short yhot;
+ unsigned short width;
+ unsigned short height;
+};
+
+class ParticleSystem
+{
+ public:
+ int mNumParticles;
+ Particle *mParticles;
+ float mSlowdown;
+ float mThreshold;
+ Bool mActive;
+ int mX, mY;
+ GLuint mBlendMode;
+
+ int mLastx, mLasty;
+ float mDelta;
+ int mNumDisplayedParticles;
+ int mLastGen;
+ float mInitialAlpha;
+ int mSizeFactor;
+ Bool mUseMousepoll;
+
+ // for random colors
+ int mColorcounter;
+ float mR; // red value
+ float mG; // green value
+ float mB; // blue value
+ float mR2; // red value
+ float mG2; // green value
+ float mB2; // blue value
+ int mColorrate;
+ int mSkip;
+ int mAtSkip;
+ int mSpeed;
+
+ // Cursor data
+ MouseCursor mCursors[TEXTURES_SIZE]; // rolling array of cursors grabbed from x
+ int mLastTextureFilled; // last slot used in textures
+ unsigned long mLastCursorSerial; // last cursor serial number grabbed from X
+ int mLastCursorIndex; // ...and its associated array index
+
+ // Moved from drawParticles to get rid of spurious malloc's
+ GLfloat *mVertices_cache;
+ int mVertex_cache_count;
+ GLfloat *mCoords_cache;
+ int mCoords_cache_count;
+ GLfloat *mColors_cache;
+ int mColor_cache_count;
+
+ void
+ initParticles (int f_numParticles);
+
+ void
+ drawParticles ();
+
+ void
+ updateParticles (float time);
+
+ void
+ finiParticles ();
+
+ void
+ genNewParticles (int time);
+
+};
+
+class MousetrailsScreen :
+ public PluginClassHandler <MousetrailsScreen, CompScreen>,
+ public CompositeScreenInterface,
+ public GLScreenInterface,
+ public MousetrailsOptions
+{
+ public:
+
+ MousetrailsScreen (CompScreen *screen);
+ ~MousetrailsScreen ();
+
+ public:
+
+ CompositeScreen *cScreen;
+ GLScreen *gScreen;
+
+ int mPosX;
+ int mPosY;
+
+ Bool mActive;
+
+ ParticleSystem *mPs;
+
+ MousePoller mPollHandle;
+
+ void
+ preparePaint (int);
+
+ bool
+ glPaintOutput (const GLScreenPaintAttrib &,
+ const GLMatrix &,
+ const CompRegion &,
+ CompOutput *,
+ unsigned int );
+
+ void
+ donePaint ();
+
+ void
+ damageRegion ();
+
+ void
+ positionUpdate (const CompPoint &p);
+
+ bool
+ terminate (CompAction *action,
+ CompAction::State state,
+ CompOption::Vector options);
+
+ bool
+ initiate (CompAction *action,
+ CompAction::State state,
+ CompOption::Vector &options);
+
+ int
+ cursorUpdate ();
+
+};
+
+#define MOUSETRAILS_SCREEN(s) \
+ MousetrailsScreen *ss = MousetrailsScreen::get (s);
+
+class MousetrailsPluginVTable :
+ public CompPlugin::VTableForScreen <MousetrailsScreen>
+{
+ public:
+
+ bool init ();
+};