1 /*
2  *  BSD 3-Clause License
3  *  
4  *  Copyright (c) 2016, Mango-Engine Team
5  *  All rights reserved.
6  *  
7  *  Redistribution and use in source and binary forms, with or without
8  *  modification, are permitted provided that the following conditions are met:
9  *  
10  *  * Redistributions of source code must retain the above copyright notice, this
11  *    list of conditions and the following disclaimer.
12  *  
13  *  * Redistributions in binary form must reproduce the above copyright notice,
14  *    this list of conditions and the following disclaimer in the documentation
15  *    and/or other materials provided with the distribution.
16  *  
17  *  * Neither the name of the copyright holder nor the names of its
18  *    contributors may be used to endorse or promote products derived from
19  *    this software without specific prior written permission.
20  *  
21  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24  *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25  *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27  *  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  *  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 module mango_engine.graphics.window;
33 
34 import mango_engine.mango;
35 import mango_engine.game;
36 import mango_engine.graphics.backend;
37 
38 /// Represents different screen sync types
39 enum SyncType {
40     /// No sync
41     SYNC_NONE,
42     /// Vertical Sync (double/triple buffering)
43     SYNC_VSYNC,
44     /// Adaptive Sync (G-Sync, FreeSync)
45     SYNC_ADAPTIVE
46 }
47 
48 /// Thrown when there is an error creating the Window context.
49 class WindowContextFailedException : Exception {
50     this(in string message) {
51         super(message);
52     }   
53 }
54 
55 /++
56     Represents a surface that the backend
57     renders on.
58 +/
59 abstract class Window {
60     private shared GameManager _game;
61     private shared string _title;
62     private shared uint _width;
63     private shared uint _height;
64     private SyncType _syncType;
65 
66     /// The title of the Window.
67     @property string title() @safe nothrow { return _title; }
68     /// The title of the Window.
69     @property void title(in string title) @trusted {
70         _title = title;
71         setTitle_(title);
72     }
73 
74     /// The width of the window in pixels.
75     @property uint width() @safe nothrow { return _width; }
76     /// The height of the window in pixels.
77     @property uint height() @safe nothrow { return _height; }
78     /// The type of synchronization the window is using.
79     @property SyncType syncType() @safe nothrow { return _syncType; }
80 
81     @property GameManager game() @trusted nothrow { return cast(GameManager) _game; }
82 
83     protected this(in string title, in uint width, in uint height, SyncType syncType) @safe nothrow {
84         this._title = title;
85         this._width = width;
86         this._height = height;
87         this._syncType = syncType;
88     }
89 
90     /++
91         Create a new window based on the GraphicsBackendType.
92         If the backend has not been compiled into mango-engine,
93         an exception will be thrown.
94 
95         Params:
96                 title =     The title of the Window.
97                 width =     The width of the window (in pixels)
98                 height =    The height of the window (in pixels)
99                 syncType =  The SyncType used by the window.
100                 backend =   The Backend to use for rendering. This needs
101                             to be consistent across your application,
102                             or else there will be strange bugs.
103                             
104         Throws: Exception if no backends are avaliable.
105     +/
106     static Window windowFactory(in string title, in uint width, in uint height, SyncType syncType, GraphicsBackendType backend) @safe {
107         import mango_engine.graphics.opengl.gl_window;
108         
109         mixin(GenFactory!("Window", "title, width, height, syncType"));
110     }
111 
112     final void resize(in uint width, in uint height) @trusted {
113         _width = width;
114         _height = height;
115         resize_(width, height);
116     }
117 
118     /// Used ONLY by GameManager. DO NOT CALL!
119     final void setGame(GameManager game) @trusted {
120         this._game = cast(shared) game;
121         setGame_();
122     }
123 
124     shared abstract void updateBuffers() @system;
125     protected abstract void setGame_() @system;
126     protected abstract void setSync_(in SyncType syncType) @system;
127     protected abstract void setTitle_(in string title) @system;
128     protected abstract void resize_(in uint width, in uint height) @system;
129 }