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个字符

202 行
6.4KB

  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_PALETTE_ACTIVE = "palette-selected";
  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 < 8 && 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(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(i.pi, i.ci));
  63. }
  64. });
  65. }
  66. function FindAndColorPalette(pi, ci, pal){
  67. if (pi >= 0 && pi < 8){
  68. var el = document.querySelector("[" + ATTRIB_PALIDX +"='" + pi + "']" +
  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. var self = this;
  80. // ------------------------------------------------------------------------------------
  81. // Defining hooks for the main system palette interactions.
  82. // ------------------------------------------------------------------------------------
  83. var handle_syspalette_clicked = function(event){
  84. if (self.__activePaletteEl !== null && this.hasAttribute(ATTRIB_NESIDX)){
  85. var idx = parseInt(this.getAttribute(ATTRIB_NESIDX), 16);
  86. if (idx >= 0 && idx < NESPalette.SystemColor.length){
  87. var i = GetPaletteIndexes(self.__activePaletteEl);
  88. if (self.__palette !== null && i !== null){
  89. self.__NESPalette.set_palette_syscolor_index(i.pi + ((self.__mode === 1) ? 4 : 0), i.ci, idx);
  90. SetPaletteElStyle(self.__activePaletteEl, NESPalette.SystemColor[idx]);
  91. }
  92. }
  93. }
  94. };
  95. var elist = document.querySelectorAll("[" + ATTRIB_NESIDX + "]");
  96. elist.forEach(function(el){
  97. var idx = parseInt(el.getAttribute(ATTRIB_NESIDX), 16);
  98. if (idx >= 0 && idx < NESPalette.SystemColor.length){
  99. SetPaletteElStyle(el, NESPalette.SystemColor[idx]);
  100. el.addEventListener("click", handle_syspalette_clicked);
  101. }
  102. });
  103. // ------------------------------------------------------------------------------------
  104. // Defining hooks for the drawing palette interactions.
  105. // ------------------------------------------------------------------------------------
  106. var handle_palcolor_clicked = function(event){
  107. if (this.hasAttribute(ATTRIB_PALIDX) && this.hasAttribute(ATTRIB_COLIDX)){
  108. if (this !== self.__activePaletteEl){
  109. var i = GetPaletteIndexes(this);
  110. if (i !== null){
  111. if (self.__activePaletteEl !== null){
  112. self.__activePaletteEl.classList.remove(CLASS_PALETTE_ACTIVE);
  113. }
  114. this.classList.add(CLASS_PALETTE_ACTIVE);
  115. self.__activePaletteEl = this;
  116. GlobalEvents.emit("active_palette_color", (i.pi%4), i.ci);
  117. }
  118. }
  119. }
  120. };
  121. var elist = document.querySelectorAll("[" + ATTRIB_PALIDX + "]");
  122. elist.forEach(function(el){
  123. if (el.hasAttribute(ATTRIB_PALIDX) && el.hasAttribute(ATTRIB_COLIDX)){
  124. el.addEventListener("click", handle_palcolor_clicked);
  125. }
  126. });
  127. // ------------------------------------------------------------------------------------
  128. // Setting some hooks to watch for some global events.
  129. // ------------------------------------------------------------------------------------
  130. var handle_set_app_palette = function(p){
  131. if (p instanceof NESPalette){
  132. self.palette = p;
  133. }
  134. }
  135. GlobalEvents.listen("set_app_palette", handle_set_app_palette);
  136. }
  137. get palette(){
  138. return this.__NESPalette;
  139. }
  140. set palette(p){
  141. if (!(p instanceof NESPalette)){
  142. throw new TypeError("Expected NESPalette object instance.");
  143. }
  144. var self = this;
  145. var handle_palettes_changed = function(event){
  146. if (self.__NESPalette !== null){
  147. if (event.type == "ALL"){
  148. SetColorPaletteEls(self.__NESPalette);
  149. } else {
  150. FindAndColorPalette(event.pindex, event.cindex, self.__NESPalette);
  151. }
  152. }
  153. }
  154. // Disconnect listener from old palette and connect it to new palette.
  155. if (this.__NESPalette !== p){
  156. if (this.__NESPalette !== null){
  157. this.__NESPalette.unlisten("palettes_changed", handle_palettes_changed);
  158. }
  159. this.__NESPalette = p;
  160. this.__NESPalette.listen("palettes_changed", handle_palettes_changed);
  161. }
  162. var elist = document.querySelectorAll("[" + ATTRIB_PALIDX + "]");
  163. elist.forEach((function(el){
  164. if (el.hasAttribute(ATTRIB_COLIDX)){
  165. var i = GetPaletteIndexes(el);
  166. if (i !== null){
  167. SetPaletteElStyle(el, p.get_palette_color(i.pi, i.ci));
  168. }
  169. }
  170. }).bind(this));
  171. }
  172. }
  173. const instance = new CTRLPalettes();
  174. export default instance;