1 /* 2 * DSFML - The Simple and Fast Multimedia Library for D 3 * 4 * Copyright (c) 2013 - 2018 Jeremy DeHaan (dehaan.jeremiah@gmail.com) 5 * 6 * This software is provided 'as-is', without any express or implied warranty. 7 * In no event will the authors be held liable for any damages arising from the 8 * use of this software. 9 * 10 * Permission is granted to anyone to use this software for any purpose, 11 * including commercial applications, and to alter it and redistribute it 12 * freely, subject to the following restrictions: 13 * 14 * 1. The origin of this software must not be misrepresented; you must not claim 15 * that you wrote the original software. If you use this software in a product, 16 * an acknowledgment in the product documentation would be appreciated but is 17 * not required. 18 * 19 * 2. Altered source versions must be plainly marked as such, and must not be 20 * misrepresented as being the original software. 21 * 22 * 3. This notice may not be removed or altered from any source distribution 23 * 24 * 25 * DSFML is based on SFML (Copyright Laurent Gomila) 26 */ 27 28 /** 29 * $(U RenderWindow) is the main class of the Graphics package. It defines an OS 30 * window that can be painted using the other classes of the graphics module. 31 * 32 * $(U RenderWindow) is derived from $(WINDOW_LINK), thus it inherits all its 33 * features : events, window management, OpenGL rendering, etc. See the 34 * documentation of $(WINDOW_LINK) for a more complete description of all these 35 * features, as well as code examples. 36 * 37 * On top of that, $(U RenderWindow) adds more features related to 2D drawing 38 * with the graphics module (see its base class $(RENDERTARGET_LINK) for more 39 * details). 40 * 41 * Here is a typical rendering and event loop with a $(U RenderWindow): 42 * --- 43 * // Declare and create a new render-window 44 * auto window = new RenderWindow(VideoMode(800, 600), "DSFML window"); 45 * 46 * // Limit the framerate to 60 frames per second (this step is optional) 47 * window.setFramerateLimit(60); 48 * 49 * // The main loop - ends as soon as the window is closed 50 * while (window.isOpen()) 51 * { 52 * // Event processing 53 * Event event; 54 * while (window.pollEvent(event)) 55 * { 56 * // Request for closing the window 57 * if (event.type == Event.Type.Closed) 58 * window.close(); 59 * } 60 * 61 * // Clear the whole window before rendering a new frame 62 * window.clear(); 63 * 64 * // Draw some graphical entities 65 * window.draw(sprite); 66 * window.draw(circle); 67 * window.draw(text); 68 * 69 * // End the current frame and display its contents on screen 70 * window.display(); 71 * } 72 * --- 73 * 74 * $(PARA Like $(WINDOW_LINK), $(U RenderWindow) is still able to render direct 75 * OpenGL stuff. It is even possible to mix together OpenGL calls and regular 76 * DSFML drawing commands.) 77 * --- 78 * // Create the render window 79 * auto window = new RenderWindow(VideoMode(800, 600), "DSFML OpenGL"); 80 * 81 * // Create a sprite and a text to display 82 * auto sprite = new Sprite(); 83 * auto text = new Text(); 84 * ... 85 * 86 * // Perform OpenGL initializations 87 * glMatrixMode(GL_PROJECTION); 88 * ... 89 * 90 * // Start the rendering loop 91 * while (window.isOpen()) 92 * { 93 * // Process events 94 * ... 95 * 96 * // Draw a background sprite 97 * window.pushGLStates(); 98 * window.draw(sprite); 99 * window.popGLStates(); 100 * 101 * // Draw a 3D object using OpenGL 102 * glBegin(GL_QUADS); 103 * glVertex3f(...); 104 * ... 105 * glEnd(); 106 * 107 * // Draw text on top of the 3D object 108 * window.pushGLStates(); 109 * window.draw(text); 110 * window.popGLStates(); 111 * 112 * // Finally, display the rendered frame on screen 113 * window.display(); 114 * } 115 * --- 116 * 117 * See_Also: 118 * $(WINDOW_LINK), $(RENDERTARGET_LINK), $(RENDERTEXTURE_LINK), $(VIEW_LINK) 119 */ 120 module nudsfml.graphics.renderwindow; 121 122 import bindbc.sfml.graphics; 123 import bindbc.sfml.window; 124 import bindbc.sfml.system; 125 126 import nudsfml.graphics.color; 127 import nudsfml.graphics.image; 128 import nudsfml.graphics.rect; 129 import nudsfml.graphics.drawable; 130 import nudsfml.graphics.primitivetype; 131 import nudsfml.graphics.renderstates; 132 import nudsfml.graphics.rendertarget; 133 import nudsfml.graphics.shader; 134 import nudsfml.graphics.text; 135 import nudsfml.graphics.texture; 136 import nudsfml.graphics.transform; 137 import nudsfml.graphics.view; 138 import nudsfml.graphics.vertex; 139 140 import nudsfml.window.contextsettings; 141 import nudsfml.window.windowhandle; 142 import nudsfml.window.event; 143 import nudsfml.window.window; 144 import nudsfml.window.videomode; 145 146 //import nudsfml.system.err; 147 import nudsfml.system.vector2; 148 149 /** 150 * Window that can serve as a target for 2D drawing. 151 */ 152 class RenderWindow : Window, RenderTarget 153 { 154 package sfRenderWindow* sfPtr; 155 private View m_currentView, m_defaultView; 156 157 /** 158 * Default constructor. 159 * 160 * This constructor doesn't actually create the window, use the other 161 * constructors or call `create()` to do so. 162 */ 163 this() 164 { 165 sfPtr = null; //sfRenderWindow_construct(); 166 super(0); 167 } 168 169 /** 170 * Construct a new window. 171 * 172 * This constructor creates the window with the size and pixel depth defined 173 * in mode. An optional style can be passed to customize the look and 174 * behavior of the window (borders, title bar, resizable, closable, ...). 175 * 176 * The fourth parameter is an optional structure specifying advanced OpenGL 177 * context settings such as antialiasing, depth-buffer bits, etc. You 178 * shouldn't care about these parameters for a regular usage of the graphics 179 * module. 180 * 181 * Params: 182 * mode = Video mode to use (defines the width, height and depth of the 183 * rendering area of the window) 184 * title = Title of the window 185 * style = Window style, a bitwise OR combination of Style enumerators 186 * settings = Additional settings for the underlying OpenGL context 187 * 188 * //deprecated: Use the constructor that takes a 'const(dchar)[]' instead. 189 */ 190 //deprecated("Use the constructor that takes a 'const(dchar)[]' instead.") 191 this(T)(VideoMode mode, const(T)[] title, Style style = Style.DefaultStyle, ContextSettings settings = ContextSettings.init) 192 if (is(T == wchar)||is(T == char)) 193 { 194 this(); 195 create(mode, title, style, settings); 196 } 197 198 /** 199 * Construct a new window. 200 * 201 * This constructor creates the window with the size and pixel depth defined 202 * in mode. An optional style can be passed to customize the look and 203 * behavior of the window (borders, title bar, resizable, closable, ...). 204 * 205 * The fourth parameter is an optional structure specifying advanced OpenGL 206 * context settings such as antialiasing, depth-buffer bits, etc. You 207 * shouldn't care about these parameters for a regular usage of the graphics 208 * module. 209 * 210 * Params: 211 * mode = Video mode to use (defines the width, height and depth of the 212 * rendering area of the window) 213 * title = Title of the window 214 * style = Window style, a bitwise OR combination of Style enumerators 215 * settings = Additional settings for the underlying OpenGL context 216 */ 217 this(T)(VideoMode mode, const(dchar)[] title, Style style = Style.DefaultStyle, ContextSettings settings = ContextSettings.init) 218 { 219 this(); 220 create(mode, title, style, settings); 221 } 222 223 /** 224 * Construct the window from an existing control. 225 * 226 * Use this constructor if you want to create an DSFML rendering area into 227 * an already existing control. 228 * 229 * The second parameter is an optional structure specifying advanced OpenGL 230 * context settings such as antialiasing, depth-buffer bits, etc. You 231 * shouldn't care about these parameters for a regular usage of the graphics 232 * module. 233 * 234 * Params: 235 * handle = Platform-specific handle of the control 236 * settings = Additional settings for the underlying OpenGL context 237 */ 238 this(WindowHandle handle, ContextSettings settings = ContextSettings.init) 239 { 240 this(); 241 create(handle, settings); 242 } 243 244 ~this() { 245 if (sfPtr != null) 246 sfRenderWindow_destroy(sfPtr); 247 } 248 249 @property 250 { 251 /** 252 * Change the position of the window on screen. 253 * 254 * This property only works for top-level windows (i.e. it will be 255 * ignored for windows created from the handle of a child 256 * window/control). 257 */ 258 override Vector2i position(Vector2i newPosition) 259 { 260 sfRenderWindow_setPosition(sfPtr,cast(sfVector2i)newPosition); 261 return newPosition; 262 } 263 264 /// ditto 265 override Vector2i position() const 266 { 267 Vector2i temp = cast(Vector2i)sfRenderWindow_getPosition(sfPtr); 268 return temp; 269 } 270 } 271 272 @property 273 { 274 /** 275 * The size of the rendering region of the window. 276 */ 277 override Vector2u size(Vector2u newSize) 278 { 279 sfRenderWindow_setSize(sfPtr, cast(sfVector2u)newSize); 280 return newSize; 281 } 282 283 /// ditto 284 override Vector2u size() const 285 { 286 Vector2u temp = cast(Vector2u) sfRenderWindow_getSize(sfPtr); 287 return temp; 288 } 289 } 290 291 @property 292 { 293 /** 294 * Change the current active view. 295 * 296 * The view is like a 2D camera, it controls which part of the 2D scene 297 * is visible, and how it is viewed in the render-target. The new view 298 * will affect everything that is drawn, until another view is set. 299 * 300 * The render target keeps its own copy of the view object, so it is not 301 * necessary to keep the original one alive after calling this function. 302 * To restore the original view of the target, you can pass the result 303 * of `getDefaultView()` to this function. 304 */ 305 override View view(View newView) 306 { 307 sfView *viewPtr = sfView_create(); 308 sfView_setCenter(viewPtr, cast(sfVector2f)newView.center); 309 sfView_setSize(viewPtr, cast(sfVector2f)newView.size); 310 sfView_setRotation(viewPtr, newView.rotation); 311 sfView_setViewport(viewPtr,cast(sfFloatRect) newView.viewport); 312 313 sfRenderWindow_setView(sfPtr, viewPtr); 314 return newView; 315 } 316 317 /// ditto 318 override View view() const 319 { 320 View currentView; 321 322 Vector2f currentCenter, currentSize; 323 float currentRotation; 324 FloatRect currentViewport; 325 326 const(sfView*) v = sfRenderWindow_getView(sfPtr); 327 328 currentView.center = cast(Vector2f)sfView_getCenter(v); 329 currentView.size = cast(Vector2f)sfView_getSize(v); 330 currentView.rotation = sfView_getRotation(v); 331 currentView.viewport = cast(FloatRect)sfView_getViewport(v); 332 333 return currentView; 334 } 335 } 336 337 /** 338 * Get the default view of the render target. 339 * 340 * The default view has the initial size of the render target, and never 341 * changes after the target has been created. 342 * 343 * Returns: The default view of the render target. 344 */ 345 View getDefaultView() const 346 { 347 View currentView; 348 349 Vector2f currentCenter, currentSize; 350 float currentRotation; 351 FloatRect currentViewport; 352 353 const(sfView*) v = sfRenderWindow_getDefaultView(sfPtr); 354 355 currentView.center = cast(Vector2f)sfView_getCenter(v); 356 currentView.size = cast(Vector2f)sfView_getSize(v); 357 currentView.rotation = sfView_getRotation(v); 358 currentView.viewport = cast(FloatRect)sfView_getViewport(v); 359 360 return currentView; 361 } 362 363 /** 364 * Get the settings of the OpenGL context of the window. 365 * 366 * Note that these settings may be different from what was passed to the 367 * constructor or the `create()` function, if one or more settings were not 368 * supported. In this case, DSFML chose the closest match. 369 * 370 * Returns: Structure containing the OpenGL context settings 371 */ 372 override ContextSettings getSettings() const 373 { 374 sfContextSettings settings; 375 ContextSettings temp; 376 //sfWindow_getSettings(sfPtr,&temp.depthBits, &temp.stencilBits, &temp.antialiasingLevel, &temp.majorVersion, &temp.minorVersion); 377 settings = sfRenderWindow_getSettings(sfPtr); 378 temp = cast(ContextSettings)settings; 379 return temp; 380 } 381 382 //this is a duplicate with the size property. Need to look into that 383 //(Inherited from RenderTarget) 384 /** 385 * Return the size of the rendering region of the target. 386 * 387 * Returns: Size in pixels 388 */ 389 Vector2u getSize() const { 390 Vector2u temp = cast(Vector2u) sfRenderWindow_getSize(sfPtr); 391 return temp; 392 } 393 394 /** 395 * Get the OS-specific handle of the window. 396 * 397 * The type of the returned handle is WindowHandle, which is a typedef to 398 * the handle type defined by the OS. You shouldn't need to use this 399 * function, unless you have very specific stuff to implement that SFML 400 * doesn't support, or implement a temporary workaround until a bug is 401 * fixed. 402 * 403 * Returns: System handle of the window 404 */ 405 override WindowHandle getSystemHandle() const 406 { 407 WindowHandle temp = cast(WindowHandle) sfRenderWindow_getSystemHandle(sfPtr); 408 return temp; 409 } 410 411 /** 412 * Get the viewport of a view, applied to this render target. 413 * 414 * A window is active only on the current thread, if you want to make it 415 * active on another thread you have to deactivate it on the previous thread 416 * first if it was active. Only one window can be active on a thread at a 417 * time, thus the window previously active (if any) automatically gets 418 * deactivated. 419 * 420 * Params: 421 * active = true to activate, false to deactivate 422 * 423 * Returns: true if operation was successful, false otherwise 424 */ 425 override bool setActive(bool active) 426 { 427 int v = active ? 1 : 0; 428 return sfRenderWindow_setActive(sfPtr, cast(sfBool)v) > 0; 429 } 430 431 /** 432 * Limit the framerate to a maximum fixed frequency. 433 * 434 * If a limit is set, the window will use a small delay after each call to 435 * `display()` to ensure that the current frame lasted long enough to match 436 * the framerate limit. 437 * 438 * DSFML will try to match the given limit as much as it can, but since it 439 * internally uses sleep, whose precision depends on the underlying OS, the 440 * results may be a little unprecise as well (for example, you can get 65 441 * FPS when requesting 60). 442 * 443 * Params: 444 * limit = Framerate limit, in frames per seconds (use 0 to disable limit) 445 */ 446 override void setFramerateLimit(uint limit) 447 { 448 sfRenderWindow_setFramerateLimit(sfPtr, limit); 449 } 450 451 /** 452 * Change the window's icon. 453 * 454 * pixels must be an array of width x height pixels in 32-bits RGBA format. 455 * 456 * The OS default icon is used by default. 457 * 458 * Params: 459 * width = Icon's width, in pixels 460 * height = Icon's height, in pixels 461 * pixels = Icon pixel array to load from 462 */ 463 override void setIcon(uint width, uint height, const(ubyte[]) pixels) 464 { 465 sfRenderWindow_setIcon(sfPtr,width, height, pixels.ptr); 466 } 467 468 /** 469 * Change the joystick threshold. 470 * 471 * The joystick threshold is the value below which no JoystickMoved event 472 * will be generated. 473 * 474 * The threshold value is 0.1 by default. 475 * 476 * Params: 477 * threshold = New threshold, in the range [0, 100] 478 */ 479 override void setJoystickThreshold(float threshold) 480 { 481 sfRenderWindow_setJoystickThreshold(sfPtr, threshold); 482 } 483 484 /** 485 * Change the joystick threshold. 486 * 487 * The joystick threshold is the value below which no JoystickMoved event 488 * will be generated. 489 * 490 * The threshold value is 0.1 by default. 491 * 492 * Params: 493 * threshhold = New threshold, in the range [0, 100] 494 * 495 * //deprecated: Use set `setJoystickThreshold` instead. 496 */ 497 //deprecated("Use setJoystickThreshold instead.") 498 override void setJoystickThreshhold(float threshhold) 499 { 500 sfRenderWindow_setJoystickThreshold(sfPtr, threshhold); 501 } 502 503 /** 504 * Enable or disable automatic key-repeat. 505 * 506 * If key repeat is enabled, you will receive repeated KeyPressed events 507 * while keeping a key pressed. If it is disabled, you will only get a 508 * single event when the key is pressed. 509 * 510 * Key repeat is enabled by default. 511 * 512 * Params: 513 * enabled = true to enable, false to disable 514 */ 515 override void setKeyRepeatEnabled(bool enabled) 516 { 517 sfRenderWindow_setKeyRepeatEnabled(sfPtr,enabled); 518 } 519 520 /** 521 * Show or hide the mouse cursor. 522 * 523 * The mouse cursor is visible by default. 524 * 525 * Params: 526 * visible = true show the mouse cursor, false to hide it 527 */ 528 override void setMouseCursorVisible(bool visible) 529 { 530 sfRenderWindow_setMouseCursorVisible(sfPtr, visible); 531 } 532 533 //Cannot use templates here as template member functions cannot be virtual. 534 535 /** 536 * Change the title of the window 537 * 538 * Params: 539 * newTitle = New title 540 */ 541 override void setTitle(const(char)[] newTitle) 542 { 543 import std.string; 544 sfRenderWindow_setTitle(sfPtr, newTitle.toStringz); 545 } 546 /** 547 * Change the title of the window 548 * 549 * Params: 550 * newTitle = New title 551 */ 552 override void setTitle(const(wchar)[] newTitle) 553 { 554 import std.utf; 555 auto convertedTitle = newTitle.toUTFz!(dchar*); 556 sfRenderWindow_setUnicodeTitle(sfPtr, cast(uint*)convertedTitle); 557 } 558 /** 559 * Change the title of the window 560 * 561 * Params: 562 * newTitle = New title 563 */ 564 override void setTitle(const(dchar)[] newTitle) 565 { 566 //import nudsfml.system.string; 567 import std.utf; 568 auto convertedTitle = newTitle.toUTFz!(dchar*); 569 sfRenderWindow_setUnicodeTitle(sfPtr,cast(uint*) newTitle); 570 } 571 572 /** 573 * Enable or disable vertical synchronization. 574 * 575 * Activating vertical synchronization will limit the number of frames 576 * displayed to the refresh rate of the monitor. This can avoid some visual 577 * artifacts, and limit the framerate to a good value (but not constant 578 * across different computers). 579 * 580 * Vertical synchronization is disabled by default. 581 * 582 * Params: 583 * enabled = true to enable v-sync, false to deactivate it 584 */ 585 override void setVerticalSyncEnabled(bool enabled) 586 { 587 sfRenderWindow_setVerticalSyncEnabled(sfPtr, enabled); 588 } 589 590 /** 591 * Show or hide the window. 592 * 593 * The window is shown by default. 594 * 595 * Params: 596 * visible = true to show the window, false to hide it 597 */ 598 override void setVisible(bool visible) 599 { 600 sfRenderWindow_setVisible(sfPtr,visible); 601 } 602 603 /** 604 * Clear the entire target with a single color. 605 * 606 * This function is usually called once every frame, to clear the previous 607 * contents of the target. 608 * 609 * Params: 610 * color = Fill color to use to clear the render target 611 */ 612 void clear(Color color = Color.Black) 613 { 614 sfRenderWindow_clear(sfPtr,cast(sfColor)color); 615 } 616 617 /** 618 * Close the window and destroy all the attached resources. 619 * 620 * After calling this function, the Window instance remains valid and you 621 * can call `create()` to recreate the window. All other functions such as 622 * `pollEvent()` or `display()` will still work (i.e. you don't have to test 623 * `isOpen()` every time), and will have no effect on closed windows. 624 */ 625 override void close() 626 { 627 sfRenderWindow_close(sfPtr); 628 } 629 630 //Cannot use templates here as template member functions cannot be virtual. 631 632 /** 633 * Create (or recreate) the window. 634 * 635 * If the window was already created, it closes it first. If style contains 636 * Window.Style.Fullscreen, then mode must be a valid video mode. 637 * 638 * The fourth parameter is an optional structure specifying advanced OpenGL 639 * context settings such as antialiasing, depth-buffer bits, etc. 640 * 641 * Params: 642 * mode = Video mode to use (defines the width, height and depth of the 643 * rendering area of the window) 644 * title = Title of the window 645 * style = Window style, a bitwise OR combination of Style enumerators 646 * settings = Additional settings for the underlying OpenGL context 647 * 648 * //deprecated: Use the version of create that takes a 'const(dchar)[]'. 649 */ 650 ////deprecated("Use the version of create that takes a 'const(dchar)[]'.") 651 override void create(VideoMode mode, const(char)[] title, Style style = Style.DefaultStyle, ContextSettings settings = ContextSettings.init) { 652 import std.string; 653 654 if(sfPtr!=null) { 655 sfRenderWindow_destroy(sfPtr); 656 } 657 sfPtr = sfRenderWindow_create(cast(sfVideoMode)mode, cast(const(char*))title.toStringz, cast(sfUint32)style, cast(sfContextSettings*)&settings); 658 659 //sfRenderWindow_createFromSettings(sfPtr, mode.width, mode.height, mode.bitsPerPixel, convertedTitle.ptr, convertedTitle.length, style, settings.depthBits, settings.stencilBits, settings.antialiasingLevel, settings.majorVersion, settings.minorVersion); 660 661 } 662 663 /// ditto 664 override void create(VideoMode mode, const(wchar)[] title, Style style = Style.DefaultStyle, ContextSettings settings = ContextSettings.init) 665 { 666 import std.utf; 667 if(sfPtr!=null) { 668 sfRenderWindow_destroy(sfPtr); 669 } 670 sfPtr = sfRenderWindow_createUnicode(cast(sfVideoMode)mode, cast(const(uint*))title.toUTFz!(dchar*), cast(sfUint32)style, cast(sfContextSettings*)&settings); 671 } 672 673 /** 674 * Create (or recreate) the window. 675 * 676 * If the window was already created, it closes it first. If style contains 677 * Window.Style.Fullscreen, then mode must be a valid video mode. 678 * 679 * The fourth parameter is an optional structure specifying advanced OpenGL 680 * context settings such as antialiasing, depth-buffer bits, etc. 681 * 682 * Params: 683 * mode = Video mode to use (defines the width, height and depth of the 684 * rendering area of the window) 685 * title = Title of the window 686 * style = Window style, a bitwise OR combination of Style enumerators 687 * settings = Additional settings for the underlying OpenGL context 688 */ 689 override void create(VideoMode mode, const(dchar)[] title, Style style = Style.DefaultStyle, ContextSettings settings = ContextSettings.init) 690 { 691 import std.utf; 692 if(sfPtr!=null) { 693 sfRenderWindow_destroy(sfPtr); 694 } 695 sfPtr = sfRenderWindow_createUnicode(cast(sfVideoMode)mode, cast(const(uint*))title.toUTFz!(dchar*), cast(sfUint32)style, cast(sfContextSettings*)&settings); 696 } 697 698 /** 699 * Create (or recreate) the window from an existing control. 700 * 701 * Use this function if you want to create an OpenGL rendering area into an 702 * already existing control. If the window was already created, it closes it 703 * first. 704 * 705 * The second parameter is an optional structure specifying advanced OpenGL 706 * context settings such as antialiasing, depth-buffer bits, etc. 707 * 708 * Params: 709 * handle = Platform-specific handle of the control 710 * settings = Additional settings for the underlying OpenGL context 711 */ 712 override void create(WindowHandle handle, ContextSettings settings = ContextSettings.init) 713 { 714 if(sfPtr!=null) { 715 sfRenderWindow_destroy(sfPtr); 716 } 717 //verify this is correct 718 sfPtr = sfRenderWindow_createFromHandle(cast(sfWindowHandle)&handle, cast(sfContextSettings*)&settings); 719 } 720 721 /** 722 * Copy the current contents of the window to an image 723 * 724 * //deprecated: 725 * Use a $(TEXTURE_LINK Texture) and its `Texture.update()` function and 726 * copy its contents into an $(IMAGE_LINK Image) instead. 727 * 728 * This is a slow operation, whose main purpose is to make screenshots of 729 * the application. If you want to update an image with the contents of the 730 * window and then use it for drawing, you should rather use a 731 * $(TEXTURE_LINK Texture) and its `update()` function. You can also draw 732 * things directly to a texture with the $(RENDERTEXTURE_LINK RenderTexture) 733 * class. 734 * 735 * Returns: An Image containing the captured contents. 736 */ 737 //deprecated("Use a Texture, its update function, and copy its contents into an Image instead.") 738 Image capture() 739 { 740 return new Image(sfRenderWindow_capture(sfPtr)); 741 } 742 743 /** 744 * Display on screen what has been rendered to the window so far. 745 * 746 * This function is typically called after all OpenGL rendering has been 747 * done for the current frame, in order to show it on screen. 748 */ 749 override void display() 750 { 751 sfRenderWindow_display(sfPtr); 752 } 753 754 /** 755 * Draw a drawable object to the render target. 756 * 757 * Params: 758 * drawable = Object to draw 759 * states = Render states to use for drawing 760 */ 761 void draw(Drawable drawable, RenderStates states = RenderStates.init) 762 { 763 drawable.draw(this,states); 764 } 765 766 /** 767 * Draw primitives defined by an array of vertices. 768 * 769 * Params: 770 * vertices = Array of vertices to draw 771 * type = Type of primitives to draw 772 * states = Render states to use for drawing 773 */ 774 void draw(const(Vertex)[] vertices, PrimitiveType type, RenderStates states = RenderStates.init) 775 { 776 import std.algorithm; 777 778 sfRenderStates sfStates; 779 sfStates.blendMode = cast(sfBlendMode)states.blendMode; 780 sfStates.transform = getFromTransform(states.transform); 781 sfStates.texture = states.texture !is null ? states.texture.sfPtr : null; 782 sfStates.shader = states.shader !is null ? states.shader.sfPtr : null; 783 784 sfRenderWindow_drawPrimitives(sfPtr, cast(sfVertex*)vertices.ptr, cast(uint)min(uint.max, vertices.length),cast(sfPrimitiveType)type, &sfStates); 785 } 786 787 /** 788 * Tell whether or not the window is open. 789 * 790 * This function returns whether or not the window exists. Note that a 791 * hidden window (`setVisible(false)`) is open (therefore this function would 792 * return true). 793 * 794 * Returns: true if the window is open, false if it has been closed 795 */ 796 override bool isOpen() const 797 { 798 return (sfRenderWindow_isOpen(sfPtr)) > 0; 799 } 800 801 /** 802 * Restore the previously saved OpenGL render states and matrices. 803 * 804 * See the description of pushGLStates to get a detailed description of 805 * these functions. 806 */ 807 void popGLStates() 808 { 809 sfRenderWindow_popGLStates(sfPtr); 810 } 811 812 /** 813 * Save the current OpenGL render states and matrices. 814 * 815 * This function can be used when you mix SFML drawing and direct OpenGL 816 * rendering. Combined with PopGLStates, it ensures that: 817 * $(UL 818 * $(LI DSFML's internal states are not messed up by your OpenGL code) 819 * $(LI your OpenGL states are not modified by a call to an SFML function)) 820 * 821 * $(PARA More specifically, it must be used around the code that calls 822 * `draw` functions. 823 * 824 * Note that this function is quite expensive: it saves all the possible 825 * OpenGL states and matrices, even the ones you don't care about.Therefore 826 * it should be used wisely. It is provided for convenience, but the best 827 * results will be achieved if you handle OpenGL states yourself (because 828 * you know which states have really changed, and need to be saved and 829 * restored). Take a look at the `resetGLStates` function if you do so.) 830 */ 831 void pushGLStates() 832 { 833 sfRenderWindow_pushGLStates(sfPtr); 834 } 835 836 /** 837 * Reset the internal OpenGL states so that the target is ready for drawing. 838 * 839 * This function can be used when you mix SFML drawing and direct OpenGL 840 * rendering, if you choose not to use `pushGLStates`/`popGLStates`. It 841 * makes sure that all OpenGL states needed by DSFML are set, so that 842 * subsequent `draw()` calls will work as expected. 843 */ 844 void resetGLStates() 845 { 846 sfRenderWindow_resetGLStates(sfPtr); 847 } 848 849 /** 850 * Pop the event on top of the event queue, if any, and return it. 851 * 852 * This function is not blocking: if there's no pending event then it will 853 * return false and leave event unmodified. Note that more than one event 854 * may be present in the event queue, thus you should always call this 855 * function in a loop to make sure that you process every pending event. 856 * 857 * Params: 858 * event = Event to be returned 859 * 860 * Returns: true if an event was returned, or false if the event queue was 861 * empty. 862 */ 863 override bool pollEvent(ref Event event) 864 { 865 sfEvent sfevent; 866 bool retval = (sfRenderWindow_pollEvent(sfPtr, &sfevent)) > 0; 867 event = fromSfEvent(sfevent); 868 return retval; 869 } 870 871 /** 872 * Wait for an event and return it. 873 * 874 * This function is blocking: if there's no pending event then it will wait 875 * until an event is received. After this function returns (and no error 876 * occured), the event object is always valid and filled properly. This 877 * function is typically used when you have a thread that is dedicated to 878 * events handling: you want to make this thread sleep as long as no new 879 * event is received. 880 * 881 * Params: 882 * event = Event to be returned 883 * 884 * Returns: false if any error occurred. 885 */ 886 override bool waitEvent(ref Event event) 887 { 888 sfEvent sfevent; 889 bool retval = (sfRenderWindow_waitEvent(sfPtr, &sfevent)) > 0; 890 event = fromSfEvent(sfevent); 891 return retval; 892 } 893 894 //TODO: Consider adding these methods. 895 //void onCreate 896 //void onResize 897 898 override protected Vector2i getMousePosition()const 899 { 900 Vector2i temp = cast(Vector2i)sfMouse_getPositionRenderWindow(sfPtr); 901 return temp; 902 } 903 904 //TODO: Fix these names or something. 905 override protected void setMousePosition(Vector2i pos) const 906 { 907 sfVector2i position = cast(sfVector2i)pos; 908 sfMouse_setPositionRenderWindow(position, sfPtr); 909 } 910 911 //let's Texture have a way to get the sfPtr of a regular window. 912 package static void* windowPointer(const(Window) window) 913 { 914 return getWindowPointer(window); 915 } 916 } 917 918 unittest 919 { 920 version(DSFML_Unittest_Graphics) 921 { 922 import std.stdio; 923 import nudsfml.graphics.image; 924 import nudsfml.system.clock; 925 import nudsfml.graphics.sprite; 926 927 writeln("Unit test for RenderWindow"); 928 929 //constructor 930 auto window = new RenderWindow(VideoMode(800,600),"Test Window"); 931 932 //perform each window call 933 Vector2u windowSize = window.size; 934 935 windowSize.x = 1000; 936 windowSize.y = 1000; 937 938 window.size = windowSize; 939 940 Vector2i windowPosition = window.position; 941 942 windowPosition.x = 100; 943 windowPosition.y = 100; 944 945 window.position = windowPosition; 946 947 window.setTitle("thing");//uses the first set title 948 949 window.setTitle("素晴らしい !"d);//forces the dstring override and uses utf-32 950 951 window.setActive(true); 952 953 window.setJoystickThreshhold(1); 954 955 window.setVisible(true); 956 957 window.setFramerateLimit(60); 958 959 window.setMouseCursorVisible(true); 960 961 window.setVerticalSyncEnabled(true); 962 963 auto settings = window.getSettings(); 964 965 auto image = new Image(); 966 image.loadFromFile("data/lain.png"); 967 968 window.setIcon(image.getSize().x,image.getSize().x,image.getPixelArray()); //validate 969 970 auto texture = new Texture(); 971 972 texture.loadFromImage(image); 973 974 auto sprite = new Sprite(texture); 975 976 auto clock = new Clock(); 977 978 while(window.isOpen()) 979 { 980 Event event; 981 if(window.pollEvent(event)) 982 { 983 //no events 984 } 985 986 if(clock.getElapsedTime().asSeconds() > 1) 987 { 988 window.close(); 989 } 990 991 window.clear(); 992 993 window.draw(sprite); 994 995 window.display(); 996 } 997 998 writeln(); 999 } 1000 } 1001