Create box function

Really useful for making boxes 👍

当前为 2023-07-28 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Create box function
  3. // @namespace create_box_owot
  4. // @version 1.2
  5. // @description Really useful for making boxes 👍
  6. // @author e_g.
  7. // @match https://ourworldoftext.com/*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=ourworldoftext.com
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. setupModals = function(){
  13. //Help modal
  14. function makeBoxHelpModal(){
  15. var helpModal = new Modal();
  16. helpModal.createForm();
  17. helpModal.setFormTitle(`Arguments available (insert them inside an object):
  18. x
  19. y
  20. width
  21. height
  22. borderSize
  23. mainColor (0x)
  24. borderColor (0x)
  25. textColor (0x)
  26. textBgColor (0x)
  27. title
  28. description
  29. footer
  30. titleAlign ("center", "left", "right")
  31. descAlign ("center", "left", "right")
  32. footerAlign ("center", "left", "right")
  33. footer2space (makes the footer 2 spaces horizontally instead of 1, to make a more precise 1:1 space)
  34. borderCollision (text will stick to the border instead of having 1 space)
  35. fullActions (set to true to make borderSize extreme values or making a box bigger than 512 characters)
  36.  
  37. Arguments you should not use because they're not customizable and are important parts from the box creation:
  38. size
  39. formattedDesc
  40. descIndex
  41. titleFormula
  42. descFormula
  43. footerFormula`);
  44. helpModal.setMaximumSize(500, 600);
  45. w.ui.boxHelpModal = helpModal;
  46. }
  47. makeBoxHelpModal();
  48. //Box creator modal
  49. function makeBoxCreatorModal() {
  50. var modal = new Modal();
  51. modal.createForm();
  52. modal.createCheckboxField();
  53. modal.setFormTitle("Let's create a box!\n");
  54. for(var inputs of ["x", "y", "width", "height", "borderSize", "mainColor", "borderColor", "textColor", "textBgColor"]){
  55. window[inputs] = modal.addEntry(inputs, "text", "number").input;
  56. };
  57. for(var inputs of ["title", "description", "footer", "titleAlign", "descAlign", "footerAlign"]){
  58. window[inputs] = modal.addEntry(inputs, "text", "string").input;
  59. };
  60. modal.setMaximumSize(500, 600);
  61. for(var inputs of ["footer2space", "borderCollision", "fullActions"]){
  62. window[inputs] = modal.addCheckbox(inputs)
  63. };
  64. modal.onSubmit(function(){
  65. createBox({
  66. x: +x.value,
  67. y: +y.value,
  68. width: +width.value,
  69. height: +height.value,
  70. borderSize: +borderSize.value,
  71. mainColor: +mainColor.value,
  72. borderColor: +borderColor.value,
  73. textColor: +textColor.value,
  74. textBgColor: +textBgColor.value,
  75. title: title.value,
  76. description: description.value,
  77. footer: footer.value,
  78. titleAlign: titleAlign.value,
  79. descAlign: descAlign.value,
  80. footerAlign: footerAlign.value,
  81. footer2space: footer2space.cbElm.checked,
  82. borderCollision: borderCollision.cbElm.checked,
  83. fullActions: fullActions.cbElm.checked
  84. });
  85. });
  86. modal.client.firstChild.append(...modal.client.children[1].children);
  87. modal.client.firstChild.insertBefore(modal.client.firstChild.children[2], modal.client.firstChild.lastChild.nextSibling);
  88. w.ui.boxCreatorModal = modal;
  89. };
  90. makeBoxCreatorModal();
  91. //Create menu options
  92. menu.addOption("Help", function(){
  93. w.ui.boxHelpModal.open()
  94. });
  95. menu.addOption("Create box", function(){
  96. var region = RegionSelection();
  97. region.init();
  98. region.startSelection();
  99. region.onselection(function(xy, _, width, height){
  100. var options = w.ui.boxCreatorModal.client.children[0].children[1];
  101. options.children[1].value = xy[0] * 16 + xy[2];
  102. options.children[3].value = xy[1] * 8 + xy[3];
  103. options.children[5].value = width;
  104. options.children[7].value = height;
  105. w.ui.boxCreatorModal.open();
  106. });
  107. });
  108. }
  109. //Main menu option, that will setup the modals
  110. menu.addEntry("<h1 onclick='setupModals();this.remove();'>Add box</h1>");
  111.  
  112. createBox = function(box){
  113. // Errors and warnings
  114. if(box.x === undefined) return console.error("X position isn't specified.");
  115. if(box.y === undefined) return console.error("Y position isn't specified.");
  116. if(box.width * box.height > 512 && !box.fullActions) return console.error("To make boxes bigger than 512 characters, add the arg fullActions and set it as true.");
  117. if(box.title.length > box.width - box.borderSize * 4 - !box.borderCollision * 2) return console.error("Title too big" + (box.title.length <= box.width - box.borderSize * 4 ? ", set borderCollision to true so you can use that title." : ""));
  118. if(box.footer && box.footer.length > box.width - box.borderSize * 4 - !box.borderCollision * 2 + box.footer2space) return console.error("Footer too big");
  119. if(box.borderSize * 4 >= box.width / 1.5 && !box.fullActions) return console.error("Box's main content is too small. Proceed by adding the arg fullActions to the args and setting it to true.");
  120. box.size = box.width * box.height + ((box.width - box.borderSize * 4) * (box.height - box.borderSize * 2)) * !!box.borderSize + box.title.length + box.description.length + (box.footer ? box.footer.length : 0);
  121. if(state.worldModel.char_rate.reduce((x, y) => x * y / 1e3) * 24 < box.size) return console.error("Your rate limit is too low to draw the box");
  122. if(state.worldModel.char_rate.reduce((x, y) => x * y / 1e3) * 2 < box.size) console.warn("The box might be messed up because your rate limit is too low for the box's size.");
  123. if(box.x % 1){
  124. box.x = Math.floor(box.x);
  125. console.warn(`The x value is a decimal value. It will be rounded to ${box.x}.`);
  126. };
  127. if(box.y % 1){
  128. box.y = Math.floor(box.y);
  129. console.warn(`The y value is a decimal value. It will be rounded to ${box.y}.`);
  130. };
  131. if(box.width % 1){
  132. box.width = Math.floor(box.width);
  133. console.warn(`The width size is a decimal value. It will be rounded to ${box.width}.`);
  134. };
  135. if(box.height % 1){
  136. box.height = Math.floor(box.height);
  137. console.warn(`The height size is a decimal value. It will be rounded to ${box.height}.`);
  138. };
  139. if(box.borderSize % 1){
  140. box.borderSize = Math.round(box.borderSize);
  141. console.warn(`The border size is a decimal value. It will be rounded to ${box.borderSize}.`);
  142. };
  143. if(box.borderSize * 4 >= box.width / 2) console.warn("Consider reducing border's size to add space for the main content!");
  144. if(box.footer2space && box.borderCollision) console.warn("Both footer2space and borderCollision are activated, this may cause conflict for the box.");
  145. // Avoid glitching when a word is too big for the box
  146. if(!box.description.endsWith(" ") && box.description.split(" ").at(-1).length > box.width - box.borderSize * 4 - 2) box.description += " ";
  147. // Rest of description's separating setup + see if it's too big for the box
  148. if(box.description.length > box.width - box.borderSize * 4 - !box.borderCollision * 2 && box.description.split(" ").length > 1){
  149. box.formattedDesc = [...box.description.match(RegExp(`.{0,${box.width - box.borderSize * 4 - !box.borderCollision * 2}} |.{${box.width - box.borderSize * 4 - !box.borderCollision * 2}}`, "g")), box.description.split(" ").at(-1)];
  150. if(box.formattedDesc.slice(-2).join("").length <= box.width - box.borderSize * 4 - !box.borderCollision * 2) box.formattedDesc = [...box.formattedDesc.slice(0, box.formattedDesc.length - 2), box.formattedDesc.slice(-2).join("")];
  151. box.formattedDesc = box.formattedDesc.map(x => x.replace(/ +$/, ""));
  152. }
  153. else box.formattedDesc = box.description.match(RegExp(`.{0,${box.width - box.borderSize * 4 - !box.borderCollision * 2}}`, "g"));
  154. box.formattedDesc = box.formattedDesc.filter(x => x != "");
  155. if(box.formattedDesc.length == 1 && box.formattedDesc[0] == "") box.formattedDesc = [];
  156. if(box.formattedDesc.length > box.height - box.borderSize * 2 - 2 - !box.borderCollision * 2 - !!box.footer * 2) return console.error("Description too long for the size of this box. Try setting borderCollision to true, or if that doesn't work, set a bigger size for the box or shorten the description.");
  157. //Make the box and box's border (reversed order)
  158. if(box.borderSize) filltoxy(box.x, box.y, box.width, box.height, "█", box.borderColor);
  159. filltoxy(box.x + box.borderSize * 2, box.y + box.borderSize, box.width - box.borderSize * 4, box.height - box.borderSize * 2, "█", box.mainColor);
  160. //Alignment formula of title and draw it
  161. if(!box.titleAlign) box.titleAlign = "center";
  162. if(box.titleAlign == "center"){
  163. box.titleFormula = Math.ceil(box.x + box.width / 2 - box.title.length / 2);
  164. }
  165. else if(box.titleAlign == "left"){
  166. box.titleFormula = Math.ceil(box.x + box.borderSize * 2 + !box.borderCollision);
  167. }
  168. else if(box.titleAlign == "right"){
  169. box.titleFormula = Math.ceil(box.x + (box.width - box.borderSize * 2 - !box.borderCollision - box.title.length));
  170. }
  171. else{
  172. console.warn("titleAlign had an invalid align, and was automatically assigned to center (the valid ones are: center, left, right)");
  173. box.titleAlign = "center";
  174. box.titleFormula = Math.ceil(box.x + box.width / 2 - box.title.length / 2);
  175. };
  176. texttoxy(box.titleFormula, box.y + box.borderSize + !box.borderCollision, box.title, box.textColor, box.textBgColor);
  177. //Alignment formula of description and draw it
  178. if(!box.descAlign) box.descAlign = "center";
  179. if(box.descAlign == "center"){
  180. box.descFormula = function(formattedDesc, descIndex){
  181. return Math.ceil(box.x + box.width / 2 - formattedDesc[descIndex - box.borderSize - 3].length / 2);
  182. };
  183. }
  184. else if(box.descAlign == "left"){
  185. box.descFormula = function(){
  186. return Math.ceil(box.x + box.borderSize * 2 + !box.borderCollision);
  187. };
  188. }
  189. else if(box.descAlign == "right"){
  190. box.descFormula = function(formattedDesc, descIndex){
  191. return Math.ceil(box.x + (box.width - box.borderSize * 2 - !box.borderCollision - formattedDesc[descIndex - box.borderSize - 3].length));
  192. };
  193. }
  194. else{
  195. console.warn("descAlign had an invalid align, and was automatically assigned to center (the valid ones are: center, left, right)");
  196. box.descAlign = "center";
  197. box.descFormula = function(formattedDesc, descIndex){
  198. return Math.ceil(box.x + box.width / 2 - formattedDesc[descIndex - box.borderSize - 3].length / 2);
  199. };
  200. };
  201. for(box.descIndex = box.borderSize + 3; box.descIndex < box.formattedDesc.length + box.borderSize + 3; box.descIndex++){
  202. texttoxy(box.descFormula(box.formattedDesc, box.descIndex), box.y + box.descIndex - !!box.borderCollision, box.formattedDesc[box.descIndex - box.borderSize - 3], box.textColor, box.textBgColor);
  203. };
  204. //Alignment formula of footer and draw it IF there's any
  205. if(!box.footer) return;
  206. if(!box.footerAlign) box.footerAlign = "right";
  207. if(box.footerAlign == "center"){
  208. box.footerFormula = Math.ceil(box.x + box.width / 2 - box.footer.length / 2);
  209. }
  210. else if(box.footerAlign == "left"){
  211. box.footerFormula = Math.ceil(box.x + box.borderSize * 2 + !box.borderCollision + !!box.footer2space);
  212. }
  213. else if(box.footerAlign == "right"){
  214. box.footerFormula = Math.ceil(box.x + (box.width - box.borderSize * 2 - !box.borderCollision - !!box.footer2space - box.footer.length));
  215. }
  216. else{
  217. console.warn("footerAlign had an invalid align, and was automatically assigned to right (the valid ones are: center, left, right)");
  218. box.footerAlign = "right";
  219. box.footerFormula = Math.ceil(box.x + (box.width - box.borderSize * 2 - !box.borderCollision - !!box.footer2space - box.footer.length));
  220. };
  221. texttoxy(box.footerFormula, box.y + box.height - box.borderSize - 1 - !box.borderCollision, box.footer, box.textColor, box.textBgColor);
  222. }