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 }