1 /* 2 Copyright (c) 2014-2015 Timur Gafarov 3 4 Boost Software License - Version 1.0 - August 17th, 2003 5 6 Permission is hereby granted, free of charge, to any person or organization 7 obtaining a copy of the software and accompanying documentation covered by 8 this license (the "Software") to use, reproduce, display, distribute, 9 execute, and transmit the Software, and to prepare derivative works of the 10 Software, and to permit third-parties to whom the Software is furnished to 11 do so, all subject to the following: 12 13 The copyright notices in the Software and this entire statement, including 14 the above license grant, this restriction and the following disclaimer, 15 must be included in all copies of the Software, in whole or in part, and 16 all derivative works of the Software, unless such copies or derivative 17 works are solely in the form of machine-executable object code generated by 18 a source language processor. 19 20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 23 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 24 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 25 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 DEALINGS IN THE SOFTWARE. 27 */ 28 29 module dgl.graphics.scene; 30 31 import std.stdio; 32 33 import dlib.core.memory; 34 import dlib.container.array; 35 import dlib.container.dict; 36 import dlib.image.color; 37 38 import dgl.core.interfaces; 39 import dgl.graphics.material; 40 import dgl.graphics.texture; 41 import dgl.graphics.lightmanager; 42 import dgl.graphics.entity; 43 import dgl.graphics.mesh; 44 import dgl.graphics.shader; 45 import dgl.asset.resman; 46 47 /* 48 * Scene class stores a number of entities together with their meshes and materials. 49 * Textures are stored separately, in ResourceManager, because textures may be shared between several Scenes. 50 * Scene is bind to ResourceManager. 51 */ 52 53 class Scene: Drawable 54 { 55 ResourceManager rm; 56 57 DynamicArray!Entity _entities; 58 DynamicArray!Mesh _meshes; 59 DynamicArray!Material _materials; 60 61 Dict!(size_t, string) entitiesByName; 62 Dict!(size_t, string) meshesByName; 63 Dict!(size_t, string) materialsByName; 64 65 bool visible = true; 66 bool lighted = true; 67 68 Entity[] entities() {return _entities.data;} 69 Mesh[] meshes() {return _meshes.data;} 70 Material[] materials() {return _materials.data;} 71 72 Entity entity(string name) 73 { 74 if (name in entitiesByName) 75 return _entities.data[entitiesByName[name]-1]; 76 else 77 return null; 78 } 79 80 Mesh mesh(string name) 81 { 82 if (name in meshesByName) 83 return _meshes.data[meshesByName[name]-1]; 84 else 85 return null; 86 } 87 88 Material material(string name) 89 { 90 if (name in materialsByName) 91 return _materials.data[materialsByName[name]-1]; 92 else 93 return null; 94 } 95 96 this(ResourceManager rm) 97 { 98 this.rm = rm; 99 createArrays(); 100 } 101 102 protected void createArrays() 103 { 104 entitiesByName = New!(Dict!(size_t, string)); 105 meshesByName = New!(Dict!(size_t, string)); 106 materialsByName = New!(Dict!(size_t, string)); 107 } 108 109 void clearArrays() 110 { 111 freeEntities(); 112 freeMeshes(); 113 freeMaterials(); 114 createArrays(); 115 } 116 117 void resolveLinks() 118 { 119 foreach(ei, e; _entities.data) 120 { 121 foreach(mi, m; _materials.data) 122 { 123 if (e.materialId == m.id) 124 { 125 e.modifier = m; 126 break; 127 } 128 } 129 130 foreach(mi, m; _meshes.data) 131 { 132 if (e.meshId == m.id) 133 { 134 e.drawable = m; 135 break; 136 } 137 } 138 } 139 140 foreach(mi, m; _meshes.data) 141 { 142 m.genFaceGroups(this); 143 } 144 } 145 146 void createDynamicLights(bool debugDraw = false) 147 { 148 foreach(i, e; _entities.data) 149 { 150 if (e.type == 1) 151 { 152 Color4f col = e.props["color"].toColor4f; 153 auto light = rm.lm.addPointLight(e.position); 154 light.debugDraw = debugDraw; 155 light.diffuseColor = col; 156 e.drawable = light; 157 } 158 } 159 } 160 161 Entity addEntity(string name, Entity e) 162 { 163 _entities.append(e); 164 entitiesByName[name] = _entities.length; 165 return e; 166 } 167 168 Mesh addMesh(string name, Mesh m) 169 { 170 _meshes.append(m); 171 meshesByName[name] = _meshes.length; 172 return m; 173 } 174 175 Material addMaterial(string name, Material m) 176 { 177 _materials.append(m); 178 materialsByName[name] = _materials.length; 179 return m; 180 } 181 182 Material getMaterialById(int id) 183 { 184 Material res = null; 185 foreach(mi, mat; _materials.data) 186 { 187 if (mat.id == id) 188 { 189 res = mat; 190 break; 191 } 192 } 193 return res; 194 } 195 196 Texture getTexture(string filename) 197 { 198 return rm.getTexture(filename); 199 } 200 201 void freeEntities() 202 { 203 foreach(i, e; _entities.data) 204 e.free(); 205 _entities.free(); 206 Delete(entitiesByName); 207 } 208 209 void freeMeshes() 210 { 211 foreach(i, m; _meshes.data) 212 m.free(); 213 _meshes.free(); 214 Delete(meshesByName); 215 } 216 217 void freeMaterials() 218 { 219 foreach(i, m; _materials.data) 220 m.free(); 221 _materials.free(); 222 Delete(materialsByName); 223 } 224 225 void setMaterialsShadeless(bool shadeless) 226 { 227 foreach(i, m; _materials.data) 228 { 229 m.shadeless = shadeless; 230 } 231 } 232 233 void setMaterialsUseTextures(bool mode) 234 { 235 foreach(i, m; _materials.data) 236 m.useTextures = mode; 237 } 238 239 void setMaterialsAmbientColor(Color4f col) 240 { 241 foreach(i, m; _materials.data) 242 { 243 m.ambientColor = col; 244 } 245 } 246 247 void setMaterialsSpecularColor(Color4f col) 248 { 249 foreach(i, m; _materials.data) 250 { 251 m.specularColor = col; 252 } 253 } 254 255 void setMaterialsShader(Shader shader) 256 { 257 foreach(i, m; _materials.data) 258 { 259 m.shader = shader; 260 } 261 } 262 263 void setMaterialsTextureSlot(uint src, uint dest) 264 { 265 foreach(i, m; _materials.data) 266 { 267 m.textures[dest] = m.textures[src]; 268 m.textures[src] = null; 269 } 270 } 271 272 void draw(double dt) 273 { 274 foreach(i, e; _entities.data) 275 { 276 if (!lighted) 277 rm.lm.lightsOn = false; 278 rm.lm.bind(e, dt); 279 e.draw(dt); 280 if (!lighted) 281 rm.lm.lightsOn = true; 282 rm.lm.unbind(e); 283 } 284 } 285 286 void free() 287 { 288 Delete(this); 289 } 290 291 ~this() 292 { 293 freeEntities(); 294 freeMeshes(); 295 freeMaterials(); 296 } 297 }