mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-10 11:51:52 +00:00
955 lines
26 KiB
C++
955 lines
26 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* 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.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*
|
|
* Based on the original sources
|
|
* Faery Tale II -- The Halls of the Dead
|
|
* (c) 1993-1996 The Wyrmkeep Entertainment Co.
|
|
*/
|
|
|
|
#define FORBIDDEN_SYMBOL_ALLOW_ALL // FIXME: Remove
|
|
|
|
#include "saga2/std.h"
|
|
#include "saga2/fta.h"
|
|
#include "saga2/cmisc.h"
|
|
#include "saga2/hresmgr.h"
|
|
#include "saga2/button.h"
|
|
#include "saga2/rmem.h"
|
|
#include "saga2/objects.h"
|
|
#include "saga2/grabinfo.h"
|
|
#include "saga2/fontlib.h"
|
|
|
|
namespace Saga2 {
|
|
|
|
typedef void *pVOID;
|
|
typedef pVOID apVOID[];
|
|
|
|
extern void playMemSound(uint32 s); // play click # s
|
|
|
|
/* ======================================================================= *
|
|
Compressed image class
|
|
* ======================================================================= */
|
|
|
|
void gCompImage::init(void) {
|
|
compImages = NULL;
|
|
max = 0;
|
|
min = 0;
|
|
internalAlloc = FALSE;
|
|
currentImage = 0;
|
|
numPtrAlloc = 0;
|
|
// imageText[ 0 ] = NULL;
|
|
}
|
|
|
|
gCompImage::gCompImage(gPanelList &list, const Rect16 &box, void *image, uint16 ident,
|
|
AppFunc *cmd) : gControl(list, box, NULL, ident, cmd) {
|
|
// setup a single image configuration
|
|
|
|
init();
|
|
|
|
if (image) {
|
|
compImages = (void **)malloc(sizeof(pVOID) * 1); // allocate room for one pointer
|
|
compImages[ 0 ] = image;
|
|
internalAlloc = FALSE;
|
|
numPtrAlloc = 1;
|
|
}
|
|
}
|
|
|
|
gCompImage::gCompImage(gPanelList &list,
|
|
const Rect16 &box,
|
|
uint32 contextID,
|
|
char a, char b, char c,
|
|
uint16 resNum, uint16 numImages,
|
|
uint16 ident,
|
|
AppFunc *cmd) : gControl(list, box, NULL, ident, cmd) {
|
|
uint16 i, rNum;
|
|
|
|
init();
|
|
|
|
// init the resource context handle
|
|
hResContext *resContext = resFile->newContext(contextID, "container window resource");
|
|
|
|
// setup for a numImages image configuration
|
|
compImages = (void **)malloc(sizeof(void *)*numImages); // allocate room for numImages pointers
|
|
|
|
for (i = 0, rNum = resNum; i < numImages; i++, rNum++) {
|
|
compImages[ i ] = LoadResource(resContext,
|
|
MKTAG(a, b, c, rNum),
|
|
" gCompImage ");
|
|
}
|
|
|
|
max = numImages - 1;
|
|
internalAlloc = TRUE;
|
|
numPtrAlloc = numImages;
|
|
|
|
// get rid of this context
|
|
resFile->disposeContext(resContext);
|
|
resContext = NULL;
|
|
}
|
|
|
|
gCompImage::gCompImage(gPanelList &list, const Rect16 &box, void *image, const char *text, textPallete &pal, uint16 ident,
|
|
AppFunc *cmd) : gControl(list, box, text, ident, cmd) {
|
|
// setup a single image configuration
|
|
init();
|
|
|
|
if (!image) return;
|
|
|
|
compImages = (void **)malloc(sizeof(void *) * 1); // allocate room for one pointer
|
|
|
|
compImages[ 0 ] = image;
|
|
max = 0;
|
|
numPtrAlloc = 1;
|
|
title = text;
|
|
textFont = &Onyx10Font; // >>> this should be dynamic
|
|
textPal = pal;
|
|
|
|
#if 0
|
|
// setup the text if any
|
|
if (text) {
|
|
// copy the maximum number of chars to the text buffer
|
|
strncpy(imageText, text, textSize);
|
|
|
|
// cap it, in case of overflow
|
|
imageText[ textSize - 1 ] = NULL;
|
|
|
|
// setup the text pallete and font type
|
|
textPal = pal;
|
|
textFont = &Onyx10Font; // >>> this should be dynamic
|
|
} else {
|
|
*imageText = NULL;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
gCompImage::gCompImage(gPanelList &list, const Rect16 &box, void **images,
|
|
int16 numRes, int16 initial,
|
|
uint16 ident, AppFunc *cmd) : gControl(list, box, NULL, ident, cmd) {
|
|
init();
|
|
|
|
if (!images) return;
|
|
|
|
compImages = images;
|
|
|
|
// set up limits
|
|
max = numRes - 1;
|
|
currentImage = clamp(min, initial, max);
|
|
}
|
|
|
|
gCompImage::gCompImage(gPanelList &list, const Rect16 &box, void **images,
|
|
int16 numRes, int16 initial, const char *text, textPallete &pal,
|
|
uint16 ident, AppFunc *cmd) : gControl(list, box, text, ident, cmd) {
|
|
init();
|
|
|
|
if (images) {
|
|
compImages = images;
|
|
|
|
// set up limits
|
|
max = numRes - 1;
|
|
currentImage = clamp(min, initial, max);
|
|
}
|
|
|
|
title = text;
|
|
textFont = &Onyx10Font; // >>> this should be dynamic
|
|
textPal = pal;
|
|
|
|
#if 0
|
|
// setup the text if any
|
|
if (text) {
|
|
// copy the maximum number of chars to the text buffer
|
|
strncpy(imageText, text, textSize);
|
|
|
|
// cap it, in case of overflow
|
|
imageText[ textSize - 1 ] = NULL;
|
|
textPal = pal;
|
|
textFont = &Onyx10Font; // >>> this should be dynamic
|
|
} else {
|
|
*imageText = NULL;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
gCompImage::~gCompImage(void) {
|
|
// delete any allocated image pointers
|
|
// for JEFFL: I took out the winklude #ifdefs becuase I belive
|
|
// I fixed the problem that was causing the crash under win32
|
|
// 11-14-95, I should talk to you tommorow. This is note is
|
|
// a precaution
|
|
|
|
// if we LoadRes'ed image internally RDispose those
|
|
if (internalAlloc) {
|
|
for (int16 i = 0; i < numPtrAlloc; i++) {
|
|
RDisposePtr(compImages[ i ]);
|
|
}
|
|
}
|
|
|
|
// delete any pointer arrays new'ed
|
|
if (numPtrAlloc > 0) {
|
|
delete compImages;
|
|
}
|
|
}
|
|
|
|
void gCompImage::pointerMove(gPanelMessage &msg) {
|
|
// call the superclass's pointerMove
|
|
gControl::pointerMove(msg);
|
|
|
|
notify(gEventMouseMove, (msg.pointerEnter ? enter : 0) | (msg.pointerLeave ? leave : 0));
|
|
}
|
|
|
|
void gCompImage::enable(bool abled) {
|
|
gPanel::enable(abled);
|
|
}
|
|
|
|
void gCompImage::invalidate(void) {
|
|
window.update(extent);
|
|
}
|
|
|
|
void gCompImage::draw(void) {
|
|
gPort &port = window.windowPort;
|
|
Rect16 rect = window.getExtent();
|
|
|
|
SAVE_GPORT_STATE(port); // save pen color, etc.
|
|
pointer.hide(port, extent); // hide mouse pointer
|
|
drawClipped(port,
|
|
Point16(0, 0),
|
|
Rect16(0, 0, rect.width, rect.height));
|
|
pointer.show(port, extent); // show mouse pointer
|
|
}
|
|
|
|
void *gCompImage::getCurrentCompImage(void) {
|
|
if (compImages) {
|
|
return compImages[ currentImage ]; // return the image pointed to by compImage
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
// waring! : the number of images has has to be == to the inital number
|
|
void gCompImage::setImages(void **images) {
|
|
if (images) {
|
|
compImages = images;
|
|
}
|
|
}
|
|
|
|
void gCompImage::setImage(void *image) {
|
|
if (image) {
|
|
compImages[ 0 ] = image;
|
|
max = 0;
|
|
currentImage = 0;
|
|
}
|
|
}
|
|
|
|
void gCompImage::select(uint16 val) {
|
|
setCurrent(val);
|
|
|
|
if (getEnabled()) {
|
|
window.update(extent);
|
|
}
|
|
}
|
|
|
|
void gCompImage::select(uint16 val, const Rect16 &rect) {
|
|
select(val);
|
|
setExtent(rect);
|
|
}
|
|
|
|
void gCompImage::setExtent(const Rect16 &rect) {
|
|
// set the new extent
|
|
extent = rect;
|
|
}
|
|
|
|
// getCurrentCompImage() is virtual function that should return
|
|
// the current image to be displayed (to be used across all sub-classes)
|
|
void gCompImage::drawClipped(gPort &port,
|
|
const Point16 &offset,
|
|
const Rect16 &r) {
|
|
if (!extent.overlap(r)) return;
|
|
|
|
SAVE_GPORT_STATE(port);
|
|
|
|
// get the current image
|
|
void *dispImage = getCurrentCompImage();
|
|
|
|
// make sure the image is valid
|
|
if (dispImage) {
|
|
// will part of this be drawn on screen?
|
|
if (extent.overlap(r)) {
|
|
// offset the image?
|
|
Point16 pos(extent.x - offset.x,
|
|
extent.y - offset.y
|
|
);
|
|
// draw the compressed image
|
|
if (isGhosted()) drawCompressedImageGhosted(port, pos, dispImage);
|
|
else drawCompressedImage(port, pos, dispImage);
|
|
|
|
// this could be modified to get the current text coloring
|
|
if (title) {
|
|
Rect16 textRect = extent;
|
|
textRect.x -= offset.x;
|
|
textRect.y -= offset.y;
|
|
|
|
writePlaqText(port, textRect, textFont, NULL, textPal, selected, title);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ===================================================================== *
|
|
gCompImageButton class member functions
|
|
* ===================================================================== */
|
|
|
|
gSpriteImage::gSpriteImage(gPanelList &list, const Rect16 &box, GameObject *object, char,
|
|
uint16 ident, AppFunc *cmd) : gCompImage(list, box, NULL, ident, cmd) {
|
|
// get the prototype for the object
|
|
ProtoObj *proto = object->proto();
|
|
|
|
// assign the sprites remapped colors
|
|
object->getColorTranslation(objColors);
|
|
|
|
// assing the sprite pointer
|
|
sprPtr = proto->getSprite(object, ProtoObj::objInContainerView).sp;
|
|
}
|
|
|
|
// getCurrentCompImage() is virtual function that should return
|
|
// the current image to be displayed (to be used across all sub-classes)
|
|
void gSpriteImage::drawClipped(gPort &port,
|
|
const Point16 &offset,
|
|
const Rect16 &r) {
|
|
if (!extent.overlap(r)) return;
|
|
|
|
SAVE_GPORT_STATE(port);
|
|
|
|
// if there's a sprite present
|
|
gPixelMap map;
|
|
|
|
//map.size = Point16( extent.height, extent.width );
|
|
map.size = sprPtr->size;
|
|
|
|
map.data = (uint8 *)RNewPtr(map.bytes(), NULL, "gcomp image sprite decompression map");
|
|
if (map.data == NULL) return;
|
|
|
|
memset(map.data, 0, map.bytes());
|
|
|
|
// Render the sprite into the bitmap image sequence
|
|
ExpandColorMappedSprite(map, sprPtr, objColors);
|
|
|
|
port.setMode(drawModeMatte);
|
|
port.bltPixels(map, 0, 0,
|
|
extent.x - offset.x, extent.y - offset.y,
|
|
map.size.x, map.size.y);
|
|
|
|
RDisposePtr(map.data);
|
|
}
|
|
|
|
/* ===================================================================== *
|
|
gCompImageButton class member functions
|
|
* ===================================================================== */
|
|
|
|
void gCompButton::loadImages(hResContext *con, hResID res1, hResID res2) {
|
|
if (con) {
|
|
checkAlloc(forImage = LoadResource(con, res1, "CBtn fore image"));
|
|
checkAlloc(resImage = LoadResource(con, res2, "CBtn res image"));
|
|
dimImage = NULL;
|
|
} else {
|
|
forImage = NULL;
|
|
resImage = NULL;
|
|
dimImage = NULL;
|
|
}
|
|
|
|
internalAlloc = TRUE;
|
|
dimmed = FALSE;
|
|
}
|
|
|
|
void gCompButton::loadImages(hResID contextID, hResID res1, hResID res2) {
|
|
// init the resource context handle
|
|
hResContext *con = resFile->newContext(contextID,
|
|
"container window resource");
|
|
|
|
loadImages(con, res1, res2);
|
|
resFile->disposeContext(con); // get rid of this context
|
|
}
|
|
|
|
gCompButton::gCompButton(gPanelList &list, const Rect16 &box, hResContext *con, hResID resID1, hResID resID2, uint16 ident,
|
|
AppFunc *cmd) : gCompImage(list, box, NULL, ident, cmd), extent(box) {
|
|
loadImages(con, resID1, resID2);
|
|
}
|
|
|
|
gCompButton::gCompButton(gPanelList &list, const Rect16 &box, hResID contextID, hResID resID1, hResID resID2, uint16 ident,
|
|
AppFunc *cmd) : gCompImage(list, box, NULL, ident, cmd), extent(box) {
|
|
loadImages(contextID, resID1, resID2);
|
|
}
|
|
|
|
gCompButton::gCompButton(gPanelList &list, const Rect16 &box, hResContext *con, char a, char b, char c, int16 butNum_1, int16 butNum_2, uint16 ident,
|
|
AppFunc *cmd) : gCompImage(list, box, NULL, ident, cmd), extent(box) {
|
|
loadImages(con, MKTAG(a, b, c, butNum_1), MKTAG(a, b, c, butNum_2));
|
|
}
|
|
|
|
gCompButton::gCompButton(gPanelList &list, const Rect16 &box, hResID contextID, char a, char b, char c, int16 butNum_1, int16 butNum_2, uint16 ident,
|
|
AppFunc *cmd) : gCompImage(list, box, NULL, ident, cmd), extent(box) {
|
|
loadImages(contextID, MKTAG(a, b, c, butNum_1), MKTAG(a, b, c, butNum_2));
|
|
}
|
|
|
|
gCompButton::gCompButton(gPanelList &list, const Rect16 &box, hResContext *con, int16 butNum, uint16 ident,
|
|
AppFunc *cmd) : gCompImage(list, box, NULL, ident, cmd), extent(box) {
|
|
loadImages(con, MKTAG('B', 'T', 'N', butNum), MKTAG('B', 'T', 'N', butNum + 1));
|
|
}
|
|
|
|
gCompButton::gCompButton(gPanelList &list, const Rect16 &box, void **images, int16 numRes, uint16 ident,
|
|
AppFunc *cmd) : gCompImage(list, box, NULL, ident, cmd) {
|
|
if (images[ 0 ] && images[ 1 ] && numRes == 2) {
|
|
forImage = images[ 0 ];
|
|
resImage = images[ 1 ];
|
|
dimImage = NULL;
|
|
} else {
|
|
forImage = NULL;
|
|
resImage = NULL;
|
|
dimImage = NULL;
|
|
}
|
|
|
|
internalAlloc = FALSE;
|
|
dimmed = FALSE;
|
|
extent = box;
|
|
}
|
|
|
|
gCompButton::gCompButton(gPanelList &list, const Rect16 &box, void **images, int16 numRes, const char *text, textPallete &pal, uint16 ident,
|
|
AppFunc *cmd) : gCompImage(list, box, NULL, 0, 0, text, pal, ident, cmd) {
|
|
if (images[ 0 ] && images[ 1 ] && numRes == 2) {
|
|
forImage = images[ 0 ];
|
|
resImage = images[ 1 ];
|
|
dimImage = NULL;
|
|
} else {
|
|
forImage = NULL;
|
|
resImage = NULL;
|
|
dimImage = NULL;
|
|
}
|
|
|
|
internalAlloc = FALSE;
|
|
dimmed = FALSE;
|
|
extent = box;
|
|
}
|
|
|
|
gCompButton::gCompButton(gPanelList &list, const Rect16 &box, void **images, int16 numRes, void *newDimImage, bool dimNess, uint16 ident,
|
|
AppFunc *cmd) : gCompImage(list, box, NULL, ident, cmd) {
|
|
if (images[ 0 ] && images[ 1 ] && numRes == 2) {
|
|
forImage = images[ 0 ];
|
|
resImage = images[ 1 ];
|
|
} else {
|
|
forImage = NULL;
|
|
resImage = NULL;
|
|
}
|
|
|
|
if (newDimImage) {
|
|
dimImage = newDimImage;
|
|
} else {
|
|
dimImage = NULL;
|
|
}
|
|
|
|
internalAlloc = FALSE;
|
|
dimmed = dimNess;
|
|
extent = box;
|
|
}
|
|
|
|
|
|
gCompButton::gCompButton(gPanelList &list, const Rect16 &box, void *image, uint16 ident,
|
|
AppFunc *cmd) : gCompImage(list, box, NULL, ident, cmd)
|
|
|
|
{
|
|
if (image) {
|
|
forImage = image;
|
|
resImage = image;
|
|
dimImage = NULL;
|
|
} else {
|
|
forImage = NULL;
|
|
resImage = NULL;
|
|
dimImage = NULL;
|
|
}
|
|
|
|
internalAlloc = FALSE;
|
|
dimmed = FALSE;
|
|
extent = box;
|
|
}
|
|
|
|
|
|
gCompButton::~gCompButton(void) {
|
|
if (internalAlloc) {
|
|
if (forImage) {
|
|
RDisposePtr(forImage);
|
|
forImage = NULL;
|
|
}
|
|
|
|
if (resImage) {
|
|
RDisposePtr(resImage);
|
|
resImage = NULL;
|
|
}
|
|
|
|
if (dimImage) {
|
|
RDisposePtr(dimImage);
|
|
dimImage = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
void gCompButton::dim(bool enable) {
|
|
if (enable) {
|
|
if (!dimmed) dimmed = TRUE;
|
|
} else {
|
|
if (dimmed) dimmed = FALSE;
|
|
}
|
|
|
|
window.update(extent);
|
|
}
|
|
|
|
|
|
void gCompButton::deactivate(void) {
|
|
selected = 0;
|
|
window.update(extent);
|
|
gPanel::deactivate();
|
|
}
|
|
|
|
bool gCompButton::activate(gEventType why) {
|
|
selected = 1;
|
|
window.update(extent);
|
|
|
|
if (why == gEventKeyDown) { // momentarily depress
|
|
#ifndef _WIN32
|
|
g_system->delayMillis(200);
|
|
#endif
|
|
deactivate();
|
|
notify(gEventNewValue, 1); // notify App of successful hit
|
|
}
|
|
playMemSound(2);
|
|
return FALSE;
|
|
}
|
|
|
|
void gCompButton::pointerMove(gPanelMessage &msg) {
|
|
if (dimmed) return;
|
|
|
|
//notify( gEventMouseMove, (msg.pointerEnter ? enter : 0)|(msg.pointerLeave ? leave : 0));
|
|
gCompImage::pointerMove(msg);
|
|
}
|
|
|
|
bool gCompButton::pointerHit(gPanelMessage &) {
|
|
if (dimmed) return FALSE;
|
|
|
|
activate(gEventMouseDown);
|
|
return TRUE;
|
|
}
|
|
|
|
void gCompButton::pointerRelease(gPanelMessage &) {
|
|
// We have to test selected first because deactivate clears it.
|
|
|
|
if (selected) {
|
|
deactivate(); // give back input focus
|
|
notify(gEventNewValue, 1); // notify App of successful hit
|
|
} else deactivate();
|
|
}
|
|
|
|
void gCompButton::pointerDrag(gPanelMessage &msg) {
|
|
if (selected != msg.inPanel) {
|
|
selected = msg.inPanel;
|
|
window.update(extent);
|
|
}
|
|
}
|
|
|
|
void gCompButton::enable(bool abled) {
|
|
gPanel::enable(abled);
|
|
}
|
|
|
|
void gCompButton::invalidate(void) {
|
|
window.update(extent);
|
|
}
|
|
|
|
|
|
void gCompButton::draw(void) {
|
|
gPort &port = window.windowPort;
|
|
Rect16 rect = window.getExtent();
|
|
|
|
SAVE_GPORT_STATE(port); // save pen color, etc.
|
|
pointer.hide(port, extent); // hide mouse pointer
|
|
drawClipped(port, Point16(0, 0), Rect16(0, 0, rect.width, rect.height));
|
|
pointer.show(port, extent); // show mouse pointer
|
|
}
|
|
|
|
void *gCompButton::getCurrentCompImage(void) {
|
|
if (dimmed) {
|
|
return dimImage;
|
|
} else if (selected) {
|
|
return resImage;
|
|
} else {
|
|
return forImage;
|
|
}
|
|
}
|
|
|
|
/************************************************************************
|
|
* gToggleCompButton -- like a gCompButton but toggle on and off. *
|
|
************************************************************************/
|
|
|
|
gToggleCompButton::gToggleCompButton(gPanelList &list, const Rect16 &box, hResContext *con, char a, char b, char c, int16 butNum_1, int16 butNum_2, uint16 ident,
|
|
AppFunc *cmd) : gCompButton(list, box, con, a, b, c, butNum_1, butNum_2, ident, cmd) {
|
|
|
|
}
|
|
|
|
|
|
gToggleCompButton::gToggleCompButton(gPanelList &list, const Rect16 &box, hResContext *con, int16 butNum, uint16 ident,
|
|
AppFunc *cmd) : gCompButton(list, box, con, butNum, ident, cmd) {
|
|
|
|
}
|
|
|
|
gToggleCompButton::gToggleCompButton(gPanelList &list, const Rect16 &box, void **images, int16 butRes, uint16 ident,
|
|
AppFunc *cmd) : gCompButton(list, box, images, butRes, ident, cmd) {
|
|
|
|
}
|
|
|
|
gToggleCompButton::gToggleCompButton(gPanelList &list, const Rect16 &box, void **images, int16 butRes, char *text, textPallete &pal, uint16 ident,
|
|
AppFunc *cmd) : gCompButton(list, box, images, butRes, text, pal, ident, cmd) {
|
|
|
|
}
|
|
|
|
bool gToggleCompButton::activate(gEventType why) {
|
|
if (why == gEventKeyDown || why == gEventMouseDown) {
|
|
// playSound( MKTAG('C','B','T',3) );
|
|
|
|
selected = !selected;
|
|
window.update(extent);
|
|
gPanel::deactivate();
|
|
notify(gEventNewValue, selected); // notify App of successful hit
|
|
playMemSound(1);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
bool gToggleCompButton::pointerHit(gPanelMessage &) {
|
|
return activate(gEventMouseDown);
|
|
}
|
|
|
|
void gToggleCompButton::select(uint16 val) {
|
|
selected = val;
|
|
|
|
setCurrent(val);
|
|
|
|
if (getEnabled()) {
|
|
window.update(extent);
|
|
}
|
|
}
|
|
|
|
|
|
/************************************************************************
|
|
* gOwnerSelCompButton -- like a gCompButton but does not chage the *
|
|
* selector bit *
|
|
************************************************************************/
|
|
|
|
gOwnerSelCompButton::gOwnerSelCompButton(gPanelList &list, const Rect16 &box, void **images, int16 butRes, uint16 ident,
|
|
AppFunc *cmd) : gCompButton(list, box, images, butRes, ident, cmd) {
|
|
|
|
}
|
|
|
|
bool gOwnerSelCompButton::activate(gEventType why) {
|
|
if (why == gEventKeyDown || why == gEventMouseDown) {
|
|
// selected = !selected;
|
|
// window.update( extent );
|
|
gPanel::deactivate();
|
|
notify(gEventNewValue, selected); // notify App of successful hit
|
|
playMemSound(2);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
bool gOwnerSelCompButton::pointerHit(gPanelMessage &) {
|
|
return activate(gEventMouseDown);
|
|
}
|
|
|
|
void gOwnerSelCompButton::select(uint16 val) {
|
|
selected = val;
|
|
|
|
setCurrent(val);
|
|
|
|
if (getEnabled()) {
|
|
window.update(extent);
|
|
}
|
|
}
|
|
|
|
/************************************************************************
|
|
* gMultCompButton -- like gCompButton but does any number of images *
|
|
************************************************************************/
|
|
|
|
gMultCompButton::gMultCompButton(gPanelList &list, const Rect16 &box, hResContext *con, char a, char b, char c, int16 resStart, int16 numRes, int16 initial, uint16 ident,
|
|
AppFunc *cmd) : gCompButton(list, box, (hResContext *)NULL, 0, ident, cmd) {
|
|
int16 i, k;
|
|
|
|
|
|
images = (void **)malloc(sizeof(void *)*numRes);
|
|
|
|
for (i = 0, k = resStart; i < numRes; i++, k++) {
|
|
images[ i ] = LoadResource(con, MKTAG(a, b, c, k), "Multi btn image");
|
|
|
|
checkAlloc(images[ i ]);
|
|
}
|
|
|
|
response = TRUE;
|
|
internalAlloc = TRUE;
|
|
max = numRes - 1;
|
|
min = 0;
|
|
current = clamp(min, initial, max);
|
|
|
|
extent = box;
|
|
}
|
|
|
|
gMultCompButton::gMultCompButton(gPanelList &list, const Rect16 &box, void **newImages, int16 numRes, int16 initial, uint16 ident,
|
|
AppFunc *cmd) : gCompButton(list, box, (hResContext *)NULL, 0, ident, cmd) {
|
|
if (!newImages) {
|
|
images = NULL;
|
|
max = 0;
|
|
min = 0;
|
|
current = 0;
|
|
return;
|
|
}
|
|
|
|
images = newImages;
|
|
|
|
response = TRUE;
|
|
internalAlloc = FALSE;
|
|
max = numRes - 1;
|
|
min = 0;
|
|
current = initial;
|
|
|
|
extent = box;
|
|
}
|
|
|
|
gMultCompButton::gMultCompButton(gPanelList &list, const Rect16 &box, void **newImages,
|
|
int16 numRes, int16 initial, bool hitResponse, uint16 ident,
|
|
AppFunc *cmd) : gCompButton(list, box, (hResContext *)NULL, 0, ident, cmd) {
|
|
if (!newImages) {
|
|
images = NULL;
|
|
max = 0;
|
|
min = 0;
|
|
current = 0;
|
|
return;
|
|
}
|
|
|
|
images = newImages;
|
|
|
|
response = hitResponse;
|
|
internalAlloc = FALSE;
|
|
max = numRes - 1;
|
|
min = 0;
|
|
current = initial;
|
|
|
|
extent = box;
|
|
}
|
|
|
|
gMultCompButton::~gMultCompButton(void) {
|
|
int16 i;
|
|
|
|
if (images && internalAlloc) {
|
|
for (i = 0; i <= max; i++) {
|
|
if (images[ i ]) {
|
|
RDisposePtr(images[ i ]);
|
|
}
|
|
}
|
|
|
|
delete images;
|
|
images = NULL;
|
|
}
|
|
}
|
|
|
|
bool gMultCompButton::activate(gEventType why) {
|
|
if (why == gEventKeyDown || why == gEventMouseDown) {
|
|
if (response) {
|
|
if (++current > max) {
|
|
current = 0;
|
|
}
|
|
window.update(extent);
|
|
}
|
|
|
|
gPanel::deactivate();
|
|
notify(gEventNewValue, current); // notify App of successful hit
|
|
playMemSound(1);
|
|
// playSound( MKTAG('C','B','T',5) );
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
bool gMultCompButton::pointerHit(gPanelMessage &) {
|
|
return activate(gEventMouseDown);
|
|
}
|
|
|
|
void *gMultCompButton::getCurrentCompImage(void) {
|
|
return images[ current ];
|
|
}
|
|
|
|
/* ===================================================================== *
|
|
gSlider class
|
|
* ===================================================================== */
|
|
|
|
gSlider::gSlider(gPanelList &list, const Rect16 &box, const Rect16 &imageBox,
|
|
int16 sliderStart, int16 sliderEnd, void **newImages, int16 resStart,
|
|
int16 initial, uint16 ident,
|
|
AppFunc *cmd) : gMultCompButton(list, box, newImages, resStart, initial, ident, cmd) {
|
|
int16 calcX;
|
|
|
|
imageRect = imageBox;
|
|
slValMin = sliderStart;
|
|
slValMax = sliderEnd;
|
|
slCurrent = initial;
|
|
|
|
// find out the position of the slider
|
|
calcX = (slValMax * 100) / clamp(1, slCurrent, slCurrent);
|
|
calcX = (extent.width * 100) / clamp(1, calcX, calcX);
|
|
|
|
imagePosX = clamp(extent.x,
|
|
calcX,
|
|
extent.width - imageRect.x);
|
|
}
|
|
|
|
void *gSlider::getCurrentCompImage(void) {
|
|
int16 val;
|
|
int32 index;
|
|
|
|
val = getSliderLenVal();
|
|
|
|
// max == number of images in array indexing;
|
|
|
|
index = val / clamp(1, max + 1, max + 1);
|
|
|
|
index = slCurrent / clamp(1, index, index);
|
|
|
|
index = clamp(0, index, max);
|
|
|
|
return images[ index ];
|
|
}
|
|
|
|
int16 gSlider::getSliderLenVal(void) {
|
|
int16 val;
|
|
|
|
if (slValMin < 0 && slValMax < 0) {
|
|
val = slValMax - slValMin;
|
|
} else if (slValMin < 0 && slValMax >= 0) {
|
|
val = abs(slValMin) + slValMax;
|
|
} else if (slValMin >= 0 && slValMax < 0) {
|
|
val = abs(slValMax) - slValMin;
|
|
} else if (slValMin >= 0 && slValMax >= 0) {
|
|
val = slValMax - slValMin;
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
void gSlider::draw(void) {
|
|
gPort &port = window.windowPort;
|
|
Rect16 rect = window.getExtent();
|
|
Point16 offset = Point16(0, 0);
|
|
|
|
SAVE_GPORT_STATE(port); // save pen color, etc.
|
|
pointer.hide(port, extent); // hide mouse pointer
|
|
drawClipped(port, offset, Rect16(0, 0, imageRect.width, imageRect.height));
|
|
pointer.show(port, extent); // show mouse pointer
|
|
}
|
|
|
|
|
|
inline int16 quantizedVolume(uint16 trueVolume) {
|
|
int16 quantized = trueVolume & 0xFFF8;
|
|
quantized += (quantized / 16);
|
|
return quantized;
|
|
}
|
|
|
|
void gSlider::drawClipped(gPort &port,
|
|
const Point16 &offset,
|
|
const Rect16 &r) {
|
|
void *dispImage = getCurrentCompImage();
|
|
if (dispImage) {
|
|
if (extent.overlap(r)) {
|
|
Point16 pos(imagePosX - offset.x,
|
|
extent.y - offset.y
|
|
);
|
|
if (isGhosted()) drawCompressedImageGhosted(port, pos, dispImage);
|
|
else drawCompressedImage(port, pos, dispImage);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool gSlider::activate(gEventType why) {
|
|
if (why == gEventKeyDown || why == gEventMouseDown) {
|
|
selected = 1;
|
|
window.update(extent);
|
|
gPanel::deactivate();
|
|
notify(gEventNewValue, slCurrent); // notify App of successful hit
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
void gSlider::deactivate(void) {
|
|
selected = 0;
|
|
window.update(extent);
|
|
gPanel::deactivate();
|
|
}
|
|
|
|
bool gSlider::pointerHit(gPanelMessage &msg) {
|
|
// update the image index
|
|
updateSliderIndexes(msg.pickPos);
|
|
|
|
// redraw the control should any visual change hath occured
|
|
window.update(extent);
|
|
|
|
activate(gEventMouseDown);
|
|
return TRUE;
|
|
}
|
|
|
|
void gSlider::pointerMove(gPanelMessage &msg) {
|
|
if (selected) {
|
|
// update the image index
|
|
updateSliderIndexes(msg.pickPos);
|
|
|
|
// redraw the control should any visual change hath occured
|
|
window.update(extent);
|
|
|
|
notify(gEventMouseMove, slCurrent);
|
|
}
|
|
}
|
|
|
|
void gSlider::pointerRelease(gPanelMessage &) {
|
|
// We have to test selected first because deactivate clears it.
|
|
if (selected) {
|
|
deactivate(); // give back input focus
|
|
notify(gEventNewValue, slCurrent); // notify App of successful hit
|
|
} else deactivate();
|
|
}
|
|
|
|
void gSlider::pointerDrag(gPanelMessage &msg) {
|
|
// update the image index
|
|
updateSliderIndexes(msg.pickPos);
|
|
|
|
notify(gEventNewValue, slCurrent); // notify App of successful hit
|
|
// redraw the control should any visual change hath occured
|
|
window.update(extent);
|
|
}
|
|
|
|
void gSlider::updateSliderIndexes(Point16 &pos) {
|
|
pos.x = quantizedVolume(pos.x);
|
|
// get x position units
|
|
int32 unit = (extent.width * 100) / clamp(1, pos.x, extent.width);
|
|
|
|
// find the ratio and get the current slider value
|
|
slCurrent = (slValMax * 100) / clamp(1, unit, unit);
|
|
|
|
// update the image position index
|
|
imagePosX = clamp(extent.x,
|
|
pos.x,
|
|
extent.width - imageRect.x);
|
|
}
|
|
|
|
} // end of namespace Saga2
|