1 /**
2 * Copyright © Novelate 2020
3 * License: MIT (https://github.com/Novelate/NovelateEngine/blob/master/LICENSE)
4 * Author: Jacob Jensen (bausshf)
5 * Website: https://novelate.com/
6 * ------
7 * Novelate is a free and open-source visual novel engine and framework written in the D programming language.
8 * It can be used freely for both personal and commercial projects.
9 * ------
10 * Module Description:
11 * This module is used for external bindings to dsfml. Types and functions should only be exposed through internal types ex. RenderWindow is only referenced through ExternalWindow.
12 * This is the main module for external bindings and all possible bindings should reference this module in terms of implementation.
13 */
14 module novelate.dsfmlbinding;
15 
16 import novelate.buildstate;
17 
18 static if (useSFML && !useDerelict)
19 {
20   import novelate.external.core;
21 
22   private
23   {
24     import dsfml.graphics;
25     import dsfml.window;
26     import dsfml.audio;
27     import dsfml.system;
28     import dsfml.network;
29   }
30 
31   /// Initialization of the external binding.
32   void initExternalBinding()
33   {
34 
35   }
36 
37   /// FloatVector -> Vector2f
38   Vector2f toNative(FloatVector vector)
39   {
40     return Vector2f(vector.x, vector.y);
41   }
42 
43   /// UintVector -> Vector2u
44   Vector2u toNative(UintVector vector)
45   {
46     return Vector2u(vector.x, vector.y);
47   }
48 
49   /// IntVector -> Vector2i
50   Vector2i toNative(IntVector vector)
51   {
52     return Vector2i(vector.x, vector.y);
53   }
54 
55   /// Vector2f -> FloatVector
56   FloatVector fromNative(Vector2f vector)
57   {
58     return FloatVector(vector.x, vector.y);
59   }
60 
61   /// Vector2u -> UintVector
62   UintVector fromNative(Vector2u vector)
63   {
64     return UintVector(vector.x, vector.y);
65   }
66 
67   /// Vector2i -> IntVector
68   IntVector fromNative(Vector2i vector)
69   {
70     return IntVector(vector.x, vector.y);
71   }
72 
73   /// Paint -> Color
74   Color toNative(Paint paint)
75   {
76     return Color(paint.r, paint.g, paint.b, paint.a);
77   }
78 
79   /// Color -> Paint
80   Paint fromNative(Color color)
81   {
82     return Paint(color.r, color.g, color.b, color.a);
83   }
84 
85   /// KeyboardKey -> Keyboard.Key
86   Keyboard.Key toNative(KeyboardKey key)
87   {
88     return cast(Keyboard.Key)key;
89   }
90 
91   /// KeyboardKey -> Keyboard.Key
92   KeyboardKey fromNative(Keyboard.Key key)
93   {
94     return cast(KeyboardKey)key;
95   }
96 
97   /// MouseButton -> Mouse.Button
98   Mouse.Button toNative(MouseButton button)
99   {
100     return cast(Mouse.Button)button;
101   }
102 
103   /// Mouse.Button -> MouseButton
104   MouseButton fromNative(Mouse.Button button)
105   {
106     return cast(MouseButton)button;
107   }
108 
109   /// IExternalDrawableComponent
110   interface IExternalDrawableComponent
111   {
112     /// draw()
113     void draw(ExternalWindow window);
114   }
115 
116   /// ExternalImage
117   final class ExternalImage : IExternalDrawableComponent
118   {
119     private:
120     /// _image
121     Image _image;
122     /// _texture
123     Texture _texture;
124     /// _sprite
125     Sprite _sprite;
126 
127     public:
128     /// this()
129     this()
130     {
131     }
132 
133     /// loadFromFile()
134     void loadFromFile(string path)
135     {
136       _image = new Image;
137       _image.loadFromFile(path);
138       _texture = new Texture;
139       _texture.loadFromImage(_image);
140   		_texture.setSmooth(true);
141       _sprite = new Sprite(_texture);
142     }
143 
144     @property
145     {
146       /// Gets bounds.
147       FloatVector bounds()
148       {
149         auto localBounds = _sprite.getLocalBounds();
150 
151         return FloatVector(localBounds.width, localBounds.height);
152       }
153 
154       /// Gets size.
155       UintVector size()
156       {
157         return _image.getSize().fromNative();
158       }
159 
160       /// Gets position.
161       FloatVector position()
162       {
163         return _sprite.position.fromNative();
164       }
165 
166       /// Sets position.
167       void position(FloatVector newPosition)
168       {
169         _sprite.position = newPosition.toNative();
170       }
171 
172       /// Gets color.
173       Paint color()
174       {
175         return _sprite.color.fromNative();
176       }
177 
178       /// Sets color.
179       void color(Paint newColor)
180       {
181         _sprite.color = newColor.toNative();
182       }
183 
184       /// Gets scale.
185       FloatVector scale()
186       {
187         return _sprite.scale.fromNative();
188       }
189 
190       /// Sets scale.
191       void scale(FloatVector newScale)
192       {
193         _sprite.scale = newScale.toNative();
194       }
195     }
196 
197     /// draw()
198     void draw(ExternalWindow window)
199     {
200       window._window.draw(_sprite);
201     }
202   }
203 
204   /// ExternalWindow.
205   final class ExternalWindow
206   {
207     private:
208     /// _window.
209     RenderWindow _window;
210     /// _fps.
211     uint _fps;
212 
213     public:
214     @property
215     {
216       /// Gets isOpen.
217       bool isOpen() { return _window.isOpen(); }
218 
219       /// Gets fps.
220       uint fps() { return _fps; }
221 
222       /// Sets fps.
223       void fps(uint newFps)
224       {
225         _fps = newFps;
226 
227         _window.setFramerateLimit(_fps);
228       }
229 
230       bool canUpdate()
231       {
232         return true;
233       }
234     }
235 
236     /// close()
237     void close()
238     {
239       _window.close();
240     }
241 
242     /// render()
243     void render()
244     {
245       _window.display();
246     }
247 
248     /// clear()
249     void clear(Paint paint)
250     {
251       _window.clear(paint.toNative());
252     }
253 
254     /// processEvents()
255     bool processEvents(ExternalEventManager eventManager)
256     {
257       Event e;
258       while(_window.pollEvent(e))
259       {
260         auto res = _window.pollEvent(e);
261 
262         switch (e.type)
263         {
264           case Event.EventType.Closed:
265             eventManager.fireEvent(cast(ExternalEventType)e.type);
266             return false;
267 
268           case Event.EventType.Resized:
269             ExternalEventState._sizeEvent = cast(ExternalSizeEvent)e.size;
270             break;
271 
272           case Event.EventType.TextEntered:
273             ExternalEventState._textEvent = cast(ExternalTextEvent)e.text;
274             break;
275 
276           case Event.EventType.KeyPressed:
277           case Event.EventType.KeyReleased:
278             ExternalEventState._keyEvent = cast(ExternalKeyEvent)e.key;
279             break;
280 
281           case Event.EventType.MouseWheelMoved:
282             ExternalEventState._mouseWheelEvent = cast(ExternalMouseWheelEvent)e.mouseWheel;
283             break;
284 
285           case Event.EventType.MouseButtonPressed:
286           case Event.EventType.MouseButtonReleased:
287             ExternalEventState._mouseButtonEvent = cast(ExternalMouseButtonEvent)e.mouseButton;
288             break;
289 
290           case Event.EventType.MouseMoved:
291             ExternalEventState._mouseMoveEvent = cast(ExternalMouseMoveEvent)e.mouseMove;
292             break;
293 
294           case Event.EventType.JoystickButtonPressed:
295           case Event.EventType.JoystickButtonReleased:
296             ExternalEventState._joystickButtonEvent = cast(ExternalJoystickButtonEvent)e.joystickButton;
297             break;
298 
299           case Event.EventType.JoystickMoved:
300             ExternalEventState._joystickMoveEvent = cast(ExternalJoystickMoveEvent)e.joystickMove;
301             break;
302 
303           case Event.EventType.JoystickConnected:
304           case Event.EventType.JoystickDisconnected:
305             ExternalEventState._joystickConnectEvent = cast(ExternalJoystickConnectEvent)e.joystickConnect;
306             break;
307 
308           default: break;
309         }
310 
311         eventManager.fireEvent(cast(ExternalEventType)e.type);
312       }
313 
314       return true;
315     }
316 
317     static:
318     /// create()
319     ExternalWindow create(string title, size_t width, size_t height, bool fullScreen)
320     {
321       auto videoMode = VideoMode(cast(int)width, cast(int)height);
322       ContextSettings context;
323       context.antialiasingLevel = 100;
324 
325       RenderWindow renderWindow;
326       if (fullScreen)
327       {
328         renderWindow = new RenderWindow(videoMode, title, (Window.Style.Fullscreen), context);
329       }
330       else
331       {
332         renderWindow = new RenderWindow(videoMode, title, (Window.Style.Titlebar | Window.Style.Close), context);
333       }
334 
335       auto window = new ExternalWindow;
336       window._window = renderWindow;
337       return window;
338     }
339   }
340 
341   /// ExternalRectangleShape
342   final class ExternalRectangleShape : IExternalDrawableComponent
343   {
344     private:
345     /// _rect
346     RectangleShape _rect;
347 
348     public:
349     final:
350     /// this()
351     this(FloatVector size)
352     {
353       _rect = new RectangleShape(size.toNative());
354     }
355 
356     @property
357     {
358       /// Gets fillColor
359       Paint fillColor()
360       {
361         return _rect.fillColor.fromNative();
362       }
363 
364       /// Sets fillColor
365       void fillColor(Paint newColor)
366       {
367         _rect.fillColor = newColor.toNative();
368       }
369 
370       /// Gets position
371       FloatVector position()
372       {
373         return _rect.position.fromNative();
374       }
375 
376       /// Sets position
377       void position(FloatVector newPosition)
378       {
379         _rect.position = newPosition.toNative();
380       }
381     }
382 
383     /// draw()
384     void draw(ExternalWindow window)
385     {
386       window._window.draw(_rect);
387     }
388   }
389 
390   /// ExternalText
391   final class ExternalText : IExternalDrawableComponent
392   {
393     private:
394     /// _text
395     Text _text;
396 
397     public:
398     final:
399     /// this()
400     this()
401     {
402       _text = new Text();
403     }
404 
405     @property
406     {
407       /// Gets bounds.
408       FloatVector bounds()
409       {
410         auto localBounds = _text.getLocalBounds();
411 
412         return FloatVector(localBounds.width, localBounds.height);
413       }
414 
415       /// Gets position.
416       FloatVector position()
417       {
418         return _text.position.fromNative();
419       }
420 
421       /// Sets position.
422       void position(FloatVector newPosition)
423       {
424         _text.position = newPosition.toNative();
425       }
426     }
427 
428     /// setFont()
429     void setFont(ExternalFont font)
430     {
431       _text.setFont(font._font);
432     }
433 
434     /// setString()
435     void setString(dstring text)
436     {
437       _text.setString(text);
438     }
439 
440     /// setCharacterSize()
441     void setCharacterSize(size_t characterSize)
442     {
443       _text.setCharacterSize(cast(uint)characterSize);
444     }
445 
446     /// setColor()
447     void setColor(Paint newColor)
448     {
449       _text.setColor(newColor.toNative());
450     }
451 
452     /// draw()
453     void draw(ExternalWindow window)
454     {
455       window._window.draw(_text);
456     }
457   }
458 
459   /// ExternalFont
460   final class ExternalFont
461   {
462     private:
463     /// _font
464     Font _font;
465 
466     public:
467     final:
468     /// this()
469     this()
470     {
471       _font = new Font;
472     }
473 
474     /// loadFromFile()
475     void loadFromFile(string path)
476     {
477       _font.loadFromFile(path);
478     }
479   }
480 
481   /// ExternalMusic
482   final class ExternalMusic
483   {
484     private:
485     /// _music
486     Music _music;
487 
488     public:
489     final:
490     /// this()
491     this()
492     {
493       _music = new Music();
494     }
495 
496     @property
497     {
498       /// Gets looping
499       bool looping()
500       {
501         return _music.isLooping;
502       }
503 
504       /// Sets looping
505       void looping(bool isLooping)
506       {
507         _music.isLooping = isLooping;
508       }
509     }
510 
511     /// openFromFile()
512     bool openFromFile(string music)
513     {
514       return _music.openFromFile(music);
515     }
516 
517     /// play()
518     void play()
519     {
520       _music.play();
521     }
522 
523     /// pause()
524     void pause()
525     {
526       _music.pause();
527     }
528 
529     /// stop()
530     void stop()
531     {
532       _music.stop();
533     }
534   }
535 
536   /// quit()
537   void quit()
538   {
539 
540   }
541 }