TileSelector.hx 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. package hide.comp;
  2. class TileSelector extends Component {
  3. public var file(default,set) : String;
  4. public var size(default,set) : {width: Int, height: Int};
  5. public var value(default,set) : Null<{ x : Int, y : Int, width : Int, height : Int }>;
  6. public var allowRectSelect(default,set) : Bool;
  7. public var allowSizeSelect(default,set) : Bool;
  8. public var allowFileChange(default,set) : Bool;
  9. var cursorPos : { x : Int, y : Int, x2 : Int, y2 : Int, dragSelect : Bool };
  10. var movePos = { x : 0, y : 0, dragScrolling : false };
  11. var valueDisp : Element;
  12. var cursor : Element;
  13. var image : Element;
  14. var imageWidth : Int;
  15. var imageHeight : Int;
  16. var zoom : Float;
  17. var imageElt : js.html.ImageElement;
  18. var modal : Element;
  19. public function new(file,size,?parent,?el) {
  20. super(parent,el);
  21. element.addClass("hide-tileselect");
  22. this.file = file;
  23. this.size = size;
  24. this.modal = parent.parent();
  25. }
  26. function set_file(file) {
  27. this.file = file;
  28. rebuild();
  29. return file;
  30. }
  31. function set_value(v) {
  32. value = v;
  33. if( cursorPos != null ) updateCursor();
  34. return v;
  35. }
  36. function set_size(size) {
  37. this.size = size;
  38. rebuild();
  39. return size;
  40. }
  41. function set_allowRectSelect(b) {
  42. allowRectSelect = b;
  43. rebuild();
  44. return b;
  45. }
  46. function set_allowSizeSelect(b) {
  47. allowSizeSelect = b;
  48. rebuild();
  49. return b;
  50. }
  51. function set_allowFileChange(b) {
  52. allowFileChange = b;
  53. rebuild();
  54. return b;
  55. }
  56. function updateCursor() {
  57. var k = { w: size.width * zoom, h: size.height * zoom };
  58. var width = hxd.Math.abs(cursorPos.x2 - cursorPos.x) + 1;
  59. var height = hxd.Math.abs(cursorPos.y2 - cursorPos.y) + 1;
  60. cursor.css({
  61. left: hxd.Math.min(cursorPos.x,cursorPos.x2)*k.w,
  62. top:hxd.Math.min(cursorPos.y,cursorPos.y2)*k.h,
  63. width:width*k.w - 1,
  64. height:height*k.h - 1,
  65. });
  66. cursor.toggle(cursorPos.x >= 0);
  67. if( value != null ) {
  68. valueDisp.show();
  69. valueDisp.css({
  70. left:value.x*k.w,
  71. top:value.y*k.h,
  72. width:value.width*k.w - 1,
  73. height:value.height*k.h - 1,
  74. });
  75. } else
  76. valueDisp.hide();
  77. }
  78. function rescale() {
  79. image.height(imageHeight*zoom).width(imageWidth*zoom);
  80. image.css("background-size",(imageWidth*zoom)+"px "+(imageHeight*zoom)+"px");
  81. updateCursor();
  82. }
  83. function rebuild() {
  84. element.empty();
  85. element.off();
  86. element.click((e) -> e.stopPropagation());
  87. element.attr("tabindex","0");
  88. element.focus();
  89. element.on("keydown", function(e) {
  90. if( e.keyCode == 27 ) {
  91. onChange(true);
  92. }
  93. });
  94. var tool = new Toolbar(element);
  95. if( allowFileChange ) {
  96. var tex = new hide.comp.TextureSelect(tool.element);
  97. tex.path = file;
  98. tex.onChange = function() this.file = tex.path;
  99. }
  100. if( allowSizeSelect ) {
  101. var widthEdit = new Element('<span class="dim-edit">Width:<input type="number" value="${size.width}">px</span>').appendTo(tool.element);
  102. widthEdit.find("input").on("blur",function(e:js.jquery.Event) {
  103. var nsize = Std.parseInt(e.getThis().val());
  104. if( this.size.width != nsize && nsize != null && nsize > 0 )
  105. this.size.width = nsize;
  106. }).on("keydown", function(e:js.jquery.Event) {
  107. if( e.keyCode == 13 ) widthEdit.find("input").blur();
  108. });
  109. var heightEdit = new Element('<span class="dim-edit">Height:<input type="number" value="${size.height}">px</span>').appendTo(tool.element);
  110. heightEdit.find("input").on("blur",function(e:js.jquery.Event) {
  111. var nsize = Std.parseInt(e.getThis().val());
  112. if( this.size.height != nsize && nsize != null && nsize > 0 )
  113. this.size.height = nsize;
  114. }).on("keydown", function(e:js.jquery.Event) {
  115. if( e.keyCode == 13 ) heightEdit.find("input").blur();
  116. });
  117. widthEdit.find("input").on("blur", updateCursor);
  118. heightEdit.find("input").on("blur", updateCursor);
  119. }
  120. if( tool.element.children().length == 0 )
  121. tool.remove();
  122. var url = ide.getUnCachedUrl(file);
  123. var scroll = new Element("<div class='flex-scroll'><div class='scroll'>").appendTo(element).find(".scroll");
  124. image = new Element('<div class="tile" style="background-image:url(\'$url\')"></div>').appendTo(scroll);
  125. valueDisp = new Element('<div class="valueDisp">').appendTo(image);
  126. cursor = new Element('<div class="cursor">').appendTo(image);
  127. cursorPos = { x : -1, y : -1, x2 : -1, y2 : -1, dragSelect : false };
  128. var i = js.Browser.document.createImageElement();
  129. this.imageElt = i;
  130. i.onload = function(_) {
  131. if( imageElt != i ) return;
  132. imageWidth = i.width;
  133. imageHeight = i.height;
  134. zoom = Math.floor(hxd.Math.min(800 / imageWidth, 580 / imageHeight));
  135. if( zoom <= 0 ) zoom = 1;
  136. scroll.on("mousewheel", function(e:js.jquery.Event) {
  137. if( untyped e.originalEvent.wheelDelta > 0 )
  138. zoom++;
  139. else if( zoom > 1 )
  140. zoom--;
  141. rescale();
  142. e.preventDefault();
  143. });
  144. scroll.parent().on("mousedown", function(e) {
  145. if( e.button == 2 ) {
  146. movePos.dragScrolling = true;
  147. movePos.x = e.pageX;
  148. movePos.y = e.pageY;
  149. }
  150. });
  151. modal.on("mousemove", function(e) {
  152. if( movePos.dragScrolling ) {
  153. var dx = e.pageX - movePos.x;
  154. var dy = e.pageY - movePos.y;
  155. element.find(".scroll")[0].scrollBy(-dx,-dy);
  156. movePos.x = e.pageX;
  157. movePos.y = e.pageY;
  158. }
  159. });
  160. image.on("mousemove", function(e:js.jquery.Event) {
  161. if( movePos.dragScrolling )
  162. return;
  163. var k = { w: size.width * zoom, h: size.height * zoom };
  164. var x = Math.floor(e.offsetX / k.w);
  165. var y = Math.floor(e.offsetY / k.h);
  166. if( (x+1) * size.width > i.width ) x--;
  167. if( (y+1) * size.height > i.height ) y--;
  168. if( cursorPos.dragSelect ) {
  169. cursorPos.x2 = x;
  170. cursorPos.y2 = y;
  171. } else {
  172. cursorPos.x = cursorPos.x2 = x;
  173. cursorPos.y = cursorPos.y2 = y;
  174. }
  175. updateCursor();
  176. });
  177. image.on("mousedown", function(e:js.jquery.Event) {
  178. if( movePos.dragScrolling )
  179. return;
  180. var k = { w: size.width * zoom, h: size.height * zoom };
  181. var x = Math.floor(e.offsetX / k.w);
  182. var y = Math.floor(e.offsetY / k.h);
  183. if( (x+1) * size.width > i.width ) x--;
  184. if( (y+1) * size.height > i.height ) y--;
  185. cursorPos.x = cursorPos.x2 = x;
  186. cursorPos.y = cursorPos.y2 = y;
  187. if( e.button == 0 && allowRectSelect )
  188. cursorPos.dragSelect = true;
  189. });
  190. modal.on("mouseup", function(e) {
  191. movePos.dragScrolling = false;
  192. cursorPos.dragSelect = false;
  193. });
  194. image.on("mouseup", function(e:js.jquery.Event) {
  195. e.preventDefault();
  196. movePos.dragScrolling = false;
  197. cursorPos.dragSelect = false;
  198. if( e.button != 0 )
  199. return;
  200. if( cursorPos.x2 >= cursorPos.x ) {
  201. value.x = cursorPos.x;
  202. value.width = cursorPos.x2 - cursorPos.x + 1;
  203. } else {
  204. value.x = cursorPos.x2;
  205. value.width = cursorPos.x - cursorPos.x2 + 1;
  206. }
  207. if( cursorPos.y2 >= cursorPos.y ) {
  208. value.y = cursorPos.y;
  209. value.height = cursorPos.y2 - cursorPos.y + 1;
  210. } else {
  211. value.y = cursorPos.y2;
  212. value.height = cursorPos.y - cursorPos.y2 + 1;
  213. }
  214. onChange(false);
  215. e.stopPropagation();
  216. });
  217. modal.on("contextmenu", function(e) {
  218. e.preventDefault();
  219. e.stopPropagation();
  220. });
  221. rescale();
  222. };
  223. i.src = url;
  224. }
  225. public dynamic function onChange( cancel : Bool ) {
  226. }
  227. }