1 /* 2 * DSFML - The Simple and Fast Multimedia Library for D 3 * 4 * Copyright (c) 2013 - 2018 Jeremy DeHaan (dehaan.jeremiah@gmail.com) 5 * 6 * This software is provided 'as-is', without any express or implied warranty. 7 * In no event will the authors be held liable for any damages arising from the 8 * use of this software. 9 * 10 * Permission is granted to anyone to use this software for any purpose, 11 * including commercial applications, and to alter it and redistribute it 12 * freely, subject to the following restrictions: 13 * 14 * 1. The origin of this software must not be misrepresented; you must not claim 15 * that you wrote the original software. If you use this software in a product, 16 * an acknowledgment in the product documentation would be appreciated but is 17 * not required. 18 * 19 * 2. Altered source versions must be plainly marked as such, and must not be 20 * misrepresented as being the original software. 21 * 22 * 3. This notice may not be removed or altered from any source distribution 23 * 24 * 25 * DSFML is based on SFML (Copyright Laurent Gomila) 26 */ 27 28 /** 29 * $(U VertexArray) is a very simple wrapper around a dynamic array of vertices 30 *and a primitives type. 31 * 32 * It inherits $(DRAWABLE_LINK), but unlike other drawables it is not 33 * transformable. 34 * 35 * Example: 36 * --- 37 * VertexArray lines(PrimitiveType.LineStrip, 4); 38 * lines[0].position = Vector2f(10, 0); 39 * lines[1].position = Vector2f(20, 0); 40 * lines[2].position = Vector2f(30, 5); 41 * lines[3].position = Vector2f(40, 2); 42 * 43 * window.draw(lines); 44 * --- 45 * 46 * See_Also: 47 * $(VERTEX_LINK) 48 */ 49 module nudsfml.graphics.vertexarray; 50 51 import nudsfml.graphics.vertex; 52 import nudsfml.graphics.primitivetype; 53 import nudsfml.graphics.rect; 54 import nudsfml.graphics.drawable; 55 import nudsfml.graphics.rendertarget; 56 import nudsfml.graphics.renderstates; 57 58 import nudsfml.system.vector2; 59 60 /** 61 * Define a set of one or more 2D primitives. 62 */ 63 class VertexArray : Drawable { 64 /** 65 * The type of primitive to draw. 66 * 67 * Can be any of the following: 68 * - Points 69 * - Lines 70 * - Triangles 71 * - Quads 72 * 73 * The default primitive type is Points. 74 */ 75 PrimitiveType primitiveType; 76 private Vertex[] Vertices; 77 78 /** 79 * Default constructor 80 * 81 * Creates an empty vertex array. 82 */ 83 this() { 84 } 85 86 /** 87 * Construct the vertex array with a type and an initial number of vertices 88 * 89 * Params: 90 * type = Type of primitives 91 * vertexCount = Initial number of vertices in the array 92 */ 93 this(PrimitiveType type, uint vertexCount = 0) { 94 primitiveType = type; 95 Vertices = new Vertex[vertexCount]; 96 } 97 98 private this(PrimitiveType type, Vertex[] vertices) { 99 primitiveType = type; 100 Vertices = vertices; 101 } 102 103 /// Destructor. 104 ~this() { 105 import nudsfml.system.config; 106 mixin(destructorOutput); 107 } 108 109 /** 110 * Compute the bounding rectangle of the vertex array. 111 * 112 * This function returns the axis-aligned rectangle that contains all the 113 * vertices of the array. 114 * 115 * Returns: Bounding rectangle of the vertex array. 116 */ 117 FloatRect getBounds() const { 118 if (Vertices.length>0) { 119 float left = Vertices[0].position.x; 120 float top = Vertices[0].position.y; 121 float right = Vertices[0].position.x; 122 float bottom = Vertices[0].position.y; 123 124 for (size_t i = 1; i < Vertices.length; ++i) { 125 Vector2f position = Vertices[i].position; 126 127 // Update left and right 128 if (position.x < left) 129 left = position.x; 130 if (position.x > right) 131 right = position.x; 132 133 // Update top and bottom 134 if (position.y <= top) 135 top = position.y; 136 if (position.y > bottom) 137 bottom = position.y; 138 } 139 return FloatRect(left, top, right - left, bottom - top); 140 } else { 141 return FloatRect(0,0,0,0); 142 } 143 } 144 145 /** 146 * Return the vertex count. 147 * 148 * Returns: Number of vertices in the array 149 */ 150 uint getVertexCount() const { 151 import std.algorithm; 152 return cast(uint)min(uint.max, Vertices.length); 153 } 154 155 /** 156 * Add a vertex to the array. 157 * 158 * Params: 159 * newVertex = Vertex to add. 160 */ 161 void append(Vertex newVertex) { 162 Vertices ~= newVertex; 163 } 164 165 /** 166 * Clear the vertex array. 167 * 168 * This function removes all the vertices from the array. It doesn't 169 * deallocate the corresponding memory, so that adding new vertices after 170 * clearing doesn't involve reallocating all the memory. 171 */ 172 void clear() { 173 Vertices.length = 0; 174 } 175 176 /** 177 * Draw the object to a render target. 178 * 179 * Params: 180 * renderTarget = Render target to draw to 181 * renderStates = Current render states 182 */ 183 override void draw(RenderTarget renderTarget, RenderStates renderStates) { 184 if(Vertices.length != 0) { 185 renderTarget.draw(Vertices, primitiveType,renderStates); 186 } 187 } 188 189 /** 190 * Resize the vertex array. 191 * 192 * If vertexCount is greater than the current size, the previous vertices 193 * are kept and new (default-constructed) vertices are added. If vertexCount 194 * is less than the current size, existing vertices are removed from the 195 * array. 196 * 197 * Params: 198 * vertexCount = New size of the array (number of vertices). 199 */ 200 void resize(uint vertexCount) { 201 Vertices.length = vertexCount; 202 } 203 204 /** 205 * Get a read-write access to a vertex by its index 206 * 207 * This function doesn't check index, it must be in range 208 * [0, getVertexCount() - 1]. The behavior is undefined otherwise. 209 * 210 * Params: 211 * index = Index of the vertex to get 212 * 213 * Returns: Reference to the index-th vertex. 214 */ 215 ref Vertex opIndex(size_t index) { 216 return Vertices[index]; 217 } 218 219 //TODO: const ref Vertex opIndex(size_t) const, perhaps? 220 } 221 222 unittest 223 { 224 version(DSFML_Unittest_Graphics) 225 { 226 import std.stdio; 227 import nudsfml.graphics.texture; 228 import nudsfml.graphics.rendertexture; 229 import nudsfml.graphics.color; 230 231 writeln("Unit test for VertexArray"); 232 233 auto texture = new Texture(); 234 235 assert(texture.loadFromFile("data/lain.png")); 236 237 auto dimensions = FloatRect(0,0,texture.getSize().x,texture.getSize().y); 238 239 auto vertexArray = new VertexArray(PrimitiveType.Quads, 0); 240 241 //Creates a vertex array at position (0,0) the width and height of the loaded texture 242 vertexArray.append(Vertex(Vector2f(dimensions.left,dimensions.top), Color.Blue, Vector2f(dimensions.left,dimensions.top))); 243 vertexArray.append(Vertex(Vector2f(dimensions.left,dimensions.height), Color.Blue, Vector2f(dimensions.left,dimensions.height))); 244 vertexArray.append(Vertex(Vector2f(dimensions.width,dimensions.height), Color.Blue, Vector2f(dimensions.width,dimensions.height))); 245 vertexArray.append(Vertex(Vector2f(dimensions.width,dimensions.top), Color.Blue, Vector2f(dimensions.width,dimensions.top))); 246 247 auto renderStates = RenderStates(texture); 248 249 auto renderTexture = new RenderTexture(); 250 251 renderTexture.create(100,100); 252 253 renderTexture.clear(); 254 255 //draw the VertexArray with the texture we loaded 256 renderTexture.draw(vertexArray, renderStates); 257 258 renderTexture.display(); 259 260 writeln(); 261 } 262 }