2
* Copyright (C) 2002,2003,2005 Daniel Heck
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public License
6
* as published by the Free Software Foundation; either version 2
7
* of the License, or (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License along
15
* with this program; if not, write to the Free Software Foundation, Inc.,
16
* 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
18
* $Id: d_models.cc,v 1.21 2004/05/27 20:30:42 dheck Exp $
21
#include "display_internal.hh"
22
#include "d_models.hh"
26
#include "d_engine.hh"
30
#include "SDL_image.h"
35
using namespace enigma;
36
using namespace display;
45
#include "global-lua.hh"
46
#include "display-lua.hh"
47
#include "enigma-lua.hh"
50
/* -------------------- Types -------------------- */
54
class SurfaceCache_Alpha : public PtrCache<Surface>{
56
Surface *acquire(const std::string &name);
59
class SurfaceCache : public PtrCache<Surface>{
61
Surface *acquire(const std::string &name);
69
void define (const std::string name, Model *m);
71
/* Create new model of type `name'. Returns 0 if no such
73
Model *create (const std::string &name);
75
/* Remove model definition for `name'. */
76
void remove (const std::string &name);
78
bool has_model (const std::string &name) const;
80
size_t num_templates() const;
84
typedef px::Dict<Model*> ModelMap;
90
/* -------------------- SurfaceCache -------------------- */
92
Surface *SurfaceCache_Alpha::acquire(const std::string &name)
95
if (file::FindImageFile (name + ".png", filename))
96
return px::LoadImage(filename.c_str());
102
Surface *SurfaceCache::acquire(const std::string &name)
105
if (file::FindImageFile (name + ".png", filename)) {
106
SDL_Surface *s = IMG_Load(filename.c_str());
108
SDL_Surface *img = 0;
109
if (s->flags & SDL_SRCALPHA) {
110
img = SDL_DisplayFormatAlpha(s);
112
SDL_SetColorKey(s, SDL_SRCCOLORKEY, //|SDL_RLEACCEL,
113
SDL_MapRGB(s->format, 255,0,255));
114
img = SDL_DisplayFormat(s);
118
return Surface::make_surface(img);
120
return Surface::make_surface(s);
127
/* -------------------- ModelManager -------------------- */
129
ModelManager::ModelManager()
133
ModelManager::~ModelManager() {
134
delete_map (m_templates.begin(), m_templates.end());
137
void ModelManager::define (const std::string name, Model *m) {
138
m_templates.insert (name, m);
141
Model * ModelManager::create (const std::string &name) {
142
ModelMap::iterator i = m_templates.find(name);
144
if (i != m_templates.end())
145
return i->second->clone();
150
void ModelManager::remove (const std::string &name)
152
ModelMap::iterator i = m_templates.find(name);
153
if (i != m_templates.end()) {
155
m_templates.remove (name);
159
bool ModelManager::has_model (const std::string &name) const {
160
return m_templates.has_key (name);
163
size_t ModelManager::num_templates() const {
164
return m_templates.size();
169
/* -------------------- Variables -------------------- */
173
SurfaceCache surface_cache;
174
SurfaceCache_Alpha surface_cache_alpha;
175
ModelManager *modelmgr = 0;
176
vector<Surface *> image_pile;
177
string anim_templ_name;
178
Anim2d *anim_templ = 0;
182
/* -------------------- Functions -------------------- */
184
void display::InitModels()
186
modelmgr = new ModelManager;
188
lua_State *L = lua_open(0);
191
lua_register (L, "FindDataFile", lua::FindDataFile);
193
tolua_global_open(L);
194
tolua_enigma_open(L);
195
tolua_display_open(L);
200
const video::VMInfo *vminfo = video::GetInfo();
201
fname = enigma::FindDataFile (vminfo->initscript);
202
if (lua_dofile (L, fname.c_str()) != 0) {
203
fprintf (stderr, "Error loading '%s'\n", fname.c_str());
205
enigma::Log << "# models: " << modelmgr->num_templates() << endl;
206
// enigma::Log << "# images: " << surface_cache.size() << endl;
208
surface_cache_alpha.clear();
211
void display::ShutdownModels()
214
surface_cache.clear();
215
delete_sequence (image_pile.begin(), image_pile.end());
217
anim_templ_name = "";
221
Surface *display::CropSurface (const Surface *s, Rect r) {
222
return px::Grab(s, r);
225
/* Register a new model template `m' under the name `name'. */
226
void display::DefineModel (const char *name, Model *m)
228
if (modelmgr->has_model (name)) {
229
enigma::Log << "Redefining model '" << name << "'\n";
230
modelmgr->remove (name);
232
modelmgr->define (name, m);
235
Model * display::MakeModel (const string &name)
237
if (Model *m = modelmgr->create (name))
240
enigma::Log << "Unknown model " << name << endl;
241
return modelmgr->create ("dummy");
245
int display::DefineImage(const char *name, const char *fname,
246
int xoff, int yoff, int padding)
248
px::Surface *sfc = surface_cache.get(fname);
252
px::Rect r = sfc->size();
253
r.x += padding; r.y += padding;
254
r.w -= 2*padding; r.h -= 2*padding;
255
DefineModel(name, new ImageModel(sfc, r, xoff+padding, yoff+padding));
259
void display::DefineImageModel (const char *name, px::Surface *s)
261
DefineModel (name, new ImageModel(s, 0, 0));
264
int display::DefineSubImage(const char *name, const char *fname,
265
int xoff, int yoff, px::Rect subrect)
267
px::Surface *sfc = surface_cache.get(fname);
271
DefineModel(name, new ImageModel(sfc, subrect, xoff, yoff));
275
void display::DefineRandModel(const char *name, int n, const char **names)
277
RandomModel *m = new RandomModel();
278
for (int i=0; i<n; i++)
279
m->add_model(names[i]);
280
DefineModel(name, m);
283
void display::DefineShadedModel (const char *name, const char *model, const char *shadow)
285
DefineModel(name, new ShadowModel(MakeModel(model), MakeModel(shadow)));
289
/* Create an image by overlaying several other images. The first entry in
290
`images' is the name of the background image, the following images are
291
drawn on top of it. */
292
void display::DefineOverlayImage (const char *name, int n,
295
Surface *sfc = Duplicate(surface_cache.get(images[0]));
298
for (int i=1; i<n; i++)
299
blit (gc, 0,0, surface_cache_alpha.get(images[i]));
300
DefineModel(name, new ImageModel(sfc, 0,0));
301
image_pile.push_back(sfc); // make sure it gets destructed
305
void display::DefineComposite (const char *name, const char *bgname, const char *fgname)
307
DefineModel(name, new CompositeModel(MakeModel(bgname), MakeModel(fgname)));
310
void display::DefineAnim (const char *name, bool loop_p) {
311
anim_templ = new Anim2d(loop_p);
312
DefineModel(name, anim_templ);
313
anim_templ_name = name;
316
void display::AddFrame (const char *name, const char *model, double time)
318
if (anim_templ_name != name)
319
fprintf(stderr, "AddFrame: Cannot add frames to completed animations.");
321
anim_templ->add_frame(MakeModel(model), time / 1000.0);
324
void display::DefineAlias (const char *name, const char *othername)
326
DefineModel(name, new AliasModel(othername));
331
/* -------------------- Model -------------------- */
332
void Model::get_extension (px::Rect &r)
337
/* -------------------- Image -------------------- */
339
Image::Image(px::Surface *sfc)
340
: surface(sfc), rect(surface->size()), refcount(1)
343
Image::Image(px::Surface *sfc, const px::Rect &r)
344
: surface(sfc), rect(r), refcount(1)
348
void display::incref(Image *i) {
352
void display::decref (Image *i) {
353
if (-- i->refcount == 0) {
359
void display::draw_image (Image *i, px::GC &gc, int x, int y)
361
blit(gc, x, y, i->surface, i->rect);
364
/* -------------------- ImageModel -------------------- */
366
ImageModel::ImageModel (Image *i, int xo, int yo)
367
: image(i), xoff(xo), yoff(yo)
373
ImageModel::ImageModel(Surface *s, int xo, int yo)
374
: image(new Image(s)), xoff(xo), yoff(yo)
377
ImageModel::ImageModel(Surface *s, const px::Rect &r, int xo, int yo)
378
: image(new Image(s, r)), xoff(xo), yoff(yo)
381
ImageModel::~ImageModel() {
385
void ImageModel::draw(px::GC &gc, int x, int y) {
386
draw_image (image, gc, x+xoff, y+yoff);
389
Model *ImageModel::clone() {
390
return new ImageModel(image, xoff, yoff);
393
void ImageModel::get_extension (px::Rect &r) {
400
/* -------------------- ShadowModel -------------------- */
402
ShadowModel::ShadowModel (Model *m, Model *sh) {
406
ShadowModel::~ShadowModel() {
407
delete model; delete shade;
410
void ShadowModel::expose (ModelLayer *ml, int vx, int vy) {
411
model->expose(ml, vx, vy);
412
shade->expose(ml, vx, vy);
414
void ShadowModel::remove (ModelLayer *ml) {
419
void ShadowModel::set_callback(ModelCallback *cb) {
420
model->set_callback(cb);
423
void ShadowModel::reverse() {
428
void ShadowModel::restart() {
433
void ShadowModel::draw(px::GC &gc, int x, int y) {
437
void ShadowModel::draw_shadow(px::GC &gc, int x, int y) {
441
Model *ShadowModel::get_shadow() const {
445
Model *ShadowModel::clone() {
446
return new ShadowModel(model->clone(), shade->clone());
449
void ShadowModel::get_extension (px::Rect &r) {
451
model->get_extension (r1);
452
shade->get_extension (r2);
453
r = boundingbox (r1, r2);
456
/* -------------------- RandomModel -------------------- */
458
Model * RandomModel::clone() {
459
if (!modelnames.empty()) {
460
int r = enigma::IntegerRand(0, modelnames.size()-1);
461
return MakeModel(modelnames[r]);
463
fprintf(stderr, "display_2d.cc: empty RandomModel\n");
468
/* -------------------- AliasModel -------------------- */
470
Model * AliasModel::clone() {
471
return MakeModel(name);
474
/* -------------------- Anim2d -------------------- */
476
Anim2d::Anim2d(bool loop)
477
: rep(new AnimRep(loop))
480
Anim2d::Anim2d (AnimRep *r)
481
: rep(r), curframe(0), frametime(0),
485
videox (0), videoy (0),
489
frametime = 0; // enigma::DoubleRand (0, 0.02);
493
if (--rep->refcount == 0)
497
void Anim2d::restart () {
498
finishedp = false; frametime = 0; curframe = 0; changedp = true;
501
void Anim2d::add_frame(Model *m, double duration) {
502
rep->frames.push_back(new AnimFrame(m, duration));
505
void Anim2d::draw(px::GC &gc, int x, int y)
508
AnimFrame *f =rep->frames[curframe];
509
f->model->draw(gc,x,y);
514
void Anim2d::draw_shadow (px::GC &gc, int x, int y)
517
AnimFrame *f =rep->frames[curframe];
518
f->model->draw_shadow(gc,x,y);
522
void Anim2d::expose (ModelLayer *ml, int vx, int vy) {
528
void Anim2d::remove (ModelLayer *ml) {
529
ml->deactivate (this);
532
bool Anim2d::has_changed (Rect &r) {
533
bool retval = changedp;
542
void Anim2d::move (int newx, int newy) {
547
void Anim2d::get_extension (px::Rect &r) {
548
AnimFrame *f =rep->frames[curframe];
549
f->model->get_extension (r);
552
void Anim2d::tick (double dtime)
554
assert(curframe < rep->frames.size());
556
double framedur = rep->frames[curframe]->duration;
558
if (frametime >= framedur) {
559
frametime -= framedur;
566
curframe = rep->frames.size()-1;
571
if (curframe+1 < rep->frames.size())
578
if (finishedp && callback!=0)
583
/* -------------------- Functions -------------------- */
587
Surface *GetSurface (const std::string &filename)
589
return surface_cache.get(filename);
592
void RegisterImage (const std::string &name, Image *img)
596
Image *LookupImage (const std::string &name)