~ubuntu-branches/ubuntu/intrepid/enigma/intrepid

« back to all changes in this revision

Viewing changes to src/d_models.cc

  • Committer: Bazaar Package Importer
  • Author(s): Erich Schubert
  • Date: 2005-08-28 15:30:09 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20050828153009-sky64kb6tcq37xt5
Tags: 0.92.1-1
* New upstream subversion checkout
* Remove menu.s3m, which we are allowed to distributed but not to modify
  also copyright notice is confusing... (Closes: #321669)
* Rebuild with new libzipios (Closes: #325405)
  I hope this works without a versioned build-dependency
* Added "enigma replaces enigma-data" for upgrades (Closes: #308558)
* Added notes about the fonts copyright.
* updated to policy 3.6.2.1 (no changes)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2002,2003,2005 Daniel Heck
3
 
 *
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.
8
 
 *  
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.
13
 
 *
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.
17
 
 *
18
 
 * $Id: d_models.cc,v 1.21 2004/05/27 20:30:42 dheck Exp $
19
 
 */
20
 
 
21
 
#include "display_internal.hh"
22
 
#include "d_models.hh"
23
 
 
24
 
#include "lua.hh"
25
 
#include "options.hh"
26
 
#include "d_engine.hh"
27
 
#include "video.hh"
28
 
#include "main.hh"
29
 
 
30
 
#include "SDL_image.h"
31
 
 
32
 
#include <cstdio>
33
 
#include <iostream>
34
 
 
35
 
using namespace enigma;
36
 
using namespace display;
37
 
using namespace std;
38
 
using namespace px;
39
 
 
40
 
 
41
 
extern "C" {
42
 
#include "lualib.h"
43
 
#include "tolua.h"
44
 
}
45
 
#include "global-lua.hh"
46
 
#include "display-lua.hh"
47
 
#include "enigma-lua.hh"
48
 
#include "px-lua.hh"
49
 
 
50
 
/* -------------------- Types -------------------- */
51
 
 
52
 
namespace
53
 
{
54
 
    class SurfaceCache_Alpha : public PtrCache<Surface>{
55
 
    public:
56
 
        Surface *acquire(const std::string &name);
57
 
    };
58
 
 
59
 
    class SurfaceCache : public PtrCache<Surface>{
60
 
    public:
61
 
        Surface *acquire(const std::string &name);
62
 
    };
63
 
 
64
 
    class ModelManager {
65
 
    public:
66
 
        ModelManager();
67
 
        ~ModelManager();
68
 
 
69
 
        void define (const std::string name, Model *m);
70
 
 
71
 
        /* Create new model of type `name'.  Returns 0 if no such
72
 
           model exists. */
73
 
        Model *create (const std::string &name);
74
 
        
75
 
        /* Remove model definition for `name'. */
76
 
        void remove (const std::string &name);
77
 
 
78
 
        bool has_model (const std::string &name) const;
79
 
 
80
 
        size_t num_templates() const;
81
 
 
82
 
    private:
83
 
        // Variables
84
 
        typedef px::Dict<Model*> ModelMap;
85
 
        ModelMap m_templates;
86
 
    };
87
 
}
88
 
 
89
 
 
90
 
/* -------------------- SurfaceCache -------------------- */
91
 
 
92
 
Surface *SurfaceCache_Alpha::acquire(const std::string &name) 
93
 
{
94
 
    string filename;
95
 
    if (file::FindImageFile (name + ".png", filename))
96
 
        return px::LoadImage(filename.c_str());
97
 
    else
98
 
        return 0;
99
 
}
100
 
 
101
 
 
102
 
Surface *SurfaceCache::acquire(const std::string &name) 
103
 
{
104
 
    string filename;
105
 
    if (file::FindImageFile (name + ".png", filename)) {
106
 
        SDL_Surface *s = IMG_Load(filename.c_str());
107
 
        if (s) {
108
 
            SDL_Surface *img = 0;
109
 
            if (s->flags & SDL_SRCALPHA) {
110
 
                img = SDL_DisplayFormatAlpha(s);
111
 
            } else {
112
 
                SDL_SetColorKey(s, SDL_SRCCOLORKEY, //|SDL_RLEACCEL, 
113
 
                                SDL_MapRGB(s->format, 255,0,255));
114
 
                img = SDL_DisplayFormat(s);
115
 
            }
116
 
            if (img) {
117
 
                SDL_FreeSurface(s);
118
 
                return Surface::make_surface(img);
119
 
            }
120
 
            return Surface::make_surface(s);
121
 
        }
122
 
    }
123
 
    return 0;
124
 
}
125
 
 
126
 
 
127
 
/* -------------------- ModelManager -------------------- */
128
 
 
129
 
ModelManager::ModelManager()
130
 
: m_templates (1069)
131
 
{}
132
 
 
133
 
ModelManager::~ModelManager() {
134
 
    delete_map (m_templates.begin(), m_templates.end());
135
 
}
136
 
 
137
 
void ModelManager::define (const std::string name, Model *m) {
138
 
    m_templates.insert (name, m);
139
 
}
140
 
 
141
 
Model * ModelManager::create (const std::string &name) {
142
 
    ModelMap::iterator i = m_templates.find(name);
143
 
 
144
 
    if (i != m_templates.end())
145
 
        return i->second->clone();
146
 
    else 
147
 
        return 0;
148
 
}
149
 
 
150
 
void ModelManager::remove (const std::string &name) 
151
 
{
152
 
    ModelMap::iterator i = m_templates.find(name);
153
 
    if (i != m_templates.end()) {
154
 
        delete i->second;
155
 
        m_templates.remove (name);
156
 
    }
157
 
}
158
 
 
159
 
bool ModelManager::has_model (const std::string &name) const { 
160
 
    return m_templates.has_key (name); 
161
 
}
162
 
        
163
 
size_t ModelManager::num_templates() const { 
164
 
    return m_templates.size(); 
165
 
}
166
 
 
167
 
 
168
 
 
169
 
/* -------------------- Variables -------------------- */
170
 
 
171
 
namespace
172
 
{
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;
179
 
}
180
 
 
181
 
 
182
 
/* -------------------- Functions -------------------- */
183
 
 
184
 
void display::InitModels() 
185
 
{
186
 
    modelmgr = new ModelManager;
187
 
 
188
 
    lua_State *L = lua_open(0);
189
 
    lua_baselibopen (L);
190
 
    lua_strlibopen(L);
191
 
    lua_register (L, "FindDataFile", lua::FindDataFile);
192
 
    tolua_open(L);
193
 
    tolua_global_open(L);
194
 
    tolua_enigma_open(L);
195
 
    tolua_display_open(L);
196
 
    tolua_px_open(L);
197
 
 
198
 
    string fname;
199
 
 
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());
204
 
    }
205
 
    enigma::Log << "# models: " << modelmgr->num_templates() << endl;
206
 
//     enigma::Log << "# images: " << surface_cache.size() << endl;
207
 
 
208
 
    surface_cache_alpha.clear();
209
 
}
210
 
 
211
 
void display::ShutdownModels() 
212
 
{
213
 
    delete modelmgr;
214
 
    surface_cache.clear();
215
 
    delete_sequence (image_pile.begin(), image_pile.end());
216
 
    image_pile.clear();
217
 
    anim_templ_name = "";
218
 
    anim_templ = 0;
219
 
}
220
 
 
221
 
Surface *display::CropSurface (const Surface *s, Rect r) {
222
 
    return px::Grab(s, r);
223
 
}
224
 
 
225
 
/* Register a new model template `m' under the name `name'. */
226
 
void display::DefineModel (const char *name, Model *m) 
227
 
{
228
 
    if (modelmgr->has_model (name)) {
229
 
        enigma::Log << "Redefining model '" << name << "'\n";
230
 
        modelmgr->remove (name);
231
 
    }
232
 
    modelmgr->define (name, m);
233
 
}
234
 
 
235
 
Model * display::MakeModel (const string &name) 
236
 
{
237
 
    if (Model *m = modelmgr->create (name))
238
 
        return m;
239
 
    else {
240
 
        enigma::Log << "Unknown model " << name << endl;
241
 
        return modelmgr->create ("dummy");
242
 
    }
243
 
}
244
 
 
245
 
int display::DefineImage(const char *name, const char *fname,
246
 
                         int xoff, int yoff, int padding)
247
 
{
248
 
    px::Surface *sfc = surface_cache.get(fname);
249
 
    if (!sfc)
250
 
        return 1;
251
 
 
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));
256
 
    return 0;
257
 
}
258
 
 
259
 
void display::DefineImageModel (const char *name, px::Surface *s)
260
 
{
261
 
    DefineModel (name, new ImageModel(s, 0, 0));
262
 
}
263
 
 
264
 
int display::DefineSubImage(const char *name, const char *fname,
265
 
                             int xoff, int yoff, px::Rect subrect)
266
 
{
267
 
    px::Surface *sfc = surface_cache.get(fname);
268
 
    if (!sfc)
269
 
        return 1;
270
 
    
271
 
    DefineModel(name, new ImageModel(sfc, subrect, xoff, yoff));
272
 
    return 0;
273
 
}
274
 
 
275
 
void display::DefineRandModel(const char *name, int n, const char **names)
276
 
{
277
 
    RandomModel *m = new RandomModel();
278
 
    for (int i=0; i<n; i++) 
279
 
        m->add_model(names[i]);
280
 
    DefineModel(name, m);
281
 
}
282
 
 
283
 
void display::DefineShadedModel (const char *name, const char *model, const char *shadow)
284
 
{
285
 
    DefineModel(name, new ShadowModel(MakeModel(model), MakeModel(shadow)));
286
 
}
287
 
 
288
 
 
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, 
293
 
                                  const char **images)
294
 
{
295
 
    Surface *sfc = Duplicate(surface_cache.get(images[0]));
296
 
    if (sfc) {
297
 
        GC gc(sfc);
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
302
 
    }
303
 
}
304
 
 
305
 
void display::DefineComposite (const char *name, const char *bgname, const char *fgname)
306
 
{
307
 
    DefineModel(name, new CompositeModel(MakeModel(bgname), MakeModel(fgname)));
308
 
}
309
 
 
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;
314
 
}
315
 
 
316
 
void display::AddFrame (const char *name, const char *model, double time)
317
 
{
318
 
    if (anim_templ_name != name) 
319
 
        fprintf(stderr, "AddFrame: Cannot add frames to completed animations.");
320
 
    else
321
 
        anim_templ->add_frame(MakeModel(model), time / 1000.0);
322
 
}
323
 
 
324
 
void display::DefineAlias (const char *name, const char *othername)
325
 
{
326
 
    DefineModel(name, new AliasModel(othername));
327
 
}
328
 
 
329
 
 
330
 
 
331
 
/* -------------------- Model -------------------- */
332
 
void Model::get_extension (px::Rect &r)
333
 
{}
334
 
 
335
 
 
336
 
 
337
 
/* -------------------- Image -------------------- */
338
 
 
339
 
Image::Image(px::Surface *sfc)
340
 
: surface(sfc), rect(surface->size()), refcount(1)
341
 
{}
342
 
 
343
 
Image::Image(px::Surface *sfc, const px::Rect &r)
344
 
: surface(sfc), rect(r), refcount(1)
345
 
{}
346
 
 
347
 
 
348
 
void display::incref(Image *i) { 
349
 
    ++i->refcount; 
350
 
}
351
 
 
352
 
void display::decref (Image *i) {
353
 
    if (-- i->refcount == 0) {
354
 
        delete i;
355
 
    }
356
 
}
357
 
 
358
 
 
359
 
void display::draw_image (Image *i, px::GC &gc, int x, int y) 
360
 
{
361
 
    blit(gc, x, y, i->surface, i->rect);
362
 
}
363
 
 
364
 
/* -------------------- ImageModel -------------------- */
365
 
 
366
 
ImageModel::ImageModel (Image *i, int xo, int yo)
367
 
: image(i), xoff(xo), yoff(yo) 
368
 
{
369
 
    assert(image);
370
 
    incref(image);
371
 
}
372
 
 
373
 
ImageModel::ImageModel(Surface *s, int xo, int yo)
374
 
: image(new Image(s)), xoff(xo), yoff(yo)
375
 
{}
376
 
 
377
 
ImageModel::ImageModel(Surface *s, const px::Rect &r, int xo, int yo)
378
 
: image(new Image(s, r)), xoff(xo), yoff(yo)
379
 
{}
380
 
 
381
 
ImageModel::~ImageModel() {
382
 
    decref(image); 
383
 
}
384
 
        
385
 
void ImageModel::draw(px::GC &gc, int x, int y) {
386
 
    draw_image (image, gc, x+xoff, y+yoff);
387
 
}
388
 
 
389
 
Model *ImageModel::clone() { 
390
 
    return new ImageModel(image, xoff, yoff); 
391
 
}
392
 
 
393
 
void ImageModel::get_extension (px::Rect &r) {
394
 
    r.x = xoff;
395
 
    r.y = yoff;
396
 
    r.w = image->rect.w;
397
 
    r.h = image->rect.h;
398
 
}
399
 
 
400
 
/* -------------------- ShadowModel -------------------- */
401
 
 
402
 
ShadowModel::ShadowModel (Model *m, Model *sh) {
403
 
    model=m; shade=sh;
404
 
}
405
 
 
406
 
ShadowModel::~ShadowModel() { 
407
 
    delete model; delete shade; 
408
 
}
409
 
 
410
 
void ShadowModel::expose (ModelLayer *ml, int vx, int vy) {
411
 
    model->expose(ml, vx, vy);
412
 
    shade->expose(ml, vx, vy);
413
 
}
414
 
void ShadowModel::remove (ModelLayer *ml) {
415
 
    shade->remove(ml);
416
 
    model->remove(ml);
417
 
}
418
 
 
419
 
void ShadowModel::set_callback(ModelCallback *cb) { 
420
 
    model->set_callback(cb); 
421
 
}
422
 
 
423
 
void ShadowModel::reverse() { 
424
 
    model->reverse(); 
425
 
    shade->reverse(); 
426
 
}
427
 
 
428
 
void ShadowModel::restart() { 
429
 
    model->restart(); 
430
 
    shade->restart(); 
431
 
}
432
 
 
433
 
void ShadowModel::draw(px::GC &gc, int x, int y) {
434
 
    model->draw(gc,x,y);
435
 
}
436
 
 
437
 
void ShadowModel::draw_shadow(px::GC &gc, int x, int y) {
438
 
    shade->draw(gc,x,y);
439
 
}
440
 
 
441
 
Model *ShadowModel::get_shadow() const { 
442
 
    return shade; 
443
 
}
444
 
 
445
 
Model *ShadowModel::clone() {
446
 
    return new ShadowModel(model->clone(), shade->clone());
447
 
}
448
 
 
449
 
void ShadowModel::get_extension (px::Rect &r) {
450
 
    px::Rect r1, r2;
451
 
    model->get_extension (r1);
452
 
    shade->get_extension (r2);
453
 
    r = boundingbox (r1, r2);
454
 
}
455
 
 
456
 
/* -------------------- RandomModel -------------------- */
457
 
 
458
 
Model * RandomModel::clone() {
459
 
    if (!modelnames.empty()) {
460
 
        int r = enigma::IntegerRand(0, modelnames.size()-1);
461
 
        return MakeModel(modelnames[r]);
462
 
    } else {
463
 
        fprintf(stderr, "display_2d.cc: empty RandomModel\n");
464
 
        return 0;
465
 
    }
466
 
}
467
 
 
468
 
/* -------------------- AliasModel -------------------- */
469
 
 
470
 
Model * AliasModel::clone() {
471
 
    return MakeModel(name);
472
 
}
473
 
 
474
 
/* -------------------- Anim2d -------------------- */
475
 
 
476
 
Anim2d::Anim2d(bool loop) 
477
 
: rep(new AnimRep(loop)) 
478
 
{}
479
 
 
480
 
Anim2d::Anim2d (AnimRep *r) 
481
 
: rep(r), curframe(0), frametime(0), 
482
 
  finishedp (false), 
483
 
  changedp (false), 
484
 
  reversep (false),
485
 
  videox (0), videoy (0),
486
 
  callback(0)
487
 
{
488
 
    rep->refcount++;
489
 
    frametime = 0; // enigma::DoubleRand (0, 0.02);
490
 
}
491
 
 
492
 
Anim2d::~Anim2d() {
493
 
    if (--rep->refcount == 0)
494
 
        delete rep;
495
 
}
496
 
 
497
 
void Anim2d::restart () {
498
 
    finishedp = false; frametime = 0; curframe = 0; changedp = true; 
499
 
}
500
 
 
501
 
void Anim2d::add_frame(Model *m, double duration) {
502
 
    rep->frames.push_back(new AnimFrame(m, duration));
503
 
}
504
 
 
505
 
void Anim2d::draw(px::GC &gc, int x, int y) 
506
 
{
507
 
    if (!finishedp) {
508
 
        AnimFrame *f =rep->frames[curframe];
509
 
        f->model->draw(gc,x,y);
510
 
        changedp = false;
511
 
    }
512
 
}
513
 
        
514
 
void Anim2d::draw_shadow (px::GC &gc, int x, int y) 
515
 
{
516
 
    if (!finishedp) {
517
 
        AnimFrame *f =rep->frames[curframe];
518
 
        f->model->draw_shadow(gc,x,y);
519
 
    }
520
 
}
521
 
 
522
 
void Anim2d::expose (ModelLayer *ml, int vx, int vy) {
523
 
    ml->activate (this);
524
 
    videox = vx;
525
 
    videoy = vy;
526
 
}
527
 
 
528
 
void Anim2d::remove (ModelLayer *ml) {
529
 
    ml->deactivate (this);
530
 
}
531
 
 
532
 
bool Anim2d::has_changed (Rect &r) {
533
 
    bool retval = changedp;
534
 
    if (changedp) {
535
 
        get_extension (r);
536
 
        r.x += videox;
537
 
        r.y += videoy;
538
 
    }
539
 
    return retval;
540
 
}
541
 
 
542
 
void Anim2d::move (int newx, int newy) {
543
 
    videox = newx;
544
 
    videoy = newy;
545
 
}
546
 
 
547
 
void Anim2d::get_extension (px::Rect &r) {
548
 
    AnimFrame *f =rep->frames[curframe];
549
 
    f->model->get_extension (r);
550
 
}
551
 
 
552
 
void Anim2d::tick (double dtime) 
553
 
{
554
 
    assert(curframe < rep->frames.size());
555
 
    frametime += dtime;
556
 
    double framedur = rep->frames[curframe]->duration;
557
 
 
558
 
    if (frametime >= framedur) {
559
 
        frametime -= framedur;
560
 
        changedp = true;
561
 
 
562
 
        if (reversep) {
563
 
            if (curframe >= 1)
564
 
                curframe--;
565
 
            else if (rep->loop)
566
 
                curframe = rep->frames.size()-1;
567
 
            else
568
 
                finishedp = true;
569
 
        } 
570
 
        else {
571
 
            if (curframe+1 < rep->frames.size())
572
 
                curframe++;
573
 
            else if (rep->loop)
574
 
                curframe = 0;
575
 
            else 
576
 
                finishedp = true;
577
 
        }
578
 
        if (finishedp && callback!=0)
579
 
            callback->animcb();
580
 
    }
581
 
}
582
 
 
583
 
/* -------------------- Functions -------------------- */
584
 
 
585
 
namespace display
586
 
{
587
 
    Surface *GetSurface (const std::string &filename)
588
 
    {
589
 
        return surface_cache.get(filename);
590
 
    }
591
 
 
592
 
    void RegisterImage (const std::string &name, Image *img)
593
 
    {
594
 
    }
595
 
 
596
 
    Image *LookupImage (const std::string &name)
597
 
    {
598
 
        return 0;
599
 
    }
600
 
 
601
 
}