1 module nudsfml.graphics.texture; 2 3 import std.string; 4 5 import bindbc.sfml.graphics; 6 import bindbc.sfml.system; 7 8 import nudsfml.graphics.rect; 9 import nudsfml.graphics.image; 10 import nudsfml.graphics.renderwindow; 11 12 import nudsfml.window.window; 13 14 import nudsfml.system.inputstream; 15 import nudsfml.system.vector2; 16 //import nudsfml.system.err; 17 18 /** 19 * Image living on the graphics card that can be used for drawing. 20 */ 21 class Texture 22 { 23 package sfTexture* sfPtr; 24 bool managed = false; 25 26 /** 27 * Default constructor 28 * 29 * Creates an empty texture. 30 */ 31 this() { 32 //sfPtr = sfTexture_construct(); 33 } 34 35 package this(sfTexture * texturePointer) 36 { 37 sfPtr = texturePointer; 38 managed = true; 39 } 40 41 /// Destructor. 42 ~this() { 43 //import nudsfml.system.config; 44 // mixin(destructorOutput); 45 if(!managed && sfPtr !is null) { 46 sfTexture_destroy(sfPtr); 47 sfPtr = null; 48 } 49 } 50 51 /** 52 * Load the texture from a file on disk. 53 * 54 * The area argument can be used to load only a sub-rectangle of the whole 55 * image. If you want the entire image then leave the default value (which 56 * is an empty IntRect). If the area rectangle crosses the bounds of the 57 * image, it is adjusted to fit the image size. 58 * 59 * The maximum size for a texture depends on the graphics driver and can be 60 * retrieved with the getMaximumSize function. 61 * 62 * If this function fails, the texture is left unchanged. 63 * 64 * Params: 65 * filename = Path of the image file to load 66 * area = Area of the image to load 67 * 68 * Returns: true if loading was successful, false otherwise. 69 */ 70 bool loadFromFile(const(char)[] filename, IntRect area = IntRect() ) 71 { 72 if(sfPtr !is null){ 73 sfTexture_destroy( sfPtr); 74 } 75 76 sfIntRect *sfArea = new sfIntRect; 77 sfArea.left = area.left; 78 sfArea.top = area.top; 79 sfArea.width = area.width; 80 sfArea.height = area.height; 81 82 sfPtr = sfTexture_createFromFile( filename.toStringz ,sfArea); 83 return sfPtr !is null; 84 } 85 86 /** 87 * Load the texture from a file in memory. 88 * 89 * The area argument can be used to load only a sub-rectangle of the whole 90 * image. If you want the entire image then leave the default value (which 91 * is an empty IntRect). If the area rectangle crosses the bounds of the 92 * image, it is adjusted to fit the image size. 93 * 94 * The maximum size for a texture depends on the graphics driver and can be 95 * retrieved with the getMaximumSize function. 96 * 97 * If this function fails, the texture is left unchanged. 98 * 99 * Params: 100 * data = Image in memory 101 * area = Area of the image to load 102 * 103 * Returns: true if loading was successful, false otherwise. 104 */ 105 bool loadFromMemory(const(void)[] data, IntRect area = IntRect()) 106 { 107 if(sfPtr !is null){ 108 sfTexture_destroy( sfPtr); 109 } 110 111 sfIntRect *sfArea = new sfIntRect; 112 sfArea.left = area.left; 113 sfArea.top = area.top; 114 sfArea.width = area.width; 115 sfArea.height = area.height; 116 117 sfPtr = sfTexture_createFromMemory(data.ptr, data.length,sfArea); 118 return sfPtr !is null; 119 120 } 121 /** 122 * Load the texture from an image. 123 * 124 * The area argument can be used to load only a sub-rectangle of the whole 125 * image. If you want the entire image then leave the default value (which 126 * is an empty IntRect). If the area rectangle crosses the bounds of the 127 * image, it is adjusted to fit the image size. 128 * 129 * The maximum size for a texture depends on the graphics driver and can be 130 * retrieved with the getMaximumSize function. 131 * 132 * If this function fails, the texture is left unchanged. 133 * 134 * Params: 135 * image = Image to load into the texture 136 * area = Area of the image to load 137 * 138 * Returns: true if loading was successful, false otherwise. 139 */ 140 bool loadFromImage(Image image, IntRect area = IntRect()) 141 { 142 143 if(sfPtr !is null){ 144 sfTexture_destroy( sfPtr); 145 } 146 147 sfIntRect *sfArea = new sfIntRect; 148 sfArea.left = area.left; 149 sfArea.top = area.top; 150 sfArea.width = area.width; 151 sfArea.height = area.height; 152 153 sfPtr = sfTexture_createFromImage(image.sfPtr,sfArea); 154 return sfPtr !is null; 155 } 156 157 /** 158 * Get the maximum texture size allowed. 159 * 160 * This Maximum size is defined by the graphics driver. You can expect a 161 * value of 512 pixels for low-end graphics card, and up to 8192 pixels or 162 * more for newer hardware. 163 * 164 * Returns: Maximum size allowed for textures, in pixels. 165 */ 166 static uint getMaximumSize() 167 { 168 return sfTexture_getMaximumSize(); 169 } 170 171 /** 172 * Return the size of the texture. 173 * 174 * Returns: Size in pixels. 175 */ 176 Vector2u getSize() const 177 { 178 sfVector2u temp = sfTexture_getSize( sfPtr); 179 Vector2u retval = Vector2u(temp.x,temp.y); 180 return retval; 181 } 182 183 /** 184 * Enable or disable the smooth filter. 185 * 186 * When the filter is activated, the texture appears smoother so that pixels 187 * are less noticeable. However if you want the texture to look exactly the 188 * same as its source file, you should leave it disabled. The smooth filter 189 * is disabled by default. 190 * 191 * Params: 192 * smooth = true to enable smoothing, false to disable it 193 */ 194 void setSmooth(bool smooth) 195 { 196 sfTexture_setSmooth(sfPtr, smooth); 197 } 198 199 /** 200 * Enable or disable repeating. 201 * 202 * Repeating is involved when using texture coordinates outside the texture 203 * rectangle [0, 0, width, height]. In this case, if repeat mode is enabled, 204 * the whole texture will be repeated as many times as needed to reach the 205 * coordinate (for example, if the X texture coordinate is 3 * width, the 206 * texture will be repeated 3 times). 207 * 208 * If repeat mode is disabled, the "extra space" will instead be filled with 209 * border pixels. Warning: on very old graphics cards, white pixels may 210 * appear when the texture is repeated. With such cards, repeat mode can be 211 * used reliably only if the texture has power-of-two dimensions 212 * (such as 256x128). Repeating is disabled by default. 213 * 214 * Params: 215 * repeated = true to repeat the texture, false to disable repeating 216 */ 217 void setRepeated(bool repeated) 218 { 219 sfTexture_setRepeated(sfPtr, repeated); 220 } 221 222 /** 223 * Bind a texture for rendering. 224 * 225 * This function is not part of the graphics API, it mustn't be used when 226 * drawing DSFML entities. It must be used only if you mix Texture with 227 * OpenGL code. 228 * 229 * Params: 230 * texture = The texture to bind. Can be null to use no texture 231 */ 232 static void bind(Texture texture) 233 { 234 (texture is null)?sfTexture_bind(null):sfTexture_bind(texture.sfPtr); 235 } 236 237 /** 238 * Create the texture. 239 * 240 * If this function fails, the texture is left unchanged. 241 * 242 * Params: 243 * width = Width of the texture 244 * height = Height of the texture 245 * 246 * Returns: true if creation was successful, false otherwise. 247 */ 248 bool create(uint width, uint height) 249 { 250 if(sfPtr !is null){ 251 sfTexture_destroy( sfPtr); 252 } 253 sfPtr = sfTexture_create(width,height); 254 return sfPtr !is null; 255 } 256 257 /** 258 * Copy the texture pixels to an image. 259 * 260 * This function performs a slow operation that downloads the texture's 261 * pixels from the graphics card and copies them to a new image, potentially 262 * applying transformations to pixels if necessary (texture may be padded or 263 * flipped). 264 * 265 * Returns: Image containing the texture's pixels. 266 */ 267 Image copyToImage() const 268 { 269 return new Image(sfTexture_copyToImage(sfPtr)); 270 } 271 272 /** 273 * Creates a new texture from the same data (this means copying the entire 274 * set of pixels). 275 */ 276 @property Texture dup() const 277 { 278 return new Texture(sfTexture_copy(sfPtr)); 279 } 280 281 /** 282 * Tell whether the texture is repeated or not. 283 * 284 * Returns: true if repeat mode is enabled, false if it is disabled. 285 */ 286 bool isRepeated() const 287 { 288 return (sfTexture_isRepeated(sfPtr)) > 0; 289 } 290 291 /** 292 * Tell whether the smooth filter is enabled or not. 293 * 294 * Returns: true if something is enabled, false if it is disabled. 295 */ 296 bool isSmooth() const 297 { 298 return (sfTexture_isSmooth(sfPtr)) > 0; 299 } 300 301 /** 302 * Update the whole texture from an array of pixels. 303 * 304 * The pixel array is assumed to have the same size as 305 * the area rectangle, and to contain 32-bits RGBA pixels. 306 * 307 * No additional check is performed on the size of the pixel 308 * array, passing invalid arguments will lead to an undefined 309 * behavior. 310 * 311 * This function does nothing if pixels is empty or if the 312 * texture was not previously created. 313 * 314 * Params: 315 * pixels = Array of pixels to copy to the texture. 316 */ 317 void update(const(ubyte)[] pixels) 318 { 319 Vector2u size = getSize(); 320 321 sfTexture_updateFromPixels(sfPtr,pixels.ptr,size.x, size.y, 0,0); 322 } 323 324 /** 325 * Update part of the texture from an array of pixels. 326 * 327 * The size of the pixel array must match the width and height arguments, 328 * and it must contain 32-bits RGBA pixels. 329 * 330 * No additional check is performed on the size of the pixel array or the 331 * bounds of the area to update, passing invalid arguments will lead to an 332 * undefined behaviour. 333 * 334 * This function does nothing if pixels is empty or if the texture was not 335 * previously created. 336 * 337 * Params: 338 * pixels = Array of pixels to copy to the texture. 339 * width = Width of the pixel region contained in pixels 340 * height = Height of the pixel region contained in pixels 341 * x = X offset in the texture where to copy the source pixels 342 * y = Y offset in the texture where to copy the source pixels 343 */ 344 void update(const(ubyte)[] pixels, uint width, uint height, uint x, uint y) 345 { 346 sfTexture_updateFromPixels(sfPtr,pixels.ptr,width, height, x,y); 347 } 348 349 /** 350 * Update the texture from an image. 351 * 352 * Although the source image can be smaller than the texture, this function 353 * is usually used for updating the whole texture. The other overload, which 354 * has (x, y) additional arguments, is more convenient for updating a 355 * sub-area of the texture. 356 * 357 * No additional check is performed on the size of the image, passing an 358 * image bigger than the texture will lead to an undefined behaviour. 359 * 360 * This function does nothing if the texture was not previously created. 361 * 362 * Params: 363 * image = Image to copy to the texture. 364 */ 365 void update(const(Image) image) 366 { 367 sfTexture_updateFromImage(sfPtr, image.sfPtr, 0, 0); 368 } 369 370 /** 371 * Update the texture from an image. 372 * 373 * No additional check is performed on the size of the image, passing an 374 * invalid combination of image size and offset will lead to an undefined 375 * behavior. 376 * 377 * This function does nothing if the texture was not previously created. 378 * 379 * Params: 380 * image = Image to copy to the texture. 381 * y = Y offset in the texture where to copy the source image. 382 * x = X offset in the texture where to copy the source image. 383 */ 384 void update(const(Image) image, uint x, uint y) 385 { 386 sfTexture_updateFromImage(sfPtr, image.sfPtr, x, y); 387 } 388 389 /** 390 * Update the texture from the contents of a window 391 * 392 * Although the source window can be smaller than the texture, this function 393 * is usually used for updating the whole texture. The other overload, which 394 * has (x, y) additional arguments, is more convenient for updating a 395 * sub-area of the texture. 396 * 397 * No additional check is performed on the size of the window, passing a 398 * window bigger than the texture will lead to an undefined behavior. 399 * 400 * This function does nothing if either the texture or the window 401 * was not previously created. 402 * 403 * Params: 404 * window = Window to copy to the texture 405 */ 406 void update(T)(const(T) window) 407 if(is(T == Window) || is(T == RenderWindow)) 408 { 409 update(window, 0, 0); 410 } 411 412 /** 413 * Update a part of the texture from the contents of a window. 414 * 415 * No additional check is performed on the size of the window, passing an 416 * invalid combination of window size and offset will lead to an undefined 417 * behavior. 418 * 419 * This function does nothing if either the texture or the window was not 420 * previously created. 421 * 422 * Params: 423 * window = Window to copy to the texture 424 * x = X offset in the texture where to copy the source window 425 * y = Y offset in the texture where to copy the source window 426 * 427 */ 428 void update(T)(const(T) window, uint x, uint y) 429 if(is(T == Window) || is(T == RenderWindow)) 430 { 431 static if(is(T == RenderWindow)) 432 { 433 sfTexture_updateFromRenderWindow(sfPtr, T.sfPtr, x, y); 434 } 435 else 436 { 437 sfTexture_updateFromWindow(sfPtr, RenderWindow.windowPointer(T), 438 x, y); 439 } 440 } 441 442 /** 443 * Update the texture from an image. 444 * 445 * Although the source image can be smaller than the texture, this function 446 * is usually used for updating the whole texture. The other overload, which 447 * has (x, y) additional arguments, is more convenient for updating a 448 * sub-area of the texture. 449 * 450 * No additional check is performed on the size of the image, passing an 451 * image bigger than the texture will lead to an undefined behaviour. 452 * 453 * This function does nothing if the texture was not previously created. 454 * 455 * Params: 456 * image = Image to copy to the texture. 457 * y = Y offset in the texture where to copy the source image. 458 * x = X offset in the texture where to copy the source image. 459 */ 460 //deprecated("Use update function.") 461 void updateFromImage(Image image, uint x, uint y) 462 { 463 sfTexture_updateFromImage(sfPtr, image.sfPtr, x, y); 464 } 465 466 /** 467 * Update part of the texture from an array of pixels. 468 * 469 * The size of the pixel array must match the width and height arguments, 470 * and it must contain 32-bits RGBA pixels. 471 * 472 * No additional check is performed on the size of the pixel array or the 473 * bounds of the area to update, passing invalid arguments will lead to an 474 * undefined behaviour. 475 * 476 * This function does nothing if pixels is null or if the texture was not 477 * previously created. 478 * 479 * Params: 480 * pixels = Array of pixels to copy to the texture. 481 * width = Width of the pixel region contained in pixels 482 * height = Height of the pixel region contained in pixels 483 * x = X offset in the texture where to copy the source pixels 484 * y = Y offset in the texture where to copy the source pixels 485 */ 486 //deprecated("Use update function.") 487 void updateFromPixels(const(ubyte)[] pixels, uint width, uint height, uint x, uint y) 488 { 489 sfTexture_updateFromPixels(sfPtr,pixels.ptr,width, height, x,y); 490 } 491 492 //TODO: Get this working via inheritance?(so custom window classes can do it too) 493 /** 494 * Update a part of the texture from the contents of a window. 495 * 496 * No additional check is performed on the size of the window, passing an 497 * invalid combination of window size and offset will lead to an undefined 498 * behaviour. 499 * 500 * This function does nothing if either the texture or the window was not 501 * previously created. 502 * 503 * Params: 504 * window = Window to copy to the texture 505 * x = X offset in the texture where to copy the source window 506 * y = Y offset in the texture where to copy the source window 507 */ 508 //deprecated("Use update function.") 509 void updateFromWindow(Window window, uint x, uint y) 510 { 511 // sfTexture_updateFromWindow(sfPtr, RenderWindow.windowPointer(window), x, y); 512 } 513 514 //Is this even safe? RenderWindow inherits from Window, so what happens? Is this bottom used or the top? 515 /** 516 * Update a part of the texture from the contents of a window. 517 * 518 * No additional check is performed on the size of the window, passing an 519 * invalid combination of window size and offset will lead to an undefined 520 * behaviour. 521 * 522 * This function does nothing if either the texture or the window was not 523 * previously created. 524 * 525 * Params: 526 * window = Window to copy to the texture 527 * x = X offset in the texture where to copy the source window 528 * y = Y offset in the texture where to copy the source window 529 */ 530 //deprecated("Use update function.") 531 void updateFromWindow(RenderWindow window, uint x, uint y) 532 { 533 // sfTexture_updateFromRenderWindow(sfPtr, window.sfPtr, x, y); 534 } 535 }