r_trans.cpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982
  1. /*
  2. LICENSE
  3. -------
  4. Copyright 2005 Nullsoft, Inc.
  5. All rights reserved.
  6. Redistribution and use in source and binary forms, with or without modification,
  7. are permitted provided that the following conditions are met:
  8. * Redistributions of source code must retain the above copyright notice,
  9. this list of conditions and the following disclaimer.
  10. * Redistributions in binary form must reproduce the above copyright notice,
  11. this list of conditions and the following disclaimer in the documentation
  12. and/or other materials provided with the distribution.
  13. * Neither the name of Nullsoft nor the names of its contributors may be used to
  14. endorse or promote products derived from this software without specific prior written permission.
  15. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
  16. IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  17. FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  18. CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  19. DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  20. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  21. IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  22. OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. */
  24. // alphachannel safe 11/21/99
  25. #define M_PI 3.14159265358979323846
  26. #include <windows.h>
  27. #include <commctrl.h>
  28. #include "r_defs.h"
  29. #include "resource.h"
  30. #include "timing.h"
  31. #include "avs_eelif.h"
  32. #include "../Agave/Language/api_language.h"
  33. #include "../nu/AutoWide.h"
  34. #include <math.h>
  35. #ifndef LASER
  36. #define C_THISCLASS C_TransTabClass
  37. #define MOD_NAME "Trans / Movement"
  38. #define REFFECT_MIN 3
  39. #define REFFECT_MAX 23
  40. typedef struct {
  41. // int index; // Just here for descriptive purposes, makes it easy to match stuff up.
  42. int list_desc; // The string to show in the listbox.
  43. char *eval_desc; // The optional string to display in the evaluation editor.
  44. 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
  45. char uses_rect; // This value sets the checkbox for rectangular calculation
  46. } Description;
  47. static Description descriptions[]=
  48. {
  49. {/* 0,*/ IDS_NONE, "", 0, 0},
  50. {/* 1,*/ IDS_SLIGHT_FUZZIFY, "", 0, 0},
  51. {/* 2,*/ IDS_SHIFT_ROTATE_LEFT, "x=x+1/32; // use wrap for this one", 0, 1},
  52. {/* 3,*/ IDS_BIG_SWIRL_OUT, "r = r + (0.1 - (0.2 * d));\r\nd = d * 0.96;", 0, 0},
  53. {/* 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},
  54. {/* 5,*/ IDS_SUNBURSTER, "d = d * (0.94 + (cos((r-$PI*0.5) * 32.0) * 0.06));", 0, 0},
  55. {/* 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},
  56. {/* 7,*/ IDS_BLOCKY_PARTIAL_OUT, "", 0, 0},
  57. {/* 8,*/ IDS_SWIRLING_AROUND_BOTH_WAYS, "r = r + (0.1 * sin(d * $PI * 5));", 0, 0},
  58. {/* 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},
  59. {/*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},
  60. {/*11,*/ IDS_5_POINTED_DISTRO, "d = d * (0.95 + (cos(((r-$PI*0.5) * 5.0) - ($PI / 2.50)) * 0.03));", 0, 0},
  61. {/*12,*/ IDS_TUNNELING, "r = r + 0.04;\r\nd = d * (0.96 + cos(d * $PI) * 0.05);", 0, 0},
  62. {/*13,*/ IDS_BLEEDIN, "t = cos(d * $PI);\r\nr = r + (0.07 * t);\r\nd = d * (0.98 + t * 0.10);", 0, 0},
  63. {/*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},
  64. {/*15,*/ IDS_PSYCHOTIC_BEAMING_OUTWARD, "d = 0.15", 0, 0},
  65. {/*16,*/ IDS_COSINE_RADIAL_3_WAY, "r = cos(r * 3)", 0, 0},
  66. {/*17,*/ IDS_SPINNY_TUBE, "d = d * (1 - ((d - .35) * .5));\r\nr = r + .1;", 0, 0},
  67. {/*18,*/ IDS_RADIAL_SWIRLIES, "d = d * (1 - (sin((r-$PI*0.5) * 7) * .03));\r\nr = r + (cos(d * 12) * .03);", 1, 0},
  68. {/*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},
  69. {/*20,*/ IDS_GRIDLEY, "x = x + (cos(y * 18) * .02);\r\ny = y + (sin(x * 14) * .03);", 1, 1},
  70. {/*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},
  71. {/*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},
  72. {/*23,*/ IDS_6_WAY_KALAEIDA, "y = (r*6)/($PI); x = d;", 1, 1},
  73. };
  74. #define MAKE_REFFECT(n,x) void _ref##n(double &r, double &d, double max_d, int &xo, int &yo) { x }
  75. typedef void t_reffect(double &r, double &d, double max_d, int &xo, int &yo);
  76. MAKE_REFFECT(3, r+=0.1-0.2*(d/max_d); d*=0.96;)
  77. MAKE_REFFECT(4, d*=0.99*(1.0-sin(r)/32.0); r+=0.03*sin(d/max_d * M_PI * 4);)
  78. MAKE_REFFECT(5, d*=0.94+(cos(r*32.0)*0.06);)
  79. MAKE_REFFECT(6, d*=1.01+(cos(r*4.0)*0.04); r+=0.03*sin(d/max_d * M_PI * 4);)
  80. MAKE_REFFECT(8, r+=0.1*sin(d/max_d*M_PI*5);)
  81. MAKE_REFFECT(9, double t; t=sin(d/max_d*M_PI); d-=8*t*t*t*t*t; )
  82. 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; )
  83. MAKE_REFFECT(11, d*=0.95+(cos(r*5.0 - M_PI/2.50)*0.03); )
  84. MAKE_REFFECT(12, r+=0.04; d*=0.96+cos(d/max_d*M_PI)*0.05; )
  85. MAKE_REFFECT(13, double t; t=cos(d/max_d*M_PI); r+=0.07*t; d*=0.98+t*0.10; )
  86. MAKE_REFFECT(14, r+=0.1-0.2*(d/max_d); d*=0.96; xo=8; )
  87. MAKE_REFFECT(15, d=max_d*0.15;)
  88. MAKE_REFFECT(16, r=cos(r*3);)
  89. MAKE_REFFECT(17, d*=(1-(((d/max_d)-.35)*.5)); r+=.1;)
  90. static t_reffect *radial_effects[REFFECT_MAX-REFFECT_MIN+1]=
  91. {
  92. _ref3, _ref4, _ref5, _ref6, NULL, _ref8, _ref9, _ref10, _ref11, _ref12, _ref13,
  93. _ref14, _ref15, _ref16, _ref17, NULL/*18*/, NULL/*19*/, NULL/*20*/, NULL/*21*/,
  94. NULL/*22*/, NULL/*23*/,
  95. };
  96. static inline bool effect_uses_eval(int t)
  97. {
  98. bool retval = false;
  99. if ((t >= REFFECT_MIN) && (t <= REFFECT_MAX))
  100. {
  101. if (descriptions[t].uses_eval)
  102. {
  103. retval = true;
  104. }
  105. }
  106. return retval;
  107. }
  108. class C_THISCLASS : public C_RBASE2 {
  109. protected:
  110. public:
  111. C_THISCLASS();
  112. virtual ~C_THISCLASS();
  113. virtual int render(char visdata[2][2][576], int isBeat, int *framebuffer, int *fbout, int w, int h);
  114. virtual int smp_getflags() { return 1; }
  115. virtual int smp_begin(int max_threads, char visdata[2][2][576], int isBeat, int *framebuffer, int *fbout, int w, int h);
  116. 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);
  117. 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
  118. virtual char *get_desc() { return MOD_NAME; }
  119. virtual HWND conf(HINSTANCE hInstance, HWND hwndParent);
  120. virtual void load_config(unsigned char *data, int len);
  121. virtual int save_config(unsigned char *data);
  122. int *trans_tab, trans_tab_w, trans_tab_h, trans_tab_subpixel;
  123. int trans_effect;
  124. RString effect_exp;
  125. int effect_exp_ch;
  126. int effect,blend;
  127. int sourcemapped;
  128. int rectangular;
  129. int subpixel;
  130. int wrap;
  131. CRITICAL_SECTION rcs;
  132. };
  133. #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
  134. #define GET_INT() (data[pos]|(data[pos+1]<<8)|(data[pos+2]<<16)|(data[pos+3]<<24))
  135. void C_THISCLASS::load_config(unsigned char *data, int len)
  136. {
  137. int pos=0;
  138. if (len-pos >= 4) { effect=GET_INT(); pos+=4; }
  139. if (effect == 32767)
  140. {
  141. if (!memcmp(data+pos,"!rect ",6))
  142. {
  143. pos+=6;
  144. rectangular=1;
  145. }
  146. if (data[pos]==1)
  147. {
  148. pos++;
  149. int l=GET_INT(); pos+=4;
  150. if (l > 0 && len-pos >= l)
  151. {
  152. effect_exp.resize(l);
  153. memcpy(effect_exp.get(), data+pos, l);
  154. pos+=l;
  155. }
  156. else
  157. {
  158. effect_exp.resize(1);
  159. effect_exp.get()[0]=0;
  160. }
  161. }
  162. else if (len-pos >= 256)
  163. {
  164. char buf[257];
  165. int l=256-(rectangular?6:0);
  166. memcpy(buf,data+pos,l);
  167. buf[l]=0;
  168. effect_exp.assign(buf);
  169. pos+=l;
  170. }
  171. }
  172. if (len-pos >= 4) { blend=GET_INT(); pos+=4; }
  173. if (len-pos >= 4) { sourcemapped=GET_INT(); pos+=4; }
  174. if (len-pos >= 4) { rectangular=GET_INT(); pos+=4; }
  175. if (len-pos >= 4) { subpixel=GET_INT(); pos+=4; }
  176. else subpixel=0;
  177. if (len-pos >= 4) { wrap=GET_INT(); pos+=4; }
  178. else wrap=0;
  179. if (!effect && len-pos >= 4)
  180. {
  181. effect=GET_INT(); pos+=4;
  182. }
  183. if (effect != 32767 && effect > REFFECT_MAX || effect < 0)
  184. effect=0;
  185. // Once we know what our _real_ effect value is, if it uses the evaluator, allocate and stuff the string, here.
  186. /*
  187. if (effect_uses_eval(effect))
  188. {
  189. const char *eval_string = descriptions[effect].eval_desc;
  190. int length = strlen(eval_string);
  191. effect_exp.resize(length+1);
  192. strcpy(effect_exp.get(), eval_string);
  193. }
  194. */
  195. effect_exp_ch=1;
  196. }
  197. int C_THISCLASS::save_config(unsigned char *data)
  198. {
  199. int pos=0;
  200. // the reason this is 15, and not REFFECT_MAX, is because old versions of AVS barf
  201. // if effect is > 15, so we put 0, and at the end put the new value
  202. if (effect > 15 && effect != 32767)
  203. {
  204. PUT_INT(0);
  205. pos += 4;
  206. }
  207. else
  208. {
  209. PUT_INT(effect);
  210. pos+=4;
  211. }
  212. if (effect == 32767)
  213. {
  214. int l=strlen(effect_exp.get())+1;
  215. data[pos++]=1;
  216. PUT_INT(l);
  217. pos+=4;
  218. memcpy(data+pos,effect_exp.get(),strlen(effect_exp.get())+1);
  219. pos+=strlen(effect_exp.get())+1;
  220. }
  221. PUT_INT(blend); pos+=4;
  222. PUT_INT(sourcemapped); pos+=4;
  223. PUT_INT(rectangular); pos+=4;
  224. PUT_INT(subpixel); pos+=4;
  225. PUT_INT(wrap); pos+=4;
  226. // see note on '15' above =)
  227. if (effect > 15 && effect != 32767)
  228. {
  229. PUT_INT(effect);
  230. pos+=4;
  231. }
  232. return pos;
  233. }
  234. C_THISCLASS::C_THISCLASS()
  235. {
  236. InitializeCriticalSection(&rcs);
  237. sourcemapped=0;
  238. trans_tab=NULL;
  239. trans_tab_w=trans_tab_h=0;
  240. effect=1;
  241. trans_effect=0;
  242. blend=0;
  243. effect_exp.assign("");
  244. rectangular=0;
  245. subpixel=1;
  246. wrap=0;
  247. trans_tab_subpixel=0;
  248. effect_exp_ch=1;
  249. }
  250. C_THISCLASS::~C_THISCLASS()
  251. {
  252. if (trans_tab) GlobalFree(trans_tab);
  253. trans_tab=NULL;
  254. trans_tab_w=trans_tab_h=0;
  255. trans_effect=0;
  256. DeleteCriticalSection(&rcs);
  257. }
  258. int C_THISCLASS::smp_begin(int max_threads, char visdata[2][2][576], int isBeat, int *framebuffer, int *fbout, int w, int h)
  259. {
  260. if (!effect) return 0;
  261. if (!trans_tab || trans_tab_w != w || trans_tab_h != h || effect != trans_effect ||
  262. effect_exp_ch)
  263. {
  264. int p;
  265. int *transp,x;
  266. if (trans_tab) GlobalFree(trans_tab);
  267. trans_tab_w=w;
  268. trans_tab_h=h;
  269. trans_tab=(int*)GlobalAlloc(GMEM_FIXED,trans_tab_w*trans_tab_h*sizeof(int));
  270. trans_effect=effect;
  271. trans_tab_subpixel=(subpixel && trans_tab_w*trans_tab_h < (1<<22) &&
  272. ((trans_effect >= REFFECT_MIN && trans_effect <= REFFECT_MAX
  273. && trans_effect != 1 && trans_effect != 2 && trans_effect != 7
  274. )||trans_effect ==32767));
  275. /* generate trans_tab */
  276. transp=trans_tab;
  277. x=w*h;
  278. p=0;
  279. if (trans_effect == 1)
  280. {
  281. while (x--)
  282. {
  283. int r=(p++)+(rand()%3)-1 + ((rand()%3)-1)*w;
  284. *transp++ = min(w*h-1,max(r,0));
  285. }
  286. }
  287. else if (trans_effect == 2)
  288. {
  289. int y=h;
  290. while (y--)
  291. {
  292. int x=w;
  293. int lp=w/64;
  294. while (x--)
  295. {
  296. *transp++ = p+lp++;
  297. if (lp >= w) lp-=w;
  298. }
  299. p+=w;
  300. }
  301. }
  302. else if (trans_effect == 7)
  303. {
  304. int y;
  305. for (y = 0; y < h; y ++)
  306. {
  307. for (x = 0; x < w; x ++)
  308. {
  309. if (x&2 || y&2)
  310. {
  311. *transp++ = x+y*w;
  312. }
  313. else
  314. {
  315. int xp=w/2+(((x&~1)-w/2)*7)/8;
  316. int yp=h/2+(((y&~1)-h/2)*7)/8;
  317. *transp++=xp+yp*w;
  318. }
  319. }
  320. }
  321. }
  322. else if (trans_effect >= REFFECT_MIN && trans_effect <= REFFECT_MAX && !effect_uses_eval(trans_effect))
  323. {
  324. double max_d=sqrt((w*w+h*h)/4.0);
  325. int y;
  326. t_reffect *ref=radial_effects[trans_effect-REFFECT_MIN];
  327. if (ref) for (y = 0; y < h; y ++)
  328. {
  329. for (x = 0; x < w; x ++)
  330. {
  331. double r,d;
  332. double xd,yd;
  333. int ow,oh,xo=0,yo=0;
  334. xd=x-(w/2);
  335. yd=y-(h/2);
  336. d=sqrt(xd*xd+yd*yd);
  337. r=atan2(yd,xd);
  338. ref(r,d,max_d,xo,yo);
  339. double tmp1,tmp2;
  340. tmp1= ((h/2) + sin(r)*d + 0.5) + (yo*h)*(1.0/256.0);
  341. tmp2= ((w/2) + cos(r)*d + 0.5) + (xo*w)*(1.0/256.0);
  342. oh=(int)tmp1;
  343. ow=(int)tmp2;
  344. if (trans_tab_subpixel)
  345. {
  346. int xpartial=(int)(32.0*(tmp2-ow));
  347. int ypartial=(int)(32.0*(tmp1-oh));
  348. if (wrap)
  349. {
  350. ow%=(w-1);
  351. oh%=(h-1);
  352. if (ow<0)ow+=w-1;
  353. if (oh<0)oh+=h-1;
  354. }
  355. else
  356. {
  357. if (ow < 0) { xpartial=0; ow=0; }
  358. if (ow >= w-1) { xpartial=31; ow=w-2; }
  359. if (oh < 0) { ypartial=0; oh=0; }
  360. if (oh >= h-1) {ypartial=31; oh=h-2; }
  361. }
  362. *transp++ = ow+oh*w | (ypartial<<22) | (xpartial<<27);
  363. }
  364. else
  365. {
  366. if (wrap)
  367. {
  368. ow%=(w);
  369. oh%=(h);
  370. if (ow<0)ow+=w;
  371. if (oh<0)oh+=h;
  372. }
  373. else
  374. {
  375. if (ow < 0) ow=0;
  376. if (ow >= w) ow=w-1;
  377. if (oh < 0) oh=0;
  378. if (oh >= h) oh=h-1;
  379. }
  380. *transp++ = ow+oh*w;
  381. }
  382. }
  383. }
  384. }
  385. else if (trans_effect == 32767 || effect_uses_eval(trans_effect))
  386. {
  387. NSEEL_VMCTX AVS_EEL_CONTEXTNAME;
  388. AVS_EEL_INITINST();
  389. double max_d=sqrt((double)(w*w+h*h))/2.0;
  390. double divmax_d=1.0/max_d;
  391. int y;
  392. double *d = registerVar("d");
  393. double *r = registerVar("r");
  394. double *px = registerVar("x");
  395. double *py = registerVar("y");
  396. double *pw = registerVar("sw");
  397. double *ph = registerVar("sh");
  398. NSEEL_CODEHANDLE codehandle=0;
  399. int offs=0;
  400. int is_rect = trans_effect == 32767 ? rectangular : descriptions[trans_effect].uses_rect;
  401. *pw=w;
  402. *ph=h;
  403. EnterCriticalSection(&rcs);
  404. codehandle=compileCode(
  405. trans_effect == 32767 ? effect_exp.get() : descriptions[trans_effect].eval_desc
  406. );
  407. LeaveCriticalSection(&rcs);
  408. if (codehandle)
  409. {
  410. double w2=w/2;
  411. double h2=h/2;
  412. double xsc=1.0/w2,ysc=1.0/h2;
  413. for (y = 0; y < h; y ++)
  414. {
  415. for (x = 0; x < w; x ++)
  416. {
  417. double xd,yd;
  418. int ow,oh;
  419. xd=x-w2;
  420. yd=y-h2;
  421. *px=xd*xsc;
  422. *py=yd*ysc;
  423. *d=sqrt(xd*xd+yd*yd)*divmax_d;
  424. *r=atan2(yd,xd) + M_PI*0.5;
  425. executeCode(codehandle,visdata);
  426. double tmp1,tmp2;
  427. if (!is_rect)
  428. {
  429. *d *= max_d;
  430. *r -= M_PI/2.0;
  431. tmp1=((h/2) + sin(*r)* *d);
  432. tmp2=((w/2) + cos(*r)* *d);
  433. }
  434. else
  435. {
  436. tmp1=((*py+1.0)*h2);
  437. tmp2=((*px+1.0)*w2);
  438. }
  439. if (trans_tab_subpixel)
  440. {
  441. oh=(int) tmp1;
  442. ow=(int) tmp2;
  443. int xpartial=(int)(32.0*(tmp2-ow));
  444. int ypartial=(int)(32.0*(tmp1-oh));
  445. if (wrap)
  446. {
  447. ow%=(w-1);
  448. oh%=(h-1);
  449. if (ow<0)ow+=w-1;
  450. if (oh<0)oh+=h-1;
  451. }
  452. else
  453. {
  454. if (ow < 0) { xpartial=0; ow=0; }
  455. if (ow >= w-1) { xpartial=31; ow=w-2; }
  456. if (oh < 0) { ypartial=0; oh=0; }
  457. if (oh >= h-1) {ypartial=31; oh=h-2; }
  458. }
  459. *transp++ = ow+oh*w | (ypartial<<22) | (xpartial<<27);
  460. }
  461. else
  462. {
  463. tmp1+=0.5;
  464. tmp2+=0.5;
  465. oh=(int) tmp1;
  466. ow=(int) tmp2;
  467. if (wrap)
  468. {
  469. ow%=(w);
  470. oh%=(h);
  471. if (ow<0)ow+=w;
  472. if (oh<0)oh+=h;
  473. }
  474. else
  475. {
  476. if (ow < 0) ow=0;
  477. if (ow >= w) ow=w-1;
  478. if (oh < 0) oh=0;
  479. if (oh >= h) oh=h-1;
  480. }
  481. *transp++ = ow+oh*w;
  482. }
  483. }
  484. }
  485. }
  486. else
  487. {
  488. transp=trans_tab;
  489. trans_tab_subpixel=0;
  490. for (x = 0; x < w*h; x ++)
  491. *transp++=x;
  492. }
  493. freeCode(codehandle);
  494. AVS_EEL_QUITINST();
  495. }
  496. effect_exp_ch=0;
  497. }
  498. if (!(isBeat & 0x80000000))
  499. {
  500. if ((sourcemapped&2)&&isBeat) sourcemapped^=1;
  501. if (sourcemapped&1)
  502. {
  503. if (!blend) memset(fbout,0,w*h*sizeof(int));
  504. else memcpy(fbout,framebuffer,w*h*sizeof(int));
  505. }
  506. }
  507. return max_threads;
  508. }
  509. 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)
  510. {
  511. if (!effect) return;
  512. #define OFFSET_MASK ((1<<22)-1)
  513. unsigned int *inp = (unsigned int *) framebuffer;
  514. unsigned int *outp;
  515. int *transp, x;
  516. if (max_threads < 1) max_threads=1;
  517. int start_l = ( this_thread * h ) / max_threads;
  518. int end_l;
  519. if (this_thread >= max_threads - 1) end_l = h;
  520. else end_l = ( (this_thread+1) * h ) / max_threads;
  521. int outh=end_l-start_l;
  522. if (outh<1) return;
  523. int skip_pix=start_l*w;
  524. transp=trans_tab;
  525. outp = (unsigned int *) fbout;
  526. x=(w*outh)/4;
  527. if (sourcemapped&1)
  528. {
  529. inp += skip_pix;
  530. transp += skip_pix;
  531. if (trans_tab_subpixel)
  532. {
  533. timingEnter(3);
  534. while (x--)
  535. {
  536. fbout[transp[0]&OFFSET_MASK]=BLEND_MAX(inp[0],fbout[transp[0]&OFFSET_MASK]);
  537. fbout[transp[1]&OFFSET_MASK]=BLEND_MAX(inp[1],fbout[transp[1]&OFFSET_MASK]);
  538. fbout[transp[2]&OFFSET_MASK]=BLEND_MAX(inp[2],fbout[transp[2]&OFFSET_MASK]);
  539. fbout[transp[3]&OFFSET_MASK]=BLEND_MAX(inp[3],fbout[transp[3]&OFFSET_MASK]);
  540. inp+=4;
  541. transp+=4;
  542. }
  543. timingLeave(3);
  544. x = (w*outh)&3;
  545. if (x>0) while (x--)
  546. {
  547. fbout[transp[0]&OFFSET_MASK]=BLEND_MAX(inp++[0],fbout[transp[0]&OFFSET_MASK]);
  548. transp++;
  549. }
  550. }
  551. else
  552. {
  553. {
  554. timingEnter(3);
  555. while (x--)
  556. {
  557. fbout[transp[0]]=BLEND_MAX(inp[0],fbout[transp[0]]);
  558. fbout[transp[1]]=BLEND_MAX(inp[1],fbout[transp[1]]);
  559. fbout[transp[2]]=BLEND_MAX(inp[2],fbout[transp[2]]);
  560. fbout[transp[3]]=BLEND_MAX(inp[3],fbout[transp[3]]);
  561. inp+=4;
  562. transp+=4;
  563. }
  564. timingLeave(3);
  565. x = (w*outh)&3;
  566. if (x>0) while (x--)
  567. {
  568. fbout[transp[0]]=BLEND_MAX(inp++[0],fbout[transp[0]]);
  569. transp++;
  570. }
  571. }
  572. }
  573. if (blend)
  574. {
  575. framebuffer += skip_pix;
  576. fbout += skip_pix;
  577. x=(w*outh)/4;
  578. while (x--)
  579. {
  580. fbout[0]=BLEND_AVG(fbout[0],framebuffer[0]);
  581. fbout[1]=BLEND_AVG(fbout[1],framebuffer[1]);
  582. fbout[2]=BLEND_AVG(fbout[2],framebuffer[2]);
  583. fbout[3]=BLEND_AVG(fbout[3],framebuffer[3]);
  584. fbout+=4;
  585. framebuffer+=4;
  586. }
  587. x=(w*outh)&3;
  588. while (x--)
  589. {
  590. fbout[0]=BLEND_AVG(fbout[0],framebuffer[0]);
  591. fbout++;
  592. framebuffer++;
  593. }
  594. }
  595. }
  596. else
  597. {
  598. inp += skip_pix;
  599. outp += skip_pix;
  600. transp += skip_pix;
  601. if (trans_tab_subpixel&&blend)
  602. {
  603. while (x--)
  604. {
  605. int offs=transp[0]&OFFSET_MASK;
  606. outp[0]=BLEND_AVG(inp[0],BLEND4((unsigned int *)framebuffer+offs,w,((transp[0]>>24)&(31<<3)),((transp[0]>>19)&(31<<3))));
  607. offs=transp[1]&OFFSET_MASK;
  608. outp[1]=BLEND_AVG(inp[1],BLEND4((unsigned int *)framebuffer+offs,w,((transp[1]>>24)&(31<<3)),((transp[1]>>19)&(31<<3))));
  609. offs=transp[2]&OFFSET_MASK;
  610. outp[2]=BLEND_AVG(inp[2],BLEND4((unsigned int *)framebuffer+offs,w,((transp[2]>>24)&(31<<3)),((transp[2]>>19)&(31<<3))));
  611. offs=transp[3]&OFFSET_MASK;
  612. outp[3]=BLEND_AVG(inp[3],BLEND4((unsigned int *)framebuffer+offs,w,((transp[3]>>24)&(31<<3)),((transp[3]>>19)&(31<<3))));
  613. transp+=4;
  614. outp+=4;
  615. inp+=4;
  616. }
  617. x=(w*outh)&3;
  618. while (x--)
  619. {
  620. int offs=transp[0]&OFFSET_MASK;
  621. outp++[0]=BLEND_AVG(inp[0],BLEND4((unsigned int *)framebuffer+offs,w,((transp[0]>>24)&(31<<3)),((transp[0]>>19)&(31<<3))));
  622. transp++;
  623. inp++;
  624. }
  625. #ifndef NO_MMX
  626. __asm emms;
  627. #endif
  628. }
  629. else if (trans_tab_subpixel)
  630. {
  631. while (x--)
  632. {
  633. int offs=transp[0]&OFFSET_MASK;
  634. outp[0]=BLEND4((unsigned int *)framebuffer+offs,w,((transp[0]>>24)&(31<<3)),((transp[0]>>19)&(31<<3)));
  635. offs=transp[1]&OFFSET_MASK;
  636. outp[1]=BLEND4((unsigned int *)framebuffer+offs,w,((transp[1]>>24)&(31<<3)),((transp[1]>>19)&(31<<3)));
  637. offs=transp[2]&OFFSET_MASK;
  638. outp[2]=BLEND4((unsigned int *)framebuffer+offs,w,((transp[2]>>24)&(31<<3)),((transp[2]>>19)&(31<<3)));
  639. offs=transp[3]&OFFSET_MASK;
  640. outp[3]=BLEND4((unsigned int *)framebuffer+offs,w,((transp[3]>>24)&(31<<3)),((transp[3]>>19)&(31<<3)));
  641. transp+=4;
  642. outp+=4;
  643. }
  644. x=(w*outh)&3;
  645. while (x--)
  646. {
  647. int offs=transp[0]&OFFSET_MASK;
  648. outp++[0]=BLEND4((unsigned int *)framebuffer+offs,w,((transp[0]>>24)&(31<<3)),((transp[0]>>19)&(31<<3)));
  649. transp++;
  650. }
  651. #ifndef NO_MMX
  652. __asm emms;
  653. #endif
  654. }
  655. else if (blend)
  656. {
  657. timingEnter(3);
  658. while (x--)
  659. {
  660. outp[0]=BLEND_AVG(inp[0],framebuffer[transp[0]]);
  661. outp[1]=BLEND_AVG(inp[1],framebuffer[transp[1]]);
  662. outp[2]=BLEND_AVG(inp[2],framebuffer[transp[2]]);
  663. outp[3]=BLEND_AVG(inp[3],framebuffer[transp[3]]);
  664. outp+=4;
  665. inp+=4;
  666. transp+=4;
  667. }
  668. timingLeave(3);
  669. x = (w*outh)&3;
  670. if (x>0) while (x--)
  671. {
  672. outp++[0]=BLEND_AVG(inp++[0],framebuffer[transp++[0]]);
  673. }
  674. }
  675. else
  676. {
  677. timingEnter(4);
  678. while (x--)
  679. {
  680. outp[0]=framebuffer[transp[0]];
  681. outp[1]=framebuffer[transp[1]];
  682. outp[2]=framebuffer[transp[2]];
  683. outp[3]=framebuffer[transp[3]];
  684. outp+=4;
  685. transp+=4;
  686. }
  687. timingLeave(4);
  688. x = (w*outh)&3;
  689. if (x>0) while (x--)
  690. {
  691. outp++[0]=framebuffer[transp++[0]];
  692. }
  693. }
  694. }
  695. }
  696. 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
  697. {
  698. return !!effect;
  699. }
  700. int C_THISCLASS::render(char visdata[2][2][576], int isBeat, int *framebuffer, int *fbout, int w, int h)
  701. {
  702. smp_begin(1,visdata,isBeat,framebuffer,fbout,w,h);
  703. if (isBeat & 0x80000000) return 0;
  704. smp_render(0,1,visdata,isBeat,framebuffer,fbout,w,h);
  705. return smp_finish(visdata,isBeat,framebuffer,fbout,w,h);
  706. }
  707. C_RBASE *R_Trans(char *desc)
  708. {
  709. if (desc) { strcpy(desc,MOD_NAME); return NULL; }
  710. return (C_RBASE *) new C_THISCLASS();
  711. }
  712. static C_THISCLASS *g_this;
  713. static BOOL CALLBACK g_DlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
  714. {
  715. static int isstart;
  716. switch (uMsg)
  717. {
  718. case WM_INITDIALOG:
  719. {
  720. int x;
  721. for (x = 0; x < sizeof(descriptions)/sizeof(descriptions[0]); x ++)
  722. {
  723. SendDlgItemMessage( hwndDlg, IDC_LIST1, LB_ADDSTRING, 0, (LPARAM)(const wchar_t *)AutoWide( WASABI_API_LNGSTRING( descriptions[ x ].list_desc ), CP_UTF8 ) );
  724. }
  725. isstart=1;
  726. SetDlgItemText(hwndDlg,IDC_EDIT1,g_this->effect_exp.get());
  727. // After we set whatever value into the edit box, that's the new saved value (ie: don't change the save format)
  728. isstart=0;
  729. if (g_this->blend)
  730. CheckDlgButton(hwndDlg,IDC_CHECK1,BST_CHECKED);
  731. if (g_this->subpixel)
  732. CheckDlgButton(hwndDlg,IDC_CHECK4,BST_CHECKED);
  733. if (g_this->wrap)
  734. CheckDlgButton(hwndDlg,IDC_WRAP,BST_CHECKED);
  735. if (g_this->rectangular)
  736. CheckDlgButton(hwndDlg,IDC_CHECK3,BST_CHECKED);
  737. if (g_this->sourcemapped&2)
  738. CheckDlgButton(hwndDlg,IDC_CHECK2,BST_INDETERMINATE);
  739. else if (g_this->sourcemapped&1)
  740. CheckDlgButton(hwndDlg,IDC_CHECK2,BST_CHECKED);
  741. SendDlgItemMessage( hwndDlg, IDC_LIST1, LB_ADDSTRING, 0, (LPARAM)(const wchar_t *)AutoWide( WASABI_API_LNGSTRING( IDS_USER_DEFINED ), CP_UTF8 ) );
  742. SendDlgItemMessage(hwndDlg,IDC_LIST1,LB_SETCURSEL,(g_this->effect==32767)?sizeof(descriptions)/sizeof(descriptions[0]):g_this->effect,0);
  743. if (g_this->effect == 32767)
  744. {
  745. EnableWindow(GetDlgItem(hwndDlg,IDC_EDIT1),1);
  746. EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK3),1);
  747. EnableWindow(GetDlgItem(hwndDlg,IDC_LABEL1),1);
  748. }
  749. else if (g_this->effect >= 0 && g_this->effect <= REFFECT_MAX)
  750. {
  751. if (strlen(descriptions[g_this->effect].eval_desc) > 0)
  752. {
  753. SetDlgItemTextA(hwndDlg,IDC_EDIT1,descriptions[g_this->effect].eval_desc);
  754. CheckDlgButton(hwndDlg,IDC_CHECK3,descriptions[g_this->effect].uses_rect?BST_CHECKED:0);
  755. EnableWindow(GetDlgItem(hwndDlg,IDC_EDIT1),1);
  756. EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK3),1);
  757. EnableWindow(GetDlgItem(hwndDlg,IDC_LABEL1),1);
  758. }
  759. else
  760. {
  761. EnableWindow(GetDlgItem(hwndDlg,IDC_EDIT1),0);
  762. EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK3),0);
  763. EnableWindow(GetDlgItem(hwndDlg,IDC_LABEL1),0);
  764. }
  765. }
  766. else
  767. {
  768. EnableWindow(GetDlgItem(hwndDlg,IDC_EDIT1),0);
  769. EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK3),0);
  770. EnableWindow(GetDlgItem(hwndDlg,IDC_LABEL1),0);
  771. }
  772. }
  773. return 1;
  774. case WM_TIMER:
  775. if (wParam == 1)
  776. {
  777. KillTimer(hwndDlg,1);
  778. EnterCriticalSection(&g_this->rcs);
  779. g_this->effect=32767;
  780. g_this->effect_exp.get_from_dlgitem(hwndDlg,IDC_EDIT1);
  781. g_this->effect_exp_ch=1;
  782. LeaveCriticalSection(&g_this->rcs);
  783. }
  784. return 0;
  785. case WM_COMMAND:
  786. if (LOWORD(wParam) == IDC_EDIT1 && HIWORD(wParam) == EN_CHANGE)
  787. {
  788. KillTimer(hwndDlg,1);
  789. if (!isstart) SetTimer(hwndDlg,1,1000,NULL);
  790. // If someone edits the editwnd, force the "(user defined)" to be the new selection.
  791. if (SendDlgItemMessageA(hwndDlg,IDC_LIST1,LB_GETCURSEL,0,0) != sizeof(descriptions)/sizeof(descriptions[0]))
  792. {
  793. g_this->rectangular=IsDlgButtonChecked(hwndDlg,IDC_CHECK3)?1:0;
  794. SendDlgItemMessageA(hwndDlg,IDC_LIST1,LB_SETCURSEL,sizeof(descriptions)/sizeof(descriptions[0]),0);
  795. }
  796. }
  797. if (LOWORD(wParam)==IDC_LIST1 && HIWORD(wParam)==LBN_SELCHANGE)
  798. {
  799. int t;
  800. t=SendDlgItemMessageA(hwndDlg,IDC_LIST1,LB_GETCURSEL,0,0);
  801. if (t == sizeof(descriptions)/sizeof(descriptions[0]))
  802. {
  803. g_this->effect=32767;
  804. EnableWindow(GetDlgItem(hwndDlg,IDC_EDIT1),1);
  805. EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK3),1);
  806. EnableWindow(GetDlgItem(hwndDlg,IDC_LABEL1),1);
  807. SetDlgItemText(hwndDlg,IDC_EDIT1,g_this->effect_exp.get());
  808. CheckDlgButton(hwndDlg,IDC_CHECK3,g_this->rectangular);
  809. // always reinit =)
  810. {
  811. EnterCriticalSection(&g_this->rcs);
  812. g_this->effect_exp.get_from_dlgitem(hwndDlg,IDC_EDIT1);
  813. g_this->effect_exp_ch=1;
  814. LeaveCriticalSection(&g_this->rcs);
  815. }
  816. }
  817. else
  818. {
  819. g_this->effect=t;
  820. // If there is a string to stuff in the eval box,
  821. if (strlen(descriptions[t].eval_desc) > 0)
  822. {
  823. // save the value to be able to restore it later
  824. // stuff it and make sure the boxes are editable
  825. SetDlgItemText(hwndDlg,IDC_EDIT1,descriptions[t].eval_desc);
  826. EnableWindow(GetDlgItem(hwndDlg,IDC_EDIT1),1);
  827. EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK3),1);
  828. EnableWindow(GetDlgItem(hwndDlg,IDC_LABEL1),1);
  829. CheckDlgButton(hwndDlg,IDC_CHECK3,descriptions[t].uses_rect?BST_CHECKED:0);
  830. }
  831. else
  832. {
  833. // otherwise, they're not editable.
  834. CheckDlgButton(hwndDlg,IDC_CHECK3,g_this->rectangular?BST_CHECKED:0);
  835. SetDlgItemText(hwndDlg,IDC_EDIT1,"");
  836. EnableWindow(GetDlgItem(hwndDlg,IDC_EDIT1),0);
  837. EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK3),0);
  838. EnableWindow(GetDlgItem(hwndDlg,IDC_LABEL1),0);
  839. }
  840. }
  841. }
  842. if (LOWORD(wParam)==IDC_CHECK1)
  843. {
  844. g_this->blend=IsDlgButtonChecked(hwndDlg,IDC_CHECK1)?1:0;
  845. }
  846. if (LOWORD(wParam)==IDC_CHECK4)
  847. {
  848. g_this->subpixel=IsDlgButtonChecked(hwndDlg,IDC_CHECK4)?1:0;
  849. g_this->effect_exp_ch=1;
  850. }
  851. if (LOWORD(wParam)==IDC_WRAP)
  852. {
  853. g_this->wrap=IsDlgButtonChecked(hwndDlg,IDC_WRAP)?1:0;
  854. g_this->effect_exp_ch=1;
  855. }
  856. if (LOWORD(wParam)==IDC_CHECK2)
  857. {
  858. int a=IsDlgButtonChecked(hwndDlg,IDC_CHECK2);
  859. if (a == BST_INDETERMINATE)
  860. g_this->sourcemapped=2;
  861. else if (a == BST_CHECKED)
  862. g_this->sourcemapped=1;
  863. else
  864. g_this->sourcemapped=0;
  865. }
  866. if (LOWORD(wParam) == IDC_CHECK3)
  867. {
  868. g_this->rectangular=IsDlgButtonChecked(hwndDlg,IDC_CHECK3)?1:0;
  869. if (SendDlgItemMessageA(hwndDlg,IDC_LIST1,LB_GETCURSEL,0,0) != sizeof(descriptions)/sizeof(descriptions[0]))
  870. {
  871. EnterCriticalSection(&g_this->rcs);
  872. g_this->effect=32767;
  873. g_this->effect_exp.get_from_dlgitem(hwndDlg,IDC_EDIT1);
  874. g_this->effect_exp_ch=1;
  875. LeaveCriticalSection(&g_this->rcs);
  876. SendDlgItemMessageA(hwndDlg,IDC_LIST1,LB_SETCURSEL,sizeof(descriptions)/sizeof(descriptions[0]),0);
  877. }
  878. else
  879. g_this->effect_exp_ch=1;
  880. }
  881. if (LOWORD(wParam) == IDC_BUTTON2)
  882. {
  883. /*
  884. char text[4096];
  885. WASABI_API_LNGSTRING_BUF(IDS_MOVEMENT,text,4096);
  886. int titlelen = lstrlen(text)+1;
  887. lstrcpyn(text+titlelen,GetTextResource(IDR_MOVEMENT),4095-titlelen);
  888. */
  889. char *text="Movement\0"
  890. "Movement help:\r\n"
  891. "To use the custom table, modify r,d,x or y.\r\n"
  892. "Rect coords: x,y are in (-1..1) . Otherwise: d is (0..1) and r is (0..2PI).\r\n"
  893. "You can also access 'sw' and 'sh' for screen dimensions in pixels (might be useful)\r\n"
  894. ;
  895. compilerfunctionlist(hwndDlg,text);
  896. }
  897. return 0;
  898. return 0;
  899. }
  900. return 0;
  901. }
  902. HWND C_THISCLASS::conf(HINSTANCE hInstance, HWND hwndParent)
  903. {
  904. g_this = this;
  905. return WASABI_API_CREATEDIALOG(IDD_CFG_TRANS,hwndParent,g_DlgProc);
  906. }
  907. #else
  908. C_RBASE *R_Trans(char *desc){return NULL; }
  909. #endif