Sunspider

Bitsy Hack - Textbox Borders and Customization

Feb 11th, 2020
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /**
  2. 💬📐
  3. @file textbox customizer
  4. @summary
  5. @license MIT
  6. @version 1.0.0
  7. @requires Bitsy Version: 6.1
  8. @author Dana Holdampf
  9.  
  10. @description
  11. This hack lets you edit the appearance, position, and other properties of the textbox.
  12. It lets you draw a border made of sprites, replace the continue arrow, etc.
  13. TODO: WRITE A MORE THOROUGH DESCRIPTION
  14.  
  15. HOW TO USE:
  16. 1. Copy-paste this script into a script tag after the bitsy source
  17. 2. Edit hackOptions below, as needed
  18.  
  19. TODO: WRITE A HOW-TO
  20.  
  21. Colors are defined as 4 values, [red,green,blue,alpha], each ranging from 0-255.
  22. Alpha is opacity; colors can be translucent by reducing Alpha below 255. 0 is fully transparent.
  23. NIGHT NOTE: Maybe recalculate center position, considering textbox margins in center calculation?
  24. */
  25. import {
  26.     after,
  27.     // addDualDialogTag,
  28.     inject
  29. } from './helpers/kitsy-script-toolkit';
  30.  
  31. export var hackOptions = {
  32.     // Determines where the textbox is positioned. "shift" moves the textbox based on the player's position.
  33.     verticalPosition: "shift", // options are "top", "center", "bottom", or "shift" (moves based on player position)
  34.     horizontalPosition: "center", // options are "left", "center", "right", or "shift" (moves based on player position)
  35.  
  36.     textboxColor: [0,0,0,255], // Colors text and textbox are drawn, in [R,G,B,A]
  37.     textboxWidth: 124, // Width of textbox in pixels. Default 104.
  38.     textboxMarginX: 4, // Pixels of space outside the left (or right) of the textbox. Default 12.
  39.     textboxMarginY: 4, // Pixels of space outside the top (or bottom) of the textbox. Default 12.
  40.  
  41.     textColor: [255,255,255,255], // Default color of text.
  42.     textMinLines: 1, // Minimum number of rows for text. Determines starting textbox height. Default 2.
  43.     textMaxLines: 2, // Maximum number of rows for text. Determines max textbox height. Default 2.
  44.     textScale: 2, // Scaling factor for text. Default 2.
  45.     textSpeed: 50, // Time to print each character, in milliseconds. Default 50.
  46.     textPaddingX: 0, // Default color of text.
  47.     textPaddingY: 2, // Default color of text.
  48.  
  49.     // Colors the borders are drawn using, in [R,G,B,A]
  50.     borderColor: [128,128,128,255],
  51.     borderBGColor: [0,0,0,255],
  52.     borderMidColor: [51,51,51,255], // Color used for middle border
  53.    
  54.     // Border is drawn past the edges of the textbox.
  55.     borderWidth: 8, // Width of border sprites, in pixels. Default 8.
  56.     borderHeight: 8, // Height of border sprites, in pixels. Default 8.
  57.     borderScale: 2, // Scaling factor for border sprites. Default 2.
  58.  
  59.     // Color the continue arrow is drawn using, in [R,G,B,A]
  60.     arrowColor: [255,255,255,255],
  61.     arrowBGColor: [0,0,0,255],
  62.     arrowScale: 2, // Scaling factor for arrow sprite. Default 2.
  63.  
  64.     // Position of textbox continue arrow, on bottom of textbox. Uncomment one.
  65.     arrowAlign: "right", // Options are: "right", "center", or "left" aligned
  66.  
  67.     // Pixels of padding the arrow is inset from the edge by
  68.     arrowInsetX: 12,
  69.     arrowInsetY: 0,
  70.  
  71.     // Arrow Sprite. 1 draws a pixel in main Color, 0 draws in BG Color.
  72.     arrowWidth: 8, // Width of arrow sprite below, in pixels
  73.     arrowHeight: 5, // Height of arrow sprite below, in pixels
  74.  
  75.     arrowSprite: [
  76.         1,1,1,1,1,1,1,1,
  77.         0,1,1,1,1,1,1,0,
  78.         0,0,1,1,1,1,0,0,
  79.         0,0,0,1,1,0,0,0,
  80.         0,0,0,0,0,0,0,0
  81.     ],
  82.     borderUL: [
  83.         0,0,0,0,0,0,0,0,
  84.         0,0,0,0,0,0,0,0,
  85.         0,0,1,1,1,1,1,1,
  86.         0,0,1,1,1,1,1,1,
  87.         0,0,1,1,0,0,0,0,
  88.         0,0,1,1,0,0,0,0,
  89.         0,0,1,1,0,0,0,0,
  90.         0,0,1,1,0,0,0,0,
  91.     ],
  92.     borderU: [
  93.         0,0,0,0,0,0,0,0,
  94.         0,0,0,0,0,0,0,0,
  95.         1,1,1,1,1,1,1,1,
  96.         1,1,1,1,1,1,1,1,
  97.         0,0,0,0,0,0,0,0,
  98.         0,0,0,0,0,0,0,0,
  99.         0,0,0,0,0,0,0,0,
  100.         0,0,0,0,0,0,0,0,
  101.     ],
  102.     borderUR: [
  103.         0,0,0,0,0,0,0,0,
  104.         0,0,0,0,0,0,0,0,
  105.         1,1,1,1,1,1,0,0,
  106.         1,1,1,1,1,1,0,0,
  107.         0,0,0,0,1,1,0,0,
  108.         0,0,0,0,1,1,0,0,
  109.         0,0,0,0,1,1,0,0,
  110.         0,0,0,0,1,1,0,0,
  111.     ],
  112.     borderL: [
  113.         0,0,1,1,0,0,0,0,
  114.         0,0,1,1,0,0,0,0,
  115.         0,0,1,1,0,0,0,0,
  116.         0,0,1,1,0,0,0,0,
  117.         0,0,1,1,0,0,0,0,
  118.         0,0,1,1,0,0,0,0,
  119.         0,0,1,1,0,0,0,0,
  120.         0,0,1,1,0,0,0,0,
  121.     ],
  122.     borderR: [
  123.         0,0,0,0,1,1,0,0,
  124.         0,0,0,0,1,1,0,0,
  125.         0,0,0,0,1,1,0,0,
  126.         0,0,0,0,1,1,0,0,
  127.         0,0,0,0,1,1,0,0,
  128.         0,0,0,0,1,1,0,0,
  129.         0,0,0,0,1,1,0,0,
  130.         0,0,0,0,1,1,0,0,
  131.     ],
  132.     borderDL: [
  133.         0,0,1,1,0,0,0,0,
  134.         0,0,1,1,0,0,0,0,
  135.         0,0,1,1,0,0,0,0,
  136.         0,0,1,1,0,0,0,0,
  137.         0,0,1,1,1,1,1,1,
  138.         0,0,1,1,1,1,1,1,
  139.         0,0,0,0,0,0,0,0,
  140.         0,0,0,0,0,0,0,0,
  141.     ],
  142.     borderD: [
  143.         0,0,0,0,0,0,0,0,
  144.         0,0,0,0,0,0,0,0,
  145.         0,0,0,0,0,0,0,0,
  146.         0,0,0,0,0,0,0,0,
  147.         1,1,1,1,1,1,1,1,
  148.         1,1,1,1,1,1,1,1,
  149.         0,0,0,0,0,0,0,0,
  150.         0,0,0,0,0,0,0,0,
  151.     ],
  152.     borderDR: [
  153.         0,0,0,0,1,1,0,0,
  154.         0,0,0,0,1,1,0,0,
  155.         0,0,0,0,1,1,0,0,
  156.         0,0,0,0,1,1,0,0,
  157.         1,1,1,1,1,1,0,0,
  158.         1,1,1,1,1,1,0,0,
  159.         0,0,0,0,0,0,0,0,
  160.         0,0,0,0,0,0,0,0,
  161.     ],
  162.     borderM: [
  163.         0,0,0,0,0,0,0,0,
  164.         0,0,0,0,0,0,0,0,
  165.         0,0,0,0,0,0,0,0,
  166.         0,0,0,0,0,0,0,0,
  167.         0,0,0,0,0,0,0,0,
  168.         0,0,0,0,0,0,0,0,
  169.         0,0,0,0,0,0,0,0,
  170.         0,0,0,0,0,0,0,0,
  171.     ],
  172.  
  173.     // You can define alternate Dialog Styles here, which can override the default style above.
  174.     // You can switch styles from dialog with the {dialogStyle "styleName"} command.
  175.     initialDialogStyle: "none", // Initial Dialog Style used on load. Can be changed to any dialog style defined below.
  176.  
  177.     // These Dialog Styles are meant as examples. Feel free to edit, rename, or remove them.
  178.     dialogStyle: {
  179.         custom: {
  180.             // Copy any hackOptions from above into this section, and modify them, to create a new style.
  181.             // Any options you redefine here will override the default style, while this style is active.
  182.            
  183.         },
  184.         // An example style, which emulates the original Bitsy textbox.
  185.         vanilla: {
  186.             verticalPosition: "shift",
  187.             horizontalPosition: "center",
  188.             textboxWidth: 104,
  189.             textboxMarginX: 12,
  190.             textboxMarginY: 12,
  191.             textMinLines: 2,
  192.             textMaxLines: 2,
  193.             textPaddingX: 8,
  194.             textPaddingY: 8,
  195.             borderWidth: 0,
  196.             borderHeight: 0,
  197.             arrowScale: 4,
  198.             arrowInsetX: 12,
  199.             arrowInsetY: 0,
  200.             arrowWidth: 5,
  201.             arrowHeight: 3,
  202.             arrowSprite: [
  203.                 1,1,1,1,1,
  204.                 0,1,1,1,0,
  205.                 0,0,1,0,0,
  206.             ],
  207.         },
  208.         // An example style, drawn with a transparent background.
  209.         transparent: {
  210.             textboxColor: [255,255,255,0],
  211.             borderBGColor: [255,255,255,0],
  212.             arrowBGColor: [255,255,255,0],
  213.         },
  214.         // An example style, that centers the textbox as with Starting or Ending text.
  215.         centered: {
  216.             verticalPosition: "center",
  217.             horizontalPosition: "center",
  218.         },
  219.         // An example style, that positions the textbox vertically, on the left or right side.
  220.         vertical: {
  221.             verticalPosition: "center",
  222.             horizontalPosition: "shift",
  223.             textboxWidth: 32,
  224.             textMinLines: 16,
  225.             textMaxLines: 16,
  226.         },
  227.         // An example style, which positions a resizing textbox in the corner opposite the player.
  228.         corner: {
  229.             verticalPosition: "shift",
  230.             horizontalPosition: "shift",
  231.             textboxWidth: 64,
  232.             textMinLines: 1,
  233.             textMaxLines: 8,
  234.         },
  235.         // An example style, which inverts the normal textbox colors
  236.         inverted: {
  237.             textboxColor: [255,255,255,255],
  238.             textColor: [0,0,0,255],
  239.             borderColor: [128,128,128,255],
  240.             borderBGColor: [255,255,255,255],
  241.             borderMidColor: [204,204,204,255],
  242.             arrowColor: [0,0,0,255],
  243.             arrowBGColor: [255,255,255,255],
  244.         },
  245.         smallBorder: {
  246.             borderWidth: 4,
  247.             borderHeight: 4,
  248.             borderUL: [
  249.                 0,0,0,0,
  250.                 0,1,1,1,
  251.                 0,1,0,1,
  252.                 0,1,1,1,
  253.             ],
  254.             borderU: [
  255.                 0,0,0,0,
  256.                 1,1,1,1,
  257.                 0,0,0,0,
  258.                 0,0,0,0,
  259.             ],
  260.             borderUR: [
  261.                 0,0,0,0,
  262.                 1,1,1,0,
  263.                 1,0,1,0,
  264.                 1,1,1,0,
  265.             ],
  266.             borderL: [
  267.                 0,1,0,0,
  268.                 0,1,0,0,
  269.                 0,1,0,0,
  270.                 0,1,0,0,
  271.             ],
  272.             borderR: [
  273.                 0,0,1,0,
  274.                 0,0,1,0,
  275.                 0,0,1,0,
  276.                 0,0,1,0,
  277.             ],
  278.             borderDL: [
  279.                 0,1,1,1,
  280.                 0,1,0,1,
  281.                 0,1,1,1,
  282.                 0,0,0,0,
  283.             ],
  284.             borderD: [
  285.                 0,0,0,0,
  286.                 0,0,0,0,
  287.                 1,1,1,1,
  288.                 0,0,0,0,
  289.             ],
  290.             borderDR: [
  291.                 1,1,1,0,
  292.                 1,0,1,0,
  293.                 1,1,1,0,
  294.                 0,0,0,0,
  295.             ],
  296.             borderM: [
  297.                 0,0,0,0,
  298.                 0,0,0,0,
  299.                 0,0,0,0,
  300.                 0,0,0,0,
  301.             ],
  302.         },
  303.     },
  304. };
  305.  
  306.  
  307.  
  308.  
  309.  
  310. // =============================================================
  311. // | RE-IMPLIMENTED LONG DIALOG HACK INJECTS |/////////////////|
  312. // =============================================================
  313. // Modified from Sean leBlanc's Long Dialog hack, to include textbox borders and padding
  314. // Needed to recalculate textbox height, based on current style parameters.
  315. // Added textMinLines and textMaxLines to hackOptions parameters, to include in style swapping
  316.  
  317. // OLD RETURN VALUE FOR REF: textboxInfo.padding_vert + (textboxInfo.padding_vert + relativeFontHeight()) * Math.max(${hackOptions.minRows}, dialogBuffer.CurPage().indexOf(dialogBuffer.CurRow())+Math.sign(dialogBuffer.CurCharCount())) + textboxInfo.arrow_height; }
  318.  
  319. // override textbox height (and recalculate textboxWidth)
  320. inject(/textboxInfo\.height = .+;/, `Object.defineProperty(textboxInfo, 'height', {
  321.     get() { return 2 + textPaddingY + borderHeight + (relativeFontHeight() * Math.max(${textMinLines}, dialogBuffer.CurPage().indexOf(dialogBuffer.CurRow())+Math.sign(dialogBuffer.CurCharCount()))); }
  322. })`);
  323. // prevent textbox from caching
  324. inject(/(if\(textboxInfo\.img == null\))/, '// $1');
  325. // rewrite hard-coded row limit
  326. inject(/(else if \(curRowIndex )== 0/g, '$1< ' + textMaxLines + ' - 1');
  327. inject(/(if\( lastPage\.length) <= 1( \) {)/, '$1 < ' + textMaxLines + ' $2');
  328.  
  329. // Add dynamic recalculation of textbox width? may need to be added after textboxInfo.height inject?
  330. //inject(/textboxInfo\.width = .+;/, `Object.defineProperty(textboxInfo, 'width', {
  331. //  get() { return textboxWidth; }
  332. //})`);
  333.  
  334.  
  335.  
  336.  
  337.  
  338. // ==========================================================================================================================
  339. // NIGHT NOTES: So... there's scope problems of some sort? Something to do with modules, I think.
  340. //
  341. // The Dialog function can't access hackOptions, or the functions defined in the hack.
  342. // It's in a virtual machine or something and can't access functions/variables?
  343. // I probably need to inject scripts for the entire function into the Dialog hack (unless there's a way to give it access)?
  344. // Keep an eye out for buggy regex; specifically check the lazy line-break-inclusive wildcards, and escaped characters.
  345. // Hack worked fine, but haven't gotten to test injected version of the hack yet, due to the scope issue.
  346. //
  347. // Once the scope issue is resolved, there's a chance hack functionality was borked or half-implemented.
  348. // Keep an eye out!
  349. //
  350. // Later, test style swapping after runtime, to make sure all the parameters get updated.
  351. // Some of the parameters might not get updated.
  352. // ==========================================================================================================================
  353.  
  354.  
  355.  
  356.  
  357.  
  358. // =============================================================
  359. // | HACK SCRIPT INJECTS |/////////////////////////////////////|
  360. // =============================================================
  361.  
  362. // Injects textbox style variables at top of Dialog function
  363. var dialogInject = `function Dialog() {
  364. console.log ("Injected Dialog Function has been called");
  365. var verticalPosition = hackOptions.verticalPosition;
  366. var horizontalPosition = hackOptions.horizontalPosition;
  367. var textboxColor = hackOptions.textboxColor;
  368. var textboxWidth = hackOptions.textboxWidth;
  369. var textboxHeight = hackOptions.textboxHeight;
  370. var textboxMarginX = hackOptions.textboxMarginX;
  371. var textboxMarginY = hackOptions.textboxMarginY;
  372. var textColor = hackOptions.textColor;
  373. var textMinLines = hackOptions.textMinLines;
  374. var textMaxLines = hackOptions.textMaxLines;
  375. var textScale = hackOptions.textScale;
  376. var textSpeed = hackOptions.textSpeed;
  377. var textPaddingX = hackOptions.textPaddingX;
  378. var textPaddingY = hackOptions.textPaddingY;
  379. var borderColor = hackOptions.borderColor;
  380. var borderBGColor = hackOptions.borderBGColor;
  381. var borderMidColor = hackOptions.borderMidColor;
  382. var borderWidth = hackOptions.borderWidth;
  383. var borderHeight = hackOptions.borderHeight;
  384. var borderScale = hackOptions.borderScale;
  385. var arrowColor = hackOptions.arrowColor;
  386. var arrowBGColor = hackOptions.arrowBGColor;
  387. var arrowScale = hackOptions.arrowScale;
  388. var arrowAlign = hackOptions.arrowAlign;
  389. var arrowInsetX = hackOptions.arrowInsetX;
  390. var arrowInsetY = hackOptions.arrowInsetY;
  391. var arrowWidth = hackOptions.arrowWidth;
  392. var arrowHeight = hackOptions.arrowHeight;
  393. var arrowSprite = hackOptions.arrowSprite;
  394. var borderUL = hackOptions.borderUL;
  395. var borderU = hackOptions.borderU;
  396. var borderUR = hackOptions.borderUR;
  397. var borderL = hackOptions.borderL;
  398. var borderR = hackOptions.borderR;
  399. var borderDL = hackOptions.borderDL;
  400. var borderD = hackOptions.borderD;
  401. var borderDR = hackOptions.borderDR;
  402. var borderM = hackOptions.borderM;
  403. `;
  404. inject(/function Dialog\(\) {/, dialogInject);
  405.  
  406. // Replaces initial textbox parameters, based on currently active style (or defaults).
  407. // Recalculates textbox parameters, even values no longer used with hack, for compatability.
  408. var textboxInfoReplace = `setTextboxStyle(hackOptions.initialDialogStyle);
  409.  
  410. var textboxInfo = {
  411.     img : null,
  412.     width : textboxWidth,
  413.     height : (textPaddingY + borderHeight + 2),
  414.     top : textboxMarginY,
  415.     left : textboxMarginX,
  416.     bottom : textboxMarginY,
  417.     font_scale : 0.5, //hackOptions.textScale/4;
  418.     padding_vert : 2,
  419.     padding_horz : 4,
  420.     arrow_height : (textPaddingY + borderHeight - 4),
  421. };`;
  422. inject(/var textboxInfo = .+?};/s, textboxInfoReplace);
  423.  
  424. // Replaces ClearTextbox function to include border-drawing scripts
  425. var clearTextboxReplace = `this.ClearTextbox = function() {
  426.     if(context == null) return;
  427.  
  428.     //create new image none exists
  429.     if(textboxInfo.img == null)
  430.         textboxInfo.img = context.createImageData(textboxInfo.width*scale, textboxInfo.height*scale);
  431.  
  432.     // Draw Textbox Background based on BGColor (indices are R,G,B, and A)
  433.     for (var i=0;i<textboxInfo.img.data.length;i+=4)
  434.     {
  435.         textboxInfo.img.data[i+0]=textboxColor[0];
  436.         textboxInfo.img.data[i+1]=textboxColor[1];
  437.         textboxInfo.img.data[i+2]=textboxColor[2];
  438.         textboxInfo.img.data[i+3]=textboxColor[3];
  439.     }
  440.  
  441.     drawTextboxBorder();
  442. };`
  443. inject(/this.ClearTextbox = .+?};/s, clearTextboxReplace);
  444.  
  445. // Replaces Draw Textbox function, with function that supports vertical and horizontal shifting
  446. var drawTextboxReplace = `this.DrawTextbox = function() {
  447.     if(context == null) return;
  448.  
  449.     // Textbox defaults to center-aligned
  450.     var textboxXPosition = ((width/2)-(textboxInfo.width/2))*scale;
  451.     var textboxYPosition = ((height/2)-(textboxInfo.height/2))*scale;
  452.  
  453.     if (isCentered) {
  454.         context.putImageData(textboxInfo.img, textboxXPosition, textboxYPosition);
  455.     }
  456.     else {
  457.         if (verticalPosition.toLowerCase() = "shift") {
  458.             if (player().y < mapsize/2) {
  459.                 //player on bottom half, so draw on top
  460.                 textboxYPosition = ((height-textboxInfo.top-textboxInfo.height)*scale);
  461.             }
  462.             else {
  463.                 textboxYPosition = textboxInfo.top*scale
  464.             }
  465.         }
  466.         else if (verticalPosition.toLowerCase() = "top") {
  467.             textboxYPosition = ((height-textboxInfo.top-textboxInfo.height)*scale);
  468.         }
  469.         else if (verticalPosition.toLowerCase() = "bottom") {
  470.             textboxYPosition = textboxInfo.top*scale
  471.         }
  472.  
  473.         if (horizontalPosition.toLowerCase() = "shift") {
  474.             if (player().x < mapsize/2) {
  475.                 // player on left half, so draw on right
  476.                 textboxXPosition = ((width-textboxInfo.left-textboxInfo.width)*scale);
  477.             }
  478.             else {
  479.                 textboxXPosition = textboxInfo.left*scale
  480.             }
  481.         }
  482.         else if (horizontalPosition.toLowerCase() = "right") {
  483.             textboxXPosition = ((width-textboxInfo.left-textboxInfo.width)*scale);
  484.         }
  485.         else if (horizontalPosition.toLowerCase() = "left") {
  486.             textboxXPosition = textboxInfo.left*scale
  487.         }
  488.  
  489.         // Draw the Textbox
  490.         context.putImageData(textboxInfo.img, textboxXPosition, textboxYPosition);
  491.     }
  492. };`;
  493. inject(/this.DrawTextbox = .+?};/s, drawTextboxReplace);
  494.  
  495. // Replace DrawNextArrow function, to support custom sprites, colors, and arrow repositioning
  496. var drawNextArrowReplace = `this.DrawNextArrow = function() {
  497.     // Arrow sprite is center-bottom by default
  498.     var top = ((4/arrowScale)*textboxInfo.height - arrowHeight - arrowInsetY) *  arrowScale;
  499.     var left = ((4/textboxArrowScale)*textboxInfo.width - arrowXSize) * textboxArrowScale*0.5;
  500.  
  501.     // Reposition arrow based on arrowAlign and RTL settings (flipped for RTL Languages)
  502.     if (arrowAlign.toLowerCase() == "left") {
  503.         if (textDirection === TextDirection.RightToLeft) {
  504.             left = ((4/arrowScale)*textboxInfo.width - arrowWidth - arrowInsetX) *  arrowScale;
  505.         }
  506.         else {
  507.             left = (arrowXPadding) * textboxArrowScale;
  508.         }
  509.     }
  510.     else if (arrowAlign.toLowerCase() == "right") {
  511.         if (textDirection === TextDirection.RightToLeft) {
  512.             left = (arrowXPadding) * textboxArrowScale;
  513.         }
  514.         else {
  515.             left = ((4/arrowScale)*textboxInfo.width - arrowWidth - arrowInsetX) *  arrowScale;
  516.         }
  517.     }
  518.    
  519.     // Draw arrow sprite pixels on textbox
  520.     for (var y = 0; y < arrowHeight; y++) {
  521.         for (var x = 0; x < arrowWidth; x++) {
  522.             var i = (y * arrowWidth) + x;
  523.  
  524.             //scaling hooplah
  525.             for (var sy = 0; sy < arrowScale; sy++) {
  526.                 for (var sx = 0; sx < arrowScale; sx++) {
  527.                     var pxl = 4 * ( ((top+(y*arrowScale)+sy) * (textboxInfo.width*4)) + (left+(x*arrowScale)+sx) );
  528.                     // Draws arrow's pixels in Arrow Color
  529.                     if (arrowSprite[i] == 1) {
  530.                         textboxInfo.img.data[pxl+0] = arrowColor[0];
  531.                         textboxInfo.img.data[pxl+1] = arrowColor[1];
  532.                         textboxInfo.img.data[pxl+2] = arrowColor[2];
  533.                         textboxInfo.img.data[pxl+3] = arrowColor[3];
  534.                     }
  535.                     // Draws arrow's bg pixels using Arrow BG Color
  536.                     else {
  537.                         textboxInfo.img.data[pxl+0] = arrowBGColor[0];
  538.                         textboxInfo.img.data[pxl+1] = arrowBGColor[1];
  539.                         textboxInfo.img.data[pxl+2] = arrowBGColor[2];
  540.                         textboxInfo.img.data[pxl+3] = arrowBGColor[3];
  541.                     }
  542.                 }
  543.             }
  544.         }
  545.     }
  546. };`;
  547. inject(/this.DrawNextArrow = .+?};/s, drawNextArrowReplace);
  548.  
  549. // Inject to support custom text scaling
  550. inject(/var text_scale = .+?;/, 'var text_scale = textScale;');
  551.  
  552. // Injects to support text padding within the textbox
  553. var topTextPaddingReplace = `var top = (2 * textPaddingY) + (borderHeight * 2) + (row * 2 * scale) + (row * font.getHeight() * textScale) + Math.floor( char.offset.y );`;
  554. var leftTextPaddingReplace = `var left = (2* textPaddingX) + (borderWidth * 2) + (leftPos * textScale) + Math.floor( char.offset.x );`;
  555. inject(/var top = \(4 \* scale\) \+ \(row \* 2 \* scale\) .+?\);/, topTextPaddingReplace);
  556. inject(/var left = \(4 \* scale\) \+ \(leftPos \* text_scale\) .+?\);/, leftTextPaddingReplace);
  557.  
  558. // Inject to support custom text speeds
  559. inject(/var nextCharMaxTime = .+?;/, 'var nextCharMaxTime = textSpeed;');
  560.  
  561. // Inject to support custom default text color
  562. inject(/this.color = .+?};/, 'this.color = { r:textColor[0], g:textColor[1], b:textColor[2], a:textColor[3] };');
  563.  
  564. // Inject to support dynamic textbox resizing
  565. inject(/var pixelsPerRow = .+?;/, 'var pixelsPerRow = (textboxWidth*2) - (borderWidth*2) - (textPaddingX*2);');
  566. //var pixelsPerRow = (textboxWidth*2) - (borderWidth*2) - (textPaddingX*2); // hard-coded fun times!!! 192
  567.  
  568. // =============================================================
  569. // | HACK FUNCTIONS |//////////////////////////////////////////|
  570. // =============================================================
  571.  
  572. // Resets Textbox Style to Default
  573. function resetTextboxStyle() {
  574.     console.log ("RESETTING TO DEFAULT TEXTBOX STYLE");
  575.     verticalPosition = hackOptions.verticalPosition;
  576.     horizontalPosition = hackOptions.horizontalPosition;
  577.     textboxColor = hackOptions.textboxColor;
  578.     textboxWidth = hackOptions.textboxWidth;
  579.     textboxMarginX = hackOptions.textboxMarginX;
  580.     textboxMarginY = hackOptions.textboxMarginY;
  581.     textColor = hackOptions.textColor;
  582.     textMinLines = hackOptions.textMinLines;
  583.     textMaxLines = hackOptions.textMaxLines;
  584.     textScale = hackOptions.textScale;
  585.     textSpeed = hackOptions.textSpeed;
  586.     textPaddingX = hackOptions.textPaddingX;
  587.     textPaddingY = hackOptions.textPaddingY;
  588.     borderColor = hackOptions.borderColor;
  589.     borderBGColor = hackOptions.borderBGColor;
  590.     borderMidColor = hackOptions.borderMidColor;
  591.     borderWidth = hackOptions.borderWidth;
  592.     borderHeight = hackOptions.borderHeight;
  593.     borderScale = hackOptions.borderScale;
  594.     arrowColor = hackOptions.arrowColor;
  595.     arrowBGColor = hackOptions.arrowBGColor;
  596.     arrowScale = hackOptions.arrowScale;
  597.     arrowAlign = hackOptions.arrowAlign;
  598.     arrowInsetX = hackOptions.arrowInsetX;
  599.     arrowInsetY = hackOptions.arrowInsetY;
  600.     arrowWidth = hackOptions.arrowWidth;
  601.     arrowHeight = hackOptions.arrowHeight;
  602.     arrowSprite = hackOptions.arrowSprite;
  603.     borderUL = hackOptions.borderUL;
  604.     borderU = hackOptions.borderU;
  605.     borderUR = hackOptions.borderUR;
  606.     borderL = hackOptions.borderL;
  607.     borderR = hackOptions.borderR;
  608.     borderDL = hackOptions.borderDL;
  609.     borderD = hackOptions.borderD;
  610.     borderDR = hackOptions.borderDR;
  611.     borderM = hackOptions.borderM;
  612. }
  613.  
  614. // Used to set or switch the Textbox Style.
  615. function setTextboxStyle(newStyle) {
  616.     console.log ("SETTING TEXTBOX STYLE TO: " + newStyle);
  617.     // If style doesn't exist, resets to default
  618.     if (hackOptions.dialogStyle[newStyle] == undefined) {
  619.         resetTextboxStyle();
  620.         return false;
  621.     }
  622.     verticalPosition = (hackOptions.dialogStyle[newStyle].verticalPosition != undefined ? hackOptions.dialogStyle[newStyle].verticalPosition : hackOptions.verticalPosition);
  623.     horizontalPosition = (hackOptions.dialogStyle[newStyle].horizontalPosition != undefined ? hackOptions.dialogStyle[newStyle].horizontalPosition : hackOptions.horizontalPosition);
  624.     textboxColor = (hackOptions.dialogStyle[newStyle].textboxColor != undefined ? hackOptions.dialogStyle[newStyle].textboxColor : hackOptions.textboxColor);
  625.     textboxWidth = (hackOptions.dialogStyle[newStyle].textboxWidth != undefined ? hackOptions.dialogStyle[newStyle].textboxWidth : hackOptions.textboxWidth);
  626.     textboxMarginX = (hackOptions.dialogStyle[newStyle].textboxMarginX != undefined ? hackOptions.dialogStyle[newStyle].textboxMarginX : hackOptions.textboxMarginX);
  627.     textboxMarginY = (hackOptions.dialogStyle[newStyle].textboxMarginY != undefined ? hackOptions.dialogStyle[newStyle].textboxMarginY : hackOptions.textboxMarginY);
  628.     textColor = (hackOptions.dialogStyle[newStyle].textColor != undefined ? hackOptions.dialogStyle[newStyle].textMinLines : hackOptions.textMinLines);
  629.     textMinLines = (hackOptions.dialogStyle[newStyle].textMinLines != undefined ? hackOptions.dialogStyle[newStyle].textMinLines : hackOptions.textMinLines);
  630.     textMaxLines = (hackOptions.dialogStyle[newStyle].textMaxLines != undefined ? hackOptions.dialogStyle[newStyle].textMaxLines : hackOptions.textMaxLines);
  631.     textScale = (hackOptions.dialogStyle[newStyle].textScale != undefined ? hackOptions.dialogStyle[newStyle].textScale : hackOptions.textScale);
  632.     textSpeed = (hackOptions.dialogStyle[newStyle].textSpeed != undefined ? hackOptions.dialogStyle[newStyle].textSpeed : hackOptions.textSpeed);
  633.     textPaddingX = (hackOptions.dialogStyle[newStyle].textPaddingX != undefined ? hackOptions.dialogStyle[newStyle].textPaddingX : hackOptions.textPaddingX);
  634.     textPaddingY = (hackOptions.dialogStyle[newStyle].textPaddingY != undefined ? hackOptions.dialogStyle[newStyle].textPaddingY : hackOptions.textPaddingY);
  635.     borderColor = (hackOptions.dialogStyle[newStyle].borderColor != undefined ? hackOptions.dialogStyle[newStyle].borderColor : hackOptions.borderColor);
  636.     borderBGColor = (hackOptions.dialogStyle[newStyle].borderBGColor != undefined ? hackOptions.dialogStyle[newStyle].borderBGColor : hackOptions.borderBGColor);
  637.     borderMidColor = (hackOptions.dialogStyle[newStyle].borderMidColor != undefined ? hackOptions.dialogStyle[newStyle].borderMidColor : hackOptions.borderMidColor);
  638.     borderWidth = (hackOptions.dialogStyle[newStyle].borderWidth != undefined ? hackOptions.dialogStyle[newStyle].borderWidth : hackOptions.borderWidth);
  639.     borderHeight = (hackOptions.dialogStyle[newStyle].borderHeight != undefined ? hackOptions.dialogStyle[newStyle].borderHeight : hackOptions.borderHeight);
  640.     borderScale = (hackOptions.dialogStyle[newStyle].borderScale != undefined ? hackOptions.dialogStyle[newStyle].borderScale : hackOptions.borderScale);
  641.     arrowColor = (hackOptions.dialogStyle[newStyle].arrowColor != undefined ? hackOptions.dialogStyle[newStyle].arrowColor : hackOptions.arrowColor);
  642.     arrowBGColor = (hackOptions.dialogStyle[newStyle].arrowBGColor != undefined ? hackOptions.dialogStyle[newStyle].arrowBGColor : hackOptions.arrowBGColor);
  643.     arrowScale = (hackOptions.dialogStyle[newStyle].arrowScale != undefined ? hackOptions.dialogStyle[newStyle].arrowScale : hackOptions.arrowScale);
  644.     arrowAlign = (hackOptions.dialogStyle[newStyle].arrowAlign != undefined ? hackOptions.dialogStyle[newStyle].arrowAlign : hackOptions.arrowAlign);
  645.     arrowInsetX = (hackOptions.dialogStyle[newStyle].arrowInsetX != undefined ? hackOptions.dialogStyle[newStyle].arrowInsetX : hackOptions.arrowInsetX);
  646.     arrowInsetY = (hackOptions.dialogStyle[newStyle].arrowInsetY != undefined ? hackOptions.dialogStyle[newStyle].arrowInsetY : hackOptions.arrowInsetY);
  647.     arrowWidth = (hackOptions.dialogStyle[newStyle].arrowWidth != undefined ? hackOptions.dialogStyle[newStyle].arrowWidth : hackOptions.arrowWidth);
  648.     arrowHeight = (hackOptions.dialogStyle[newStyle].arrowHeight != undefined ? hackOptions.dialogStyle[newStyle].arrowHeight : hackOptions.arrowHeight);
  649.     arrowSprite = (hackOptions.dialogStyle[newStyle].arrowSprite != undefined ? hackOptions.dialogStyle[newStyle].arrowSprite : hackOptions.arrowSprite);
  650.     borderUL = (hackOptions.dialogStyle[newStyle].borderUL != undefined ? hackOptions.dialogStyle[newStyle].borderUL : hackOptions.borderUL);
  651.     borderU = (hackOptions.dialogStyle[newStyle].borderU != undefined ? hackOptions.dialogStyle[newStyle].borderU : hackOptions.borderU);
  652.     borderUR = (hackOptions.dialogStyle[newStyle].borderUR != undefined ? hackOptions.dialogStyle[newStyle].borderUR : hackOptions.borderUR);
  653.     borderL = (hackOptions.dialogStyle[newStyle].borderL != undefined ? hackOptions.dialogStyle[newStyle].borderL : hackOptions.borderL);
  654.     borderR = (hackOptions.dialogStyle[newStyle].borderR != undefined ? hackOptions.dialogStyle[newStyle].borderR : hackOptions.borderR);
  655.     borderDL = (hackOptions.dialogStyle[newStyle].borderDL != undefined ? hackOptions.dialogStyle[newStyle].borderDL : hackOptions.borderDL);
  656.     borderD = (hackOptions.dialogStyle[newStyle].borderD != undefined ? hackOptions.dialogStyle[newStyle].borderD : hackOptions.borderD);
  657.     borderDR = (hackOptions.dialogStyle[newStyle].borderDR != undefined ? hackOptions.dialogStyle[newStyle].borderDR : hackOptions.borderDR);
  658.     borderM = (hackOptions.dialogStyle[newStyle].borderM != undefined ? hackOptions.dialogStyle[newStyle].borderM : hackOptions.borderM);
  659.  
  660.     // Reset textbox.Info values? TODO: overwrite instances of textboxInfo with injects
  661.     textboxInfo.width = textboxWidth;
  662.     // textboxInfo.height = textboxHeight;
  663.     textboxInfo.top = textboxMarginY;
  664.     textboxInfo.left = textboxMarginX;
  665.     textboxInfo.bottom = textboxMarginY;
  666.     // textboxInfo.font_scale = 0.5; //hackOptions.textScale/4;
  667.     // textboxInfo.arrow_height = borderHeight+textPaddingY-4;
  668. }
  669.  
  670. // TODO: pass it the textbox image as a parameter?
  671. // TODO: Cache it at the start of the dialog, so it needn't be recalculated each frame?
  672.  
  673. function drawTextboxBorder() {
  674.     // Iterates through each pixel of the textbox, and determines if a border pixel should be drawn.
  675.     // Compares 1D array of textbox pixels to 1D arrays for each border sprite, to determine whether to draw a pixel.
  676.     for (var y = 0; y < textboxInfo.height * borderScale; y++) {
  677.         for (var x = 0; x < (textboxInfo.width) * borderScale; x++) {
  678.             // NOTE: borderXId and borderYId translate message box coordinates to border tile coordinates.
  679.             // Use modulo to translate textbox space into tiles, for drawing borders pixel-by-pixel.
  680.             // For bottom/right borders, border sprites should be anchored to the bottom/right instead.
  681.             // borderYId and borderXId get pixel coordinates anchored to the top or left
  682.             // borderDId and borderRId get pixel coordinates anchored to down or right (for right/bottom edges)
  683.             var borderYId = (y % borderHeight);
  684.             var borderXId = (x % borderWidth);
  685.             var borderDId = ((y+(textboxInfo.height*borderScale)) % borderHeight);
  686.             var borderRId = ((x+(textboxInfo.width*borderScale)) % borderWidth);
  687.            
  688.             // NOTE: There's a weird bug with odd vs even textbox heights. Here's a hacky fix for now.
  689.             // TODO: Handle decimal heights? Still bugs with those (may come up with bitsy's text scaling)
  690.             if (textboxInfo.height % 2 != 0) {
  691.                 borderDId = ((y-4+(textboxInfo.height*borderScale)) % borderHeight);   
  692.             }
  693.  
  694.             // Calculates index in the 1D array of the border sprite.
  695.             var borderPxl = (borderYId*borderWidth) + borderXId;
  696.             var bottomPxl = (borderDId*borderWidth) + borderXId;
  697.             var rightPxl = (borderYId*borderWidth) + borderRId;
  698.             var bottomRightPxl = (borderDId*borderWidth) + borderRId;
  699.  
  700.             // Determines if the current pixel is along one of the textbox's edges, or if it's in the center.
  701.             var borderTop = y < borderHeight;
  702.             var borderBottom = y >= textboxInfo.height*borderScale-borderHeight;
  703.             var borderLeft = x < borderWidth;
  704.             var borderRight = x >= textboxInfo.width*borderScale-borderWidth;
  705.  
  706.             // Does this pixel is draw???
  707.             // 1= draw a border pixel, 0= No! Draw a border bg pixel instead
  708.             var borderDraw;
  709.  
  710.             // Retrieve pixel data from appropriate sprite. Special handling for bottom/right borders!
  711.             if (borderBottom) {
  712.                 // Bottom Left Corner
  713.                 if (borderLeft) { borderDraw = borderDL[bottomPxl]; }
  714.                 // Bottom Right Corner
  715.                 else if (borderRight) { borderDraw = borderDR[bottomRightPxl]; }
  716.                 // Bottom Middle Edge
  717.                 else { borderDraw = borderD[bottomPxl]; }
  718.             }
  719.             else if (borderTop) {
  720.                 // Top Left Corner
  721.                 if (borderLeft) { borderDraw = borderUL[borderPxl]; }
  722.                 // Top Right Corner
  723.                 else if (borderRight) { borderDraw = borderUR[rightPxl]; }
  724.                 // Top Middle Edge
  725.                 else { borderDraw = borderU[borderPxl]; }
  726.             }
  727.             // Left Edge
  728.             else if (borderLeft) { borderDraw = borderL[borderPxl]; }
  729.             // Right Edge
  730.             else if (borderRight) { borderDraw = borderR[rightPxl]; }
  731.             // Middle
  732.             else { borderDraw = borderM[borderPxl]; }
  733.  
  734.             //scaling shenanigans (maps sprite scale pixels to bitsy/screen-scale pixels)
  735.             for (var sy = 0; sy < borderScale; sy++) {
  736.                 for (var sx = 0; sx < borderScale; sx++) {
  737.                     var pxl = 4 * ( (((borderScale*y)+sy) * (4*textboxInfo.width)) + (borderScale*x)+sx );
  738.  
  739.                     // If it's a border pixel, Retrieves RGBA values for the border, and draws it.
  740.                     if (borderDraw) {
  741.                         if (borderTop || borderBottom || borderLeft || borderRight) {
  742.                             textboxInfo.img.data[pxl+0] = borderColor[0];
  743.                             textboxInfo.img.data[pxl+1] = borderColor[1];
  744.                             textboxInfo.img.data[pxl+2] = borderColor[2];
  745.                             textboxInfo.img.data[pxl+3] = borderColor[3];
  746.                         }
  747.                         else {
  748.                             textboxInfo.img.data[pxl+0] = borderMidColor[0];
  749.                             textboxInfo.img.data[pxl+1] = borderMidColor[1];
  750.                             textboxInfo.img.data[pxl+2] = borderMidColor[2];
  751.                             textboxInfo.img.data[pxl+3] = borderMidColor[3];
  752.                         }
  753.                         //DEBUG COLORS. UNCOMMENT TO DRAW PIXELS BASED ON TEXTBOX COORDINATES, 0-255
  754.                         /*textboxInfo.img.data[pxl+0] = 204-(x);
  755.                         textboxInfo.img.data[pxl+1] = 204-(x+y);
  756.                         textboxInfo.img.data[pxl+2] = 204-(y*2);
  757.                         textboxInfo.img.data[pxl+3] = 255;
  758.                         //DRAWS TOP-LEFT-ANCHORED GRID TILE COORDINATES IN GREY
  759.                         if (y % borderHeight == 0 || x % borderWidth == 0) {
  760.                             textboxInfo.img.data[pxl+0] = 128;
  761.                             textboxInfo.img.data[pxl+1] = 128;
  762.                             textboxInfo.img.data[pxl+2] = 128;
  763.                             textboxInfo.img.data[pxl+3] = 255;
  764.                         }*/
  765.                     }
  766.                     // If it's a border BG pixel, gets RGBA colors based on if it's on an edge or in middle.
  767.                     else {
  768.                         if (borderTop || borderBottom || borderLeft || borderRight) {
  769.                             textboxInfo.img.data[pxl+0] = borderBGColor[0];
  770.                             textboxInfo.img.data[pxl+1] = borderBGColor[1];
  771.                             textboxInfo.img.data[pxl+2] = borderBGColor[2];
  772.                             textboxInfo.img.data[pxl+3] = borderBGColor[3];
  773.                         }
  774.                         else {
  775.                             textboxInfo.img.data[pxl+0] = textboxColor[0];
  776.                             textboxInfo.img.data[pxl+1] = textboxColor[1];
  777.                             textboxInfo.img.data[pxl+2] = textboxColor[2];
  778.                             textboxInfo.img.data[pxl+3] = textboxColor[3];
  779.                         }
  780.                         //DEBUG COLORS. UNCOMMENT TO DRAW PIXELS BASED ON TEXTBOX COORDINATES, 0-255
  781.                         /*textboxInfo.img.data[pxl+0] = (x)+102;
  782.                         textboxInfo.img.data[pxl+1] = (x+y);
  783.                         textboxInfo.img.data[pxl+2] = (y*2)+51;
  784.                         textboxInfo.img.data[pxl+3] = 255;
  785.                         //DRAWS TOP-LEFT-ANCHORED GRID COORDINATES IN GREY
  786.                         if (y % borderHeight == 0 || x % borderWidth == 0) {
  787.                             textboxInfo.img.data[pxl+0] = 76;
  788.                             textboxInfo.img.data[pxl+1] = 76;
  789.                             textboxInfo.img.data[pxl+2] = 76;
  790.                             textboxInfo.img.data[pxl+3] = 255;
  791.                         }*/
  792.                     }
  793.                 }
  794.             }
  795.         }
  796.     }
  797. }
Add Comment
Please, Sign In to add comment