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文字以内のものにしてください。

210 行
6.8KB

  1. import GlobalEvents from "/app/js/common/EventCaller.js";
  2. import NESPalette from "/app/js/models/NESPalette.js";
  3. const ATTRIB_NESIDX = "nesidx";
  4. // The two attributes below MUST BOTH be in the element.
  5. const ATTRIB_PALIDX = "pidx"; // This is the palette index (0 - 3 (Tiles) 4 - 7 (Sprites))
  6. const ATTRIB_COLIDX = "cidx"; // This is the color index in the selected palette (0 - 3)
  7. const CLASS_BTN_ACTIVE = "pure-button-active";
  8. var Active_Palette_Index = 0;
  9. var Active_Color_Index = 0;
  10. function InvertRGB(hex){
  11. var h = (255 - parseInt(hex, 16)).toString(16);
  12. return (h.length < 2) ? "0" + h : h;
  13. }
  14. function InvertColor(chex, bw){
  15. bw = (bw === true);
  16. if (chex.indexOf("#") === 0){
  17. chex = chex.slice(1);
  18. }
  19. if (chex.length === 3){
  20. chex = chex[0] + chex[0] + chex[1] + chex[1] + chex[2] + chex[2];
  21. }
  22. if (chex.length !== 6){
  23. throw new ValueError("Hex color expected to be 3 or 6 characters long.");
  24. }
  25. if (bw) {
  26. var r = parseInt(chex.slice(0, 2), 16);
  27. var g = parseInt(chex.slice(2, 4), 16);
  28. var b = parseInt(chex.slice(4, 6), 16);
  29. // http://stackoverflow.com/a/3943023/112731
  30. return (r * 0.299 + g * 0.587 + b * 0.114) > 186
  31. ? '#000000' : '#FFFFFF';
  32. }
  33. return "#" + InvertRGB(chex.slice(0, 2)) + InvertRGB(chex.slice(2, 4)) + InvertRGB(chex.slice(4, 6));
  34. }
  35. function GetPaletteIndexes(el){
  36. if (el.hasAttribute(ATTRIB_PALIDX) && el.hasAttribute(ATTRIB_COLIDX)){
  37. var pi = el.getAttribute(ATTRIB_PALIDX);
  38. if (!isNaN(pi))
  39. pi = parseInt(pi);
  40. else
  41. pi = -1;
  42. var ci = el.getAttribute(ATTRIB_COLIDX);
  43. if (!isNaN(ci))
  44. ci = parseInt(ci);
  45. else
  46. ci = -1;
  47. if (pi >= 0 && pi < 4 && ci >= 0 && ci < 4){
  48. return {pi:pi, ci:ci};
  49. }
  50. }
  51. return null;
  52. }
  53. function SetPaletteElStyle(el, c){
  54. el.style["background-color"] = c;
  55. el.style.color = InvertColor(c);
  56. }
  57. function SetColorPaletteEls(mode, pal){
  58. var elist = document.querySelectorAll("[" + ATTRIB_PALIDX + "]");
  59. elist.forEach(function(el){
  60. var i = GetPaletteIndexes(el);
  61. if (i !== null){
  62. SetPaletteElStyle(el, pal.get_palette_color((mode*4) + i.pi, i.ci));
  63. }
  64. });
  65. }
  66. function FindAndColorPalette(mode, pi, ci, pal){
  67. if ((mode == 0 && pi < 4) || (mode == 1 && pi >= 4)){
  68. var el = document.querySelector("[" + ATTRIB_PALIDX +"='" + (pi%4) + "']" +
  69. "[" + ATTRIB_COLIDX + "='" + ci + "']");
  70. if (el){
  71. SetPaletteElStyle(el, pal.get_palette_color(pi, ci));
  72. }
  73. }
  74. }
  75. class CTRLPalettes{
  76. constructor(){
  77. this.__NESPalette = null;
  78. this.__activePaletteEl = null;
  79. this.__mode = 0; // 0 = Tile palette mode | 1 = Sprite palette mode.
  80. var self = this;
  81. // ------------------------------------------------------------------------------------
  82. // Defining hooks for the main system palette interactions.
  83. // ------------------------------------------------------------------------------------
  84. var handle_syspalette_clicked = function(event){
  85. if (self.__activePaletteEl !== null && this.hasAttribute(ATTRIB_NESIDX)){
  86. var idx = parseInt(this.getAttribute(ATTRIB_NESIDX), 16);
  87. if (idx >= 0 && idx < NESPalette.SystemColor.length){
  88. var i = GetPaletteIndexes(self.__activePaletteEl);
  89. if (self.__palette !== null && i !== null){
  90. self.__NESPalette.set_palette_syscolor_index(i.pi, i.ci, idx);
  91. SetPaletteElStyle(self.__activePaletteEl, NESPalette.SystemColor[idx]);
  92. }
  93. }
  94. }
  95. };
  96. var elist = document.querySelectorAll("[" + ATTRIB_NESIDX + "]");
  97. elist.forEach(function(el){
  98. var idx = parseInt(el.getAttribute(ATTRIB_NESIDX), 16);
  99. if (idx >= 0 && idx < NESPalette.SystemColor.length){
  100. SetPaletteElStyle(el, NESPalette.SystemColor[idx]);
  101. el.addEventListener("click", handle_syspalette_clicked);
  102. }
  103. });
  104. // ------------------------------------------------------------------------------------
  105. // Defining hooks for the drawing palette interactions.
  106. // ------------------------------------------------------------------------------------
  107. var handle_palcolor_clicked = function(event){
  108. if (this.hasAttribute(ATTRIB_PALIDX) && this.hasAttribute(ATTRIB_COLIDX)){
  109. if (this !== self.__activePaletteEl){
  110. var i = GetPaletteIndexes(this);
  111. if (i !== null){
  112. if (self.__activePaletteEl !== null){
  113. self.__activePaletteEl.classList.remove(CLASS_BTN_ACTIVE);
  114. }
  115. this.classList.add(CLASS_BTN_ACTIVE);
  116. self.__activePaletteEl = this;
  117. GlobalEvents.emit("active_palette_color", i.pi, i.ci);
  118. }
  119. }
  120. }
  121. };
  122. var elist = document.querySelectorAll("[" + ATTRIB_PALIDX + "]");
  123. elist.forEach(function(el){
  124. if (el.hasAttribute(ATTRIB_PALIDX) && el.hasAttribute(ATTRIB_COLIDX)){
  125. el.addEventListener("click", handle_palcolor_clicked);
  126. }
  127. });
  128. // ------------------------------------------------------------------------------------
  129. // Setting some hooks to watch for some global events.
  130. // ------------------------------------------------------------------------------------
  131. var handle_set_app_palette = function(p){
  132. if (p instanceof NESPalette){
  133. self.palette = p;
  134. }
  135. }
  136. GlobalEvents.listen("set_app_palette", handle_set_app_palette);
  137. var handle_palettemode = (function(mode){
  138. if (mode === 0 || mode ===1){
  139. this.__mode = mode;
  140. SetColorPaletteEls(this.__mode, this.__NESPalette);
  141. }
  142. }).bind(this);
  143. GlobalEvents.listen("set_palette_mode", handle_palettemode);
  144. }
  145. get palette(){
  146. return this.__NESPalette;
  147. }
  148. set palette(p){
  149. if (!(p instanceof NESPalette)){
  150. throw new TypeError("Expected NESPalette object instance.");
  151. }
  152. var self = this;
  153. var handle_palettes_changed = function(event){
  154. if (self.__NESPalette !== null){
  155. if (event.type == "ALL"){
  156. SetColorPaletteEls(self.__mode, self.__NESPalette);
  157. } else {
  158. FindAndColorPalette(self.__mode, event.pindex, event.cindex, self.__NESPalette);
  159. }
  160. }
  161. }
  162. // Disconnect listener from old palette and connect it to new palette.
  163. if (this.__NESPalette !== p){
  164. if (this.__NESPalette !== null){
  165. this.__NESPalette.unlisten("palettes_changed", handle_palettes_changed);
  166. }
  167. this.__NESPalette = p;
  168. this.__NESPalette.listen("palettes_changed", handle_palettes_changed);
  169. }
  170. var elist = document.querySelectorAll("[" + ATTRIB_PALIDX + "]");
  171. elist.forEach((function(el){
  172. if (el.hasAttribute(ATTRIB_COLIDX)){
  173. var i = GetPaletteIndexes(el);
  174. if (i !== null){
  175. SetPaletteElStyle(el, p.get_palette_color((this.__mode * 4) + i.pi, i.ci));
  176. }
  177. }
  178. }).bind(this));
  179. }
  180. }
  181. const instance = new CTRLPalettes();
  182. export default instance;