Simplified global label management and added subtitles for BRA.

svn-id: r28828
This commit is contained in:
Nicola Mettifogo 2007-09-02 18:34:11 +00:00
parent f1f324cee4
commit 21e4f4f176
10 changed files with 177 additions and 59 deletions

View File

@ -44,6 +44,50 @@ typedef OpcodeImpl<Parallaction_br> OpcodeV2;
#define INSTRUCTION_OPCODE(op) OpcodeV2(this, &Parallaction_br::instOp_##op)
#define DECLARE_INSTRUCTION_OPCODE(op) void Parallaction_br::instOp_##op()
void Parallaction_br::setupSubtitles(char *s, char *s2, int y) {
if (!scumm_stricmp("clear", s)) {
removeJob(_jDisplaySubtitle);
addJob(kJobWaitRemoveSubtitleJob, _jEraseSubtitle, 15);
_jDisplaySubtitle = 0;
_subtitle0.free();
_subtitle1.free();
return;
}
_subtitle0.free();
_subtitle1.free();
renderLabel(&_subtitle0._cnv, s);
_subtitle0._text = strdup(s);
if (s2) {
renderLabel(&_subtitle1._cnv, s2);
_subtitle1._text = strdup(s2);
}
_subtitleLipSync = 0;
if (y != -1) {
_subtitle0._pos.y = y;
_subtitle1._pos.y = y + 5 + _labelFont->height();
}
_subtitle0._pos.x = (_gfx->_screenX << 2) + ((640 - _subtitle0._cnv.w) >> 1);
if (_subtitle1._text)
_subtitle1._pos.x = (_gfx->_screenX << 2) + ((640 - _subtitle1._cnv.w) >> 1);
if (_jDisplaySubtitle == 0) {
_subtitle0._old.x = -1000;
_subtitle0._old.y = -1000;
_jDisplaySubtitle = addJob(kJobDisplaySubtitle, 0, 1);
_jEraseSubtitle = addJob(kJobEraseSubtitle, 0, 20);
}
}
DECLARE_COMMAND_OPCODE(location) {
warning("Parallaction_br::cmdOp_location command not yet implemented");
@ -201,7 +245,8 @@ DECLARE_COMMAND_OPCODE(give) {
DECLARE_COMMAND_OPCODE(text) {
warning("Parallaction_br::cmdOp_text not yet implemented");
CommandData *data = &_cmdRunCtxt.cmd->u;
setupSubtitles(data->_string, data->_string2, data->_zeta0);
}
@ -354,8 +399,31 @@ DECLARE_INSTRUCTION_OPCODE(print) {
}
void Parallaction_br::jobDisplaySubtitle(void *parm, Job *job) {
_gfx->drawLabel(_subtitle0);
_gfx->drawLabel(_subtitle1);
}
void Parallaction_br::jobEraseSubtitle(void *parm, Job *job) {
Common::Rect r;
if (_subtitle0._old.x != -1000) {
_subtitle0.getRect(r);
_gfx->restoreBackground(r);
}
_subtitle0._old = _subtitle0._pos;
if (_subtitle1._old.x != -1000) {
_subtitle0.getRect(r);
_gfx->restoreBackground(r);
}
_subtitle1._old = _subtitle1._pos;
}
DECLARE_INSTRUCTION_OPCODE(text) {
warning("Parallaction_br::instOp_text not yet implemented");
Instruction *inst = (*_instRunCtxt.inst);
setupSubtitles(inst->_text, inst->_text2, inst->_y);
}

View File

@ -858,9 +858,7 @@ void Parallaction_ns::jobDisplayLabel(void *parm, Job *j) {
Label *label = (Label*)parm;
debugC(9, kDebugJobs, "jobDisplayLabel (%p)", (const void*) label);
if (label->_cnv.w == 0)
return;
_gfx->flatBlitCnv(&label->_cnv, _gfx->_labelPosition[0].x, _gfx->_labelPosition[0].y, Gfx::kBitBack);
_gfx->drawLabel(*label);
return;
}
@ -886,13 +884,13 @@ void Parallaction_ns::jobEraseLabel(void *parm, Job *j) {
if (label->_cnv.w + _si > _screenWidth)
_si = _screenWidth - label->_cnv.w;
Common::Rect r(label->_cnv.w, label->_cnv.h);
r.moveTo(_gfx->_labelPosition[1]);
Common::Rect r;
label->getRect(r, true);
_gfx->restoreBackground(r);
_gfx->_labelPosition[1] = _gfx->_labelPosition[0];
_gfx->_labelPosition[0].x = _si;
_gfx->_labelPosition[0].y = _di;
label->_old = label->_pos;
label->_pos.x = _si;
label->_pos.y = _di;
return;
}

View File

@ -409,12 +409,12 @@ void Gfx::blit(const Common::Rect& r, uint16 z, byte *data, Gfx::Buffers buffer)
}
void Gfx::drawLabel(Label &label) {
if (label._text == 0)
return;
flatBlitCnv(&label._cnv, label._pos.x, label._pos.y, Gfx::kBitBack);
}
//

View File

@ -135,7 +135,7 @@ class Parallaction;
struct DoorData;
struct GetData;
struct Label;
struct MaskBuffer {
// handles a 2-bit depth buffer used for z-buffering
@ -219,6 +219,8 @@ public:
uint16 getStringWidth(const char *text);
void getStringExtent(char *text, uint16 maxwidth, int16* width, int16* height);
void drawLabel(Label &label);
// cut/paste
void flatBlitCnv(Graphics::Surface *cnv, int16 x, int16 y, Gfx::Buffers buffer);
void flatBlitCnv(Frames *cnv, uint16 frame, int16 x, int16 y, Gfx::Buffers buffer);
@ -259,7 +261,6 @@ public:
public:
Common::Point _labelPosition[2];
uint16 _bgLayers[4];
PaletteFxRange _palettefx[6];
Palette _palette;
@ -296,3 +297,4 @@ protected:

View File

@ -131,8 +131,6 @@ Zone::Zone() {
Zone::~Zone() {
// printf("~Zone(%s)\n", _label._text);
_label._cnv.free();
switch (_type & 0xFFFF) {
case kZoneExamine:
free(u.examine->_filename);
@ -198,15 +196,40 @@ uint16 Zone::height() const {
}
Label::Label() {
_text = NULL;
resetPosition();
_text = 0;
}
Label::~Label() {
_cnv.free();
if (_text)
free(_text);
free();
}
void Label::free() {
_cnv.free();
if (_text)
::free(_text);
_text = 0;
resetPosition();
}
void Label::resetPosition() {
_pos.x = -1000;
_pos.y = -1000;
_old.x = -1000;
_old.y = -1000;
}
void Label::getRect(Common::Rect &r, bool old) {
r.setWidth(_cnv.w);
r.setHeight(_cnv.h);
if (old) {
r.moveTo(_old);
} else {
r.moveTo(_pos);
}
}
Answer::Answer() {
_text = NULL;

View File

@ -263,8 +263,15 @@ struct Label {
char* _text;
Graphics::Surface _cnv;
Common::Point _pos;
Common::Point _old;
Label();
~Label();
void free();
void resetPosition();
void getRect(Common::Rect &r, bool old = false);
};
struct Zone {

View File

@ -353,6 +353,31 @@ void Parallaction::runGame() {
return;
}
void Parallaction::showLabel(Label &label) {
label.resetPosition();
_jDrawLabel = addJob(kJobDisplayLabel, (void*)&label, kPriority0);
_jEraseLabel = addJob(kJobEraseLabel, (void*)&label, kPriority20);
}
void Parallaction::hideLabel(uint priority) {
if (!_jDrawLabel)
return;
removeJob(_jDrawLabel);
_jDrawLabel = 0;
if (priority == kPriority99) {
// remove job immediately
removeJob(_jEraseLabel);
_jEraseLabel = 0;
} else {
// schedule job for deletion
addJob(kJobWaitRemoveJob, _jEraseLabel, priority);
}
}
void Parallaction::processInput(InputData *data) {
Zone *z;
@ -360,19 +385,12 @@ void Parallaction::processInput(InputData *data) {
switch (data->_event) {
case kEvEnterZone:
debugC(2, kDebugInput, "processInput: kEvEnterZone");
_gfx->_labelPosition[1].x = -1000;
_gfx->_labelPosition[1].y = -1000;
_gfx->_labelPosition[0].x = -1000;
_gfx->_labelPosition[0].y = -1000;
_jDrawLabel = addJob(kJobDisplayLabel, (void*)data->_label, kPriority0);
_jEraseLabel = addJob(kJobEraseLabel, (void*)data->_label, kPriority20);
showLabel(*data->_label);
break;
case kEvExitZone:
debugC(2, kDebugInput, "processInput: kEvExitZone");
removeJob(_jDrawLabel);
addJob(kJobWaitRemoveJob, _jEraseLabel, kPriority15);
_jDrawLabel = NULL;
hideLabel(kPriority15);
break;
case kEvAction:
@ -390,13 +408,10 @@ void Parallaction::processInput(InputData *data) {
case kEvOpenInventory:
_procCurrentHoverItem = -1;
_hoverZone = NULL;
if (_jDrawLabel != 0) {
removeJob(_jDrawLabel);
_jDrawLabel = NULL;
addJob(kJobWaitRemoveJob, _jEraseLabel, kPriority2);
hideLabel(kPriority2);
if (hitZone(kZoneYou, _mousePos.x, _mousePos.y) == 0) {
changeCursor(kCursorArrow);
}
if (hitZone(kZoneYou, _mousePos.x, _mousePos.y) == 0)
changeCursor(kCursorArrow);
removeJob(_jRunScripts);
_jDrawInventory = addJob(kJobShowInventory, 0, kPriority2);
openInventory();
@ -619,11 +634,7 @@ void Parallaction::changeCursor(int32 index) {
debugC(1, kDebugInput, "changeCursor(%i), label: %p", index, (const void*)_jDrawLabel);
if (_jDrawLabel != NULL) {
removeJob(_jDrawLabel);
addJob(kJobWaitRemoveJob, _jEraseLabel, kPriority15 );
_jDrawLabel = NULL;
}
hideLabel(kPriority15);
_activeItem._id = 0;

View File

@ -90,7 +90,8 @@ enum {
kPriority18 = 18,
kPriority19 = 19,
kPriority20 = 20,
kPriority21 = 21
kPriority21 = 21,
kPriority99 = 99 // fictitious priority value used as a flag to handle quick label deletion
};
enum {
@ -372,8 +373,8 @@ enum Jobs {
kJobHideInventory,
// BRA specific
kJobClearSubtitle = 10,
kJobDrawSubtitle,
kJobEraseSubtitle = 10,
kJobDisplaySubtitle,
kJobWaitRemoveSubtitleJob,
kJobPauseSfx,
kJobStopFollower,
@ -475,6 +476,9 @@ public:
Table *_localFlagNames;
void showLabel(Label &label);
void hideLabel(uint priority);
public:
int getGameType() const;
uint32 getFeatures() const;
@ -745,6 +749,9 @@ protected:
CommandList *list;
bool endcommands;
Command *cmd;
// BRA specific
int numZones;
} _locParseCtxt;
DECLARE_UNQUALIFIED_LOCATION_PARSER(invalid);
@ -914,6 +921,10 @@ public:
int _zeta2;
int16 _lipSyncVal;
uint _subtitleLipSync;
Label _subtitle0;
Label _subtitle1;
Zone *_activeZone2;
@ -921,10 +932,6 @@ public:
uint32 _zoneFlags[NUM_LOCATIONS][NUM_ZONES];
struct LocationParserContext_br : public LocationParserContext {
int numZones;
} _locParseCtxt;
private:
void initResources();
void initFonts();
@ -1082,6 +1089,13 @@ private:
DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(stop);
DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endscript);
Job *_jDisplaySubtitle;
Job *_jEraseSubtitle;
void jobDisplaySubtitle(void *parm, Job *job);
void jobEraseSubtitle(void *parm, Job *job);
void setupSubtitles(char *s, char *s2, int y);
};
// FIXME: remove global

View File

@ -232,16 +232,10 @@ void Parallaction_ns::changeLocation(char *location) {
_soundMan->playLocationMusic(location);
// WORKAROUND: this if-statement has been added to avoid crashes caused by
// WORKAROUND: this hideLabel has been added to avoid crashes caused by
// execution of label jobs after a location switch. The other workaround in
// Parallaction::runGame should have been rendered useless by this one.
if (_jDrawLabel != NULL) {
removeJob(_jDrawLabel);
removeJob(_jEraseLabel);
_jDrawLabel = NULL;
_jEraseLabel = NULL;
}
hideLabel(kPriority99);
_hoverZone = NULL;
if (_engineFlags & kEngineBlockInput) {

View File

@ -705,7 +705,8 @@ void Parallaction_br::initParsers() {
INSTRUCTION_PARSER(inc), // div
INSTRUCTION_PARSER(if_op),
INSTRUCTION_PARSER(endif),
INSTRUCTION_PARSER(zone) // stop
INSTRUCTION_PARSER(zone), // stop
INSTRUCTION_PARSER(endscript)
};
uint i;