winamp/Src/Plugins/Visualization/vis_avs/r_trans.cpp

982 lines
31 KiB
C++
Raw Normal View History

2024-09-24 14:54:57 +02:00
/*
LICENSE
-------
Copyright 2005 Nullsoft, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of Nullsoft nor the names of its contributors may be used to
endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// alphachannel safe 11/21/99
#define M_PI 3.14159265358979323846
#include <windows.h>
#include <commctrl.h>
#include "r_defs.h"
#include "resource.h"
#include "timing.h"
#include "avs_eelif.h"
#include "../Agave/Language/api_language.h"
#include "../nu/AutoWide.h"
#include <math.h>
#ifndef LASER
#define C_THISCLASS C_TransTabClass
#define MOD_NAME "Trans / Movement"
#define REFFECT_MIN 3
#define REFFECT_MAX 23
typedef struct {
// int index; // Just here for descriptive purposes, makes it easy to match stuff up.
int list_desc; // The string to show in the listbox.
char *eval_desc; // The optional string to display in the evaluation editor.
char uses_eval; // If this is true, the preset engages the eval library and there is NULL in the radial_effects array for its entry
char uses_rect; // This value sets the checkbox for rectangular calculation
} Description;
static Description descriptions[]=
{
{/* 0,*/ IDS_NONE, "", 0, 0},
{/* 1,*/ IDS_SLIGHT_FUZZIFY, "", 0, 0},
{/* 2,*/ IDS_SHIFT_ROTATE_LEFT, "x=x+1/32; // use wrap for this one", 0, 1},
{/* 3,*/ IDS_BIG_SWIRL_OUT, "r = r + (0.1 - (0.2 * d));\r\nd = d * 0.96;", 0, 0},
{/* 4,*/ IDS_MEDIUM_SWIRL, "d = d * (0.99 * (1.0 - sin(r-$PI*0.5) / 32.0));\r\nr = r + (0.03 * sin(d * $PI * 4));", 0, 0},
{/* 5,*/ IDS_SUNBURSTER, "d = d * (0.94 + (cos((r-$PI*0.5) * 32.0) * 0.06));", 0, 0},
{/* 6,*/ IDS_SWIRL_TO_CENTER, "d = d * (1.01 + (cos((r-$PI*0.5) * 4) * 0.04));\r\nr = r + (0.03 * sin(d * $PI * 4));", 0, 0},
{/* 7,*/ IDS_BLOCKY_PARTIAL_OUT, "", 0, 0},
{/* 8,*/ IDS_SWIRLING_AROUND_BOTH_WAYS, "r = r + (0.1 * sin(d * $PI * 5));", 0, 0},
{/* 9,*/ IDS_BUBBLING_OUTWARD, "t = sin(d * $PI);\r\nd = d - (8*t*t*t*t*t)/sqrt((sw*sw+sh*sh)/4);", 0, 0},
{/*10,*/ IDS_BUBBLING_OUTWARD_WITH_SWIRL, "t = sin(d * $PI);\r\nd = d - (8*t*t*t*t*t)/sqrt((sw*sw+sh*sh)/4);\r\nt=cos(d*$PI/2.0);\r\nr= r + 0.1*t*t*t;", 0, 0},
{/*11,*/ IDS_5_POINTED_DISTRO, "d = d * (0.95 + (cos(((r-$PI*0.5) * 5.0) - ($PI / 2.50)) * 0.03));", 0, 0},
{/*12,*/ IDS_TUNNELING, "r = r + 0.04;\r\nd = d * (0.96 + cos(d * $PI) * 0.05);", 0, 0},
{/*13,*/ IDS_BLEEDIN, "t = cos(d * $PI);\r\nr = r + (0.07 * t);\r\nd = d * (0.98 + t * 0.10);", 0, 0},
{/*14,*/ IDS_SHIFTED_BIG_SWIRL_OUT, "// this is a very bad approximation in script. fixme.\r\nd=sqrt(x*x+y*y); r=atan2(y,x);\r\nr=r+0.1-0.2*d; d=d*0.96;\r\nx=cos(r)*d + 8/128; y=sin(r)*d;", 0, 1},
{/*15,*/ IDS_PSYCHOTIC_BEAMING_OUTWARD, "d = 0.15", 0, 0},
{/*16,*/ IDS_COSINE_RADIAL_3_WAY, "r = cos(r * 3)", 0, 0},
{/*17,*/ IDS_SPINNY_TUBE, "d = d * (1 - ((d - .35) * .5));\r\nr = r + .1;", 0, 0},
{/*18,*/ IDS_RADIAL_SWIRLIES, "d = d * (1 - (sin((r-$PI*0.5) * 7) * .03));\r\nr = r + (cos(d * 12) * .03);", 1, 0},
{/*19,*/ IDS_SWILL, "d = d * (1 - (sin((r - $PI*0.5) * 12) * .05));\r\nr = r + (cos(d * 18) * .05);\r\nd = d * (1-((d - .4) * .03));\r\nr = r + ((d - .4) * .13)", 1, 0},
{/*20,*/ IDS_GRIDLEY, "x = x + (cos(y * 18) * .02);\r\ny = y + (sin(x * 14) * .03);", 1, 1},
{/*21,*/ IDS_GRAPEVINE, "x = x + (cos(abs(y-.5) * 8) * .02);\r\ny = y + (sin(abs(x-.5) * 8) * .05);\r\nx = x * .95;\r\ny = y * .95;", 1, 1},
{/*22,*/ IDS_QUADRANT, "y = y * ( 1 + (sin(r + $PI/2) * .3) );\r\nx = x * ( 1 + (cos(r + $PI/2) * .3) );\r\nx = x * .995;\r\ny = y * .995;", 1, 1},
{/*23,*/ IDS_6_WAY_KALAEIDA, "y = (r*6)/($PI); x = d;", 1, 1},
};
#define MAKE_REFFECT(n,x) void _ref##n(double &r, double &d, double max_d, int &xo, int &yo) { x }
typedef void t_reffect(double &r, double &d, double max_d, int &xo, int &yo);
MAKE_REFFECT(3, r+=0.1-0.2*(d/max_d); d*=0.96;)
MAKE_REFFECT(4, d*=0.99*(1.0-sin(r)/32.0); r+=0.03*sin(d/max_d * M_PI * 4);)
MAKE_REFFECT(5, d*=0.94+(cos(r*32.0)*0.06);)
MAKE_REFFECT(6, d*=1.01+(cos(r*4.0)*0.04); r+=0.03*sin(d/max_d * M_PI * 4);)
MAKE_REFFECT(8, r+=0.1*sin(d/max_d*M_PI*5);)
MAKE_REFFECT(9, double t; t=sin(d/max_d*M_PI); d-=8*t*t*t*t*t; )
MAKE_REFFECT(10,double t; t=sin(d/max_d*M_PI); d-=8*t*t*t*t*t; t=cos((d/max_d)*M_PI/2.0); r+=0.1*t*t*t; )
MAKE_REFFECT(11, d*=0.95+(cos(r*5.0 - M_PI/2.50)*0.03); )
MAKE_REFFECT(12, r+=0.04; d*=0.96+cos(d/max_d*M_PI)*0.05; )
MAKE_REFFECT(13, double t; t=cos(d/max_d*M_PI); r+=0.07*t; d*=0.98+t*0.10; )
MAKE_REFFECT(14, r+=0.1-0.2*(d/max_d); d*=0.96; xo=8; )
MAKE_REFFECT(15, d=max_d*0.15;)
MAKE_REFFECT(16, r=cos(r*3);)
MAKE_REFFECT(17, d*=(1-(((d/max_d)-.35)*.5)); r+=.1;)
static t_reffect *radial_effects[REFFECT_MAX-REFFECT_MIN+1]=
{
_ref3, _ref4, _ref5, _ref6, NULL, _ref8, _ref9, _ref10, _ref11, _ref12, _ref13,
_ref14, _ref15, _ref16, _ref17, NULL/*18*/, NULL/*19*/, NULL/*20*/, NULL/*21*/,
NULL/*22*/, NULL/*23*/,
};
static inline bool effect_uses_eval(int t)
{
bool retval = false;
if ((t >= REFFECT_MIN) && (t <= REFFECT_MAX))
{
if (descriptions[t].uses_eval)
{
retval = true;
}
}
return retval;
}
class C_THISCLASS : public C_RBASE2 {
protected:
public:
C_THISCLASS();
virtual ~C_THISCLASS();
virtual int render(char visdata[2][2][576], int isBeat, int *framebuffer, int *fbout, int w, int h);
virtual int smp_getflags() { return 1; }
virtual int smp_begin(int max_threads, char visdata[2][2][576], int isBeat, int *framebuffer, int *fbout, int w, int h);
virtual void smp_render(int this_thread, int max_threads, char visdata[2][2][576], int isBeat, int *framebuffer, int *fbout, int w, int h);
virtual int smp_finish(char visdata[2][2][576], int isBeat, int *framebuffer, int *fbout, int w, int h); // return value is that of render() for fbstuff etc
virtual char *get_desc() { return MOD_NAME; }
virtual HWND conf(HINSTANCE hInstance, HWND hwndParent);
virtual void load_config(unsigned char *data, int len);
virtual int save_config(unsigned char *data);
int *trans_tab, trans_tab_w, trans_tab_h, trans_tab_subpixel;
int trans_effect;
RString effect_exp;
int effect_exp_ch;
int effect,blend;
int sourcemapped;
int rectangular;
int subpixel;
int wrap;
CRITICAL_SECTION rcs;
};
#define PUT_INT(y) data[pos]=(y)&255; data[pos+1]=(y>>8)&255; data[pos+2]=(y>>16)&255; data[pos+3]=(y>>24)&255
#define GET_INT() (data[pos]|(data[pos+1]<<8)|(data[pos+2]<<16)|(data[pos+3]<<24))
void C_THISCLASS::load_config(unsigned char *data, int len)
{
int pos=0;
if (len-pos >= 4) { effect=GET_INT(); pos+=4; }
if (effect == 32767)
{
if (!memcmp(data+pos,"!rect ",6))
{
pos+=6;
rectangular=1;
}
if (data[pos]==1)
{
pos++;
int l=GET_INT(); pos+=4;
if (l > 0 && len-pos >= l)
{
effect_exp.resize(l);
memcpy(effect_exp.get(), data+pos, l);
pos+=l;
}
else
{
effect_exp.resize(1);
effect_exp.get()[0]=0;
}
}
else if (len-pos >= 256)
{
char buf[257];
int l=256-(rectangular?6:0);
memcpy(buf,data+pos,l);
buf[l]=0;
effect_exp.assign(buf);
pos+=l;
}
}
if (len-pos >= 4) { blend=GET_INT(); pos+=4; }
if (len-pos >= 4) { sourcemapped=GET_INT(); pos+=4; }
if (len-pos >= 4) { rectangular=GET_INT(); pos+=4; }
if (len-pos >= 4) { subpixel=GET_INT(); pos+=4; }
else subpixel=0;
if (len-pos >= 4) { wrap=GET_INT(); pos+=4; }
else wrap=0;
if (!effect && len-pos >= 4)
{
effect=GET_INT(); pos+=4;
}
if (effect != 32767 && effect > REFFECT_MAX || effect < 0)
effect=0;
// Once we know what our _real_ effect value is, if it uses the evaluator, allocate and stuff the string, here.
/*
if (effect_uses_eval(effect))
{
const char *eval_string = descriptions[effect].eval_desc;
int length = strlen(eval_string);
effect_exp.resize(length+1);
strcpy(effect_exp.get(), eval_string);
}
*/
effect_exp_ch=1;
}
int C_THISCLASS::save_config(unsigned char *data)
{
int pos=0;
// the reason this is 15, and not REFFECT_MAX, is because old versions of AVS barf
// if effect is > 15, so we put 0, and at the end put the new value
if (effect > 15 && effect != 32767)
{
PUT_INT(0);
pos += 4;
}
else
{
PUT_INT(effect);
pos+=4;
}
if (effect == 32767)
{
int l=strlen(effect_exp.get())+1;
data[pos++]=1;
PUT_INT(l);
pos+=4;
memcpy(data+pos,effect_exp.get(),strlen(effect_exp.get())+1);
pos+=strlen(effect_exp.get())+1;
}
PUT_INT(blend); pos+=4;
PUT_INT(sourcemapped); pos+=4;
PUT_INT(rectangular); pos+=4;
PUT_INT(subpixel); pos+=4;
PUT_INT(wrap); pos+=4;
// see note on '15' above =)
if (effect > 15 && effect != 32767)
{
PUT_INT(effect);
pos+=4;
}
return pos;
}
C_THISCLASS::C_THISCLASS()
{
InitializeCriticalSection(&rcs);
sourcemapped=0;
trans_tab=NULL;
trans_tab_w=trans_tab_h=0;
effect=1;
trans_effect=0;
blend=0;
effect_exp.assign("");
rectangular=0;
subpixel=1;
wrap=0;
trans_tab_subpixel=0;
effect_exp_ch=1;
}
C_THISCLASS::~C_THISCLASS()
{
if (trans_tab) GlobalFree(trans_tab);
trans_tab=NULL;
trans_tab_w=trans_tab_h=0;
trans_effect=0;
DeleteCriticalSection(&rcs);
}
int C_THISCLASS::smp_begin(int max_threads, char visdata[2][2][576], int isBeat, int *framebuffer, int *fbout, int w, int h)
{
if (!effect) return 0;
if (!trans_tab || trans_tab_w != w || trans_tab_h != h || effect != trans_effect ||
effect_exp_ch)
{
int p;
int *transp,x;
if (trans_tab) GlobalFree(trans_tab);
trans_tab_w=w;
trans_tab_h=h;
trans_tab=(int*)GlobalAlloc(GMEM_FIXED,trans_tab_w*trans_tab_h*sizeof(int));
trans_effect=effect;
trans_tab_subpixel=(subpixel && trans_tab_w*trans_tab_h < (1<<22) &&
((trans_effect >= REFFECT_MIN && trans_effect <= REFFECT_MAX
&& trans_effect != 1 && trans_effect != 2 && trans_effect != 7
)||trans_effect ==32767));
/* generate trans_tab */
transp=trans_tab;
x=w*h;
p=0;
if (trans_effect == 1)
{
while (x--)
{
int r=(p++)+(rand()%3)-1 + ((rand()%3)-1)*w;
*transp++ = min(w*h-1,max(r,0));
}
}
else if (trans_effect == 2)
{
int y=h;
while (y--)
{
int x=w;
int lp=w/64;
while (x--)
{
*transp++ = p+lp++;
if (lp >= w) lp-=w;
}
p+=w;
}
}
else if (trans_effect == 7)
{
int y;
for (y = 0; y < h; y ++)
{
for (x = 0; x < w; x ++)
{
if (x&2 || y&2)
{
*transp++ = x+y*w;
}
else
{
int xp=w/2+(((x&~1)-w/2)*7)/8;
int yp=h/2+(((y&~1)-h/2)*7)/8;
*transp++=xp+yp*w;
}
}
}
}
else if (trans_effect >= REFFECT_MIN && trans_effect <= REFFECT_MAX && !effect_uses_eval(trans_effect))
{
double max_d=sqrt((w*w+h*h)/4.0);
int y;
t_reffect *ref=radial_effects[trans_effect-REFFECT_MIN];
if (ref) for (y = 0; y < h; y ++)
{
for (x = 0; x < w; x ++)
{
double r,d;
double xd,yd;
int ow,oh,xo=0,yo=0;
xd=x-(w/2);
yd=y-(h/2);
d=sqrt(xd*xd+yd*yd);
r=atan2(yd,xd);
ref(r,d,max_d,xo,yo);
double tmp1,tmp2;
tmp1= ((h/2) + sin(r)*d + 0.5) + (yo*h)*(1.0/256.0);
tmp2= ((w/2) + cos(r)*d + 0.5) + (xo*w)*(1.0/256.0);
oh=(int)tmp1;
ow=(int)tmp2;
if (trans_tab_subpixel)
{
int xpartial=(int)(32.0*(tmp2-ow));
int ypartial=(int)(32.0*(tmp1-oh));
if (wrap)
{
ow%=(w-1);
oh%=(h-1);
if (ow<0)ow+=w-1;
if (oh<0)oh+=h-1;
}
else
{
if (ow < 0) { xpartial=0; ow=0; }
if (ow >= w-1) { xpartial=31; ow=w-2; }
if (oh < 0) { ypartial=0; oh=0; }
if (oh >= h-1) {ypartial=31; oh=h-2; }
}
*transp++ = ow+oh*w | (ypartial<<22) | (xpartial<<27);
}
else
{
if (wrap)
{
ow%=(w);
oh%=(h);
if (ow<0)ow+=w;
if (oh<0)oh+=h;
}
else
{
if (ow < 0) ow=0;
if (ow >= w) ow=w-1;
if (oh < 0) oh=0;
if (oh >= h) oh=h-1;
}
*transp++ = ow+oh*w;
}
}
}
}
else if (trans_effect == 32767 || effect_uses_eval(trans_effect))
{
NSEEL_VMCTX AVS_EEL_CONTEXTNAME;
AVS_EEL_INITINST();
double max_d=sqrt((double)(w*w+h*h))/2.0;
double divmax_d=1.0/max_d;
int y;
double *d = registerVar("d");
double *r = registerVar("r");
double *px = registerVar("x");
double *py = registerVar("y");
double *pw = registerVar("sw");
double *ph = registerVar("sh");
NSEEL_CODEHANDLE codehandle=0;
int offs=0;
int is_rect = trans_effect == 32767 ? rectangular : descriptions[trans_effect].uses_rect;
*pw=w;
*ph=h;
EnterCriticalSection(&rcs);
codehandle=compileCode(
trans_effect == 32767 ? effect_exp.get() : descriptions[trans_effect].eval_desc
);
LeaveCriticalSection(&rcs);
if (codehandle)
{
double w2=w/2;
double h2=h/2;
double xsc=1.0/w2,ysc=1.0/h2;
for (y = 0; y < h; y ++)
{
for (x = 0; x < w; x ++)
{
double xd,yd;
int ow,oh;
xd=x-w2;
yd=y-h2;
*px=xd*xsc;
*py=yd*ysc;
*d=sqrt(xd*xd+yd*yd)*divmax_d;
*r=atan2(yd,xd) + M_PI*0.5;
executeCode(codehandle,visdata);
double tmp1,tmp2;
if (!is_rect)
{
*d *= max_d;
*r -= M_PI/2.0;
tmp1=((h/2) + sin(*r)* *d);
tmp2=((w/2) + cos(*r)* *d);
}
else
{
tmp1=((*py+1.0)*h2);
tmp2=((*px+1.0)*w2);
}
if (trans_tab_subpixel)
{
oh=(int) tmp1;
ow=(int) tmp2;
int xpartial=(int)(32.0*(tmp2-ow));
int ypartial=(int)(32.0*(tmp1-oh));
if (wrap)
{
ow%=(w-1);
oh%=(h-1);
if (ow<0)ow+=w-1;
if (oh<0)oh+=h-1;
}
else
{
if (ow < 0) { xpartial=0; ow=0; }
if (ow >= w-1) { xpartial=31; ow=w-2; }
if (oh < 0) { ypartial=0; oh=0; }
if (oh >= h-1) {ypartial=31; oh=h-2; }
}
*transp++ = ow+oh*w | (ypartial<<22) | (xpartial<<27);
}
else
{
tmp1+=0.5;
tmp2+=0.5;
oh=(int) tmp1;
ow=(int) tmp2;
if (wrap)
{
ow%=(w);
oh%=(h);
if (ow<0)ow+=w;
if (oh<0)oh+=h;
}
else
{
if (ow < 0) ow=0;
if (ow >= w) ow=w-1;
if (oh < 0) oh=0;
if (oh >= h) oh=h-1;
}
*transp++ = ow+oh*w;
}
}
}
}
else
{
transp=trans_tab;
trans_tab_subpixel=0;
for (x = 0; x < w*h; x ++)
*transp++=x;
}
freeCode(codehandle);
AVS_EEL_QUITINST();
}
effect_exp_ch=0;
}
if (!(isBeat & 0x80000000))
{
if ((sourcemapped&2)&&isBeat) sourcemapped^=1;
if (sourcemapped&1)
{
if (!blend) memset(fbout,0,w*h*sizeof(int));
else memcpy(fbout,framebuffer,w*h*sizeof(int));
}
}
return max_threads;
}
void C_THISCLASS::smp_render(int this_thread, int max_threads, char visdata[2][2][576], int isBeat, int *framebuffer, int *fbout, int w, int h)
{
if (!effect) return;
#define OFFSET_MASK ((1<<22)-1)
unsigned int *inp = (unsigned int *) framebuffer;
unsigned int *outp;
int *transp, x;
if (max_threads < 1) max_threads=1;
int start_l = ( this_thread * h ) / max_threads;
int end_l;
if (this_thread >= max_threads - 1) end_l = h;
else end_l = ( (this_thread+1) * h ) / max_threads;
int outh=end_l-start_l;
if (outh<1) return;
int skip_pix=start_l*w;
transp=trans_tab;
outp = (unsigned int *) fbout;
x=(w*outh)/4;
if (sourcemapped&1)
{
inp += skip_pix;
transp += skip_pix;
if (trans_tab_subpixel)
{
timingEnter(3);
while (x--)
{
fbout[transp[0]&OFFSET_MASK]=BLEND_MAX(inp[0],fbout[transp[0]&OFFSET_MASK]);
fbout[transp[1]&OFFSET_MASK]=BLEND_MAX(inp[1],fbout[transp[1]&OFFSET_MASK]);
fbout[transp[2]&OFFSET_MASK]=BLEND_MAX(inp[2],fbout[transp[2]&OFFSET_MASK]);
fbout[transp[3]&OFFSET_MASK]=BLEND_MAX(inp[3],fbout[transp[3]&OFFSET_MASK]);
inp+=4;
transp+=4;
}
timingLeave(3);
x = (w*outh)&3;
if (x>0) while (x--)
{
fbout[transp[0]&OFFSET_MASK]=BLEND_MAX(inp++[0],fbout[transp[0]&OFFSET_MASK]);
transp++;
}
}
else
{
{
timingEnter(3);
while (x--)
{
fbout[transp[0]]=BLEND_MAX(inp[0],fbout[transp[0]]);
fbout[transp[1]]=BLEND_MAX(inp[1],fbout[transp[1]]);
fbout[transp[2]]=BLEND_MAX(inp[2],fbout[transp[2]]);
fbout[transp[3]]=BLEND_MAX(inp[3],fbout[transp[3]]);
inp+=4;
transp+=4;
}
timingLeave(3);
x = (w*outh)&3;
if (x>0) while (x--)
{
fbout[transp[0]]=BLEND_MAX(inp++[0],fbout[transp[0]]);
transp++;
}
}
}
if (blend)
{
framebuffer += skip_pix;
fbout += skip_pix;
x=(w*outh)/4;
while (x--)
{
fbout[0]=BLEND_AVG(fbout[0],framebuffer[0]);
fbout[1]=BLEND_AVG(fbout[1],framebuffer[1]);
fbout[2]=BLEND_AVG(fbout[2],framebuffer[2]);
fbout[3]=BLEND_AVG(fbout[3],framebuffer[3]);
fbout+=4;
framebuffer+=4;
}
x=(w*outh)&3;
while (x--)
{
fbout[0]=BLEND_AVG(fbout[0],framebuffer[0]);
fbout++;
framebuffer++;
}
}
}
else
{
inp += skip_pix;
outp += skip_pix;
transp += skip_pix;
if (trans_tab_subpixel&&blend)
{
while (x--)
{
int offs=transp[0]&OFFSET_MASK;
outp[0]=BLEND_AVG(inp[0],BLEND4((unsigned int *)framebuffer+offs,w,((transp[0]>>24)&(31<<3)),((transp[0]>>19)&(31<<3))));
offs=transp[1]&OFFSET_MASK;
outp[1]=BLEND_AVG(inp[1],BLEND4((unsigned int *)framebuffer+offs,w,((transp[1]>>24)&(31<<3)),((transp[1]>>19)&(31<<3))));
offs=transp[2]&OFFSET_MASK;
outp[2]=BLEND_AVG(inp[2],BLEND4((unsigned int *)framebuffer+offs,w,((transp[2]>>24)&(31<<3)),((transp[2]>>19)&(31<<3))));
offs=transp[3]&OFFSET_MASK;
outp[3]=BLEND_AVG(inp[3],BLEND4((unsigned int *)framebuffer+offs,w,((transp[3]>>24)&(31<<3)),((transp[3]>>19)&(31<<3))));
transp+=4;
outp+=4;
inp+=4;
}
x=(w*outh)&3;
while (x--)
{
int offs=transp[0]&OFFSET_MASK;
outp++[0]=BLEND_AVG(inp[0],BLEND4((unsigned int *)framebuffer+offs,w,((transp[0]>>24)&(31<<3)),((transp[0]>>19)&(31<<3))));
transp++;
inp++;
}
#ifndef NO_MMX
__asm emms;
#endif
}
else if (trans_tab_subpixel)
{
while (x--)
{
int offs=transp[0]&OFFSET_MASK;
outp[0]=BLEND4((unsigned int *)framebuffer+offs,w,((transp[0]>>24)&(31<<3)),((transp[0]>>19)&(31<<3)));
offs=transp[1]&OFFSET_MASK;
outp[1]=BLEND4((unsigned int *)framebuffer+offs,w,((transp[1]>>24)&(31<<3)),((transp[1]>>19)&(31<<3)));
offs=transp[2]&OFFSET_MASK;
outp[2]=BLEND4((unsigned int *)framebuffer+offs,w,((transp[2]>>24)&(31<<3)),((transp[2]>>19)&(31<<3)));
offs=transp[3]&OFFSET_MASK;
outp[3]=BLEND4((unsigned int *)framebuffer+offs,w,((transp[3]>>24)&(31<<3)),((transp[3]>>19)&(31<<3)));
transp+=4;
outp+=4;
}
x=(w*outh)&3;
while (x--)
{
int offs=transp[0]&OFFSET_MASK;
outp++[0]=BLEND4((unsigned int *)framebuffer+offs,w,((transp[0]>>24)&(31<<3)),((transp[0]>>19)&(31<<3)));
transp++;
}
#ifndef NO_MMX
__asm emms;
#endif
}
else if (blend)
{
timingEnter(3);
while (x--)
{
outp[0]=BLEND_AVG(inp[0],framebuffer[transp[0]]);
outp[1]=BLEND_AVG(inp[1],framebuffer[transp[1]]);
outp[2]=BLEND_AVG(inp[2],framebuffer[transp[2]]);
outp[3]=BLEND_AVG(inp[3],framebuffer[transp[3]]);
outp+=4;
inp+=4;
transp+=4;
}
timingLeave(3);
x = (w*outh)&3;
if (x>0) while (x--)
{
outp++[0]=BLEND_AVG(inp++[0],framebuffer[transp++[0]]);
}
}
else
{
timingEnter(4);
while (x--)
{
outp[0]=framebuffer[transp[0]];
outp[1]=framebuffer[transp[1]];
outp[2]=framebuffer[transp[2]];
outp[3]=framebuffer[transp[3]];
outp+=4;
transp+=4;
}
timingLeave(4);
x = (w*outh)&3;
if (x>0) while (x--)
{
outp++[0]=framebuffer[transp++[0]];
}
}
}
}
int C_THISCLASS::smp_finish(char visdata[2][2][576], int isBeat, int *framebuffer, int *fbout, int w, int h) // return value is that of render() for fbstuff etc
{
return !!effect;
}
int C_THISCLASS::render(char visdata[2][2][576], int isBeat, int *framebuffer, int *fbout, int w, int h)
{
smp_begin(1,visdata,isBeat,framebuffer,fbout,w,h);
if (isBeat & 0x80000000) return 0;
smp_render(0,1,visdata,isBeat,framebuffer,fbout,w,h);
return smp_finish(visdata,isBeat,framebuffer,fbout,w,h);
}
C_RBASE *R_Trans(char *desc)
{
if (desc) { strcpy(desc,MOD_NAME); return NULL; }
return (C_RBASE *) new C_THISCLASS();
}
static C_THISCLASS *g_this;
static BOOL CALLBACK g_DlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
{
static int isstart;
switch (uMsg)
{
case WM_INITDIALOG:
{
int x;
for (x = 0; x < sizeof(descriptions)/sizeof(descriptions[0]); x ++)
{
SendDlgItemMessage( hwndDlg, IDC_LIST1, LB_ADDSTRING, 0, (LPARAM)(const wchar_t *)AutoWide( WASABI_API_LNGSTRING( descriptions[ x ].list_desc ), CP_UTF8 ) );
}
isstart=1;
SetDlgItemText(hwndDlg,IDC_EDIT1,g_this->effect_exp.get());
// After we set whatever value into the edit box, that's the new saved value (ie: don't change the save format)
isstart=0;
if (g_this->blend)
CheckDlgButton(hwndDlg,IDC_CHECK1,BST_CHECKED);
if (g_this->subpixel)
CheckDlgButton(hwndDlg,IDC_CHECK4,BST_CHECKED);
if (g_this->wrap)
CheckDlgButton(hwndDlg,IDC_WRAP,BST_CHECKED);
if (g_this->rectangular)
CheckDlgButton(hwndDlg,IDC_CHECK3,BST_CHECKED);
if (g_this->sourcemapped&2)
CheckDlgButton(hwndDlg,IDC_CHECK2,BST_INDETERMINATE);
else if (g_this->sourcemapped&1)
CheckDlgButton(hwndDlg,IDC_CHECK2,BST_CHECKED);
SendDlgItemMessage( hwndDlg, IDC_LIST1, LB_ADDSTRING, 0, (LPARAM)(const wchar_t *)AutoWide( WASABI_API_LNGSTRING( IDS_USER_DEFINED ), CP_UTF8 ) );
SendDlgItemMessage(hwndDlg,IDC_LIST1,LB_SETCURSEL,(g_this->effect==32767)?sizeof(descriptions)/sizeof(descriptions[0]):g_this->effect,0);
if (g_this->effect == 32767)
{
EnableWindow(GetDlgItem(hwndDlg,IDC_EDIT1),1);
EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK3),1);
EnableWindow(GetDlgItem(hwndDlg,IDC_LABEL1),1);
}
else if (g_this->effect >= 0 && g_this->effect <= REFFECT_MAX)
{
if (strlen(descriptions[g_this->effect].eval_desc) > 0)
{
SetDlgItemTextA(hwndDlg,IDC_EDIT1,descriptions[g_this->effect].eval_desc);
CheckDlgButton(hwndDlg,IDC_CHECK3,descriptions[g_this->effect].uses_rect?BST_CHECKED:0);
EnableWindow(GetDlgItem(hwndDlg,IDC_EDIT1),1);
EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK3),1);
EnableWindow(GetDlgItem(hwndDlg,IDC_LABEL1),1);
}
else
{
EnableWindow(GetDlgItem(hwndDlg,IDC_EDIT1),0);
EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK3),0);
EnableWindow(GetDlgItem(hwndDlg,IDC_LABEL1),0);
}
}
else
{
EnableWindow(GetDlgItem(hwndDlg,IDC_EDIT1),0);
EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK3),0);
EnableWindow(GetDlgItem(hwndDlg,IDC_LABEL1),0);
}
}
return 1;
case WM_TIMER:
if (wParam == 1)
{
KillTimer(hwndDlg,1);
EnterCriticalSection(&g_this->rcs);
g_this->effect=32767;
g_this->effect_exp.get_from_dlgitem(hwndDlg,IDC_EDIT1);
g_this->effect_exp_ch=1;
LeaveCriticalSection(&g_this->rcs);
}
return 0;
case WM_COMMAND:
if (LOWORD(wParam) == IDC_EDIT1 && HIWORD(wParam) == EN_CHANGE)
{
KillTimer(hwndDlg,1);
if (!isstart) SetTimer(hwndDlg,1,1000,NULL);
// If someone edits the editwnd, force the "(user defined)" to be the new selection.
if (SendDlgItemMessageA(hwndDlg,IDC_LIST1,LB_GETCURSEL,0,0) != sizeof(descriptions)/sizeof(descriptions[0]))
{
g_this->rectangular=IsDlgButtonChecked(hwndDlg,IDC_CHECK3)?1:0;
SendDlgItemMessageA(hwndDlg,IDC_LIST1,LB_SETCURSEL,sizeof(descriptions)/sizeof(descriptions[0]),0);
}
}
if (LOWORD(wParam)==IDC_LIST1 && HIWORD(wParam)==LBN_SELCHANGE)
{
int t;
t=SendDlgItemMessageA(hwndDlg,IDC_LIST1,LB_GETCURSEL,0,0);
if (t == sizeof(descriptions)/sizeof(descriptions[0]))
{
g_this->effect=32767;
EnableWindow(GetDlgItem(hwndDlg,IDC_EDIT1),1);
EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK3),1);
EnableWindow(GetDlgItem(hwndDlg,IDC_LABEL1),1);
SetDlgItemText(hwndDlg,IDC_EDIT1,g_this->effect_exp.get());
CheckDlgButton(hwndDlg,IDC_CHECK3,g_this->rectangular);
// always reinit =)
{
EnterCriticalSection(&g_this->rcs);
g_this->effect_exp.get_from_dlgitem(hwndDlg,IDC_EDIT1);
g_this->effect_exp_ch=1;
LeaveCriticalSection(&g_this->rcs);
}
}
else
{
g_this->effect=t;
// If there is a string to stuff in the eval box,
if (strlen(descriptions[t].eval_desc) > 0)
{
// save the value to be able to restore it later
// stuff it and make sure the boxes are editable
SetDlgItemText(hwndDlg,IDC_EDIT1,descriptions[t].eval_desc);
EnableWindow(GetDlgItem(hwndDlg,IDC_EDIT1),1);
EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK3),1);
EnableWindow(GetDlgItem(hwndDlg,IDC_LABEL1),1);
CheckDlgButton(hwndDlg,IDC_CHECK3,descriptions[t].uses_rect?BST_CHECKED:0);
}
else
{
// otherwise, they're not editable.
CheckDlgButton(hwndDlg,IDC_CHECK3,g_this->rectangular?BST_CHECKED:0);
SetDlgItemText(hwndDlg,IDC_EDIT1,"");
EnableWindow(GetDlgItem(hwndDlg,IDC_EDIT1),0);
EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK3),0);
EnableWindow(GetDlgItem(hwndDlg,IDC_LABEL1),0);
}
}
}
if (LOWORD(wParam)==IDC_CHECK1)
{
g_this->blend=IsDlgButtonChecked(hwndDlg,IDC_CHECK1)?1:0;
}
if (LOWORD(wParam)==IDC_CHECK4)
{
g_this->subpixel=IsDlgButtonChecked(hwndDlg,IDC_CHECK4)?1:0;
g_this->effect_exp_ch=1;
}
if (LOWORD(wParam)==IDC_WRAP)
{
g_this->wrap=IsDlgButtonChecked(hwndDlg,IDC_WRAP)?1:0;
g_this->effect_exp_ch=1;
}
if (LOWORD(wParam)==IDC_CHECK2)
{
int a=IsDlgButtonChecked(hwndDlg,IDC_CHECK2);
if (a == BST_INDETERMINATE)
g_this->sourcemapped=2;
else if (a == BST_CHECKED)
g_this->sourcemapped=1;
else
g_this->sourcemapped=0;
}
if (LOWORD(wParam) == IDC_CHECK3)
{
g_this->rectangular=IsDlgButtonChecked(hwndDlg,IDC_CHECK3)?1:0;
if (SendDlgItemMessageA(hwndDlg,IDC_LIST1,LB_GETCURSEL,0,0) != sizeof(descriptions)/sizeof(descriptions[0]))
{
EnterCriticalSection(&g_this->rcs);
g_this->effect=32767;
g_this->effect_exp.get_from_dlgitem(hwndDlg,IDC_EDIT1);
g_this->effect_exp_ch=1;
LeaveCriticalSection(&g_this->rcs);
SendDlgItemMessageA(hwndDlg,IDC_LIST1,LB_SETCURSEL,sizeof(descriptions)/sizeof(descriptions[0]),0);
}
else
g_this->effect_exp_ch=1;
}
if (LOWORD(wParam) == IDC_BUTTON2)
{
/*
char text[4096];
WASABI_API_LNGSTRING_BUF(IDS_MOVEMENT,text,4096);
int titlelen = lstrlen(text)+1;
lstrcpyn(text+titlelen,GetTextResource(IDR_MOVEMENT),4095-titlelen);
*/
char *text="Movement\0"
"Movement help:\r\n"
"To use the custom table, modify r,d,x or y.\r\n"
"Rect coords: x,y are in (-1..1) . Otherwise: d is (0..1) and r is (0..2PI).\r\n"
"You can also access 'sw' and 'sh' for screen dimensions in pixels (might be useful)\r\n"
;
compilerfunctionlist(hwndDlg,text);
}
return 0;
return 0;
}
return 0;
}
HWND C_THISCLASS::conf(HINSTANCE hInstance, HWND hwndParent)
{
g_this = this;
return WASABI_API_CREATEDIALOG(IDD_CFG_TRANS,hwndParent,g_DlgProc);
}
#else
C_RBASE *R_Trans(char *desc){return NULL; }
#endif