1 /*
2  *******************************************************************************************
3  * Dgame (a D game framework) - Copyright (c) Randy Schütt
4  * 
5  * This software is provided 'as-is', without any express or implied warranty.
6  * In no event will the authors be held liable for any damages arising from
7  * the use of this software.
8  * 
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  * 
13  * 1. The origin of this software must not be misrepresented; you must not claim
14  *    that you wrote the original software. If you use this software in a product,
15  *    an acknowledgment in the product documentation would be appreciated but is
16  *    not required.
17  * 
18  * 2. Altered source versions must be plainly marked as such, and must not be
19  *    misrepresented as being the original software.
20  * 
21  * 3. This notice may not be removed or altered from any source distribution.
22  *******************************************************************************************
23  */
24 module Dgame.Graphic.Sprite;
25 
26 private:
27 
28 import Dgame.Math.Rect;
29 import Dgame.Math.Vector2;
30 import Dgame.Math.Vertex;
31 import Dgame.Math.Geometry;
32 
33 import Dgame.Graphic.Drawable;
34 import Dgame.Graphic.Transformable;
35 import Dgame.Graphic.Texture;
36 import Dgame.Graphic.Color;
37 
38 public:
39 
40 /**
41  * Sprite represents a drawable object and maintains a Texture
42  *
43  * Author: Randy Schuett (rswhite4@googlemail.com)
44  */
45 class Sprite : Transformable, Drawable {
46 protected:
47     Texture* _texture;
48     Rect _texRect;
49     Vertex[4] _vertices;
50 
51     @nogc
52     override void draw(ref const Window wnd) nothrow {
53         wnd.draw(Geometry.TriangleStrip, super.getMatrix(), _texture, _vertices[]);
54     }
55 
56     @nogc
57     final void _updateVertices() pure nothrow {
58         immutable float tx = float(_texRect.x) / _texture.width;
59         immutable float ty = float(_texRect.y) / _texture.height;
60         immutable float tw = float(_texRect.width) / _texture.width;
61         immutable float th = float(_texRect.height) / _texture.height;
62 
63         immutable float tx_tw = tx + tw;
64         immutable float ty_th = ty + th;
65 
66         _vertices[0].position = Vector2f(0, 0);
67         _vertices[0].texCoord = Vector2f(tx, ty);
68 
69         _vertices[1].position = Vector2f(_texRect.width, 0);
70         _vertices[1].texCoord = Vector2f(tx_tw, ty);
71 
72         _vertices[2].position = Vector2f(0, _texRect.height);
73         _vertices[2].texCoord = Vector2f(tx, ty_th);
74 
75         _vertices[3].position = Vector2f(_texRect.width, _texRect.height);
76         _vertices[3].texCoord = Vector2f(tx_tw, ty_th);
77     }
78 
79     @nogc
80     final void _adjustTextureRect() pure nothrow {
81         _texRect.x = 0;
82         _texRect.y = 0;
83         _texRect.width = _texture.width;
84         _texRect.height = _texture.height;
85     }
86 
87 public:
88 final:
89     /**
90      * CTor
91      */
92     @nogc
93     this(ref Texture tex) pure nothrow {
94         _texture = &tex;
95 
96         _adjustTextureRect();
97         _updateVertices();
98 
99         this.setColor(Color4b.White);
100     }
101 
102     /**
103      * CTor
104      */
105     @nogc
106     this(ref Texture tex, const Vector2f pos) pure nothrow {
107         this(tex);
108 
109         super.setPosition(pos);
110     }
111 
112     /**
113      * Reset the Texture
114      */
115     @nogc
116     void setTexture(ref Texture tex) pure nothrow {
117         _texture = &tex;
118 
119         this.setColor(Color4b.White);
120 
121         _adjustTextureRect();
122         _updateVertices();
123     }
124 
125     /**
126      * Returns a pointer to the current Texture
127      */
128     @nogc
129     inout(Texture*) getTexture() inout pure nothrow {
130         return _texture;
131     }
132 
133     /**
134      * Set a Color for the Sprite which is painted over the displayed Texture.
135      */
136     @nogc
137     void setColor(const Color4b col) pure nothrow {
138         foreach (ref Vertex v; _vertices) {
139             v.color = Color4f(col);
140         }
141     }
142 
143     /**
144      * Set the Texture Rect. With this you can define a specific view of the Texture,
145      * so that only this specific view will be drawn.
146      */
147     @nogc
148     void setTextureRect(const Rect texRect) pure nothrow {
149         _texRect = texRect;
150         _updateVertices();
151     }
152 
153     /**
154      * Returns the current Texture Rect
155      */
156     @nogc
157     ref const(Rect) getTextureRect() const pure nothrow {
158         return _texRect;
159     }
160 
161     /**
162      * Returns the Clip Rect.
163      * The Sprite will notice if a Texture Rect is used or not and will therefore adapt the size of the view automatically
164      */
165     @nogc
166     Rect getClipRect() const pure nothrow {
167         uint w = 0, h = 0;
168         if (_texRect.isEmpty()) {
169             w = _texture.width;
170             h = _texture.height;
171         } else {
172             w = _texRect.width;
173             h = _texRect.height;
174         }
175 
176         return Rect(cast(int) super.x, cast(int) super.y, w, h);
177     }
178 }