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