Advertisement
TheSixth

Font EX

Oct 12th, 2018
390
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 64.52 KB | None | 0 0
  1. #===============================================================================
  2. # * [ACE] Font EX
  3. #===============================================================================
  4. # * Made by: Sixth (www.rpgmakervxace.net, www.forums.rpgmakerweb.com)
  5. # * Version: 1.3
  6. # * Updated: 25/10/2018
  7. # * Requires: -------
  8. #-------------------------------------------------------------------------------
  9. # * < Change Log >
  10. #-------------------------------------------------------------------------------
  11. # * Version 1.0 (27/11/2017)
  12. #   - Initial release.
  13. # * Version 1.1 (18/03/2018)
  14. #   - Fixed a specific issue with automatic line breaks and manual line breaks.
  15. #     This issue happened only if the line which triggered the auto line break
  16. #     is a single "word", and if the previous line had a manual line break
  17. #     before a space (going backwards).
  18. #   - Fixed some horizontal and vertical spacing issues. A lot of them.
  19. #   - Added an option to enable the horizontal justified alignment type for
  20. #     lines which consist of a single long word. If you enable it, the spacing
  21. #     between the letters on these specific lines will be set to the same value,
  22. #     or at least close to that (can't break down pixels to float values, so
  23. #     there can be some inconsistency in the spacing, but that can only be seen
  24. #     when your letters are kinda big compared to the reserved width of these
  25. #     lines).
  26. # * Version 1.2 (10/10/2018)
  27. #   - Changed the setting area for the preload feature. You can now specify
  28. #     which character images to preload for each font style separately.
  29. # * Version 1.3 (25/10/2018)
  30. #   - Added hue change option.
  31. #   - Changed the cache clearing method to support clearing different hue
  32. #     variants of character images.
  33. #   - Added an option to display the text drawing area for individual texts for
  34. #     easier debugging.
  35. #   - Fixed a typo in the script call details. Opps!
  36. #-------------------------------------------------------------------------------
  37. # * < Description >
  38. #-------------------------------------------------------------------------------
  39. # * This is a scripter's tool, so it won't do anything by itself!
  40. # * With this script, you can display text using images on any bitmap object.
  41. # * The default text drawing method won't let you make fancy styles for your
  42. #   fonts, it won't let you control the spacing between each characters, and
  43. #   it can also be kinda slow. These were the main reasons I wrote this script.
  44. # * The new text drawing method has the following features:
  45. #   - Automatic line-breaks.
  46. #   - Separate alignment options horizontally and vertically (with automatic
  47. #     line-breaks!).
  48. #     Available alignment options:
  49. #     ~ Left (horizontal) / Top (vertical)
  50. #     ~ Middle
  51. #     ~ Right (horizontal) / Bottom (vertical)
  52. #     ~ Justified
  53. #   - Full control over the horizontal spacing between each characters.
  54. #     You can make default spacing settings and specific spacing settings which
  55. #     will only trigger between the 2 specified characters.
  56. #   - Full control over the speed of the character drawing.
  57. #     You can setup a wait time for character drawing and make it wait that
  58. #     many frames before the next character is drawn.
  59. #   - Message sound effects.
  60. #     Setup an SE for the character drawing. Use randomized effects or static
  61. #     ones, play the effect after each characters or after several characters
  62. #     periodically.
  63. #   - Setup speed up keys for your messages.
  64. #     In case your message's wait time is greater than 1 frame, you can
  65. #     designate a key which when pressed will speed up the character drawing.
  66. #   - Setup skip keys for your messages.
  67. #     In case your message is not an instant one, you can designate a key which
  68. #     when pressed will draw the remaining text instantly.
  69. #   - Setup "wait for key input" pauses in your messages.
  70. #     If you want to display your text periodically, with breaks between each
  71. #     section, you can do by assigning break points in your text.
  72. #   - Setup automatic position and width changes for each lines.
  73. #     Sometimes we can't predict the exact line number where some words or
  74. #     characters will end up, but we want to make sure that out text is
  75. #     displayed in a well structured manner. And guess what? We are so lazy, we
  76. #     want it to be done automatically whatever we may write in our messages! :D
  77. #     Well, that is now possible, just setup the starting position and width of
  78. #     each specific lines, and it's done!
  79. #   - Setup automatic height changes for each lines.
  80. #     The same principle as for the previous feature. Being lazy enough, we
  81. #     surely don't want to format our text manually. What would be the point
  82. #     of automatic line-breaks that way, right? So, if you want to, you can
  83. #     setup the height of each specific lines in advance, and forget about it,
  84. #     the drawing will do the rest for you automatically.
  85. #   - Built-in text replacing message codes.
  86. #     Just some basic stuffs here, such as:
  87. #     ~ Variable value display.
  88. #     ~ Actor name display (based on actor ID or party position).
  89. #     ~ Actor's class name display (based on actor ID or party position).
  90. #     ~ Skill, item, weapon, armor name display.
  91. #   - Built-in special message codes:
  92. #     ~ Drawing position modifier codes for moving the next character
  93. #       left/right or moving the next line up/down.
  94. #     ~ Wait time modifier code to change the wait time from the next character.
  95. #     ~ Style changing code to change the font style used during the drawing.
  96. #     ~ Break point code to stop the text drawing until a key is pressed.
  97. #   - And of course, image based text drawing. Not the static one with static
  98. #     character spacing, but the dynamic one with many customization options
  99. #     right off the bat! The drawing method also uses the cache to speed up the
  100. #     drawing, so it will most probably be much faster than the default text
  101. #     drawing method.
  102. #   - Ohh, and it works on ANY bitmap, so you can use it on ANY sprites/planes!
  103. #-------------------------------------------------------------------------------
  104. # * < Image Setup >
  105. #-------------------------------------------------------------------------------
  106. # * First thing first, you must setup your character images before you can
  107. #   actually use this text drawing method, obviously.
  108. #   I won't lie, this can be a pretty boring job, but once it's done, you can
  109. #   use the completed character set any time you want in the future.
  110. # * Each font style used by this script must be in it's own separate folder!
  111. #   You can setup the folder used for each font style separately in the script
  112. #   settings, so you have full control over this too.
  113. # * You must have an image for each characters you use in your texts, even if
  114. #   they are only used once during a 120 hours game (which is highly unlikely,
  115. #   but still :D)! However, if you are sure that a character will not appear in
  116. #   a given font style ever during your game, it is safe to leave that character
  117. #   out from that font style's folder.
  118. # * The character images themselves must all have the same height in the same
  119. #   style! This is to let you adjust the vertical positions of your characters
  120. #   manually, since doing this automatically would lead to a pretty convoluted
  121. #   setting area, which is not what most of us want, right?
  122. #   This means that the height of your characters will always be the height
  123. #   between the top of the tallest character and the bottom of the smallest
  124. #   character. Well, this is the only way I can explain it, but if it's not
  125. #   enough, you can check the PSD files in each font style folder, and check the
  126. #   "Guide Lines" layer folder to see what I mean. I marked the important
  127. #   vertical positioning lines there, so that I always know the vertical
  128. #   positioning of my characters. Note that those layers are only there as a
  129. #   guide, they do not affect anything in this script, nor are they needed for
  130. #   this script to work!
  131. # * There can be no empty pixels on the left or right side on your character
  132. #   images! The automatic character width calculation is based on the width of
  133. #   the character images, that's why there should be no useless empty pixels
  134. #   on the sides. The spacing between the characters itself can be setup for
  135. #   each font styles separately in the script settings, so this part is not on
  136. #   your character images at all.
  137. # * You can have whatever drawn on your character images. This script is meant
  138. #   to be used for text drawing, but that is not the only thing you can draw
  139. #   with it, it all depends on what you have on your character images.
  140. #-------------------------------------------------------------------------------
  141. # * < Usage Information >
  142. #-------------------------------------------------------------------------------
  143. # * No surprise, but you will need scripting knowledge to use this script.
  144. #   For that reason, I will explain this part in a way that assumes that the
  145. #   reader has sufficient knowledge about the relevant classes and scripting
  146. #   in general.
  147. #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  148. # * Here is the method call to trigger the new text drawing method:
  149. #
  150. #     draw_text_fex_a( * options go here * )
  151. #
  152. #   This method must be called on a Bitmap object!
  153. #
  154. #   You have several named options you can use as arguments. All of them are
  155. #   optional except the :txt argument, obviously. If you omit them, a default
  156. #   value will be loaded for them automatically. The default values will be
  157. #   noted for each options below.
  158. #
  159. #   Here are all the options you can use:
  160. #
  161. #     :x => value,   # Default value: 0
  162. #     :y => value,   # Default value: 0
  163. #     :w => value,   # Default value: the bitmap's width
  164. #     :h => value,   # Default value: the bitmap's height
  165. #   These will setup the drawing area on the bitmap. The drawing area plays a
  166. #   huge part in text positioning along with the used alignment options.
  167. #   All of them can be a single integer number representing pixels.
  168. #   Aside from setting up a single value for them, you can also setup automatic
  169. #   drawing area changes based on line numbers. This option is available for the
  170. #   :x and :w arguments. To set them up this way, you will have to use a hash
  171. #   with the following options:
  172. #     :default => value,
  173. #   This sets the default value. If a line does not have a custom value set up,
  174. #   this value will be used automatically.
  175. #     [line_num1,line_num2,...] => value,
  176. #   This sets up custom values for the specified line numbers.
  177. #   For example, setting up the :x argument like this:
  178. #     :x => { :default => 4, [*4..7] => 82, [*12..16] => 46 },
  179. #   Will make the starting X position for line 4 to 7 set to 82, and for line
  180. #   12 to 16 it will be set to 46. Any other lines will use 4 automatically.
  181. #   Naturally, this would only make sense if you also change the :w argument
  182. #   the same way, since otherwise you might get some text cut down on some
  183. #   lines, or end up with a weirdly formatted text layout.
  184. #   Using these options along with the alignment options you are able to format
  185. #   your text layout in very specific ways.
  186. #
  187. #     :vs => value,   # Default value: loaded from the 'VertSp' settings
  188. #   This will setup a custom vertical spacing between the lines.
  189. #   In case you want to use a custom vertical spacing between your lines for
  190. #   different texts, you can do so with this option.
  191. #   Note that the vertical spacing is just the extra pixels added after each
  192. #   lines, so it doesn't include the line's height! The line's height is
  193. #   calculated automatically based on the height of your character images.
  194. #   You can use a single integer value for this argument, or you can use a hash
  195. #   to setup the vertical spacing for each lines separately, just like you can
  196. #   with the :x and :w options.
  197. #
  198. #     :ah => value,   # Default value: 0
  199. #     :av => value,   # Default value: 0
  200. #   These are the text alignment types used for the text drawing.
  201. #   You can setup the horizontal (:ah) and vertical (:av) alignments separately
  202. #   for more control over the text layout.
  203. #   It's important to note that the alignment options will work even for
  204. #   automatic line breaks! No other drawing methods I saw so far can do this.
  205. #   Both of them can take 4 values, so you have 4 options for each of them.
  206. #   0 - Left (horizontal) / Top (vertical)
  207. #   1 - Middle (both)
  208. #   2 - Right (horizontal) / Bottom (vertical)
  209. #   3 - Justified (both)
  210. #   Most of these alignment types are pretty self-explanatory.
  211. #   Just to note an important fact:
  212. #   The horizontal alignment will affect the horizontal placement of the text
  213. #   together with your :x and :w options.
  214. #   The vertical alignment will affect the vertical placement of the text
  215. #   together with your :y and :h options.
  216. #   The mentioned options are closely related, never forget this!
  217. #   And a little extra not for the justified alignment options:
  218. #   In case you don't know, this alignment type means that the spacing between
  219. #   words (for horizontal alignment) and/or the spacing between lines (for
  220. #   vertical alignment) will be the exact same for each line.
  221. #   This will make each line have the exact same width (with 1 pixel difference
  222. #   at most) in the case of horizontal alignment, and it will make the text use
  223. #   up all of the available height for line-breaks in the case of vertical
  224. #   alignment. This alignment type is mostly used in newspapers, where each
  225. #   column of text has the same amount of width and the text columns have sharp
  226. #   "edges" to clearly divide the columns from each other.
  227. #   In the case of horizontal alignment, the lines will only trigger the
  228. #   justified version if the line-break itself was made automatically! Manual
  229. #   line breaks will simply apply the left side alignment for the line.
  230. #   Well, if you want to know more about this alignment type, feel free to use
  231. #   the almighty google, or just check it in a text editor program you use.
  232. #
  233. #     :style => value,  # Default value: 'default'
  234. #   This option will setup the font style used for the text drawing.
  235. #   Must be a string value, and a valid setting key from the 'Types' setting
  236. #   found in the script!
  237. #
  238. #     :opa => value,    # Default value: 255
  239. #   This will be the opacity of the text. Valid values: 0 - 255.
  240. #   Note that the opacity will also be influenced by the opacity of the
  241. #   sprite/plane the bitmap is assigned to.
  242. #
  243. #     :hue => value,    # Default value: 0
  244. #   The hue of the character images. Valid values: 0 - 360.
  245. #   In case you have a red character image set, and you don't want to make a
  246. #   new image set for a blue one with the same font style, you can change the
  247. #   hue value to make it blue without using a new image set.
  248. #   Note that each character image with different hue values will be loaded
  249. #   separately, so if you want to preload a style with multiple hue values, you
  250. #   will have to add the hue values in the 'Preload' settings, otherwise they
  251. #   won't be preloaded.
  252. #
  253. #     :wait => value,   # Default value: 0
  254. #   This will setup the wait time between each character drawing.
  255. #   Setting the value to 0 will make the text instant, while using positive
  256. #   numbers will make the text drawn character by character.
  257. #   Note that text sound effects can not be played for instant texts for pretty
  258. #   obviosu reasons.
  259. #   The wait time can be skipped and/or sped up by the player during the game if
  260. #   you also use the :skip_key and/or :spd_key arguments for the text.
  261. #  
  262. #     :se => [file,volume,pitch,freq],     # Default value: nil
  263. #   This will setup a sound effect which will play after each character or after
  264. #   each set of characters.
  265. #   The file, volume and pitch options can take single values or an array with
  266. #   multiple values. If you use an array for them, a random value will be
  267. #   selected from the array each time the sound effect is triggered.
  268. #   The values for the file option must be strings, and they must be valid
  269. #   sound effect file names.
  270. #   The values for the volume option must be integer numbers from 0 to 100.
  271. #   The values for the pitch option must be integer numbers from 0 to 150.
  272. #   Although I am not sure what is the highest value the pitch option can really
  273. #   take, so that maximum value I noted above might be off.
  274. #   The freq option must be an positive integer number! If you use 1, the sound
  275. #   effect will be played after each character. If you use some higher values,
  276. #   the sound effect will only play after that many characters.
  277. #   If you don't use the :se option, there will be no sound effects played for
  278. #   the text. Instant texts can not play sound effects for obvious reasons.
  279. #  
  280. #     :spd_key => value,    # Default value: nil
  281. #   If you use this option, and if the :wait option is set to something higher
  282. #   than 1, the player can speed up the text drawing by holding down the
  283. #   specified key.
  284. #   The value must be a valid key symbol. If you use a custom input script, you
  285. #   can use the key identifiers used from that script as well, as long as the
  286. #   custom input script uses the default Input check methods for checking key
  287. #   presses.
  288. #   If you don't use this option, the player won't be able to speed up the text
  289. #   display.
  290. #
  291. #     :skip_key => value,   # Default value: nil
  292. #   If you use this option, and if the text is not an instant one, the player
  293. #   can press a key to display the text instantly.
  294. #   It takes the same values as the previous argument option.
  295. #   Note that if the text got some break points set up with the provided
  296. #   message code for it, the text will only be displayed to the next break
  297. #   point! The player must pass the break point by pressing the specified key
  298. #   set up for it in the message code in order to be able to use the skip
  299. #   message key set up with this option again.
  300. #   If you don't use this option, the player won't be able to skip the text
  301. #   display.
  302. #
  303. #     :txt => "text",   # Default value: ""
  304. #   And finally, maybe the most important option, the text you want to display.
  305. #   Needless to say, this must be a string value.
  306. #   While it has a default value set up, using that wouldn't make any sense, so
  307. #   this option is kinda mandatory to use.
  308. #
  309. #     :debug => true,
  310. #   Using this option, you can enable the debug background for displaying the
  311. #   drawing area of the text. The color of the drawing area will be the same as
  312. #   the color you have setup in the 'Debug' settings.
  313. #   This option got no editable parts. You use it if you want to enable the
  314. #   debug background for the text, and you omit it if you don't want to display
  315. #   that background.
  316. #
  317. #   Quite a lot of options for a seemingly simple text drawing method, right?
  318. #   Well, options are always nice to have, so never hold back with them. :P
  319. #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  320. # * Here is the method call to update the new text drawing method:
  321. #  
  322. #     update_font_ex
  323. #
  324. #   This method must be called on each frame on any bitmaps where you want to
  325. #   display non-instant texts! Instant texts will be displayed even without
  326. #   updating the bitmap with this method.
  327. #   I added an option in the script which enables auto-updates for all bitmap
  328. #   objects, but if you would like to manually decide which bitmaps should
  329. #   update texts, you can simply disable that option and call this method on
  330. #   your bitmap manually.
  331. #  
  332. #   What's the point of calling it manually if there is an automatic way to do
  333. #   so? Well, even though not by much, doing it only on bitmaps with actual text
  334. #   drawing (so only if you need it) is better performance-wise.
  335. #   The only thing running on bitmaps without actual text drawing is the check
  336. #   for text data, so it really shouldn't slow down anything, but for
  337. #   perfectionists, I decided to allow the disabling of the automatic update
  338. #   method.
  339. #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  340. # * Here is the method to clear the font cache:
  341. #
  342. #     Cache.clear_font_ex('style_key', ['style_key',hue], ...)
  343. #
  344. #   The new text drawing method uses the cache to speed up the text drawing.
  345. #   The first time you draw a text with a font style, you might experience a
  346. #   small lag spike. That is when the character images are loaded into the
  347. #   cache. You can try to pre-load your character images to avoid this
  348. #   completely, in fact, I recommend you do so.
  349. #
  350. #   While I do not recommend clearing the font cache at all during the game, you
  351. #   can do it with this method.
  352. #   This method accepts any amount of arguments, so you can clear any amount of
  353. #   font styles with it from the cache.
  354. #  
  355. #   You can use 2 types of arguments:
  356. #
  357. #   1. A simple 'style_key' from the 'Types' setting area.
  358. #   This one will clear the character images used for the specified font style.
  359. #   If you use this type of argument, the code will assume that the hue value of
  360. #   the images needed to be cleared is 0 (which is the default hue value).
  361. #
  362. #   2. An array of 2 elements: 'style_key' and hue value, in this order.
  363. #   With this argument type, you can specify the hue value of the style you want
  364. #   to clear. Each hue value will have it's own character image stored in the
  365. #   cache, so if you want to get rid of them for real, you will have to clear
  366. #   all used hue variants as well.
  367. #
  368. #   You can combine the 2 argument types if needed.
  369. #   All characters from the specified font styles and hue values (if specified)
  370. #   will be cleared from the cache after this script call.
  371. #
  372. #   Leaving the character images in the cache should not consume much RAM, but
  373. #   it really depends on the file size of your character images, so I can't
  374. #   guarantee that it is impossible to overload the RAM with it. Although, doing
  375. #   that would require quite big file sizes, so the chance of that happening is
  376. #   very low.
  377. #-------------------------------------------------------------------------------
  378. # * < Built-in Text Message Codes >
  379. #-------------------------------------------------------------------------------
  380. # * I added several commonly used message codes which will automatically replace
  381. #   themselves with the specified data.
  382. #   Here is a list of these message codes:
  383. #
  384. #     <VAR: ID>    # Displays the value of the variable.
  385. #     <ANAME: ID>  # Displays the name of the actor based on actor ID.
  386. #     <MNAME: ID>  # Displays the name of the actor based on party position.
  387. #     <ACLASS: ID> # Displays the class of the actor based on actor ID.
  388. #     <MCLASS: ID> # Displays the class of the actor based on party position.
  389. #     <ANICK: ID>  # Displays the nickname of the actor based on actor ID.
  390. #     <MNICK: ID>  # Displays the nickname of the actor based on party position.
  391. #     <ITEM: ID>   # Displays the name of the item.
  392. #     <WEAPON: ID> # Displays the name of the weapon.
  393. #     <ARMOR: ID>  # Displays the name of the armor.
  394. #     <SKILL: ID>  # Displays the name of the skill.
  395. #     <STATE: ID>  # Displays the name of the state.
  396. #     <CLASS: ID>  # Displays the name of the class.
  397. #
  398. #   The message code identifiers (VAR, ACTOR, etc) are not case-sensitive, so if
  399. #   you prefer lower-case letters, you can write them that way too.
  400. #
  401. #   The variable display will be replaced first, so, in theory, you can display
  402. #   all other message codes based on a variable as well by using the variable
  403. #   message code as their ID. But I never tested this, so don't yell on me if
  404. #   this doesn't actually work. :P
  405. #
  406. #   If you want to add your own message codes, feel free to do so. Since this
  407. #   scriptt requires scripting knowledge, I won't explain how to do it. It is
  408. #   pretty easy to find these message codes in the code, so adding new ones
  409. #   should not be a problem for anyone.
  410. #-------------------------------------------------------------------------------
  411. # * < Built-in Function Message Codes >
  412. #-------------------------------------------------------------------------------
  413. # * These are message codes which will add some new features for your text
  414. #   drawing, or change some aspects of it during the drawing itself.
  415. #   Here is a list of available message codes in this section:
  416. #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  417. #     <S: FONT_STYLE>
  418. #
  419. #   Changes the font style.
  420. #   The new font style is loaded for the next normal character after this
  421. #   message code.
  422. #   You must replace the FONT_STYLE part with a valid setting key from the
  423. #   'Types' settings found in this script.
  424. #
  425. #   Note that if there are multiple font styles on the same line, the Y position
  426. #   of the characters will be the same, aligned to the bottom of the line height
  427. #   line. This means that in this case, some font styles might not look good if
  428. #   combined with other font styles if they got different heights. This all
  429. #   depends on how you position your characters on your images vertically, so if
  430. #   you plan your fonts well, they might not have any visual awkwardness at all.
  431. #
  432. #   Also, if there are multiple font styles on the same lines, the line height
  433. #   will be taken from the tallest font style to keep enough space for all
  434. #   characters.
  435. #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  436. #     <H: VALUE>
  437. #
  438. #   Changes the hue for the following characters.
  439. #   Replace VALUE with an integer number between 0 and 360.
  440. #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  441. #     <X: VALUE>      
  442. #
  443. #   Moves the rest of the line to the left or right.
  444. #   The X position added this way will be reset on each new lines!
  445. #   The VALUE must be a positive or negative integer number.
  446. #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  447. #     <Y: VALUE>      
  448. #
  449. #   Moves the next line this many pixels downwards.
  450. #   The rest of the lines below the first affected one will get their Y position
  451. #   corrected automatically.
  452. #   You can only use positive integer numbers for the VALUE here.
  453. #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  454. #     <W: VALUE>      
  455. #
  456. #   Sets up a new wait time between characters.
  457. #   The VALUE must be an integer number, positive or 0 (0 = instant text).
  458. #   Can be good to use if you want to display some parts of the text slower or
  459. #   quicker.
  460. #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  461. #     <K: KEY>        
  462. #
  463. #   Sets up a break point in the text.
  464. #   What is a break point? Well, it is a point where the text will stop
  465. #   advancing until the player presses a key.
  466. #   These break points can NOT be skipped with the :skip_key option used in the
  467. #   draw_text_fex script call, they can only be skipped by pressing the
  468. #   designated key you specified in this message code.
  469. #   The KEY must be replaced with a valid key identifier. If you use a custom
  470. #   input script, you can use the key identifiers from that script as well, as
  471. #   long as that custom input script uses the default Input check methods.
  472. #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  473. # * Note for scripters:
  474. #   All of the function message codes operate by recording the character
  475. #   positions they are placed in the text. This means that ALL of them must be
  476. #   obtained, processed and replaced with a single swoop, otherwise the recorded
  477. #   positions WILL get messed up. You are free to add in your own function codes
  478. #   if you want, just be aware that you can't simply do a .gsub! on the text
  479. #   because that will get you wrong position recordings. Check how this part of
  480. #   the code is written, you should be able to figure out the rest from there.
  481. #  
  482. #   As a last note, your message codes must NOT contain any > signs aside from
  483. #   the message code closure point! The regex I used will break the message
  484. #   code at the first > sign found, so if you would add that sign in the key or
  485. #   in the parameter of the message code, your message code will most probably
  486. #   NOT function at all.
  487. #-------------------------------------------------------------------------------
  488. # * < Installation >
  489. #-------------------------------------------------------------------------------
  490. # * Place this script below Materials but above Main!
  491. #-------------------------------------------------------------------------------
  492. # * < Compatibility Info >
  493. #-------------------------------------------------------------------------------
  494. # * No known incompatibilities.
  495. #-------------------------------------------------------------------------------
  496. # * < Known Issues >
  497. #-------------------------------------------------------------------------------
  498. # * No known issues.
  499. #-------------------------------------------------------------------------------
  500. # * < Terms of Use >
  501. #-------------------------------------------------------------------------------
  502. # * Free to use for whatever purposes you want.
  503. # * Credit me (Sixth) in your game, pretty please! :P
  504. # * Posting modified versions of this script is allowed as long as you notice me
  505. #   about it with a link to it!
  506. #===============================================================================
  507. $imported = {} if $imported.nil?
  508. $imported["SixthFontEX"] = true
  509. #===============================================================================
  510. # Settings:
  511. #===============================================================================
  512. module FontEX
  513.   #-----------------------------------------------------------------------------
  514.   # Character Settings:
  515.   #-----------------------------------------------------------------------------
  516.   # This is where you will setup the character list and their image names.
  517.   # Each character you want to use in any font style must be specified here.
  518.   #
  519.   # Format:
  520.   #
  521.   #   'character' => 'filename',
  522.   #
  523.   # The character can be any valid character, really.
  524.   # Although, sadly, the font type used in this editor does not support some
  525.   # (well, a lot of) extra character symbols, so you won't be able to set those
  526.   # up here.
  527.   #
  528.   # There are some extra characters which are normally not displayed, but you
  529.   # can still specify a filename for them and use them in your texts.
  530.   # One of them, for example, is the "\t" character, which denotes the paragraph
  531.   # character when the TAB key is pressed.
  532.   # The only special character which is processed automatically is the "\n"
  533.   # character which denotes a line-break. That won't be displayed at all, it
  534.   # will just start a new line, like it would normally.
  535.   #
  536.   # And this is a good place to state that you can insert a manual line-break
  537.   # with the "\n" character in your texts.
  538.   #
  539.   # The list I made contains most of the basic characters (letters, numbers,
  540.   # signs, etc) and some extra ones as well, but it is far from including all
  541.   # of the displayable characters, so feel free to add your own character
  542.   # settings here.
  543.   #
  544.   # The character images must be named the same way in all of your font style
  545.   # folders!
  546.   #
  547.   # I have noted some of the settings here with a "No image file setup!" line.
  548.   # That means that these characters don't have a character image for any font
  549.   # style I made, so they are unusable in your texts until you make an image
  550.   # for them.
  551.   #-----------------------------------------------------------------------------
  552.   Chs = {
  553.     # Spaces:
  554.     ' ' => 'space',
  555.     "\t" => 'tab',
  556.     # Lowercase letters:
  557.     'a' => 'a_lc',
  558.     'b' => 'b_lc',
  559.     'c' => 'c_lc',
  560.     'd' => 'd_lc',
  561.     'e' => 'e_lc',
  562.     'f' => 'f_lc',
  563.     'g' => 'g_lc',
  564.     'h' => 'h_lc',
  565.     'i' => 'i_lc',
  566.     'j' => 'j_lc',
  567.     'k' => 'k_lc',
  568.     'l' => 'l_lc',
  569.     'm' => 'm_lc',
  570.     'n' => 'n_lc',
  571.     'o' => 'o_lc',
  572.     'p' => 'p_lc',
  573.     'q' => 'q_lc',
  574.     'r' => 'r_lc',
  575.     's' => 's_lc',
  576.     't' => 't_lc',
  577.     'u' => 'u_lc',
  578.     'v' => 'v_lc',
  579.     'w' => 'w_lc',
  580.     'x' => 'x_lc',
  581.     'y' => 'y_lc',
  582.     'z' => 'z_lc',
  583.     # Uppercase letters:
  584.     'A' => 'a_uc',
  585.     'B' => 'b_uc',
  586.     'C' => 'c_uc',
  587.     'D' => 'd_uc',
  588.     'E' => 'e_uc',
  589.     'F' => 'f_uc',
  590.     'G' => 'g_uc',
  591.     'H' => 'h_uc',
  592.     'I' => 'i_uc',
  593.     'J' => 'j_uc',
  594.     'K' => 'k_uc',
  595.     'L' => 'l_uc',
  596.     'M' => 'm_uc',
  597.     'N' => 'n_uc',
  598.     'O' => 'o_uc',
  599.     'P' => 'p_uc',
  600.     'Q' => 'q_uc',
  601.     'R' => 'r_uc',
  602.     'S' => 's_uc',
  603.     'T' => 't_uc',
  604.     'U' => 'u_uc',
  605.     'V' => 'v_uc',
  606.     'W' => 'w_uc',
  607.     'X' => 'x_uc',
  608.     'Y' => 'y_uc',
  609.     'Z' => 'z_uc',
  610.     # Numbers:
  611.     '0' => '0',
  612.     '1' => '1',
  613.     '2' => '2',
  614.     '3' => '3',
  615.     '4' => '4',
  616.     '5' => '5',
  617.     '6' => '6',
  618.     '7' => '7',
  619.     '8' => '8',
  620.     '9' => '9',
  621.     # Signs:
  622.     '.' => 'point',
  623.     ',' => 'comma',
  624.     ';' => 'semicolon',
  625.     ':' => 'doublepoint',
  626.     '!' => 'exclamation',
  627.     '?' => 'question',
  628.     '_' => 'underscore',
  629.     "'" => 'apostrophe1',
  630.     '`' => 'apostrophe2',
  631.     #'’' => 'apostrophe3', # No image file setup!
  632.     '"' => 'quote',
  633.     #'“' => 'quote1', # No image file setup!
  634.     #'”' => 'quote2', # No image file setup!
  635.     '@' => 'at',
  636.     '#' => 'numero',
  637.     '$' => 'dollar',
  638.     '€' => 'euro',
  639.     '£' => 'pound',
  640.     "\\" => 'lbrace',
  641.     '/' => 'rbrace',
  642.     # Math:
  643.     '+' => 'plus',
  644.     '-' => 'minus',
  645.     '*' => 'multiply',
  646.     '÷' => 'divide',
  647.     '=' => 'equal',
  648.     '~' => 'approx',
  649.     '%' => 'percent',
  650.     '^' => 'on_square',
  651.     '&' => 'and',
  652.     '|' => 'or',
  653.     '(' => 'lbracket_normal',
  654.     ')' => 'rbracket_normal',
  655.     '[' => 'lbracket_square',
  656.     ']' => 'rbracket_square',
  657.     '{' => 'lbracket_curly',
  658.     '}' => 'rbracket_curly',
  659.     '<' => 'smaller',
  660.     '>' => 'higher',
  661.     # <-- Add more character settings here if needed!
  662.   }
  663.  
  664.   #-----------------------------------------------------------------------------
  665.   # Font Style Settings:
  666.   #-----------------------------------------------------------------------------
  667.   # This is the place where you can setup the identifiers and folders used for
  668.   # your different font styles.
  669.   # You will use the setting keys from this setting in all font style related
  670.   # things in the provided script calls and message codes.
  671.   #
  672.   # Format:
  673.   #
  674.   #   'style_key' => "folder_path/",
  675.   #
  676.   # You can make as many font style settings as you want.
  677.   #
  678.   # If you don't setup a :style argument for the text drawing script call,
  679.   # the 'default' font style will be used automatically.
  680.   #-----------------------------------------------------------------------------
  681.   Types = {
  682.     'default'     => "Graphics/FontEX/Microsoft Himalaya/s23_white_gray_grad/",
  683.     'mod_up'      => "Graphics/FontEX/Microsoft Himalaya/s23_green_grad/",
  684.     'card_name'   => "Graphics/FontEX/MatrixBoldSmallCaps/s23_black_white/",
  685.     'card_desc'   => "Graphics/FontEX/Tw Cen MT Condensed/s15_white/",
  686.     'card_desc2'  => "Graphics/FontEX/Tw Cen MT Condensed/s16_white_small_caps/",
  687.     'card_desc3'  => "Graphics/FontEX/Tw Cen MT Condensed/s16_black_small_caps/",
  688.     'check_value' => "Graphics/FontEX/Tw Cen MT Condensed/s20_white_small_caps/",
  689.     'hp_value'    => "Graphics/FontEX/WST_Engl/s21_green_grad/",
  690.     'ap_value'    => "Graphics/FontEX/WST_Engl/s21_yellow_grad/",
  691.     'lvl_value'   => "Graphics/FontEX/WST_Engl/s21_blue_grad/",
  692.     'xp_value'    => "Graphics/FontEX/WST_Engl/s20_blue_grad/",
  693.     'icons'       => "Graphics/FontEX/Icons/",
  694.     # <-- Add more font style settings here if needed!
  695.   }
  696.  
  697.   #-----------------------------------------------------------------------------
  698.   # Horizontal Spacing Settings:
  699.   #-----------------------------------------------------------------------------
  700.   # This is where you will setup the horizontal spacing between the characters
  701.   # for your font styles.
  702.   #
  703.   # You have multiple ways to set these up. I will list them now...
  704.   #
  705.   #   'rescue' => value,
  706.   # If the 'rescue' key is used, that means that this setting will be loaded for
  707.   # any characters which got no custom spacing setting set up.
  708.   # The very first setting here is a default spacing setting for ALL of your
  709.   # font styles. In case a font style got no setting at all here, or if a
  710.   # character got no spacing setting in a font style and the font style got no
  711.   # separate 'rescue' setting, this first 'rescue' setting will be used instead.
  712.   # You can have a 'rescue' setting for each of your font styles.
  713.   #
  714.   #   'character' => value,
  715.   # This one will setup the spacing used after the specified character. This
  716.   # spacing is only used for the specified character.
  717.   #
  718.   #   'character1character2' => value,
  719.   # And this one is the most specific spacing setting you can use.
  720.   # This will setup the spacing used between the 2 characters used in the
  721.   # setting key. This setting type will only be triggered if the character after
  722.   # 'character1' is 'character2'!
  723.   #
  724.   # So, by using the above setting options, you can setup a custom spacing
  725.   # setting group for each of your font styles. Just follow this format:
  726.   #
  727.   #   'style_key' => {
  728.   #     'setting1' => value,
  729.   #     'setting2' => value,
  730.   #     ...
  731.   #   },
  732.   #
  733.   # The 'style_key' must be a valid setting key used in the 'Types' setting
  734.   # area found above.
  735.   # You can add as many settings in these setting groups as you want, and you
  736.   # can make as many font style group settings as you want too.
  737.   #-----------------------------------------------------------------------------
  738.   HorzSp = {
  739.     'rescue' => 0, # Default spacing for all characters for all font styles
  740.     'default' => {
  741.       'rescue' => 0, # Default spacing for all characters for this style only
  742.       'av' => -2, # Spacing between lower-case a and v
  743.       'Av' => -1, # Spacing between upper-case A and lower-case v
  744.       'AV' => -1, # Spacing between upper-case A and V
  745.       'ly' => -1, # Spacing between lower-case l and y
  746.       'rv' => -1,
  747.     },
  748.     'mod_up' => {
  749.       'rescue' => -2, # Default spacing for all characters for this style only
  750.       'av' => -4, # Spacing between lower-case a and v
  751.       'Av' => -3, # Spacing between upper-case A and lower-case v
  752.       'AV' => -3, # Spacing between upper-case A and V
  753.       'ly' => -3, # Spacing between lower-case l and y
  754.     },
  755.     'card_name' => {
  756.       'rescue' => -1, # Default spacing for all characters for this style only
  757.     },
  758.     'card_desc' => {
  759.       'rescue' => 1, # Default spacing for all characters for this style only
  760.     },
  761.     'card_desc2' => {
  762.       'rescue' => 1, # Default spacing for all characters for this style only
  763.     },
  764.     'card_desc3' => {
  765.       'rescue' => 1, # Default spacing for all characters for this style only
  766.     },
  767.     'check_value' => {
  768.       'rescue' => 1, # Default spacing for all characters for this style only
  769.     },
  770.     'icons' => {
  771.       'rescue' => 2,
  772.     },
  773.     # <-- Add more horizontal spacing settings here if needed!
  774.   }
  775.  
  776.   #-----------------------------------------------------------------------------
  777.   # Vertical Spacing Settings:
  778.   #-----------------------------------------------------------------------------
  779.   # This is where you will setup the extra vertical spacing between the lines.
  780.   #
  781.   # The line height will be automatically calculated based on the character
  782.   # images' height. The vertical spacing value will be added to the line height,
  783.   # and the result will decide the Y position of the next line after a
  784.   # line-break.
  785.   #
  786.   # Format:
  787.   #
  788.   #   'style_key' => value,
  789.   #
  790.   # The 'style_key' must be a valid setting key used in the 'Types' setting
  791.   # area found above.
  792.   # The value is the amount of pixels to add to the line height (or in other
  793.   # words, the amount of pixels between each lines).
  794.   #
  795.   # Note that these are just the default values your font styles will use.
  796.   # You can use a custom vertical spacing value with the draw_text_fex method's
  797.   # :vs option if you want.
  798.   #
  799.   # The 'rescue' setting will be used automatically if there is no setting made
  800.   # for a font style and if no custom vertical spacing has been set up with the
  801.   # above mentioned :vs option.
  802.   #-----------------------------------------------------------------------------
  803.   VertSp = {
  804.     'rescue'      => 1, # Default for all font styles.
  805.     'default'     => 2,
  806.     'mod_up'      => 1,
  807.     'card_name'   => 2,
  808.     'card_desc'   => 4,
  809.     'card_desc2'  => 1,
  810.     'card_desc3'  => 1,
  811.     'check_value' => 2,
  812.     'icons' => 2,
  813.     # <-- Add more vertical spacing settings here if needed!
  814.   }
  815.    
  816.   #-----------------------------------------------------------------------------
  817.   # Preload Font Styles Settings:
  818.   #-----------------------------------------------------------------------------
  819.   # You can choose the font styles you want to be preloaded on game startup.
  820.   # Doing this will prevent the lag-spike which would happen otherwise the first
  821.   # time you use a font style with an instant text drawing.
  822.   # I recommend loading every commonly used font styles here, but it is your
  823.   # choice to do so at the end, it is not mandatory for this script to work.
  824.   #
  825.   # You have several ways of preloading your font styles here.
  826.   #
  827.   # 1. Load all characters for a font style:
  828.   #   To do this, simply enter a setting that looks like this:
  829.   #     'style_key' => {},
  830.   #   Replace the 'style_key' with a valid setting key from the 'Types' setting
  831.   #   area found above.
  832.   #   This will load the images for all of the characters you made in the 'Chs'
  833.   #   setting area.
  834.   #   If you use certain font styles for displaying numbers only, you shouldn't
  835.   #   load all characters for them, obviously, only the numbers, for example.
  836.   #
  837.   # 2. Load specific characters only:
  838.   #   To do this, enter a setting that looks like this:
  839.   #     'style_key' => {
  840.   #       :load => ['ch1', 'ch2', ..., 'chN'],
  841.   #     },
  842.   #   The 'style_key' is the same as in the above setting type.
  843.   #   The 'ch1', 'ch2', and so on, must be valid setting keys from the 'Chs'
  844.   #   setting area. Only the images for the entered characters will be
  845.   #   preloaded. The rest of the characters will only be loaded on demand, so
  846.   #   only if you use them during the game at any point.
  847.   #   You can enter as many character keys as you want in the array.
  848.   #   If you only use numbers from a font style, for example, this is the
  849.   #   setting type you should use for it. Same if you only have Russian letters
  850.   #   made for a font style and want to preload them, you will have to use this
  851.   #   type of setting in that case too.
  852.   #
  853.   # 3. Skip specific characters, load all others:
  854.   #   To do this, enter a setting that looks like this:
  855.   #     'style_key' => {
  856.   #       :skip => ['ch1', 'ch2', ..., 'chN'],
  857.   #     },
  858.   #   The editable parts are the same as in the previous setting type, but this
  859.   #   time, instead of specifying which ones to preload, you specifiy which ones
  860.   #   NOT to preload, in other words, which ones to skip.
  861.   #   All of the characters you enter into the array will be skipped, so they
  862.   #   won't be preloaded on startup, and all of the characters you DON'T enter
  863.   #   will be preloaded.
  864.   #
  865.   # These are the 3 ways you can setup the preload behaviour for your font
  866.   # styles.
  867.   #
  868.   # Additionally, you can mix the last 2 setting types if you want, but the use
  869.   # of that setting type is pretty limited, so I won't go into details on that.
  870.   #
  871.   # If you don't enter any settings for a font style here, the character images
  872.   # for that font type will NOT be preloaded at all. You can still use them in
  873.   # the game, of course, but they will only be loaded on demand and not on game
  874.   # startup.
  875.   #
  876.   # From v1.3, you can also enter preload settings for different hue values.
  877.   # You can do that by adding a setting option like this:
  878.   #   'style_key' => {
  879.   #     :hue => {
  880.   #       hue_value1 => { * :load or :skip setting here if needed * },
  881.   #       hue_value2 => { * :load or :skip setting here if needed * },
  882.   #       ...
  883.   #     },
  884.   #   },
  885.   # As you can see, you can add as many hue values as you want.
  886.   # Replace the hue_valueX parts with integer numbers between 0 and 360.
  887.   # Although using 0 is not necessary if you have setup the preload settings
  888.   # for the font style outside the :hue option, since those settings will load
  889.   # the default hue version of the character set, and the default hue is 0.
  890.   # And the :load/:skip settings are the same like in the "hue-less" setting
  891.   # options, so you can use them the same way.
  892.   # If you use a hue changed character set without preloading them, they will
  893.   # be loaded on demand only, just like the regular, not preloaded character
  894.   # images.
  895.   #-----------------------------------------------------------------------------
  896.   Preload = [
  897.     #'default' => {}, # Preload all letters
  898.     #'rus_1' => {
  899.     #  :load => [ # Load only these letters
  900.     #    'А','Б','В','Г','Д','Е','Ж','З','И','Й','К','Л','М','Н','О','П',
  901.     #    'Р','С','Т','У','Ф','Х','Ц','Ч','Ш','Щ','Ъ','Ы','Ь','Э','Ю','Я',
  902.     #  ],
  903.     #},
  904.   ]
  905.  
  906.   #-----------------------------------------------------------------------------
  907.   # Auto Update Settings:
  908.   #-----------------------------------------------------------------------------
  909.   # The bitmaps with non-instant text drawings must be updated in each frames.
  910.   # This script can do that automatically or you can do it manually yourself in
  911.   # your own code.
  912.   # Setting the below options to true will enable the automatic text drawing
  913.   # update for all bitmaps assigned for the specified objects.
  914.   # Set them to false to disable this feature for them.
  915.   #-----------------------------------------------------------------------------
  916.   Auto = {
  917.     :sprite => true,
  918.     :window => true,
  919.   }
  920.  
  921.   #-----------------------------------------------------------------------------
  922.   # Debug Settings:
  923.   #-----------------------------------------------------------------------------
  924.   # Sometimes it is annoying to guess the drawing area for the texts.
  925.   # Okay, it's always annoying...
  926.   # For that reason, I added a debug feature which will paint the specified
  927.   # drawing area for the texts drawn with this script.
  928.   #
  929.   # The setting options here should be self-explanatory.
  930.   #-----------------------------------------------------------------------------
  931.   Debug = {
  932.     :enable => false, # Set it to true to enable or false to disable.
  933.     :color => Color.new(255,100,100,220), # The color of the drawing area.
  934.   }
  935.  
  936.   #-----------------------------------------------------------------------------
  937.   # Miscellaneous Settings:
  938.   #-----------------------------------------------------------------------------
  939.   # Any other settings not fitting into the other setting areas will go here.
  940.   # For now, there is only one lonely option here...
  941.   #
  942.   #   :single => true/false,
  943.   # This is an experimental feature, and quite honestly, not very useful for
  944.   # most people. I explained what this option does in the update logs, so check
  945.   # for the details there.
  946.   # Setting this option to true will enable this feature, while setting it to
  947.   # false will disable it.
  948.   #-----------------------------------------------------------------------------
  949.   Misc = {
  950.     :single => false,
  951.   }
  952.  
  953. end
  954. #===============================================================================
  955. # End of settings! O.o
  956. #===============================================================================
  957.  
  958. module Cache
  959.  
  960.   @font_ex_cache = {}
  961.  
  962.   def self.font_ex(fname,folder,hue=0)
  963.     fky = [folder,hue]
  964.     @font_ex_cache[fky] = [] if @font_ex_cache[fky].nil?
  965.     @font_ex_cache[fky] << fname unless @font_ex_cache[fky].include?(fname)
  966.     load_bitmap(folder,fname,hue)
  967.   end
  968.  
  969.   def self.clear_font_ex(*styles)
  970.     styles.each do |style|
  971.       case style
  972.       when Array
  973.         folder = FontEX::Types[style[0]]
  974.         fky = [folder,style[1]]
  975.       else
  976.         folder = FontEX::Types[style]
  977.         fky = [folder,0]
  978.       end
  979.       next unless @font_ex_cache[fky]
  980.       @font_ex_cache[fky].each do |img|
  981.         if fky[1] == 0 # No hue change
  982.           ky = folder + img
  983.         else # Custom hue
  984.           ky = [folder + img,fky[1]]
  985.         end
  986.         @cache[ky].dispose
  987.         @cache.delete(ky)
  988.       end
  989.       @font_ex_cache.delete(fky)
  990.     end
  991.   end
  992.  
  993.   def self.preload_styles(styles)
  994.     styles.each do |style,sdt|
  995.       # Load normal characters, no hue change
  996.       letters = (sdt[:load] || FontEX::Chs.keys).clone
  997.       letters -= sdt[:skip] if sdt[:skip]
  998.       letters.each {|ch| Cache.font_ex(FontEX::Chs[ch],FontEX::Types[style],0) }
  999.       if sdt[:hue] # Load custom hue types if there is any
  1000.         sdt[:hue].each do |hue,hdt|
  1001.           letters = (hdt[:load] || FontEX::Chs.keys).clone
  1002.           letters -= hdt[:skip] if hdt[:skip]
  1003.           letters.each {|ch| Cache.font_ex(FontEX::Chs[ch],FontEX::Types[style],hue) }
  1004.         end
  1005.       end
  1006.     end
  1007.   end
  1008.  
  1009. end
  1010.  
  1011. Cache.preload_styles(FontEX::Preload)
  1012.  
  1013. class Bitmap
  1014.  
  1015.   attr_accessor :fex
  1016.      
  1017.   def char_horz_sp(char,style,nchar=nil)
  1018.     if nchar
  1019.       ky = char + nchar
  1020.       if FontEX::HorzSp[style] && FontEX::HorzSp[style][ky]
  1021.         return FontEX::HorzSp[style][ky]
  1022.       end
  1023.     end
  1024.     if FontEX::HorzSp[style] && FontEX::HorzSp[style][char]
  1025.       return FontEX::HorzSp[style][char] # There is a set value for the char
  1026.     elsif FontEX::HorzSp[style] && FontEX::HorzSp[style]['rescue']
  1027.       return FontEX::HorzSp[style]['rescue'] # There is a set value for the font style
  1028.     else
  1029.       return FontEX::HorzSp['rescue'] # Load default spacing value
  1030.     end
  1031.   end
  1032.  
  1033.   def char_vert_sp(vsp,style,lnum)
  1034.     if vsp.is_a?(Hash)
  1035.       sv = vsp.find {|lnums,nh| lnums.is_a?(Array) && lnums.include?(lnum) }
  1036.       vh = sv ? sv[1] : vsp[:default]
  1037.       vh = (FontEX::VertSp[style] || FontEX::VertSp['rescue']) if vh == :style
  1038.       return vh
  1039.     else
  1040.       return vsp
  1041.     end
  1042.   end
  1043.      
  1044.   def debug_back_paint(xx,yy,ww,hh)
  1045.     if xx.is_a?(Hash)
  1046.       mx = xx.values.min_by {|val| val }
  1047.     else
  1048.       mx = xx
  1049.     end
  1050.     if ww.is_a?(Hash)
  1051.       mw = ww.values.max_by {|val| val }
  1052.     else
  1053.       mw = ww
  1054.     end
  1055.     fill_rect(mx,yy,mw,hh,FontEX::Debug[:color])
  1056.   end
  1057.    
  1058.   def draw_text_fex_a(args={})
  1059.     if @fex.nil?
  1060.       @fex = []
  1061.     else
  1062.       @fex.reject! {|fdt| fdt[:done] }
  1063.     end
  1064.    
  1065.     # Setting up all the data for the text
  1066.     dt = {
  1067.       :x => 0, :y => 0, :w => self.width, :h => self.height, :wait => 0, :hue => 0,
  1068.       :ah => 0, :av => 0, :opa => 255, :style => 'default', :lines => {}, :debug => false,
  1069.       :mods => {'s' => {}, 'x' => {}, 'y' => {}, 'w' => {}, 'k' => {}, 'h' => {}},
  1070.       :done => false, :spd_key => nil, :skip_key => nil, :se => nil, :txt => "",
  1071.     }.merge(args)
  1072.     dt[:wait] -= 1
  1073.     dt[:num] = dt[:wait]
  1074.     dt[:vs] = (FontEX::VertSp[dt[:style]] || FontEX::VertSp['rescue']) if dt[:vs].nil?
  1075.     @fex << dt
  1076.     dt[:txt] = process_text_fex(dt[:txt])
  1077.     ori_font = dt[:style].clone
  1078.     ori_hue = dt[:hue]
  1079.    
  1080.     debug_back_paint(dt[:x],dt[:y],dt[:w],dt[:h]) if FontEX::Debug[:enable] || dt[:debug]
  1081.    
  1082.     ax = 0 # Stores the X value added after the last character
  1083.     ay = char_vert_sp(dt[:vs],dt[:style],0) # Vertical spacing
  1084.     tw = 0 # Total width
  1085.     ch_h = 0
  1086.     ci = 0
  1087.     hsp = 0
  1088.     ch_w = []
  1089.     r_h = [] # Records previous line height values
  1090.     rym = 0
  1091.     spaces = 0
  1092.     last = 0
  1093.     loop do
  1094.       ch = dt[:txt][ci,1] # Current character
  1095.       break if ch.nil? || ch == ""
  1096.       if dt[:mods]['s'][ci] # Style change found!
  1097.         dt[:style] = dt[:mods]['s'][ci]
  1098.         vsp = char_vert_sp(dt[:vs],dt[:style],dt[:lines].size)
  1099.         ay = vsp if ay < vsp
  1100.       end
  1101.       if dt[:mods]['h'][ci] # Hue change found!
  1102.         dt[:hue] = dt[:mods]['h'][ci]
  1103.       end
  1104.       if ch == "\n" || ch == "\r\n"
  1105.         lw = tw
  1106.         pch = dt[:txt][ci-1,1]
  1107.         lw -= char_horz_sp(pch,dt[:style]) if pch && pch != ""
  1108.         if spaces > 0
  1109.           clw = lwidth(dt[:w],dt[:lines].size)
  1110.           sp = (clw - lw)/spaces.to_f
  1111.         else
  1112.           clw = lwidth(dt[:w],dt[:lines].size)
  1113.           sp = clw - lw
  1114.         end
  1115.         dt[:lines][ci] = {:w => lw, :ch => ch_h, :vs => ay, :ry => rym, :sp => 0.0}
  1116.         tw = 0
  1117.         ay = char_vert_sp(dt[:vs],dt[:style],dt[:lines].size)
  1118.         ch_h = 0
  1119.         spaces = 0
  1120.         rym = 0
  1121.         ci += 1
  1122.         next
  1123.       end
  1124.       if dt[:mods]['x'][ci]
  1125.         tw += dt[:mods]['x'][ci].to_i
  1126.       end
  1127.       if dt[:mods]['y'][ci]
  1128.         rym += dt[:mods]['y'][ci].to_i
  1129.       end
  1130.       img = Cache.font_ex(FontEX::Chs[ch],FontEX::Types[dt[:style]],dt[:hue])
  1131.       ch_h = img.height if ch_h < img.height
  1132.       ry = ch_h - img.height
  1133.       rym = ry if rym < ry
  1134.       r_h[ci] = [ch_h,rym,ay]
  1135.       nch = dt[:txt][ci+1,1]
  1136.       hsp = char_horz_sp(ch,dt[:style],nch) # Horizontal spacing
  1137.       ax = img.width + hsp # Added x after the character
  1138.       ch_w[ci] = [img.width,hsp,ch_h,rym] if ch_w[ci].nil? # Stores the width of the char
  1139.       tw += img.width
  1140.       spaces += 1 if ch == ' '
  1141.       if break_line?(tw,dt[:w],dt[:lines].size) # Line-break needed
  1142.         if ch == ' ' # The character is a space
  1143.           phsp = char_horz_sp(dt[:txt][ci-1,1],dt[:style],ch)
  1144.           lw = tw - img.width - phsp
  1145.           spaces -= 1
  1146.           if spaces > 0
  1147.             clw = lwidth(dt[:w],dt[:lines].size)
  1148.             sp = (clw - lw)/spaces.to_f
  1149.           else
  1150.             clw = lwidth(dt[:w],dt[:lines].size)
  1151.             sp = clw - lw.to_f
  1152.           end
  1153.           last = ci + 1
  1154.           # Starts a new line and leaves the space char on the prev line
  1155.           dt[:lines][ci+1] = {:w => lw, :ch => ch_h, :vs => ay, :ry => rym, :sp => sp}
  1156.         else
  1157.           oci = ci
  1158.           ostyle = dt[:style]
  1159.           #pstyle = dt[:style]
  1160.           orym = rym
  1161.           och_h = ch_h
  1162.           oay = ay
  1163.           subw = -hsp
  1164.           until [" ","\t","\n","\r\n"].include?(dt[:txt][ci]) || ci == last
  1165.  
  1166.             if dt[:mods]['s'][ci] # Style change found!
  1167.               pstyle = dt[:mods]['s'].find {|cid,dt| cid < ci }
  1168.               if pstyle # Previous style change found
  1169.                 dt[:style] = pstyle[1]
  1170.               else # No other style change found, load original style
  1171.                 dt[:style] = ori_font
  1172.               end
  1173.               vsp = char_vert_sp(dt[:vs],dt[:style],dt[:lines].size)
  1174.               ay = vsp if ay < vsp
  1175.             end
  1176.            
  1177.             if dt[:mods]['h'][ci] # Hue change found!
  1178.               phue = dt[:mods]['h'].find {|cid,dt| cid < ci }
  1179.               if phue # Previous hue change found
  1180.                 dt[:hue] = phue[1]
  1181.               else # No other hue change found, load original hue
  1182.                 dt[:hue] = ori_hue
  1183.               end
  1184.             end
  1185.            
  1186.             # Space found or reached the start
  1187.             if ch_w[ci]
  1188.               subw += ch_w[ci][0] + ch_w[ci][1]
  1189.             end
  1190.             ci -= 1
  1191.             if r_h[ci]
  1192.               ch_h = r_h[ci][0]
  1193.               rym = r_h[ci][1]
  1194.               ay = r_h[ci][2]
  1195.             end
  1196.           end
  1197.           if ["\n","\r\n"].include?(dt[:txt][ci,1]) || ci == last
  1198.             dt[:style] = ostyle
  1199.             phsp = char_horz_sp(dt[:txt][oci-1,1],dt[:style],ch)
  1200.             lw = tw - img.width - phsp
  1201.             cnum = oci - 1 - ci
  1202.             clw = lwidth(dt[:w],dt[:lines].size)
  1203.             sp = (clw - lw) / cnum.to_f
  1204.            
  1205.             ch_h = och_h
  1206.             rym = orym
  1207.             ay = oay
  1208.             vsp = char_vert_sp(dt[:vs],dt[:style],dt[:lines].size)
  1209.             ay = vsp if ay < vsp
  1210.            
  1211.             dt[:lines][oci] = {:w => lw, :ch => ch_h, :vs => ay, :ry => rym, :sp => sp, :single => true}
  1212.             last = oci
  1213.             ci = oci-1 # Reset the char counter
  1214.           else
  1215.             subw += ch_w[ci-1][1] if ch_w[ci-1]
  1216.             simg = Cache.font_ex(FontEX::Chs[" "],FontEX::Types[dt[:style]],dt[:hue])
  1217.             lw = tw - (subw + simg.width + char_horz_sp(" ",dt[:style],dt[:txt][ci,1]))
  1218.             spaces -= 1
  1219.             if spaces > 0
  1220.               clw = lwidth(dt[:w],dt[:lines].size)
  1221.               sp = (clw - lw)/spaces.to_f
  1222.             else
  1223.               clw = lwidth(dt[:w],dt[:lines].size)
  1224.               sp = clw - lw.to_f
  1225.             end
  1226.             last = ci
  1227.             # Just make a line break
  1228.             dt[:lines][ci] = {:w => lw, :ch => ch_h, :vs => ay, :ry => rym, :sp => sp}
  1229.           end
  1230.         end
  1231.         tw = 0
  1232.         spaces = 0
  1233.         ay = char_vert_sp(dt[:vs],dt[:style],dt[:lines].size)
  1234.         ch_h = 0
  1235.         rym = 0
  1236.       else
  1237.         tw += hsp
  1238.       end
  1239.  
  1240.       ci += 1
  1241.     end
  1242.     if spaces > 0
  1243.       clw = lwidth(dt[:w],dt[:lines].size)
  1244.       sp = (clw-(tw-hsp))/spaces.to_f
  1245.     else
  1246.       clw = lwidth(dt[:w],dt[:lines].size)
  1247.       sp = clw-(tw-hsp)
  1248.     end
  1249.     # The width of the last line
  1250.     dt[:lines][:last] = {:w => tw-hsp, :ch => ch_h, :vs => ay, :ry => rym, :sp => 0}
  1251.        
  1252.     dt[:style] = ori_font
  1253.     dt[:hue] = ori_hue
  1254.    
  1255.     dt[:ci] = 0
  1256.     dt[:lnum] = 0 # Current line number
  1257.     dt[:cline] = dt[:lines].values[0]
  1258.     dt[:cw] = dt[:cline][:w] # Current line width
  1259.    
  1260.     dt[:th] = dt[:lines].values.inject(0) {|r,ldt| r += ldt[:ch] + ldt[:vs] + ldt[:ry] }
  1261.     dt[:th] -= ay + rym
  1262.     dt[:vsp] = (dt[:h] - dt[:th].to_f) / (dt[:lines].size - 1)
  1263.    
  1264.     dt[:cx] = font_ex_align_h(dt[:x],dt[:w],dt[:cw],dt[:ah],0)
  1265.     dt[:cy] = font_ex_align_v(dt[:y],dt[:h],dt[:th],dt[:av])
  1266.     dt[:rym] = 0
  1267.    
  1268.     # Kept for future debugging
  1269.     #ii = 0
  1270.     #dt[:lines].each do |ci,line|
  1271.     #  p "line #{ii}: #{line}"
  1272.     #  ii += 1
  1273.     #end
  1274.     #p "total height: #{dt[:th]}"
  1275.    
  1276.     update_fex(dt,@fex.size - 1) if dt[:wait] < 0
  1277.   end
  1278.  
  1279.   def lwidth(tw,lnum)
  1280.     if tw.is_a?(Hash)
  1281.       sw = tw.find {|lnums,nw| lnums.is_a?(Array) && lnums.include?(lnum) }
  1282.       lw = sw ? sw[1] : tw[:default]
  1283.       return lw
  1284.     else
  1285.       return tw
  1286.     end
  1287.   end
  1288.  
  1289.   def break_line?(cw,tw,lnum)
  1290.     if tw.is_a?(Hash)
  1291.       sw = tw.find {|lnums,nw| lnums.is_a?(Array) && lnums.include?(lnum) }
  1292.       lw = sw ? sw[1] : tw[:default]
  1293.       return cw > lw
  1294.     else
  1295.       return cw > tw
  1296.     end
  1297.   end
  1298.  
  1299.   def update_font_ex
  1300.     return unless @fex
  1301.     @fex.each_with_index do |dt,i|
  1302.       update_fex(dt,i)
  1303.     end
  1304.   end
  1305.  
  1306.   def update_fex(dt,fi)
  1307.     return if dt[:done]
  1308.     if dt[:skip_key] && !dt[:skip]
  1309.       dt[:skip] = true if Input.trigger?(dt[:skip_key])
  1310.     end
  1311.     if dt[:num] >= dt[:wait] || dt[:spd_key] && Input.press?(dt[:spd_key])
  1312.       loop do
  1313.         ch = dt[:txt][dt[:ci]]
  1314.         if ch.nil? || ch == "" # No more char!
  1315.           dt[:done] = true
  1316.           break
  1317.         end
  1318.         if dt[:mods]['k'][dt[:ci]]
  1319.           unless Input.trigger?(dt[:mods]['k'][dt[:ci]].to_sym)
  1320.             dt[:skip] = false if dt[:skip]
  1321.             return
  1322.           end
  1323.         end
  1324.         if dt[:mods]['s'][dt[:ci]]
  1325.           dt[:style] = dt[:mods]['s'][dt[:ci]]
  1326.         end
  1327.         if dt[:mods]['h'][dt[:ci]]
  1328.           dt[:hue] = dt[:mods]['h'][dt[:ci]]
  1329.         end
  1330.         if dt[:mods]['w'][dt[:ci]]
  1331.           dt[:wait] = dt[:mods]['w'][dt[:ci]].to_i - 1
  1332.         end
  1333.         if dt[:lines][dt[:ci]] # Do a linebreak here
  1334.           dt[:cy] += dt[:cline][:ch] + dt[:cline][:vs] # Start new line
  1335.           dt[:cy] += dt[:vsp] if dt[:av] == 3
  1336.           dt[:lnum] += 1
  1337.           dt[:cline] = dt[:lines].values[dt[:lnum]]
  1338.           dt[:cw] = dt[:cline][:w] # Current line width
  1339.           dt[:cx] = font_ex_align_h(dt[:x],dt[:w],dt[:cw],dt[:ah],dt[:lnum]) # Reset X pos
  1340.           dt[:rym] = 0
  1341.           if ch == " " || ch == "\n" || ch == "\r\n"
  1342.             dt[:ci] += 1
  1343.             if dt[:wait] >= 0 && !dt[:skip]
  1344.               dt[:num] = 0
  1345.               break
  1346.             else
  1347.               next
  1348.             end
  1349.           end
  1350.         end
  1351.         if dt[:mods]['x'][dt[:ci]]
  1352.           dt[:cx] += dt[:mods]['x'][dt[:ci]].to_i
  1353.         end
  1354.         if dt[:mods]['y'][dt[:ci]]
  1355.           dt[:rym] += dt[:mods]['y'][dt[:ci]].to_i
  1356.         end
  1357.         if ch == ' ' || (FontEX::Misc[:single] && dt[:cline][:single])
  1358.           dt[:cx] += dt[:lines].values[dt[:lnum]][:sp] if dt[:ah] == 3
  1359.         end
  1360.        
  1361.         img = Cache.font_ex(FontEX::Chs[ch],FontEX::Types[dt[:style]],dt[:hue])
  1362.         rct = Rect.new(0,0,img.width,img.height)
  1363.        
  1364.         play_fex_se(dt[:ci],dt[:se]) if dt[:se] && !dt[:skip] && dt[:wait] >= 0
  1365.         ry = dt[:cline][:ch] - img.height
  1366.         dt[:rym] = ry if dt[:rym] < ry
  1367.  
  1368.         blt(dt[:cx], dt[:cy]+ry, img, rct, dt[:opa]) # Draw the char
  1369.        
  1370.         # Added x after the character
  1371.         ax = img.width + char_horz_sp(ch,dt[:style],dt[:txt][dt[:ci]+1])
  1372.         dt[:cx] += ax
  1373.  
  1374.         dt[:ci] += 1
  1375.         break if dt[:wait] >= 0 && !dt[:skip]
  1376.       end
  1377.       dt[:num] = 0
  1378.     else
  1379.       dt[:num] += 1
  1380.     end
  1381.   end
  1382.  
  1383.   def font_ex_align_h(xx,ww,cw,al=0,lnum)
  1384.     if xx.is_a?(Hash)
  1385.       sx = xx.find {|lnums,nx| lnums.is_a?(Array) && lnums.include?(lnum) }
  1386.       nx = sx ? sx[1] : xx[:default]
  1387.     else
  1388.       nx = xx
  1389.     end
  1390.     if ww.is_a?(Hash)
  1391.       sw = ww.find {|lnums,nw| lnums.is_a?(Array) && lnums.include?(lnum) }
  1392.       tw = sw ? sw[1] : ww[:default]
  1393.     else
  1394.       tw = ww
  1395.     end
  1396.     case al
  1397.     when 0, 3; return nx # Current X pos
  1398.     when 1; return nx + (tw - cw) / 2 # Current X pos
  1399.     when 2; return nx + tw - cw # Current X pos
  1400.     end
  1401.   end
  1402.  
  1403.   def font_ex_align_v(yy,hh,th,al=0)
  1404.     case al
  1405.     when 0, 3; return yy # Current Y pos
  1406.     when 1; return yy + (hh - th) / 2 # Current Y pos
  1407.     when 2; return yy + hh - th # Current Y pos
  1408.     end
  1409.   end
  1410.  
  1411.   def play_fex_se(ci,dt)
  1412.     return unless ci % dt[3] == 0
  1413.     se = dt[0].is_a?(Array) ? dt[0].sample : dt[0]
  1414.     vol = dt[1].is_a?(Array) ? dt[1].sample : dt[1]
  1415.     pitch = dt[2].is_a?(Array) ? dt[2].sample : dt[2]
  1416.     RPG::SE.new(se,vol,pitch).play
  1417.   end
  1418.  
  1419.   def process_text_fex(txt) # Text message codes
  1420.     ctxt = txt.dup
  1421.     ctxt.gsub!(/<VAR:(?:\s*)(\d+)>/i) { $game_variables[$1.to_i].to_s }
  1422.     ctxt.gsub!(/<VAR:(?:\s*)(\d+)>/i) { $game_variables[$1.to_i].to_s }
  1423.     ctxt.gsub!(/<ANAME:(?:\s*)(\d+)>/i) { actor_name($1.to_i) }
  1424.     ctxt.gsub!(/<MNAME:(?:\s*)(\d+)>/i) { member_name($1.to_i) }
  1425.     ctxt.gsub!(/<ACLASS:(?:\s*)(\d+)>/i) { actor_class_name($1.to_i) }
  1426.     ctxt.gsub!(/<MCLASS:(?:\s*)(\d+)>/i) { member_class_name($1.to_i) }
  1427.     ctxt.gsub!(/<ANICK:(?:\s*)(\d+)>/i) { actor_nickname($1.to_i) }
  1428.     ctxt.gsub!(/<MNICK:(?:\s*)(\d+)>/i) { member_nickname($1.to_i) }
  1429.     ctxt.gsub!(/<ITEM:(?:\s*)(\d+)>/i) { obj_name($data_items[$1.to_i]) }
  1430.     ctxt.gsub!(/<ARMOR:(?:\s*)(\d+)>/i) { obj_name($data_armors[$1.to_i]) }
  1431.     ctxt.gsub!(/<WEAPON:(?:\s*)(\d+)>/i) { obj_name($data_weapons[$1.to_i]) }
  1432.     ctxt.gsub!(/<SKILL:(?:\s*)(\d+)>/i) { obj_name($data_skills[$1.to_i]) }
  1433.     ctxt.gsub!(/<CLASS:(?:\s*)(\d+)>/i) { obj_name($data_classes[$1.to_i]) }
  1434.     ctxt.gsub!(/<STATE:(?:\s*)(\d+)>/i) { obj_name($data_states[$1.to_i]) }
  1435.     return post_process_text_fex(ctxt)
  1436.   end
  1437.  
  1438.   def post_process_text_fex(ctxt) # Functional message codes
  1439.     pos = 0
  1440.     while ctxt =~ /<(S|X|Y|W|K|H):(?:\s*)([^>]*)>/i
  1441.       tp = $1
  1442.       mod = $2
  1443.       pos = ctxt.index(/<(S|X|Y|W|K|H):(?:\s*)([^>]*)>/i,pos)
  1444.       @fex[-1][:mods][tp.downcase][pos] = mod
  1445.       ctxt.sub!(/<(S|X|Y|W|K|H):(?:\s*)([^>]*)>/i,"")
  1446.     end
  1447.     return ctxt
  1448.   end
  1449.    
  1450.   def obj_name(obj)
  1451.     return obj ? obj.name : ""
  1452.   end
  1453.  
  1454.   def actor_name(id)
  1455.     act = $game_actors[id]
  1456.     return act ? act.name : ""
  1457.   end
  1458.  
  1459.   def member_name(id)
  1460.     act = $game_party.members[id]
  1461.     return act ? act.name : ""
  1462.   end
  1463.  
  1464.   def actor_nickname(id)
  1465.     act = $game_actors[id]
  1466.     return act ? act.nickname : ""
  1467.   end
  1468.  
  1469.   def member_nickname(id)
  1470.     act = $game_party.members[id]
  1471.     return act ? act.nickname : ""
  1472.   end
  1473.  
  1474.   def actor_class_name(id)
  1475.     act = $game_actors[id]
  1476.     return act ? act.class.name : ""
  1477.   end
  1478.  
  1479.   def member_class_name(id)
  1480.     act = $game_party.members[id]
  1481.     return act ? act.class.name : ""
  1482.   end
  1483.  
  1484.   alias clear_fex9927 dispose
  1485.   def dispose
  1486.     @fex = nil
  1487.     clear_fex9927
  1488.   end
  1489.  
  1490. end
  1491.  
  1492. if FontEX::Auto[:sprite]
  1493.  
  1494.   class Sprite
  1495.    
  1496.     alias add_fex_update9971 update
  1497.     def update
  1498.       add_fex_update9971
  1499.       bitmap.update_font_ex if !self.disposed? && bitmap
  1500.     end
  1501.    
  1502.   end
  1503.  
  1504. end
  1505.  
  1506. if FontEX::Auto[:window]
  1507.  
  1508.   class Window
  1509.    
  1510.     alias add_fex_update9973 update
  1511.     def update
  1512.       add_fex_update9973
  1513.       self.contents.update_font_ex if !self.disposed? && self.contents
  1514.     end
  1515.    
  1516.   end
  1517.  
  1518. end
  1519. #==============================================================================
  1520. # !!END OF SCRIPT - OHH, NOES!!
  1521. #==============================================================================
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement