1 module nudsfml.graphics.view;
2 
3 import nudsfml.graphics.rect;
4 import nudsfml.system.vector2;
5 
6 import nudsfml.graphics.transform;
7 
8 struct View {
9     package {
10         Vector2f m_center = Vector2f(500, 500);
11         Vector2f m_size = Vector2f(1000, 1000);
12         float m_rotation = 0;
13         FloatRect m_viewport = FloatRect(0, 0, 1, 1);
14     } private {
15         bool m_transformUpdated;
16         bool m_invTransformUpdated;
17         Transform m_transform;
18         Transform m_invTransform;
19     }
20 
21     this (FloatRect rectangle){
22         reset (rectangle);
23     }
24 
25     this (Vector2f center, Vector2f size){
26         m_center = center;
27         m_size = size;
28     }
29 
30     @property { //center 
31         Vector2f center(Vector2f newCenter){
32             m_center = newCenter;
33             m_transformUpdated = false;
34             m_invTransformUpdated = false;
35             return m_center;
36         }
37 
38         Vector2f center() const {
39             return m_center;
40         }
41     }
42 
43     @property {//rotation 
44         float rotation(float newRotation){
45             m_rotation = newRotation;
46             if (m_rotation < 0) {
47                 m_rotation += 360;
48             }
49             m_transformUpdated = false;
50             m_invTransformUpdated = false;
51             return m_rotation;
52         }
53         float rotation() const {
54             return m_rotation;
55         }
56     }
57 
58     @property {//size 
59         Vector2f size(Vector2f newSize){
60             m_size = newSize;
61             m_transformUpdated = false;
62             m_invTransformUpdated = false;
63             return m_size;
64         }
65         Vector2f size() const {
66             return m_size;
67         }
68     }
69 
70     @property {//viewport 
71         FloatRect viewport(FloatRect newViewport){
72             m_viewport = newViewport;
73             m_transformUpdated = false;
74             m_invTransformUpdated = false;
75             return m_viewport;
76         }
77         FloatRect viewport() const {
78             return m_viewport;
79         }
80     }
81 
82     void move(Vector2f offset){
83         m_center += offset;
84     }
85 
86     void reset(FloatRect rectangle){
87         m_center.x  = rectangle.left + rectangle.width / 2;
88         m_center.y = rectangle.top + rectangle.height / 2;
89         m_size.x = rectangle.width;
90         m_size.y = rectangle.height;
91         m_rotation = 0;
92 
93         m_transformUpdated = false;
94         m_invTransformUpdated = false;
95     }
96 
97     void zoom(float factor){
98         m_size *= factor;
99     }
100 
101     Transform getTransform() {
102         import std.math;
103 
104         Transform currentTransform;
105 
106         float angle =   m_rotation * 3.141592654f / 180.0;
107         float cosine =  cos(angle);
108         float sine =    sin(angle);
109         float tx =      -m_center.x * cosine - m_center.y * sine + m_center.x;
110         float ty =      m_center.x * sine - m_center.y * cosine + m_center.y;
111 
112         float a = 2.0 / m_size.x;
113         float b = 2.0 / m_size.y;
114         float c = -a * m_center.x - b * m_center.y;
115         float d = -b * m_center.y;
116 
117         currentTransform = Transform(a * cosine,    a * sine,   a * tx + c,
118                                     -b * sine,      b * cosine, b * ty + d,
119                                      0.0,           0.0,        1.0);
120 
121         return currentTransform;
122     }
123 
124     Transform getInverseTransform() {
125         if (!m_invTransformUpdated) {
126             m_invTransform = getTransform().getInverse();
127             m_invTransformUpdated = true;
128         }
129 
130         return m_invTransform;
131     }
132 }