1 /*
2 DSFML - The Simple and Fast Multimedia Library for D
3 
4 Copyright (c) 2013 - 2015 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 use of this software.
8 
9 Permission is granted to anyone to use this software for any purpose, including commercial applications,
10 and to alter it and redistribute it freely, subject to the following restrictions:
11 
12 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software.
13 If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
14 
15 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
16 
17 3. This notice may not be removed or altered from any source distribution
18 */
19 
20 module dsfml.graphics.renderstates;
21 
22 import dsfml.graphics.blendmode;
23 import dsfml.graphics.transform;
24 import dsfml.graphics.texture;
25 import dsfml.graphics.shader;
26 import std.typecons:Rebindable;
27 
28 /++
29  + Define the states used for drawing to a RenderTarget.
30  + 
31  + There are four global states that can be applied to the drawn objects:
32  + - the blend mode: how pixels of the object are blended with the background
33  + - the transform: how the object is positioned/rotated/scaled
34  + - the texture: what image is mapped to the object
35  + - the shader: what custom effect is applied to the object
36  + 
37  + High-level objects such as sprites or text force some of these states when they are drawn. For example, a sprite will set its own texture, so that you don't have to care about it when drawing the sprite.
38  + 
39  + The transform is a special case: sprites, texts and shapes (and it's a good idea to do it with your own drawable classes too) combine their transform with the one that is passed in the RenderStates structure. So that you can use a "global" transform on top of each object's transform.
40  + 
41  + Most objects, especially high-level drawables, can be drawn directly without defining render states explicitely – the default set of states is ok in most cases.
42  + 
43  + If you want to use a single specific render state, for example a shader, you can pass it directly to the Draw function: RenderStates has an implicit one-argument constructor for each state.
44  + 
45  + When you're inside the Draw function of a drawable object (inherited from sf::Drawable), you can either pass the render states unmodified, or change some of them. For example, a transformable object will combine the current transform with its own transform. A sprite will set its texture. Etc.
46  + 
47  + Authors: Laurent Gomila, Jeremy DeHaan
48  + See_Also: http://www.sfml-dev.org/documentation/2.0/classsf_1_1RenderStates.php#details
49  +/
50 struct RenderStates
51 {
52 	BlendMode blendMode;
53 	Transform transform;
54 	private
55 	{
56 		Rebindable!(const(Texture)) m_texture;
57 		Rebindable!(const(Shader)) m_shader;
58 	}
59 
60 	this(BlendMode theBlendMode)
61 	{
62 		blendMode = theBlendMode;
63 		transform = Transform();
64 
65 		m_texture = emptyTexture;
66 		m_shader = emptyShader;
67 
68 	}
69 
70 	this(Transform theTransform)
71 	{
72 		transform = theTransform;
73 
74 		blendMode = BlendMode.Alpha;
75 
76 		m_texture = emptyTexture;
77 		m_shader = emptyShader;
78 	}
79 
80 	this(const(Texture) theTexture)
81 	{
82 		if(theTexture !is null)
83 		{
84 			
85 			m_texture = theTexture;
86 		}
87 		else
88 		{
89 			m_texture = emptyTexture;
90 		}
91 
92 		blendMode = BlendMode.Alpha;
93 
94 		transform = Transform();
95 		m_shader = emptyShader;
96 	}
97 
98 	this(const(Shader) theShader)
99 	{
100 		if(theShader !is null)
101 		{
102 			m_shader = theShader;
103 		}
104 		else
105 		{
106 			m_shader = emptyShader;
107 		}
108 	}
109 
110 	this(BlendMode theBlendMode, Transform theTransform, const(Texture) theTexture, const(Shader) theShader)
111 	{
112 		blendMode = theBlendMode;
113 		transform = theTransform;
114 		if(theTexture !is null)
115 		{
116 			
117 			m_texture = theTexture;
118 		}
119 		else
120 		{
121 			m_texture = emptyTexture;
122 		}
123 		if(theShader !is null)
124 		{
125 			m_shader = theShader;
126 		}
127 		else
128 		{
129 			m_shader = emptyShader;
130 		}
131 	}
132 
133 	/// The shader to apply while rendering.
134 	@property
135 	{
136 		const(Shader) shader(const(Shader) theShader)
137 		{
138 			if(theShader !is null)
139 			{
140 				m_shader = theShader;
141 			}
142 			else
143 			{
144 				m_shader = emptyShader;
145 			}
146 			return theShader;
147 		}
148 		const(Shader) shader()
149 		{
150 			return m_shader;
151 		}
152 	}
153 
154 	/// The texture to apply while rendering.
155 	@property
156 	{
157 		const(Texture) texture(const(Texture) theTexture)
158 		{
159 			if(theTexture !is null)
160 			{
161 				
162 				m_texture = theTexture;
163 			}
164 			else
165 			{
166 				m_texture = emptyTexture;
167 			}
168 			return theTexture;
169 		}
170 		const(Texture) texture()
171 		{
172 			return m_texture;
173 		}
174 	}
175 
176 	/// A default, empty render state.
177 	@property
178 	static RenderStates Default()
179 	{
180 		RenderStates temp;//make a static variable?
181 
182 		temp.m_texture = emptyTexture;
183 		temp.m_shader = emptyShader;
184 
185 		return temp;
186 	}
187 
188 	//Creates empty an epty texture and shader for continuous use to prevent
189 	//creating them on the fly
190 	package static Texture emptyTexture;
191 	package static Shader emptyShader;
192 
193 	private static this()
194 	{
195 		emptyTexture = new Texture();
196 		emptyShader = new Shader();
197 	}
198 }