summaryrefslogtreecommitdiffstats
path: root/kwin4/kwin4/kspritecache.h
blob: 9d762a13f15566404094e766ccbf11b511c3e886 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
/***************************************************************************
                               kspritecache.h
                             -------------------
    begin                : September 2001  by Martin Heni
    email                : martin@heni-online.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef _KSPRITECACHE_H
#define _KSPRITECACHE_H

#include <tqcanvas.h>
#include <tqdict.h>

class KConfig;

class KSprite;

    /**
    * this is an internal class to provide a @ref TQObject to emit
    * a signal from a sprite if a notify object is created
    * You do not need this directly.
    * TODO: Can be part of the KSprite class
    **/
    class KSpriteNotify : public QObject
    {
      Q_OBJECT

      public:
        KSpriteNotify() :TQObject(0,0) {mRefCnt=0;}
        void emitSignal(TQCanvasItem *parent,int mode) {emit signalNotify(parent,mode);}
        void incRefCnt() {mRefCnt++;}
        void decRefCnt() {mRefCnt--;}
        int refCnt() {return mRefCnt;}
      signals:
        void signalNotify(TQCanvasItem *,int);
      private:
        int mRefCnt;
    };

    class KSpriteMove 
    {
      public:
        KSpriteMove() {}
        virtual ~KSpriteMove() {}
        virtual bool spriteMove(double ,double ,KSprite *) {return false;}
      private:
    };

/**
 * The KSprite class is an advance TQCanvasSprite class which
 * is usable with the @ref KSpriteCache. It furthermore contains a
 * few useful functions like advanced movement and animations which
 * go beyond the TQCanvasSprite versions of them. Also it provides
 * a signal which is emitted when movement or animation are finished.
 *
 * @short The main KDE game object
 * @author Martin Heni <martin@heni-online.de>
 *
 */
class KSprite : public QCanvasSprite
{
  public:
    /**
    * Contructs a KSprite object. It is anlogous to the @ref QCanvasSprite
    * constructor
    * 
    * @param array - the frames of the sprite
    * @param canvas - the canvas the sprites lives on
    **/
    KSprite(TQCanvasPixmapArray* array, TQCanvas* canvas);

    /**
    * Destructs the sprite
    **/
    virtual ~KSprite(); 

    /** 
    * The sprites runtime idendification (32)
    **/
    int rtti() const {return 32;}

    /**
    * returns a pointer to the pixmap array which holds the
    * frames of the sprite.
    **/
    TQCanvasPixmapArray* images() const {return mImages;}

    /**
    * Moves the sprite to the given position with the given speed.
    * When it reaches its desitnation a signal is emmited if the
    * emmiter @ref createNotify is enabled
    *
    * @param x - the x coordinate
    * @param y - the y coordinate
    * @param speed - the speed to move . If zero the last set speed is taken
    **/
    void moveTo(double x,double y,double speed=0.0);

    /**
    * Generates a linear move to the target tx,ty from the current
    * position of the sprite with its set speed @ref setSpeed
    * Upon arrival the function returns false to indicate an end of the
    * movment. Otherwise true is returned. 
    * The sprite is moved in this function.
    **/
    bool spriteMove(double tx,double ty);

    /**
    * The sprites advance function. See the qt @ref QcanvasSprite advance
    **/
    void advance(int stage);

    /**
    * Sets the speed for the next move. Can be set with moveTo too.
    * 
    * @param v - the speed in pixel per animation cycle
    **/ 
    void setSpeed(double v) {mSpeed=v;}

    /**
    * returns the speed
    **/
    double speed() {return mSpeed;}

    /**
    * returns the notification TQObject. You probably do not need this but
    * @ref createNotify instead
    **/
    TQObject *notify() {return (TQObject *)mNotify;}

    /**
    * Directly emits the notification signal with the given parameter
    *
    * @param the notification parameter
    **/
    void emitNotify(int mode);

    /**
    * Creates a notification object. You can connect to it and it will emit
    * the signal signalNotify(TQCanvasItem *parent, intmode) when a move or
    * animation is finished.
    * Example:
    * <pre>
    *  connect(sprite->createNotify(),TQT_SIGNAL(signalNotify(TQCanvasItem *,int)),
    *          this,TQT_SLOT(moveDone(TQCanvasItem *,int)));
    * </pre>
    * In the move done function you best delete the notify again with 
    * @ref deleteNotify
    **/
    TQObject *createNotify();

    /**
    * Deletes the sprite notify if it is no longer used. The notify keeps a
    * reference count which deletes the TQObject when no reference to it is in
    * use. 
    **/ 
    void deleteNotify();

    /**
    * Reads the animation parameters into the given variables for the given
    * animation. Mostly used by @ref KSpriteCache
    * 
    * @param no - the animation number
    * @param startframe - the first frame of the animation
    * @param endframe - the last frame of the animation
    * @param mode - the mode of the animation see @ref creaetAnimation
    * @param delay - the delay in TQCanvas animation cycles between two frames
    **/
    void getAnimation(int no,int &startframe,int &endframe,int &mode,int &delay);

    /**
    * Creates an animation of the sprite between two frames in one of the
    * following modes
    * 0: no animation
    * 1: single shot a->b
    *-1: single shot b->a
    * 2: cycle  a->b->a
    *-2: cycle  b->a->b
    * 3: cycle  a->b 
    *-3: cycle  b->a 
    * 
    * The single shot animations will emit the above mentioned signal over the
    * notify object if it is created.
    * If you load the sprite over the KSpriteCache's config file you need not
    * bother about calling this function.
    **/
    void createAnimation(int no,int startframe,int endframe,int mode,int delay);

    /**
    * Switches on the animation of the given number. Of course it needs to be
    * defined beforehand either via loading the sprite with the 
    * @ref KSpriteCache or be calling @ref createAnimation
    *
    * @param no - the number of the animation
    **/
    void setAnimation(int no);

    /**
    * Returns how many different animations are stored
    **/
    unsigned int animationCount() {return mAnimFrom.count();}

    void setMoveObject(KSpriteMove *m) {mMoveObj=m;}
    KSpriteMove *moveObject() {return mMoveObj;}
    
  protected:
    KSpriteMove *mMoveObj;

  private:
    KSpriteNotify *mNotify;
    TQCanvasPixmapArray* mImages;
    TQByteArray mAnimFrom;
    TQByteArray mAnimTo;
    TQByteArray mAnimDirection;
    TQByteArray mAnimDelay;

    double mTargetX,mTargetY;
    double mSpeed;
    int mAnimationNumber;
    int mAnimSpeedCnt;
    int mCurrentAnimDir;
};


/**
 * The KSpriteCache class is used to load and cache sprites. Loading
 * is done via a @ref KConfig file which contains the definitions of the
 * sprite in text form. Usng this approach allows you to tun the sprites
 * without chaning the sourcecode of the program. This is especially useful if
 * the graphics team is independent of the programmer or if you want to write
 * external themes for your game.
 * Furhtermore the class keeps sprites in memory so that they are fastly
 * reloaded when you use more than one sprite of a given type.
 * 
 * Example:
 * <pre>
 * # Sprite with three frames and a common mask for them
 * # z position given but x,y set manually in the program
 *  [arrow]
 *  file=arrow%d.png
 *  mask=arrow_mask.png
 *  number=3
 *  offset=19,5
 *  rtti=32
 *  z=9.0
 *
 * # Simple sprite which is already positioned correcly. No mask just one file
 *  [board]
 *  file=board.png
 *  rtti=32
 *  x=15.0
 *  y=40.0
 *  z=0.0
 * 
 * # Sprite with one cyclic (2) animation of  5 frames (0-4) and
 * # a slow delay of 8
 *  [star]
 *  anim0=0,4,2,8
 *  file=star%d.png
 *  mask=star%d_mask.png
 *  number=5
 *  offset=19,20
 *  rtti=32
 *  z=100.0
 *
 * </pre>
 *
 * @todo Support single sprites (only one copy in memory)
 *       Support more sprite types (currently KSprite and TQCanvasText)
 *
 * @short The main KDE game object
 * @author Martin Heni <martin@heni-online.de>
 *
 */
class KSpriteCache : public QObject
{
  Q_OBJECT

  public:
  /**
  * Create a sprite cache. Usuzally you will need one per program only.
  * 
  * @param grafixdir - the directory where the configuration file and the graphics reside
  **/
  KSpriteCache(TQString grafixdir, TQObject* parent=0,const char * name=0);

  /**
  * Delete the sprite cache
  **/
  ~KSpriteCache();

  /**
  * Change the grafichs directory.
  * 
  * @todo  this does not flush the cache or so...
  **/
  bool setGrafixDir(TQString dir); // dir and load config

  /**
  * Change the name of the config file. Its default is <em>grafix.rc</em>
  **/
  void setRcFile(TQString file);

  /**
  * return the graphics directory
  **/
  TQString grafixDir() {return mGrafixDir;}

  /**
  * return the rc/configuration file
  **/
  TQString rcFile() {return mRcFile;}

  /**
  * returns the canvas which belongs to the cache
  **/
  TQCanvas *canvas() const {return mCanvas;}

  /**
  * sets the canvas belonging to the cache
  * 
  * @todo could be done in the constructor
  **/
  void setCanvas(TQCanvas *c) {mCanvas=c;}

  /**
  * returns the @ref KConfig configuration file where thegraphical data is
  * read. Access to this is necessary if you want to store general game infos
  * in theis file to or if you want to read additional sprite data which are
  * not read be the default functions.
  **/
  KConfig *config() {return mConfig;}

  /**
  * Main function to create a sprite. You call this like
  * <pre>
  * KSprite *sprite=(KSprite *)(yourcahce->getItem("hello",1));
  * if (sprite) sprite->show();
  * </pre>
  * Calling this function will load the given sprite from the
  * configuration file. Its type is determined by the rtti= entry
  * of the section [hello] in that file. Default is a KSprite.
  * This file defines all data of the sprite so that you just have to show it.
  * Each copy of the sprite gets its own number (1,2,...)
  * Note: The sprite is hidden upon creation and you need to show it
  * explicitly.
  * TODO: What definitions are possible in the rc file
  * 
  * @param name - the name of the sprite resp. the secion in the rc file
  * @param no - the unique number of the sprite 
  * @return sprite - returns the sprite pointer as @ref QCanvasItem
  *
  * @todo support call without number argument as single sprite's
  * @todo support loading of frame sequence via one big pixmap
  *
  **/
  TQCanvasItem *getItem(TQString name, int no);

  /**
  * This function loads a pixmap from the given file. Optional you can also
  * provide a mask file. Also optinal you can provide the directory. Default
  * is the directory which is set with this @ref KSpriteCache
  **/
  TQPixmap * loadPixmap(TQString file,TQString mask=TQString::null,TQString dir=TQString::null);

  /** 
  * Deletes a item form the sprite cache given as a pointer to it
  **/
  void deleteItem(TQCanvasItem *item);

  /**
  * Same as above but delete the item with the name and number
  **/
  void deleteItem(TQString s,int no);

  /**
  * Deletes all items in the cache
  **/
  void deleteAllItems();

  protected:
  /**
  * Loads the default properties for all QCanvasItems from the given config
  * file. This is at the moment
  * <pre>
  * x=(double)
  * y=(double)
  * z=(double)
  * </pre>
  **/
  void configureCanvasItem(KConfig *config,TQCanvasItem *item);
  
  /**
  * Copies the default properties for all QCanvasItems from another sprite.
  * Same as above.
  **/
  void configureCanvasItem(TQCanvasItem *original,TQCanvasItem *item);

  /**
  * Loads an item with the given name form the given config file. From the
  * rtti entry it is determined what type it is and then it is loaded.
  **/
  virtual TQCanvasItem *loadItem(KConfig *config,TQString name);

  /**
  * Clone the sprite from another sprite, mostly from the copy stored in the
  * cache.
  **/
  virtual TQCanvasItem *cloneItem(TQCanvasItem *original);

  /**
  * Creates a pixmap array for a @ref KSprite from the given config file
  * for the sprite with the given name (is the name necessary?).
  * Parameters are
  * <pre>
  *   offset=(TQPoint)       : The sprites offset (where 0,0 is)
  *   pixmaps=(TQStringList) : List of operations to create frames (TODO *   rename)
  *                           if ommited one operation without name is used
  * </pre>
  * All following calls have to be preceded by every given string of the
  * pixmaps section. If this section is not supplied they can be used without
  * prefix but only one frame sequence is created.
  * <pre>
  *   method=(TQString)  : load, scale (default=load)
  *                       load: loads number frames from file
  *                       scale: scales  number frames from one loaded file
  *   number=(int)      : how many frames to generate
  *   file=(Qstring)    : the filename to load (can contain printf format args
  *                       as %d which are replaced, e.g. file=hello_%d.png
  *   mask=(TQString)    : Same for the mask of the pixmaps
  *   axis=(int)        : (scale only): scale axis (1=x,2=y,3=x+y)
  *   final=(double)    : final scale in percent (default 0.0, i.e. complete scaling)
  *   colorfilter=1,h,s,v: make a HSV transform of all sprite images
  *   colorfilter=2     :  make it gray (lighter=100 is default)
  *   colorfilter=2,g   : make it gray and lighter (positiv) or darker (negative)
  * </pre>
  **/
  virtual TQCanvasPixmapArray *createPixmapArray(KConfig *config,TQString name);

  /**
  * Reads the animations from the config file and calls the corresponding
  * KSprite function to create them.
  * <pre>
  *  anim0=a,b,c,d
  *  anim1=e,f,g,h
  * </pre>
  *  Where the animations have to to be in sequence starting with 0 (i.e.
  *  anim0). <em>a</em> is the first frame of the animation. <em>b</em> is
  * the last frame of the animation. <em>c</em> is the mode of the animations,
  * see @ref KSprite::createAnimation and <em>d</em> is the delay in cycles
  * of the qcanvas animnation.
  *
  * @param config - the config file the sprite is read from
  * @param sprite - the sprite whose animations are set
  **/
  void createAnimations(KConfig *config,KSprite *sprite);

  /**
  * Same as above but to copy the animations from an existing sprite
  **/
  void createAnimations(KSprite *original,KSprite *sprite);

  /**
  * Change a pixmap to grey values. If the second argument is bigger
  * than 100 the pixmap is made lighter and if it less then 100 it is
  * made darker too
  **/
  virtual void changeGrey(TQPixmap *pixmap,int lighter=100);

  /**
  * Change the HAS value of the pixmap by dH, dS and dV
  **/
  virtual void changeHSV(TQPixmap *pixmap,int dh,int ds,int dv);

  /**
  * Apply the filters as defined in the config file to the sprite name
  * (TODO is this argument needed) to the pixmap.
  */
  virtual void applyFilter(TQPixmap *pixmap,KConfig *config,TQString name);

  /**
  * resets the cache (?)
  */
  void reset();

  protected:
    TQDict<TQCanvasItem> mItemDict;                // Spritename lookup
    TQDict<TQCanvasItem> mCloneDict;               // clone Items lookup

    TQString mGrafixDir;
    TQString mRcFile;
    KConfig *mConfig;
    TQCanvas *mCanvas;
 
};

#endif