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