ScaleGrid.hx 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. package h2d;
  2. /**
  3. A simple 9-slice bitmap renderer.
  4. Enables rendering of the Tile as a stretchable surface with unscaled corners, stretched center and either stretched or tiled borders.
  5. Set `ScaleGrid.width` and `ScaleGrid.height` to resize the ScaleGrid.
  6. **/
  7. class ScaleGrid extends h2d.TileGroup {
  8. /**
  9. The width of the left and right borders in pixels.
  10. **/
  11. public var borderWidth(default,set) : Int;
  12. /**
  13. The height of the top and bottom borders in pixels.
  14. **/
  15. public var borderHeight(default,set) : Int;
  16. /**
  17. The width of the bitmap. Setting to values less than `borderWidth * 2` leads to undefined results.
  18. **/
  19. public var width(default,set) : Float;
  20. /**
  21. The height of the bitmap. Setting to values less than `borderHeight * 2` leads to undefined results.
  22. **/
  23. public var height(default,set) : Float;
  24. /**
  25. When enabled, borders will be tiled along the edges instead of stretching to match the desired dimensions.
  26. Center tile is always stretched.
  27. **/
  28. public var tileBorders(default, set) : Bool;
  29. var contentTile : h2d.Tile;
  30. /**
  31. Create a new ScaleGrid with specified parameters.
  32. @param tile The source tile which will be sliced.
  33. @param borderW The width of the left and right borders in pixels.
  34. @param borderH The height of the top and bottom borders in pixels.
  35. @param parent An optional parent `h2d.Object` instance to which ScaleGrid adds itself if set.
  36. **/
  37. public function new( tile, borderW, borderH, ?parent ) {
  38. super(tile,parent);
  39. borderWidth = borderW;
  40. borderHeight = borderH;
  41. width = tile.width;
  42. height = tile.height;
  43. content.useAllocator = true;
  44. }
  45. function set_tileBorders(b) {
  46. if( tileBorders == b ) return b;
  47. this.tileBorders = b;
  48. clear();
  49. return b;
  50. }
  51. function set_width(w) {
  52. if( width == w ) return w;
  53. this.width = w;
  54. clear();
  55. return w;
  56. }
  57. function set_height(h) {
  58. if( height == h ) return h;
  59. this.height = h;
  60. clear();
  61. return h;
  62. }
  63. function set_borderWidth(w) {
  64. if( borderWidth == w ) return w;
  65. this.borderWidth = w;
  66. clear();
  67. return w;
  68. }
  69. function set_borderHeight(h) {
  70. if( borderHeight == h ) return h;
  71. this.borderHeight = h;
  72. clear();
  73. return h;
  74. }
  75. override function getBoundsRec(relativeTo, out, forSize) {
  76. checkUpdate();
  77. super.getBoundsRec(relativeTo, out, forSize);
  78. }
  79. function checkUpdate() {
  80. if( content.isEmpty() || tile != contentTile ) {
  81. clear();
  82. contentTile = tile;
  83. updateContent();
  84. }
  85. }
  86. function updateContent() {
  87. var bw = borderWidth, bh = borderHeight;
  88. // 4 corners
  89. content.addColor(0, 0, curColor, tile.sub(0, 0, bw, bh));
  90. content.addColor(width - bw, 0, curColor, tile.sub(tile.width - bw, 0, bw, bh));
  91. content.addColor(0, height-bh, curColor, tile.sub(0, tile.height - bh, bw, bh));
  92. content.addColor(width - bw, height - bh, curColor, tile.sub(tile.width - bw, tile.height - bh, bw, bh));
  93. var sizeX = tile.width - bw * 2;
  94. var sizeY = tile.height - bh * 2;
  95. if( !tileBorders ) {
  96. var w = width - bw * 2;
  97. var h = height - bh * 2;
  98. var t = tile.sub(bw, 0, sizeX, bh);
  99. t.scaleToSize(w, bh);
  100. content.addColor(bw, 0, curColor, t);
  101. var t = tile.sub(bw, tile.height - bh, sizeX, bh);
  102. t.scaleToSize(w, bh);
  103. content.addColor(bw, h + bh, curColor, t);
  104. var t = tile.sub(0, bh, bw, sizeY);
  105. t.scaleToSize(bw, h);
  106. content.addColor(0, bh, curColor, t);
  107. var t = tile.sub(tile.width - bw, bh, bw, sizeY);
  108. t.scaleToSize(bw, h);
  109. content.addColor(w + bw, bh, curColor, t);
  110. } else {
  111. var rw = Std.int((width - bw * 2) / sizeX);
  112. for( x in 0...rw ) {
  113. content.addColor(bw + x * sizeX, 0, curColor, tile.sub(bw, 0, sizeX, bh));
  114. content.addColor(bw + x * sizeX, height - bh, curColor, tile.sub(bw, tile.height - bh, sizeX, bh));
  115. }
  116. var dx = width - bw * 2 - rw * sizeX;
  117. if( dx > 0 ) {
  118. content.addColor(bw + rw * sizeX, 0, curColor, tile.sub(bw, 0, dx, bh));
  119. content.addColor(bw + rw * sizeX, height - bh, curColor, tile.sub(bw, tile.height - bh, dx, bh));
  120. }
  121. var rh = Std.int((height - bh * 2) / sizeY);
  122. for( y in 0...rh ) {
  123. content.addColor(0, bh + y * sizeY, curColor, tile.sub(0, bh, bw, sizeY));
  124. content.addColor(width - bw, bh + y * sizeY, curColor, tile.sub(tile.width - bw, bh, bw, sizeY));
  125. }
  126. var dy = height - bh * 2 - rh * sizeY;
  127. if( dy > 0 ) {
  128. content.addColor(0, bh + rh * sizeY, curColor, tile.sub(0, bh, bw, dy));
  129. content.addColor(width - bw, bh + rh * sizeY, curColor, tile.sub(tile.width - bw, bh, bw, dy));
  130. }
  131. }
  132. var t = tile.sub(bw, bh, sizeX, sizeY);
  133. t.scaleToSize(width - bw * 2,height - bh * 2);
  134. content.addColor(bw, bh, curColor, t);
  135. }
  136. override function sync( ctx : RenderContext ) {
  137. checkUpdate();
  138. super.sync(ctx);
  139. }
  140. }