2 /*******************************************************************************
4 Copyright (c) 2009, Charles McGarvey
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
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.
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.
27 *******************************************************************************/
39 #include "Settings.hh"
46 static std::string
getPath(const std::string
& name
)
48 return Resource::getPath("scenes/" + name
+ ".lua");
68 octree
= Octree::alloc(Aabb());
71 static int loadBox(Script
& script
, Aabb
& aabb
)
73 Script::Value table
[] = {script
[1], script
[2]};
75 if (!table
[0].isTable() || !table
[1].isTable())
77 logWarning("wrong arguments to setPlayfieldBounds; ignoring...");
81 for (int i
= 0; i
<= 1; ++i
)
83 for (int j
= 1; j
<= 3; ++j
)
90 script
[3].get(aabb
.min
[0]);
91 script
[4].get(aabb
.min
[1]);
92 script
[5].get(aabb
.min
[2]);
93 script
[6].get(aabb
.max
[0]);
94 script
[7].get(aabb
.max
[1]);
95 script
[8].get(aabb
.max
[2]);
100 int setPlayfieldBounds(Script
& script
)
103 return loadBox(script
, bounds
);
106 int setMaximumBounds(Script
& script
)
109 int ret
= loadBox(script
, bounds
);
110 octree
= Octree::alloc(bounds
);
114 int resetTransform(Script
& script
)
116 transform
.identity();
120 int translate(Script
& script
)
122 Script::Value x
= script
[1].requireNumber();
123 Script::Value y
= script
[2].requireNumber();
124 Script::Value z
= script
[3].requireNumber();
132 cml::matrix_translation(translation
, vec
);
133 transform
= translation
* transform
;
138 int scale(Script
& script
)
140 if (script
.getSize() == 3)
143 script
[1].requireNumber().get(vec
[0]);
144 script
[2].requireNumber().get(vec
[1]);
145 script
[3].requireNumber().get(vec
[2]);
148 cml::matrix_scale(scaling
, vec
);
149 transform
= scaling
* transform
;
151 else if (script
.getSize() == 1)
154 script
[1].requireNumber().get(value
);
157 cml::matrix_uniform_scale(scaling
, value
);
158 transform
= scaling
* transform
;
162 script
.getTop().throwError("wrong number of arguments");
168 int rotate(Script
& script
)
170 Script::Value axis
= script
[1].requireString();
171 Script::Value angle
= script
[2].requireNumber();
179 cml::matrix_rotate_about_world_axis(transform
, index
, cml::rad(value
));
184 int setTexture(Script
& script
)
186 Script::Value name
= script
[1].requireString();
193 int makeTilemap(Script
& script
)
195 Script::Value table
= script
[1].requireTable();
196 Script::Value top
= script
[-1];
201 table
.pushField("width");
206 table
.pushField("tiles");
207 Script::Value tiles
= script
.getTop();
208 nTiles
= tiles
.getLength();
210 if (nTiles
% width
!= 0) table
.throwError("invalid number of tiles");
212 std::vector
< std::vector
<Tilemap::Index
> > indices
;
216 height
= nTiles
/ width
;
217 indices
.resize(height
);
219 // the indices are stored upside-down in the scene file so that they
220 // are easier to edit as text, so we'll need to load them last row
224 for (h
= height
- 1; h
>= 0; --h
)
226 std::vector
<Tilemap::Index
> row
;
228 for (w
= 0; w
< width
; ++w
, ++i
)
230 script
.checkStack(2);
231 script
.push(long(i
));
237 row
.push_back(Tilemap::Index(index
));
243 Vector4 vertices
[height
+1][width
+1];
245 Matrix4 transposedTransform
= transform
;
246 transposedTransform
.transpose();
248 for (int h
= 0; h
<= height
; ++h
)
250 for (int w
= 0; w
<= width
; ++w
)
252 vertices
[h
][w
] = Vector4(Scalar(w
), Scalar(h
), 0.0, 1.0) *
257 for (int h
= 0; h
< height
; ++h
)
259 for (int w
= 0; w
< width
; ++w
)
261 if (indices
[h
][w
] == Tilemap::NO_TILE
) continue;
263 Vector3 quadVertices
[4];
265 demoteVector(quadVertices
[0], vertices
[h
][w
]);
266 demoteVector(quadVertices
[1], vertices
[h
][w
+1]);
267 demoteVector(quadVertices
[2], vertices
[h
+1][w
+1]);
268 demoteVector(quadVertices
[3], vertices
[h
+1][w
]);
270 Quad
* quad
= new Quad(quadVertices
, texture
, indices
[h
][w
]);
271 boost::shared_ptr
<Quad
> quadPtr(quad
);
273 octree
->insert(quadPtr
);
280 int makeBillboard(Script
& script
)
282 Script::Value table
= script
[1];
283 Script::Value top
= script
[-1];
287 bool blending
= false;
292 table
.pushField("tile");
295 table
.pushField("u_scale");
298 table
.pushField("blend");
301 table
.pushField("fog");
305 Vector4 vertices
[2][width
+1];
307 Matrix4 transposedTransform
= transform
;
308 transposedTransform
.transpose();
311 Scalar increment
= 1.0 / Scalar(width
);
313 for (int h
= 0; h
<= 1; ++h
)
316 for (int w
= 0; w
<= width
; ++w
, xf
+= increment
)
318 vertices
[h
][w
] = Vector4(xf
, Scalar(h
), 0.0, 1.0) *
323 for (int w
= 0; w
< width
; ++w
)
325 Vector3 quadVertices
[4];
327 demoteVector(quadVertices
[0], vertices
[0][w
]);
328 demoteVector(quadVertices
[1], vertices
[0][w
+1]);
329 demoteVector(quadVertices
[2], vertices
[1][w
+1]);
330 demoteVector(quadVertices
[3], vertices
[1][w
]);
332 Quad
* quad
= new Quad(quadVertices
, texture
, Tilemap::Index(index
));
333 quad
->setBlending(blending
);
336 boost::shared_ptr
<Quad
> quadPtr(quad
);
338 octree
->insert(quadPtr
);
346 static void importSceneBindings(Script
& script
, Meh
& scene
)
348 script
.importFunction("SetPlayfieldBounds",
349 boost::bind(&Meh::setPlayfieldBounds
, &scene
, _1
));
350 script
.importFunction("SetMaximumBounds",
351 boost::bind(&Meh::setMaximumBounds
, &scene
, _1
));
352 script
.importFunction("ResetTransform",
353 boost::bind(&Meh::resetTransform
, &scene
, _1
));
354 script
.importFunction("Translate",
355 boost::bind(&Meh::translate
, &scene
, _1
));
356 script
.importFunction("Scale",
357 boost::bind(&Meh::scale
, &scene
, _1
));
358 script
.importFunction("Rotate",
359 boost::bind(&Meh::rotate
, &scene
, _1
));
360 script
.importFunction("SetTexture",
361 boost::bind(&Meh::setTexture
, &scene
, _1
));
362 script
.importFunction("MakeTilemap",
363 boost::bind(&Meh::makeTilemap
, &scene
, _1
));
364 script
.importFunction("MakeBillboard",
365 boost::bind(&Meh::makeBillboard
, &scene
, _1
));
368 Settings::getInstance().get("detail", detail
);
370 script
.set("detail");
372 script
.push(Quad::LEFT
);
374 script
.push(Quad::RIGHT
);
376 script
.push(Quad::TOP
);
388 OctreeP
loadScene(const std::string
& name
)
390 std::string filePath
= getPath(name
);
395 script
.importStandardLibraries();
396 importLogScript(script
);
397 importSceneBindings(script
, cool
);
399 if (script
.doFile(filePath
) != Script::SUCCESS
)
403 logScript("%s", str
.c_str());
413 /** vim: set ts=4 sw=4 tw=80: *************************************************/