1 module d2d.rendering.rectangleshape;
2 
3 import d2d;
4 
5 /**
6  * A resizable rectangle containing a texture.
7  * Examples:
8  * ---
9  * auto rect = new RectangleShape();
10  * rect.size = vec2(100, 50); // 100x50 px
11  * rect.create();
12  * window.draw(rect);
13  *
14  * // OR
15  *
16  * auto rect = RectangleShape.create(vec2(0, 0), vec2(100, 50)); // At 0,0 with size 100x50 px
17  * window.draw(rect);
18  * ---
19  */
20 class RectangleShape : Shape, IDisposable, IVerifiable
21 {
22 protected:
23 	Mesh _mesh; // TODO: Only 1 Mesh
24 	vec4 _texCoords = vec4(0, 0, 1, 1);
25 	vec2 _size = vec2(1, 1);
26 
27 public:
28 	///
29 	this()
30 	{
31 		_mesh = new Mesh();
32 		create();
33 	}
34 
35 	~this()
36 	{
37 		dispose();
38 	}
39 
40 	/// Returns if the mesh is valid.
41 	override @property bool valid()
42 	{
43 		return _mesh.valid;
44 	}
45 
46 	/// Property for the size of the rectangle.
47 	@property ref vec2 size()
48 	{
49 		return _size;
50 	}
51 
52 	/// Property for begin xy and end xy using a vec4 for texture coordinates.
53 	@property ref vec4 texCoords()
54 	{
55 		return _texCoords;
56 	}
57 
58 	override void dispose()
59 	{
60 		if (_mesh.valid)
61 		{
62 			_mesh.dispose();
63 		}
64 	}
65 
66 	/// Creates a new mesh after disposing the old mesh.
67 	void create()
68 	{
69 		_mesh.dispose();
70 		_mesh = new Mesh();
71 		_mesh.addVertices([vec3(0, 0, 0), vec3(_size.x, 0, 0), vec3(_size.x, _size.y, 0), vec3(0, _size.y, 0)]);
72 		_mesh.addTexCoords([vec2(_texCoords.x, _texCoords.y), vec2(_texCoords.z, _texCoords.y), vec2(_texCoords.z, _texCoords.w), vec2(_texCoords.x, _texCoords.w)]);
73 		_mesh.addIndices([0, 1, 2, 0, 2, 3]);
74 		_mesh.create();
75 	}
76 
77 	/// Sets the current transformation matrix and draws this onto the target.
78 	override void draw(IRenderTarget target, ShaderProgram shader = null)
79 	{
80 		assert(_mesh.valid, "Mesh not valid!");
81 		matrixStack.push();
82 		matrixStack.top = matrixStack.top * transform;
83 		if (texture !is null)
84 			texture.bind(0);
85 		target.draw(_mesh, shader);
86 		matrixStack.pop();
87 	}
88 
89 	///
90 	static RectangleShape create(vec2 position, vec2 size)
91 	{
92 		auto shape = new RectangleShape();
93 		shape.position = position;
94 		shape.size = size;
95 		shape.create();
96 		return shape;
97 	}
98 
99 	///
100 	static RectangleShape create(Texture texture, vec2 position, vec2 size)
101 	{
102 		auto shape = new RectangleShape();
103 		shape.texture = texture;
104 		shape.position = position;
105 		shape.size = size;
106 		shape.create();
107 		return shape;
108 	}
109 
110 	///
111 	static RectangleShape create(Texture texture, vec2 position, vec2 size, vec4 texCoords)
112 	{
113 		auto shape = new RectangleShape();
114 		shape.texture = texture;
115 		shape.position = position;
116 		shape.size = size;
117 		shape.texCoords = texCoords;
118 		shape.create();
119 		return shape;
120 	}
121 }