1 /++ 2 + Authors: Avaxar <avaxar@nekkl.org> 3 + Copyright: Copyright © 2023, Avaxar 4 + License: $(LINK2 https://mit-license.org, MIT License) 5 +/ 6 7 module dsdl2.renderer; 8 @safe: 9 10 import bindbc.sdl; 11 import dsdl2.sdl; 12 import dsdl2.blend; 13 import dsdl2.rect; 14 import dsdl2.frect; 15 import dsdl2.pixels; 16 import dsdl2.surface; 17 import dsdl2.texture; 18 import dsdl2.window; 19 20 import core.memory : GC; 21 import std.bitmanip : bitfields; 22 import std.conv : to; 23 import std.format : format; 24 import std.string : toStringz; 25 import std.typecons : Nullable, nullable; 26 27 private uint toSDLRendererFlags(bool software, bool accelerated, bool presentVSync, bool targetTexture) { 28 uint flags = 0; 29 30 flags |= software ? SDL_RENDERER_SOFTWARE : 0; 31 flags |= accelerated ? SDL_RENDERER_ACCELERATED : 0; 32 flags |= presentVSync ? SDL_RENDERER_PRESENTVSYNC : 0; 33 flags |= targetTexture ? SDL_RENDERER_TARGETTEXTURE : 0; 34 35 return flags; 36 } 37 38 /++ 39 + D struct that wraps `SDL_RendererInfo` containing renderer information 40 +/ 41 struct RendererInfo { 42 string name; /// Name of the renderer 43 PixelFormat[] textureFormats; /// Available texture pixel formats 44 uint[2] maxTextureSize; /// Maximum texture size 45 uint sdlFlags; /// Internal SDL bitmask of supported renderer flags 46 47 this() @disable; 48 49 /++ 50 + Constructs a `dsdl2.RendererInfo` from a vanilla `SDL_RendererInfo` from bindbc-sdl 51 + 52 + Params: 53 + sdlRendererInfo = the `SDL_RendererInfo` struct 54 +/ 55 this(SDL_RendererInfo sdlRendererInfo) @trusted { 56 this.name = sdlRendererInfo.name.to!string; 57 this.sdlFlags = sdlRendererInfo.flags; 58 this.textureFormats.length = sdlRendererInfo.num_texture_formats; 59 foreach (i; 0 .. sdlRendererInfo.num_texture_formats) { 60 this.textureFormats[i] = new PixelFormat(sdlRendererInfo.texture_formats[i]); 61 } 62 this.maxTextureSize = [ 63 sdlRendererInfo.max_texture_width.to!uint, 64 sdlRendererInfo.max_texture_height.to!uint 65 ]; 66 } 67 68 /++ 69 + Constructs a `dsdl2.RendererInfo` by feeding it its attributes 70 + 71 + Params: 72 + name = name of the renderer 73 + textureFormats = available texture pixel format(s) 74 + maxTextureSize = maximum size a texture can be 75 + software = adds `SDL_RENDERER_SOFTWARE` flag 76 + accelerated = adds `SDL_RENDERER_ACCELERATED` flag 77 + presentVSync = adds `SDL_RENDERER_PRESENTVSYNC` flag 78 + targetTexture = adds `SDL_RENDERER_TARGETTEXTURE` flag 79 +/ 80 this(string name, PixelFormat[] textureFormats, uint[2] maxTextureSize, bool software = false, 81 bool accelerated = false, bool presentVSync = false, bool targetTexture = false) @trusted { 82 this.name = name; 83 this.textureFormats = textureFormats; 84 this.maxTextureSize = maxTextureSize; 85 this.sdlFlags = toSDLRendererFlags(software, accelerated, presentVSync, targetTexture); 86 } 87 88 /++ 89 + Formats the `dsdl2.RendererInfo` into its construction representation: 90 + `"dsdl2.RendererInfo(<name>, <textureFormats>, <maxTextureSize>, <flag> : <value> ...)"` 91 + 92 + Returns: the formatted `string` 93 +/ 94 string toString() const { 95 return "dsdl2.RendererInfo(%s, %s, %s, software : %s, accelerated : %s, presentVSync : %s, targetTexture : %s)" 96 .format([this.name].to!string[1 .. $ - 1], this.textureFormats, this.maxTextureSize, 97 this.software, this.accelerated, this.presentVSync, this.targetTexture); 98 } 99 100 /++ 101 + Gets the internal `SDL_RendererInfo` representation 102 + 103 + Returns: `SDL_RendererInfo` with all of the attributes 104 +/ 105 inout(SDL_RendererInfo) sdlRendererInfo() inout @property { 106 uint[16] textureFormatEnums = void; 107 foreach (i, inout textureFormat; this.textureFormats) { 108 textureFormatEnums[i] = textureFormat.sdlPixelFormatEnum; 109 } 110 111 return inout SDL_RendererInfo(this.name.toStringz(), this.sdlFlags, this.textureFormats.length.to!uint, 112 textureFormatEnums, this.maxTextureWidth, this.maxTextureHeight); 113 } 114 115 /++ 116 + Gets whether the `dsdl2.RendererInfo` has `SDL_RENDERER_SOFTWARE` flag 117 + 118 + Returns: `true` if it has `SDL_RENDERER_SOFTWARE` flag, otherwise `false` 119 +/ 120 bool software() const @property { 121 return (this.sdlFlags & SDL_RENDERER_SOFTWARE) != 0; 122 } 123 124 /++ 125 + Sets whether the `dsdl2.RendererInfo` has `SDL_RENDERER_SOFTWARE` flag 126 + 127 + Params: 128 + value = `true` to set `SDL_RENDERER_SOFTWARE` flag; `false` to unset it 129 +/ 130 void software(bool value) @property { 131 this.sdlFlags |= value ? SDL_RENDERER_SOFTWARE : 0; 132 } 133 134 /++ 135 + Gets whether the `dsdl2.RendererInfo` has `SDL_RENDERER_ACCELERATED` flag 136 + 137 + Returns: `true` if it has `SDL_RENDERER_ACCELERATED` flag, otherwise `false` 138 +/ 139 bool accelerated() const @property { 140 return (this.sdlFlags & SDL_RENDERER_ACCELERATED) != 0; 141 } 142 143 /++ 144 + Sets whether the `dsdl2.RendererInfo` has `SDL_RENDERER_ACCELERATED` flag 145 + 146 + Params: 147 + value = `true` to set `SDL_RENDERER_ACCELERATED` flag; `false` to unset it 148 +/ 149 void accelerated(bool value) @property { 150 this.sdlFlags |= value ? SDL_RENDERER_ACCELERATED : 0; 151 } 152 153 /++ 154 + Gets whether the `dsdl2.RendererInfo` has `SDL_RENDERER_PRESENTVSYNC` flag 155 + 156 + Returns: `true` if it has `SDL_RENDERER_PRESENTVSYNC` flag, otherwise `false` 157 +/ 158 bool presentVSync() const @property { 159 return (this.sdlFlags & SDL_RENDERER_PRESENTVSYNC) != 0; 160 } 161 162 /++ 163 + Sets whether the `dsdl2.RendererInfo` has `SDL_RENDERER_PRESENTVSYNC` flag 164 + 165 + Params: 166 + value = `true` to set `SDL_RENDERER_PRESENTVSYNC` flag; `false` to unset it 167 +/ 168 void presentVSync(bool value) @property { 169 this.sdlFlags |= value ? SDL_RENDERER_PRESENTVSYNC : 0; 170 } 171 172 /++ 173 + Gets whether the `dsdl2.RendererInfo` has `SDL_RENDERER_TARGETTEXTURE` flag 174 + 175 + Returns: `true` if it has `SDL_RENDERER_TARGETTEXTURE` flag, otherwise `false` 176 +/ 177 bool targetTexture() const @property { 178 return (this.sdlFlags & SDL_RENDERER_TARGETTEXTURE) != 0; 179 } 180 181 /++ 182 + Sets whether the `dsdl2.RendererInfo` has `SDL_RENDERER_TARGETTEXTURE` flag 183 + 184 + Params: 185 + value = `true` to set `SDL_RENDERER_TARGETTEXTURE` flag; `false` to unset it 186 +/ 187 void targetTexture(bool value) @property { 188 this.sdlFlags |= value ? SDL_RENDERER_TARGETTEXTURE : 0; 189 } 190 191 /++ 192 + Proxy to the maximum texture width of the `dsdl2.RendererInfo` 193 + 194 + Returns: maximum texture width of the `dsdl2.RendererInfo` 195 +/ 196 ref inout(uint) maxTextureWidth() return inout @property { 197 return this.maxTextureSize[0]; 198 } 199 200 /++ 201 + Proxy to the maximum texture height of the `dsdl2.RendererInfo` 202 + 203 + Returns: maximum texture height of the `dsdl2.RendererInfo` 204 +/ 205 ref inout(uint) maxTextureHeight() return inout @property { 206 return this.maxTextureSize[1]; 207 } 208 } 209 210 /++ 211 + D class that acts as a proxy for a render driver from a render driver index 212 +/ 213 final class RenderDriver { 214 const uint sdlRenderDriverIndex; /// Render driver index from SDL 215 const RendererInfo info = void; /// `dsdl2.RendererInfo` instance fetched from the driver 216 217 this() @disable; 218 219 private this(uint sdlRenderDriverIndex) @trusted { 220 this.sdlRenderDriverIndex = sdlRenderDriverIndex; 221 222 SDL_RendererInfo sdlRendererInfo; 223 if (SDL_GetRenderDriverInfo(sdlRenderDriverIndex.to!int, &sdlRendererInfo) != 0) { 224 throw new SDLException; 225 } 226 227 this.info = RendererInfo(sdlRendererInfo); 228 } 229 230 /++ 231 + Formats the `dsdl2.RenderDriver` into its construction representation: 232 + `"dsdl2.RenderDriver(<sdlRenderDriverIndex>)"` 233 + 234 + Returns: the formatted `string` 235 +/ 236 override string toString() const { 237 return "dsdl2.RenderDriver(%d)".format(this.sdlRenderDriverIndex); 238 } 239 } 240 241 /++ 242 + Gets `dsdl2.RenderDriver` proxy instances of the available render drivers in the system 243 + 244 + Returns: array of proxies to the available `dsdl2.RenderDriver`s 245 + Throws: `dsdl2.SDLException` if failed to get the available render drivers 246 +/ 247 const(RenderDriver[]) getRenderDrivers() @trusted { 248 int numDrivers = SDL_GetNumRenderDrivers(); 249 if (numDrivers < 0) { 250 throw new SDLException; 251 } 252 253 static RenderDriver[] drivers; 254 if (drivers !is null) { 255 size_t originalLength = drivers.length; 256 drivers.length = numDrivers; 257 258 if (numDrivers > originalLength) { 259 foreach (i; originalLength .. numDrivers) { 260 drivers[i] = new RenderDriver(i.to!uint); 261 } 262 } 263 } 264 else { 265 drivers = new RenderDriver[](numDrivers); 266 foreach (i; 0 .. numDrivers) { 267 drivers[i] = new RenderDriver(i); 268 } 269 } 270 271 return drivers; 272 } 273 274 static if (sdlSupport >= SDLSupport.v2_0_18) { 275 /++ 276 + D struct that wraps `SDL_Vertex` (from SDL 2.0.18) containing 2D vertex information 277 + 278 + `dsdl2.Vertex` stores the `position` of the vertex, `color` modulation (as well as alpha), and mapped texture 279 + `texCoord`inate. 280 +/ 281 struct Vertex { 282 SDL_Vertex sdlVertex; /// Internal `SDL_Vertex` struct 283 284 this() @disable; 285 286 /++ 287 + Constructs a `dsdl2.Vertex` from a vanilla `SDL_Vertex` from bindbc-sdl 288 + 289 + Params: 290 + sdlVertex = the `dsdl2.Vertex` struct 291 +/ 292 this(SDL_Vertex sdlVertex) { 293 this.sdlVertex = sdlVertex; 294 } 295 296 /++ 297 + Constructs a `dsdl2.Vertex` by feeding in the position, color, and texture coordinate 298 + 299 + Params: 300 + position = vertex target position 301 + color = color and alpha modulation of the vertex 302 + texCoord = vertex texture coordinate 303 +/ 304 this(FPoint position, Color color, FPoint texCoord) { 305 this.sdlVertex.position = position.sdlFPoint; 306 this.sdlVertex.color = color.sdlColor; 307 this.sdlVertex.tex_coord = texCoord.sdlFPoint; 308 } 309 310 /++ 311 + Formats the `dsdl2.Vertex` into its construction representation: 312 + `"dsdl2.Vertex(<position>, <color>, <texCoord>)"` 313 + 314 + Returns: the formatted `string` 315 +/ 316 string toString() const { 317 return "dsdl2.Vertex(%f, %f)".format(this.position, this.color, this.texCoord); 318 } 319 320 /++ 321 + Proxy to the X position of the `dsdl2.Vertex` 322 + 323 + Returns: X position of the `dsdl2.Vertex` 324 +/ 325 ref inout(float) x() return inout @property { 326 return this.sdlVertex.position.x; 327 } 328 329 /++ 330 + Proxy to the Y position of the `dsdl2.Vertex` 331 + 332 + Returns: Y position of the `dsdl2.Vertex` 333 +/ 334 ref inout(float) y() return inout @property { 335 return this.sdlVertex.position.y; 336 } 337 338 /++ 339 + Proxy to the position of the `dsdl2.Vertex` 340 + 341 + Returns: position of the `dsdl2.Vertex` 342 +/ 343 ref inout(FPoint) position() return inout @property { 344 return *cast(inout(FPoint*))&this.sdlVertex.position; 345 } 346 347 /++ 348 + Proxy to the color of the `dsdl2.Vertex` 349 + 350 + Returns: color of the `dsdl2.Vertex` 351 +/ 352 ref inout(Color) color() return inout @property { 353 return *cast(inout(Color*))&this.sdlVertex.color; 354 } 355 356 /++ 357 + Proxy to the X texture coordinate of the `dsdl2.Vertex` 358 + 359 + Returns: X texture coordinate of the `dsdl2.Vertex` 360 +/ 361 ref inout(float) texX() return inout @property { 362 return this.sdlVertex.tex_coord.x; 363 } 364 365 /++ 366 + Proxy to the Y texture coordinate of the `dsdl2.Vertex` 367 + 368 + Returns: Y texture coordinate of the `dsdl2.Vertex` 369 +/ 370 ref inout(float) texY() return inout @property { 371 return this.sdlVertex.tex_coord.y; 372 } 373 374 /++ 375 + Proxy to the texture coordinate of the `dsdl2.Vertex` 376 + 377 + Returns: texture coordinate of the `dsdl2.Vertex` 378 +/ 379 ref inout(FPoint) texCoord() return inout @property { 380 return *cast(inout(FPoint*))&this.sdlVertex.tex_coord; 381 } 382 } 383 } 384 385 /++ 386 + D class that wraps `SDL_Renderer` managing a backend rendering instance 387 + 388 + `dsdl2.Renderer` provides access to 2D draw commands, which accesses the internal backend renderer. The output/target 389 + of the renderer can be displayed to a `dsdl2.Window` if desired, or be done in software to the RAM as a 390 + `dsdl2.Surface`. 391 + 392 + Example: 393 + --- 394 + auto window = new dsdl2.Window("My Window", [dsdl2.WindowPos.centered, dsdl2.WindowPos.centered], [800, 600]); 395 + auto renderer = new dsdl2.Renderer(window, accelerated : true, acceleratedVSync : true); 396 + --- 397 +/ 398 final class Renderer { 399 private Texture targetProxy = null; 400 private bool isOwner = true; 401 private void* userRef = null; 402 403 @system SDL_Renderer* sdlRenderer = null; /// Internal `SDL_Renderer` pointer 404 405 /++ 406 + Constructs a `dsdl2.Renderer` from a vanilla `SDL_Renderer*` from bindbc-sdl 407 + 408 + Params: 409 + sdlRenderer = the `SDL_Renderer` pointer to manage 410 + isOwner = whether the instance owns the given `SDL_Renderer*` and should destroy it on its own 411 + userRef = optional pointer to maintain reference link, avoiding GC cleanup 412 +/ 413 this(SDL_Renderer* sdlRenderer, bool isOwner = true, void* userRef = null) @system 414 in { 415 assert(sdlRenderer !is null); 416 } 417 do { 418 this.sdlRenderer = sdlRenderer; 419 this.isOwner = isOwner; 420 this.userRef = userRef; 421 } 422 423 /++ 424 + Creates a hardware `dsdl2.Renderer` that renders to a `dsdl2.Window`, which wraps `SDL_CreateRenderer` 425 + 426 + Params: 427 + window = target `dsdl2.Window` for the renderer to draw onto which must not have a surface associated 428 + renderDriver = the `dsdl2.RenderDriver` to use; `null` to use the default 429 + software = adds `SDL_RENDERER_SOFTWARE` flag 430 + accelerated = adds `SDL_RENDERER_ACCELERATED` flag 431 + presentVSync = adds `SDL_RENDERER_PRESENTVSYNC` flag 432 + targetTexture = adds `SDL_RENDERER_TARGETTEXTURE` flag 433 + Throws: `dsdl2.SDLException` if creation failed 434 +/ 435 this(Window window, const RenderDriver renderDriver = null, bool software = false, 436 bool accelerated = false, bool presentVSync = false, bool targetTexture = false) @trusted 437 in { 438 assert(window !is null); 439 } 440 do { 441 uint flags = toSDLRendererFlags(software, accelerated, presentVSync, targetTexture); 442 this.sdlRenderer = SDL_CreateRenderer(window.sdlWindow, 443 renderDriver is null ? -1 : renderDriver.sdlRenderDriverIndex.to!uint, flags); 444 if (this.sdlRenderer is null) { 445 throw new SDLException; 446 } 447 } 448 449 /++ 450 + Creates a software `dsdl2.Renderer` that renders to a target surface, which wraps `SDL_CreateSoftwareRenderer` 451 + 452 + Params: 453 + surface = `dsdl2.Surface` to be the target of rendering 454 + Throws: `dsdl2.SDLException` if creation failed 455 +/ 456 this(Surface surface) @trusted 457 in { 458 assert(surface !is null); 459 } 460 do { 461 this.sdlRenderer = SDL_CreateSoftwareRenderer(surface.sdlSurface); 462 if (this.sdlRenderer is null) { 463 throw new SDLException; 464 } 465 466 this.userRef = cast(void*) surface; 467 } 468 469 ~this() @trusted { 470 if (this.isOwner) { 471 SDL_DestroyRenderer(this.sdlRenderer); 472 } 473 } 474 475 @trusted invariant { // @suppress(dscanner.trust_too_much) 476 // Instance might be in an invalid state due to holding a non-owned externally-freed object when 477 // destructed in an unpredictable order. 478 if (!this.isOwner && GC.inFinalizer) { 479 return; 480 } 481 482 assert(this.sdlRenderer !is null); 483 } 484 485 /++ 486 + Equality operator overload 487 +/ 488 bool opEquals(const Renderer rhs) const @trusted { 489 return this.sdlRenderer is rhs.sdlRenderer; 490 } 491 492 /++ 493 + Gets the hash of the `dsdl2.Renderer` 494 + 495 + Returns: unique hash for the instance being the pointer of the internal `SDL_Renderer` pointer 496 +/ 497 override hash_t toHash() const @trusted { 498 return cast(hash_t) this.sdlRenderer; 499 } 500 501 /++ 502 + Formats the `dsdl2.Renderer` into its construction representation: `"dsdl2.Renderer(<sdlRenderer>)"` 503 + 504 + Returns: the formatted `string` 505 +/ 506 override string toString() const @trusted { 507 return "dsdl2.Renderer(0x%x)".format(this.sdlRenderer); 508 } 509 510 /++ 511 + Wraps `SDL_GetRendererInfo` which gets the renderer information 512 + 513 + Returns: `dsdl2.RendererInfo` of the renderer 514 + Throws: `dsdl2.SDLException` if failed to get the renderer information 515 +/ 516 RendererInfo info() const @property @trusted { 517 SDL_RendererInfo sdlRendererInfo = void; 518 if (SDL_GetRendererInfo(cast(SDL_Renderer*) this.sdlRenderer, &sdlRendererInfo) != 0) { 519 throw new SDLException; 520 } 521 522 return RendererInfo(sdlRendererInfo); 523 } 524 525 /++ 526 + Wraps `SDL_GetRendererOutputSize` which gets the renderer output's width 527 + 528 + Returns: drawable width of the renderer's output/target 529 + Throws: `dsdl2.SDLException` if failed to get the renderer output width 530 +/ 531 uint width() const @property @trusted { 532 uint w = void; 533 if (SDL_GetRendererOutputSize(cast(SDL_Renderer*) this.sdlRenderer, cast(int*) w, null) != 1) { 534 throw new SDLException; 535 } 536 537 return w; 538 } 539 540 /++ 541 + Wraps `SDL_GetRendererOutputSize` which gets the renderer output's height 542 + 543 + Returns: drawable height of the renderer's output/target 544 + Throws: `dsdl2.SDLException` if failed to get the renderer output height 545 +/ 546 uint height() const @property @trusted { 547 uint h = void; 548 if (SDL_GetRendererOutputSize(cast(SDL_Renderer*) this.sdlRenderer, null, cast(int*) h) != 1) { 549 throw new SDLException; 550 } 551 552 return h; 553 } 554 555 /++ 556 + Wraps `SDL_GetRendererOutputSize` which gets the renderer output's size 557 + 558 + Returns: drawable size of the renderer's output/target 559 + Throws: `dsdl2.SDLException` if failed to get the renderer output size 560 +/ 561 uint[2] size() const @property @trusted { 562 uint[2] xy = void; 563 if (SDL_GetRendererOutputSize(cast(SDL_Renderer*) this.sdlRenderer, cast(int*) xy[0], 564 cast(int*) xy[1]) != 1) { 565 throw new SDLException; 566 } 567 568 return xy; 569 } 570 571 /++ 572 + Wraps `SDL_RenderTargetSupported` which checks if the renderer supports texture targets 573 + 574 + Returns: `true` if the renderer supports, otherwise `false` 575 +/ 576 bool supportsTarget() const @property @trusted { 577 return SDL_RenderTargetSupported(cast(SDL_Renderer*) this.sdlRenderer) == SDL_TRUE; 578 } 579 580 /++ 581 + Wraps `SDL_GetRenderTarget` which gets the renderer's target 582 + 583 + Returns: `null` if the renderer uses the default target (usually the window), otherwise a `dsdl2.Texture` 584 + proxy to the the set texture target 585 +/ 586 inout(Texture) target() inout @property @trusted { 587 SDL_Texture* targetPtr = SDL_GetRenderTarget(cast(SDL_Renderer*) this.sdlRenderer); 588 if (targetPtr is null) { 589 (cast(Renderer) this).targetProxy = null; 590 } 591 else { 592 // If the target texture pointer happens to change, rewire the proxy. 593 if (this.targetProxy is null || this.targetProxy.sdlTexture !is targetPtr) { 594 (cast(Renderer) this).targetProxy = new Texture(targetPtr); 595 } 596 } 597 598 return this.targetProxy; 599 } 600 601 /++ 602 + Wraps `SDL_SetRenderTarget` which sets the renderer's target 603 + 604 + Params: 605 + newTarget = `null` to set the target to be the default target (usually the window), or a valid target 606 + `dsdl2.Texture` as the texture target 607 + Throws: `dsdl2.SDLException` if failed to set the renderer's target 608 +/ 609 void target(Texture newTarget) @property @trusted { 610 if (newTarget is null) { 611 if (SDL_SetRenderTarget(cast(SDL_Renderer*) this.sdlRenderer, null) != 0) { 612 throw new SDLException; 613 } 614 } 615 else { 616 if (SDL_SetRenderTarget(cast(SDL_Renderer*) this.sdlRenderer, newTarget.sdlTexture) != 0) { 617 throw new SDLException; 618 } 619 } 620 } 621 622 /++ 623 + Wraps `SDL_RenderGetClipRect` which gets the clipping `dsdl2.Rect` of the renderer 624 + 625 + Returns: clipping `dsdl2.Rect` of the renderer 626 +/ 627 Rect clipRect() const @property @trusted { 628 Rect rect = void; 629 SDL_RenderGetClipRect(cast(SDL_Renderer*) this.sdlRenderer, &rect.sdlRect); 630 return rect; 631 } 632 633 /++ 634 + Wraps `SDL_RenderSetClipRect` which sets the clipping `dsdl2.Rect` of the renderer 635 + 636 + Params: 637 + newRect = `dsdl2.Rect` to set as the clipping rectangle 638 +/ 639 void clipRect(Rect newRect) @property @trusted { 640 SDL_RenderSetClipRect(this.sdlRenderer, &newRect.sdlRect); 641 } 642 643 /++ 644 + Acts as `SDL_RenderSetClipRect(renderer, NULL)` which removes the clipping `dsdl2.Rect` of the 645 + renderer 646 +/ 647 void clipRect(typeof(null) _) @property @trusted { 648 SDL_RenderSetClipRect(this.sdlRenderer, null); 649 } 650 651 /++ 652 + Wraps `SDL_RenderSetClipRect` which sets or removes the clipping `dsdl2.Rect` of the renderer 653 + 654 + Params: 655 + newRect = `dsdl2.Rect` to set as the clipping rectangle; `null` to remove the clipping rectangle 656 +/ 657 void clipRect(Nullable!Rect newRect) @property @trusted { 658 if (newRect.isNull) { 659 this.clipRect = null; 660 } 661 else { 662 this.clipRect = newRect.get; 663 } 664 } 665 666 /++ 667 + Wraps `SDL_RenderGetLogicalSize` which gets the renderer output's logical width 668 + 669 + Returns: logical width of the renderer's output/target 670 +/ 671 uint logicalWidth() const @property @trusted { 672 uint w = void; 673 SDL_RenderGetLogicalSize(cast(SDL_Renderer*) this.sdlRenderer, cast(int*) w, null); 674 return w; 675 } 676 677 /++ 678 + Wraps `SDL_RenderSetLogicalSize` which sets the renderer output's logical width 679 + 680 + Params: 681 + newWidth = new logical width of the renderer's output 682 + Throws: `dsdl2.SDLException` if failed to set the renderer's logical width 683 +/ 684 void logicalWidth(uint newWidth) @property @trusted { 685 if (SDL_RenderSetLogicalSize(this.sdlRenderer, newWidth, this.logicalHeight) != 0) { 686 throw new SDLException; 687 } 688 } 689 690 /++ 691 + Wraps `SDL_RenderGetLogicalSize` which gets the renderer output's logical height 692 + 693 + Returns: logical height of the renderer's output/target 694 +/ 695 uint logicalHeight() const @property @trusted { 696 uint h = void; 697 SDL_RenderGetLogicalSize(cast(SDL_Renderer*) this.sdlRenderer, null, cast(int*) h); 698 return h; 699 } 700 701 /++ 702 + Wraps `SDL_RenderSetLogicalSize` which sets the renderer output's logical height 703 + 704 + Params: 705 + newHeight = new logical height of the renderer's output 706 + Throws: `dsdl2.SDLException` if failed to set the renderer's logical height 707 +/ 708 void logicalHeight(uint newHeight) @property @trusted { 709 if (SDL_RenderSetLogicalSize(this.sdlRenderer, this.logicalWidth, newHeight) != 0) { 710 throw new SDLException; 711 } 712 } 713 714 /++ 715 + Wraps `SDL_RenderGetLogicalSize` which gets the renderer logical size 716 + 717 + Returns: logical size of the renderer's output/target 718 +/ 719 uint[2] logicalSize() const @property @trusted { 720 uint[2] wh = void; 721 SDL_RenderGetLogicalSize(cast(SDL_Renderer*) this.sdlRenderer, cast(int*) wh[0], cast(int*) wh[1]); 722 return wh; 723 } 724 725 /++ 726 + Wraps `SDL_RenderSetLogicalSize` which sets the renderer output's logical size 727 + 728 + Params: 729 + newSize = new logical size (width and height) of the renderer's output 730 + Throws: `dsdl2.SDLException` if failed to set the renderer's logical size 731 +/ 732 void logicalSize(uint[2] newSize) @property @trusted { 733 if (SDL_RenderSetLogicalSize(this.sdlRenderer, newSize[0].to!int, newSize[1].to!int) != 0) { 734 throw new SDLException; 735 } 736 } 737 738 /++ 739 + Wraps `SDL_RenderGetViewport` which gets the `dsdl2.Rect` viewport of the renderer 740 + 741 + Returns: viewport `dsdl2.Rect` of the renderer 742 +/ 743 Rect viewport() const @property @trusted { 744 Rect rect = void; 745 SDL_RenderGetClipRect(cast(SDL_Renderer*) this.sdlRenderer, &rect.sdlRect); 746 return rect; 747 } 748 749 /++ 750 + Wraps `SDL_RenderSetViewport` which sets the `dsdl2.Rect` viewport of the `dsdl2.Renderer` 751 + 752 + Params: 753 + newViewport = `dsdl2.Rect` to set as the rectangle viewport 754 + Throws: `dsdl2.SDLException` if failed to set the renderer's viewport 755 +/ 756 void viewport(Rect newViewport) @property @trusted { 757 if (SDL_RenderSetViewport(this.sdlRenderer, &newViewport.sdlRect) != 0) { 758 throw new SDLException; 759 } 760 } 761 762 /++ 763 + Acts as `SDL_RenderSetViewport(renderer, NULL)` which removes the `dsdl2.Rect` viewport of the 764 + `dsdl2.Renderer` 765 + Throws: `dsdl2.SDLException` if failed to set the renderer's viewport 766 +/ 767 void viewport(typeof(null) _) @property @trusted { 768 if (SDL_RenderSetViewport(this.sdlRenderer, null) != 0) { 769 throw new SDLException; 770 } 771 } 772 773 /++ 774 + Wraps `SDL_RenderSetViewport` which sets or removes the viewport `dsdl2.Rect` of the `dsdl2.Renderer` 775 + 776 + Params: 777 + newViewport = `dsdl2.Rect` to set as the rectangle viewport; `null` to remove the rectangle viewport 778 + Throws: `dsdl2.SDLException` if failed to set the renderer's viewport 779 +/ 780 void viewport(Nullable!Rect newViewport) @property @trusted { 781 if (newViewport.isNull) { 782 this.clipRect = null; 783 } 784 else { 785 this.clipRect = newViewport.get; 786 } 787 } 788 789 /++ 790 + Wraps `SDL_RenderGetScale` which gets the X drawing scale of the renderer target 791 + 792 + Returns: `float` scale in the X axis 793 +/ 794 float scaleX() const @property @trusted { 795 float x = void; 796 SDL_RenderGetScale(cast(SDL_Renderer*) this.sdlRenderer, &x, null); 797 return x; 798 } 799 800 /++ 801 + Wraps `SDL_RenderSetScale` which sets the X drawing scale of the renderer target 802 + 803 + Params: 804 + newX = new `float` scale of the X axis 805 + Throws: `dsdl2.SDLException` if failed to set the scale 806 +/ 807 void scaleX(float newX) @property @trusted { 808 if (SDL_RenderSetScale(this.sdlRenderer, newX, this.scaleY) != 0) { 809 throw new SDLException; 810 } 811 } 812 813 /++ 814 + Wraps `SDL_RenderGetScale` which gets the Y drawing scale of the renderer target 815 + 816 + Returns: `float` scale in the Y axis 817 +/ 818 float scaleY() const @property @trusted { 819 float y = void; 820 SDL_RenderGetScale(cast(SDL_Renderer*) this.sdlRenderer, null, &y); 821 return y; 822 } 823 824 /++ 825 + Wraps `SDL_RenderSetScale` which sets the Y drawing scale of the renderer target 826 + 827 + Params: 828 + newY = new `float` scale of the Y axis 829 + Throws: `dsdl2.SDLException` if failed to set the scale 830 +/ 831 void scaleY(float newY) @property @trusted { 832 if (SDL_RenderSetScale(this.sdlRenderer, this.scaleX, newY) != 0) { 833 throw new SDLException; 834 } 835 } 836 837 /++ 838 + Wraps `SDL_RenderGetScale` which gets the drawing scale of the renderer target 839 + 840 + Returns: array of 2 `float`s for the X and Y scales 841 +/ 842 float[2] scale() const @property @trusted { 843 float[2] xy = void; 844 SDL_RenderGetScale(cast(SDL_Renderer*) this.sdlRenderer, &xy[0], &xy[1]); 845 return xy; 846 } 847 848 /++ 849 + Wraps `SDL_RenderSetScale` which sets the drawing scale of the renderer target 850 + 851 + Params: 852 + newScale = array of 2 `float`s for the new X and Y scales 853 + Throws: `dsdl2.SDLException` if failed to set the scale 854 +/ 855 void scale(float[2] newScale) @property @trusted { 856 if (SDL_RenderSetScale(this.sdlRenderer, newScale[0], newScale[1]) != 0) { 857 throw new SDLException; 858 } 859 } 860 861 /++ 862 + Wraps `SDL_GetRenderDrawColor` which gets the draw color for the following draw calls 863 + 864 + Returns: `dsdl2.Color` of the renderer's current draw color 865 +/ 866 Color drawColor() const @property @trusted { 867 Color color = void; 868 if (SDL_GetRenderDrawColor(cast(SDL_Renderer*) this.sdlRenderer, &color.r(), &color.g(), &color.b(), 869 &color.a()) != 0) { 870 throw new SDLException; 871 } 872 873 return color; 874 } 875 876 /++ 877 + Wraps `SDL_SetRenderDrawColor` which sets the draw color for the following draw calls 878 + 879 + Params: 880 + newColor = new `dsdl2.Color` as the renderer's current draw color 881 + Throws: `dsdl2.SDLException` if failed to set the draw color 882 +/ 883 void drawColor(Color newColor) @property @trusted { 884 if (SDL_SetRenderDrawColor(this.sdlRenderer, newColor.r, newColor.g, newColor.b, newColor.a) != 0) { 885 throw new SDLException; 886 } 887 } 888 889 /++ 890 + Wraps `SDL_GetRenderDrawBlendMode` which gets the color blending mode of the renderer 891 + 892 + Returns: color `dsdl2.BlendMode` of the renderer 893 + Throws: `dsdl2.SDLException` if failed to get the color blending mode 894 +/ 895 BlendMode blendMode() const @property @trusted { 896 BlendMode mode = void; 897 if (SDL_GetRenderDrawBlendMode(cast(SDL_Renderer*) this.sdlRenderer, &mode.sdlBlendMode) != 0) { 898 throw new SDLException; 899 } 900 901 return mode; 902 } 903 904 /++ 905 + Wraps `SDL_SetRenderDrawBlendMode` which sets the color blending mode of the renderer 906 + 907 + Params: 908 + newMode = new `dsdl2.BlendMode` as the renderer's current color blending mode 909 + Throws: `dsdl2.SDLException` if failed to set the color blending mode 910 +/ 911 void blendMode(BlendMode newMode) @property @trusted { 912 if (SDL_SetRenderDrawBlendMode(this.sdlRenderer, newMode.sdlBlendMode) != 0) { 913 throw new SDLException; 914 } 915 } 916 917 /++ 918 + Wraps `SDL_RenderClear` which clears the target with the renderer's draw color 919 + 920 + Throws: `dsdl2.SDLException` if failed to clear 921 +/ 922 void clear() @trusted { 923 if (SDL_RenderClear(this.sdlRenderer) != 0) { 924 throw new SDLException; 925 } 926 } 927 928 /++ 929 + Wraps `SDL_RenderDrawPoint` which draws a single point at a given position with the renderer's draw color 930 + 931 + Params: 932 + point = `dsdl2.Point` position the point is drawn at 933 + Throws: `dsdl2.SDLException` if point failed to draw 934 +/ 935 void drawPoint(Point point) @trusted { 936 if (SDL_RenderDrawPoint(this.sdlRenderer, point.x, point.y) != 0) { 937 throw new SDLException; 938 } 939 } 940 941 /++ 942 + Wraps `SDL_RenderDrawPoints` which draws multiple points at given positions with the renderer's draw color 943 + 944 + Params: 945 + points = array of `dsdl2.Point` positions the points are drawn at 946 + Throws: `dsdl2.SDLException` if points failed to draw 947 +/ 948 void drawPoints(const Point[] points) @trusted { 949 if (SDL_RenderDrawPoints(this.sdlRenderer, cast(SDL_Point*) points.ptr, points.length.to!int) != 0) { 950 throw new SDLException; 951 } 952 } 953 954 /++ 955 + Wraps `SDL_RenderDrawLine` which draws a line between two points with the renderer's draw color 956 + 957 + Params: 958 + line = array of two `dsdl2.Point`s indicating the line's start and end 959 + Throws: `dsdl2.SDLException` if line failed to draw 960 +/ 961 void drawLine(Point[2] line) @trusted { 962 if (SDL_RenderDrawLine(this.sdlRenderer, line[0].x, line[0].y, line[1].x, line[1].y) != 0) { 963 throw new SDLException; 964 } 965 } 966 967 /++ 968 + Wraps `SDL_RenderDrawLines` which draws multiple lines following given points with the renderer's draw color 969 + 970 + Params: 971 + points = array of `dsdl2.Point` edges the lines are drawn from and to 972 + Throws: `dsdl2.SDLException` if lines failed to draw 973 +/ 974 void drawLines(const Point[] points) @trusted { 975 if (SDL_RenderDrawLines(this.sdlRenderer, cast(SDL_Point*) points.ptr, points.length.to!int) != 0) { 976 throw new SDLException; 977 } 978 } 979 980 /++ 981 + Wraps `SDL_RenderDrawRect` which draws a rectangle's edges with the renderer's draw color 982 + 983 + Params: 984 + rect = `dsdl2.Rect` of the rectangle 985 + Throws: `dsdl2.SDLException` if rectangle failed to draw 986 +/ 987 void drawRect(Rect rect) @trusted { 988 if (SDL_RenderDrawRect(this.sdlRenderer, &rect.sdlRect) != 0) { 989 throw new SDLException; 990 } 991 } 992 993 /++ 994 + Wraps `SDL_RenderDrawRects` which draws multiple rectangles' edges with the renderer's draw color 995 + 996 + Params: 997 + rects = array of `dsdl2.Rect` of the rectangles 998 + Throws: `dsdl2.SDLException` if rectangles failed to draw 999 +/ 1000 void drawRects(const Rect[] rects) @trusted { 1001 if (SDL_RenderDrawRects(this.sdlRenderer, cast(SDL_Rect*) rects.ptr, rects.length.to!int) != 0) { 1002 throw new SDLException; 1003 } 1004 } 1005 1006 /++ 1007 + Wraps `SDL_RenderFillRect` which fills a rectangle with the renderer's draw color 1008 + 1009 + Params: 1010 + rect = `dsdl2.Rect` of the rectangle 1011 + Throws: `dsdl2.SDLException` if rectangle failed to fill 1012 +/ 1013 void fillRect(Rect rect) @trusted { 1014 if (SDL_RenderFillRect(this.sdlRenderer, &rect.sdlRect) != 0) { 1015 throw new SDLException; 1016 } 1017 } 1018 1019 /++ 1020 + Wraps `SDL_RenderFillRects` which fills multiple rectangles with the renderer's draw color 1021 + 1022 + Params: 1023 + rects = array of `dsdl2.Rect` of the rectangles 1024 + Throws: `dsdl2.SDLException` if rectangles failed to fill 1025 +/ 1026 void fillRects(const Rect[] rects) @trusted { 1027 if (SDL_RenderFillRects(this.sdlRenderer, cast(SDL_Rect*) rects.ptr, rects.length.to!int) != 0) { 1028 throw new SDLException; 1029 } 1030 } 1031 1032 /++ 1033 + Acts as `SDL_RenderCopy(renderer, texture, NULL, destRect)` which copies the entire texture to `destRect` at 1034 + the renderer's target 1035 + 1036 + Params: 1037 + texture = `dsdl2.Texture` to be copied/drawn 1038 + destRect = destination `dsdl2.Rect` in the target for the texture to be drawn to 1039 + Throws: `dsdl2.SDLException` if texture failed to draw 1040 +/ 1041 void copy(const Texture texture, Rect destRect) @trusted 1042 in { 1043 assert(texture !is null); 1044 } 1045 do { 1046 if (SDL_RenderCopy(this.sdlRenderer, cast(SDL_Texture*) texture.sdlTexture, null, &destRect.sdlRect) != 0) { 1047 throw new SDLException; 1048 } 1049 } 1050 1051 /++ 1052 + Wraps `SDL_RenderCopy` which copies a part of the texture at `srcRect` to `destRect` at the renderer's target 1053 + 1054 + Params: 1055 + texture = `dsdl2.Texture` to be copied/drawn 1056 + destRect = destination `dsdl2.Rect` in the target for the texture to be drawn to 1057 + srcRect = source `dsdl2.Rect` which clips the given texture 1058 + Throws: `dsdl2.SDLException` if texture failed to draw 1059 +/ 1060 void copy(const Texture texture, Rect destRect, Rect srcRect) @trusted 1061 in { 1062 assert(texture !is null); 1063 } 1064 do { 1065 if (SDL_RenderCopy(this.sdlRenderer, cast(SDL_Texture*) texture.sdlTexture, &srcRect.sdlRect, 1066 &destRect.sdlRect) != 0) { 1067 throw new SDLException; 1068 } 1069 } 1070 1071 /++ 1072 + Acts as `SDL_RenderCopyEx(renderer, texture, NULL, destRect, angle, NULL, flip)` which copies the 1073 + entire texture to `destRect` at the renderer's target with certain `angle` and flipping 1074 + 1075 + Params: 1076 + texture = `dsdl2.Texture` to be copied/drawn 1077 + destRect = destination `dsdl2.Rect` in the target for the texture to be drawn to 1078 + angle = angle in degrees to rotate the texture counterclockwise 1079 + flippedHorizontally = `true` to flip the texture horizontally, otherwise `false` 1080 + flippedVertically = `true` to flip the texture vertically, otherwise `false` 1081 + Throws: `dsdl2.SDLException` if texture failed to draw 1082 +/ 1083 void copyEx(const Texture texture, Rect destRect, double angle, bool flippedHorizontally = false, 1084 bool flippedVertically = false) @trusted 1085 in { 1086 assert(texture !is null); 1087 } 1088 do { 1089 if (SDL_RenderCopyEx(this.sdlRenderer, cast(SDL_Texture*) texture.sdlTexture, null, &destRect.sdlRect, angle, 1090 null, (flippedHorizontally ? SDL_FLIP_HORIZONTAL : 0) | 1091 (flippedVertically ? SDL_FLIP_VERTICAL : 0)) != 0) { 1092 throw new SDLException; 1093 } 1094 } 1095 1096 /++ 1097 + Acts as `SDL_RenderCopyEx(renderer, texture, srcRect, destRect, angle, NULL, flip)` which copies the 1098 + entire texture to `destRect` at the renderer's target with certain `angle` and flipping 1099 + 1100 + Params: 1101 + texture = `dsdl2.Texture` to be copied/drawn 1102 + destRect = destination `dsdl2.Rect` in the target for the texture to be drawn to 1103 + angle = angle in degrees to rotate the texture counterclockwise 1104 + srcRect = source `dsdl2.Rect` which clips the given texture 1105 + flippedHorizontally = `true` to flip the texture horizontally, otherwise `false` 1106 + flippedVertically = `true` to flip the texture vertically, otherwise `false` 1107 + Throws: `dsdl2.SDLException` if texture failed to draw 1108 +/ 1109 void copyEx(const Texture texture, Rect destRect, double angle, Rect srcRect, bool flippedHorizontally = false, 1110 bool flippedVertically = false) @trusted 1111 in { 1112 assert(texture !is null); 1113 } 1114 do { 1115 if (SDL_RenderCopyEx(this.sdlRenderer, cast(SDL_Texture*) texture.sdlTexture, &srcRect.sdlRect, 1116 &destRect.sdlRect, angle, null, (flippedHorizontally ? SDL_FLIP_HORIZONTAL : 0) | 1117 (flippedVertically ? SDL_FLIP_VERTICAL : 0)) != 0) { 1118 throw new SDLException; 1119 } 1120 } 1121 1122 /++ 1123 + Acts as `SDL_RenderCopyEx(renderer, texture, NULL, destRect, angle, center, flip)` which copies the 1124 + entire texture to `destRect` at the renderer's target with certain `angle` and flipping 1125 + 1126 + Params: 1127 + texture = `dsdl2.Texture` to be copied/drawn 1128 + destRect = destination `dsdl2.Rect` in the target for the texture to be drawn to 1129 + angle = angle in degrees to rotate the texture counterclockwise 1130 + center = pivot `dsdl2.Point` of the texture for rotation 1131 + flippedHorizontally = `true` to flip the texture horizontally, otherwise `false` 1132 + flippedVertically = `true` to flip the texture vertically, otherwise `false` 1133 + Throws: `dsdl2.SDLException` if texture failed to draw 1134 +/ 1135 void copyEx(const Texture texture, Rect destRect, double angle, Point center, bool flippedHorizontally = false, 1136 bool flippedVertically = false) @trusted 1137 in { 1138 assert(texture !is null); 1139 } 1140 do { 1141 if (SDL_RenderCopyEx(this.sdlRenderer, cast(SDL_Texture*) texture.sdlTexture, null, &destRect.sdlRect, angle, 1142 ¢er.sdlPoint, (flippedHorizontally ? SDL_FLIP_HORIZONTAL : 0) | 1143 (flippedVertically ? SDL_FLIP_VERTICAL : 0)) != 0) { 1144 throw new SDLException; 1145 } 1146 } 1147 1148 /++ 1149 + Wraps `SDL_RenderCopyEx` which copies the entire texture to `destRect` at the renderer's target with certain 1150 + `angle` and flipping 1151 + 1152 + Params: 1153 + texture = `dsdl2.Texture` to be copied/drawn 1154 + destRect = destination `dsdl2.Rect` in the target for the texture to be drawn to 1155 + angle = angle in degrees to rotate the texture counterclockwise 1156 + srcRect = source `dsdl2.Rect` which clips the given texture 1157 + center = pivot `dsdl2.Point` of the texture for rotation 1158 + flippedHorizontally = `true` to flip the texture horizontally, otherwise `false` 1159 + flippedVertically = `true` to flip the texture vertically, otherwise `false` 1160 + Throws: `dsdl2.SDLException` if texture failed to draw 1161 +/ 1162 void copyEx(const Texture texture, Rect destRect, double angle, Rect srcRect, Point center, 1163 bool flippedHorizontally = false, bool flippedVertically = false) @trusted 1164 in { 1165 assert(texture !is null); 1166 } 1167 do { 1168 if (SDL_RenderCopyEx(this.sdlRenderer, cast(SDL_Texture*) texture.sdlTexture, &srcRect.sdlRect, 1169 &destRect.sdlRect, angle, ¢er.sdlPoint, (flippedHorizontally ? SDL_FLIP_HORIZONTAL 1170 : 0) | (flippedVertically ? SDL_FLIP_VERTICAL : 0)) != 0) { 1171 throw new SDLException; 1172 } 1173 } 1174 1175 /++ 1176 + Wraps `SDL_RenderReadPixels` which makes a `dsdl2.Surface` from the renderer's entire target 1177 + 1178 + Params: 1179 + format = requested `dsdl2.PixelFormat` of the returned `dsdl2.Surface` 1180 + Returns: `dsdl2.Surface` copy of the renderer's entire target 1181 + Throws: `dsdl2.SDLException` if pixels failed to be read 1182 +/ 1183 Surface readPixels(const PixelFormat format = PixelFormat.rgba8888) const @trusted 1184 in { 1185 assert(!format.indexed); 1186 } 1187 do { 1188 Surface surface = new Surface(this.size, format); 1189 if (SDL_RenderReadPixels(cast(SDL_Renderer*) this.sdlRenderer, null, format.sdlPixelFormatEnum, 1190 surface.buffer.ptr, surface.pitch.to!int) != 0) { 1191 throw new SDLException; 1192 } 1193 1194 return surface; 1195 } 1196 1197 /++ 1198 + Wraps `SDL_RenderReadPixels` which makes a `dsdl2.Surface` from a specified `dsdl2.Rect` boundary at the 1199 + renderer's target 1200 + 1201 + Params: 1202 + rect = `dsdl2.Rect` boundary to be read and copied 1203 + format = requested `dsdl2.PixelFormat` of the returned `dsdl2.Surface` 1204 + Returns: `dsdl2.Surface` copy of the specified rectangle boundary in the renderer's target 1205 + Throws: `dsdl2.SDLException` if pixels failed to be read 1206 +/ 1207 Surface readPixels(Rect rect, const PixelFormat format = PixelFormat.rgba8888) const @trusted 1208 in { 1209 assert(!format.indexed); 1210 } 1211 do { 1212 Surface surface = new Surface([rect.x, rect.x], format); 1213 if (SDL_RenderReadPixels(cast(SDL_Renderer*) this.sdlRenderer, &rect.sdlRect, format.sdlPixelFormatEnum, 1214 surface.buffer.ptr, surface.pitch.to!int) != 0) { 1215 throw new SDLException; 1216 } 1217 1218 return surface; 1219 } 1220 1221 /++ 1222 + Wraps `SDL_RenderPresent` which presents any appending changes to the renderer's target 1223 +/ 1224 void present() @trusted { 1225 SDL_RenderPresent(this.sdlRenderer); 1226 } 1227 1228 static if (sdlSupport >= SDLSupport.v2_0_4) { 1229 /++ 1230 + Wraps `SDL_RenderIsClipEnabled` (from SDL 2.0.4) which checks whether a clipping rectangle is set in the 1231 + renderer 1232 + 1233 + Returns: `true` if a clipping rectangle is set, otherwise `false` 1234 +/ 1235 bool hasClipRect() const @property @trusted 1236 in { 1237 assert(getVersion() >= Version(2, 0, 4)); 1238 } 1239 do { 1240 return SDL_RenderIsClipEnabled(cast(SDL_Renderer*) this.sdlRenderer) == SDL_TRUE; 1241 } 1242 } 1243 1244 static if (sdlSupport >= SDLSupport.v2_0_5) { 1245 /++ 1246 + Wraps `SDL_RenderGetIntegerScale` (from SDL 2.0.5) which gets whether integer scales are forced 1247 + 1248 + Returns: `true` if integer scaling is enabled, otherwise `false` 1249 +/ 1250 bool integerScaling() const @property @trusted 1251 in { 1252 assert(getVersion() >= Version(2, 0, 5)); 1253 } 1254 do { 1255 return SDL_RenderGetIntegerScale(cast(SDL_Renderer*) this.sdlRenderer) == SDL_TRUE; 1256 } 1257 1258 /++ 1259 + Wraps `SDL_RenderSetIntegerScale` (from SDL 2.0.5) which sets whether integer scales should be forced 1260 + 1261 + Params: 1262 + newScale = `true` to enable integer scaling, otherwise `false` 1263 + Throws: `dsdl2.SDLException` if failed to set integer scaling 1264 +/ 1265 void integerScaling(bool newScale) @property @trusted 1266 in { 1267 assert(getVersion() >= Version(2, 0, 5)); 1268 } 1269 do { 1270 if (SDL_RenderSetIntegerScale(this.sdlRenderer, newScale) != 0) { 1271 throw new SDLException; 1272 } 1273 } 1274 } 1275 1276 static if (sdlSupport >= SDLSupport.v2_0_8) { 1277 /++ 1278 + Wraps `SDL_RenderGetMetalLayer` (from SDL 2.0.8) which gets the `CAMetalLayer` pointer associated with the 1279 + given Metal renderer 1280 + 1281 + Returns: pointer to the `CAMetalLayer`, otherwise `null` if not using a Metal renderer 1282 +/ 1283 void* getMetalLayer() @system 1284 in { 1285 assert(getVersion() >= Version(2, 0, 8)); 1286 } 1287 do { 1288 return SDL_RenderGetMetalLayer(this.sdlRenderer); 1289 } 1290 1291 /++ 1292 + Wraps `SDL_RenderGetMetalCommandEncoder` (from SDL 2.0.8) which gets the Metal command encoder for the 1293 + current frame 1294 + 1295 + Returns: ID of the `MTLRenderCommandEncoder`, otherwise `null` if not using a Metal renderer 1296 +/ 1297 void* getMetalCommandEncoder() @system 1298 in { 1299 assert(getVersion() >= Version(2, 0, 8)); 1300 } 1301 do { 1302 return SDL_RenderGetMetalCommandEncoder(this.sdlRenderer); 1303 } 1304 } 1305 1306 static if (sdlSupport >= SDLSupport.v2_0_10) { 1307 /++ 1308 + Wraps `SDL_RenderDrawPointF` (from SDL 2.0.10) which draws a single point at a given position with the 1309 + renderer's draw color 1310 + 1311 + Params: 1312 + point = `dsdl2.FPoint` position the point is drawn at 1313 + Throws: `dsdl2.SDLException` if point failed to draw 1314 +/ 1315 void drawPoint(FPoint point) @trusted 1316 in { 1317 assert(getVersion() >= Version(2, 0, 10)); 1318 } 1319 do { 1320 if (SDL_RenderDrawPointF(this.sdlRenderer, point.x, point.y) != 0) { 1321 throw new SDLException; 1322 } 1323 } 1324 1325 /++ 1326 + Wraps `SDL_RenderDrawPointsF` (from SDL 2.0.10) which draws multiple points at given positions with the 1327 + renderer's draw color 1328 + 1329 + Params: 1330 + points = array of `dsdl2.FPoint` positions the points are drawn at 1331 + Throws: `dsdl2.SDLException` if points failed to draw 1332 +/ 1333 void drawPoints(const FPoint[] points) @trusted 1334 in { 1335 assert(getVersion() >= Version(2, 0, 10)); 1336 } 1337 do { 1338 if (SDL_RenderDrawPointsF(this.sdlRenderer, cast(SDL_FPoint*) points.ptr, points.length.to!int) != 0) { 1339 throw new SDLException; 1340 } 1341 } 1342 1343 /++ 1344 + Wraps `SDL_RenderDrawLineF` (from SDL 2.0.10) which draws a line between two points with the renderer's draw 1345 + color 1346 + 1347 + Params: 1348 + line = array of two `dsdl2.FPoint`s indicating the line's start and end 1349 + Throws: `dsdl2.SDLException` if line failed to draw 1350 +/ 1351 void drawLine(FPoint[2] line) @trusted 1352 in { 1353 assert(getVersion() >= Version(2, 0, 10)); 1354 } 1355 do { 1356 if (SDL_RenderDrawLineF(this.sdlRenderer, line[0].x, line[0].y, line[1].x, line[1].y) != 0) { 1357 throw new SDLException; 1358 } 1359 } 1360 1361 /++ 1362 + Wraps `SDL_RenderDrawLinesF` (from SDL 2.0.10) which draws multiple lines following given points with the 1363 + renderer's draw color 1364 + 1365 + Params: 1366 + points = array of `dsdl2.FPoint` edges the lines are drawn from and to 1367 + Throws: `dsdl2.SDLException` if lines failed to draw 1368 +/ 1369 void drawLines(const FPoint[] points) @trusted 1370 in { 1371 assert(getVersion() >= Version(2, 0, 10)); 1372 } 1373 do { 1374 if (SDL_RenderDrawLinesF(this.sdlRenderer, cast(SDL_FPoint*) points.ptr, points.length.to!int) != 0) { 1375 throw new SDLException; 1376 } 1377 } 1378 1379 /++ 1380 + Wraps `SDL_RenderDrawRectF` (from SDL 2.0.10) which draws a rectangle's edges with the renderer's draw color 1381 + 1382 + Params: 1383 + rect = `dsdl2.FRect` of the rectangle 1384 + Throws: `dsdl2.SDLException` if rectangle failed to draw 1385 +/ 1386 void drawRect(FRect rect) @trusted 1387 in { 1388 assert(getVersion() >= Version(2, 0, 10)); 1389 } 1390 do { 1391 if (SDL_RenderDrawRectF(this.sdlRenderer, &rect.sdlFRect) != 0) { 1392 throw new SDLException; 1393 } 1394 } 1395 1396 /++ 1397 + Wraps `SDL_RenderDrawRectsF` (from SDL 2.0.10) which draws multiple rectangles' edges with the renderer's 1398 + draw color 1399 + 1400 + Params: 1401 + rects = array of `dsdl2.FRect` of the rectangles 1402 + Throws: `dsdl2.SDLException` if rectangles failed to draw 1403 +/ 1404 void drawRects(const FRect[] rects) @trusted 1405 in { 1406 assert(getVersion() >= Version(2, 0, 10)); 1407 } 1408 do { 1409 if (SDL_RenderDrawRectsF(this.sdlRenderer, cast(SDL_FRect*) rects.ptr, rects.length.to!int) != 0) { 1410 throw new SDLException; 1411 } 1412 } 1413 1414 /++ 1415 + Wraps `SDL_RenderFillRectF` (from SDL 2.0.10) which fills a rectangle with the renderer's draw color 1416 + 1417 + Params: 1418 + rect = `dsdl2.FRect` of the rectangle 1419 + Throws: `dsdl2.SDLException` if rectangle failed to fill 1420 +/ 1421 void fillRect(FRect rect) @trusted 1422 in { 1423 assert(getVersion() >= Version(2, 0, 10)); 1424 } 1425 do { 1426 if (SDL_RenderFillRectF(this.sdlRenderer, &rect.sdlFRect) != 0) { 1427 throw new SDLException; 1428 } 1429 } 1430 1431 /++ 1432 + Wraps `SDL_RenderFillRectsF` (from SDL 2.0.10) which fills multiple rectangles with the renderer's draw color 1433 + 1434 + Params: 1435 + rects = array of `dsdl2.FRect` of the rectangles 1436 + Throws: `dsdl2.SDLException` if rectangles failed to fill 1437 +/ 1438 void fillRects(const FRect[] rects) @trusted 1439 in { 1440 assert(getVersion() >= Version(2, 0, 10)); 1441 } 1442 do { 1443 if (SDL_RenderFillRectsF(this.sdlRenderer, cast(SDL_FRect*) rects.ptr, rects.length.to!int) != 0) { 1444 throw new SDLException; 1445 } 1446 } 1447 1448 /++ 1449 + Acts as `SDL_RenderCopyF(renderer, texture, NULL, destRect)` (from SDL 2.0.10) which copies the entire 1450 + texture to `destRect` at the renderer's target 1451 + 1452 + Params: 1453 + texture = `dsdl2.Texture` to be copied/drawn 1454 + destRect = destination `dsdl2.FRect` in the target for the texture to be drawn to 1455 + Throws: `dsdl2.SDLException` if texture failed to draw 1456 +/ 1457 void copy(const Texture texture, FRect destRect) @trusted 1458 in { 1459 assert(getVersion() >= Version(2, 0, 10)); 1460 assert(texture !is null); 1461 } 1462 do { 1463 if (SDL_RenderCopyF(this.sdlRenderer, cast(SDL_Texture*) texture.sdlTexture, null, 1464 &destRect.sdlFRect) != 0) { 1465 throw new SDLException; 1466 } 1467 } 1468 1469 /++ 1470 + Wraps `SDL_RenderCopyF` (from SDL 2.0.10) which copies a part of the texture at `srcRect` to `destRect` at 1471 + the renderer's target 1472 + 1473 + Params: 1474 + texture = `dsdl2.Texture` to be copied/drawn 1475 + destRect = destination `dsdl2.FRect` in the target for the texture to be drawn to 1476 + srcRect = source `dsdl2.Rect` which clips the given texture 1477 + Throws: `dsdl2.SDLException` if texture failed to draw 1478 +/ 1479 void copy(const Texture texture, FRect destRect, Rect srcRect) @trusted 1480 in { 1481 assert(getVersion() >= Version(2, 0, 10)); 1482 assert(texture !is null); 1483 } 1484 do { 1485 if (SDL_RenderCopyF(this.sdlRenderer, cast(SDL_Texture*) texture.sdlTexture, &srcRect.sdlRect, 1486 &destRect.sdlFRect) != 0) { 1487 throw new SDLException; 1488 } 1489 } 1490 1491 /++ 1492 + Acts as `SDL_RenderCopyExF(renderer, texture, NULL, destRect, angle, NULL, flip)` (from SDL 2.0.10) which 1493 + copies the entire texture to `destRect` at the renderer's target with certain `angle` and flipping 1494 + 1495 + Params: 1496 + texture = `dsdl2.Texture` to be copied/drawn 1497 + destRect = destination `dsdl2.FRect` in the target for the texture to be drawn to 1498 + angle = angle in degrees to rotate the texture counterclockwise 1499 + flippedHorizontally = `true` to flip the texture horizontally, otherwise `false` 1500 + flippedVertically = `true` to flip the texture vertically, otherwise `false` 1501 + Throws: `dsdl2.SDLException` if texture failed to draw 1502 +/ 1503 void copyEx(const Texture texture, FRect destRect, double angle, bool flippedHorizontally = false, 1504 bool flippedVertically = false) @trusted 1505 in { 1506 assert(getVersion() >= Version(2, 0, 10)); 1507 assert(texture !is null); 1508 } 1509 do { 1510 if (SDL_RenderCopyExF(this.sdlRenderer, cast(SDL_Texture*) texture.sdlTexture, null, &destRect.sdlFRect, 1511 angle, null, (flippedHorizontally ? SDL_FLIP_HORIZONTAL : 0) | 1512 (flippedVertically ? SDL_FLIP_VERTICAL : 0)) != 0) { 1513 throw new SDLException; 1514 } 1515 } 1516 1517 /++ 1518 + Acts as `SDL_RenderCopyExF(renderer, texture, srcRect, destRect, angle, NULL, flip)` (from SDL 2.0.10) which 1519 + copies the entire texture to `destRect` at the renderer's target with certain `angle` and flipping 1520 + 1521 + Params: 1522 + texture = `dsdl2.Texture` to be copied/drawn 1523 + destRect = destination `dsdl2.FRect` in the target for the texture to be drawn to 1524 + angle = angle in degrees to rotate the texture counterclockwise 1525 + srcRect = source `dsdl2.Rect` which clips the given texture 1526 + flippedHorizontally = `true` to flip the texture horizontally, otherwise `false` 1527 + flippedVertically = `true` to flip the texture vertically, otherwise `false` 1528 + Throws: `dsdl2.SDLException` if texture failed to draw 1529 +/ 1530 void copyEx(const Texture texture, FRect destRect, double angle, Rect srcRect, bool flippedHorizontally = false, 1531 bool flippedVertically = false) @trusted 1532 in { 1533 assert(getVersion() >= Version(2, 0, 10)); 1534 assert(texture !is null); 1535 } 1536 do { 1537 if (SDL_RenderCopyExF(this.sdlRenderer, cast(SDL_Texture*) texture.sdlTexture, &srcRect.sdlRect, 1538 &destRect.sdlFRect, angle, null, (flippedHorizontally ? SDL_FLIP_HORIZONTAL : 0) | 1539 (flippedVertically ? SDL_FLIP_VERTICAL : 0)) != 0) { 1540 throw new SDLException; 1541 } 1542 } 1543 1544 /++ 1545 + Acts as `SDL_RenderCopyExF(renderer, texture, NULL, destRect, angle, center, flip)` (from SDL 2.0.10) which 1546 + copies the entire texture to `destRect` at the renderer's target with certain `angle` and flipping 1547 + 1548 + Params: 1549 + texture = `dsdl2.Texture` to be copied/drawn 1550 + destRect = destination `dsdl2.FRect` in the target for the texture to be drawn to 1551 + angle = angle in degrees to rotate the texture counterclockwise 1552 + center = pivot `dsdl2.FPoint` of the texture for rotation 1553 + flippedHorizontally = `true` to flip the texture horizontally, otherwise `false` 1554 + flippedVertically = `true` to flip the texture vertically, otherwise `false` 1555 + Throws: `dsdl2.SDLException` if texture failed to draw 1556 +/ 1557 void copyEx(const Texture texture, FRect destRect, double angle, FPoint center, 1558 bool flippedHorizontally = false, bool flippedVertically = false) @trusted 1559 in { 1560 assert(getVersion() >= Version(2, 0, 10)); 1561 assert(texture !is null); 1562 } 1563 do { 1564 if (SDL_RenderCopyExF(this.sdlRenderer, cast(SDL_Texture*) texture.sdlTexture, null, &destRect.sdlFRect, 1565 angle, ¢er.sdlFPoint, (flippedHorizontally ? SDL_FLIP_HORIZONTAL : 0) | 1566 (flippedVertically ? SDL_FLIP_VERTICAL : 0)) != 0) { 1567 throw new SDLException; 1568 } 1569 } 1570 1571 /++ 1572 + Wraps `SDL_RenderCopyExF` (from SDL 2.0.10) which copies the entire texture to `destRect` at the renderer's 1573 + target with certain `angle` and flipping 1574 + 1575 + Params: 1576 + texture = `dsdl2.Texture` to be copied/drawn 1577 + destRect = destination `dsdl2.FRect` in the target for the texture to be drawn to 1578 + angle = angle in degrees to rotate the texture counterclockwise 1579 + srcRect = source `dsdl2.Rect` which clips the given texture 1580 + center = pivot `dsdl2.FPoint` of the texture for rotation 1581 + flippedHorizontally = `true` to flip the texture horizontally, otherwise `false` 1582 + flippedVertically = `true` to flip the texture vertically, otherwise `false` 1583 + Throws: `dsdl2.SDLException` if texture failed to draw 1584 +/ 1585 void copyEx(const Texture texture, FRect destRect, double angle, Rect srcRect, FPoint center, 1586 bool flippedHorizontally = false, bool flippedVertically = false) @trusted 1587 in { 1588 assert(getVersion() >= Version(2, 0, 10)); 1589 assert(texture !is null); 1590 } 1591 do { 1592 if (SDL_RenderCopyExF(this.sdlRenderer, cast(SDL_Texture*) texture.sdlTexture, &srcRect.sdlRect, 1593 &destRect.sdlFRect, angle, ¢er.sdlFPoint, (flippedHorizontally ? SDL_FLIP_HORIZONTAL 1594 : 0) | (flippedVertically ? SDL_FLIP_VERTICAL : 0)) != 0) { 1595 throw new SDLException; 1596 } 1597 } 1598 1599 /++ 1600 + Wraps `SDL_RenderFlush` (from SDL 2.0.10) which executes and flushes all pending rendering operations 1601 + 1602 + Throws: `dsdl2.SDLException` if cannot flush 1603 +/ 1604 void flush() @trusted 1605 in { 1606 assert(getVersion() >= Version(2, 0, 10)); 1607 } 1608 do { 1609 if (SDL_RenderFlush(this.sdlRenderer) != 0) { 1610 throw new SDLException; 1611 } 1612 } 1613 } 1614 1615 static if (sdlSupport >= SDLSupport.v2_0_18) { 1616 /++ 1617 + Wraps `SDL_RenderWindowToLogical` (from SDL 2.0.18) which maps window coordinates to logical coordinates 1618 + 1619 + Params: 1620 + xy = `int[2]` window coordinate of X and Y 1621 + Returns: mapped `float[2]` logical coordinate of X and Y 1622 +/ 1623 float[2] windowToLogical(int[2] xy) const @trusted 1624 in { 1625 assert(getVersion() >= Version(2, 0, 18)); 1626 } 1627 do { 1628 float[2] fxy = void; 1629 SDL_RenderWindowToLogical(cast(SDL_Renderer*) this.sdlRenderer, xy[0], xy[1], &fxy[0], &fxy[1]); 1630 return fxy; 1631 } 1632 1633 /++ 1634 + Wraps `SDL_RenderLogicalToWindow` (from SDL 2.0.18) which maps logical coordinates to window coordinates 1635 + 1636 + Params: 1637 + fxy = `float[2]` logical coordinate of X and Y 1638 + Returns: mapped `int[2]` window coordinate of X and Y 1639 +/ 1640 int[2] logicalToWindow(float[2] fxy) const @trusted 1641 in { 1642 assert(getVersion() >= Version(2, 0, 18)); 1643 } 1644 do { 1645 int[2] xy = void; 1646 SDL_RenderLogicalToWindow(cast(SDL_Renderer*) this.sdlRenderer, fxy[0], fxy[1], &xy[0], &xy[1]); 1647 return xy; 1648 } 1649 1650 /++ 1651 + Wraps `SDL_RenderGeometry` (from SDL 2.0.18) which renders triangles to the renderer's target 1652 + 1653 + Params: 1654 + vertices = array of `dsdl2.Vertex`es of the triangles 1655 + texture = `dsdl2.Texture` for the drawn triangles; `null` for none 1656 + indices = array of `uint` indices for the vertices to be drawn (must be in multiples of three); `null` 1657 + for order defined by `vertices` directly 1658 + Throws: `dsdl2.SDLException` if failed to render 1659 +/ 1660 void renderGeometry(const Vertex[] vertices, Texture texture = null, const uint[] indices = null) @trusted { 1661 SDL_Texture* sdlTexture = texture is null ? null : texture.sdlTexture; 1662 if (SDL_RenderGeometry(this.sdlRenderer, sdlTexture, cast(SDL_Vertex*) vertices.ptr, 1663 vertices.length.to!int, cast(int*) indices.ptr, indices.length.to!int) != 0) { 1664 throw new SDLException; 1665 } 1666 } 1667 1668 /++ 1669 + Wraps `SDL_RenderSetVSync` which sets whether vertical synchronization should be enabled 1670 + 1671 + Params: 1672 + vSync = `true` to enable v-sync, otherwise `false` 1673 + Throws: `dsdl2.SDLException` if failed to set v-sync 1674 +/ 1675 void setVSync(bool vSync) @trusted { 1676 if (SDL_RenderSetVSync(this.sdlRenderer, vSync) != 0) { 1677 throw new SDLException; 1678 } 1679 } 1680 } 1681 1682 static if (sdlSupport >= SDLSupport.v2_0_22) { 1683 /++ 1684 + Wraps `SDL_RenderGetWindow` (from SDL 2.0.22) which gets a `dsdl2.Window` proxy to the window associated 1685 + with the renderer 1686 + 1687 + Returns: `dsdl2.Window` proxy to the window 1688 + Throws: `dsdl2.SDLException` if failed to get window 1689 +/ 1690 inout(Window) window() inout @property @trusted 1691 in { 1692 assert(getVersion() >= Version(2, 0, 22)); 1693 } 1694 do { 1695 SDL_Window* sdlWindow = SDL_RenderGetWindow(cast(SDL_Renderer*) this.sdlRenderer); 1696 if (sdlWindow is null) { 1697 throw new SDLException; 1698 } 1699 1700 return cast(inout Window) new Window(sdlWindow, false, cast(void*) this); 1701 } 1702 } 1703 }