settings subsystem now using lua
[chaz/yoink] / src / Moof / Scene.cc
1
2 /*******************************************************************************
3
4 Copyright (c) 2009, Charles McGarvey
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9
10 * Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright notice,
13 this list of conditions and the following disclaimer in the documentation
14 and/or other materials provided with the distribution.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 *******************************************************************************/
28
29 #include <map>
30 #include <vector>
31
32 #include "Aabb.hh"
33 #include "Camera.hh"
34 #include "Entity.hh"
35 #include "Log.hh"
36 #include "Math.hh"
37 #include "Scene.hh"
38 #include "Script.hh"
39 #include "Settings.hh"
40 #include "Tilemap.hh"
41
42
43 namespace Mf {
44
45
46 static std::string getPath(const std::string& name)
47 {
48 return Resource::getPath("scenes/" + name + ".lua");
49 }
50
51
52 struct Meh
53 {
54 Matrix4 transform;
55 std::string texture;
56
57 OctreeP octree;
58
59 Meh()
60 {
61 octree = Octree::alloc(Aabb());
62 }
63
64 static int loadBox(Script& script, Aabb& aabb)
65 {
66 Script::Value table[] = {script[1], script[2]};
67
68 if (!table[0].isTable() || !table[1].isTable())
69 {
70 logWarning("wrong arguments to setPlayfieldBounds; ignoring...");
71 return 0;
72 }
73
74 for (int i = 0; i <= 1; ++i)
75 {
76 for (int j = 1; j <= 3; ++j)
77 {
78 script.push((long)j);
79 table[i].pushField();
80 }
81 }
82
83 script[3].get(aabb.min[0]);
84 script[4].get(aabb.min[1]);
85 script[5].get(aabb.min[2]);
86 script[6].get(aabb.max[0]);
87 script[7].get(aabb.max[1]);
88 script[8].get(aabb.max[2]);
89
90 return 0;
91 }
92
93 int setPlayfieldBounds(Script& script)
94 {
95 Aabb bounds;
96 return loadBox(script, bounds);
97 }
98
99 int setMaximumBounds(Script& script)
100 {
101 Aabb bounds;
102 int ret = loadBox(script, bounds);
103 octree = Octree::alloc(bounds);
104 return ret;
105 }
106
107 int resetTransform(Script& script)
108 {
109 transform.identity();
110 return 0;
111 }
112
113 int translate(Script& script)
114 {
115 Script::Value x = script[1];
116 Script::Value y = script[2];
117 Script::Value z = script[3];
118
119 if (!x.isNumber() || !y.isNumber() || !z.isNumber())
120 {
121 logWarning("wrong arguments to translate; ignoring...");
122 return 0;
123 }
124
125 Vector3 vec;
126 x.get(vec[0]);
127 y.get(vec[1]);
128 z.get(vec[2]);
129
130 Matrix4 translation;
131 cml::matrix_translation(translation, vec);
132 transform = translation * transform;
133
134 return 0;
135 }
136
137 int scale(Script& script)
138 {
139 if (script.getSize() == 3)
140 {
141 Vector3 vec;
142 script[1].get(vec[0]);
143 script[2].get(vec[1]);
144 script[3].get(vec[2]);
145
146 Matrix4 scaling;
147 cml::matrix_scale(scaling, vec);
148 transform = scaling * transform;
149 }
150 else if (script.getSize() == 1)
151 {
152 Scalar value = 1.0;
153 script[1].get(value);
154
155 Matrix4 scaling;
156 cml::matrix_uniform_scale(scaling,
157 Scalar(value));
158 transform = scaling * transform;
159 }
160 else
161 {
162 logWarning("wrong arguments to scale; ignoring...");
163 }
164
165 return 0;
166 }
167
168 int rotate(Script& script)
169 {
170 Script::Value a = script[1];
171 Script::Value d = script[2];
172
173 if (!a.isString() || !d.isNumber())
174 {
175 logWarning("wrong arguments to rotate; ignoring...");
176 return 0;
177 }
178
179 std::string axis;
180 a.get(axis);
181
182 size_t index = 0;
183 if (axis == "x") index = 0;
184 else if (axis == "y") index = 1;
185 else if (axis == "z") index = 2;
186
187 Scalar value;
188 d.get(value);
189
190 cml::matrix_rotate_about_world_axis(transform,
191 index, cml::rad(Scalar(value)));
192
193 return 0;
194 }
195
196 int setTexture(Script& script)
197 {
198 Script::Value t = script[1];
199
200 if (t.isString()) t.get(texture);
201 else logWarning("wrong arguments to setTexture; ignoring...");
202
203 return 0;
204 }
205
206 int makeTilemap(Script& script)
207 {
208 Script::Value table = script[1];
209 Script::Value top = script[-1];
210
211 if (!table.isTable())
212 {
213 logWarning("wrong arguments to makeTilemap; ignoring...");
214 return 0;
215 }
216
217 long width = 1;
218 long height = 1;
219
220 table.pushField("width");
221 top.get(width);
222
223 long nTiles = 0;
224
225 table.pushField("tiles");
226 Script::Value tiles = script.getTop();
227 nTiles = tiles.getLength();
228
229 std::vector< std::vector<Tilemap::Index> > indices;
230
231 if (nTiles % width == 0)
232 {
233 int i, w, h;
234
235 height = nTiles / width;
236 indices.resize(height);
237
238 // the indices are stored upside-down in the scene file so that they
239 // are easier to edit as text, so we'll need to load them last row
240 // first
241
242 i = 1;
243 for (h = height - 1; h >= 0; --h)
244 {
245 std::vector<Tilemap::Index> row;
246
247 for (w = 0; w < width; ++w, ++i)
248 {
249 script.checkStack(2);
250 script.push(long(i));
251 tiles.pushField();
252
253 long index;
254 top.get(index);
255
256 row.push_back(Tilemap::Index(index));
257 }
258
259 indices[h] = row;
260 }
261 }
262 else
263 {
264 logError("invalid tiles in tilemap instruction");
265 return 0;
266 }
267
268 Vector4 vertices[height+1][width+1];
269
270 Matrix4 transposedTransform = transform;
271 transposedTransform.transpose();
272
273 for (int h = 0; h <= height; ++h)
274 {
275 for (int w = 0; w <= width; ++w)
276 {
277 vertices[h][w] = Vector4(Scalar(w), Scalar(h), 0.0, 1.0) *
278 transposedTransform;
279 }
280 }
281
282 for (int h = 0; h < height; ++h)
283 {
284 for (int w = 0; w < width; ++w)
285 {
286 if (indices[h][w] == Tilemap::NO_TILE) continue;
287
288 Vector3 quadVertices[4];
289
290 demoteVector(quadVertices[0], vertices[h][w]);
291 demoteVector(quadVertices[1], vertices[h][w+1]);
292 demoteVector(quadVertices[2], vertices[h+1][w+1]);
293 demoteVector(quadVertices[3], vertices[h+1][w]);
294
295 Quad* quad = new Quad(quadVertices, texture, indices[h][w]);
296 boost::shared_ptr<Quad> quadPtr(quad);
297
298 octree->insert(quadPtr);
299 }
300 }
301
302 return 0;
303 }
304
305 int makeBillboard(Script& script)
306 {
307 Script::Value table = script[1];
308 Script::Value top = script[-1];
309
310 long index = 0;
311 long width = 1;
312 bool blending = false;
313 bool fog = false;
314
315 if (table.isTable())
316 {
317 table.pushField("tile");
318 if (top.isNumber()) top.get(index);
319
320 table.pushField("u_scale");
321 if (top.isNumber()) top.get(width);
322
323 table.pushField("blend");
324 if (top.isBoolean()) top.get(blending);
325
326 table.pushField("fog");
327 if (top.isBoolean()) top.get(fog);
328 }
329
330 Vector4 vertices[2][width+1];
331
332 Matrix4 transposedTransform = transform;
333 transposedTransform.transpose();
334
335 Scalar xf;
336 Scalar increment = 1.0 / Scalar(width);
337
338 for (int h = 0; h <= 1; ++h)
339 {
340 xf = 0.0;
341 for (int w = 0; w <= width; ++w, xf += increment)
342 {
343 vertices[h][w] = Vector4(xf, Scalar(h), 0.0, 1.0) *
344 transposedTransform;
345 }
346 }
347
348 for (int w = 0; w < width; ++w)
349 {
350 Vector3 quadVertices[4];
351
352 demoteVector(quadVertices[0], vertices[0][w]);
353 demoteVector(quadVertices[1], vertices[0][w+1]);
354 demoteVector(quadVertices[2], vertices[1][w+1]);
355 demoteVector(quadVertices[3], vertices[1][w]);
356
357 Quad* quad = new Quad(quadVertices, texture, Tilemap::Index(index));
358 quad->setBlending(blending);
359 quad->setFog(fog);
360
361 boost::shared_ptr<Quad> quadPtr(quad);
362
363 octree->insert(quadPtr);
364 }
365
366 return 0;
367 }
368 };
369
370
371 static void importScriptBindings(Script& script, Meh& scene)
372 {
373 script.importFunction("SetPlayfieldBounds",
374 boost::bind(&Meh::setPlayfieldBounds, &scene, _1));
375 script.importFunction("SetMaximumBounds",
376 boost::bind(&Meh::setMaximumBounds, &scene, _1));
377 script.importFunction("ResetTransform",
378 boost::bind(&Meh::resetTransform, &scene, _1));
379 script.importFunction("Translate",
380 boost::bind(&Meh::translate, &scene, _1));
381 script.importFunction("Scale",
382 boost::bind(&Meh::scale, &scene, _1));
383 script.importFunction("Rotate",
384 boost::bind(&Meh::rotate, &scene, _1));
385 script.importFunction("SetTexture",
386 boost::bind(&Meh::setTexture, &scene, _1));
387 script.importFunction("MakeTilemap",
388 boost::bind(&Meh::makeTilemap, &scene, _1));
389 script.importFunction("MakeBillboard",
390 boost::bind(&Meh::makeBillboard, &scene, _1));
391 }
392
393
394 OctreeP loadScene(const std::string& name)
395 {
396 std::string filePath = getPath(name);
397
398 Meh cool;
399
400 Script script;
401 script.importStandardLibraries();
402 importLogScript(script);
403 importScriptBindings(script, cool);
404
405 long detail = 3;
406 Settings::getInstance().get("detail", detail);
407
408 script.push(detail);
409 script.set("detail");
410
411 logInfo("doing file...");
412 if (script.doFile(filePath) != 0)
413 {
414 std::string str;
415 script[-1].get(str);
416 logError("lua error: %s", str.c_str());
417 }
418 logInfo("done");
419
420 cool.octree->sort();
421 return cool.octree;
422 }
423
424
425 } // namespace Mf
426
427 /** vim: set ts=4 sw=4 tw=80: *************************************************/
428
This page took 0.050604 seconds and 4 git commands to generate.