1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 *
22 * Based on the original sources
23 * Faery Tale II -- The Halls of the Dead
24 * (c) 1993-1996 The Wyrmkeep Entertainment Co.
25 */
26
27 #include "saga2/saga2.h"
28 #include "saga2/fta.h"
29 #include "saga2/hresmgr.h"
30 #include "saga2/button.h"
31 #include "saga2/objects.h"
32 #include "saga2/fontlib.h"
33
34 namespace Saga2 {
35
36 typedef void *pVOID;
37 typedef pVOID apVOID[];
38
39 extern void playMemSound(uint32 s); // play click # s
40
41 /* ======================================================================= *
42 Compressed image class
43 * ======================================================================= */
44
init(void)45 void GfxCompImage::init(void) {
46 _compImages = NULL;
47 _max = 0;
48 _min = 0;
49 _internalAlloc = false;
50 _currentImage = 0;
51 _numPtrAlloc = 0;
52 _textFont = &Onyx10Font; // default
53 }
54
GfxCompImage(gPanelList & list,const Rect16 & box,void * image,uint16 ident,AppFunc * cmd)55 GfxCompImage::GfxCompImage(gPanelList &list, const Rect16 &box, void *image, uint16 ident,
56 AppFunc *cmd) : gControl(list, box, NULL, ident, cmd) {
57 // setup a single image configuration
58
59 init();
60
61 if (image) {
62 _compImages = (void **)malloc(sizeof(pVOID) * 1); // allocate room for one pointer
63 _compImages[0] = image;
64 _internalAlloc = false;
65 _numPtrAlloc = 1;
66 }
67 }
68
GfxCompImage(gPanelList & list,const Rect16 & box,uint32 contextID,char a,char b,char c,uint16 resNum,uint16 numImages,uint16 ident,AppFunc * cmd)69 GfxCompImage::GfxCompImage(gPanelList &list,
70 const Rect16 &box,
71 uint32 contextID,
72 char a, char b, char c,
73 uint16 resNum, uint16 numImages,
74 uint16 ident,
75 AppFunc *cmd) : gControl(list, box, NULL, ident, cmd) {
76 uint16 i, rNum;
77
78 init();
79
80 // init the resource context handle
81 hResContext *resContext = resFile->newContext(contextID, "container window resource");
82
83 // setup for a numImages image configuration
84 _compImages = (void **)malloc(sizeof(void *)*numImages); // allocate room for numImages pointers
85
86 for (i = 0, rNum = resNum; i < numImages; i++, rNum++) {
87 _compImages[i] = LoadResource(resContext,
88 MKTAG(a, b, c, rNum),
89 " GfxCompImage ");
90 }
91
92 _max = numImages - 1;
93 _internalAlloc = true;
94 _numPtrAlloc = numImages;
95
96 // get rid of this context
97 resFile->disposeContext(resContext);
98 resContext = NULL;
99 }
100
GfxCompImage(gPanelList & list,const Rect16 & box,void * image,const char * text,textPallete & pal,uint16 ident,AppFunc * cmd)101 GfxCompImage::GfxCompImage(gPanelList &list, const Rect16 &box, void *image, const char *text, textPallete &pal, uint16 ident,
102 AppFunc *cmd) : gControl(list, box, text, ident, cmd) {
103 // setup a single image configuration
104 init();
105
106 if (!image)
107 return;
108
109 _compImages = (void **)malloc(sizeof(void *) * 1); // allocate room for one pointer
110
111 _compImages[0] = image;
112 _max = 0;
113 _numPtrAlloc = 1;
114 title = text;
115 _textFont = &Onyx10Font; // >>> this should be dynamic
116 _textPal = pal;
117 }
118
GfxCompImage(gPanelList & list,const Rect16 & box,void ** images,int16 numRes,int16 initial,uint16 ident,AppFunc * cmd)119 GfxCompImage::GfxCompImage(gPanelList &list, const Rect16 &box, void **images,
120 int16 numRes, int16 initial,
121 uint16 ident, AppFunc *cmd) : gControl(list, box, NULL, ident, cmd) {
122 init();
123
124 if (!images)
125 return;
126
127 _compImages = images;
128
129 // set up limits
130 _max = numRes - 1;
131 _currentImage = clamp(_min, initial, _max);
132 }
133
GfxCompImage(gPanelList & list,const Rect16 & box,void ** images,int16 numRes,int16 initial,const char * text,textPallete & pal,uint16 ident,AppFunc * cmd)134 GfxCompImage::GfxCompImage(gPanelList &list, const Rect16 &box, void **images,
135 int16 numRes, int16 initial, const char *text, textPallete &pal,
136 uint16 ident, AppFunc *cmd) : gControl(list, box, text, ident, cmd) {
137 init();
138
139 if (images) {
140 _compImages = images;
141
142 // set up limits
143 _max = numRes - 1;
144 _currentImage = clamp(_min, initial, _max);
145 }
146
147 title = text;
148 _textFont = &Onyx10Font; // >>> this should be dynamic
149 _textPal = pal;
150 }
151
GfxCompImage(gPanelList & list,const StaticRect & box,void ** images,int16 numRes,int16 initial,const char * text,textPallete & pal,uint16 ident,AppFunc * cmd)152 GfxCompImage::GfxCompImage(gPanelList &list, const StaticRect &box, void **images,
153 int16 numRes, int16 initial, const char *text, textPallete &pal,
154 uint16 ident, AppFunc *cmd) : gControl(list, box, text, ident, cmd) {
155 init();
156
157 if (images) {
158 _compImages = images;
159
160 // set up limits
161 _max = numRes - 1;
162 _currentImage = clamp(_min, initial, _max);
163 }
164
165 title = text;
166 _textFont = &Onyx10Font; // >>> this should be dynamic
167 _textPal = pal;
168 }
169
170
~GfxCompImage(void)171 GfxCompImage::~GfxCompImage(void) {
172 // delete any allocated image pointers
173 // for JEFFL: I took out the winklude #ifdefs becuase I belive
174 // I fixed the problem that was causing the crash under win32
175 // 11-14-95, I should talk to you tommorow. This is note is
176 // a precaution
177
178 // if we LoadRes'ed image internally RDispose those
179 if (_internalAlloc) {
180 for (int16 i = 0; i < _numPtrAlloc; i++) {
181 free(_compImages[i]);
182 }
183 }
184
185 // delete any pointer arrays new'ed
186 if (_numPtrAlloc > 0) {
187 free(_compImages);
188 }
189 }
190
pointerMove(gPanelMessage & msg)191 void GfxCompImage::pointerMove(gPanelMessage &msg) {
192 // call the superclass's pointerMove
193 gControl::pointerMove(msg);
194
195 notify(gEventMouseMove, (msg.pointerEnter ? enter : 0) | (msg.pointerLeave ? leave : 0));
196 }
197
enable(bool abled)198 void GfxCompImage::enable(bool abled) {
199 gPanel::enable(abled);
200 }
201
invalidate(Rect16 *)202 void GfxCompImage::invalidate(Rect16 *) {
203 window.update(_extent);
204 }
205
draw(void)206 void GfxCompImage::draw(void) {
207 gPort &port = window.windowPort;
208 Rect16 rect = window.getExtent();
209
210 SAVE_GPORT_STATE(port); // save pen color, etc.
211 g_vm->_pointer->hide(port, _extent); // hide mouse pointer
212 drawClipped(port,
213 Point16(0, 0),
214 Rect16(0, 0, rect.width, rect.height));
215 g_vm->_pointer->show(port, _extent); // show mouse pointer
216 }
217
getCurrentCompImage(void)218 void *GfxCompImage::getCurrentCompImage(void) {
219 if (_compImages) {
220 return _compImages[_currentImage]; // return the image pointed to by compImage
221 } else {
222 return NULL;
223 }
224 }
225
226 // waring! : the number of images has has to be == to the inital number
setImages(void ** images)227 void GfxCompImage::setImages(void **images) {
228 if (images) {
229 _compImages = images;
230 }
231 }
232
setImage(void * image)233 void GfxCompImage::setImage(void *image) {
234 if (image) {
235 _compImages[0] = image;
236 _max = 0;
237 _currentImage = 0;
238 }
239 }
240
select(uint16 val)241 void GfxCompImage::select(uint16 val) {
242 setCurrent(val);
243
244 if (getEnabled()) {
245 window.update(_extent);
246 }
247 }
248
select(uint16 val,const Rect16 & rect)249 void GfxCompImage::select(uint16 val, const Rect16 &rect) {
250 select(val);
251 setExtent(rect);
252 }
253
setExtent(const Rect16 & rect)254 void GfxCompImage::setExtent(const Rect16 &rect) {
255 // set the new extent
256 _extent = rect;
257 }
258
259 // getCurrentCompImage() is virtual function that should return
260 // the current image to be displayed (to be used across all sub-classes)
drawClipped(gPort & port,const Point16 & offset,const Rect16 & r)261 void GfxCompImage::drawClipped(gPort &port,
262 const Point16 &offset,
263 const Rect16 &r) {
264 if (!_extent.overlap(r)) return;
265
266 SAVE_GPORT_STATE(port);
267
268 // get the current image
269 void *dispImage = getCurrentCompImage();
270
271 // make sure the image is valid
272 if (dispImage) {
273 // will part of this be drawn on screen?
274 if (_extent.overlap(r)) {
275 // offset the image?
276 Point16 pos(_extent.x - offset.x,
277 _extent.y - offset.y
278 );
279 // draw the compressed image
280 if (isGhosted()) drawCompressedImageGhosted(port, pos, dispImage);
281 else drawCompressedImage(port, pos, dispImage);
282
283 // this could be modified to get the current text coloring
284 if (title) {
285 Rect16 textRect = _extent;
286 textRect.x -= offset.x;
287 textRect.y -= offset.y;
288
289 writePlaqText(port, textRect, _textFont, 0, _textPal, selected, title);
290 }
291 }
292 }
293 }
294
295 /* ===================================================================== *
296 GfxSpriteImage class member functions
297 * ===================================================================== */
298
GfxSpriteImage(gPanelList & list,const Rect16 & box,GameObject * object,char,uint16 ident,AppFunc * cmd)299 GfxSpriteImage::GfxSpriteImage(gPanelList &list, const Rect16 &box, GameObject *object, char,
300 uint16 ident, AppFunc *cmd) : GfxCompImage(list, box, NULL, ident, cmd) {
301 // get the prototype for the object
302 ProtoObj *proto = object->proto();
303
304 // assign the sprites remapped colors
305 object->getColorTranslation(_objColors);
306
307 // assing the sprite pointer
308 _sprPtr = proto->getSprite(object, ProtoObj::objInContainerView).sp;
309 }
310
311 // getCurrentCompImage() is virtual function that should return
312 // the current image to be displayed (to be used across all sub-classes)
drawClipped(gPort & port,const Point16 & offset,const Rect16 & r)313 void GfxSpriteImage::drawClipped(gPort &port,
314 const Point16 &offset,
315 const Rect16 &r) {
316 if (!_extent.overlap(r)) return;
317
318 SAVE_GPORT_STATE(port);
319
320 // if there's a sprite present
321 gPixelMap map;
322
323 //map.size = Point16( extent.height, extent.width );
324 map.size = _sprPtr->size;
325
326 map.data = (uint8 *)malloc(map.bytes() * sizeof(uint8));
327 if (map.data == NULL) return;
328
329 memset(map.data, 0, map.bytes());
330
331 // Render the sprite into the bitmap image sequence
332 ExpandColorMappedSprite(map, _sprPtr, _objColors);
333
334 port.setMode(drawModeMatte);
335 port.bltPixels(map, 0, 0,
336 _extent.x - offset.x, _extent.y - offset.y,
337 map.size.x, map.size.y);
338
339 free(map.data);
340 }
341
342 /* ===================================================================== *
343 GfxCompButton class member functions
344 * ===================================================================== */
345
loadImages(hResContext * con,hResID res1,hResID res2)346 void GfxCompButton::loadImages(hResContext *con, hResID res1, hResID res2) {
347 if (con) {
348 _forImage = LoadResource(con, res1, "CBtn fore image");
349 _resImage = LoadResource(con, res2, "CBtn res image");
350 _dimImage = NULL;
351 } else {
352 _forImage = NULL;
353 _resImage = NULL;
354 _dimImage = NULL;
355 }
356
357 _internalAlloc = true;
358 _dimmed = false;
359 }
360
loadImages(hResID contextID,hResID res1,hResID res2)361 void GfxCompButton::loadImages(hResID contextID, hResID res1, hResID res2) {
362 // init the resource context handle
363 hResContext *con = resFile->newContext(contextID,
364 "container window resource");
365
366 loadImages(con, res1, res2);
367 resFile->disposeContext(con); // get rid of this context
368 }
369
GfxCompButton(gPanelList & list,const Rect16 & box,hResContext * con,hResID resID1,hResID resID2,uint16 ident,AppFunc * cmd)370 GfxCompButton::GfxCompButton(gPanelList &list, const Rect16 &box, hResContext *con, hResID resID1, hResID resID2, uint16 ident,
371 AppFunc *cmd) : GfxCompImage(list, box, NULL, ident, cmd), _extent(box) {
372 loadImages(con, resID1, resID2);
373 }
374
GfxCompButton(gPanelList & list,const Rect16 & box,hResID contextID,hResID resID1,hResID resID2,uint16 ident,AppFunc * cmd)375 GfxCompButton::GfxCompButton(gPanelList &list, const Rect16 &box, hResID contextID, hResID resID1, hResID resID2, uint16 ident,
376 AppFunc *cmd) : GfxCompImage(list, box, NULL, ident, cmd), _extent(box) {
377 loadImages(contextID, resID1, resID2);
378 }
379
GfxCompButton(gPanelList & list,const Rect16 & box,hResContext * con,char a,char b,char c,int16 butNum_1,int16 butNum_2,uint16 ident,AppFunc * cmd)380 GfxCompButton::GfxCompButton(gPanelList &list, const Rect16 &box, hResContext *con, char a, char b, char c, int16 butNum_1, int16 butNum_2, uint16 ident,
381 AppFunc *cmd) : GfxCompImage(list, box, NULL, ident, cmd), _extent(box) {
382 loadImages(con, MKTAG(a, b, c, butNum_1), MKTAG(a, b, c, butNum_2));
383 }
384
GfxCompButton(gPanelList & list,const Rect16 & box,hResID contextID,char a,char b,char c,int16 butNum_1,int16 butNum_2,uint16 ident,AppFunc * cmd)385 GfxCompButton::GfxCompButton(gPanelList &list, const Rect16 &box, hResID contextID, char a, char b, char c, int16 butNum_1, int16 butNum_2, uint16 ident,
386 AppFunc *cmd) : GfxCompImage(list, box, NULL, ident, cmd), _extent(box) {
387 loadImages(contextID, MKTAG(a, b, c, butNum_1), MKTAG(a, b, c, butNum_2));
388 }
389
GfxCompButton(gPanelList & list,const Rect16 & box,hResContext * con,int16 butNum,uint16 ident,AppFunc * cmd)390 GfxCompButton::GfxCompButton(gPanelList &list, const Rect16 &box, hResContext *con, int16 butNum, uint16 ident,
391 AppFunc *cmd) : GfxCompImage(list, box, NULL, ident, cmd), _extent(box) {
392 loadImages(con, MKTAG('B', 'T', 'N', butNum), MKTAG('B', 'T', 'N', butNum + 1));
393 }
394
GfxCompButton(gPanelList & list,const Rect16 & box,void ** images,int16 numRes,uint16 ident,AppFunc * cmd)395 GfxCompButton::GfxCompButton(gPanelList &list, const Rect16 &box, void **images, int16 numRes, uint16 ident,
396 AppFunc *cmd) : GfxCompImage(list, box, NULL, ident, cmd) {
397 if (images[0] && images[1] && numRes == 2) {
398 _forImage = images[0];
399 _resImage = images[1];
400 _dimImage = NULL;
401 } else {
402 _forImage = NULL;
403 _resImage = NULL;
404 _dimImage = NULL;
405 }
406
407 _internalAlloc = false;
408 _dimmed = false;
409 _extent = box;
410 }
411
GfxCompButton(gPanelList & list,const Rect16 & box,void ** images,int16 numRes,const char * text,textPallete & pal,uint16 ident,AppFunc * cmd)412 GfxCompButton::GfxCompButton(gPanelList &list, const Rect16 &box, void **images, int16 numRes, const char *text, textPallete &pal, uint16 ident,
413 AppFunc *cmd) : GfxCompImage(list, box, NULL, 0, 0, text, pal, ident, cmd) {
414 if (images[0] && images[1] && numRes == 2) {
415 _forImage = images[0];
416 _resImage = images[1];
417 _dimImage = NULL;
418 } else {
419 _forImage = NULL;
420 _resImage = NULL;
421 _dimImage = NULL;
422 }
423
424 _internalAlloc = false;
425 _dimmed = false;
426 _extent = box;
427 }
428
GfxCompButton(gPanelList & list,const Rect16 & box,void ** images,int16 numRes,void * newDimImage,bool dimNess,uint16 ident,AppFunc * cmd)429 GfxCompButton::GfxCompButton(gPanelList &list, const Rect16 &box, void **images, int16 numRes, void *newDimImage, bool dimNess, uint16 ident,
430 AppFunc *cmd) : GfxCompImage(list, box, NULL, ident, cmd) {
431 if (images[0] && images[1] && numRes == 2) {
432 _forImage = images[0];
433 _resImage = images[1];
434 } else {
435 _forImage = NULL;
436 _resImage = NULL;
437 }
438
439 if (newDimImage) {
440 _dimImage = newDimImage;
441 } else {
442 _dimImage = NULL;
443 }
444
445 _internalAlloc = false;
446 _dimmed = dimNess;
447 _extent = box;
448 }
449
450
GfxCompButton(gPanelList & list,const Rect16 & box,void * image,uint16 ident,AppFunc * cmd)451 GfxCompButton::GfxCompButton(gPanelList &list, const Rect16 &box, void *image, uint16 ident,
452 AppFunc *cmd) : GfxCompImage(list, box, NULL, ident, cmd)
453
454 {
455 if (image) {
456 _forImage = image;
457 _resImage = image;
458 _dimImage = NULL;
459 } else {
460 _forImage = NULL;
461 _resImage = NULL;
462 _dimImage = NULL;
463 }
464
465 _internalAlloc = false;
466 _dimmed = false;
467 _extent = box;
468 }
469
GfxCompButton(gPanelList & list,const StaticRect & box,void ** images,int16 numRes,const char * text,textPallete & pal,uint16 ident,AppFunc * cmd)470 GfxCompButton::GfxCompButton(gPanelList &list, const StaticRect &box, void **images, int16 numRes, const char *text, textPallete &pal, uint16 ident, AppFunc *cmd) : GfxCompImage(list, box, NULL, 0, 0, text, pal, ident, cmd) {
471 if (images[0] && images[1] && numRes == 2) {
472 _forImage = images[0];
473 _resImage = images[1];
474 _dimImage = nullptr;
475 } else {
476 _forImage = nullptr;
477 _resImage = nullptr;
478 _dimImage = nullptr;
479 }
480
481 _internalAlloc = false;
482 _dimmed = false;
483 _extent = box;
484 }
485
GfxCompButton(gPanelList & list,const Rect16 & box,AppFunc * cmd)486 GfxCompButton::GfxCompButton(gPanelList &list, const Rect16 &box, AppFunc *cmd) : GfxCompImage(list, box, NULL, 0, cmd) {
487 _forImage = NULL;
488 _resImage = NULL;
489 _dimImage = NULL;
490
491 _internalAlloc = false;
492 _dimmed = false;
493 _extent = box;
494 }
495
~GfxCompButton(void)496 GfxCompButton::~GfxCompButton(void) {
497 if (_internalAlloc) {
498 if (_forImage) {
499 free(_forImage);
500 _forImage = NULL;
501 }
502
503 if (_resImage) {
504 free(_resImage);
505 _resImage = NULL;
506 }
507
508 if (_dimImage) {
509 free(_dimImage);
510 _dimImage = NULL;
511 }
512 }
513 }
514
dim(bool enableFlag)515 void GfxCompButton::dim(bool enableFlag) {
516 if (enableFlag) {
517 if (!_dimmed)
518 _dimmed = true;
519 } else {
520 if (_dimmed)
521 _dimmed = false;
522 }
523
524 window.update(_extent);
525 }
526
527
deactivate(void)528 void GfxCompButton::deactivate(void) {
529 selected = 0;
530 window.update(_extent);
531 gPanel::deactivate();
532 }
533
activate(gEventType why)534 bool GfxCompButton::activate(gEventType why) {
535 selected = 1;
536 window.update(_extent);
537
538 if (why == gEventKeyDown) { // momentarily depress
539 deactivate();
540 notify(gEventNewValue, 1); // notify App of successful hit
541 }
542 playMemSound(2);
543 return false;
544 }
545
pointerMove(gPanelMessage & msg)546 void GfxCompButton::pointerMove(gPanelMessage &msg) {
547 if (_dimmed)
548 return;
549
550 //notify( gEventMouseMove, (msg.pointerEnter ? enter : 0)|(msg.pointerLeave ? leave : 0));
551 GfxCompImage::pointerMove(msg);
552 }
553
pointerHit(gPanelMessage &)554 bool GfxCompButton::pointerHit(gPanelMessage &) {
555 if (_dimmed)
556 return false;
557
558 activate(gEventMouseDown);
559 return true;
560 }
561
pointerRelease(gPanelMessage &)562 void GfxCompButton::pointerRelease(gPanelMessage &) {
563 // We have to test selected first because deactivate clears it.
564
565 if (selected) {
566 deactivate(); // give back input focus
567 notify(gEventNewValue, 1); // notify App of successful hit
568 } else deactivate();
569 }
570
pointerDrag(gPanelMessage & msg)571 void GfxCompButton::pointerDrag(gPanelMessage &msg) {
572 if (selected != msg.inPanel) {
573 selected = msg.inPanel;
574 window.update(_extent);
575 }
576 }
577
enable(bool abled)578 void GfxCompButton::enable(bool abled) {
579 gPanel::enable(abled);
580 }
581
invalidate(Rect16 *)582 void GfxCompButton::invalidate(Rect16 *) {
583 window.update(_extent);
584 }
585
586
draw(void)587 void GfxCompButton::draw(void) {
588 gPort &port = window.windowPort;
589 Rect16 rect = window.getExtent();
590
591 SAVE_GPORT_STATE(port); // save pen color, etc.
592 g_vm->_pointer->hide(port, _extent); // hide mouse pointer
593 drawClipped(port, Point16(0, 0), Rect16(0, 0, rect.width, rect.height));
594 g_vm->_pointer->show(port, _extent); // show mouse pointer
595 }
596
getCurrentCompImage(void)597 void *GfxCompButton::getCurrentCompImage(void) {
598 if (_dimmed) {
599 return _dimImage;
600 } else if (selected) {
601 return _resImage;
602 } else {
603 return _forImage;
604 }
605 }
606
607 /************************************************************************
608 * GfxOwnerSelCompButton -- like a GfxCompButton but does not chage the *
609 * selector bit *
610 ************************************************************************/
611
GfxOwnerSelCompButton(gPanelList & list,const Rect16 & box,void ** images,int16 butRes,uint16 ident,AppFunc * cmd)612 GfxOwnerSelCompButton::GfxOwnerSelCompButton(gPanelList &list, const Rect16 &box, void **images, int16 butRes, uint16 ident,
613 AppFunc *cmd) : GfxCompButton(list, box, images, butRes, ident, cmd) {
614
615 }
616
activate(gEventType why)617 bool GfxOwnerSelCompButton::activate(gEventType why) {
618 if (why == gEventKeyDown || why == gEventMouseDown) {
619 // selected = !selected;
620 // window.update( extent );
621 gPanel::deactivate();
622 notify(gEventNewValue, selected); // notify App of successful hit
623 playMemSound(2);
624 }
625 return false;
626 }
627
pointerHit(gPanelMessage &)628 bool GfxOwnerSelCompButton::pointerHit(gPanelMessage &) {
629 return activate(gEventMouseDown);
630 }
631
select(uint16 val)632 void GfxOwnerSelCompButton::select(uint16 val) {
633 selected = val;
634
635 setCurrent(val);
636
637 if (getEnabled()) {
638 window.update(_extent);
639 }
640 }
641
642 /************************************************************************
643 * GfxMultCompButton -- like GfxCompButton but does any number of images *
644 ************************************************************************/
645
GfxMultCompButton(gPanelList & list,const Rect16 & box,hResContext * con,char a,char b,char c,int16 resStart,int16 numRes,int16 initial,uint16 ident,AppFunc * cmd)646 GfxMultCompButton::GfxMultCompButton(gPanelList &list, const Rect16 &box, hResContext *con, char a, char b, char c, int16 resStart, int16 numRes, int16 initial, uint16 ident,
647 AppFunc *cmd) : GfxCompButton(list, box, (hResContext *)NULL, 0, ident, cmd) {
648 int16 i, k;
649
650
651 _images = (void **)malloc(sizeof(void *)*numRes);
652
653 for (i = 0, k = resStart; i < numRes; i++, k++) {
654 _images[i] = LoadResource(con, MKTAG(a, b, c, k), "Multi btn image");
655 }
656
657 _response = true;
658 _internalAlloc = true;
659 _max = numRes - 1;
660 _min = 0;
661 _current = clamp(_min, initial, _max);
662
663 _extent = box;
664 }
665
GfxMultCompButton(gPanelList & list,const Rect16 & box,void ** newImages,int16 numRes,int16 initial,uint16 ident,AppFunc * cmd)666 GfxMultCompButton::GfxMultCompButton(gPanelList &list, const Rect16 &box, void **newImages, int16 numRes, int16 initial, uint16 ident,
667 AppFunc *cmd) : GfxCompButton(list, box, (hResContext *)NULL, 0, ident, cmd) {
668 if (!newImages) {
669 _images = NULL;
670 _max = 0;
671 _min = 0;
672 _current = 0;
673 _response = false;
674 return;
675 }
676
677 _images = newImages;
678
679 _response = true;
680 _internalAlloc = false;
681 _max = numRes - 1;
682 _min = 0;
683 _current = initial;
684
685 _extent = box;
686 }
687
GfxMultCompButton(gPanelList & list,const Rect16 & box,void ** newImages,int16 numRes,int16 initial,bool hitResponse,uint16 ident,AppFunc * cmd)688 GfxMultCompButton::GfxMultCompButton(gPanelList &list, const Rect16 &box, void **newImages,
689 int16 numRes, int16 initial, bool hitResponse, uint16 ident,
690 AppFunc *cmd) : GfxCompButton(list, box, (hResContext *)NULL, 0, ident, cmd) {
691 if (!newImages) {
692 _images = NULL;
693 _max = 0;
694 _min = 0;
695 _current = 0;
696 _response = hitResponse;
697 return;
698 }
699
700 _images = newImages;
701
702 _response = hitResponse;
703 _internalAlloc = false;
704 _max = numRes - 1;
705 _min = 0;
706 _current = initial;
707
708 _extent = box;
709 }
710
~GfxMultCompButton(void)711 GfxMultCompButton::~GfxMultCompButton(void) {
712 int16 i;
713
714 if (_images && _internalAlloc) {
715 for (i = 0; i <= _max; i++) {
716 if (_images[i]) {
717 free(_images[i]);
718 }
719 }
720
721 free(_images);
722 _images = NULL;
723 }
724 }
725
activate(gEventType why)726 bool GfxMultCompButton::activate(gEventType why) {
727 if (why == gEventKeyDown || why == gEventMouseDown) {
728 if (_response) {
729 if (++_current > _max) {
730 _current = 0;
731 }
732 window.update(_extent);
733 }
734
735 gPanel::deactivate();
736 notify(gEventNewValue, _current); // notify App of successful hit
737 playMemSound(1);
738 // playSound( MKTAG('C','B','T',5) );
739 }
740 return false;
741 }
742
pointerHit(gPanelMessage &)743 bool GfxMultCompButton::pointerHit(gPanelMessage &) {
744 return activate(gEventMouseDown);
745 }
746
getCurrentCompImage(void)747 void *GfxMultCompButton::getCurrentCompImage(void) {
748 return _images[_current];
749 }
750
751 /* ===================================================================== *
752 GfxSlider class
753 * ===================================================================== */
754
GfxSlider(gPanelList & list,const Rect16 & box,const Rect16 & imageBox,int16 sliderStart,int16 sliderEnd,void ** newImages,int16 resStart,int16 initial,uint16 ident,AppFunc * cmd)755 GfxSlider::GfxSlider(gPanelList &list, const Rect16 &box, const Rect16 &imageBox,
756 int16 sliderStart, int16 sliderEnd, void **newImages, int16 resStart,
757 int16 initial, uint16 ident,
758 AppFunc *cmd) : GfxMultCompButton(list, box, newImages, resStart, initial, ident, cmd) {
759 int16 calcX;
760
761 _imageRect = imageBox;
762 _slValMin = sliderStart;
763 _slValMax = sliderEnd;
764 _slCurrent = initial;
765
766 // find out the position of the slider
767 calcX = (_slValMax * 100) / clamp(1, _slCurrent, _slCurrent);
768 calcX = (_extent.width * 100) / clamp(1, calcX, calcX);
769
770 _imagePosX = clamp(_extent.x,
771 calcX,
772 _extent.width - _imageRect.x);
773 }
774
getCurrentCompImage(void)775 void *GfxSlider::getCurrentCompImage(void) {
776 int16 val;
777 int32 index;
778
779 val = getSliderLenVal();
780
781 // max == number of images in array indexing;
782
783 index = val / clamp(1, _max + 1, _max + 1);
784
785 index = _slCurrent / clamp(1, index, index);
786
787 index = clamp(0, index, _max);
788
789 return _images[index];
790 }
791
getSliderLenVal(void)792 int16 GfxSlider::getSliderLenVal(void) {
793 int16 val = 0;
794
795 if (_slValMin < 0 && _slValMax < 0) {
796 val = _slValMax - _slValMin;
797 } else if (_slValMin < 0 && _slValMax >= 0) {
798 val = ABS(_slValMin) + _slValMax;
799 } else if (_slValMin >= 0 && _slValMax < 0) {
800 val = ABS(_slValMax) - _slValMin;
801 } else if (_slValMin >= 0 && _slValMax >= 0) {
802 val = _slValMax - _slValMin;
803 }
804
805 return val;
806 }
807
draw(void)808 void GfxSlider::draw(void) {
809 gPort &port = window.windowPort;
810 Point16 offset = Point16(0, 0);
811
812 SAVE_GPORT_STATE(port); // save pen color, etc.
813 g_vm->_pointer->hide(port, _extent); // hide mouse pointer
814 drawClipped(port, offset, Rect16(0, 0, _imageRect.width, _imageRect.height));
815 g_vm->_pointer->show(port, _extent); // show mouse pointer
816 }
817
818
quantizedVolume(uint16 trueVolume)819 inline int16 quantizedVolume(uint16 trueVolume) {
820 int16 quantized = trueVolume & 0xFFF8;
821 quantized += (quantized / 16);
822 return quantized;
823 }
824
drawClipped(gPort & port,const Point16 & offset,const Rect16 & r)825 void GfxSlider::drawClipped(gPort &port,
826 const Point16 &offset,
827 const Rect16 &r) {
828 void *dispImage = getCurrentCompImage();
829 if (dispImage) {
830 if (_extent.overlap(r)) {
831 Point16 pos(_imagePosX - offset.x,
832 _extent.y - offset.y
833 );
834 if (isGhosted()) drawCompressedImageGhosted(port, pos, dispImage);
835 else drawCompressedImage(port, pos, dispImage);
836 }
837 }
838 }
839
activate(gEventType why)840 bool GfxSlider::activate(gEventType why) {
841 if (why == gEventKeyDown || why == gEventMouseDown) {
842 selected = 1;
843 window.update(_extent);
844 gPanel::deactivate();
845 notify(gEventNewValue, _slCurrent); // notify App of successful hit
846 }
847 return false;
848 }
849
deactivate(void)850 void GfxSlider::deactivate(void) {
851 selected = 0;
852 window.update(_extent);
853 gPanel::deactivate();
854 }
855
pointerHit(gPanelMessage & msg)856 bool GfxSlider::pointerHit(gPanelMessage &msg) {
857 // update the image index
858 updateSliderIndexes(msg.pickPos);
859
860 // redraw the control should any visual change hath occured
861 window.update(_extent);
862
863 activate(gEventMouseDown);
864 return true;
865 }
866
pointerMove(gPanelMessage & msg)867 void GfxSlider::pointerMove(gPanelMessage &msg) {
868 if (selected) {
869 // update the image index
870 updateSliderIndexes(msg.pickPos);
871
872 // redraw the control should any visual change hath occured
873 window.update(_extent);
874
875 notify(gEventMouseMove, _slCurrent);
876 }
877 }
878
pointerRelease(gPanelMessage &)879 void GfxSlider::pointerRelease(gPanelMessage &) {
880 // We have to test selected first because deactivate clears it.
881 if (selected) {
882 deactivate(); // give back input focus
883 notify(gEventNewValue, _slCurrent); // notify App of successful hit
884 } else deactivate();
885 }
886
pointerDrag(gPanelMessage & msg)887 void GfxSlider::pointerDrag(gPanelMessage &msg) {
888 // update the image index
889 updateSliderIndexes(msg.pickPos);
890
891 notify(gEventNewValue, _slCurrent); // notify App of successful hit
892 // redraw the control should any visual change hath occured
893 window.update(_extent);
894 }
895
updateSliderIndexes(Point16 & pos)896 void GfxSlider::updateSliderIndexes(Point16 &pos) {
897 pos.x = quantizedVolume(pos.x);
898 // get x position units
899 int32 unit = (_extent.width * 100) / clamp(1, pos.x, _extent.width);
900
901 // find the ratio and get the current slider value
902 _slCurrent = (_slValMax * 100) / clamp(1, unit, unit);
903
904 // update the image position index
905 _imagePosX = clamp(_extent.x,
906 pos.x,
907 _extent.width - _imageRect.x);
908 }
909
910 } // end of namespace Saga2
911