y_colours - Copy.inc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. /**--------------------------------------------------------------------------**\
  2. ==========================
  3. y_colours - X11 colours!
  4. ==========================
  5. Description:
  6. This holds the colour information that used to be part of the text system
  7. but which is far more useful than just for text. This now supports the full
  8. set of X11 colours, both by name and by definition. You can also define
  9. your own if you so choose (up to 32 - should be enough given that this
  10. includes the X11 colours).
  11. Legal:
  12. Version: MPL 1.1
  13. The contents of this file are subject to the Mozilla Public License Version
  14. 1.1 (the "License"); you may not use this file except in compliance with
  15. the License. You may obtain a copy of the License at
  16. http://www.mozilla.org/MPL/
  17. Software distributed under the License is distributed on an "AS IS" basis,
  18. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  19. for the specific language governing rights and limitations under the
  20. License.
  21. The Original Code is the YSI colours include.
  22. The Initial Developer of the Original Code is Alex "Y_Less" Cole.
  23. Portions created by the Initial Developer are Copyright (C) 2011
  24. the Initial Developer. All Rights Reserved.
  25. Contributors:
  26. ZeeX, koolk, JoeBullet/Google63, g_aSlice/Slice
  27. Thanks:
  28. JoeBullet/Google63 - Handy arbitrary ASM jump code using SCTRL.
  29. ZeeX - Very productive conversations.
  30. koolk - IsPlayerinAreaEx code.
  31. TheAlpha - Danish translation.
  32. breadfish - German translation.
  33. Fireburn - Dutch translation.
  34. yom - French translation.
  35. 50p - Polish translation.
  36. Zamaroht - Spanish translation.
  37. Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes
  38. for me to strive to better.
  39. Pixels^ - Running XScripters where the idea was born.
  40. Matite - Pestering me to release it and using it.
  41. Very special thanks to:
  42. Thiadmer - PAWN, whose limits continue to amaze me!
  43. Kye/Kalcor - SA:MP.
  44. SA:MP Team past, present and future - SA:MP.
  45. Version:
  46. 1.0
  47. Changelog:
  48. 06/01/14:
  49. Added embeddable versions of all colours.
  50. Cached all macros for faster compilation.
  51. Added "GT" macro for "~r~" use in SA:MP text.
  52. Split gametext colours in to a separate file.
  53. 20/02/12:
  54. Added broadcastfunc of colours.
  55. 29/11/10:
  56. Added the ability to use "X11" prefixes in strings.
  57. Added colourspace resolution for converting {FF0000} to ~r~.
  58. 25/11/10:
  59. First version.
  60. \**--------------------------------------------------------------------------**/
  61. #if defined _INC_y_colours
  62. #endinput
  63. #endif
  64. #define _INC_y_colours
  65. #include "..\YSI_Internal\y_version"
  66. #include "..\YSI_Coding\y_stringhash"
  67. #include "..\YSI_Core\y_debug"
  68. #include "..\YSI_Coding\y_remote"
  69. #include "..\YSI_Core\y_utils"
  70. #if !defined MAX_TEXT_COLOURS
  71. #if defined MAX_TEXT_COLORS
  72. #define MAX_TEXT_COLOURS MAX_TEXT_COLORS
  73. #else
  74. #define MAX_TEXT_COLOURS (32)
  75. #endif
  76. #endif
  77. #if !defined NO_X11_COLOURS && !defined NO_X11_COLORS && !defined YSI_NO_X11
  78. #define _YSI_USE_X11 true
  79. #else
  80. #define _YSI_USE_X11 false
  81. #endif
  82. // Note that these are VERY unsafe, they're not designed for general use!
  83. #define MK_RGB(%0,%1,%2) ((%0)<<24|(%1)<<16|(%2)<<8|0xAA)
  84. #define MK_RGBA(%0,%1,%2,%3) ((%0)<<24|(%1)<<16|(%2)<<8|(%3))
  85. #define MK_D_RGB(%0,%1,%2) ((%0)<<24|(%1)<<16|(%2)<<8|0xAA)
  86. #define MK_D_RGBA(%0,%1,%2,%3) ((%0)<<24|(%1)<<16|(%2)<<8|(%3))
  87. #define MK_S_RGB(%0,%1,%2) #%0#%1#%2
  88. #define MK_S_RGBA(%0,%1,%2,%3) #%0#%1#%2
  89. #define MK_S_DEF(%0) ((%0) >>> 8)
  90. #if _YSI_USE_X11
  91. #include "y_colours/x11def"
  92. #endif
  93. #include "y_colours/gtdef"
  94. // Special macro for adding game text colours.
  95. #define GT(%0) __hGT_%0
  96. #define __hGT_~%0~ {#AeC01e"}{"#__hGT_%0"}"
  97. // The two normal colour defines can be done with tag defines, and both using
  98. // the same recursive macro, but with different inputs.
  99. #define @GT(%0) (_:_@GT_:(__@GT_)%0)
  100. #define _GT(%0) (_:_@GT_:(___GT_)%0)
  101. #define _@GT_:(%1)~%0~ _@GT_:(%1%0)
  102. #define EMBED "{%06x}"
  103. #define COLOUR(%0) ((%0) >>> 8)
  104. #define COLOR(%0) ((%0) >>> 8)
  105. // This does redefine a possible colour, but with a very obscure pattern. Also
  106. // with awkward mixed case to not match "AEC01E" or "aec01e".
  107. #define AeC01e"}{"#%0"}"~h~ AeC01e"}{"#%0h"}"
  108. // Main code start. Apparently there is a copy of the hash code in y_td.
  109. #define COLOUR_NAME_HASH(%0) YHash((%0), false, hash_bernstein, (YSI_g_sCheckSpaces) ? (-1) : (strfind((%0), " ")))
  110. #define COLOR_NAME_HASH COLOUR_NAME_HASH
  111. #if !defined X11_ALLOW_SPACES
  112. #define X11_ALLOW_SPACES (false)
  113. #endif
  114. static stock
  115. YSI_g_sColours[MAX_TEXT_COLOURS][2],
  116. bool:YSI_g_sCheckSpaces = X11_ALLOW_SPACES;
  117. remotefunc void:_SetColoursCanHaveSpaces(bool:set)
  118. {
  119. YSI_g_sCheckSpaces = set;
  120. }
  121. #define SetColorsCanHaveSpaces SetColoursCanHaveSpaces
  122. stock SetColoursCanHaveSpaces(bool:set)
  123. {
  124. // Set this true/false in ALL scripts, since the text system is distributed.
  125. broadcastfunc _SetColoursCanHaveSpaces(set);
  126. //return 1;
  127. }
  128. #define SetColor SetColour
  129. stock SetColour(const name[], color)
  130. {
  131. P:3("SetColour called: \"%s\", %i", name, color);
  132. #if _YSI_USE_X11
  133. //if (name[0] | 0x20 == 'x' && name[1] == '1' && name[2] == '1')
  134. if (!strcmp(name, "X11", true, 3))
  135. {
  136. if (name[3] == ' ' || name[3] == '_')
  137. {
  138. SetColourHash(COLOUR_NAME_HASH(name[4]), color);
  139. }
  140. else
  141. {
  142. SetColourHash(COLOUR_NAME_HASH(name[3]), color);
  143. }
  144. }
  145. else
  146. #endif
  147. {
  148. SetColourHash(COLOUR_NAME_HASH(name), color);
  149. }
  150. }
  151. stock SetColourHash(hash, color)
  152. {
  153. broadcastfunc _SetColourHash(hash, color);
  154. }
  155. #define SetColorHash SetColourHash
  156. remotefunc void:_SetColourHash(hash, color)
  157. {
  158. P:3("SetColourHash called: %i, %i", hash, color);
  159. color &= 0xFFFFFF00;
  160. #if _YSI_USE_X11
  161. new
  162. id = GetColourHash(hash);
  163. if (id != 0)
  164. {
  165. for (new i = 0; i != MAX_TEXT_COLOURS; ++i)
  166. {
  167. new
  168. iColor = YSI_g_sColours[i][0];
  169. if (iColor == hash)
  170. {
  171. YSI_g_sColours[i][1] = color;
  172. return; // i;
  173. }
  174. else if (iColor == 0)
  175. {
  176. // Tried to rename an X11 colour.
  177. return; // -1;
  178. }
  179. }
  180. }
  181. #endif
  182. for (new i = 0; i != MAX_TEXT_COLOURS; ++i)
  183. {
  184. new
  185. iColor = YSI_g_sColours[i][0];
  186. if (iColor == hash || iColor == 0)
  187. {
  188. YSI_g_sColours[i][0] = hash;
  189. YSI_g_sColours[i][1] = color;
  190. return; // i;
  191. }
  192. }
  193. return; // -1;
  194. }
  195. // This now uses REVERSE bernstein hash for switch compatibility.
  196. #define GetColor GetColour
  197. stock GetColour(const name[], alpha = 0xAA)
  198. {
  199. P:3("GetColour called: \"%s\", %i", name, alpha);
  200. //if (name[0] | 0x20 == 'x' && name[1] == '1' && name[2] == '2')
  201. #if _YSI_USE_X11
  202. if (!strcmp(name, "X11", true, 3))
  203. {
  204. if ((YSI_g_sCheckSpaces && name[3] == ' ') || name[3] == '_')
  205. {
  206. return GetColourHash(COLOUR_NAME_HASH(name[4]), alpha);
  207. }
  208. else
  209. {
  210. return GetColourHash(COLOUR_NAME_HASH(name[3]), alpha);
  211. }
  212. }
  213. else
  214. #endif
  215. {
  216. return GetColourHash(COLOUR_NAME_HASH(name), alpha);
  217. }
  218. }
  219. #define GetColorStream GetColourStream
  220. stock GetColourStream(const str[], &idx, alpha = 0xAA)
  221. {
  222. P:3("GetColourStream called: \"%s\", %i, %i", str, idx, alpha);
  223. // This doesn't work because the hash is backwards, not forwards. You can't
  224. // do a reverse hash incrementally. Actually you can, but not well.
  225. new
  226. pos = idx,
  227. ret = -1;
  228. #if _YSI_USE_X11
  229. //new
  230. // bool:checkSpace = YSI_g_sCheckSpaces;
  231. if (!strcmp(str[pos], "X11", true, 3))
  232. {
  233. pos += 3;
  234. if ((YSI_g_sCheckSpaces && str[pos] == ' ') || str[pos] == '_')
  235. {
  236. ++pos;
  237. }
  238. }
  239. ret = Colours_DoHashParse(str[pos], pos, YSI_g_sCheckSpaces);
  240. if (ret != -1)
  241. {
  242. idx = pos;
  243. return ret | alpha;
  244. }
  245. #endif
  246. // Do the incremental hash. This *should* be "idx = pos + 16;", but it
  247. // isn't as you shouldn't prefix custom colours with "X11" as they're not.
  248. new
  249. test = min(strlen(str[pos]), 16);
  250. while (test)
  251. {
  252. // This is a greedy test, and restricts custom text to 16 characters.
  253. ret = YHash(str[pos], false, hash_bernstein, test);
  254. for (new i = 0; i != MAX_TEXT_COLOURS; ++i)
  255. {
  256. new
  257. iColor = YSI_g_sColours[i][0];
  258. if (iColor == ret)
  259. {
  260. idx = pos + test;
  261. return alpha | YSI_g_sColours[i][1];
  262. }
  263. else if (iColor == 0)
  264. {
  265. break;
  266. }
  267. }
  268. --test;
  269. }
  270. return 0;
  271. }
  272. #define GetColorHash GetColourHash
  273. stock GetColourHash(hash, alpha = 0xAA)
  274. {
  275. P:3("GetColourHash called: %i, %i", hash, alpha);
  276. alpha &= 0xFF;
  277. // Do the REVERSE hash from YHash
  278. #pragma tabsize 4
  279. #if _YSI_USE_X11
  280. #include "y_colours/x11switch"
  281. #endif
  282. #pragma tabsize 4
  283. // Do the default code here.
  284. for (new i = 0; i != MAX_TEXT_COLOURS; ++i)
  285. {
  286. new
  287. iColor = YSI_g_sColours[i][0];
  288. if (iColor == hash)
  289. {
  290. return alpha | YSI_g_sColours[i][1];
  291. }
  292. else if (iColor == 0)
  293. {
  294. return 0;
  295. }
  296. }
  297. return 0;
  298. }
  299. #if _YSI_USE_X11
  300. static stock Colours_DoHashParse(const str[], &idx, bool:checkSpace)
  301. {
  302. // You can't use custom colours with the "#COLOR" format, but you can
  303. // with the "{COLOR}" format, this is to save on memory. It is in
  304. // theory possible to get it working with the hash format using an
  305. // incremental hash and compare. NOW SUPPORTED!
  306. #include "y_colours/x11parse"
  307. #pragma tabsize 4
  308. return -1;
  309. }
  310. #endif
  311. #define _COLOUR_GT_SPACE_DEF_0(%0) SAMP_GAME_TEXT_%0
  312. #define _COLOUR_GT_SPACE_DEF_1(%0) SAMP_GAME_TEXT_%0H
  313. #define _COLOUR_GT_SPACE_DEF_2(%0) SAMP_GAME_TEXT_%0HH
  314. #define _COLOUR_GT_SPACE_DEF_3(%0) SAMP_GAME_TEXT_%0HHH
  315. #define _COLOUR_GT_SPACE_DEF_4(%0) SAMP_GAME_TEXT_%0HHHH
  316. #define _COLOUR_GT_SPACE_DEF_5(%0) SAMP_GAME_TEXT_%0HHHHH
  317. #define _COLOUR_GT_SPACE(%0,%1) {('%0'|0x20)|(%1<<8),_COLOUR_GT_SPACE_DEF_%1(%0)>>>24,_COLOUR_GT_SPACE_DEF_%1(%0)>>16&0xFF,_COLOUR_GT_SPACE_DEF_%1(%0)>>8&0xFF}
  318. #define Colors_SAMPToGT Colours_SAMPToGT
  319. stock Colours_SAMPToGT(colour, start)
  320. {
  321. P:4("Colours_SAMPToGT called: %i", colour);
  322. // Find the closest matching game text colour to the given SA:MP colour.
  323. static const
  324. sc_aColours[][4] =
  325. {
  326. // These can't be used as you can't set text to them. You can
  327. // however use them at the start by not changing.
  328. _COLOUR_GT_SPACE(X,0), _COLOUR_GT_SPACE(X,1),
  329. _COLOUR_GT_SPACE(X,2),
  330. _COLOUR_GT_SPACE(R,0), _COLOUR_GT_SPACE(R,1),
  331. _COLOUR_GT_SPACE(R,2), _COLOUR_GT_SPACE(R,3),
  332. _COLOUR_GT_SPACE(R,4), _COLOUR_GT_SPACE(R,5),
  333. _COLOUR_GT_SPACE(G,0), _COLOUR_GT_SPACE(G,1),
  334. _COLOUR_GT_SPACE(G,2), _COLOUR_GT_SPACE(G,3),
  335. //_COLOUR_GT_SPACE(G,4), // Don't want this twice (see Y2).
  336. _COLOUR_GT_SPACE(B,0), _COLOUR_GT_SPACE(B,1),
  337. _COLOUR_GT_SPACE(B,2), _COLOUR_GT_SPACE(B,3),
  338. _COLOUR_GT_SPACE(Y,0), _COLOUR_GT_SPACE(Y,1),
  339. _COLOUR_GT_SPACE(Y,2),
  340. _COLOUR_GT_SPACE(P,0), _COLOUR_GT_SPACE(P,1),
  341. _COLOUR_GT_SPACE(P,2),
  342. _COLOUR_GT_SPACE(W,0),
  343. _COLOUR_GT_SPACE(L,0)
  344. };
  345. new
  346. dist = cellmax,
  347. found = '\0',
  348. r = colour >> 16,
  349. g = (colour >> 8) & 0xFF,
  350. b = colour & 0xFF,
  351. tr, tg, tb, cur;
  352. for ( ; start != sizeof (sc_aColours); ++start)
  353. {
  354. tr = r - sc_aColours[start][1],
  355. tg = g - sc_aColours[start][2],
  356. tb = b - sc_aColours[start][3],
  357. cur = (tr * tr) + (tg * tg) + (tb * tb);
  358. P:6("Colours_SAMPToGT: Test %x %d", sc_aColours[start][0], cur);
  359. if (cur < dist)
  360. {
  361. P:6("Colours_SAMPToGT: Change %x %d", found, dist);
  362. // This may sometimes give odd results in fades for draw results.
  363. // Though I've not seen it happen yet.
  364. dist = cur,
  365. found = sc_aColours[start][0];
  366. }
  367. }
  368. return found;
  369. }
  370. stock Colours_EncodeGameText(str[])
  371. {
  372. new
  373. ret;
  374. if (str[0] == '~')
  375. {
  376. switch (str[1] | 0x20)
  377. {
  378. case 'r', 'g', 'b', 'y', 'p', 'w', 'l', 'x':
  379. {
  380. ret = str[1] | 0x20;
  381. }
  382. case 'h':
  383. {
  384. ret = 0x100 | 'x';
  385. }
  386. default: return 0;
  387. }
  388. if (str[2] != '~') return 0;
  389. new
  390. pos = 3;
  391. while (str[pos++] == '~' && str[pos++] | 0x20 == 'h' && str[pos++] == '~')
  392. {
  393. ret += 0x100;
  394. }
  395. }
  396. return ret;
  397. }