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