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