Panel Image.cpp 94 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. #define CC4_PIMG CC4('P','I','M','G')
  4. namespace EE{
  5. /******************************************************************************
  6. Vertex Shear:
  7. Flt shear=Ms.pos().x, offset=shear*-rect.centerY();
  8. REP(vtxs)v[i].pos.x+=v[i].pos.y*shear+offset;
  9. /******************************************************************************/
  10. DEFINE_CACHE(PanelImage, PanelImages, PanelImagePtr, "Panel Image");
  11. /******************************************************************************/
  12. static inline Flt LightSpecularBase(C Vec &nrm, C Vec &light_dir, C Vec &eye_dir)
  13. {
  14. #if 0 // blinn
  15. return Sat(Dot(nrm, !(light_dir+eye_dir)));
  16. #else // phong, use phong in this case because it has nicer specular on the edges
  17. Vec reflection=!(nrm*(2*Dot(nrm, light_dir)) - light_dir);
  18. return Sat(Dot(reflection, eye_dir));
  19. #endif
  20. }
  21. static inline Flt LightSpecular(C Vec &nrm, C Vec &light_dir, C Vec &eye_dir, Flt power=64)
  22. {
  23. return Pow(LightSpecularBase(nrm, light_dir, eye_dir), power);
  24. }
  25. static void GetFracMulAddFromValues(Flt from, Flt to, Flt &mul, Flt &add)
  26. {
  27. // from*mul+add=0
  28. // to *mul+add=1
  29. Flt d=to-from;
  30. mul=(d ? 1.0f/d : 0); add=-from*mul;
  31. }
  32. static void AdjustFracMulAdd_1_1(Flt &mul, Flt &add) // adjust frac mul add (0..1) to (-1..1)
  33. {
  34. // from*mul'+add'=-1
  35. // to *mul'+add'= 1
  36. // mul'=mul*2
  37. // add'=-1 - from*mul*2
  38. // add'=-1 + add*2
  39. mul*=2;
  40. add =add*2-1;
  41. }
  42. // 'x0' and 'y0' are inclusive, while 'x1' and 'y1' are exclusive
  43. static void GetFracMulAddFromImage(Int x0, Int x1, Int y0, Int y1, C Image *image, Vec4 &frac_mul_add, Bool mirror_x=false, Bool mirror_y=false)
  44. {
  45. if(image)
  46. {
  47. if(mirror_x)Swap(x0, x1);
  48. if(mirror_y)Swap(y0, y1);
  49. Int w=x1-x0, h=y1-y0;
  50. // x0*frac_mul_add.x+frac_mul_add.y=0
  51. // y0*frac_mul_add.z+frac_mul_add.w=0
  52. frac_mul_add.x=Flt(image->w())/w; frac_mul_add.y=-x0*frac_mul_add.x + frac_mul_add.x*0.5f-0.5f;
  53. frac_mul_add.z=Flt(image->h())/h; frac_mul_add.w=-y0*frac_mul_add.z + frac_mul_add.z*0.5f-0.5f;
  54. }
  55. }
  56. static void ScaleTex(Flt &tex, Flt scale) {tex=(tex-0.5f)*scale+0.5f;}
  57. static void ScaleTex(Vec2 &tex, C Vec2 &scale) {ScaleTex(tex.x, scale.x); ScaleTex(tex.y, scale.y);}
  58. /******************************************************************************/
  59. struct SmoothDepth
  60. {
  61. Bool is[2];
  62. Vec2 val, sqr;
  63. SmoothDepth() {}
  64. SmoothDepth(C Vec2 &smooth_depth)
  65. {
  66. is[0]= (smooth_depth.x>EPS);
  67. is[1]= (smooth_depth.y>EPS);
  68. val = smooth_depth;
  69. sqr =Sqr(smooth_depth);
  70. }
  71. };
  72. struct SectionParams
  73. {
  74. Flt size, size_top;
  75. Vec2 frac_mul, frac_add, norm_mul, norm_add;
  76. Vec4 color_top, color_bottom, color_left, color_right,
  77. outer_color, inner_color,
  78. outer_border_color, inner_border_color, prev_border_color;
  79. Flt noise_intensity, noise_uv_scale, noise_uv_warp;
  80. Image noise_map;
  81. Flt overlay_intensity, overlay_uv_scale, overlay_uv_warp;
  82. Vec2 overlay_uv_offset;
  83. Image overlay_image;
  84. C Image *overlay;
  85. Bool reflection_one;
  86. Image reflection_image;
  87. C Image *reflection;
  88. SmoothDepth smooth_depth;
  89. SectionParams()
  90. {
  91. overlay=reflection=null;
  92. }
  93. ~SectionParams()
  94. {
  95. if(overlay )overlay ->unlock();
  96. if(reflection)reflection->unlock();
  97. }
  98. void setColors(C PanelImageParams::Section &src)
  99. {
  100. color_top =src.color_top .asVec4();
  101. color_bottom=src.color_bottom.asVec4();
  102. color_left =src.color_left .asVec4();
  103. color_right =src.color_right .asVec4();
  104. outer_color =src.outer_color .asVec4();
  105. inner_color =src.inner_color .asVec4();
  106. outer_border_color=src.outer_border_color.asVec4();
  107. inner_border_color=src.inner_border_color.asVec4();
  108. prev_border_color=src. prev_border_color.asVec4();
  109. Vec4 src_color=src.color.asVec4(); outer_color*=src_color; inner_color*=src_color;
  110. }
  111. void setColorY(Flt section_frac, C Vec4 &global_color_y, Vec4 &section_color_y)
  112. {
  113. section_color_y=Lerp(color_top, color_bottom, section_frac)*global_color_y;
  114. }
  115. void setDepthNoise(C PanelImageParams::Section &src, Int w, Int h, Int super_sample, Threads *threads)
  116. {
  117. if(src.depth_noise.is())
  118. {
  119. Randomizer random(UIDZero);
  120. noise_map.createSoftTry(w/super_sample, h/super_sample, 1, IMAGE_F32);
  121. REPD(y, noise_map.h())
  122. REPD(x, noise_map.w())noise_map.pixF(x, y)=random.f();
  123. noise_map.blur(src.depth_noise.blur, src.depth_noise.blur_clamp, threads);
  124. noise_intensity=src.depth_noise.intensity*((src.depth_noise.mode==PanelImageParams::ImageParams::SCALE) ? 1.5f : 1);
  125. noise_uv_scale =src.depth_noise.uv_scale/super_sample;
  126. noise_uv_warp =src.depth_noise.uv_warp*noise_map.h();
  127. }else noise_map.del();
  128. }
  129. void setColorNoise(C PanelImageParams::Section &src, Int w, Int h, Int super_sample, Threads *threads)
  130. {
  131. if(src.color_noise.is())
  132. {
  133. Randomizer random(UIDZero);
  134. noise_map.createSoftTry(w/super_sample, h/super_sample, 1, IMAGE_F32);
  135. REPD(y, noise_map.h())
  136. REPD(x, noise_map.w())noise_map.pixF(x, y)=random.f();
  137. noise_map.blur(src.color_noise.blur, src.color_noise.blur_clamp, threads);
  138. noise_intensity=src.color_noise.intensity*((src.color_noise.mode==PanelImageParams::ImageParams::SCALE) ? 1.5f : 1);
  139. noise_uv_scale =src.color_noise.uv_scale/super_sample;
  140. noise_uv_warp =src.color_noise.uv_warp*noise_map.h();
  141. }else noise_map.del();
  142. }
  143. void setDepthOverlay(C PanelImageParams::Section &src, Int resolution, Threads *threads)
  144. {
  145. if(overlay){overlay->unlock(); overlay=null;}
  146. if(overlay=src.depth_overlay)
  147. {
  148. if(overlay->compressed() || src.depth_overlay_params.blur)
  149. if(overlay->copyTry(overlay_image, -1, -1, -1, ImageTI[overlay->hwType()].a ? IMAGE_F32_4 : IMAGE_F32, IMAGE_SOFT, 1))overlay=&overlay_image;else overlay=null;
  150. if(overlay)
  151. {
  152. overlay_image.blur(src.depth_overlay_params.blur, src.depth_overlay_params.blur_clamp, threads); // this will blur only if 'src.depth_overlay_params.blur' in which case the "overlay==&overlay_image"
  153. overlay->lockRead();
  154. overlay_intensity=src.depth_overlay_params.intensity*((src.depth_overlay_params.mode==PanelImageParams::ImageParams::SCALE) ? 1.5f : 1);
  155. overlay_uv_scale =src.depth_overlay_params.uv_scale*(Flt(overlay->h())/resolution);
  156. overlay_uv_warp =src.depth_overlay_params.uv_warp*overlay->h();
  157. overlay_uv_offset=overlay_uv_scale*0.5f-0.5f+src.depth_overlay_params.uv_offset*(overlay->size()*VecI2(-1, 1)); // change X sign in uv_offset so when editing it in editor using property mouse edit, the image moves along the mouse movement
  158. }
  159. }
  160. }
  161. void setColorOverlay(C PanelImageParams::Section &src, Int resolution, Threads *threads)
  162. {
  163. if(overlay){overlay->unlock(); overlay=null;}
  164. if(overlay=src.color_overlay)
  165. {
  166. if(overlay->compressed() || src.color_overlay_params.blur)
  167. if(overlay->copyTry(overlay_image, -1, -1, -1, IMAGE_R8G8B8A8, IMAGE_SOFT, 1))overlay=&overlay_image;else overlay=null;
  168. if(overlay)
  169. {
  170. overlay_image.blur(src.color_overlay_params.blur, src.color_overlay_params.blur_clamp, threads); // this will blur only if 'src.color_overlay_params.blur' in which case the "overlay==&overlay_image"
  171. overlay->lockRead();
  172. overlay_intensity=src.color_overlay_params.intensity*((src.color_overlay_params.mode==PanelImageParams::ImageParams::SCALE) ? 1.5f : 1);
  173. overlay_uv_scale =src.color_overlay_params.uv_scale*(Flt(overlay->h())/resolution);
  174. overlay_uv_warp =src.color_overlay_params.uv_warp*overlay->h();
  175. overlay_uv_offset=overlay_uv_scale*0.5f-0.5f+src.color_overlay_params.uv_offset*(overlay->size()*VecI2(-1, 1)); // change X sign in uv_offset so when editing it in editor using property mouse edit, the image moves along the mouse movement
  176. }
  177. }
  178. }
  179. void setReflection(C PanelImageParams::Section &src)
  180. {
  181. if(reflection=src.reflection)
  182. {
  183. if(reflection->compressed() || reflection->cube())if(reflection->copyTry(reflection_image, -1, -1, -1, reflection->compressed() ? IMAGE_R8G8B8A8 : -1, IMAGE_SOFT, 1))reflection=&reflection_image;else reflection=null;
  184. if(reflection)
  185. {
  186. reflection->lockRead();
  187. reflection_one=(reflection->aspect()<AvgF(1, 6)); // source is only 1 face, not "6*face"
  188. }
  189. }
  190. }
  191. void setSize(Flt size, Flt top_offset)
  192. {
  193. T.size =size;
  194. T.size_top=Max(size+top_offset, 0);
  195. }
  196. void setOffset(Flt offset, Flt offset_top, Int resolution, Int image_w, Int image_h)
  197. {
  198. Flt o=offset *0.5f*resolution,
  199. t=offset_top*0.5f*resolution;
  200. GetFracMulAddFromValues(o, image_w-1-o, frac_mul.x, frac_add.x);
  201. GetFracMulAddFromValues(t, image_h-1-o, frac_mul.y, frac_add.y);
  202. norm_mul=frac_mul;
  203. norm_add=frac_add;
  204. REP(2)AdjustFracMulAdd_1_1(norm_mul.c[i], norm_add.c[i]);
  205. }
  206. void setParams(C PanelImageParams::Section &src, Int resolution, Threads *threads)
  207. {
  208. smooth_depth =src.smooth_depth;
  209. setSize (src.size, src.top_offset);
  210. setColors (src);
  211. setDepthOverlay(src, resolution, threads);
  212. setReflection (src);
  213. }
  214. };
  215. /******************************************************************************/
  216. // PANEL IMAGE PARAMS
  217. /******************************************************************************/
  218. PanelImageParams::Light::Light()
  219. {
  220. enabled=false;
  221. intensity=0.5f;
  222. back=0.25f;
  223. highlight=0.0f;
  224. highlight_cut=specular_highlight_cut=0.8f;
  225. specular=1.0f;
  226. specular_back=0.0f;
  227. specular_exp=32;
  228. specular_highlight=0.0f;
  229. angle.set(0, 0.4f);
  230. }
  231. Bool PanelImageParams::Light::save(File &f)C
  232. {
  233. f.cmpUIntV(0);
  234. f<<enabled<<intensity<<back<<highlight<<highlight_cut<<specular<<specular_back<<specular_exp<<specular_highlight<<specular_highlight_cut<<angle;
  235. return f.ok();
  236. }
  237. Bool PanelImageParams::Light::load(File &f)
  238. {
  239. switch(f.decUIntV())
  240. {
  241. case 0:
  242. {
  243. f>>enabled>>intensity>>back>>highlight>>highlight_cut>>specular>>specular_back>>specular_exp>>specular_highlight>>specular_highlight_cut>>angle;
  244. if(f.ok())return true;
  245. }break;
  246. }
  247. return false;
  248. }
  249. /******************************************************************************/
  250. PanelImageParams::ImageParams::ImageParams()
  251. {
  252. blur_clamp=false;
  253. blur =0;
  254. uv_scale =1.0f;
  255. uv_offset =0.0f;
  256. uv_warp =0.0f;
  257. intensity =0.0f;
  258. mode =MULTIPLY;
  259. }
  260. Bool PanelImageParams::ImageParams::save(File &f)C
  261. {
  262. f.cmpUIntV(0); // !! WARNING: IN THE FUTURE SAVE 'mode' AS 1 BYTE USING << >> !!
  263. f<<blur_clamp<<blur<<uv_scale<<uv_offset<<uv_warp<<intensity; f.putUInt(mode);
  264. return f.ok();
  265. }
  266. Bool PanelImageParams::ImageParams::load(File &f)
  267. {
  268. switch(f.decUIntV())
  269. {
  270. case 0:
  271. {
  272. f>>blur_clamp>>blur>>uv_scale>>uv_offset>>uv_warp>>intensity; mode=MODE(f.getUInt());
  273. if(f.ok())return true;
  274. }break;
  275. }
  276. return false;
  277. }
  278. /******************************************************************************/
  279. PanelImageParams::Section::Section()
  280. {
  281. size=0.0f;
  282. top_offset=0;
  283. round_depth =1.0f;
  284. outer_depth =1.0f;
  285. inner_depth =1.0f;
  286. inner_distance=0.5f;
  287. smooth_depth.zero();
  288. specular=0.0f;
  289. reflection_intensity=0.3f;
  290. color=outer_color=inner_color=color_top=color_bottom=color_left=color_right=WHITE;
  291. outer_border_color=BLACK; outer_border_color.a=128;
  292. inner_border_color=WHITE; inner_border_color.a=64;
  293. prev_border_color=TRANSPARENT;
  294. color_overlay=depth_overlay=reflection=null;
  295. depth_overlay_params.intensity=1.0f;
  296. color_overlay_params.intensity=1.0f;
  297. color_noise .uv_warp =1.0f;
  298. }
  299. Bool PanelImageParams::Section::save(File &f)C
  300. {
  301. f.cmpUIntV(0);
  302. f<<size<<top_offset<<round_depth<<outer_depth<<inner_depth<<inner_distance<<specular<<reflection_intensity<<smooth_depth
  303. <<color<<outer_color<<inner_color<<color_top<<color_bottom<<color_left<<color_right<<outer_border_color<<inner_border_color<<prev_border_color;
  304. if(depth_overlay_params.save(f))
  305. if(color_overlay_params.save(f))
  306. if(depth_noise .save(f))
  307. if(color_noise .save(f))
  308. return f.ok();
  309. return false;
  310. }
  311. Bool PanelImageParams::Section::load(File &f)
  312. {
  313. switch(f.decUIntV())
  314. {
  315. case 0:
  316. {
  317. f>>size>>top_offset>>round_depth>>outer_depth>>inner_depth>>inner_distance>>specular>>reflection_intensity>>smooth_depth
  318. >>color>>outer_color>>inner_color>>color_top>>color_bottom>>color_left>>color_right>>outer_border_color>>inner_border_color>>prev_border_color;
  319. if(depth_overlay_params.load(f))
  320. if(color_overlay_params.load(f))
  321. if(depth_noise .load(f))
  322. if(color_noise .load(f))
  323. if(f.ok())return true;
  324. }break;
  325. }
  326. return false;
  327. }
  328. /******************************************************************************/
  329. PanelImageParams::PanelImageParams()
  330. {
  331. cut_left=cut_right=cut_bottom=cut_top=false;
  332. Zero(cut_corners); Zero(force_uniform_stretch);
  333. resolution=64;
  334. width=height=1;
  335. round_corners=0.5f;
  336. cut_corner_slope=1.0f;
  337. cut_corner_amount=1.0f;
  338. left_slope=right_slope=0.0f;
  339. light_ambient=0.5f;
  340. border_size=2.0f/resolution; // this sets border to exactly one pixel
  341. outer_glow_spread=0.5f;
  342. outer_glow_radius=inner_glow_radius=border_size*12;
  343. max_side_stretch=0.2f;
  344. extend.zero();
  345. extend_inner_padd.zero();
  346. depth =1.0f;
  347. round_depth =1.0f;
  348. inner_distance=0.5f;
  349. smooth_depth.zero();
  350. color=color_top=color_bottom=color_left=color_right=WHITE;
  351. outer_glow_color=inner_glow_color=TRANSPARENT;
  352. shadow_radius=0;
  353. shadow_opacity=0.5f;
  354. shadow_spread=0.5f;
  355. lights[0].enabled=true;
  356. sections[0].inner_distance=1.0f;
  357. images_size=0.5f;
  358. top_height=bottom_height=left_right_width=top_corner_width=bottom_corner_width=1;
  359. top_image=bottom_image=center_image=left_image=right_image=top_left_image=top_right_image=bottom_left_image=bottom_right_image=null;
  360. }
  361. Bool PanelImageParams::save(File &f)C
  362. {
  363. f.cmpUIntV(1);
  364. f<<cut_left<<cut_right<<cut_bottom<<cut_top<<cut_corners<<force_uniform_stretch
  365. <<resolution<<width<<height<<round_corners<<cut_corner_slope<<cut_corner_amount<<left_slope<<right_slope
  366. <<border_size<<outer_glow_spread<<outer_glow_radius<<inner_glow_radius
  367. <<light_ambient<<depth<<round_depth<<inner_distance<<shadow_radius<<shadow_opacity<<shadow_spread<<max_side_stretch<<smooth_depth<<extend<<extend_inner_padd
  368. <<color<<color_top<<color_bottom<<color_left<<color_right<<outer_glow_color<<inner_glow_color
  369. <<images_size<<top_height<<bottom_height<<left_right_width<<top_corner_width<<bottom_corner_width;
  370. FREPA(lights )if(!lights [i].save(f))return false;
  371. FREPA(sections)if(!sections[i].save(f))return false;
  372. return f.ok();
  373. }
  374. Bool PanelImageParams::load(File &f)
  375. {
  376. switch(f.decUIntV())
  377. {
  378. case 1:
  379. {
  380. f>>cut_left>>cut_right>>cut_bottom>>cut_top>>cut_corners>>force_uniform_stretch
  381. >>resolution>>width>>height>>round_corners>>cut_corner_slope>>cut_corner_amount>>left_slope>>right_slope
  382. >>border_size>>outer_glow_spread>>outer_glow_radius>>inner_glow_radius
  383. >>light_ambient>>depth>>round_depth>>inner_distance>>shadow_radius>>shadow_opacity>>shadow_spread>>max_side_stretch>>smooth_depth>>extend>>extend_inner_padd
  384. >>color>>color_top>>color_bottom>>color_left>>color_right>>outer_glow_color>>inner_glow_color
  385. >>images_size>>top_height>>bottom_height>>left_right_width>>top_corner_width>>bottom_corner_width;
  386. FREPA(lights )if(!lights [i].load(f))goto error;
  387. FREPA(sections)if(!sections[i].load(f))goto error;
  388. if(f.ok())return true;
  389. }break;
  390. case 0:
  391. {
  392. f>>cut_left>>cut_right>>cut_bottom>>cut_top>>cut_corners>>force_uniform_stretch
  393. >>resolution>>width>>height>>round_corners>>cut_corner_slope>>cut_corner_amount>>left_slope>>right_slope
  394. >>border_size>>outer_glow_spread>>outer_glow_radius>>inner_glow_radius
  395. >>light_ambient>>depth>>round_depth>>inner_distance>>shadow_radius>>shadow_opacity>>shadow_spread>>max_side_stretch>>smooth_depth>>extend
  396. >>color>>color_top>>color_bottom>>color_left>>color_right>>outer_glow_color>>inner_glow_color
  397. >>images_size>>top_height>>bottom_height>>left_right_width>>top_corner_width>>bottom_corner_width;
  398. FREPA(lights )if(!lights [i].load(f))goto error;
  399. FREPA(sections)if(!sections[i].load(f))goto error;
  400. extend_inner_padd.zero();
  401. if(f.ok())return true;
  402. }break;
  403. }
  404. error:
  405. return false;
  406. }
  407. /******************************************************************************/
  408. // PANEL IMAGE
  409. /******************************************************************************/
  410. PanelImage::PanelImage() {zero();}
  411. void PanelImage::zero()
  412. {
  413. _same_x=_padd_any=false;
  414. REPAO(_force_uniform_stretch)=false;
  415. REPAD(y, _size_x)REPAD(x, _size_x[y])_size_x[y][x]=0;
  416. REPAD(y, _tex_x)REPAD(x, _tex_x[y]) _tex_x[y][x]=0;
  417. REPAO( _size_y)=0;
  418. REPAO( _tex_y)=0;
  419. _side_size .zero();
  420. _padd .zero();
  421. _tex_left_top .zero();
  422. _tex_right_bottom.zero();
  423. _inner_padding .zero();
  424. }
  425. void PanelImage::del() {image.del(); zero();}
  426. /******************************************************************************/
  427. #define MEMBER_ELMS2(Class, member) ELMS(MEMBER(Class, member)) // get elements of member in class
  428. #define LIGHTS MEMBER_ELMS2(PanelImageParams, lights)
  429. struct PanelImageCreate
  430. {
  431. struct Line
  432. {
  433. Bool on;
  434. Vec2 pos, normal, dir;
  435. void finalize(Bool on)
  436. {
  437. T.on=on;
  438. normal.normalize();
  439. dir=Perp(normal);
  440. }
  441. Flt yAtX(Flt x)C {if(!dir.x)return pos.y; Flt dx=x-pos.x, d=dx/dir.x; return pos.y+d*dir.y;}
  442. Flt xAtY(Flt y)C {if(!dir.y)return pos.x; Flt dy=y-pos.y, d=dy/dir.y; return pos.x+d*dir.x;}
  443. };
  444. struct ImageSrc
  445. {
  446. C Image *src ; // we keep a pointer to the original image, to avoid creating software copies of the same image multiple times (in case it's assigned to multiple slots), also this is necessary to detect mirroring
  447. Image soft;
  448. };
  449. Int resolution, super_sample;
  450. PanelImage &panel_image;
  451. C PanelImageParams &params;
  452. Image &image, map, dist_map, *depth_map;
  453. Vec light_dir[LIGHTS], light_dir_neg[LIGHTS];
  454. VecI2 image_size, image_size1, image_size_2i;
  455. Vec2 image_size_2, corner_size;
  456. SmoothDepth smooth_depth;
  457. SectionParams sps[MEMBER_ELMS2(PanelImageParams, sections)], &last;
  458. Flt top_offset, max_scale;
  459. Vec4 color_top, color_bottom, color_left, color_right, inner_glow_color;
  460. Memb<ImageSrc> temp_images; // use 'Memb' because pointers to elements are stored
  461. C Image *top_image, *bottom_image, *center_image, *left_image, *right_image, *top_left_image, *top_right_image, *bottom_left_image, *bottom_right_image;
  462. Int x3, y3, y1, y2, x1, x2, top_x1, top_x2, bottom_x1, bottom_x2;
  463. Vec4 image_frac_mul_add[3][3]; // [x][y]
  464. C Vec2 &full_frac_mul, //&full_frac_add, // this is always zero
  465. &full_norm_mul, &full_norm_add;
  466. Line corner_line[2][2], // [y][x]
  467. side_line[2]; // [x]
  468. Threads *threads;
  469. PanelImageCreate(PanelImage &panel_image, C PanelImageParams &params, Image *depth_map, Int super_sample, Threads *threads)
  470. : panel_image(panel_image), params(params), depth_map(depth_map), image(panel_image.image), last(sps[Elms(sps)-1]), threads(threads),
  471. full_frac_mul(last.frac_mul), full_norm_mul(last.norm_mul), full_norm_add(last.norm_add) // last section is always full
  472. {
  473. if(depth_map)depth_map->del();
  474. T.super_sample=Mid(super_sample, 1, 16);
  475. T.resolution =params.resolution*T.super_sample;
  476. top_image=bottom_image=center_image=left_image=right_image=top_left_image=top_right_image=bottom_left_image=bottom_right_image=null;
  477. }
  478. ~PanelImageCreate()
  479. {
  480. if( top_image) top_image->unlock();
  481. if( bottom_image) bottom_image->unlock();
  482. if( center_image) center_image->unlock();
  483. if( left_image) left_image->unlock();
  484. if( right_image) right_image->unlock();
  485. if( top_left_image) top_left_image->unlock();
  486. if( top_right_image) top_right_image->unlock();
  487. if( bottom_left_image) bottom_left_image->unlock();
  488. if(bottom_right_image)bottom_right_image->unlock();
  489. }
  490. C Image* getImage(C Image *image)
  491. {
  492. if(image && image->compressed())
  493. {
  494. REPA(temp_images)if(temp_images[i].src==image){image=&temp_images[i].soft; goto found;} // goto found and lock it, because it's always unlocked in the codes below
  495. ImageSrc &temp=temp_images.New(); temp.src=image;
  496. if(image->copyTry(temp.soft, -1, -1, -1, IMAGE_R8G8B8A8, IMAGE_SOFT, 1))image=&temp.soft;else image=null;
  497. }
  498. found:
  499. return (image && image->lockRead()) ? image : null;
  500. }
  501. void alignTex()
  502. {
  503. REPAD(y, panel_image._tex_x)
  504. {
  505. panel_image._tex_x[y][0]=AlignCeil (panel_image._tex_x[y][0], super_sample);
  506. panel_image._tex_x[y][1]=AlignFloor(panel_image._tex_x[y][1], super_sample);
  507. }
  508. panel_image._tex_y[0]=AlignCeil (panel_image._tex_y[0], super_sample);
  509. panel_image._tex_y[1]=AlignFloor(panel_image._tex_y[1], super_sample);
  510. }
  511. Bool create()
  512. {
  513. if(image .createSoftTry(resolution*params.width, resolution*params.height, 1, IMAGE_R8G8B8A8)
  514. && map .createSoftTry(image.w(), image.h(), 1, IMAGE_F32 )
  515. && dist_map.createSoftTry(image.w(), image.h(), 1, IMAGE_F32_4))
  516. {
  517. REPA(params.lights)
  518. {
  519. light_dir [i]=Matrix3().setRotateY(Sat(params.lights[i].angle.length())*PI_2).rotateZ(-Angle(params.lights[i].angle)).z;
  520. light_dir_neg[i]=-light_dir[i];
  521. }
  522. image_size=image.size(); image_size1=image_size-1; image_size_2i=image_size/2; image_size_2=image_size*0.5f;
  523. smooth_depth=params.smooth_depth;
  524. corner_size=resolution*0.5f*params.round_corners;
  525. REPAO(sps).setParams(params.sections[i], resolution, threads); sps[0].setSize(1-params.sections[1].size, 0);
  526. Flt offset=0, offset_top=0;
  527. REPA(sps) // go from the end
  528. {
  529. sps[i].setOffset(offset, offset_top, resolution, image.w(), image.h());
  530. offset +=sps[i].size ;
  531. offset_top+=sps[i].size_top;
  532. }
  533. top_offset=-(last.size_top-last.size)*0.5f*resolution;
  534. color_top =params.color_top .asVec4()*params.color.asVec4();
  535. color_bottom=params.color_bottom.asVec4()*params.color.asVec4();
  536. color_left =params.color_left .asVec4();
  537. color_right =params.color_right .asVec4();
  538. inner_glow_color =params.inner_glow_color.asVec4();
  539. Flt cut_corner_amount=params.cut_corner_amount*0.5f*resolution, cut_corner_slope=Max(0, params.cut_corner_slope);
  540. corner_line[0][0].pos.set( 0, 0+cut_corner_amount); corner_line[0][0].normal.set( 1, cut_corner_slope);
  541. corner_line[0][1].pos.set(image_size1.x, 0+cut_corner_amount); corner_line[0][1].normal.set(-1, cut_corner_slope);
  542. corner_line[1][0].pos.set( 0, image_size1.y-cut_corner_amount); corner_line[1][0].normal.set( 1, -cut_corner_slope);
  543. corner_line[1][1].pos.set(image_size1.x, image_size1.y-cut_corner_amount); corner_line[1][1].normal.set(-1, -cut_corner_slope);
  544. Bool line_on=(cut_corner_amount>0.5f);
  545. REPD(y, 2)
  546. REPD(x, 2)corner_line[y][x].finalize(line_on && params.cut_corners[y][x]);
  547. side_line[0].pos.set(0, (params.left_slope<0) ? 0 : image_size1.y); side_line[0].normal.set(1, params.left_slope/params.height);
  548. side_line[0].finalize(!Equal(params.left_slope, 0));
  549. side_line[1].pos.set(image_size1.x, (params.right_slope<0) ? 0 : image_size1.y); side_line[1].normal.set(-1, params.right_slope/params.height);
  550. side_line[1].finalize(!Equal(params.right_slope, 0));
  551. if(params.cut_top ) REPD(x, 2)corner_line[0][x].on=false;
  552. if(params.cut_bottom) REPD(x, 2)corner_line[1][x].on=false;
  553. if(params.cut_left ){REPD(y, 2)corner_line[y][0].on=false; side_line[0].on=false;}
  554. if(params.cut_right ){REPD(y, 2)corner_line[y][1].on=false; side_line[1].on=false;}
  555. top_image=getImage(params. top_image);
  556. bottom_image=getImage(params. bottom_image);
  557. center_image=getImage(params. center_image);
  558. left_image=getImage(params. left_image);
  559. right_image=getImage(params. right_image);
  560. top_left_image=getImage(params. top_left_image);
  561. top_right_image=getImage(params. top_right_image);
  562. bottom_left_image=getImage(params. bottom_left_image);
  563. bottom_right_image=getImage(params.bottom_right_image);
  564. // following bottom-right coordinates are exclusive
  565. Flt mul=0.5f*resolution*params.images_size;
  566. x3=image_size.x; // don't subtract one because here the right coordinate is exclusive
  567. y3=image_size.y; // don't subtract one because here the bottom coordinate is exclusive
  568. y1=Min( Round(params. top_height*mul), image_size_2.y);
  569. y2=Max(y3-Round(params. bottom_height*mul), image_size_2.y);
  570. x1=Min( Round(params. left_right_width *mul), image_size_2.x);
  571. x2=Max(x3-Round(params. left_right_width *mul), image_size_2.x);
  572. top_x1=Min( Round(params. top_corner_width *mul), image_size_2.x);
  573. top_x2=Max(x3-Round(params. top_corner_width *mul), image_size_2.x);
  574. bottom_x1=Min( Round(params.bottom_corner_width *mul), image_size_2.x);
  575. bottom_x2=Max(x3-Round(params.bottom_corner_width *mul), image_size_2.x);
  576. GetFracMulAddFromImage( 0, top_x1, 0, y1, top_left_image, image_frac_mul_add[0][0], top_left_image==top_right_image);
  577. GetFracMulAddFromImage( top_x1, top_x2, 0, y1, top_image, image_frac_mul_add[1][0]);
  578. GetFracMulAddFromImage( top_x2, x3, 0, y1, top_right_image, image_frac_mul_add[2][0]);
  579. GetFracMulAddFromImage( 0, x1, y1, y2, left_image, image_frac_mul_add[0][1], left_image==right_image);
  580. GetFracMulAddFromImage( x1, x2, y1, y2, center_image, image_frac_mul_add[1][1]);
  581. GetFracMulAddFromImage( x2, x3, y1, y2, right_image, image_frac_mul_add[2][1]);
  582. GetFracMulAddFromImage( 0, bottom_x1, y2, y3, bottom_left_image, image_frac_mul_add[0][2], bottom_left_image==bottom_right_image, bottom_left_image==top_left_image);
  583. GetFracMulAddFromImage(bottom_x1, bottom_x2, y2, y3, bottom_image, image_frac_mul_add[1][2], false, bottom_image==top_image);
  584. GetFracMulAddFromImage(bottom_x2, x3, y2, y3, bottom_right_image, image_frac_mul_add[2][2], false, bottom_right_image==top_right_image);
  585. Flt tex=0, tex_top;
  586. // set section #0
  587. if(params.sections[0].outer_border_color.a)MAX(tex, params.border_size );
  588. if(params.sections[0].inner_border_color.a)MAX(tex, params.border_size*2);
  589. if(params.depth && !Equal(params.sections[0].outer_depth, params.sections[0].inner_depth))MAX(tex, params.sections[0].inner_distance);
  590. // add section #1
  591. tex+=sps[1].size;
  592. // globals affected by 'top_offset'
  593. MAX(tex, params.round_corners);
  594. // calculate
  595. tex*=0.5f*resolution;
  596. tex_top=tex-top_offset;
  597. // globals unaffected by 'top_offset'
  598. Flt global=0;
  599. if(!Equal(params.depth, 0) )MAX(global, params.inner_distance );
  600. if(params.inner_glow_color.a)MAX(global, params.inner_glow_radius);
  601. global*=0.5f*resolution;
  602. MAX(tex , global);
  603. MAX(tex_top, global);
  604. // set to tex
  605. REPAD(y, panel_image._tex_x)REPAD(x, panel_image._tex_x[y])panel_image._tex_x[y][x]=(x ? image_size.x-tex : tex);
  606. panel_image._tex_y[0]= tex_top;
  607. panel_image._tex_y[1]=image_size.y-tex;
  608. // tex values based on image presence
  609. if( top_left_image || top_image)MAX(panel_image._tex_x[0][0], top_x1); // any of these images require 'top_x1'
  610. if( top_right_image || top_image)MIN(panel_image._tex_x[0][1], top_x2); // any of these images require 'top_x2'
  611. if( left_image || center_image)MAX(panel_image._tex_x[1][0], x1); // any of these images require 'x1'
  612. if( right_image || center_image)MIN(panel_image._tex_x[1][1], x2); // any of these images require 'x2'
  613. if( bottom_left_image || bottom_image)MAX(panel_image._tex_x[2][0], bottom_x1); // any of these images require 'bottom_x1'
  614. if(bottom_right_image || bottom_image)MIN(panel_image._tex_x[2][1], bottom_x2); // any of these images require 'bottom_x2'
  615. if( top_left_image || top_image || top_right_image
  616. || left_image || center_image || right_image)MAX(panel_image._tex_y[0], y1); // any of these images require 'y1'
  617. if(bottom_left_image || bottom_image || bottom_right_image
  618. || left_image || center_image || right_image)MIN(panel_image._tex_y[1], y2); // any of these images require 'y2'
  619. Flt tex_ofs=(0.5f+(super_sample>1))*super_sample; // if we're doing super-sampling then it means we'll have to down-sample the image later, this means we'll be getting neighbor pixels, so we need to padd more
  620. alignTex();
  621. // lines
  622. Bool include_size_mid[]={false, false};
  623. Flt l=image_size.x, r=0;
  624. REPD(y, 3)
  625. {
  626. MIN(l, panel_image._tex_x[y][0]);
  627. MAX(r, panel_image._tex_x[y][1]);
  628. }
  629. REPD(y, 2)
  630. {
  631. C Line &l0=corner_line[y][0]; if(l0.on)
  632. {
  633. Vec2 n=l0.normal; if(y)n.y--;else n.y++; n/=Abs(n.y); Flt lt=n.x*tex; // line.normal+Vec2(0, 1)
  634. MAX(l, l0.xAtY( 0)+lt);
  635. MAX(l, l0.xAtY(image_size1.y)+lt);
  636. }
  637. C Line &l1=corner_line[y][1]; if(l1.on)
  638. {
  639. Vec2 n=l1.normal; if(y)n.y--;else n.y++; n/=Abs(n.y); Flt rt=n.x*tex; // line.normal+Vec2(0, 1)
  640. MIN(r, l1.xAtY( 0)+rt);
  641. MIN(r, l1.xAtY(image_size1.y)+rt);
  642. }
  643. }
  644. if(side_line[0].on)
  645. {
  646. Vec2 n=side_line[0].normal; if(n.y>0)n.y++;else n.y--; n/=Abs(n.y); Flt t=n.x*tex; // normal+Vec2(0, 1)
  647. MAX(l, side_line[0].xAtY( 0)+t);
  648. MAX(l, side_line[0].xAtY(image_size1.y)+t);
  649. }
  650. if(side_line[1].on)
  651. {
  652. Vec2 n=side_line[1].normal; if(n.y>0)n.y++;else n.y--; n/=Abs(n.y); Flt t=n.x*tex; // normal+Vec2(0, 1)
  653. MIN(r, side_line[1].xAtY( 0)+t);
  654. MIN(r, side_line[1].xAtY(image_size1.y)+t);
  655. }
  656. if(l+tex_ofs<r)REPD(y, 3)
  657. {
  658. MAX(panel_image._tex_x[y][0], l);
  659. MIN(panel_image._tex_x[y][1], r);
  660. }else include_size_mid[0]=true; // if lines overlap then we need to force middle part in the size calculation
  661. Flt t=panel_image._tex_y[0], b=panel_image._tex_y[1];
  662. REPD(x, 2)
  663. {
  664. C Line &l0=corner_line[0][x]; if(l0.on)
  665. {
  666. Vec2 n=l0.normal; if(x)n.x--;else n.x++; n/=Abs(n.x); Flt tt=n.y*tex; // line.normal+Vec2(1, 0)
  667. MAX(t, l0.yAtX( 0)+tt);
  668. MAX(t, l0.yAtX(image_size1.x)+tt);
  669. }
  670. C Line &l1=corner_line[1][x]; if(l1.on)
  671. {
  672. Vec2 n=l1.normal; if(x)n.x--;else n.x++; n/=Abs(n.x); Flt bt=n.y*tex; // line.normal+Vec2(1, 0)
  673. MIN(b, l1.yAtX( 0)+bt);
  674. MIN(b, l1.yAtX(image_size1.x)+bt);
  675. }
  676. }
  677. if(t+tex_ofs<b)
  678. {
  679. MAX(panel_image._tex_y[0], t);
  680. MIN(panel_image._tex_y[1], b);
  681. }else include_size_mid[1]=true; // if lines overlap then we need to force middle part in the size calculation
  682. if(params.force_uniform_stretch[0])REPAD(y, panel_image._tex_x)
  683. {
  684. panel_image._tex_x[y][0]=0;
  685. panel_image._tex_x[y][1]=image_size.x;
  686. }
  687. if(params.force_uniform_stretch[1])
  688. {
  689. panel_image._tex_y[0]=0;
  690. panel_image._tex_y[1]=image_size.y;
  691. }
  692. // align, offset and scale
  693. alignTex();
  694. REPAD(y, panel_image._tex_x)
  695. {
  696. if(!Equal(panel_image._tex_x[y][0], 0))panel_image._tex_x[y][0]+=tex_ofs;
  697. if(!Equal(panel_image._tex_x[y][1], image_size.x))panel_image._tex_x[y][1]-=tex_ofs;
  698. REPAD(x, panel_image._tex_x[y])panel_image._tex_x[y][x]/=image_size.x;
  699. if(panel_image._tex_x[y][0]>panel_image._tex_x[y][1])panel_image._tex_x[y][0]=panel_image._tex_x[y][1]=Avg(panel_image._tex_x[y][0], panel_image._tex_x[y][1]);
  700. }
  701. if(!Equal(panel_image._tex_y[0], 0))panel_image._tex_y[0]+=tex_ofs;
  702. if(!Equal(panel_image._tex_y[1], image_size.y))panel_image._tex_y[1]-=tex_ofs;
  703. REPAO(panel_image._tex_y)/=image_size.y;
  704. if(panel_image._tex_y[0]>panel_image._tex_y[1])panel_image._tex_y[0]=panel_image._tex_y[1]=Avg(panel_image._tex_y[0], panel_image._tex_y[1]);
  705. max_scale=Max(params.max_side_stretch, 0);
  706. panel_image._same_x=true; REPAD(x, panel_image._tex_x[0])if(!Equal(panel_image._tex_x[0][x], panel_image._tex_x[1][x]) || !Equal(panel_image._tex_x[1][x], panel_image._tex_x[2][x]))panel_image._same_x=false;
  707. panel_image._tex_left_top=0;
  708. panel_image._tex_right_bottom=1;
  709. Flt mulx =params.width * max_scale,
  710. muly =params.height* max_scale;
  711. Vec2 extend=params.extend*(max_scale*0.5f);
  712. panel_image._size_y[0]= panel_image._tex_y[0] *muly-extend.y;
  713. panel_image._size_y[1]=(1-panel_image._tex_y[1])*muly-extend.y;
  714. REPAD(y, panel_image._size_x)
  715. {
  716. panel_image._size_x[y][0]= panel_image._tex_x[y][0] *mulx-extend.x;
  717. panel_image._size_x[y][1]=(1-panel_image._tex_x[y][1])*mulx-extend.x;
  718. }
  719. if(include_size_mid[0])panel_image._side_size.x=mulx;else{panel_image._side_size.x=0; REPAD(y, panel_image._size_x)MAX(panel_image._side_size.x, Max(panel_image._size_x[y][0], 0)+Max(panel_image._size_x[y][1], 0));}
  720. if(include_size_mid[1])panel_image._side_size.y=muly;else panel_image._side_size.y=Max(panel_image._size_y[0], 0)+Max(panel_image._size_y[1], 0);
  721. REPAO(sps).setDepthNoise(params.sections[i], image.w(), image.h(), super_sample, threads);
  722. return true;
  723. }
  724. panel_image.del(); return false;
  725. }
  726. void setDepthY(Int y)
  727. {
  728. REPD(x, map.w())
  729. {
  730. Vec2 pos(x, y);
  731. Flt dist_x=FLT_MAX, dist_y=FLT_MAX, dist_global=FLT_MAX, dist_sect=FLT_MAX, dist_depth=0.5f, dist_depth_sect=0.5f, d;
  732. d= pos.x /resolution; MIN(dist_global, d); MIN(dist_sect, d); MIN(dist_x, d); if(!params.cut_left ){MIN(dist_depth, d); MIN(dist_depth_sect, d);}
  733. d= pos.y /resolution; MIN(dist_global, d); MIN(dist_y, d); if(!params.cut_top ){MIN(dist_depth, d); }
  734. d=(image_size1.x-pos.x)/resolution; MIN(dist_global, d); MIN(dist_sect, d); MIN(dist_x, d); if(!params.cut_right ){MIN(dist_depth, d); MIN(dist_depth_sect, d);}
  735. d=(image_size1.y-pos.y)/resolution; MIN(dist_global, d); MIN(dist_sect, d); MIN(dist_y, d); if(!params.cut_bottom){MIN(dist_depth, d); MIN(dist_depth_sect, d);}
  736. d=( top_offset+pos.y)/resolution; MIN(dist_sect, d); if(!params.cut_top ){ MIN(dist_depth_sect, d);}
  737. REPD(y, 2)
  738. REPD(x, 2)
  739. {
  740. C Line &line=corner_line[y][x]; if(line.on)
  741. {
  742. d=DistPointPlane(pos, line.pos, line.normal)/resolution;
  743. MIN(dist_global, d); MIN(dist_sect, d); MIN(dist_depth, d); MIN(dist_depth_sect, d);
  744. }
  745. }
  746. REPD(x, 2)
  747. {
  748. C Line &line=side_line[x]; if(line.on)
  749. {
  750. d=DistPointPlane(pos, line.pos, line.normal)/resolution;
  751. MIN(dist_global, d); MIN(dist_sect, d); MIN(dist_depth, d); MIN(dist_depth_sect, d);
  752. }
  753. }
  754. if(corner_size.max()>0.5f)
  755. {
  756. Vec2 corner;
  757. if(!params.cut_top && !params.cut_left) // top left
  758. {
  759. corner.set(corner_size.x, corner_size.y);
  760. Bool cx=(pos.x<corner.x), cy=(pos.y<corner.y);
  761. if(cx && cy){d=(-Dist(pos, corner)+corner_size.x)/resolution; MIN(dist_global, d); MIN(dist_depth, d);}
  762. if(cx ){Flt y=(1-CosSin(1-pos.x/corner_size.x))*corner_size.y; d=(pos.y-y)/resolution; MIN(dist_y, d);}
  763. if( cy){Flt x=(1-CosSin(1-pos.y/corner_size.y))*corner_size.x; d=(pos.x-x)/resolution; MIN(dist_x, d);}
  764. if(cx){corner.y-=top_offset; cy=(pos.y<corner.y); if(cy){d=(-Dist(pos, corner)+corner_size.x)/resolution; MIN(dist_sect, d); MIN(dist_depth_sect, d);}}
  765. }
  766. if(!params.cut_top && !params.cut_right) // top right
  767. {
  768. corner.set(image_size1.x-corner_size.x, corner_size.y);
  769. Bool cx=(pos.x>corner.x), cy=(pos.y<corner.y);
  770. if(cx && cy){d=(-Dist(pos, corner)+corner_size.x)/resolution; MIN(dist_global, d); MIN(dist_depth, d);}
  771. if(cx ){Flt y= (1-CosSin((corner.x-pos.x)/corner_size.x))*corner_size.y; d=(pos.y-y)/resolution; MIN(dist_y, d);}
  772. if( cy){Flt x=corner.x+CosSin( 1-pos.y /corner_size.y) *corner_size.x; d=(x-pos.x)/resolution; MIN(dist_x, d);}
  773. if(cx){corner.y-=top_offset; cy=(pos.y<corner.y); if(cy){d=(-Dist(pos, corner)+corner_size.x)/resolution; MIN(dist_sect, d); MIN(dist_depth_sect, d);}}
  774. }
  775. if(!params.cut_bottom && !params.cut_left) // bottom left
  776. {
  777. corner.set(corner_size.x, image_size1.y-corner_size.y);
  778. Bool cx=(pos.x<corner.x), cy=(pos.y>corner.y);
  779. if(cx && cy){d=(-Dist(pos, corner)+corner_size.x)/resolution; MIN(dist_global, d); MIN(dist_sect, d); MIN(dist_depth, d); MIN(dist_depth_sect, d);}
  780. if(cx ){Flt y=corner.y+CosSin( 1-pos.x /corner_size.x) *corner_size.y; d=(y-pos.y)/resolution; MIN(dist_y, d);}
  781. if( cy){Flt x= (1-CosSin((corner.y-pos.y)/corner_size.y))*corner_size.x; d=(pos.x-x)/resolution; MIN(dist_x, d);}
  782. }
  783. if(!params.cut_bottom && !params.cut_right) // bottom right
  784. {
  785. corner.set(image_size1.x-corner_size.x, image_size1.y-corner_size.y);
  786. Bool cx=(pos.x>corner.x), cy=(pos.y>corner.y);
  787. if(cx && cy){d=(-Dist(pos, corner)+corner_size.x)/resolution; MIN(dist_global, d); MIN(dist_sect, d); MIN(dist_depth, d); MIN(dist_depth_sect, d);}
  788. if(cx ){Flt y=corner.y+CosSin((corner.x-pos.x)/corner_size.x)*corner_size.y; d=(y-pos.y)/resolution; MIN(dist_y, d);}
  789. if( cy){Flt x=corner.x+CosSin((corner.y-pos.y)/corner_size.y)*corner_size.x; d=(x-pos.x)/resolution; MIN(dist_x, d);}
  790. }
  791. }
  792. // 'dist_global' is now -Inf .. 0.5
  793. Flt depth;
  794. if(dist_global>=0) // 'dist_depth' is now 0 .. 0.5
  795. {
  796. dist_x *=2 ; // 'dist_x' is now 0 .. width
  797. dist_y *=2 ; // 'dist_y' is now 0 .. height
  798. dist_global *=2 ; // 'dist_global' is now 0 ..
  799. dist_sect *=2 ; // 'dist_sect' is now 0 ..
  800. SAT(dist_depth *=2); // 'dist_depth' is now 0 .. 1.0
  801. SAT(dist_depth_sect*=2); // 'dist_depth_sect' is now 0 .. 1.0
  802. Int section_i=(dist_sect<sps[1].size);
  803. C SectionParams &sp = sps [section_i];
  804. C PanelImageParams::Section &section =params.sections[section_i];
  805. Flt global_depth, frac=(params.inner_distance ? Sat(dist_depth/params.inner_distance) : 1);
  806. global_depth=Lerp(frac, CosSin(1-frac), params.round_depth); // first apply round, because it needs depth in 0..1 range
  807. global_depth*=params.depth;
  808. Flt dist=(section_i ? dist_depth : dist_depth_sect-sps[1].size), // we need to use 'dist_depth' for section #1 because of 'top_size'
  809. dist_frac=(sp.size ? dist/sp.size : 1), section_depth;
  810. if(dist_frac<section.inner_distance)
  811. {
  812. frac=dist_frac/section.inner_distance;
  813. frac=Lerp(frac, CosSin(1-frac), section.round_depth); // first apply round, because it needs depth in 0..1 range
  814. section_depth=(section_i ? Lerp(0.0f, section.outer_depth, frac) : Lerp(section.outer_depth, section.inner_depth, frac));
  815. }else
  816. {
  817. frac=LerpRS(section.inner_distance, 1.0f, dist_frac);
  818. frac=Lerp(frac, 1-CosSin(frac), section.round_depth); // first apply round, because it needs depth in 0..1 range
  819. section_depth=(section_i ? Lerp(section.outer_depth, section.inner_depth, frac) : section.inner_depth);
  820. }
  821. depth=global_depth*section_depth;
  822. // apply smooth depth
  823. REP(2) // section and global
  824. {
  825. C SmoothDepth &sd =(i ? sp.smooth_depth : smooth_depth );
  826. C Vec2 &norm_mul=(i ? sp.norm_mul : full_norm_mul),
  827. &norm_add=(i ? sp.norm_add : full_norm_add);
  828. REPA(sd.is)if(sd.is[i]) // axis X and Y
  829. {
  830. Flt center=pos.c[i]*norm_mul.c[i]+norm_add.c[i];
  831. if(i==0)
  832. {
  833. if(pos.y<corner_size.y && !params.cut_top)
  834. {
  835. if((x>image_size_2i.x) ? !params.cut_right : !params.cut_left)
  836. {
  837. Flt x=(1-CosSin(1-pos.y/corner_size.y))*corner_size.x; x=image_size_2.x/(image_size_2.x-x);
  838. center*=Lerp(1.0f, x, sd.sqr.y); // make this adjustment smaller if the other axis is disabled
  839. }
  840. }else
  841. if(pos.y>image_size1.y-corner_size.y && !params.cut_bottom)
  842. {
  843. if((x>image_size_2i.x) ? !params.cut_right : !params.cut_left)
  844. {
  845. Flt x=(1-CosSin(1-(image_size1.y-pos.y)/corner_size.y))*corner_size.x; x=image_size_2.x/(image_size_2.x-x);
  846. center*=Lerp(1.0f, x, sd.sqr.y); // make this adjustment smaller if the other axis is disabled
  847. }
  848. }
  849. }else
  850. {
  851. if(pos.x<corner_size.x && !params.cut_left)
  852. {
  853. if((y>image_size_2i.y) ? !params.cut_bottom : !params.cut_top)
  854. {
  855. Flt y=(1-CosSin(1-pos.x/corner_size.x))*corner_size.y; y=image_size_2.y/(image_size_2.y-y);
  856. center*=Lerp(1.0f, y, sd.sqr.x); // make this adjustment smaller if the other axis is disabled
  857. }
  858. }else
  859. if(pos.x>image_size1.x-corner_size.x && !params.cut_right)
  860. {
  861. if((y>image_size_2i.y) ? !params.cut_bottom : !params.cut_top)
  862. {
  863. Flt y=(1-CosSin(1-(image_size1.x-pos.x)/corner_size.x))*corner_size.y; y=image_size_2.y/(image_size_2.y-y);
  864. center*=Lerp(1.0f, y, sd.sqr.x); // make this adjustment smaller if the other axis is disabled
  865. }
  866. }
  867. }
  868. depth*=CosSin(center*sd.val.c[i]);
  869. }
  870. }
  871. // apply depth overlay
  872. if(sp.overlay)
  873. {
  874. Vec4 ovr=sp.overlay->colorFCubicFast(x*sp.overlay_uv_scale+sp.overlay_uv_offset.x,
  875. y*sp.overlay_uv_scale+sp.overlay_uv_offset.y, false);
  876. ovr.xyz=ovr.xyz.max();
  877. ovr.w *=sp.overlay_intensity;
  878. switch(section.depth_overlay_params.mode)
  879. {
  880. case PanelImageParams::ImageParams::MULTIPLY : depth*=Lerp (1.0f, ovr.x, ovr.w); break;
  881. case PanelImageParams::ImageParams::SCALE : depth*=ScaleFactor((ovr.x-0.5f)*ovr.w); break;
  882. case PanelImageParams::ImageParams::ADD : depth+= ovr.x *ovr.w ; break;
  883. case PanelImageParams::ImageParams::ADD_SIGNED: depth+= (ovr.x-0.5f)*ovr.w ; break;
  884. case PanelImageParams::ImageParams::BLEND : depth =Blend(Vec4(depth, depth, depth, 1), ovr).x; break;
  885. }
  886. }
  887. // apply depth noise
  888. if(sp.noise_map.is())
  889. {
  890. Flt noise=sp.noise_map.pixelFCubicFast(x*sp.noise_uv_scale, y*sp.noise_uv_scale, false);
  891. switch(section.depth_noise.mode)
  892. {
  893. case PanelImageParams::ImageParams::MULTIPLY : depth*=Lerp (1.0f, noise, sp.noise_intensity); break;
  894. case PanelImageParams::ImageParams::SCALE : depth*=ScaleFactor((noise-0.5f)*sp.noise_intensity); break;
  895. case PanelImageParams::ImageParams::ADD : depth+= noise *sp.noise_intensity ; break;
  896. case PanelImageParams::ImageParams::ADD_SIGNED: depth+= (noise-0.5f)*sp.noise_intensity ; break;
  897. case PanelImageParams::ImageParams::BLEND : depth =Blend(Vec4(depth, depth, depth, 1), Vec4(noise, noise, noise, sp.noise_intensity)).x; break;
  898. }
  899. }
  900. }else depth=0;
  901. #if DEBUG
  902. if(Kb.b(KB_V))depth=dist_depth_sect;
  903. #endif
  904. map.pixF (x, y)=depth;
  905. dist_map.pixF4(x, y).set(dist_x, dist_y, dist_global, dist_sect);
  906. }
  907. }
  908. void afterDepth()
  909. {
  910. if(depth_map)Swap(*depth_map, map);
  911. (depth_map ? *depth_map : map).bumpToNormal(map, resolution, true);
  912. REPA(sps)
  913. {
  914. sps[i].setColorOverlay(params.sections[i], resolution, threads);
  915. sps[i].setColorNoise (params.sections[i], image_size.x, image_size.y, super_sample, threads);
  916. }
  917. }
  918. void setColorY(Int y)
  919. {
  920. Flt frac_y=y*full_frac_mul.y/*+full_frac_add.y*/; // 0..1, 'full_frac_add' is always zero
  921. Vec4 color_y=Lerp(color_top, color_bottom, frac_y);
  922. Flt image_frac_y[3][3];
  923. Vec4 section_color_y[ELMS(params.sections)];
  924. REPD(sy, 3)
  925. REPD(sx, 3)image_frac_y[sx][sy]=y*image_frac_mul_add[sx][sy].z+image_frac_mul_add[sx][sy].w;
  926. REPA(sps)
  927. {
  928. Flt section_frac_y=y*sps[i].frac_mul.y+sps[i].frac_add.y;
  929. sps[i].setColorY(section_frac_y, color_y, section_color_y[i]);
  930. }
  931. REPD(x, image_size.x)
  932. {
  933. Vec4 col =0;
  934. C Vec4 &dist4 =dist_map.pixF4(x, y);
  935. Flt dist_global =dist4.z;
  936. if( dist_global>=0)
  937. {
  938. Flt dist_x =dist4.x, dist_y=dist4.y, dist_sect=dist4.w;
  939. Vec4 nrm_d =map.pixF4(x, y);
  940. Flt depth =nrm_d.w;
  941. C Vec &nrm =nrm_d.xyz;
  942. Int section_i=(dist_sect<sps[1].size);
  943. C SectionParams &sp = sps [section_i];
  944. C PanelImageParams::Section &section=params.sections[section_i];
  945. if(!section_i)dist_sect-=sps[1].size;
  946. Flt dist=(section_i ? dist_global : dist_sect), dist_frac=(sp.size ? Sat(dist/sp.size) : 1); // we need to use 'dist_global' for section #1 because of 'top_size', we need to use 'Sat' because of 'top_size'
  947. Flt frac_x=x*full_frac_mul.x/*+full_frac_add.x*/, // 0..1, 'full_frac_add' is always zero
  948. section_frac_x=x*sp.frac_mul.x+sp.frac_add.x;
  949. Vec4 color_x=Lerp(color_left, color_right, frac_x);
  950. col=section_color_y[section_i]*color_x*Lerp(sp.color_left, sp.color_right, section_frac_x)*Lerp(sp.outer_color, sp.inner_color, dist_frac);
  951. // apply color overlay
  952. if(sp.overlay)
  953. {
  954. Vec2 tex(x, y); tex*=sp.overlay_uv_scale; tex+=sp.overlay_uv_offset;
  955. if(sp.overlay_uv_warp){Vec2 n=nrm.xy; n.setLength(1-CosSin(n.length())); tex+=sp.overlay_uv_warp*n;}
  956. Vec4 ovr=sp.overlay->colorFCubicFast(tex.x, tex.y, false);
  957. switch(section.color_overlay_params.mode)
  958. {
  959. case PanelImageParams::ImageParams::MULTIPLY : col *=Lerp (Vec4(1) , ovr , sp.overlay_intensity ); break;
  960. case PanelImageParams::ImageParams::SCALE : col.xyz*=ScaleFactor((ovr.xyz-0.5f)*(ovr.w*sp.overlay_intensity)); break;
  961. case PanelImageParams::ImageParams::ADD : col.xyz+= ovr.xyz *(ovr.w*sp.overlay_intensity) ; break;
  962. case PanelImageParams::ImageParams::ADD_SIGNED: col.xyz+= (ovr.xyz-0.5f)*(ovr.w*sp.overlay_intensity) ; break;
  963. case PanelImageParams::ImageParams::BLEND : ovr.w *=sp.overlay_intensity; col=Blend(col, ovr); break;
  964. }
  965. }
  966. // apply color noise
  967. if(sp.noise_map.is())
  968. {
  969. Vec2 tex(x, y); tex*=sp.noise_uv_scale;
  970. if(sp.noise_uv_warp){Vec2 n=nrm.xy; n.setLength(1-CosSin(n.length())); tex+=sp.noise_uv_warp*n;}
  971. Flt noise=sp.noise_map.pixelFCubicFast(tex.x, tex.y, false);
  972. switch(section.color_noise.mode)
  973. {
  974. case PanelImageParams::ImageParams::MULTIPLY : col.xyz*=Lerp (1.0f, noise, sp.noise_intensity); break;
  975. case PanelImageParams::ImageParams::SCALE : col.xyz*=ScaleFactor((noise-0.5f)*sp.noise_intensity); break;
  976. case PanelImageParams::ImageParams::ADD : col.xyz+= noise *sp.noise_intensity ; break;
  977. case PanelImageParams::ImageParams::ADD_SIGNED: col.xyz+= (noise-0.5f)*sp.noise_intensity ; break;
  978. case PanelImageParams::ImageParams::BLEND : col.xyz =Blend(col, Vec4(noise, noise, noise, sp.noise_intensity)).xyz; break;
  979. }
  980. }
  981. // apply 3x3 images
  982. if(y<y1)
  983. {
  984. if(x<top_x1){if( top_left_image)col*= top_left_image->colorFCubicFast(x*image_frac_mul_add[0][0].x+image_frac_mul_add[0][0].y, image_frac_y[0][0], true, true);}else
  985. if(x<top_x2){if( top_image)col*= top_image->colorFCubicFast(x*image_frac_mul_add[1][0].x+image_frac_mul_add[1][0].y, image_frac_y[1][0], true, true);}else
  986. {if(top_right_image)col*=top_right_image->colorFCubicFast(x*image_frac_mul_add[2][0].x+image_frac_mul_add[2][0].y, image_frac_y[2][0], true, true);}
  987. }else
  988. if(y<y2)
  989. {
  990. if(x<x1){if( left_image)col*= left_image->colorFCubicFast(x*image_frac_mul_add[0][1].x+image_frac_mul_add[0][1].y, image_frac_y[0][1], true, true);}else
  991. if(x<x2){if(center_image)col*=center_image->colorFCubicFast(x*image_frac_mul_add[1][1].x+image_frac_mul_add[1][1].y, image_frac_y[1][1], true, true);}else
  992. {if( right_image)col*= right_image->colorFCubicFast(x*image_frac_mul_add[2][1].x+image_frac_mul_add[2][1].y, image_frac_y[2][1], true, true);}
  993. }else
  994. {
  995. if(x<bottom_x1){if( bottom_left_image)col*= bottom_left_image->colorFCubicFast(x*image_frac_mul_add[0][2].x+image_frac_mul_add[0][2].y, image_frac_y[0][2], true, true);}else
  996. if(x<bottom_x2){if( bottom_image)col*= bottom_image->colorFCubicFast(x*image_frac_mul_add[1][2].x+image_frac_mul_add[1][2].y, image_frac_y[1][2], true, true);}else
  997. {if(bottom_right_image)col*=bottom_right_image->colorFCubicFast(x*image_frac_mul_add[2][2].x+image_frac_mul_add[2][2].y, image_frac_y[2][2], true, true);}
  998. }
  999. // calculate light and specular
  1000. Flt light=params.light_ambient, specular=0;
  1001. REPA(params.lights)if(params.lights[i].enabled)
  1002. {
  1003. Flt dot=Dot(light_dir[i], nrm);
  1004. if( dot>0)light+=params.lights[i].intensity*dot;
  1005. else light-=params.lights[i].back *dot;
  1006. light+=(dot>params.lights[i].highlight_cut)*params.lights[i].highlight;
  1007. Flt spec_base=LightSpecularBase(nrm, light_dir [i], VecDir[DIR_FORWARD]);
  1008. specular+= LightSpecular (nrm, light_dir_neg[i], VecDir[DIR_FORWARD], params.lights[i].specular_exp )*params.lights[i].specular_back ;
  1009. specular+= Pow(spec_base, params.lights[i].specular_exp )*params.lights[i].specular ;
  1010. specular+= (spec_base> params.lights[i].specular_highlight_cut)*params.lights[i].specular_highlight;
  1011. }
  1012. specular*=section.specular;
  1013. // apply light
  1014. MAX(light, 0);
  1015. col.xyz*=light;
  1016. // apply reflection
  1017. if(sp.reflection)
  1018. {
  1019. #define FACE_LEFT 0
  1020. #define FACE_FRONT 1
  1021. #define FACE_RIGHT 2
  1022. #define FACE_BACK 3
  1023. #define FACE_DOWN 4
  1024. #define FACE_UP 5
  1025. Vec dir=Reflect(VecDir[DIR_BACK], nrm);
  1026. CHS(dir.x); CHS(dir.z); // make FACE_FRONT to be visible by default
  1027. #if DEBUG
  1028. if(Kb.b(KB_R))dir*=Matrix().setRotateY(Time.appTime());
  1029. #endif
  1030. dir/=Abs(dir).max();
  1031. Int face=0;
  1032. switch(Abs(dir).maxI())
  1033. {
  1034. case 0: face=((dir.x<0) ? FACE_LEFT : FACE_RIGHT); break;
  1035. case 1: face=((dir.y<0) ? FACE_DOWN : FACE_UP ); break;
  1036. case 2: face=((dir.z<0) ? FACE_BACK : FACE_FRONT); break;
  1037. }
  1038. Vec2 uv;
  1039. switch(face)
  1040. {
  1041. case FACE_LEFT : uv.set( dir.z, -dir.y); break;
  1042. case FACE_FRONT: uv.set( dir.x, -dir.y); break;
  1043. case FACE_RIGHT: uv.set(-dir.z, -dir.y); break;
  1044. case FACE_BACK : uv.set(-dir.x, -dir.y); break;
  1045. case FACE_DOWN : uv.set( dir.x, -dir.z); break;
  1046. case FACE_UP : uv.set( dir.x, dir.z); break;
  1047. }
  1048. uv=(uv*0.5f+0.5f)*sp.reflection->h();
  1049. if(!sp.reflection_one)uv.x+=sp.reflection->h()*face;
  1050. Vec tex=sp.reflection->colorFCubicFast(uv.x, uv.y).xyz;
  1051. col=AdditiveBlend(col, Vec4(tex, section.reflection_intensity));
  1052. }
  1053. // apply inner glow
  1054. if(params.inner_glow_color.a && params.inner_glow_radius>0 && dist_global>=0 && dist_global<params.inner_glow_radius) // glow
  1055. {
  1056. Flt d=dist_global, x=params.inner_glow_radius-dist_x, y=params.inner_glow_radius-dist_y;
  1057. // this increases glow in square corners
  1058. if(x>=0 && y>=0) // only in corners (this may process circular corners too)
  1059. if(Equal(dist_x, dist_global)
  1060. || Equal(dist_y, dist_global)) // allow only square corners
  1061. MIN(d, Max(0, params.inner_glow_radius-Dist(x, y)));
  1062. Flt g=1-d/params.inner_glow_radius;
  1063. Vec4 glow=inner_glow_color; glow.w*=g; col=Blend(col, glow);
  1064. }
  1065. // apply specular, do this after inner glow, so that can be used for inner shadowing
  1066. col=Blend(col, Vec4(1, 1, 1, Sat(specular)));
  1067. // apply outer glow and borders
  1068. if(section.outer_border_color.a && dist>=0 && dist<params.border_size )col=Blend(col, sp.outer_border_color);else
  1069. if(section.inner_border_color.a && dist>=params.border_size && dist<params.border_size*2)col=Blend(col, sp.inner_border_color);else
  1070. if(section. prev_border_color.a && section_i && dist_sect>=sps[1].size-params.border_size )col=Blend(col, sp. prev_border_color);
  1071. #if DEBUG
  1072. if(Kb.b(KB_X))col=ColorBrightness(dist_x ).asVec4();
  1073. if(Kb.b(KB_Y))col=ColorBrightness(dist_y ).asVec4();
  1074. if(Kb.b(KB_I))col=ColorBrightness(dist_sect ).asVec4();
  1075. if(Kb.b(KB_D))col=ColorBrightness(dist_global).asVec4();
  1076. if(Kb.b(KB_H))col=ColorBrightness(depth ).asVec4();
  1077. #endif
  1078. }
  1079. image.color(x, y, col);
  1080. }
  1081. }
  1082. void afterColor(FILTER_TYPE filter)
  1083. {
  1084. image.transparentToNeighbor();
  1085. #if DEBUG
  1086. if(Kb.b(KB_N)){map.mulAdd(Vec4(0.5f, 0.5f, 0.5f, 1), Vec4(0.5f, 0.5f, 0.5f, 0)); map.copy(image, -1, -1, -1, IMAGE_R8G8B8);}
  1087. #endif
  1088. image.resize(image_size.x/super_sample, image_size.y/super_sample, filter, true, true); // 'alpha_weight' needed when having 2 sections with different opacities }
  1089. panel_image._padd.zero();
  1090. VecI2 old_size=image.size();
  1091. Image glow_image, shadow_image;
  1092. Int glow_radius=RoundPos(params.outer_glow_radius*0.5f*params.resolution);
  1093. if( glow_radius>0 && params.outer_glow_color.a)
  1094. {
  1095. MIN(glow_radius, params.resolution/2);
  1096. glow_image.createShadow(image, glow_radius, 1.0f, params.outer_glow_spread, glow_radius>0); // apply border padd only with a positive radius, to avoid making textures bigger with radius = 0
  1097. }
  1098. if(params.shadow_opacity>EPS) // create the shadow even if radius is zero, because the panel may be transparent
  1099. {
  1100. Int shadow_radius=RoundPos(params.shadow_radius*0.5f*params.resolution);
  1101. MIN(shadow_radius, params.resolution/2);
  1102. shadow_image.createShadow(image, shadow_radius, params.shadow_opacity, params.shadow_spread, shadow_radius>0); // apply border padd only with a positive radius, to avoid making textures bigger with radius = 0
  1103. }
  1104. if( glow_image.is())image.applyShadow( glow_image, params.outer_glow_color, (image.size()- glow_image.size())/2); // yes, glow needs to be applied first (before shadows), because 'applyShadow' works in a way that it doesn't apply pixels on opaque ones
  1105. if(shadow_image.is())image.applyShadow(shadow_image, BLACK , (image.size()-shadow_image.size())/2);
  1106. image_size =image.size();
  1107. if(old_size!=image_size)
  1108. {
  1109. Vec2 scale=Vec2(old_size)/image_size;
  1110. REPAD(y, panel_image._tex_x)REPAD(x, panel_image._tex_x[y])ScaleTex(panel_image._tex_x[y][x] , scale.x);
  1111. REPAD(y, panel_image._tex_y) ScaleTex(panel_image._tex_y[y] , scale.y);
  1112. ScaleTex(panel_image._tex_left_top , scale );
  1113. ScaleTex(panel_image._tex_right_bottom, scale );
  1114. panel_image._padd=(1/scale-1)*Vec2(params.width, params.height);
  1115. }
  1116. panel_image._padd+=params.extend;
  1117. REPA(panel_image._force_uniform_stretch)
  1118. {
  1119. panel_image._padd.c[i]*=0.5f;
  1120. panel_image._force_uniform_stretch[i]=params.force_uniform_stretch[i];
  1121. if(!params.force_uniform_stretch[i])panel_image._padd.c[i]*=max_scale;
  1122. }
  1123. panel_image._padd_any=panel_image._padd.any();
  1124. panel_image._inner_padding.set(panel_image._size_x[1][0], panel_image._size_y[1],
  1125. panel_image._size_x[1][1], panel_image._size_y[0]);
  1126. panel_image._inner_padding.min+=params.extend_inner_padd.min;
  1127. panel_image._inner_padding.max+=params.extend_inner_padd.max;
  1128. }
  1129. };
  1130. static void SetDepth(IntPtr y, PanelImageCreate &pic, Int thread_index) {pic.setDepthY(y);}
  1131. static void SetColor(IntPtr y, PanelImageCreate &pic, Int thread_index) {pic.setColorY(y);}
  1132. void PanelImage::create(C PanelImageParams &params, Image *depth_map, Int super_sample, FILTER_TYPE filter, Threads *threads)
  1133. {
  1134. PanelImageCreate pic(T, params, depth_map, super_sample, threads);
  1135. if(pic.create())
  1136. {
  1137. if(threads)threads->process1(pic.map.h(), SetDepth, pic);else REPD(y, pic.map .h())pic.setDepthY(y);
  1138. pic.afterDepth();
  1139. if(threads)threads->process1(pic.map.h(), SetColor, pic);else REPD(y, pic.image.h())pic.setColorY(y);
  1140. pic.afterColor(filter);
  1141. }
  1142. }
  1143. /******************************************************************************/
  1144. Bool PanelImage::getSideScale(C Rect &rect, Flt &scale)C
  1145. {
  1146. Flt w=rect.w(), h=rect.h();
  1147. if(_side_size.x>w){scale=w/_side_size.x; Flt side_size_y=_side_size.y*scale; if(side_size_y>h)scale*=h/side_size_y; return true;}
  1148. if(_side_size.y>h){scale=h/_side_size.y; return true;}
  1149. return false;
  1150. }
  1151. Bool PanelImage::getSideScaleVertical(C Rect &rect, Flt &scale)C
  1152. {
  1153. Flt w=rect.h(), h=rect.w();
  1154. if(_side_size.x>w){scale=w/_side_size.x; Flt side_size_y=_side_size.y*scale; if(side_size_y>h)scale*=h/side_size_y; return true;}
  1155. if(_side_size.y>h){scale=h/_side_size.y; return true;}
  1156. return false;
  1157. }
  1158. Bool PanelImage::extendedRect(C Rect &rect, Rect &extended)C
  1159. {
  1160. extended=rect;
  1161. if(_padd_any)
  1162. {
  1163. // !! change 'extended' after using 'rect' in case they're the same 'Rect' !!
  1164. Flt scale; if(getSideScale(rect, scale))
  1165. {
  1166. extended.extendX(_force_uniform_stretch[0] ? _padd.x*rect.w() : _padd.x*scale);
  1167. extended.extendY(_force_uniform_stretch[1] ? _padd.y*rect.h() : _padd.y*scale);
  1168. }else
  1169. {
  1170. extended.extendX(_force_uniform_stretch[0] ? _padd.x*rect.w() : _padd.x);
  1171. extended.extendY(_force_uniform_stretch[1] ? _padd.y*rect.h() : _padd.y);
  1172. }
  1173. return true;
  1174. }
  1175. return false;
  1176. }
  1177. void PanelImage::innerPadding(C Rect &rect, Rect &padding)C
  1178. {
  1179. Flt scale; Bool scale_do=getSideScale(rect, scale);
  1180. padding=defaultInnerPadding(); // change 'padding' after using 'rect' in case they're the same 'Rect'
  1181. if(scale_do)padding*=scale;
  1182. }
  1183. void PanelImage::defaultInnerPaddingSize(Vec2 &padd_size)C
  1184. {
  1185. padd_size=_inner_padding.min+_inner_padding.max;
  1186. }
  1187. /******************************************************************************/
  1188. void PanelImage::draw( C Rect &rect)C {draw(WHITE, TRANSPARENT, rect);}
  1189. void PanelImage::draw(C Color &color, C Color &color_add, C Rect &rect)C
  1190. {
  1191. VI.color (color );
  1192. VI.color2 (color_add);
  1193. VI.image (&image );
  1194. VI.setType(VI_2D_TEX, VI_SP_COL);
  1195. const Int vtxs=(_same_x ? 16 : 20);
  1196. if(Vtx2DTex *v=(Vtx2DTex*)VI.addVtx(vtxs))
  1197. {
  1198. Flt scale; Bool scale_do=getSideScale(rect, scale);
  1199. Flt l =rect.min.x, r =rect.max.x, x[3][2], // [y][x]
  1200. y0=rect.max.y, y3=rect.min.y, y1, y2;
  1201. if(scale_do)
  1202. {
  1203. y1 =y0-_size_y[0] *scale;
  1204. y2 =y3+_size_y[1] *scale;
  1205. x[0][0]=l +_size_x[0][0]*scale;
  1206. x[0][1]=r -_size_x[0][1]*scale;
  1207. if(_padd_any)
  1208. {
  1209. Flt padd;
  1210. padd=_padd.x*(_force_uniform_stretch[0] ? rect.w() : scale); l -=padd; r +=padd;
  1211. padd=_padd.y*(_force_uniform_stretch[1] ? rect.h() : scale); y0+=padd; y3-=padd;
  1212. }
  1213. }else
  1214. {
  1215. y1 =y0-_size_y[0];
  1216. y2 =y3+_size_y[1];
  1217. x[0][0]=l +_size_x[0][0];
  1218. x[0][1]=r -_size_x[0][1];
  1219. if(_padd_any)
  1220. {
  1221. if(_force_uniform_stretch[0]){Flt padd=_padd.x*rect.w(); l -=padd; r +=padd;}else{l -=_padd.x; r +=_padd.x;}
  1222. if(_force_uniform_stretch[1]){Flt padd=_padd.y*rect.h(); y0+=padd; y3-=padd;}else{y0+=_padd.y; y3-=_padd.y;}
  1223. }
  1224. }
  1225. if(_same_x)
  1226. {
  1227. v[ 0].pos.set( l, y0);
  1228. v[ 1].pos.set(x[0][0], y0);
  1229. v[ 2].pos.set(x[0][1], y0);
  1230. v[ 3].pos.set( r, y0);
  1231. v[ 4].pos.set( l, y1);
  1232. v[ 5].pos.set(x[0][0], y1);
  1233. v[ 6].pos.set(x[0][1], y1);
  1234. v[ 7].pos.set( r, y1);
  1235. v[ 8].pos.set( l, y2);
  1236. v[ 9].pos.set(x[0][0], y2);
  1237. v[10].pos.set(x[0][1], y2);
  1238. v[11].pos.set( r, y2);
  1239. v[12].pos.set( l, y3);
  1240. v[13].pos.set(x[0][0], y3);
  1241. v[14].pos.set(x[0][1], y3);
  1242. v[15].pos.set( r, y3);
  1243. v[ 0].tex.set( 0, 0);
  1244. v[ 1].tex.set(_tex_x[0][0], 0);
  1245. v[ 2].tex.set(_tex_x[0][1], 0);
  1246. v[ 3].tex.set( 1, 0);
  1247. v[ 4].tex.set( 0, _tex_y[0]);
  1248. v[ 5].tex.set(_tex_x[0][0], _tex_y[0]);
  1249. v[ 6].tex.set(_tex_x[0][1], _tex_y[0]);
  1250. v[ 7].tex.set( 1, _tex_y[0]);
  1251. v[ 8].tex.set( 0, _tex_y[1]);
  1252. v[ 9].tex.set(_tex_x[0][0], _tex_y[1]);
  1253. v[10].tex.set(_tex_x[0][1], _tex_y[1]);
  1254. v[11].tex.set( 1, _tex_y[1]);
  1255. v[12].tex.set( 0, 1);
  1256. v[13].tex.set(_tex_x[0][0], 1);
  1257. v[14].tex.set(_tex_x[0][1], 1);
  1258. v[15].tex.set( 1, 1);
  1259. }else
  1260. {
  1261. if(scale_do)
  1262. {
  1263. x[1][0]=rect.min.x+_size_x[1][0]*scale;
  1264. x[1][1]=rect.max.x-_size_x[1][1]*scale;
  1265. x[2][0]=rect.min.x+_size_x[2][0]*scale;
  1266. x[2][1]=rect.max.x-_size_x[2][1]*scale;
  1267. }else
  1268. {
  1269. x[1][0]=rect.min.x+_size_x[1][0];
  1270. x[1][1]=rect.max.x-_size_x[1][1];
  1271. x[2][0]=rect.min.x+_size_x[2][0];
  1272. x[2][1]=rect.max.x-_size_x[2][1];
  1273. }
  1274. v[ 0].pos.set( l, y0);
  1275. v[ 1].pos.set(x[0][0], y0);
  1276. v[ 2].pos.set(x[0][1], y0);
  1277. v[ 3].pos.set( r, y0);
  1278. v[ 4].pos.set( l, y1);
  1279. v[ 5].pos.set(x[0][0], y1);
  1280. v[ 6].pos.set(x[0][1], y1);
  1281. v[ 7].pos.set( r, y1);
  1282. v[ 8].pos.set(x[1][0], y1);
  1283. v[ 9].pos.set(x[1][1], y1);
  1284. v[10].pos.set( l, y2);
  1285. v[11].pos.set(x[1][0], y2);
  1286. v[12].pos.set(x[1][1], y2);
  1287. v[13].pos.set( r, y2);
  1288. v[14].pos.set(x[2][0], y2);
  1289. v[15].pos.set(x[2][1], y2);
  1290. v[16].pos.set( l, y3);
  1291. v[17].pos.set(x[2][0], y3);
  1292. v[18].pos.set(x[2][1], y3);
  1293. v[19].pos.set( r, y3);
  1294. v[ 0].tex.set( 0, 0);
  1295. v[ 1].tex.set(_tex_x[0][0], 0);
  1296. v[ 2].tex.set(_tex_x[0][1], 0);
  1297. v[ 3].tex.set( 1, 0);
  1298. v[ 4].tex.set( 0, _tex_y[0]);
  1299. v[ 5].tex.set(_tex_x[0][0], _tex_y[0]);
  1300. v[ 6].tex.set(_tex_x[0][1], _tex_y[0]);
  1301. v[ 7].tex.set( 1, _tex_y[0]);
  1302. v[ 8].tex.set(_tex_x[1][0], _tex_y[0]);
  1303. v[ 9].tex.set(_tex_x[1][1], _tex_y[0]);
  1304. v[10].tex.set( 0, _tex_y[1]);
  1305. v[11].tex.set(_tex_x[1][0], _tex_y[1]);
  1306. v[12].tex.set(_tex_x[1][1], _tex_y[1]);
  1307. v[13].tex.set( 1, _tex_y[1]);
  1308. v[14].tex.set(_tex_x[2][0], _tex_y[1]);
  1309. v[15].tex.set(_tex_x[2][1], _tex_y[1]);
  1310. v[16].tex.set( 0, 1);
  1311. v[17].tex.set(_tex_x[2][0], 1);
  1312. v[18].tex.set(_tex_x[2][1], 1);
  1313. v[19].tex.set( 1, 1);
  1314. }
  1315. if(image.partial())REP(vtxs)v[i].tex*=image._part.xy;
  1316. VI.flushIndexed(_same_x ? IndBufPanel : IndBufPanelEx, 3*3*2*3);
  1317. }
  1318. VI.clear();
  1319. }
  1320. /******************************************************************************/
  1321. void PanelImage::drawVertical( C Rect &rect)C {drawVertical(WHITE, TRANSPARENT, rect);}
  1322. void PanelImage::drawVertical(C Color &color, C Color &color_add, C Rect &rect)C
  1323. {
  1324. VI.color (color );
  1325. VI.color2 (color_add);
  1326. VI.image (&image );
  1327. VI.setType(VI_2D_TEX, VI_SP_COL);
  1328. const Int vtxs=(_same_x ? 16 : 20);
  1329. if(Vtx2DTex *v=(Vtx2DTex*)VI.addVtx(vtxs))
  1330. {
  1331. Flt scale; Bool scale_do=getSideScaleVertical(rect, scale);
  1332. Flt b =rect.min.y, t =rect.max.y, y[3][2], // [y][x]
  1333. x0=rect.min.x, x3=rect.max.x, x1, x2;
  1334. if(scale_do)
  1335. {
  1336. x1 =x0+_size_y[0] *scale;
  1337. x2 =x3-_size_y[1] *scale;
  1338. y[0][0]=b +_size_x[0][0]*scale;
  1339. y[0][1]=t -_size_x[0][1]*scale;
  1340. if(_padd_any)
  1341. {
  1342. Flt padd;
  1343. padd=_padd.x*(_force_uniform_stretch[0] ? rect.h() : scale); b -=padd; t +=padd;
  1344. padd=_padd.y*(_force_uniform_stretch[1] ? rect.w() : scale); x0-=padd; x3+=padd;
  1345. }
  1346. }else
  1347. {
  1348. x1 =x0+_size_y[0];
  1349. x2 =x3-_size_y[1];
  1350. y[0][0]=b +_size_x[0][0];
  1351. y[0][1]=t -_size_x[0][1];
  1352. if(_padd_any)
  1353. {
  1354. if(_force_uniform_stretch[0]){Flt padd=_padd.x*rect.h(); b -=padd; t +=padd;}else{b -=_padd.x; t +=_padd.x;}
  1355. if(_force_uniform_stretch[1]){Flt padd=_padd.y*rect.w(); x0-=padd; x3+=padd;}else{x0-=_padd.y; x3+=_padd.y;}
  1356. }
  1357. }
  1358. if(_same_x)
  1359. {
  1360. v[ 0].pos.set(x0, b);
  1361. v[ 1].pos.set(x0, y[0][0]);
  1362. v[ 2].pos.set(x0, y[0][1]);
  1363. v[ 3].pos.set(x0, t);
  1364. v[ 4].pos.set(x1, b);
  1365. v[ 5].pos.set(x1, y[0][0]);
  1366. v[ 6].pos.set(x1, y[0][1]);
  1367. v[ 7].pos.set(x1, t);
  1368. v[ 8].pos.set(x2, b);
  1369. v[ 9].pos.set(x2, y[0][0]);
  1370. v[10].pos.set(x2, y[0][1]);
  1371. v[11].pos.set(x2, t);
  1372. v[12].pos.set(x3, b);
  1373. v[13].pos.set(x3, y[0][0]);
  1374. v[14].pos.set(x3, y[0][1]);
  1375. v[15].pos.set(x3, t);
  1376. v[ 0].tex.set( 0, 0);
  1377. v[ 1].tex.set(_tex_x[0][0], 0);
  1378. v[ 2].tex.set(_tex_x[0][1], 0);
  1379. v[ 3].tex.set( 1, 0);
  1380. v[ 4].tex.set( 0, _tex_y[0]);
  1381. v[ 5].tex.set(_tex_x[0][0], _tex_y[0]);
  1382. v[ 6].tex.set(_tex_x[0][1], _tex_y[0]);
  1383. v[ 7].tex.set( 1, _tex_y[0]);
  1384. v[ 8].tex.set( 0, _tex_y[1]);
  1385. v[ 9].tex.set(_tex_x[0][0], _tex_y[1]);
  1386. v[10].tex.set(_tex_x[0][1], _tex_y[1]);
  1387. v[11].tex.set( 1, _tex_y[1]);
  1388. v[12].tex.set( 0, 1);
  1389. v[13].tex.set(_tex_x[0][0], 1);
  1390. v[14].tex.set(_tex_x[0][1], 1);
  1391. v[15].tex.set( 1, 1);
  1392. }else
  1393. {
  1394. if(scale_do)
  1395. {
  1396. y[1][0]=rect.min.y+_size_x[1][0]*scale;
  1397. y[1][1]=rect.max.y-_size_x[1][1]*scale;
  1398. y[2][0]=rect.min.y+_size_x[2][0]*scale;
  1399. y[2][1]=rect.max.y-_size_x[2][1]*scale;
  1400. }else
  1401. {
  1402. y[1][0]=rect.min.y+_size_x[1][0];
  1403. y[1][1]=rect.max.y-_size_x[1][1];
  1404. y[2][0]=rect.min.y+_size_x[2][0];
  1405. y[2][1]=rect.max.y-_size_x[2][1];
  1406. }
  1407. v[ 0].pos.set(x0, b);
  1408. v[ 1].pos.set(x0, y[0][0]);
  1409. v[ 2].pos.set(x0, y[0][1]);
  1410. v[ 3].pos.set(x0, t);
  1411. v[ 4].pos.set(x1, b);
  1412. v[ 5].pos.set(x1, y[0][0]);
  1413. v[ 6].pos.set(x1, y[0][1]);
  1414. v[ 7].pos.set(x1, t);
  1415. v[ 8].pos.set(x1, y[1][0]);
  1416. v[ 9].pos.set(x1, y[1][1]);
  1417. v[10].pos.set(x2, b);
  1418. v[11].pos.set(x2, y[1][0]);
  1419. v[12].pos.set(x2, y[1][1]);
  1420. v[13].pos.set(x2, t);
  1421. v[14].pos.set(x2, y[2][0]);
  1422. v[15].pos.set(x2, y[2][1]);
  1423. v[16].pos.set(x3, b);
  1424. v[17].pos.set(x3, y[2][0]);
  1425. v[18].pos.set(x3, y[2][1]);
  1426. v[19].pos.set(x3, t);
  1427. v[ 0].tex.set( 0, 0);
  1428. v[ 1].tex.set(_tex_x[0][0], 0);
  1429. v[ 2].tex.set(_tex_x[0][1], 0);
  1430. v[ 3].tex.set( 1, 0);
  1431. v[ 4].tex.set( 0, _tex_y[0]);
  1432. v[ 5].tex.set(_tex_x[0][0], _tex_y[0]);
  1433. v[ 6].tex.set(_tex_x[0][1], _tex_y[0]);
  1434. v[ 7].tex.set( 1, _tex_y[0]);
  1435. v[ 8].tex.set(_tex_x[1][0], _tex_y[0]);
  1436. v[ 9].tex.set(_tex_x[1][1], _tex_y[0]);
  1437. v[10].tex.set( 0, _tex_y[1]);
  1438. v[11].tex.set(_tex_x[1][0], _tex_y[1]);
  1439. v[12].tex.set(_tex_x[1][1], _tex_y[1]);
  1440. v[13].tex.set( 1, _tex_y[1]);
  1441. v[14].tex.set(_tex_x[2][0], _tex_y[1]);
  1442. v[15].tex.set(_tex_x[2][1], _tex_y[1]);
  1443. v[16].tex.set( 0, 1);
  1444. v[17].tex.set(_tex_x[2][0], 1);
  1445. v[18].tex.set(_tex_x[2][1], 1);
  1446. v[19].tex.set( 1, 1);
  1447. }
  1448. if(image.partial())REP(vtxs)v[i].tex*=image._part.xy;
  1449. VI.flushIndexed(_same_x ? IndBufPanel : IndBufPanelEx, 3*3*2*3);
  1450. }
  1451. VI.clear();
  1452. }
  1453. /******************************************************************************/
  1454. void PanelImage::drawBorders(C Color &color, C Color &color_add, C Rect &rect)C
  1455. {
  1456. VI.color (color );
  1457. VI.color2 (color_add);
  1458. VI.image (&image );
  1459. VI.setType(VI_2D_TEX, VI_SP_COL);
  1460. const Int vtxs=(_same_x ? 16 : 20);
  1461. if(Vtx2DTex *v=(Vtx2DTex*)VI.addVtx(vtxs))
  1462. {
  1463. Flt scale; Bool scale_do=getSideScale(rect, scale);
  1464. Flt l =rect.min.x, r =rect.max.x, x[3][2], // [y][x]
  1465. y0=rect.max.y, y3=rect.min.y, y1, y2;
  1466. if(scale_do)
  1467. {
  1468. y1 =y0-_size_y[0] *scale;
  1469. y2 =y3+_size_y[1] *scale;
  1470. x[0][0]=l +_size_x[0][0]*scale;
  1471. x[0][1]=r -_size_x[0][1]*scale;
  1472. if(_padd_any)
  1473. {
  1474. Flt padd;
  1475. padd=_padd.x*(_force_uniform_stretch[0] ? rect.w() : scale); l -=padd; r +=padd;
  1476. padd=_padd.y*(_force_uniform_stretch[1] ? rect.h() : scale); y0+=padd; y3-=padd;
  1477. }
  1478. }else
  1479. {
  1480. y1 =y0-_size_y[0];
  1481. y2 =y3+_size_y[1];
  1482. x[0][0]=l +_size_x[0][0];
  1483. x[0][1]=r -_size_x[0][1];
  1484. if(_padd_any)
  1485. {
  1486. if(_force_uniform_stretch[0]){Flt padd=_padd.x*rect.w(); l -=padd; r +=padd;}else{l -=_padd.x; r +=_padd.x;}
  1487. if(_force_uniform_stretch[1]){Flt padd=_padd.y*rect.h(); y0+=padd; y3-=padd;}else{y0+=_padd.y; y3-=_padd.y;}
  1488. }
  1489. }
  1490. if(_same_x)
  1491. {
  1492. v[ 0].pos.set( l, y0);
  1493. v[ 1].pos.set(x[0][0], y0);
  1494. v[ 2].pos.set(x[0][1], y0);
  1495. v[ 3].pos.set( r, y0);
  1496. v[ 4].pos.set( l, y1);
  1497. v[ 5].pos.set(x[0][0], y1);
  1498. v[ 6].pos.set(x[0][1], y1);
  1499. v[ 7].pos.set( r, y1);
  1500. v[ 8].pos.set( l, y2);
  1501. v[ 9].pos.set(x[0][0], y2);
  1502. v[10].pos.set(x[0][1], y2);
  1503. v[11].pos.set( r, y2);
  1504. v[12].pos.set( l, y3);
  1505. v[13].pos.set(x[0][0], y3);
  1506. v[14].pos.set(x[0][1], y3);
  1507. v[15].pos.set( r, y3);
  1508. v[ 0].tex.set( 0, 0);
  1509. v[ 1].tex.set(_tex_x[0][0], 0);
  1510. v[ 2].tex.set(_tex_x[0][1], 0);
  1511. v[ 3].tex.set( 1, 0);
  1512. v[ 4].tex.set( 0, _tex_y[0]);
  1513. v[ 5].tex.set(_tex_x[0][0], _tex_y[0]);
  1514. v[ 6].tex.set(_tex_x[0][1], _tex_y[0]);
  1515. v[ 7].tex.set( 1, _tex_y[0]);
  1516. v[ 8].tex.set( 0, _tex_y[1]);
  1517. v[ 9].tex.set(_tex_x[0][0], _tex_y[1]);
  1518. v[10].tex.set(_tex_x[0][1], _tex_y[1]);
  1519. v[11].tex.set( 1, _tex_y[1]);
  1520. v[12].tex.set( 0, 1);
  1521. v[13].tex.set(_tex_x[0][0], 1);
  1522. v[14].tex.set(_tex_x[0][1], 1);
  1523. v[15].tex.set( 1, 1);
  1524. }else
  1525. {
  1526. if(scale_do)
  1527. {
  1528. x[1][0]=rect.min.x+_size_x[1][0]*scale;
  1529. x[1][1]=rect.max.x-_size_x[1][1]*scale;
  1530. x[2][0]=rect.min.x+_size_x[2][0]*scale;
  1531. x[2][1]=rect.max.x-_size_x[2][1]*scale;
  1532. }else
  1533. {
  1534. x[1][0]=rect.min.x+_size_x[1][0];
  1535. x[1][1]=rect.max.x-_size_x[1][1];
  1536. x[2][0]=rect.min.x+_size_x[2][0];
  1537. x[2][1]=rect.max.x-_size_x[2][1];
  1538. }
  1539. v[ 0].pos.set( l, y0);
  1540. v[ 1].pos.set(x[0][0], y0);
  1541. v[ 2].pos.set(x[0][1], y0);
  1542. v[ 3].pos.set( r, y0);
  1543. v[ 4].pos.set( l, y1);
  1544. v[ 5].pos.set(x[0][0], y1);
  1545. v[ 6].pos.set(x[0][1], y1);
  1546. v[ 7].pos.set( r, y1);
  1547. v[ 8].pos.set(x[1][0], y1);
  1548. v[ 9].pos.set(x[1][1], y1);
  1549. v[10].pos.set( l, y2);
  1550. v[11].pos.set(x[1][0], y2);
  1551. v[12].pos.set(x[1][1], y2);
  1552. v[13].pos.set( r, y2);
  1553. v[14].pos.set(x[2][0], y2);
  1554. v[15].pos.set(x[2][1], y2);
  1555. v[16].pos.set( l, y3);
  1556. v[17].pos.set(x[2][0], y3);
  1557. v[18].pos.set(x[2][1], y3);
  1558. v[19].pos.set( r, y3);
  1559. v[ 0].tex.set( 0, 0);
  1560. v[ 1].tex.set(_tex_x[0][0], 0);
  1561. v[ 2].tex.set(_tex_x[0][1], 0);
  1562. v[ 3].tex.set( 1, 0);
  1563. v[ 4].tex.set( 0, _tex_y[0]);
  1564. v[ 5].tex.set(_tex_x[0][0], _tex_y[0]);
  1565. v[ 6].tex.set(_tex_x[0][1], _tex_y[0]);
  1566. v[ 7].tex.set( 1, _tex_y[0]);
  1567. v[ 8].tex.set(_tex_x[1][0], _tex_y[0]);
  1568. v[ 9].tex.set(_tex_x[1][1], _tex_y[0]);
  1569. v[10].tex.set( 0, _tex_y[1]);
  1570. v[11].tex.set(_tex_x[1][0], _tex_y[1]);
  1571. v[12].tex.set(_tex_x[1][1], _tex_y[1]);
  1572. v[13].tex.set( 1, _tex_y[1]);
  1573. v[14].tex.set(_tex_x[2][0], _tex_y[1]);
  1574. v[15].tex.set(_tex_x[2][1], _tex_y[1]);
  1575. v[16].tex.set( 0, 1);
  1576. v[17].tex.set(_tex_x[2][0], 1);
  1577. v[18].tex.set(_tex_x[2][1], 1);
  1578. v[19].tex.set( 1, 1);
  1579. }
  1580. if(image.partial())REP(vtxs)v[i].tex*=image._part.xy;
  1581. VI.flushIndexed(_same_x ? IndBufPanel : IndBufPanelEx, (3*3-1)*2*3);
  1582. }
  1583. VI.clear();
  1584. }
  1585. /******************************************************************************/
  1586. static void Clip(Flt &min_pos, Flt &max_pos, Flt min_tex, Flt &max_tex, Flt clip_pos)
  1587. {
  1588. if(min_pos>=clip_pos)min_pos=max_pos=clip_pos;else
  1589. if(max_pos> clip_pos)
  1590. {
  1591. Flt frac=LerpR(min_pos, max_pos, clip_pos);
  1592. max_pos=clip_pos;
  1593. max_tex=Lerp(min_tex, max_tex, frac);
  1594. }
  1595. }
  1596. void PanelImage::drawFrac(C Color &color, C Color &color_add, C Rect &rect, Flt frac_x, Bool include_padding)C
  1597. {
  1598. VI.color (color );
  1599. VI.color2 (color_add);
  1600. VI.image (&image );
  1601. VI.setType(VI_2D_TEX, VI_SP_COL);
  1602. const Int vtxs=(_same_x ? 16 : 20);
  1603. if(Vtx2DTex *v=(Vtx2DTex*)VI.addVtx(vtxs))
  1604. {
  1605. Flt scale; Bool scale_do=getSideScale(rect, scale);
  1606. Flt l =rect.min.x, r =rect.max.x, x[3][2], // [y][x]
  1607. y0=rect.max.y, y3=rect.min.y, y1, y2;
  1608. if(scale_do)
  1609. {
  1610. y1 =y0-_size_y[0] *scale;
  1611. y2 =y3+_size_y[1] *scale;
  1612. x[0][0]=l +_size_x[0][0]*scale;
  1613. x[0][1]=r -_size_x[0][1]*scale;
  1614. if(_padd_any)
  1615. {
  1616. Flt padd;
  1617. padd=_padd.x*(_force_uniform_stretch[0] ? rect.w() : scale); l -=padd; r +=padd;
  1618. padd=_padd.y*(_force_uniform_stretch[1] ? rect.h() : scale); y0+=padd; y3-=padd;
  1619. }
  1620. }else
  1621. {
  1622. y1 =y0-_size_y[0];
  1623. y2 =y3+_size_y[1];
  1624. x[0][0]=l +_size_x[0][0];
  1625. x[0][1]=r -_size_x[0][1];
  1626. if(_padd_any)
  1627. {
  1628. if(_force_uniform_stretch[0]){Flt padd=_padd.x*rect.w(); l -=padd; r +=padd;}else{l -=_padd.x; r +=_padd.x;}
  1629. if(_force_uniform_stretch[1]){Flt padd=_padd.y*rect.h(); y0+=padd; y3-=padd;}else{y0+=_padd.y; y3-=_padd.y;}
  1630. }
  1631. }
  1632. Flt pos_x=(include_padding ? Lerp(l, r, frac_x) : rect.lerpX(frac_x)),
  1633. tex_x[3][2], // [y][x]
  1634. tex_r=1;
  1635. tex_x[0][0]=_tex_x[0][0];
  1636. tex_x[0][1]=_tex_x[0][1];
  1637. if(_same_x)
  1638. {
  1639. Clip( l, x[0][0], 0, tex_x[0][0], pos_x);
  1640. Clip(x[0][0], x[0][1], tex_x[0][0], tex_x[0][1], pos_x);
  1641. Clip(x[0][1], r, tex_x[0][1], tex_r , pos_x);
  1642. v[ 0].pos.set( l, y0);
  1643. v[ 1].pos.set(x[0][0], y0);
  1644. v[ 2].pos.set(x[0][1], y0);
  1645. v[ 3].pos.set( r, y0);
  1646. v[ 4].pos.set( l, y1);
  1647. v[ 5].pos.set(x[0][0], y1);
  1648. v[ 6].pos.set(x[0][1], y1);
  1649. v[ 7].pos.set( r, y1);
  1650. v[ 8].pos.set( l, y2);
  1651. v[ 9].pos.set(x[0][0], y2);
  1652. v[10].pos.set(x[0][1], y2);
  1653. v[11].pos.set( r, y2);
  1654. v[12].pos.set( l, y3);
  1655. v[13].pos.set(x[0][0], y3);
  1656. v[14].pos.set(x[0][1], y3);
  1657. v[15].pos.set( r, y3);
  1658. v[ 0].tex.set( 0, 0);
  1659. v[ 1].tex.set(tex_x[0][0], 0);
  1660. v[ 2].tex.set(tex_x[0][1], 0);
  1661. v[ 3].tex.set(tex_r , 0);
  1662. v[ 4].tex.set( 0, _tex_y[0]);
  1663. v[ 5].tex.set(tex_x[0][0], _tex_y[0]);
  1664. v[ 6].tex.set(tex_x[0][1], _tex_y[0]);
  1665. v[ 7].tex.set(tex_r , _tex_y[0]);
  1666. v[ 8].tex.set( 0, _tex_y[1]);
  1667. v[ 9].tex.set(tex_x[0][0], _tex_y[1]);
  1668. v[10].tex.set(tex_x[0][1], _tex_y[1]);
  1669. v[11].tex.set(tex_r , _tex_y[1]);
  1670. v[12].tex.set( 0, 1);
  1671. v[13].tex.set(tex_x[0][0], 1);
  1672. v[14].tex.set(tex_x[0][1], 1);
  1673. v[15].tex.set(tex_r , 1);
  1674. }else
  1675. {
  1676. if(scale_do)
  1677. {
  1678. x[1][0]=rect.min.x+_size_x[1][0]*scale;
  1679. x[1][1]=rect.max.x-_size_x[1][1]*scale;
  1680. x[2][0]=rect.min.x+_size_x[2][0]*scale;
  1681. x[2][1]=rect.max.x-_size_x[2][1]*scale;
  1682. }else
  1683. {
  1684. x[1][0]=rect.min.x+_size_x[1][0];
  1685. x[1][1]=rect.max.x-_size_x[1][1];
  1686. x[2][0]=rect.min.x+_size_x[2][0];
  1687. x[2][1]=rect.max.x-_size_x[2][1];
  1688. }
  1689. tex_x[1][0]=_tex_x[1][0];
  1690. tex_x[1][1]=_tex_x[1][1];
  1691. tex_x[2][0]=_tex_x[2][0];
  1692. tex_x[2][1]=_tex_x[2][1];
  1693. Flt L=l; Clip( l, x[0][0], 0, tex_x[0][0], pos_x);
  1694. Clip(x[0][0], x[0][1], tex_x[0][0], tex_x[0][1], pos_x);
  1695. Clip(x[0][1], r, tex_x[0][1], tex_r , pos_x);
  1696. l=L; Clip( l, x[1][0], 0, tex_x[1][0], pos_x);
  1697. Clip(x[1][0], x[1][1], tex_x[1][0], tex_x[1][1], pos_x);
  1698. l=L; Clip( l, x[2][0], 0, tex_x[2][0], pos_x);
  1699. Clip(x[2][0], x[2][1], tex_x[2][0], tex_x[2][1], pos_x);
  1700. v[ 0].pos.set( l, y0);
  1701. v[ 1].pos.set(x[0][0], y0);
  1702. v[ 2].pos.set(x[0][1], y0);
  1703. v[ 3].pos.set( r, y0);
  1704. v[ 4].pos.set( l, y1);
  1705. v[ 5].pos.set(x[0][0], y1);
  1706. v[ 6].pos.set(x[0][1], y1);
  1707. v[ 7].pos.set( r, y1);
  1708. v[ 8].pos.set(x[1][0], y1);
  1709. v[ 9].pos.set(x[1][1], y1);
  1710. v[10].pos.set( l, y2);
  1711. v[11].pos.set(x[1][0], y2);
  1712. v[12].pos.set(x[1][1], y2);
  1713. v[13].pos.set( r, y2);
  1714. v[14].pos.set(x[2][0], y2);
  1715. v[15].pos.set(x[2][1], y2);
  1716. v[16].pos.set( l, y3);
  1717. v[17].pos.set(x[2][0], y3);
  1718. v[18].pos.set(x[2][1], y3);
  1719. v[19].pos.set( r, y3);
  1720. v[ 0].tex.set( 0, 0);
  1721. v[ 1].tex.set(tex_x[0][0], 0);
  1722. v[ 2].tex.set(tex_x[0][1], 0);
  1723. v[ 3].tex.set(tex_r , 0);
  1724. v[ 4].tex.set( 0, _tex_y[0]);
  1725. v[ 5].tex.set(tex_x[0][0], _tex_y[0]);
  1726. v[ 6].tex.set(tex_x[0][1], _tex_y[0]);
  1727. v[ 7].tex.set(tex_r , _tex_y[0]);
  1728. v[ 8].tex.set(tex_x[1][0], _tex_y[0]);
  1729. v[ 9].tex.set(tex_x[1][1], _tex_y[0]);
  1730. v[10].tex.set( 0, _tex_y[1]);
  1731. v[11].tex.set(tex_x[1][0], _tex_y[1]);
  1732. v[12].tex.set(tex_x[1][1], _tex_y[1]);
  1733. v[13].tex.set(tex_r , _tex_y[1]);
  1734. v[14].tex.set(tex_x[2][0], _tex_y[1]);
  1735. v[15].tex.set(tex_x[2][1], _tex_y[1]);
  1736. v[16].tex.set( 0, 1);
  1737. v[17].tex.set(tex_x[2][0], 1);
  1738. v[18].tex.set(tex_x[2][1], 1);
  1739. v[19].tex.set(tex_r , 1);
  1740. }
  1741. if(image.partial())REP(vtxs)v[i].tex*=image._part.xy;
  1742. VI.flushIndexed(_same_x ? IndBufPanel : IndBufPanelEx, 3*3*2*3);
  1743. }
  1744. VI.clear();
  1745. }
  1746. void PanelImage::drawVerticalFrac(C Color &color, C Color &color_add, C Rect &rect, Flt frac_y, Bool include_padding)C
  1747. {
  1748. VI.color (color );
  1749. VI.color2 (color_add);
  1750. VI.image (&image );
  1751. VI.setType(VI_2D_TEX, VI_SP_COL);
  1752. const Int vtxs=(_same_x ? 16 : 20);
  1753. if(Vtx2DTex *v=(Vtx2DTex*)VI.addVtx(vtxs))
  1754. {
  1755. Flt scale; Bool scale_do=getSideScaleVertical(rect, scale);
  1756. Flt b =rect.min.y, t =rect.max.y, y[3][2], // [y][x]
  1757. x0=rect.min.x, x3=rect.max.x, x1, x2;
  1758. if(scale_do)
  1759. {
  1760. x1 =x0+_size_y[0] *scale;
  1761. x2 =x3-_size_y[1] *scale;
  1762. y[0][0]=b +_size_x[0][0]*scale;
  1763. y[0][1]=t -_size_x[0][1]*scale;
  1764. if(_padd_any)
  1765. {
  1766. Flt padd;
  1767. padd=_padd.x*(_force_uniform_stretch[0] ? rect.h() : scale); b -=padd; t +=padd;
  1768. padd=_padd.y*(_force_uniform_stretch[1] ? rect.w() : scale); x0-=padd; x3+=padd;
  1769. }
  1770. }else
  1771. {
  1772. x1 =x0+_size_y[0];
  1773. x2 =x3-_size_y[1];
  1774. y[0][0]=b +_size_x[0][0];
  1775. y[0][1]=t -_size_x[0][1];
  1776. if(_padd_any)
  1777. {
  1778. if(_force_uniform_stretch[0]){Flt padd=_padd.x*rect.h(); b -=padd; t +=padd;}else{b -=_padd.x; t +=_padd.x;}
  1779. if(_force_uniform_stretch[1]){Flt padd=_padd.y*rect.w(); x0-=padd; x3+=padd;}else{x0-=_padd.y; x3+=_padd.y;}
  1780. }
  1781. }
  1782. Flt pos_y=(include_padding ? Lerp(b, t, frac_y) : rect.lerpY(frac_y)),
  1783. tex_x[3][2], // [y][x]
  1784. tex_t=1;
  1785. tex_x[0][0]=_tex_x[0][0];
  1786. tex_x[0][1]=_tex_x[0][1];
  1787. if(_same_x)
  1788. {
  1789. Clip( b, y[0][0], 0, tex_x[0][0], pos_y);
  1790. Clip(y[0][0], y[0][1], tex_x[0][0], tex_x[0][1], pos_y);
  1791. Clip(y[0][1], t, tex_x[0][1], tex_t , pos_y);
  1792. v[ 0].pos.set(x0, b);
  1793. v[ 1].pos.set(x0, y[0][0]);
  1794. v[ 2].pos.set(x0, y[0][1]);
  1795. v[ 3].pos.set(x0, t);
  1796. v[ 4].pos.set(x1, b);
  1797. v[ 5].pos.set(x1, y[0][0]);
  1798. v[ 6].pos.set(x1, y[0][1]);
  1799. v[ 7].pos.set(x1, t);
  1800. v[ 8].pos.set(x2, b);
  1801. v[ 9].pos.set(x2, y[0][0]);
  1802. v[10].pos.set(x2, y[0][1]);
  1803. v[11].pos.set(x2, t);
  1804. v[12].pos.set(x3, b);
  1805. v[13].pos.set(x3, y[0][0]);
  1806. v[14].pos.set(x3, y[0][1]);
  1807. v[15].pos.set(x3, t);
  1808. v[ 0].tex.set( 0, 0);
  1809. v[ 1].tex.set(tex_x[0][0], 0);
  1810. v[ 2].tex.set(tex_x[0][1], 0);
  1811. v[ 3].tex.set(tex_t , 0);
  1812. v[ 4].tex.set( 0, _tex_y[0]);
  1813. v[ 5].tex.set(tex_x[0][0], _tex_y[0]);
  1814. v[ 6].tex.set(tex_x[0][1], _tex_y[0]);
  1815. v[ 7].tex.set(tex_t , _tex_y[0]);
  1816. v[ 8].tex.set( 0, _tex_y[1]);
  1817. v[ 9].tex.set(tex_x[0][0], _tex_y[1]);
  1818. v[10].tex.set(tex_x[0][1], _tex_y[1]);
  1819. v[11].tex.set(tex_t , _tex_y[1]);
  1820. v[12].tex.set( 0, 1);
  1821. v[13].tex.set(tex_x[0][0], 1);
  1822. v[14].tex.set(tex_x[0][1], 1);
  1823. v[15].tex.set(tex_t , 1);
  1824. }else
  1825. {
  1826. if(scale_do)
  1827. {
  1828. y[1][0]=rect.min.y+_size_x[1][0]*scale;
  1829. y[1][1]=rect.max.y-_size_x[1][1]*scale;
  1830. y[2][0]=rect.min.y+_size_x[2][0]*scale;
  1831. y[2][1]=rect.max.y-_size_x[2][1]*scale;
  1832. }else
  1833. {
  1834. y[1][0]=rect.min.y+_size_x[1][0];
  1835. y[1][1]=rect.max.y-_size_x[1][1];
  1836. y[2][0]=rect.min.y+_size_x[2][0];
  1837. y[2][1]=rect.max.y-_size_x[2][1];
  1838. }
  1839. tex_x[1][0]=_tex_x[1][0];
  1840. tex_x[1][1]=_tex_x[1][1];
  1841. tex_x[2][0]=_tex_x[2][0];
  1842. tex_x[2][1]=_tex_x[2][1];
  1843. Flt B=b; Clip( b, y[0][0], 0, tex_x[0][0], pos_y);
  1844. Clip(y[0][0], y[0][1], tex_x[0][0], tex_x[0][1], pos_y);
  1845. Clip(y[0][1], t, tex_x[0][1], tex_t , pos_y);
  1846. b=B; Clip( b, y[1][0], 0, tex_x[1][0], pos_y);
  1847. Clip(y[1][0], y[1][1], tex_x[1][0], tex_x[1][1], pos_y);
  1848. b=B; Clip( b, y[2][0], 0, tex_x[2][0], pos_y);
  1849. Clip(y[2][0], y[2][1], tex_x[2][0], tex_x[2][1], pos_y);
  1850. v[ 0].pos.set(x0, b);
  1851. v[ 1].pos.set(x0, y[0][0]);
  1852. v[ 2].pos.set(x0, y[0][1]);
  1853. v[ 3].pos.set(x0, t);
  1854. v[ 4].pos.set(x1, b);
  1855. v[ 5].pos.set(x1, y[0][0]);
  1856. v[ 6].pos.set(x1, y[0][1]);
  1857. v[ 7].pos.set(x1, t);
  1858. v[ 8].pos.set(x1, y[1][0]);
  1859. v[ 9].pos.set(x1, y[1][1]);
  1860. v[10].pos.set(x2, b);
  1861. v[11].pos.set(x2, y[1][0]);
  1862. v[12].pos.set(x2, y[1][1]);
  1863. v[13].pos.set(x2, t);
  1864. v[14].pos.set(x2, y[2][0]);
  1865. v[15].pos.set(x2, y[2][1]);
  1866. v[16].pos.set(x3, b);
  1867. v[17].pos.set(x3, y[2][0]);
  1868. v[18].pos.set(x3, y[2][1]);
  1869. v[19].pos.set(x3, t);
  1870. v[ 0].tex.set( 0, 0);
  1871. v[ 1].tex.set(tex_x[0][0], 0);
  1872. v[ 2].tex.set(tex_x[0][1], 0);
  1873. v[ 3].tex.set(tex_t , 0);
  1874. v[ 4].tex.set( 0, _tex_y[0]);
  1875. v[ 5].tex.set(tex_x[0][0], _tex_y[0]);
  1876. v[ 6].tex.set(tex_x[0][1], _tex_y[0]);
  1877. v[ 7].tex.set(tex_t , _tex_y[0]);
  1878. v[ 8].tex.set(tex_x[1][0], _tex_y[0]);
  1879. v[ 9].tex.set(tex_x[1][1], _tex_y[0]);
  1880. v[10].tex.set( 0, _tex_y[1]);
  1881. v[11].tex.set(tex_x[1][0], _tex_y[1]);
  1882. v[12].tex.set(tex_x[1][1], _tex_y[1]);
  1883. v[13].tex.set(tex_t , _tex_y[1]);
  1884. v[14].tex.set(tex_x[2][0], _tex_y[1]);
  1885. v[15].tex.set(tex_x[2][1], _tex_y[1]);
  1886. v[16].tex.set( 0, 1);
  1887. v[17].tex.set(tex_x[2][0], 1);
  1888. v[18].tex.set(tex_x[2][1], 1);
  1889. v[19].tex.set(tex_t , 1);
  1890. }
  1891. if(image.partial())REP(vtxs)v[i].tex*=image._part.xy;
  1892. VI.flushIndexed(_same_x ? IndBufPanel : IndBufPanelEx, 3*3*2*3);
  1893. }
  1894. VI.clear();
  1895. }
  1896. /******************************************************************************/
  1897. void PanelImage::drawBaseLines(C Color &line_color, C Rect &rect)C
  1898. {
  1899. Rect r=rect; r.swapY();
  1900. Vec2 lt=r.lerp (_tex_left_top ),
  1901. rb=r.lerp (_tex_right_bottom);
  1902. Flt y1=r.lerpY(_tex_y[0] ),
  1903. y2=r.lerpY(_tex_y[1] );
  1904. Rect(lt, rb).draw(line_color, false);
  1905. D.lineX(line_color, y1, lt.x, rb.x);
  1906. D.lineX(line_color, y2, lt.x, rb.x);
  1907. REP(2)D.lineY(line_color, r.lerpX(_tex_x[0][i]), lt.y, y1 );
  1908. REP(2)D.lineY(line_color, r.lerpX(_tex_x[1][i]), y1 , y2 );
  1909. REP(2)D.lineY(line_color, r.lerpX(_tex_x[2][i]), y2 , rb.y);
  1910. }
  1911. void PanelImage::drawScaledLines(C Color &line_color, C Rect &rect)C
  1912. {
  1913. Flt scale; Bool scale_do=getSideScale(rect, scale);
  1914. Flt l =rect.min.x, r =rect.max.x, x[3][2], // [y][x]
  1915. y0=rect.max.y, y3=rect.min.y, y1, y2;
  1916. if(scale_do)
  1917. {
  1918. y1 =y0-_size_y[0] *scale;
  1919. y2 =y3+_size_y[1] *scale;
  1920. x[0][0]=l +_size_x[0][0]*scale;
  1921. x[0][1]=r -_size_x[0][1]*scale;
  1922. x[1][0]=l+_size_x[1][0]*scale;
  1923. x[1][1]=r-_size_x[1][1]*scale;
  1924. x[2][0]=l+_size_x[2][0]*scale;
  1925. x[2][1]=r-_size_x[2][1]*scale;
  1926. if(_padd_any)
  1927. {
  1928. Flt padd;
  1929. padd=_padd.x*(_force_uniform_stretch[0] ? rect.w() : scale); l -=padd; r +=padd;
  1930. padd=_padd.y*(_force_uniform_stretch[1] ? rect.h() : scale); y0+=padd; y3-=padd;
  1931. }
  1932. }else
  1933. {
  1934. y1 =y0-_size_y[0];
  1935. y2 =y3+_size_y[1];
  1936. x[0][0]=l +_size_x[0][0];
  1937. x[0][1]=r -_size_x[0][1];
  1938. x[1][0]=l+_size_x[1][0];
  1939. x[1][1]=r-_size_x[1][1];
  1940. x[2][0]=l+_size_x[2][0];
  1941. x[2][1]=r-_size_x[2][1];
  1942. if(_padd_any)
  1943. {
  1944. if(_force_uniform_stretch[0]){Flt padd=_padd.x*rect.w(); l -=padd; r +=padd;}else{l -=_padd.x; r +=_padd.x;}
  1945. if(_force_uniform_stretch[1]){Flt padd=_padd.y*rect.h(); y0+=padd; y3-=padd;}else{y0+=_padd.y; y3-=_padd.y;}
  1946. }
  1947. }
  1948. Rect(l, y3, r, y0).draw(line_color, false);
  1949. D.lineX(line_color, y1, l, r);
  1950. D.lineX(line_color, y2, l, r);
  1951. REP(2)D.lineY(line_color, x[0][i], y0, y1);
  1952. REP(2)D.lineY(line_color, x[1][i], y1, y2);
  1953. REP(2)D.lineY(line_color, x[2][i], y2, y3);
  1954. }
  1955. /******************************************************************************/
  1956. void PanelImage::drawInnerPadding(C Color &line_color, C Rect &rect)C
  1957. {
  1958. Rect padding; innerPadding(rect, padding);
  1959. padding.min=rect.min+padding.min;
  1960. padding.max=rect.max-padding.max;
  1961. padding.draw(line_color, false);
  1962. }
  1963. /******************************************************************************/
  1964. Bool PanelImage::save(File &f)C
  1965. {
  1966. f.putUInt(CC4_PIMG);
  1967. f.cmpUIntV(1);
  1968. f<<_same_x<<_padd_any<<_force_uniform_stretch<<_size_x<<_size_y<<_tex_x<<_tex_y<<_side_size<<_padd<<_tex_left_top<<_tex_right_bottom<<_inner_padding;
  1969. if(!image.save(f))return false;
  1970. return f.ok();
  1971. }
  1972. Bool PanelImage::load(File &f)
  1973. {
  1974. if(f.getUInt()==CC4_PIMG)switch(f.decUIntV())
  1975. {
  1976. case 1:
  1977. {
  1978. f>>_same_x>>_padd_any>>_force_uniform_stretch>>_size_x>>_size_y>>_tex_x>>_tex_y>>_side_size>>_padd>>_tex_left_top>>_tex_right_bottom>>_inner_padding;
  1979. if(!image.load(f))goto error;
  1980. if(f.ok())return true;
  1981. }break;
  1982. case 0:
  1983. {
  1984. f>>_same_x>>_padd_any>>_force_uniform_stretch>>_size_x>>_size_y>>_tex_x>>_tex_y>>_side_size>>_padd>>_tex_left_top>>_tex_right_bottom;
  1985. _inner_padding.set(_size_x[1][0], _size_y[1], _size_x[1][1], _size_y[0]);
  1986. if(!image.load(f))goto error;
  1987. if(f.ok())return true;
  1988. }break;
  1989. }
  1990. error:
  1991. del(); return false;
  1992. }
  1993. Bool PanelImage::save(C Str &name)C
  1994. {
  1995. File f; if(f.writeTry(name)){if(save(f) && f.flush())return true; f.del(); FDelFile(name);}
  1996. return false;
  1997. }
  1998. Bool PanelImage::load(C Str &name)
  1999. {
  2000. File f; if(f.readTry(name))return load(f);
  2001. del(); return false;
  2002. }
  2003. /******************************************************************************/
  2004. }
  2005. /******************************************************************************/