AbstractMask.hx 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. package h2d.filter;
  2. @:dox(hide)
  3. class Hide extends Filter {
  4. public var frame : Int;
  5. public var input : h2d.Tile;
  6. public var maskVisible : Bool;
  7. public var inputWidth:Int;
  8. public var inputHeight:Int;
  9. public function new() {
  10. super();
  11. this.boundsExtend = 1;
  12. }
  13. override function draw( ctx : RenderContext, input : h2d.Tile ) {
  14. this.frame = ctx.frame;
  15. this.input = input;
  16. this.inputWidth = input.iwidth;
  17. this.inputHeight = input.iheight;
  18. return maskVisible ? input : null;
  19. }
  20. }
  21. /**
  22. A base class for filters that utilize separate Objects as a masking object.
  23. Not intended to be used directly.
  24. Masking objects have a number of restrictions on them, see `AbstractMask.mask` for details.
  25. **/
  26. class AbstractMask extends Filter {
  27. var hide : Hide;
  28. var maskMatrix : h2d.col.Matrix;
  29. var tmpMatrix : h2d.col.Matrix;
  30. var obj : h2d.Object;
  31. var bindCount : Int = 0;
  32. /**
  33. The Object contents of which serve as a mask to the filtered Object.
  34. Masking Objects have following limitations:
  35. * It cannot be a parent of the filtered Object.
  36. * It should not contain any filters.
  37. * It should be present in the object tree and precede the Object it masks in the rendering order (rendered before it).
  38. * Same masking Object cannot be used by multiple mask filters.
  39. **/
  40. public var mask(default, set) : h2d.Object;
  41. /**
  42. When enabled, masking Object will be visible to the user. Hidden otherwise. ( default : false )
  43. **/
  44. public var maskVisible(default, set) : Bool;
  45. function new(mask) {
  46. super();
  47. hide = new Hide();
  48. this.mask = mask;
  49. this.maskMatrix = new h2d.col.Matrix();
  50. tmpMatrix = new h2d.col.Matrix();
  51. }
  52. function set_maskVisible(b) {
  53. hide.maskVisible = b;
  54. return maskVisible = b;
  55. }
  56. override function bind(s:Object) {
  57. bindCount++;
  58. if( bindCount == 1 )
  59. this.mask = mask;
  60. }
  61. override function unbind(s:Object) {
  62. bindCount--;
  63. if( bindCount == 0 )
  64. this.mask = mask;
  65. }
  66. function set_mask(m:h2d.Object) {
  67. if( mask != null ) {
  68. if( mask.filter == hide )
  69. mask.filter = null;
  70. }
  71. mask = m;
  72. if( m != null && bindCount > 0 ) {
  73. if( m.filter != null ) {
  74. if( hxd.impl.Api.isOfType(m.filter,Hide) ) throw "Same mask can't be part of several filters";
  75. throw "Can't set mask with filter "+m.filter;
  76. }
  77. m.filter = hide;
  78. }
  79. hide.input = null;
  80. return m;
  81. }
  82. function getMaskTexture( ctx : h2d.RenderContext, tile : h2d.Tile ) {
  83. var t = hide.input == null ? null : hide.input.getTexture();
  84. if( t == null ) return null;
  85. // Note : this does not seem to work very nice with rotations
  86. // because of the not uniform final scaling. let's fix that some other day
  87. @:privateAccess mask.getMatrix(maskMatrix);
  88. maskMatrix.prependTranslate(hide.input.dx, hide.input.dy);
  89. maskMatrix.invert();
  90. @:privateAccess obj.getMatrix(tmpMatrix);
  91. tmpMatrix.prependTranslate(tile.dx, tile.dy);
  92. maskMatrix.multiply(tmpMatrix, maskMatrix);
  93. var resolutionScale = ctx.getFilterScale(@:privateAccess h2d.Object.tmpPoint);
  94. // move from tex a to tex b
  95. maskMatrix.x /= tile.width / resolutionScale.x;
  96. maskMatrix.y /= tile.height / resolutionScale.y;
  97. maskMatrix.scale(tile.width / hide.inputWidth, tile.height / hide.inputHeight);
  98. t.filter = smooth ? Linear : Nearest;
  99. return t;
  100. }
  101. override function sync( ctx : RenderContext, obj : h2d.Object ) {
  102. this.obj = obj;
  103. if( mask == null || hide.frame != ctx.frame ) {
  104. var p = obj;
  105. while( p != null ) {
  106. if( p == mask ) throw "You can't mask with one of the object parents";
  107. p = p.parent;
  108. }
  109. hide.input = null;
  110. }
  111. }
  112. override function set_resolutionScale(v:Float):Float
  113. {
  114. hide.resolutionScale = v;
  115. return super.set_resolutionScale(v);
  116. }
  117. override function set_useScreenResolution(v:Bool):Bool
  118. {
  119. hide.useScreenResolution = v;
  120. return super.set_useScreenResolution(v);
  121. }
  122. }