A pixel art painter geared specifically at NES pixel art. Includes export for .chr binary file as well as palette and namespace data.
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

183 行
4.8KB

  1. import Utils from "/app/js/common/Utils.js";
  2. import GlobalEvents from "/app/js/common/EventCaller.js";
  3. import Renderer from "/app/js/ui/Renderer.js";
  4. import NESNameTable from "/app/js/models/NESNameTable.js";
  5. import CTRLBanksStore from "/app/js/ctrls/CTRLBanksStore.js";
  6. var ELCtrl = null;
  7. var SURF = null;
  8. var TileIndex = -1;
  9. function UpdateBankList(curbankname){
  10. var elsel = ELCtrl.querySelector(".nametable-bank-select");
  11. if (elsel){
  12. var child = elsel.firstChild;
  13. // Clear old bank names...
  14. while(child !== null){
  15. let nchild = child.nextSibling;
  16. let drop = true;
  17. if (Utils.isElement(child)){
  18. if (child.hasAttribute("value")){
  19. if (child.getAttribute("value") === "NULL_BANK"){
  20. drop = false;
  21. }
  22. }
  23. }
  24. if (drop){
  25. elsel.removeChild(child);
  26. }
  27. child = nchild;
  28. }
  29. // Get the only remaining option...
  30. var elop = elsel.querySelector("option");
  31. // Get the current list of bank names...
  32. var banknames = CTRLBanksStore.keys;
  33. // Loop through bank names, if there are any, and add new options to the list...
  34. if (elop && banknames.length > 0){
  35. banknames.forEach((name) => {
  36. var newop = elop.cloneNode(true);
  37. newop.setAttribute("value", name);
  38. newop.innerHTML = name;
  39. elsel.appendChild(newop);
  40. });
  41. elsel.value = curbankname;
  42. }
  43. }
  44. }
  45. function UpdateBankTileList(){
  46. var el = ELCtrl.querySelector(".nametable-tile");
  47. if (el){
  48. if (SURF.bank === null){
  49. el.classList.add("hidden");
  50. } else {
  51. var elsel = ELCtrl.querySelector(".nametable-tile-select");
  52. if (elsel){
  53. let tiles = SURF.bank.rp;
  54. for (let i=0; i < tiles.length; i++){
  55. let cnv = elsel.querySelector('canvas[value="' + i + '"]');
  56. if (cnv){
  57. let ctx = cnv.getContext("2d");
  58. let tsurf = new Renderer.NESTileSurface(tiles[i], SURF.palette, 0);
  59. Renderer.renderToFit(tsurf, ctx);
  60. }
  61. }
  62. el.classList.remove("hidden");
  63. }
  64. }
  65. }
  66. }
  67. function OpenControls(){
  68. if (ELCtrl !== null && SURF !== null){
  69. var curbankname = (SURF.bank !== null) ? CTRLBanksStore.getBankName(SURF.bank) : "NULL_BANK";
  70. if (curbankname === null){
  71. SURF.bank = null;
  72. curbankname = "NULL_BANK";
  73. }
  74. UpdateBankList(curbankname);
  75. UpdateBankTileList();
  76. ELCtrl.classList.remove("hidden");
  77. }
  78. }
  79. function CloseControls(){
  80. if (ELCtrl !== null){
  81. ELCtrl.classList.add("hidden");
  82. }
  83. }
  84. function HANDLE_PaintNametable(x, y){
  85. if (TileIndex >= 0 && TileIndex < 256){
  86. SURF.setTileIndex(x, y, TileIndex);
  87. }
  88. }
  89. function HANDLE_SurfChange(surf){
  90. if (surf instanceof NESNameTable){
  91. if (SURF !== null)
  92. SURF.unlisten("paint_nametable", HANDLE_PaintNametable);
  93. SURF = surf;
  94. SURF.listen("paint_nametable", HANDLE_PaintNametable);
  95. OpenControls();
  96. } else {
  97. if (SURF !== null)
  98. SURF.unlisten("paint_nametable", HANDLE_PaintNametable);
  99. SURF = null;
  100. CloseControls();
  101. }
  102. }
  103. class CTRLNametableTools{
  104. constructor(){
  105. GlobalEvents.listen("change_surface", HANDLE_SurfChange);
  106. }
  107. initialize(){
  108. ELCtrl = document.querySelector(".toolbar-nametable-control");
  109. if (!ELCtrl)
  110. throw new Error("Failed to find element class 'toolbar-nametable-control'.");
  111. var elbanksel = ELCtrl.querySelector(".nametable-bank-select");
  112. if (!elbanksel)
  113. throw new Error("Failed to find element class 'nametable-bank-select' within toolbar.");
  114. // Building out and setting up the tile selections.
  115. var eltilesel = ELCtrl.querySelector(".nametable-tile-select");
  116. if (!eltilesel)
  117. throw new Error("Failed to find element class 'nametable-tile-select' within toolbar.");
  118. var op0 = eltilesel.querySelector('canvas[value="0"]');
  119. if (!op0)
  120. throw new Error("Failed to find initial canvas element within 'nametable-tile-select'.");
  121. for (let i=1; i < 256; i++){
  122. let op = eltilesel.querySelector('canvas[value="' + i + '"]');
  123. if (!op){
  124. op = op0.cloneNode(true);
  125. op.setAttribute("value", i);
  126. eltilesel.appendChild(op);
  127. op.addEventListener("click", function(){
  128. TileIndex = parseInt(this.getAttribute("value"));
  129. });
  130. }
  131. }
  132. elbanksel.addEventListener("change", function(){
  133. if (SURF !== null){
  134. var bankname = this.value;
  135. if (bankname === "NULL_BANK"){
  136. SURF.bank = null;
  137. } else {
  138. var bank = CTRLBanksStore.getBank(bankname);
  139. if (bank !== null){
  140. if (SURF.bank === null || (SURF.bank.eq(bank) === false)){
  141. SURF.bank = bank;
  142. UpdateBankTileList();
  143. }
  144. }
  145. }
  146. }
  147. });
  148. }
  149. }
  150. const instance = new CTRLNametableTools();
  151. export default instance;