1 /** @file material.cpp  Material definition accessor.
2  *
3  * @authors Copyright © 2015 Daniel Swanson <danij@dengine.net>
4  *
5  * @par License
6  * GPL: http://www.gnu.org/licenses/gpl.html
7  *
8  * <small>This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by the
10  * Free Software Foundation; either version 2 of the License, or (at your
11  * option) any later version. This program is distributed in the hope that it
12  * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
14  * Public License for more details. You should have received a copy of the GNU
15  * General Public License along with this program; if not, see:
16  * http://www.gnu.org/licenses</small>
17  */
18 
19 #include "doomsday/defs/material.h"
20 #include "doomsday/defs/ded.h"
21 
22 #include <de/Record>
23 #include <de/RecordValue>
24 
25 using namespace de;
26 
27 namespace defn {
28 
resetToDefaults()29 void MaterialDecoration::resetToDefaults()
30 {
31     Definition::resetToDefaults();
32 
33     // Add all expected fields with their default values.
34     def().addArray("patternOffset", new ArrayValue(Vector2i()));
35     def().addArray("patternSkip", new ArrayValue(Vector2i()));
36     def().addArray("stage", new ArrayValue);
37 }
38 
addStage()39 Record &MaterialDecoration::addStage()
40 {
41     auto *stage = new Record;
42 
43     stage->addNumber("tics", 0);
44     stage->addNumber("variance", 0);                              // Time.
45     stage->addArray ("origin", new ArrayValue(Vector2f()));       // Surface-relative offset.
46     stage->addNumber("elevation", 1);                             // Distance from the surface.
47     stage->addArray ("color", new ArrayValue(Vector3f()));        // Light color. (0,0,0) means not visible during this stage.
48     stage->addNumber("radius", 1);                                // Dynamic light radius (-1 = no light).
49     stage->addArray ("lightLevels", new ArrayValue(Vector2f()));  // Fade by sector lightlevel.
50 
51     stage->addText  ("lightmapUp", "");                           // Uri. None.
52     stage->addText  ("lightmapDown", "");                         // Uri. None.
53     stage->addText  ("lightmapSide", "");                         // Uri. None.
54 
55     stage->addNumber("haloRadius", 0);                            // Halo radius (zero = no halo).
56     stage->addText  ("haloTexture", "");                          // Uri. None.
57     stage->addNumber("haloTextureIndex", 0);                      // Overrides haloTexture
58 
59     def()["stage"].array().add(new RecordValue(stage, RecordValue::OwnsRecord));
60 
61     return *stage;
62 }
63 
stageCount() const64 int MaterialDecoration::stageCount() const
65 {
66     return int(geta("stage").size());
67 }
68 
hasStage(int index) const69 bool MaterialDecoration::hasStage(int index) const
70 {
71     return index >= 0 && index < stageCount();
72 }
73 
stage(int index)74 Record &MaterialDecoration::stage(int index)
75 {
76     return *def().geta("stage")[index].as<RecordValue>().record();
77 }
78 
stage(int index) const79 Record const &MaterialDecoration::stage(int index) const
80 {
81     return *geta("stage")[index].as<RecordValue>().record();
82 }
83 
84 // ------------------------------------------------------------------------------------
85 
resetToDefaults()86 void MaterialLayer::resetToDefaults()
87 {
88     Definition::resetToDefaults();
89 
90     // Add all expected fields with their default values.
91     def().addArray("stage", new ArrayValue);
92 }
93 
addStage()94 Record &MaterialLayer::addStage()
95 {
96     auto *stage = new Record;
97 
98     stage->addText  ("texture", "");  // Uri. None.
99     stage->addNumber("tics", 0);
100     stage->addNumber("variance", 0);  // Time.
101     stage->addNumber("glowStrength", 0);
102     stage->addNumber("glowStrengthVariance", 0);
103     stage->addArray ("texOrigin", new ArrayValue(Vector2f()));
104 
105     def()["stage"].array().add(new RecordValue(stage, RecordValue::OwnsRecord));
106 
107     return *stage;
108 }
109 
stageCount() const110 int MaterialLayer::stageCount() const
111 {
112     return int(geta("stage").size());
113 }
114 
hasStage(int index) const115 bool MaterialLayer::hasStage(int index) const
116 {
117     return index >= 0 && index < stageCount();
118 }
119 
stage(int index)120 Record &MaterialLayer::stage(int index)
121 {
122     return *def().geta("stage")[index].as<RecordValue>().record();
123 }
124 
stage(int index) const125 Record const &MaterialLayer::stage(int index) const
126 {
127     return *geta("stage")[index].as<RecordValue>().record();
128 }
129 
130 // ------------------------------------------------------------------------------------
131 
resetToDefaults()132 void Material::resetToDefaults()
133 {
134     Definition::resetToDefaults();
135 
136     // Add all expected fields with their default values.
137     def().addText   (VAR_ID, "");  // URI. Unknown.
138     def().addBoolean("autoGenerated", false);
139     def().addNumber ("flags", 0);
140     def().addArray  ("dimensions", new ArrayValue(Vector2i()));
141     def().addArray  ("decoration", new ArrayValue);
142     def().addArray  ("layer", new ArrayValue);
143 }
144 
addDecoration()145 Record &Material::addDecoration()
146 {
147     auto *decor = new Record;
148     MaterialDecoration(*decor).resetToDefaults();
149     def()["decoration"].array().add(new RecordValue(decor, RecordValue::OwnsRecord));
150     return *decor;
151 }
152 
decorationCount() const153 int Material::decorationCount() const
154 {
155     return int(geta("decoration").size());
156 }
157 
hasDecoration(int index) const158 bool Material::hasDecoration(int index) const
159 {
160     return index >= 0 && index < decorationCount();
161 }
162 
decoration(int index)163 Record &Material::decoration(int index)
164 {
165     return *def().geta("decoration")[index].as<RecordValue>().record();
166 }
167 
decoration(int index) const168 Record const &Material::decoration(int index) const
169 {
170     return *geta("decoration")[index].as<RecordValue>().record();
171 }
172 
addLayer()173 Record &Material::addLayer()
174 {
175     auto *layer = new Record;
176     MaterialLayer(*layer).resetToDefaults();
177     def()["layer"].array().add(new RecordValue(layer, RecordValue::OwnsRecord));
178     return *layer;
179 }
180 
layerCount() const181 int Material::layerCount() const
182 {
183     return int(geta("layer").size());
184 }
185 
hasLayer(int index) const186 bool Material::hasLayer(int index) const
187 {
188     return index >= 0 && index < layerCount();
189 }
190 
layer(int index)191 Record &Material::layer(int index)
192 {
193     return *def().geta("layer")[index].as<RecordValue>().record();
194 }
195 
layer(int index) const196 Record const &Material::layer(int index) const
197 {
198     return *geta("layer")[index].as<RecordValue>().record();
199 }
200 
201 } // namespace defn
202