2
* paranormal: iterated pipeline-driven visualization plugin
3
* Copyright (c) 2006, 2007 William Pitcock <nenolod@dereferenced.org>
4
* Portions copyright (c) 2001 Jamie Gennis <jgennis@mindspring.com>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; under version 2 of the License.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
/* FIXME: what to name this file? */
24
#include "paranormal.h"
25
#include "actuators.h"
27
#include "libcalc/calc.h"
29
/* **************** general_fade **************** */
30
static struct pn_actuator_option_desc general_fade_opts[] =
32
{ "amount", "The amount by which the color index of each "
33
"pixel should be decreased by each frame (MAX 255)",
34
OPT_TYPE_INT, { ival: 3 } },
39
general_fade_exec (const struct pn_actuator_option *opts,
42
int amt = opts[0].val.ival > 255 || opts[0].val.ival < 0 ? 3 : opts[0].val.ival;
45
for (j=0; j<pn_image_data->height; j++)
46
for (i=0; i<pn_image_data->width; i++)
47
pn_image_data->surface[0][PN_IMG_INDEX (i, j)] =
48
CAPLO (pn_image_data->surface[0][PN_IMG_INDEX (i, j)]
52
struct pn_actuator_desc builtin_general_fade =
54
"general_fade", "Fade-out", "Decreases the color index of each pixel",
56
NULL, NULL, general_fade_exec
59
/* thanks to feelgood_ICBM @ freenode for this */
60
#define glError() { GLenum err; for(err = glGetError(); err; err = glGetError()) { fprintf(stderr, "glError: %s caught at %s:%u\n", \
61
(GLchar*)gluErrorString(err), __FILE__, __LINE__); } }
63
/* **************** general_blur **************** */
65
general_blur_exec (const struct pn_actuator_option *opts,
70
glGenTextures(1, &texture_id);
71
glBindTexture(GL_TEXTURE_2D, texture_id);
75
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 128, 128, 0, GL_RGBA, GL_BYTE, NULL);
79
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, -1, -1, 1, 1, 0);
83
glBindTexture(GL_TEXTURE_2D, 0);
85
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
87
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
88
glBindTexture(GL_TEXTURE_2D, texture_id);
94
glColor4f(1.0f, 1.0f, 1.0f, 0.5f);
102
glBindTexture(GL_TEXTURE_2D, 0);
106
glDeleteTextures(1, &texture_id);
113
struct pn_actuator_desc builtin_general_blur =
115
"general_blur", "Blur", "A simple radial blur",
117
NULL, NULL, general_blur_exec
120
/* **************** general_mosaic **************** */
121
/* FIXME: add a variable radius */
123
static struct pn_actuator_option_desc general_mosaic_opts[] =
125
{ "radius", "The pixel radius that should be used for the effect.",
126
OPT_TYPE_INT, { ival: 6 } },
131
general_mosaic_exec (const struct pn_actuator_option *opts,
135
register guchar *srcptr = pn_image_data->surface[0];
136
register guchar *destptr = pn_image_data->surface[1];
138
int radius = opts[0].val.ival > 255 || opts[0].val.ival < 0 ? 6 : opts[0].val.ival;
140
for (j=0; j<pn_image_data->height; j += radius)
141
for (i=0; i<pn_image_data->width; i += radius)
146
/* find the brightest colour */
147
for (jj = 0; jj < radius && (j + jj < pn_image_data->height); jj++)
148
for (ii = 0; ii < radius && (i + ii < pn_image_data->width); ii++)
150
guchar val = srcptr[PN_IMG_INDEX(i + ii, j + jj)];
156
for (jj = 0; jj < radius && (j + jj < pn_image_data->height); jj++)
157
for (ii = 0; ii < radius && (i + ii < pn_image_data->width); ii++)
159
destptr[PN_IMG_INDEX(i + ii, j + jj)] = bval;
166
struct pn_actuator_desc builtin_general_mosaic =
168
"general_mosaic", "Mosaic", "A simple mosaic effect.",
169
0, general_mosaic_opts,
170
NULL, NULL, general_mosaic_exec
173
/* **************** general_clear **************** */
175
general_clear_exec (const struct pn_actuator_option *opts,
178
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
181
struct pn_actuator_desc builtin_general_clear =
183
"general_clear", "Clear Surface", "Clears the surface.",
185
NULL, NULL, general_clear_exec
188
/* **************** general_setalpha **************** */
189
static struct pn_actuator_option_desc general_setalpha_opts[] =
191
{ "blend_colour", "The colour which should be used for blending.",
192
OPT_TYPE_COLOR, { cval: {255, 255, 255} } },
193
{ "alpha", "The alpha value.",
194
OPT_TYPE_COLOR_INDEX, { ival: 128 } },
199
general_setalpha_exec (const struct pn_actuator_option *opts,
202
GLubyte colour[] = { opts[0].val.cval.r, opts[0].val.cval.g, opts[0].val.cval.b,
206
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
209
struct pn_actuator_desc builtin_general_setalpha =
211
"general_setalpha", "Change Blend Setting", "Changes the blending setting (alpha transparency mask).",
212
0, general_setalpha_opts,
213
NULL, NULL, general_setalpha_exec
216
/* **************** general_noop **************** */
218
general_noop_exec (const struct pn_actuator_option *opts,
224
struct pn_actuator_desc builtin_general_noop =
226
"general_noop", "Do Nothing", "Does absolutely nothing.",
228
NULL, NULL, general_noop_exec
231
/* **************** general_invert **************** */
233
general_invert_exec (const struct pn_actuator_option *opts,
238
for (j=0; j < pn_image_data->height; j++)
239
for (i=0; i < pn_image_data->width; i++)
240
pn_image_data->surface[0][PN_IMG_INDEX (i, j)] =
241
255 - pn_image_data->surface[0][PN_IMG_INDEX (i, j)];
244
struct pn_actuator_desc builtin_general_invert =
246
"general_invert", "Value Invert", "Performs a value invert.",
248
NULL, NULL, general_invert_exec
251
/* **************** general_replace **************** */
252
static struct pn_actuator_option_desc general_replace_opts[] =
254
{ "start", "The beginning colour value that should be replaced by the value of out.",
255
OPT_TYPE_INT, { ival: 250 } },
256
{ "end", "The ending colour value that should be replaced by the value of out.",
257
OPT_TYPE_INT, { ival: 255 } },
258
{ "out", "The colour value that in is replaced with.",
259
OPT_TYPE_INT, { ival: 0 } },
264
general_replace_exec (const struct pn_actuator_option *opts,
269
guchar begin = opts[0].val.ival > 255 || opts[0].val.ival < 0 ? 250 : opts[0].val.ival;
270
guchar end = opts[1].val.ival > 255 || opts[1].val.ival < 0 ? 255 : opts[1].val.ival;
271
guchar out = opts[2].val.ival > 255 || opts[2].val.ival < 0 ? 0 : opts[2].val.ival;
273
for (j=0; j < pn_image_data->height; j++)
274
for (i=0; i < pn_image_data->width; i++)
276
val = pn_image_data->surface[0][PN_IMG_INDEX (i, j)];
277
if (val >= begin && val <= end)
278
pn_image_data->surface[0][PN_IMG_INDEX (i, j)] = out;
282
struct pn_actuator_desc builtin_general_replace =
284
"general_replace", "Value Replace", "Performs a value replace on a range of values.",
285
0, general_replace_opts,
286
NULL, NULL, general_replace_exec
289
/* **************** general_swap **************** */
291
general_swap_exec (const struct pn_actuator_option *opts,
297
struct pn_actuator_desc builtin_general_swap =
299
"general_swap", "Swap Surface", "Swaps the surface.",
301
NULL, NULL, general_swap_exec
304
/* **************** general_copy **************** */
306
general_copy_exec (const struct pn_actuator_option *opts,
309
memcpy(pn_image_data->surface[1], pn_image_data->surface[0],
310
(pn_image_data->width * pn_image_data->height));
313
struct pn_actuator_desc builtin_general_copy =
315
"general_copy", "Copy Surface", "Copies the surface to the other surface.",
317
NULL, NULL, general_copy_exec
320
/* **************** general_flip **************** */
321
static struct pn_actuator_option_desc general_flip_opts[] =
323
{ "direction", "Negative is horizontal, positive is vertical.",
324
OPT_TYPE_INT, { ival: -1 } },
329
general_flip_exec (const struct pn_actuator_option *opts,
334
if (opts[0].val.ival < 0)
336
for (y = 0; y < pn_image_data->height; y++)
337
for (x = 0; x < pn_image_data->width; x++)
339
pn_image_data->surface[1][PN_IMG_INDEX(pn_image_data->width - x, y)] =
340
pn_image_data->surface[0][PN_IMG_INDEX(x, y)];
345
for (y = 0; y < pn_image_data->height; y++)
346
for (x = 0; x < pn_image_data->width; x++)
348
pn_image_data->surface[1][PN_IMG_INDEX(x, pn_image_data->height - y)] =
349
pn_image_data->surface[0][PN_IMG_INDEX(x, y)];
356
struct pn_actuator_desc builtin_general_flip =
358
"general_flip", "Flip Surface", "Flips the surface.",
359
0, general_flip_opts,
360
NULL, NULL, general_flip_exec
363
/* ***************** general_evaluate ***************** */
365
static struct pn_actuator_option_desc general_evaluate_opts[] =
367
{ "init_script", "Script to run on start.", OPT_TYPE_STRING, {sval: "global_reg0 = 27;"} },
368
{ "frame_script", "Script to run.", OPT_TYPE_STRING, {sval: "global_reg0 = global_reg0 + 1;"} },
372
struct pn_evaluate_ctx
374
expression_t *expr_on_init, *expr_on_frame;
380
general_evaluate_init(gpointer *data)
382
*data = g_new0(struct pn_evaluate_ctx, 1);
384
((struct pn_evaluate_ctx *)*data)->reset = TRUE;
388
general_evaluate_cleanup(gpointer op_data)
390
struct pn_evaluate_ctx *data = (struct pn_evaluate_ctx *) op_data;
392
g_return_if_fail(data != NULL);
394
if (data->expr_on_init)
395
expr_free(data->expr_on_init);
397
if (data->expr_on_frame)
398
expr_free(data->expr_on_frame);
401
dict_free(data->dict);
408
general_evaluate_exec(const struct pn_actuator_option *opts,
411
struct pn_evaluate_ctx *data = (struct pn_evaluate_ctx *) op_data;
416
dict_free(data->dict);
418
data->dict = dict_new();
420
if (opts[0].val.sval != NULL);
421
data->expr_on_init = expr_compile_string(opts[0].val.sval, data->dict);
423
if (opts[1].val.sval != NULL);
424
data->expr_on_frame = expr_compile_string(opts[1].val.sval, data->dict);
426
if (data->expr_on_init != NULL)
427
expr_execute(data->expr_on_init, data->dict);
432
if (data->expr_on_frame != NULL)
433
expr_execute(data->expr_on_frame, data->dict);
436
struct pn_actuator_desc builtin_general_evaluate =
438
"general_evaluate", "Evalulate VM Code",
439
"Evaluates arbitrary VM code. Does not draw anything.",
440
0, general_evaluate_opts,
441
general_evaluate_init, general_evaluate_cleanup, general_evaluate_exec