dynamicTexture.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. import { Logger } from "../../Misc/logger.js";
  2. import { Texture } from "../../Materials/Textures/texture.js";
  3. import "../../Engines/Extensions/engine.dynamicTexture.js";
  4. /**
  5. * A class extending Texture allowing drawing on a texture
  6. * @see https://doc.babylonjs.com/features/featuresDeepDive/materials/using/dynamicTexture
  7. */
  8. export class DynamicTexture extends Texture {
  9. /**
  10. * Creates a DynamicTexture
  11. * @param name defines the name of the texture
  12. * @param options provides 3 alternatives for width and height of texture, a canvas, object with width and height properties, number for both width and height
  13. * @param scene defines the scene where you want the texture
  14. * @param generateMipMaps defines the use of MinMaps or not (default is false)
  15. * @param samplingMode defines the sampling mode to use (default is Texture.TRILINEAR_SAMPLINGMODE)
  16. * @param format defines the texture format to use (default is Engine.TEXTUREFORMAT_RGBA)
  17. * @param invertY defines if the texture needs to be inverted on the y axis during loading
  18. */
  19. constructor(name, options, scene = null, generateMipMaps = false, samplingMode = 3, format = 5, invertY) {
  20. super(null, scene, !generateMipMaps, invertY, samplingMode, undefined, undefined, undefined, undefined, format);
  21. this.name = name;
  22. this.wrapU = Texture.CLAMP_ADDRESSMODE;
  23. this.wrapV = Texture.CLAMP_ADDRESSMODE;
  24. this._generateMipMaps = generateMipMaps;
  25. const engine = this._getEngine();
  26. if (!engine) {
  27. return;
  28. }
  29. if (options.getContext) {
  30. this._canvas = options;
  31. this._ownCanvas = false;
  32. this._texture = engine.createDynamicTexture(options.width, options.height, generateMipMaps, samplingMode);
  33. }
  34. else {
  35. this._canvas = engine.createCanvas(1, 1);
  36. this._ownCanvas = true;
  37. if (options.width || options.width === 0) {
  38. this._texture = engine.createDynamicTexture(options.width, options.height, generateMipMaps, samplingMode);
  39. }
  40. else {
  41. this._texture = engine.createDynamicTexture(options, options, generateMipMaps, samplingMode);
  42. }
  43. }
  44. const textureSize = this.getSize();
  45. if (this._canvas.width !== textureSize.width) {
  46. this._canvas.width = textureSize.width;
  47. }
  48. if (this._canvas.height !== textureSize.height) {
  49. this._canvas.height = textureSize.height;
  50. }
  51. this._context = this._canvas.getContext("2d");
  52. }
  53. /**
  54. * Get the current class name of the texture useful for serialization or dynamic coding.
  55. * @returns "DynamicTexture"
  56. */
  57. getClassName() {
  58. return "DynamicTexture";
  59. }
  60. /**
  61. * Gets the current state of canRescale
  62. */
  63. get canRescale() {
  64. return true;
  65. }
  66. _recreate(textureSize) {
  67. this._canvas.width = textureSize.width;
  68. this._canvas.height = textureSize.height;
  69. this.releaseInternalTexture();
  70. this._texture = this._getEngine().createDynamicTexture(textureSize.width, textureSize.height, this._generateMipMaps, this.samplingMode);
  71. }
  72. /**
  73. * Scales the texture
  74. * @param ratio the scale factor to apply to both width and height
  75. */
  76. scale(ratio) {
  77. const textureSize = this.getSize();
  78. textureSize.width *= ratio;
  79. textureSize.height *= ratio;
  80. this._recreate(textureSize);
  81. }
  82. /**
  83. * Resizes the texture
  84. * @param width the new width
  85. * @param height the new height
  86. */
  87. scaleTo(width, height) {
  88. const textureSize = this.getSize();
  89. textureSize.width = width;
  90. textureSize.height = height;
  91. this._recreate(textureSize);
  92. }
  93. /**
  94. * Gets the context of the canvas used by the texture
  95. * @returns the canvas context of the dynamic texture
  96. */
  97. getContext() {
  98. return this._context;
  99. }
  100. /**
  101. * Clears the texture
  102. * @param clearColor Defines the clear color to use
  103. */
  104. clear(clearColor) {
  105. const size = this.getSize();
  106. if (clearColor) {
  107. this._context.fillStyle = clearColor;
  108. }
  109. this._context.clearRect(0, 0, size.width, size.height);
  110. }
  111. /**
  112. * Updates the texture
  113. * @param invertY defines the direction for the Y axis (default is true - y increases downwards)
  114. * @param premulAlpha defines if alpha is stored as premultiplied (default is false)
  115. * @param allowGPUOptimization true to allow some specific GPU optimizations (subject to engine feature "allowGPUOptimizationsForGUI" being true)
  116. */
  117. update(invertY, premulAlpha = false, allowGPUOptimization = false) {
  118. this._getEngine().updateDynamicTexture(this._texture, this._canvas, invertY === undefined ? true : invertY, premulAlpha, this._format || undefined, undefined, allowGPUOptimization);
  119. }
  120. /**
  121. * Draws text onto the texture
  122. * @param text defines the text to be drawn
  123. * @param x defines the placement of the text from the left
  124. * @param y defines the placement of the text from the top when invertY is true and from the bottom when false
  125. * @param font defines the font to be used with font-style, font-size, font-name
  126. * @param color defines the color used for the text
  127. * @param fillColor defines the color for the canvas, use null to not overwrite canvas (this bleands with the background to replace, use the clear function)
  128. * @param invertY defines the direction for the Y axis (default is true - y increases downwards)
  129. * @param update defines whether texture is immediately update (default is true)
  130. */
  131. drawText(text, x, y, font, color, fillColor, invertY, update = true) {
  132. const size = this.getSize();
  133. if (fillColor) {
  134. this._context.fillStyle = fillColor;
  135. this._context.fillRect(0, 0, size.width, size.height);
  136. }
  137. this._context.font = font;
  138. if (x === null || x === undefined) {
  139. const textSize = this._context.measureText(text);
  140. x = (size.width - textSize.width) / 2;
  141. }
  142. if (y === null || y === undefined) {
  143. const fontSize = parseInt(font.replace(/\D/g, ""));
  144. y = size.height / 2 + fontSize / 3.65;
  145. }
  146. this._context.fillStyle = color || "";
  147. this._context.fillText(text, x, y);
  148. if (update) {
  149. this.update(invertY);
  150. }
  151. }
  152. /**
  153. * Disposes the dynamic texture.
  154. */
  155. dispose() {
  156. super.dispose();
  157. if (this._ownCanvas) {
  158. this._canvas?.remove?.();
  159. }
  160. this._canvas = null;
  161. this._context = null;
  162. }
  163. /**
  164. * Clones the texture
  165. * @returns the clone of the texture.
  166. */
  167. clone() {
  168. const scene = this.getScene();
  169. if (!scene) {
  170. return this;
  171. }
  172. const textureSize = this.getSize();
  173. const newTexture = new DynamicTexture(this.name, textureSize, scene, this._generateMipMaps);
  174. // Base texture
  175. newTexture.hasAlpha = this.hasAlpha;
  176. newTexture.level = this.level;
  177. // Dynamic Texture
  178. newTexture.wrapU = this.wrapU;
  179. newTexture.wrapV = this.wrapV;
  180. return newTexture;
  181. }
  182. /**
  183. * Serializes the dynamic texture. The scene should be ready before the dynamic texture is serialized
  184. * @returns a serialized dynamic texture object
  185. */
  186. serialize() {
  187. const scene = this.getScene();
  188. if (scene && !scene.isReady()) {
  189. Logger.Warn("The scene must be ready before serializing the dynamic texture");
  190. }
  191. const serializationObject = super.serialize();
  192. if (DynamicTexture._IsCanvasElement(this._canvas)) {
  193. serializationObject.base64String = this._canvas.toDataURL();
  194. }
  195. serializationObject.invertY = this._invertY;
  196. serializationObject.samplingMode = this.samplingMode;
  197. return serializationObject;
  198. }
  199. static _IsCanvasElement(canvas) {
  200. return canvas.toDataURL !== undefined;
  201. }
  202. /** @internal */
  203. _rebuild() {
  204. this.update();
  205. }
  206. }
  207. //# sourceMappingURL=dynamicTexture.js.map