Initial commit
This commit is contained in:
156
engines/ultima/ultima8/gumps/ask_gump.cpp
Normal file
156
engines/ultima/ultima8/gumps/ask_gump.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "ultima/ultima8/gumps/ask_gump.h"
|
||||
#include "ultima/ultima8/gumps/bark_gump.h"
|
||||
#include "ultima/ultima8/gumps/widgets/button_widget.h"
|
||||
#include "ultima/ultima8/usecode/uc_list.h"
|
||||
#include "ultima/ultima8/usecode/uc_machine.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
// p_dynamic_class stuff
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(AskGump)
|
||||
|
||||
AskGump::AskGump() : ItemRelativeGump(), _answers(0) {
|
||||
}
|
||||
|
||||
AskGump::AskGump(uint16 owner, UCList *answers) :
|
||||
ItemRelativeGump(0, 0, 0, 0, owner, FLAG_KEEP_VISIBLE, LAYER_ABOVE_NORMAL),
|
||||
_answers(new UCList(2)) {
|
||||
_answers->copyStringList(*answers);
|
||||
}
|
||||
|
||||
AskGump::~AskGump() {
|
||||
_answers->freeStrings();
|
||||
delete _answers;
|
||||
}
|
||||
|
||||
// Init the gump, call after construction
|
||||
void AskGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
// OK, this is a bit of a hack, but it's how it has to be
|
||||
int fontnum = BarkGump::dialogFontForActor(_owner);
|
||||
|
||||
int px = 0, py = 0;
|
||||
|
||||
// This is a hack. We init the gump twice...
|
||||
ItemRelativeGump::InitGump(newparent, take_focus);
|
||||
|
||||
for (unsigned int i = 0; i < _answers->getSize(); ++i) {
|
||||
Std::string str_answer = "@ ";
|
||||
str_answer += UCMachine::get_instance()->getString(_answers->getStringIndex(i));
|
||||
|
||||
ButtonWidget *child = new ButtonWidget(px, py, str_answer,
|
||||
true, fontnum);
|
||||
child->InitGump(this);
|
||||
child->SetIndex(i);
|
||||
|
||||
Common::Rect32 cd = child->getDims();
|
||||
if (i + 1 < _answers->getSize())
|
||||
cd.setHeight(cd.height() + child->getVlead());
|
||||
|
||||
if (px + cd.width() > 160 && px != 0) {
|
||||
py = _dims.height();
|
||||
px = 0;
|
||||
child->Move(px, py);
|
||||
}
|
||||
|
||||
if (cd.width() + px > _dims.width())
|
||||
_dims.setWidth(cd.width() + px);
|
||||
if (cd.height() + py > _dims.height())
|
||||
_dims.setHeight(cd.height() + py);
|
||||
|
||||
px += cd.width() + 4;
|
||||
}
|
||||
|
||||
// Wait with ItemRelativeGump initialization until we calculated our size.
|
||||
ItemRelativeGump::InitGump(newparent, take_focus);
|
||||
}
|
||||
|
||||
void AskGump::ChildNotify(Gump *child, uint32 message) {
|
||||
if (message == ButtonWidget::BUTTON_CLICK) {
|
||||
uint16 s = _answers->getStringIndex(child->GetIndex());
|
||||
_processResult = s;
|
||||
|
||||
// _answers' strings are going to be deleted, so make sure
|
||||
// the response string won't be deleted
|
||||
_answers->removeString(s, true); //!! assuming that answers doesn't
|
||||
//!! contain two identical strings
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
void AskGump::saveData(Common::WriteStream *ws) {
|
||||
ItemRelativeGump::saveData(ws);
|
||||
|
||||
_answers->save(ws);
|
||||
}
|
||||
|
||||
bool AskGump::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
if (!ItemRelativeGump::loadData(rs, version)) return false;
|
||||
|
||||
_answers = new UCList(2);
|
||||
_answers->load(rs, version);
|
||||
|
||||
// HACK ALERT
|
||||
int px = 0, py = 0;
|
||||
|
||||
_dims.setWidth(0);
|
||||
_dims.setHeight(0);
|
||||
|
||||
|
||||
for (unsigned int i = 0; i < _answers->getSize(); ++i) {
|
||||
|
||||
ButtonWidget *child = nullptr;
|
||||
|
||||
for (auto *g : _children) {
|
||||
if (g->GetIndex() != (int)i)
|
||||
continue;
|
||||
child = dynamic_cast<ButtonWidget *>(g);
|
||||
if (!child)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!child) return false;
|
||||
|
||||
Common::Rect32 cd = child->getDims();
|
||||
|
||||
if (px + cd.width() > 160 && px != 0) {
|
||||
py = _dims.height();
|
||||
px = 0;
|
||||
}
|
||||
child->Move(px, py);
|
||||
|
||||
if (cd.width() + px > _dims.width())
|
||||
_dims.setWidth(cd.width() + px);
|
||||
if (cd.height() + py > _dims.height())
|
||||
_dims.setHeight(cd.height() + py);
|
||||
|
||||
px += cd.width() + 4;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
58
engines/ultima/ultima8/gumps/ask_gump.h
Normal file
58
engines/ultima/ultima8/gumps/ask_gump.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_ASKGUMP_H
|
||||
#define ULTIMA8_GUMPS_ASKGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/item_relative_gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class UCList;
|
||||
|
||||
/**
|
||||
* Represents asking a question while talking to an NPC
|
||||
*/
|
||||
class AskGump : public ItemRelativeGump {
|
||||
UCList *_answers;
|
||||
public:
|
||||
// p_dynamic_class stuff
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
AskGump();
|
||||
AskGump(uint16 owner, UCList *answers);
|
||||
~AskGump() override;
|
||||
|
||||
// Init the gump, call after construction
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
|
||||
void ChildNotify(Gump *child, uint32 message) override;
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
249
engines/ultima/ultima8/gumps/bark_gump.cpp
Normal file
249
engines/ultima/ultima8/gumps/bark_gump.cpp
Normal file
@@ -0,0 +1,249 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/config-manager.h"
|
||||
|
||||
#include "ultima/ultima8/gumps/bark_gump.h"
|
||||
#include "ultima/ultima8/gumps/widgets/text_widget.h"
|
||||
#include "ultima/ultima8/kernel/kernel.h"
|
||||
#include "ultima/ultima8/audio/audio_process.h"
|
||||
#include "ultima/ultima8/world/get_object.h"
|
||||
#include "ultima/ultima8/world/item.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
static const int INT_MAX_VALUE = 0x7fffffff;
|
||||
static const int NO_SPEECH_LENGTH = 480;
|
||||
static const int MILLIS_PER_TICK = (1000 / Kernel::TICKS_PER_SECOND) + 1;
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(BarkGump)
|
||||
|
||||
BarkGump::BarkGump() : ItemRelativeGump(), _counter(0), _textWidget(0),
|
||||
_speechShapeNum(0), _speechLength(0),
|
||||
_subtitles(false), _speechMute(false), _talkSpeed(0) {
|
||||
_subtitles = ConfMan.getBool("subtitles");
|
||||
_speechMute = ConfMan.getBool("speech_mute");
|
||||
_talkSpeed = ConfMan.getInt("talkspeed");
|
||||
}
|
||||
|
||||
BarkGump::BarkGump(uint16 owner, const Std::string &msg, uint32 speechShapeNum) :
|
||||
ItemRelativeGump(0, 0, 100, 100, owner, FLAG_KEEP_VISIBLE, LAYER_ABOVE_NORMAL),
|
||||
_barked(msg), _counter(100), _speechShapeNum(speechShapeNum),
|
||||
_speechLength(0), _textWidget(0),
|
||||
_subtitles(false), _speechMute(false), _talkSpeed(0) {
|
||||
_subtitles = ConfMan.getBool("subtitles");
|
||||
_speechMute = ConfMan.getBool("speech_mute");
|
||||
_talkSpeed = ConfMan.getInt("talkspeed");
|
||||
}
|
||||
|
||||
BarkGump::~BarkGump(void) {
|
||||
}
|
||||
|
||||
int BarkGump::dialogFontForActor(uint16 actor) {
|
||||
// OK, this is a bit of a hack, but it's how it has to be
|
||||
if (actor == kMainActorId || actor == kGuardianId)
|
||||
return 6;
|
||||
if (actor > 256)
|
||||
return 8;
|
||||
switch (actor % 3) {
|
||||
case 1:
|
||||
return 5;
|
||||
case 2:
|
||||
return 7;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void BarkGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
int fontnum = dialogFontForActor(_owner);
|
||||
|
||||
//.Set a reasonable minimum speed for text speed when not in stasis
|
||||
if (_talkSpeed < 10 && !Ultima8Engine::get_instance()->isAvatarInStasis()) {
|
||||
_talkSpeed = 10;
|
||||
}
|
||||
|
||||
// This is a hack. We init the gump twice...
|
||||
ItemRelativeGump::InitGump(newparent, take_focus);
|
||||
|
||||
// Create the TextWidget
|
||||
TextWidget *widget = new TextWidget(0, 0, _barked, true, fontnum, 194, 55);
|
||||
widget->InitGump(this);
|
||||
|
||||
_textWidget = widget->getObjId();
|
||||
|
||||
// see if we need to play speech
|
||||
AudioProcess *ap = AudioProcess::get_instance();
|
||||
_speechLength = 0;
|
||||
if (!_speechMute && _speechShapeNum && ap) {
|
||||
if (ap->playSpeech(_barked, _speechShapeNum, _owner)) {
|
||||
_speechLength = ap->getSpeechLength(_barked, _speechShapeNum);
|
||||
if (_speechLength == 0)
|
||||
_speechLength = 1;
|
||||
|
||||
if (!_subtitles) {
|
||||
widget->SetVisibility(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Common::Rect32 d = widget->getDims();
|
||||
_dims.setHeight(d.height());
|
||||
_dims.setWidth(d.width());
|
||||
_counter = calculateTicks();
|
||||
|
||||
// Wait with ItemRelativeGump initialization until we calculated our size.
|
||||
ItemRelativeGump::InitGump(newparent, take_focus);
|
||||
}
|
||||
|
||||
|
||||
void BarkGump::Close(bool no_del) {
|
||||
Item *item = getItem(_owner);
|
||||
if (item)
|
||||
item->clearBark();
|
||||
|
||||
ItemRelativeGump::Close(no_del);
|
||||
}
|
||||
|
||||
bool BarkGump::NextText() {
|
||||
TextWidget *widget = dynamic_cast<TextWidget *>(getGump(_textWidget));
|
||||
assert(widget);
|
||||
if (widget->setupNextText()) {
|
||||
Common::Rect32 d = widget->getDims();
|
||||
_dims.setHeight(d.height());
|
||||
_dims.setWidth(d.width());
|
||||
_counter = calculateTicks();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int BarkGump::calculateTicks() {
|
||||
uint start = 0, end = 0;
|
||||
TextWidget *widget = dynamic_cast<TextWidget *>(getGump(_textWidget));
|
||||
widget->getCurrentText(start, end);
|
||||
uint length = end - start;
|
||||
int ticks = INT_MAX_VALUE;
|
||||
if (length > 0) {
|
||||
if (_speechLength && !_barked.empty()) {
|
||||
ticks = (length * _speechLength) / (_barked.size() * MILLIS_PER_TICK);
|
||||
} else if (_talkSpeed) {
|
||||
ticks = (length * NO_SPEECH_LENGTH) / _talkSpeed;
|
||||
}
|
||||
} else if (_talkSpeed) {
|
||||
ticks = NO_SPEECH_LENGTH / _talkSpeed;
|
||||
}
|
||||
|
||||
return ticks;
|
||||
}
|
||||
|
||||
void BarkGump::run() {
|
||||
ItemRelativeGump::run();
|
||||
|
||||
// Auto close
|
||||
if (!Kernel::get_instance()->isPaused()) {
|
||||
if (!--_counter) {
|
||||
// try next text
|
||||
bool done = !NextText();
|
||||
if (done) {
|
||||
bool speechplaying = false;
|
||||
if (!_speechMute && _speechLength) {
|
||||
// waiting for speech to finish?
|
||||
AudioProcess *ap = AudioProcess::get_instance();
|
||||
if (ap)
|
||||
speechplaying = ap->isSpeechPlaying(_barked,
|
||||
_speechShapeNum);
|
||||
}
|
||||
|
||||
// if speech done too, close
|
||||
if (!speechplaying)
|
||||
Close();
|
||||
else
|
||||
_counter = calculateTicks();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Gump *BarkGump::onMouseDown(int button, int32 mx, int32 my) {
|
||||
Gump *g = ItemRelativeGump::onMouseDown(button, mx, my);
|
||||
if (g) return g;
|
||||
|
||||
// Scroll to next text, if possible
|
||||
if (!NextText()) {
|
||||
if (!_speechMute && _speechLength) {
|
||||
AudioProcess *ap = AudioProcess::get_instance();
|
||||
if (ap) ap->stopSpeech(_barked, _speechShapeNum, _owner);
|
||||
}
|
||||
Close();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
void BarkGump::saveData(Common::WriteStream *ws) {
|
||||
ItemRelativeGump::saveData(ws);
|
||||
|
||||
ws->writeUint32LE(static_cast<uint32>(_counter));
|
||||
ws->writeUint16LE(_textWidget);
|
||||
ws->writeUint32LE(_speechShapeNum);
|
||||
ws->writeUint32LE(_speechLength);
|
||||
ws->writeUint32LE(0); // Unused
|
||||
ws->writeUint32LE(static_cast<uint32>(_barked.size()));
|
||||
ws->write(_barked.c_str(), _barked.size());
|
||||
}
|
||||
|
||||
bool BarkGump::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
if (!ItemRelativeGump::loadData(rs, version)) return false;
|
||||
|
||||
_counter = static_cast<int32>(rs->readUint32LE());
|
||||
_textWidget = rs->readUint16LE();
|
||||
_speechShapeNum = rs->readUint32LE();
|
||||
_speechLength = rs->readUint32LE();
|
||||
rs->readUint32LE(); // Unused
|
||||
|
||||
uint32 slen = rs->readUint32LE();
|
||||
if (slen > 0) {
|
||||
char *buf = new char[slen + 1];
|
||||
rs->read(buf, slen);
|
||||
buf[slen] = 0;
|
||||
_barked = buf;
|
||||
delete[] buf;
|
||||
} else {
|
||||
_barked = "";
|
||||
}
|
||||
|
||||
TextWidget *widget = dynamic_cast<TextWidget *>(getGump(_textWidget));
|
||||
if (!widget)
|
||||
return false;
|
||||
|
||||
Common::Rect32 d = widget->getDims();
|
||||
_dims.setHeight(d.height());
|
||||
_dims.setWidth(d.width());
|
||||
|
||||
_counter = calculateTicks();
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
81
engines/ultima/ultima8/gumps/bark_gump.h
Normal file
81
engines/ultima/ultima8/gumps/bark_gump.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_BARKGUMP_H
|
||||
#define ULTIMA8_GUMPS_BARKGUMP_H
|
||||
|
||||
#include "ultima/shared/std/string.h"
|
||||
#include "ultima/ultima8/gumps/item_relative_gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/**
|
||||
* Represents text which appears on the screen to show the name of an item, etc
|
||||
*/
|
||||
class BarkGump : public ItemRelativeGump {
|
||||
protected:
|
||||
Std::string _barked;
|
||||
int32 _counter;
|
||||
ObjId _textWidget;
|
||||
uint32 _speechShapeNum;
|
||||
uint32 _speechLength;
|
||||
bool _subtitles;
|
||||
bool _speechMute;
|
||||
int _talkSpeed;
|
||||
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
BarkGump();
|
||||
BarkGump(uint16 owner, const Std::string &msg, uint32 speechShapeNum = 0);
|
||||
~BarkGump() override;
|
||||
|
||||
// Run the gump (decrement the counter)
|
||||
void run() override;
|
||||
|
||||
// Got to the next page on mouse click
|
||||
Gump *onMouseDown(int button, int32 mx, int32 my) override;
|
||||
|
||||
// Init the gump, call after construction
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
|
||||
// Close the gump
|
||||
void Close(bool no_del = false) override;
|
||||
|
||||
/// Get the font that should be used from dialog from this actor
|
||||
static int dialogFontForActor(uint16 actor);
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
|
||||
protected:
|
||||
//! show next text.
|
||||
//! returns false if no more text available
|
||||
bool NextText();
|
||||
int calculateTicks();
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
147
engines/ultima/ultima8/gumps/book_gump.cpp
Normal file
147
engines/ultima/ultima8/gumps/book_gump.cpp
Normal file
@@ -0,0 +1,147 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/keyboard.h"
|
||||
#include "ultima/ultima8/gumps/book_gump.h"
|
||||
#include "ultima/ultima8/gumps/widgets/text_widget.h"
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/gfx/gump_shape_archive.h"
|
||||
#include "ultima/ultima8/usecode/uc_machine.h"
|
||||
#include "ultima/ultima8/gumps/gump_notify_process.h"
|
||||
#include "ultima/ultima8/world/item.h"
|
||||
#include "ultima/ultima8/world/get_object.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(BookGump)
|
||||
|
||||
BookGump::BookGump()
|
||||
: ModalGump(), _textWidgetL(0), _textWidgetR(0) {
|
||||
|
||||
}
|
||||
|
||||
BookGump::BookGump(ObjId owner, const Std::string &msg) :
|
||||
ModalGump(0, 0, 100, 100, owner), _text(msg),
|
||||
_textWidgetL(0), _textWidgetR(0) {
|
||||
}
|
||||
|
||||
BookGump::~BookGump(void) {
|
||||
}
|
||||
|
||||
void BookGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
ModalGump::InitGump(newparent, take_focus);
|
||||
|
||||
//
|
||||
// WORKAROUND (HACK), ScummVM bug #12503
|
||||
// The original game usecode has a bug which does not display the correct text for the
|
||||
// The Spell of Resurrection book. This bug only exists in some versions of the game.
|
||||
//
|
||||
// Original book text is in the config as "translations" for "spell of resurrection".
|
||||
//
|
||||
Item *item = getItem(_owner);
|
||||
if (item && item->getShape() == 0x120 && item->getQuality() == 0x66) {
|
||||
const Std::string placeholder = "spell of resurrection";
|
||||
const Std::string replacement = _TL_(placeholder);
|
||||
if (replacement != placeholder)
|
||||
_text = replacement;
|
||||
}
|
||||
|
||||
// Create the TextWidgets (NOTE: they _must_ have exactly the same _dims)
|
||||
TextWidget *widget = new TextWidget(9, 5, _text, true, 9, 123, 129, Font::TEXT_LEFT, true); //!! constants
|
||||
widget->InitGump(this);
|
||||
_textWidgetL = widget->getObjId();
|
||||
|
||||
widget = new TextWidget(150, 5, _text, true, 9, 123, 129, Font::TEXT_LEFT, true); //!! constants
|
||||
widget->InitGump(this);
|
||||
_textWidgetR = widget->getObjId();
|
||||
widget->setupNextText();
|
||||
|
||||
_text.clear(); // no longer need this
|
||||
|
||||
//!! constant
|
||||
Shape *shapeP = GameData::get_instance()->getGumps()->getShape(6);
|
||||
|
||||
SetShape(shapeP, 0);
|
||||
UpdateDimsFromShape();
|
||||
}
|
||||
|
||||
void BookGump::NextText() {
|
||||
TextWidget *widgetL = dynamic_cast<TextWidget *>(getGump(_textWidgetL));
|
||||
TextWidget *widgetR = dynamic_cast<TextWidget *>(getGump(_textWidgetR));
|
||||
assert(widgetL);
|
||||
assert(widgetR);
|
||||
if (!widgetR->setupNextText()) {
|
||||
Close();
|
||||
}
|
||||
widgetL->setupNextText();
|
||||
widgetL->setupNextText();
|
||||
widgetR->setupNextText();
|
||||
}
|
||||
|
||||
void BookGump::onMouseClick(int button, int32 mx, int32 my) {
|
||||
// Scroll to next text, if possible
|
||||
NextText();
|
||||
}
|
||||
|
||||
void BookGump::onMouseDouble(int button, int32 mx, int32 my) {
|
||||
Close();
|
||||
}
|
||||
|
||||
bool BookGump::OnKeyDown(int key, int mod) {
|
||||
switch (key) {
|
||||
case Common::KEYCODE_ESCAPE:
|
||||
Close();
|
||||
break;
|
||||
case Common::KEYCODE_SPACE:
|
||||
NextText();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 BookGump::I_readBook(const uint8 *args, unsigned int /*argsize*/) {
|
||||
ARG_ITEM_FROM_PTR(item);
|
||||
ARG_STRING(str);
|
||||
assert(item);
|
||||
|
||||
Gump *gump = new BookGump(item->getObjId(), str);
|
||||
gump->InitGump(0);
|
||||
gump->setRelativePosition(CENTER);
|
||||
|
||||
return gump->GetNotifyProcess()->getPid();
|
||||
}
|
||||
|
||||
void BookGump::saveData(Common::WriteStream *ws) {
|
||||
warning("Trying to save ModalGump");
|
||||
}
|
||||
|
||||
bool BookGump::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
warning("Trying to load ModalGump");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
71
engines/ultima/ultima8/gumps/book_gump.h
Normal file
71
engines/ultima/ultima8/gumps/book_gump.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_BOOKGUMP_H
|
||||
#define ULTIMA8_GUMPS_BOOKGUMP_H
|
||||
|
||||
#include "ultima/shared/std/string.h"
|
||||
#include "ultima/ultima8/gumps/modal_gump.h"
|
||||
#include "ultima/ultima8/usecode/intrinsics.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/**
|
||||
* The gump to display the text of a book
|
||||
*/
|
||||
class BookGump : public ModalGump {
|
||||
Std::string _text;
|
||||
ObjId _textWidgetL;
|
||||
ObjId _textWidgetR;
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
BookGump();
|
||||
BookGump(ObjId owner, const Std::string &msg);
|
||||
~BookGump() override;
|
||||
|
||||
// Go to the next page on mouse click
|
||||
void onMouseClick(int button, int32 mx, int32 my) override;
|
||||
|
||||
// Close on double click
|
||||
void onMouseDouble(int button, int32 mx, int32 my) override;
|
||||
|
||||
bool OnKeyDown(int key, int mod) override;
|
||||
|
||||
// Init the gump, call after construction
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
|
||||
INTRINSIC(I_readBook);
|
||||
|
||||
protected:
|
||||
void NextText();
|
||||
|
||||
public:
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
274
engines/ultima/ultima8/gumps/computer_gump.cpp
Normal file
274
engines/ultima/ultima8/gumps/computer_gump.cpp
Normal file
@@ -0,0 +1,274 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/keyboard.h"
|
||||
|
||||
#include "ultima/shared/std/string.h"
|
||||
#include "ultima/ultima8/gumps/computer_gump.h"
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/audio/audio_process.h"
|
||||
#include "ultima/ultima8/gfx/shape.h"
|
||||
#include "ultima/ultima8/gfx/gump_shape_archive.h"
|
||||
#include "ultima/ultima8/gfx/shape_frame.h"
|
||||
#include "ultima/ultima8/gfx/fonts/rendered_text.h"
|
||||
#include "ultima/ultima8/gfx/fonts/font.h"
|
||||
#include "ultima/ultima8/gfx/fonts/font_manager.h"
|
||||
#include "ultima/ultima8/gfx/fonts/shape_font.h"
|
||||
#include "ultima/ultima8/usecode/uc_machine.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(ComputerGump)
|
||||
|
||||
static const int COMPUTER_FONT = 6;
|
||||
static const int COMPUTER_GUMP_SHAPE = 30;
|
||||
static const int COMPUTER_GUMP_SOUND = 0x33;
|
||||
static const int MAX_LINE_LEN = 19;
|
||||
|
||||
static const int TEXT_XOFF = 41;
|
||||
static const int TEXT_YOFF = 38;
|
||||
|
||||
ComputerGump::ComputerGump()
|
||||
: ModalGump(), _curTextLine(0), _charOff(0), _nextCharTick(0), _paused(false), _curDisplayLine(0), _tick(0) {
|
||||
for (int i = 0; i < ARRAYSIZE(_renderedLines); i++) {
|
||||
_renderedLines[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ComputerGump::ComputerGump(const Std::string &msg) :
|
||||
ModalGump(0, 0, 100, 100), _curTextLine(0), _curDisplayLine(0),
|
||||
_charOff(0), _nextCharTick(0), _paused(false), _tick(0) {
|
||||
for (int i = 0; i < ARRAYSIZE(_renderedLines); i++) {
|
||||
_renderedLines[i] = nullptr;
|
||||
}
|
||||
|
||||
// Split the string on ^ or flow to 20 char lines.
|
||||
debug("M '%s'", msg.c_str());
|
||||
uint32 start = 0;
|
||||
uint32 end = 0;
|
||||
for (uint32 i = 0; i < msg.size(); i++) {
|
||||
if (msg[i] == '^') {
|
||||
_textLines.push_back(msg.substr(start, end - start));
|
||||
debug("^ %d %d %d '%s'", i, start, end, _textLines.back().c_str());
|
||||
end = i + 1;
|
||||
start = i + 1;
|
||||
continue;
|
||||
}
|
||||
end++;
|
||||
if (end >= msg.size())
|
||||
break;
|
||||
if (end - start >= MAX_LINE_LEN) {
|
||||
while (end > start && msg[end] != ' ')
|
||||
end--;
|
||||
_textLines.push_back(msg.substr(start, end - start));
|
||||
debug("L %d %d %d '%s'", i, start, end, _textLines.back().c_str());
|
||||
i = end;
|
||||
end = i + 1;
|
||||
start = i + 1;
|
||||
}
|
||||
}
|
||||
if (start < msg.size())
|
||||
_textLines.push_back(msg.substr(start));
|
||||
}
|
||||
|
||||
ComputerGump::~ComputerGump(void) {
|
||||
for (int i = 0; i < ARRAYSIZE(_renderedLines); i++) {
|
||||
if (_renderedLines[i])
|
||||
delete _renderedLines[i];
|
||||
}
|
||||
}
|
||||
|
||||
void ComputerGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
ModalGump::InitGump(newparent, take_focus);
|
||||
|
||||
Shape *shape = GameData::get_instance()->getGumps()->
|
||||
getShape(COMPUTER_GUMP_SHAPE);
|
||||
if (!shape) {
|
||||
error("Couldn't load shape for computer");
|
||||
return;
|
||||
}
|
||||
|
||||
const ShapeFrame *topFrame = shape->getFrame(0);
|
||||
const ShapeFrame *botFrame = shape->getFrame(1);
|
||||
if (!topFrame || !botFrame) {
|
||||
error("Couldn't load shape frames for computer");
|
||||
return;
|
||||
}
|
||||
|
||||
_dims.left = 0;
|
||||
_dims.top = 0;
|
||||
_dims.setWidth(topFrame->_width);
|
||||
_dims.setHeight(topFrame->_height + botFrame->_height);
|
||||
|
||||
Gump *topGump = new Gump(0, 0, topFrame->_width, topFrame->_height);
|
||||
topGump->SetShape(shape, 0);
|
||||
topGump->InitGump(this, false);
|
||||
Gump *botGump = new Gump(0, topFrame->_height, botFrame->_width, botFrame->_height);
|
||||
botGump->SetShape(shape, 1);
|
||||
botGump->InitGump(this, false);
|
||||
|
||||
}
|
||||
|
||||
void ComputerGump::run() {
|
||||
ModalGump::run();
|
||||
|
||||
_tick++;
|
||||
if (_paused || _tick < _nextCharTick)
|
||||
return;
|
||||
|
||||
bool playsound = nextChar();
|
||||
|
||||
AudioProcess *audio = AudioProcess::get_instance();
|
||||
if (playsound && audio) {
|
||||
if (audio->isSFXPlaying(COMPUTER_GUMP_SOUND))
|
||||
audio->stopSFX(COMPUTER_GUMP_SOUND, 0);
|
||||
audio->playSFX(COMPUTER_GUMP_SOUND, 0x80, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ComputerGump::nextChar() {
|
||||
Font *computerfont = FontManager::get_instance()->getGameFont(COMPUTER_FONT, true);
|
||||
|
||||
if (_charOff >= _textLines[_curTextLine].size()) {
|
||||
_curTextLine++;
|
||||
_curDisplayLine++;
|
||||
_charOff = 0;
|
||||
|
||||
if (_curTextLine >= _textLines.size()) {
|
||||
_paused = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_nextCharTick = _tick + 2;
|
||||
|
||||
Common::String display;
|
||||
if (_curDisplayLine == ARRAYSIZE(_renderedLines) - 1) {
|
||||
display = "<MORE>";
|
||||
_paused = true;
|
||||
} else {
|
||||
const Common::String &curline = _textLines[_curTextLine];
|
||||
if (_charOff < curline.size() && curline[_charOff] == '*') {
|
||||
_nextCharTick += 10;
|
||||
_charOff++;
|
||||
return false;
|
||||
}
|
||||
_charOff++;
|
||||
for (uint32 i = 0; i < _charOff && i < curline.size(); i++) {
|
||||
char next = curline[i];
|
||||
if (next == '*')
|
||||
display += ' ';
|
||||
else
|
||||
display += next;
|
||||
}
|
||||
}
|
||||
|
||||
// Render the new line
|
||||
unsigned int remaining;
|
||||
RenderedText *rendered = computerfont->renderText(display, remaining);
|
||||
|
||||
if (_renderedLines[_curDisplayLine] != nullptr) {
|
||||
delete _renderedLines[_curDisplayLine];
|
||||
}
|
||||
_renderedLines[_curDisplayLine] = rendered;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void ComputerGump::Paint(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
ModalGump::Paint(surf, lerp_factor, scaled);
|
||||
for (int i = 0; i < ARRAYSIZE(_renderedLines); i++) {
|
||||
if (_renderedLines[i] != nullptr)
|
||||
_renderedLines[i]->draw(surf, _x + TEXT_XOFF, _y + TEXT_YOFF + i * 9);
|
||||
}
|
||||
}
|
||||
|
||||
void ComputerGump::nextScreen() {
|
||||
_nextCharTick = 0;
|
||||
_charOff = 0;
|
||||
_paused = false;
|
||||
_curTextLine++;
|
||||
_curDisplayLine = 0;
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(_renderedLines); i++) {
|
||||
if (_renderedLines[i] != nullptr) {
|
||||
delete _renderedLines[i];
|
||||
_renderedLines[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (_curTextLine >= _textLines.size())
|
||||
Close();
|
||||
}
|
||||
|
||||
Gump *ComputerGump::onMouseDown(int button, int32 mx, int32 my) {
|
||||
if (_paused) {
|
||||
nextScreen();
|
||||
} else {
|
||||
// Not super efficient but it does the job.
|
||||
while (!_paused)
|
||||
nextChar();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
bool ComputerGump::OnKeyDown(int key, int mod) {
|
||||
if (key == Common::KEYCODE_ESCAPE) {
|
||||
_paused = true;
|
||||
Close();
|
||||
}
|
||||
|
||||
if (_paused) {
|
||||
nextScreen();
|
||||
} else {
|
||||
// Not super efficient but it does the job.
|
||||
while (!_paused)
|
||||
nextChar();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 ComputerGump::I_readComputer(const uint8 *args, unsigned int /*argsize*/) {
|
||||
ARG_STRING(str);
|
||||
|
||||
Gump *gump = new ComputerGump(str);
|
||||
gump->InitGump(0);
|
||||
gump->setRelativePosition(CENTER);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ComputerGump::saveData(Common::WriteStream *ws) {
|
||||
warning("Trying to save ModalGump");
|
||||
}
|
||||
|
||||
bool ComputerGump::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
warning("Trying to load ModalGump");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
91
engines/ultima/ultima8/gumps/computer_gump.h
Normal file
91
engines/ultima/ultima8/gumps/computer_gump.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_COMPUTERGUMP_H
|
||||
#define ULTIMA8_GUMPS_COMPUTERGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/modal_gump.h"
|
||||
#include "ultima/ultima8/gfx/fonts/rendered_text.h"
|
||||
#include "ultima/ultima8/usecode/intrinsics.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/**
|
||||
* The gump for showing the computer with text in Crusader
|
||||
*/
|
||||
class ComputerGump : public ModalGump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
ComputerGump();
|
||||
ComputerGump(const Std::string &msg);
|
||||
~ComputerGump() override;
|
||||
|
||||
// Close on mouse click on key press
|
||||
Gump *onMouseDown(int button, int32 mx, int32 my) override;
|
||||
bool OnKeyDown(int key, int mod) override;
|
||||
|
||||
// Init the gump, call after construction
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
|
||||
void run() override;
|
||||
|
||||
void Paint(RenderSurface *, int32 lerp_factor, bool scaled) override;
|
||||
|
||||
INTRINSIC(I_readComputer);
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
|
||||
private:
|
||||
void nextScreen();
|
||||
|
||||
bool nextChar();
|
||||
|
||||
RenderedText *_renderedLines[14];
|
||||
|
||||
Common::Array<Common::String> _textLines;
|
||||
|
||||
//! The current line from the full text
|
||||
uint32 _curTextLine;
|
||||
|
||||
//! The current line in the rendered lines array
|
||||
uint32 _curDisplayLine;
|
||||
|
||||
//! The current char within the current line
|
||||
uint32 _charOff;
|
||||
|
||||
//! The frame when the next character will be added
|
||||
uint32 _nextCharTick;
|
||||
|
||||
//! Tick now (timed separately to the kernel as this is run when game is paused)
|
||||
uint32 _tick;
|
||||
|
||||
//! Whether display is currently paused waiting for input (with "MORE" at the bottom)
|
||||
bool _paused;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
603
engines/ultima/ultima8/gumps/container_gump.cpp
Normal file
603
engines/ultima/ultima8/gumps/container_gump.cpp
Normal file
@@ -0,0 +1,603 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima.h"
|
||||
#include "ultima/ultima8/gumps/container_gump.h"
|
||||
|
||||
#include "ultima/ultima8/gfx/shape.h"
|
||||
#include "ultima/ultima8/gfx/shape_frame.h"
|
||||
#include "ultima/ultima8/gfx/render_surface.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
#include "ultima/ultima8/kernel/kernel.h"
|
||||
#include "ultima/ultima8/kernel/mouse.h"
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/gfx/main_shape_archive.h"
|
||||
#include "ultima/ultima8/gumps/slider_gump.h"
|
||||
#include "ultima/ultima8/gumps/gump_notify_process.h"
|
||||
#include "ultima/ultima8/world/item_factory.h"
|
||||
#include "ultima/ultima8/world/split_item_process.h"
|
||||
#include "ultima/ultima8/gumps/game_map_gump.h"
|
||||
#include "ultima/ultima8/world/actors/main_actor.h"
|
||||
#include "ultima/ultima8/world/get_object.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(ContainerGump)
|
||||
|
||||
ContainerGump::ContainerGump()
|
||||
: ItemRelativeGump(), _displayDragging(false), _draggingShape(0),
|
||||
_draggingFrame(0), _draggingFlags(0), _draggingX(0), _draggingY(0) {
|
||||
|
||||
}
|
||||
|
||||
ContainerGump::ContainerGump(const Shape *shape, uint32 frameNum, uint16 owner,
|
||||
uint32 flags, int32 layer)
|
||||
: ItemRelativeGump(0, 0, 5, 5, owner, flags, layer),
|
||||
_displayDragging(false), _draggingShape(0), _draggingFrame(0),
|
||||
_draggingFlags(0), _draggingX(0), _draggingY(0) {
|
||||
_shape = shape;
|
||||
_frameNum = frameNum;
|
||||
}
|
||||
|
||||
ContainerGump::~ContainerGump() {
|
||||
}
|
||||
|
||||
void ContainerGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
UpdateDimsFromShape();
|
||||
|
||||
// Wait with ItemRelativeGump initialization until we calculated our size.
|
||||
ItemRelativeGump::InitGump(newparent, take_focus);
|
||||
|
||||
// make every item enter the fast area
|
||||
Container *c = getContainer(_owner);
|
||||
|
||||
if (!c) return; // Container gone!?
|
||||
|
||||
for (auto *item : c->_contents) {
|
||||
item->enterFastArea();
|
||||
}
|
||||
|
||||
|
||||
// Position isn't like in the original
|
||||
// U8 puts a container gump slightly to the left of an object
|
||||
}
|
||||
|
||||
void ContainerGump::run() {
|
||||
Gump::run();
|
||||
|
||||
Container *c = getContainer(_owner);
|
||||
if (!c) {
|
||||
// Container gone!?
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto *item : c->_contents) {
|
||||
int32 itemx, itemy;
|
||||
item->getGumpLocation(itemx, itemy);
|
||||
|
||||
const Shape *sh = item->getShapeObject();
|
||||
assert(sh);
|
||||
const ShapeFrame *fr = sh->getFrame(item->getFrame());
|
||||
assert(fr);
|
||||
|
||||
// Ensure item locations within item area.
|
||||
int32 minx = fr->_xoff;
|
||||
int32 miny = fr->_yoff;
|
||||
|
||||
int32 maxx = _itemArea.width() + fr->_xoff - fr->_width;
|
||||
int32 maxy = _itemArea.height() + fr->_yoff - fr->_height;
|
||||
|
||||
if (itemx == 0xFF && itemy == 0xFF) {
|
||||
// randomize position
|
||||
// TODO: maybe try to put it somewhere where it doesn't overlap others?
|
||||
|
||||
Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
|
||||
itemx = rs.getRandomNumberRng(minx, maxx);
|
||||
itemy = rs.getRandomNumberRng(miny, maxy);
|
||||
|
||||
item->setGumpLocation(itemx, itemy);
|
||||
}
|
||||
|
||||
if (itemx < minx) {
|
||||
itemx = minx;
|
||||
item->setGumpLocation(itemx, itemy);
|
||||
}
|
||||
|
||||
if (itemx > maxx) {
|
||||
itemx = maxx;
|
||||
item->setGumpLocation(itemx, itemy);
|
||||
}
|
||||
|
||||
if (itemy < miny) {
|
||||
itemy = miny;
|
||||
item->setGumpLocation(itemx, itemy);
|
||||
}
|
||||
|
||||
if (itemy > maxy) {
|
||||
itemy = maxy;
|
||||
item->setGumpLocation(itemx, itemy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ContainerGump::getItemCoords(Item *item, int32 &itemx, int32 &itemy) {
|
||||
item->getGumpLocation(itemx, itemy);
|
||||
|
||||
itemx += _itemArea.left;
|
||||
itemy += _itemArea.top;
|
||||
}
|
||||
|
||||
|
||||
void ContainerGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
// paint self
|
||||
ItemRelativeGump::PaintThis(surf, lerp_factor, scaled);
|
||||
|
||||
Container *c = getContainer(_owner);
|
||||
|
||||
if (!c) {
|
||||
// Container gone!?
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
int32 gameframeno = Kernel::get_instance()->getFrameNum();
|
||||
|
||||
//!! TODO: check these painting commands (flipped? translucent?)
|
||||
bool showEditorItems = Ultima8Engine::get_instance()->isShowEditorItems();
|
||||
|
||||
for (auto *item : c->_contents) {
|
||||
item->setupLerp(gameframeno);
|
||||
|
||||
if (!showEditorItems && item->getShapeInfo()->is_editor())
|
||||
continue;
|
||||
|
||||
int32 itemx, itemy;
|
||||
getItemCoords(item, itemx, itemy);
|
||||
const Shape *s = item->getShapeObject();
|
||||
assert(s);
|
||||
surf->Paint(s, item->getFrame(), itemx, itemy);
|
||||
}
|
||||
|
||||
|
||||
if (_displayDragging) {
|
||||
int32 itemx, itemy;
|
||||
itemx = _draggingX + _itemArea.left;
|
||||
itemy = _draggingY + _itemArea.top;
|
||||
Shape *s = GameData::get_instance()->getMainShapes()->
|
||||
getShape(_draggingShape);
|
||||
assert(s);
|
||||
surf->PaintInvisible(s, _draggingFrame, itemx, itemy, false, (_draggingFlags & Item::FLG_FLIPPED) != 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Find object (if any) at (mx,my)
|
||||
// (mx,my) are relative to parent
|
||||
uint16 ContainerGump::TraceObjId(int32 mx, int32 my) {
|
||||
uint16 objId_ = Gump::TraceObjId(mx, my);
|
||||
if (objId_ && objId_ != 65535) return objId_;
|
||||
|
||||
ParentToGump(mx, my);
|
||||
|
||||
Container *c = getContainer(_owner);
|
||||
|
||||
if (!c)
|
||||
return 0; // Container gone!?
|
||||
|
||||
bool showEditorItems = Ultima8Engine::get_instance()->isShowEditorItems();
|
||||
|
||||
Std::list<Item *> &contents = c->_contents;
|
||||
Std::list<Item *>::iterator iter;
|
||||
|
||||
// iterate backwards, since we're painting from begin() to end()
|
||||
for (iter = contents.reverse_begin(); iter != contents.end(); --iter) {
|
||||
Item *item = *iter;
|
||||
if (!showEditorItems && item->getShapeInfo()->is_editor())
|
||||
continue;
|
||||
|
||||
int32 itemx, itemy;
|
||||
getItemCoords(item, itemx, itemy);
|
||||
const Shape *s = item->getShapeObject();
|
||||
assert(s);
|
||||
const ShapeFrame *frame = s->getFrame(item->getFrame());
|
||||
|
||||
if (frame->hasPoint(mx - itemx, my - itemy)) {
|
||||
// found it
|
||||
return item->getObjId();
|
||||
}
|
||||
}
|
||||
|
||||
// didn't find anything, so return self
|
||||
return getObjId();
|
||||
}
|
||||
|
||||
// get item coords relative to self
|
||||
bool ContainerGump::GetLocationOfItem(uint16 itemid, int32 &gx, int32 &gy,
|
||||
int32 lerp_factor) {
|
||||
Item *item = getItem(itemid);
|
||||
if (!item) return false;
|
||||
Item *parent = item->getParentAsContainer();
|
||||
if (!parent) return false;
|
||||
if (parent->getObjId() != _owner) return false;
|
||||
|
||||
//!!! need to use lerp_factor
|
||||
|
||||
int32 itemx, itemy;
|
||||
getItemCoords(item, itemx, itemy);
|
||||
|
||||
gx = itemx;
|
||||
gy = itemy;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// we don't want our position to depend on Gump of parent container
|
||||
// so change the default ItemRelativeGump behaviour
|
||||
void ContainerGump::GetItemLocation(int32 lerp_factor) {
|
||||
Item *it = getItem(_owner);
|
||||
|
||||
if (!it) {
|
||||
// This shouldn't ever happen, the GumpNotifyProcess should
|
||||
// close us before we get here
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
int32 gx, gy;
|
||||
Container *root = it->getRootContainer();
|
||||
Item *topitem = root ? root : it;
|
||||
|
||||
Gump *gump = GetRootGump()->FindGump<GameMapGump>();
|
||||
assert(gump);
|
||||
gump->GetLocationOfItem(topitem->getObjId(), gx, gy, lerp_factor);
|
||||
|
||||
// Convert the GumpSpaceCoord relative to the world/item gump
|
||||
// into screenspace coords
|
||||
gy = gy - it->getShapeInfo()->_z * 8 - 16;
|
||||
gump->GumpToScreenSpace(gx, gy);
|
||||
|
||||
// Convert the screenspace coords into the coords of us
|
||||
if (_parent) _parent->ScreenSpaceToGump(gx, gy);
|
||||
|
||||
// Set x and y, and center us over it
|
||||
_ix = gx - _dims.width() / 2;
|
||||
_iy = gy - _dims.height();
|
||||
}
|
||||
|
||||
void ContainerGump::Close(bool no_del) {
|
||||
// close any gumps belonging to contents
|
||||
// and make every item leave the fast area
|
||||
Container *c = getContainer(_owner);
|
||||
if (!c) return; // Container gone!?
|
||||
|
||||
Std::list<Item *> &contents = c->_contents;
|
||||
Std::list<Item *>::iterator iter = contents.begin();
|
||||
while (iter != contents.end()) {
|
||||
Item *item = *iter;
|
||||
++iter;
|
||||
Gump *g = getGump(item->getGump());
|
||||
if (g) {
|
||||
g->Close(); //!! what about no_del?
|
||||
}
|
||||
item->leaveFastArea(); // Can destroy the item
|
||||
}
|
||||
|
||||
Item *o = getItem(_owner);
|
||||
if (o)
|
||||
o->clearGump(); //!! is this the appropriate place?
|
||||
|
||||
ItemRelativeGump::Close(no_del);
|
||||
}
|
||||
|
||||
Container *ContainerGump::getTargetContainer(Item *item, int mx, int my) {
|
||||
int32 px = mx, py = my;
|
||||
GumpToParent(px, py);
|
||||
Container *targetcontainer = getContainer(TraceObjId(px, py));
|
||||
|
||||
if (targetcontainer && targetcontainer->getObjId() == item->getObjId())
|
||||
targetcontainer = nullptr;
|
||||
|
||||
if (targetcontainer) {
|
||||
const ShapeInfo *targetinfo = targetcontainer->getShapeInfo();
|
||||
if ((targetcontainer->getObjId() == item->getObjId()) ||
|
||||
targetinfo->is_land() ||
|
||||
targetcontainer->hasFlags(Item::FLG_IN_NPC_LIST)) {
|
||||
targetcontainer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (!targetcontainer)
|
||||
targetcontainer = getContainer(_owner);
|
||||
|
||||
return targetcontainer;
|
||||
}
|
||||
|
||||
|
||||
Gump *ContainerGump::onMouseDown(int button, int32 mx, int32 my) {
|
||||
Gump *handled = Gump::onMouseDown(button, mx, my);
|
||||
if (handled) return handled;
|
||||
|
||||
// only interested in left clicks
|
||||
if (button == Mouse::BUTTON_LEFT)
|
||||
return this;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ContainerGump::onMouseClick(int button, int32 mx, int32 my) {
|
||||
if (button == Mouse::BUTTON_LEFT) {
|
||||
uint16 objID = TraceObjId(mx, my);
|
||||
|
||||
Item *item = getItem(objID);
|
||||
if (item) {
|
||||
debugC(kDebugObject, "%s", item->dumpInfo().c_str());
|
||||
|
||||
if (Ultima8Engine::get_instance()->isAvatarInStasis()) {
|
||||
debugC(kDebugObject, "Can't look: avatarInStasis");
|
||||
} else {
|
||||
item->callUsecodeEvent_look();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ContainerGump::onMouseDouble(int button, int32 mx, int32 my) {
|
||||
if (button == Mouse::BUTTON_LEFT) {
|
||||
uint16 objID = TraceObjId(mx, my);
|
||||
|
||||
if (objID == getObjId()) {
|
||||
objID = _owner; // use container when double click on self
|
||||
}
|
||||
|
||||
Item *item = getItem(objID);
|
||||
if (item) {
|
||||
debugC(kDebugObject, "%s", item->dumpInfo().c_str());
|
||||
|
||||
if (objID == _owner) {
|
||||
// call the 'use' event
|
||||
item->use();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Ultima8Engine::get_instance()->isAvatarInStasis()) {
|
||||
debugC(kDebugObject, "Can't use: avatarInStasis");
|
||||
return;
|
||||
}
|
||||
|
||||
MainActor *avatar = getMainActor();
|
||||
if (avatar->canReach(item, 128)) { // CONSTANT!
|
||||
// call the 'use' event
|
||||
item->use();
|
||||
} else {
|
||||
Mouse::get_instance()->flashCrossCursor();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ContainerGump::StartDraggingItem(Item *item, int mx, int my) {
|
||||
// probably don't need to check if item can be moved, since it shouldn't
|
||||
// be in a container otherwise
|
||||
|
||||
Container *c = getContainer(_owner);
|
||||
assert(c);
|
||||
|
||||
// check if the container the item is in is in range
|
||||
MainActor *avatar = getMainActor();
|
||||
if (!avatar->canReach(c, 128)) return false;
|
||||
|
||||
int32 itemx, itemy;
|
||||
getItemCoords(item, itemx, itemy);
|
||||
|
||||
Mouse::get_instance()->setDraggingOffset(mx - itemx, my - itemy);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ContainerGump::DraggingItem(Item *item, int mx, int my) {
|
||||
Container *c = getContainer(_owner);
|
||||
assert(c);
|
||||
|
||||
// check if the container the item is in is in range
|
||||
MainActor *avatar = getMainActor();
|
||||
if (!avatar->canReach(c, 128)) {
|
||||
_displayDragging = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
int32 dox, doy;
|
||||
Mouse::get_instance()->getDraggingOffset(dox, doy);
|
||||
Mouse::get_instance()->setMouseCursor(Mouse::MOUSE_TARGET);
|
||||
_displayDragging = true;
|
||||
|
||||
_draggingShape = item->getShape();
|
||||
_draggingFrame = item->getFrame();
|
||||
_draggingFlags = item->getFlags();
|
||||
|
||||
// determine target location and set dragging_x/y
|
||||
|
||||
_draggingX = mx - _itemArea.left - dox;
|
||||
_draggingY = my - _itemArea.top - doy;
|
||||
|
||||
const Shape *sh = item->getShapeObject();
|
||||
assert(sh);
|
||||
const ShapeFrame *fr = sh->getFrame(_draggingFrame);
|
||||
assert(fr);
|
||||
|
||||
if (_draggingX - fr->_xoff < 0 ||
|
||||
_draggingX - fr->_xoff + fr->_width > _itemArea.width() ||
|
||||
_draggingY - fr->_yoff < 0 ||
|
||||
_draggingY - fr->_yoff + fr->_height > _itemArea.height()) {
|
||||
_displayDragging = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if item will fit (weight/volume/adding container to itself)
|
||||
Container *target = getTargetContainer(item, mx, my);
|
||||
if (!target || !target->CanAddItem(item, true)) {
|
||||
_displayDragging = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ContainerGump::DraggingItemLeftGump(Item *item) {
|
||||
_displayDragging = false;
|
||||
}
|
||||
|
||||
|
||||
void ContainerGump::StopDraggingItem(Item *item, bool moved) {
|
||||
if (!moved) return; // nothing to do
|
||||
}
|
||||
|
||||
void ContainerGump::DropItem(Item *item, int mx, int my) {
|
||||
_displayDragging = false;
|
||||
|
||||
int32 px = mx, py = my;
|
||||
GumpToParent(px, py);
|
||||
// see what the item is being dropped on
|
||||
Item *targetitem = getItem(TraceObjId(px, py));
|
||||
Container *targetcontainer = dynamic_cast<Container *>(targetitem);
|
||||
|
||||
|
||||
if (item->getShapeInfo()->hasQuantity() &&
|
||||
item->getQuality() > 1) {
|
||||
// more than one, so see if we should ask if we should split it up
|
||||
|
||||
Item *splittarget = nullptr;
|
||||
|
||||
// also try to combine
|
||||
if (targetitem && item->canMergeWith(targetitem)) {
|
||||
splittarget = targetitem;
|
||||
}
|
||||
|
||||
if (!splittarget) {
|
||||
// create new item
|
||||
splittarget = ItemFactory::createItem(
|
||||
item->getShape(), item->getFrame(), 0,
|
||||
item->getFlags() & (Item::FLG_DISPOSABLE | Item::FLG_OWNED | Item::FLG_INVISIBLE | Item::FLG_FLIPPED | Item::FLG_FAST_ONLY | Item::FLG_LOW_FRICTION), item->getNpcNum(), item->getMapNum(),
|
||||
item->getExtFlags() & (Item::EXT_SPRITE | Item::EXT_HIGHLIGHT | Item::EXT_TRANSPARENT), true);
|
||||
if (!splittarget) {
|
||||
warning("ContainerGump failed to create item (%u,%u) while splitting",
|
||||
item->getShape(), item->getFrame());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (targetcontainer) {
|
||||
splittarget->moveToContainer(targetcontainer);
|
||||
splittarget->randomGumpLocation();
|
||||
} else {
|
||||
splittarget->moveToContainer(getContainer(_owner));
|
||||
splittarget->setGumpLocation(_draggingX, _draggingY);
|
||||
}
|
||||
}
|
||||
|
||||
SliderGump *slidergump = new SliderGump(100, 100,
|
||||
0, item->getQuality(),
|
||||
item->getQuality());
|
||||
slidergump->InitGump(0);
|
||||
slidergump->CreateNotifier(); // manually create notifier
|
||||
Process *notifier = slidergump->GetNotifyProcess();
|
||||
SplitItemProcess *splitproc = new SplitItemProcess(item, splittarget);
|
||||
Kernel::get_instance()->addProcess(splitproc);
|
||||
splitproc->waitFor(notifier);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (targetitem && item->getShapeInfo()->hasQuantity()) {
|
||||
// try to combine items
|
||||
if (item->canMergeWith(targetitem)) {
|
||||
uint16 newquant = targetitem->getQuality() + item->getQuality();
|
||||
if (newquant > Item::MAX_QUANTITY) {
|
||||
item->setQuality(newquant - Item::MAX_QUANTITY);
|
||||
targetitem->setQuality(Item::MAX_QUANTITY);
|
||||
// maybe this isn't needed? original doesn't do it here..
|
||||
targetitem->callUsecodeEvent_combine();
|
||||
} else {
|
||||
targetitem->setQuality(newquant);
|
||||
targetitem->callUsecodeEvent_combine();
|
||||
// combined, so delete other
|
||||
item->destroy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
targetcontainer = getTargetContainer(item, mx, my);
|
||||
assert(targetcontainer);
|
||||
|
||||
if (targetcontainer->getObjId() != _owner) {
|
||||
if (item->getParent() == targetcontainer->getObjId()) {
|
||||
// already in this container, so move item to let it be drawn
|
||||
// on top of all other items
|
||||
targetcontainer->moveItemToEnd(item);
|
||||
} else {
|
||||
item->moveToContainer(targetcontainer);
|
||||
item->randomGumpLocation();
|
||||
}
|
||||
} else {
|
||||
// add item to self
|
||||
|
||||
if (item->getParent() == _owner) {
|
||||
targetcontainer->moveItemToEnd(item);
|
||||
} else {
|
||||
item->moveToContainer(targetcontainer);
|
||||
}
|
||||
|
||||
int32 dox, doy;
|
||||
Mouse::get_instance()->getDraggingOffset(dox, doy);
|
||||
_draggingX = mx - _itemArea.left - dox;
|
||||
_draggingY = my - _itemArea.top - doy;
|
||||
item->setGumpLocation(_draggingX, _draggingY);
|
||||
}
|
||||
}
|
||||
|
||||
void ContainerGump::saveData(Common::WriteStream *ws) {
|
||||
ItemRelativeGump::saveData(ws);
|
||||
|
||||
ws->writeUint32LE(static_cast<uint32>(_itemArea.left));
|
||||
ws->writeUint32LE(static_cast<uint32>(_itemArea.top));
|
||||
ws->writeUint32LE(static_cast<uint32>(_itemArea.width()));
|
||||
ws->writeUint32LE(static_cast<uint32>(_itemArea.height()));
|
||||
}
|
||||
|
||||
bool ContainerGump::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
if (!ItemRelativeGump::loadData(rs, version)) return false;
|
||||
|
||||
int32 iax = static_cast<int32>(rs->readUint32LE());
|
||||
int32 iay = static_cast<int32>(rs->readUint32LE());
|
||||
int32 iaw = static_cast<int32>(rs->readUint32LE());
|
||||
int32 iah = static_cast<int32>(rs->readUint32LE());
|
||||
_itemArea.moveTo(iax, iay);
|
||||
_itemArea.setWidth(iaw);
|
||||
_itemArea.setHeight(iah);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
102
engines/ultima/ultima8/gumps/container_gump.h
Normal file
102
engines/ultima/ultima8/gumps/container_gump.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_CONTAINERGUMP_H
|
||||
#define ULTIMA8_GUMPS_CONTAINERGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/item_relative_gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class Shape;
|
||||
class Container;
|
||||
|
||||
/**
|
||||
* Base gump class for all containers (backpack, barrel, etc)
|
||||
*/
|
||||
class ContainerGump : public ItemRelativeGump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
ContainerGump();
|
||||
ContainerGump(const Shape *shape, uint32 frameNum, uint16 owner,
|
||||
uint32 flags = FLAG_DRAGGABLE, int32 layer = LAYER_NORMAL);
|
||||
~ContainerGump() override;
|
||||
|
||||
void setItemArea(Common::Rect32 *itemArea) {
|
||||
_itemArea = *itemArea;
|
||||
}
|
||||
|
||||
// Close the gump
|
||||
void Close(bool no_del = false) override;
|
||||
|
||||
// Init the gump, call after construction
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
|
||||
void run() override;
|
||||
|
||||
// Paint the Gump
|
||||
void PaintThis(RenderSurface *, int32 lerp_factor, bool scaled) override;
|
||||
|
||||
// Trace a click, and return ObjId
|
||||
uint16 TraceObjId(int32 mx, int32 my) override;
|
||||
|
||||
// Get the location of an item in the gump (coords relative to this).
|
||||
// Returns false on failure.
|
||||
bool GetLocationOfItem(uint16 itemid, int32 &gx, int32 &gy,
|
||||
int32 lerp_factor = 256) override;
|
||||
|
||||
|
||||
bool StartDraggingItem(Item *item, int mx, int my) override;
|
||||
bool DraggingItem(Item *item, int mx, int my) override;
|
||||
void DraggingItemLeftGump(Item *item) override;
|
||||
void StopDraggingItem(Item *item, bool moved) override;
|
||||
void DropItem(Item *item, int mx, int my) override;
|
||||
|
||||
Gump *onMouseDown(int button, int32 mx, int32 my) override;
|
||||
void onMouseClick(int button, int32 mx, int32 my) override;
|
||||
void onMouseDouble(int button, int32 mx, int32 my) override;
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
|
||||
protected:
|
||||
void GetItemLocation(int32 lerp_factor) override;
|
||||
|
||||
virtual Container *getTargetContainer(Item *item, int mx, int my);
|
||||
|
||||
void getItemCoords(Item *item, int32 &itemx, int32 &itemy);
|
||||
|
||||
Common::Rect32 _itemArea;
|
||||
|
||||
bool _displayDragging;
|
||||
uint32 _draggingShape;
|
||||
uint32 _draggingFrame;
|
||||
uint32 _draggingFlags;
|
||||
int32 _draggingX, _draggingY;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
409
engines/ultima/ultima8/gumps/credits_gump.cpp
Normal file
409
engines/ultima/ultima8/gumps/credits_gump.cpp
Normal file
@@ -0,0 +1,409 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/config-manager.h"
|
||||
#include "common/events.h"
|
||||
|
||||
#include "ultima/ultima8/gumps/credits_gump.h"
|
||||
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
#include "ultima/ultima8/kernel/mouse.h"
|
||||
#include "ultima/ultima8/gfx/render_surface.h"
|
||||
#include "ultima/ultima8/gfx/texture.h"
|
||||
#include "ultima/ultima8/gfx/fonts/rendered_text.h"
|
||||
#include "ultima/ultima8/gfx/fonts/font.h"
|
||||
#include "ultima/ultima8/gfx/fonts/font_manager.h"
|
||||
#include "ultima/ultima8/audio/music_process.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(CreditsGump)
|
||||
|
||||
CreditsGump::CreditsGump()
|
||||
: ModalGump(), _parSkip(0), _timer(0), _title(nullptr),
|
||||
_nextTitle(nullptr), _state(CS_PLAYING),
|
||||
_nextTitleSurf(0), _currentSurface(0), _currentY(0) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
_scroll[i] = nullptr;
|
||||
_scrollHeight[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
CreditsGump::CreditsGump(const Std::string &text, int parskip,
|
||||
uint32 flags, int32 layer)
|
||||
: ModalGump(0, 0, 320, 200, 0, flags, layer), _text(text), _parSkip(parskip),
|
||||
_timer(0), _title(nullptr), _nextTitle(nullptr), _state(CS_PLAYING),
|
||||
_nextTitleSurf(0), _currentSurface(0), _currentY(0) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
_scroll[i] = nullptr;
|
||||
_scrollHeight[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
CreditsGump::~CreditsGump() {
|
||||
delete _scroll[0];
|
||||
delete _scroll[1];
|
||||
delete _scroll[2];
|
||||
delete _scroll[3];
|
||||
|
||||
delete _title;
|
||||
delete _nextTitle;
|
||||
}
|
||||
|
||||
void CreditsGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
ModalGump::InitGump(newparent, take_focus);
|
||||
|
||||
Graphics::Screen *screen = Ultima8Engine::get_instance()->getScreen();
|
||||
uint32 width = 256;
|
||||
uint32 height = 280;
|
||||
|
||||
_scroll[0] = new RenderSurface(width, height, screen->format);
|
||||
_scroll[1] = new RenderSurface(width, height, screen->format);
|
||||
_scroll[2] = new RenderSurface(width, height, screen->format);
|
||||
_scroll[3] = new RenderSurface(width, height, screen->format);
|
||||
|
||||
uint32 color = TEX32_PACK_RGB(0, 0, 0);
|
||||
_scroll[0]->fill32(color, 0, 0, width, height); // black background
|
||||
_scroll[1]->fill32(color, 0, 0, width, height);
|
||||
_scroll[2]->fill32(color, 0, 0, width, height);
|
||||
_scroll[3]->fill32(color, 0, 0, width, height);
|
||||
|
||||
_scrollHeight[0] = 156;
|
||||
_scrollHeight[1] = 0;
|
||||
_scrollHeight[2] = 0;
|
||||
_scrollHeight[3] = 0;
|
||||
|
||||
_currentSurface = 0;
|
||||
_currentY = 0;
|
||||
|
||||
Mouse::get_instance()->pushMouseCursor(Mouse::MOUSE_NONE);
|
||||
}
|
||||
|
||||
void CreditsGump::Close(bool no_del) {
|
||||
Mouse::get_instance()->popMouseCursor();
|
||||
|
||||
ModalGump::Close(no_del);
|
||||
|
||||
MusicProcess *musicproc = MusicProcess::get_instance();
|
||||
if (musicproc) musicproc->playMusic(0);
|
||||
}
|
||||
|
||||
void CreditsGump::extractLine(Std::string &text,
|
||||
char &modifier, Std::string &line) {
|
||||
if (!text.empty() && (text[0] == '+' || text[0] == '&' || text[0] == '}' ||
|
||||
text[0] == '~' || text[0] == '@')) {
|
||||
modifier = text[0];
|
||||
text.erase(0, 1);
|
||||
} else {
|
||||
modifier = 0;
|
||||
}
|
||||
|
||||
if (text.empty()) {
|
||||
line = "";
|
||||
return;
|
||||
}
|
||||
|
||||
Std::string::size_type starpos = text.find('*');
|
||||
|
||||
line = text.substr(0, starpos);
|
||||
|
||||
// replace '%%' by '%'.
|
||||
// (Original interpreted these strings as format strings??)
|
||||
Std::string::size_type ppos;
|
||||
while ((ppos = line.find("%%")) != Std::string::npos) {
|
||||
line.replace(ppos, 2, "%");
|
||||
}
|
||||
|
||||
if (starpos != Std::string::npos) starpos++;
|
||||
text.erase(0, starpos);
|
||||
}
|
||||
|
||||
|
||||
void CreditsGump::run() {
|
||||
ModalGump::run();
|
||||
|
||||
if (_timer) {
|
||||
_timer--;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_state == CS_CLOSING) {
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
_timer = 1;
|
||||
|
||||
int available = _scrollHeight[_currentSurface] - _currentY;
|
||||
int nextblock = -1;
|
||||
for (int i = 1; i < 4; i++) {
|
||||
available += _scrollHeight[(_currentSurface + i) % 4];
|
||||
if (nextblock == -1 && _scrollHeight[(_currentSurface + i) % 4] == 0)
|
||||
nextblock = (_currentSurface + i) % 4;
|
||||
}
|
||||
if (available == 0) nextblock = 0;
|
||||
|
||||
if (_state == CS_FINISHING && available <= 156) {
|
||||
debug(6, "CreditsGump: waiting before closing");
|
||||
_timer = 120;
|
||||
_state = CS_CLOSING;
|
||||
|
||||
if (!_configKey.empty()) {
|
||||
ConfMan.setBool(_configKey, true);
|
||||
ConfMan.flushToDisk();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (_state == CS_PLAYING && available <= 160) {
|
||||
// This shouldn't happen, but just in case..
|
||||
if (nextblock == -1)
|
||||
nextblock = 0;
|
||||
// time to render next block
|
||||
Common::Rect32 bounds = _scroll[nextblock]->getSurfaceDims();
|
||||
|
||||
uint32 color = TEX32_PACK_RGB(0, 0, 0);
|
||||
_scroll[nextblock]->fill32(color, 0, 0, bounds.width(), bounds.height());
|
||||
|
||||
//color = TEX32_PACK_RGB(0xFF, 0xFF, 0xFF);
|
||||
//_scroll[nextblock]->fill32(color, 0, 0, bounds.width(), 2); // block marker
|
||||
_scrollHeight[nextblock] = 0;
|
||||
|
||||
Font *redfont, *yellowfont;
|
||||
|
||||
redfont = FontManager::get_instance()->getGameFont(6, true);
|
||||
yellowfont = FontManager::get_instance()->getGameFont(8, true);
|
||||
|
||||
bool done = false;
|
||||
bool firstline = true;
|
||||
while (!_text.empty() && !done) {
|
||||
Std::string::size_type endline = _text.find('\n');
|
||||
Std::string line = _text.substr(0, endline);
|
||||
|
||||
if (line.empty()) {
|
||||
_text.erase(0, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
debug(6, "Rendering paragraph: %s", line.c_str());
|
||||
|
||||
if (line[0] == '+') {
|
||||
// set _title
|
||||
if (!firstline) {
|
||||
// if this isn't the first line of the block,
|
||||
// postpone setting _title until next block
|
||||
done = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
Std::string titletext;
|
||||
char modifier;
|
||||
|
||||
extractLine(line, modifier, titletext);
|
||||
|
||||
unsigned int remaining;
|
||||
_nextTitle = redfont->renderText(titletext, remaining, 192, 0,
|
||||
Font::TEXT_CENTER);
|
||||
|
||||
if (!_title) {
|
||||
_title = _nextTitle;
|
||||
_nextTitle = nullptr;
|
||||
} else {
|
||||
_nextTitleSurf = nextblock;
|
||||
_scrollHeight[nextblock] = 160; // skip some space
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
int height = 0;
|
||||
|
||||
Font *font = redfont;
|
||||
Font::TextAlign align = Font::TEXT_LEFT;
|
||||
int indent = 0;
|
||||
|
||||
while (!line.empty()) {
|
||||
Std::string outline;
|
||||
char modifier;
|
||||
unsigned int remaining;
|
||||
extractLine(line, modifier, outline);
|
||||
|
||||
debug(6, "Rendering line: %s", outline.c_str());
|
||||
|
||||
switch (modifier) {
|
||||
case '&':
|
||||
font = yellowfont;
|
||||
align = Font::TEXT_CENTER;
|
||||
break;
|
||||
case '}':
|
||||
font = redfont;
|
||||
align = Font::TEXT_CENTER;
|
||||
break;
|
||||
case '~':
|
||||
font = yellowfont;
|
||||
align = Font::TEXT_LEFT;
|
||||
indent = 32;
|
||||
break;
|
||||
case '@':
|
||||
debug(6, "CreditsGump: done, finishing");
|
||||
_state = CS_FINISHING;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!modifier && outline.empty()) {
|
||||
height += 48;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (outline.hasPrefix("&")) {
|
||||
// horizontal line
|
||||
|
||||
if (_scrollHeight[nextblock] + height + 7 > bounds.height()) {
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
|
||||
int linewidth = outline.size() * 8;
|
||||
if (linewidth > 192) linewidth = 192;
|
||||
|
||||
color = TEX32_PACK_RGB(0xD4, 0x30, 0x30);
|
||||
_scroll[nextblock]->fill32(color, 128 - (linewidth / 2),
|
||||
_scrollHeight[nextblock] + height + 3,
|
||||
linewidth, 1);
|
||||
height += 7;
|
||||
continue;
|
||||
}
|
||||
|
||||
RenderedText *rt = font->renderText(outline, remaining,
|
||||
bounds.width() - indent, 0,
|
||||
align);
|
||||
int xd, yd;
|
||||
rt->getSize(xd, yd);
|
||||
|
||||
if (_scrollHeight[nextblock] + height + yd > bounds.height()) {
|
||||
delete rt;
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
|
||||
rt->draw(_scroll[nextblock], indent,
|
||||
_scrollHeight[nextblock] + height +
|
||||
font->getBaseline());
|
||||
|
||||
height += yd + rt->getVlead();
|
||||
|
||||
delete rt;
|
||||
}
|
||||
|
||||
if (_state == CS_PLAYING)
|
||||
height += _parSkip;
|
||||
|
||||
if (_scrollHeight[nextblock] + height > bounds.height()) {
|
||||
if (firstline) {
|
||||
height = bounds.height() - _scrollHeight[nextblock];
|
||||
assert(height >= 0);
|
||||
} else {
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (done) break; // no room
|
||||
|
||||
_scrollHeight[nextblock] += height;
|
||||
}
|
||||
|
||||
|
||||
if (endline != Std::string::npos) endline++;
|
||||
_text.erase(0, endline);
|
||||
|
||||
firstline = false;
|
||||
}
|
||||
}
|
||||
|
||||
_currentY++;
|
||||
|
||||
if (_currentY >= _scrollHeight[_currentSurface]) {
|
||||
// next surface
|
||||
_currentY -= _scrollHeight[_currentSurface];
|
||||
_scrollHeight[_currentSurface] = 0;
|
||||
_currentSurface = (_currentSurface + 1) % 4;
|
||||
|
||||
if (_nextTitle && _currentSurface == _nextTitleSurf) {
|
||||
delete _title;
|
||||
_title = _nextTitle;
|
||||
_nextTitle = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CreditsGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
uint32 color = TEX32_PACK_RGB(0, 0, 0);
|
||||
surf->fill32(color, 0, 0, 320, 200);
|
||||
|
||||
// line between _title and scroller
|
||||
color = TEX32_PACK_RGB(0xD4, 0x30, 0x30);
|
||||
surf->fill32(color, 64, 41, 192, 1);
|
||||
|
||||
if (_title)
|
||||
_title->draw(surf, 64, 34);
|
||||
|
||||
int h = _scrollHeight[_currentSurface] - _currentY;
|
||||
if (h > 156) h = 156;
|
||||
if (h > 0) {
|
||||
Graphics::ManagedSurface* ms = _scroll[_currentSurface]->getRawSurface();
|
||||
Common::Rect srcRect(0, _currentY, ms->w, _currentY + h);
|
||||
surf->Blit(*ms, srcRect, 32, 44);
|
||||
}
|
||||
|
||||
int y = h;
|
||||
for (int i = 1; i < 4; i++) {
|
||||
if (h == 156) break;
|
||||
|
||||
int s = (_currentSurface + i) % 4;
|
||||
h = _scrollHeight[s];
|
||||
if (h > 156 - y) h = 156 - y;
|
||||
if (h > 0) {
|
||||
Graphics::ManagedSurface* ms = _scroll[s]->getRawSurface();
|
||||
Common::Rect srcRect(0, 0, ms->w, h);
|
||||
surf->Blit(*ms, srcRect, 32, 44 + y);
|
||||
}
|
||||
y += h;
|
||||
}
|
||||
}
|
||||
|
||||
bool CreditsGump::OnKeyDown(int key, int mod) {
|
||||
switch (key) {
|
||||
case Common::KEYCODE_ESCAPE: {
|
||||
Close();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
93
engines/ultima/ultima8/gumps/credits_gump.h
Normal file
93
engines/ultima/ultima8/gumps/credits_gump.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_CREDITSGUMP_H
|
||||
#define ULTIMA8_GUMPS_CREDITSGUMP_H
|
||||
|
||||
#include "ultima/shared/std/string.h"
|
||||
#include "ultima/ultima8/gumps/modal_gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class RenderedText;
|
||||
|
||||
/**
|
||||
* Full-screen gump for the credits roll in U8
|
||||
*/
|
||||
class CreditsGump : public ModalGump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
CreditsGump();
|
||||
CreditsGump(const Std::string &text, int parskip = 24,
|
||||
uint32 flags = FLAG_PREVENT_SAVE, int32 layer = LAYER_MODAL);
|
||||
~CreditsGump() override;
|
||||
|
||||
// Init the gump, call after construction
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
|
||||
// Set a configuration option to true when user watches entire sequence
|
||||
void SetFlagWhenFinished(Std::string configKey) {
|
||||
_configKey = configKey;
|
||||
}
|
||||
|
||||
void Close(bool no_del = false) override;
|
||||
|
||||
void run() override;
|
||||
|
||||
// Paint the Gump
|
||||
void PaintThis(RenderSurface *, int32 lerp_factor, bool scaled) override;
|
||||
|
||||
bool OnKeyDown(int key, int mod) override;
|
||||
|
||||
protected:
|
||||
|
||||
void extractLine(Std::string &text, char &modifier, Std::string &line);
|
||||
|
||||
Std::string _text;
|
||||
int _parSkip;
|
||||
|
||||
enum CreditsState {
|
||||
CS_PLAYING,
|
||||
CS_FINISHING,
|
||||
CS_CLOSING
|
||||
} _state;
|
||||
|
||||
int _timer;
|
||||
|
||||
RenderedText *_title;
|
||||
RenderedText *_nextTitle;
|
||||
int _nextTitleSurf;
|
||||
|
||||
RenderSurface *_scroll[4];
|
||||
int _scrollHeight[4];
|
||||
int _currentSurface;
|
||||
int _currentY;
|
||||
|
||||
Std::string _configKey;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
140
engines/ultima/ultima8/gumps/cru_ammo_gump.cpp
Normal file
140
engines/ultima/ultima8/gumps/cru_ammo_gump.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/cru_ammo_gump.h"
|
||||
|
||||
#include "ultima/ultima8/world/actors/main_actor.h"
|
||||
#include "ultima/ultima8/gumps/widgets/text_widget.h"
|
||||
#include "ultima/ultima8/world/get_object.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(CruAmmoGump)
|
||||
|
||||
static const int REM_FONT_NUM = 15;
|
||||
static const int REG_FONT_NUM = 8;
|
||||
|
||||
static const int REM_XOFF = 22;
|
||||
static const int REG_XOFF = 38;
|
||||
static const int REM_YOFF = 3;
|
||||
static const int REG_YOFF = 6;
|
||||
|
||||
CruAmmoGump::CruAmmoGump() : CruStatGump(), _clipsText(nullptr), _bulletsText(nullptr) {
|
||||
|
||||
}
|
||||
|
||||
CruAmmoGump::CruAmmoGump(Shape *shape, int x) : CruStatGump(shape, x),
|
||||
_clipsText(nullptr), _bulletsText(nullptr) {
|
||||
_frameNum = 1;
|
||||
}
|
||||
|
||||
CruAmmoGump::~CruAmmoGump() {
|
||||
}
|
||||
|
||||
void CruAmmoGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
CruStatGump::InitGump(newparent, take_focus);
|
||||
}
|
||||
|
||||
void CruAmmoGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
MainActor *a = getMainActor();
|
||||
if (!a) {
|
||||
// avatar gone??
|
||||
return;
|
||||
}
|
||||
|
||||
uint16 active = a->getActiveWeapon();
|
||||
uint16 ammoitem = 0;
|
||||
int bullets = -1;
|
||||
uint16 clips = 0;
|
||||
if (active) {
|
||||
Item *item = getItem(active);
|
||||
if (item) {
|
||||
const WeaponInfo *weaponinfo = item->getShapeInfo()->_weaponInfo;
|
||||
//uint16 frameno = 0;
|
||||
if (weaponinfo && weaponinfo->_ammoType) {
|
||||
//frameno = weaponinfo->_ammoType;
|
||||
ammoitem = weaponinfo->_ammoShape;
|
||||
bullets = item->getQuality();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Only paint if this weapon has bullets that get used up.
|
||||
if (bullets >= 0 && a == getControlledActor()) {
|
||||
const int xoff = GAME_IS_REMORSE ? REM_XOFF : REG_XOFF;
|
||||
const int yoff = GAME_IS_REMORSE ? REM_YOFF : REG_YOFF;
|
||||
const int fontno = GAME_IS_REMORSE ? REM_FONT_NUM : REG_FONT_NUM;
|
||||
|
||||
const Std::string bulletstr = Std::string::format("%d", bullets);
|
||||
if (!_bulletsText || !bulletstr.equals(_bulletsText->getText())) {
|
||||
if (_bulletsText) {
|
||||
RemoveChild(_bulletsText);
|
||||
_bulletsText->Close();
|
||||
}
|
||||
_bulletsText = new TextWidget(xoff, _dims.height() / 2 - yoff, bulletstr, true, fontno);
|
||||
_bulletsText->InitGump(this, false);
|
||||
}
|
||||
|
||||
if (ammoitem) {
|
||||
Item *item = a->getFirstItemWithShape(ammoitem, true);
|
||||
if (item) {
|
||||
clips = item->getQuality();
|
||||
} else {
|
||||
clips = 0;
|
||||
}
|
||||
}
|
||||
|
||||
const Std::string clipstr = Std::string::format("%d", clips);
|
||||
if (!_clipsText || !clipstr.equals(_clipsText->getText())) {
|
||||
if (_clipsText) {
|
||||
RemoveChild(_clipsText);
|
||||
_clipsText->Close();
|
||||
}
|
||||
_clipsText = new TextWidget(_dims.width() / 2 + xoff, _dims.height() / 2 - yoff, clipstr, true, fontno);
|
||||
_clipsText->InitGump(this, false);
|
||||
}
|
||||
CruStatGump::PaintThis(surf, lerp_factor, scaled);
|
||||
} else {
|
||||
if (_bulletsText) {
|
||||
RemoveChild(_bulletsText);
|
||||
_bulletsText->Close();
|
||||
_bulletsText = nullptr;
|
||||
}
|
||||
if (_clipsText) {
|
||||
RemoveChild(_clipsText);
|
||||
_clipsText->Close();
|
||||
_clipsText = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CruAmmoGump::saveData(Common::WriteStream *ws) {
|
||||
CruStatGump::saveData(ws);
|
||||
}
|
||||
|
||||
bool CruAmmoGump::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
return CruStatGump::loadData(rs, version);
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
61
engines/ultima/ultima8/gumps/cru_ammo_gump.h
Normal file
61
engines/ultima/ultima8/gumps/cru_ammo_gump.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_CRUAMMOGUMP_H
|
||||
#define ULTIMA8_GUMPS_CRUAMMOGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/cru_stat_gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class TextWidget;
|
||||
|
||||
/**
|
||||
* Second box along the bottom of the screen, shows current ammo
|
||||
*/
|
||||
class CruAmmoGump : public CruStatGump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
CruAmmoGump();
|
||||
CruAmmoGump(Shape *shape, int x);
|
||||
~CruAmmoGump() override;
|
||||
|
||||
// Init the gump, call after construction
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
|
||||
// Paint this Gump
|
||||
void PaintThis(RenderSurface *, int32 lerp_factor, bool scaled) override;
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
|
||||
private:
|
||||
TextWidget *_bulletsText;
|
||||
TextWidget *_clipsText;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
218
engines/ultima/ultima8/gumps/cru_credits_gump.cpp
Normal file
218
engines/ultima/ultima8/gumps/cru_credits_gump.cpp
Normal file
@@ -0,0 +1,218 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/config-manager.h"
|
||||
#include "image/bmp.h"
|
||||
|
||||
#include "ultima/ultima8/gumps/cru_credits_gump.h"
|
||||
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
#include "ultima/ultima8/kernel/mouse.h"
|
||||
#include "ultima/ultima8/gfx/render_surface.h"
|
||||
#include "ultima/ultima8/gfx/palette_manager.h"
|
||||
#include "ultima/ultima8/gfx/texture.h"
|
||||
#include "ultima/ultima8/gfx/fonts/rendered_text.h"
|
||||
#include "ultima/ultima8/gfx/fonts/font.h"
|
||||
#include "ultima/ultima8/gfx/fonts/font_manager.h"
|
||||
#include "ultima/ultima8/gfx/fonts/shape_font.h"
|
||||
#include "ultima/ultima8/audio/music_process.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(CruCreditsGump)
|
||||
|
||||
CruCreditsGump::CruCreditsGump()
|
||||
: ModalGump(), _timer(0), _background(nullptr), _nextScreenStart(0),
|
||||
_screenNo(-1) {
|
||||
}
|
||||
|
||||
CruCreditsGump::CruCreditsGump(Common::SeekableReadStream *txtrs,
|
||||
Common::SeekableReadStream *bmprs,
|
||||
uint32 flags, int32 layer)
|
||||
: ModalGump(0, 0, 640, 480, 0, flags, layer),
|
||||
_timer(0), _background(nullptr), _nextScreenStart(0), _screenNo(-1)
|
||||
{
|
||||
Image::BitmapDecoder decoder;
|
||||
Graphics::Screen *sc = Ultima8Engine::get_instance()->getScreen();
|
||||
_background = new RenderSurface(640, 480, sc->format);
|
||||
|
||||
uint32 color = TEX32_PACK_RGB(0, 0, 0);
|
||||
_background->fill32(color, 0, 0, 640, 480); // black background
|
||||
|
||||
if (decoder.loadStream(*bmprs)) {
|
||||
// This does an extra copy via the ManagedSurface, but it's a once-off.
|
||||
const Graphics::Surface *bmpsurf = decoder.getSurface();
|
||||
Graphics::ManagedSurface ms;
|
||||
ms.copyFrom(*bmpsurf);
|
||||
ms.setPalette(decoder.getPalette().data(), 0, decoder.getPalette().size());
|
||||
Common::Rect srcRect(640, 480);
|
||||
_background->Blit(ms, srcRect, 0, 0);
|
||||
} else {
|
||||
warning("couldn't load bitmap background for credits.");
|
||||
}
|
||||
|
||||
// Lots of extra copies here, but it's only 4kb of text so it's fine.
|
||||
CredScreen screen;
|
||||
CredLine credline;
|
||||
|
||||
// not sure what these 4 bytes are?
|
||||
txtrs->readUint32LE();
|
||||
while (!txtrs->eos()) {
|
||||
Common::String line = txtrs->readString();
|
||||
if (!line.size())
|
||||
break;
|
||||
credline._text = line.substr(1);
|
||||
switch (line[0]) {
|
||||
case '@':
|
||||
credline._lineType = kCredTitle;
|
||||
screen._lines.push_back(credline);
|
||||
break;
|
||||
case '$':
|
||||
credline._lineType = kCredName;
|
||||
screen._lines.push_back(credline);
|
||||
break;
|
||||
case '*': {
|
||||
unsigned int i = 1;
|
||||
while (i < line.size() && line[i] == '*')
|
||||
i++;
|
||||
screen._delay = 60 * i;
|
||||
_screens.push_back(screen);
|
||||
screen._lines.clear();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (line.size())
|
||||
debug(6, "unhandled line in credits: %s", line.c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CruCreditsGump::~CruCreditsGump() {
|
||||
delete _background;
|
||||
|
||||
for (auto *line : _currentLines) {
|
||||
delete line;
|
||||
}
|
||||
}
|
||||
|
||||
void CruCreditsGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
ModalGump::InitGump(newparent, take_focus);
|
||||
|
||||
Mouse::get_instance()->pushMouseCursor(Mouse::MOUSE_NONE);
|
||||
|
||||
MusicProcess *musicproc = MusicProcess::get_instance();
|
||||
if (musicproc) {
|
||||
if (GAME_IS_REMORSE)
|
||||
musicproc->playMusic(19);
|
||||
else
|
||||
musicproc->playMusic(17);
|
||||
}
|
||||
}
|
||||
|
||||
void CruCreditsGump::Close(bool no_del) {
|
||||
Mouse::get_instance()->popMouseCursor();
|
||||
|
||||
ModalGump::Close(no_del);
|
||||
|
||||
// Just let it play out?
|
||||
//MusicProcess *musicproc = MusicProcess::get_instance();
|
||||
//if (musicproc) musicproc->restoreMusic();
|
||||
}
|
||||
|
||||
void CruCreditsGump::run() {
|
||||
ModalGump::run();
|
||||
|
||||
_timer++;
|
||||
|
||||
if (_timer < _nextScreenStart)
|
||||
return;
|
||||
|
||||
_screenNo++;
|
||||
if (_screenNo >= static_cast<int>(_screens.size())) {
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
_nextScreenStart += _screens[_screenNo]._delay;
|
||||
for (auto *line : _currentLines) {
|
||||
delete line;
|
||||
}
|
||||
_currentLines.clear();
|
||||
|
||||
const Common::Array<CredLine> &lines = _screens[_screenNo]._lines;
|
||||
|
||||
Font *titlefont = FontManager::get_instance()->getGameFont(16, true);
|
||||
Font *namefont = FontManager::get_instance()->getGameFont(17, true);
|
||||
Palette *pal = PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Cred);
|
||||
|
||||
ShapeFont *titleshapefont = dynamic_cast<ShapeFont *>(titlefont);
|
||||
if (pal && titleshapefont)
|
||||
titleshapefont->setPalette(pal);
|
||||
ShapeFont *nameshapefont = dynamic_cast<ShapeFont *>(namefont);
|
||||
if (pal && nameshapefont)
|
||||
nameshapefont->setPalette(pal);
|
||||
|
||||
for (const auto &line : lines) {
|
||||
Font *linefont = (line._lineType == kCredTitle) ? titlefont : namefont;
|
||||
if (!linefont) {
|
||||
// shouldn't happen.. just to be sure?
|
||||
warning("can't render credits line type %d, font is null", line._lineType);
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned int remaining;
|
||||
RenderedText *rendered = linefont->renderText(line._text, remaining, 640, 0, Font::TEXT_CENTER);
|
||||
_currentLines.push_back(rendered);
|
||||
}
|
||||
}
|
||||
|
||||
void CruCreditsGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
Common::Rect srcRect(640, 480);
|
||||
surf->Blit(*_background->getRawSurface(), srcRect, 0, 0);
|
||||
|
||||
unsigned int nlines = _currentLines.size();
|
||||
if (!nlines)
|
||||
return;
|
||||
|
||||
int width, height;
|
||||
_currentLines[0]->getSize(width, height);
|
||||
int vlead = _currentLines[0]->getVlead();
|
||||
|
||||
int total = nlines * (height + vlead);
|
||||
int yoffset = 240 - total / 2;
|
||||
|
||||
for (auto *line : _currentLines) {
|
||||
line->draw(surf, 0, yoffset);
|
||||
yoffset += (height + vlead);
|
||||
}
|
||||
}
|
||||
|
||||
bool CruCreditsGump::OnKeyDown(int key, int mod) {
|
||||
if (key == Common::KEYCODE_ESCAPE)
|
||||
Close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
95
engines/ultima/ultima8/gumps/cru_credits_gump.h
Normal file
95
engines/ultima/ultima8/gumps/cru_credits_gump.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_CRUCREDITSGUMP_H
|
||||
#define ULTIMA8_GUMPS_CRUCREDITSGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/modal_gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class RenderedText;
|
||||
|
||||
/**
|
||||
* Full-screen gump for the credits roll in Crusader: No Remorse
|
||||
*/
|
||||
class CruCreditsGump : public ModalGump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
CruCreditsGump();
|
||||
CruCreditsGump(Common::SeekableReadStream *txtrs, Common::SeekableReadStream *bmprs,
|
||||
uint32 flags = FLAG_PREVENT_SAVE, int32 layer = LAYER_MODAL);
|
||||
~CruCreditsGump() override;
|
||||
|
||||
// Init the gump, call after construction
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
|
||||
void Close(bool no_del = false) override;
|
||||
|
||||
void run() override;
|
||||
|
||||
// Paint the Gump
|
||||
void PaintThis(RenderSurface *, int32 lerp_factor, bool scaled) override;
|
||||
|
||||
bool OnKeyDown(int key, int mod) override;
|
||||
|
||||
protected:
|
||||
enum CredLineType {
|
||||
kCredTitle,
|
||||
kCredName
|
||||
};
|
||||
|
||||
struct CredLine {
|
||||
Common::String _text;
|
||||
enum CredLineType _lineType;
|
||||
};
|
||||
|
||||
struct CredScreen {
|
||||
//! The lines of text for this screen
|
||||
Common::Array<CredLine> _lines;
|
||||
//! How long to display this screen, in engine ticks
|
||||
unsigned int _delay;
|
||||
};
|
||||
|
||||
//! Number of clock ticks the gump has run
|
||||
int _timer;
|
||||
//! Clock tick where the next screen should be shown
|
||||
int _nextScreenStart;
|
||||
//! Current screen number
|
||||
int _screenNo;
|
||||
|
||||
//! Pre-rendered text
|
||||
Common::Array<RenderedText *> _currentLines;
|
||||
|
||||
//! The starry background picture
|
||||
RenderSurface *_background;
|
||||
|
||||
//! Screen text data
|
||||
Common::Array<CredScreen> _screens;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
108
engines/ultima/ultima8/gumps/cru_demo_gump.cpp
Normal file
108
engines/ultima/ultima8/gumps/cru_demo_gump.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/config-manager.h"
|
||||
#include "image/bmp.h"
|
||||
|
||||
#include "ultima/ultima8/gumps/cru_demo_gump.h"
|
||||
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
#include "ultima/ultima8/kernel/mouse.h"
|
||||
#include "ultima/ultima8/gfx/render_surface.h"
|
||||
#include "ultima/ultima8/gfx/texture.h"
|
||||
#include "ultima/ultima8/audio/music_process.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(CruDemoGump)
|
||||
|
||||
CruDemoGump::CruDemoGump()
|
||||
: ModalGump(), _background(nullptr) {
|
||||
}
|
||||
|
||||
CruDemoGump::CruDemoGump(Common::SeekableReadStream *bmprs, uint32 flags, int32 layer)
|
||||
: ModalGump(0, 0, 640, 480, 0, flags, layer), _background(nullptr)
|
||||
{
|
||||
Image::BitmapDecoder decoder;
|
||||
Graphics::Screen *screen = Ultima8Engine::get_instance()->getScreen();
|
||||
_background = new RenderSurface(640, 480, screen->format);
|
||||
|
||||
uint32 color = TEX32_PACK_RGB(0, 0, 0);
|
||||
_background->fill32(color, 0, 0, 640, 480); // black background
|
||||
|
||||
if (decoder.loadStream(*bmprs)) {
|
||||
// This does an extra copy via the ManagedSurface, but it's a once-off.
|
||||
const Graphics::Surface *bmpsurf = decoder.getSurface();
|
||||
Graphics::ManagedSurface ms;
|
||||
ms.copyFrom(*bmpsurf);
|
||||
ms.setPalette(decoder.getPalette().data(), 0, decoder.getPalette().size());
|
||||
Common::Rect srcRect(640, 480);
|
||||
_background->Blit(ms, srcRect, 0, 0);
|
||||
} else {
|
||||
warning("couldn't load bitmap background for demo screen.");
|
||||
}
|
||||
}
|
||||
|
||||
CruDemoGump::~CruDemoGump() {
|
||||
delete _background;
|
||||
}
|
||||
|
||||
void CruDemoGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
ModalGump::InitGump(newparent, take_focus);
|
||||
|
||||
Mouse::get_instance()->pushMouseCursor(Mouse::MOUSE_NONE);
|
||||
|
||||
MusicProcess *musicproc = MusicProcess::get_instance();
|
||||
if (musicproc) {
|
||||
if (GAME_IS_REMORSE) {
|
||||
musicproc->playMusic(21);
|
||||
} else {
|
||||
// TODO: What music do we play for Regret demo?
|
||||
musicproc->playMusic(18);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CruDemoGump::Close(bool no_del) {
|
||||
Mouse::get_instance()->popMouseCursor();
|
||||
|
||||
ModalGump::Close(no_del);
|
||||
|
||||
// Just let it play out?
|
||||
//MusicProcess *musicproc = MusicProcess::get_instance();
|
||||
//if (musicproc) musicproc->restoreMusic();
|
||||
}
|
||||
|
||||
void CruDemoGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
Common::Rect srcRect(640, 480);
|
||||
surf->Blit(*_background->getRawSurface(), srcRect, 0, 0);
|
||||
}
|
||||
|
||||
bool CruDemoGump::OnKeyDown(int key, int mod) {
|
||||
if (key == Common::KEYCODE_ESCAPE)
|
||||
Close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
61
engines/ultima/ultima8/gumps/cru_demo_gump.h
Normal file
61
engines/ultima/ultima8/gumps/cru_demo_gump.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_CRUDEMOGUMP_H
|
||||
#define ULTIMA8_GUMPS_CRUDEMOGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/modal_gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/**
|
||||
* Full-screen gump for showing the "buy me" screen
|
||||
*/
|
||||
class CruDemoGump : public ModalGump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
CruDemoGump();
|
||||
CruDemoGump(Common::SeekableReadStream *bmprs,
|
||||
uint32 flags = FLAG_PREVENT_SAVE, int32 layer = LAYER_MODAL);
|
||||
~CruDemoGump() override;
|
||||
|
||||
// Init the gump, call after construction
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
|
||||
void Close(bool no_del = false) override;
|
||||
|
||||
// Paint the Gump
|
||||
void PaintThis(RenderSurface *, int32 lerp_factor, bool scaled) override;
|
||||
|
||||
bool OnKeyDown(int key, int mod) override;
|
||||
|
||||
protected:
|
||||
//! The background picture
|
||||
RenderSurface *_background;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
88
engines/ultima/ultima8/gumps/cru_energy_gump.cpp
Normal file
88
engines/ultima/ultima8/gumps/cru_energy_gump.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/cru_energy_gump.h"
|
||||
|
||||
#include "ultima/ultima8/world/actors/main_actor.h"
|
||||
#include "ultima/ultima8/gfx/palette.h"
|
||||
#include "ultima/ultima8/gfx/palette_manager.h"
|
||||
#include "ultima/ultima8/gfx/render_surface.h"
|
||||
#include "ultima/ultima8/gfx/texture.h"
|
||||
#include "ultima/ultima8/world/get_object.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
static const uint ENERGY_BAR_COLOR = 245;
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(CruEnergyGump)
|
||||
|
||||
CruEnergyGump::CruEnergyGump() : CruStatGump() {
|
||||
|
||||
}
|
||||
|
||||
CruEnergyGump::CruEnergyGump(Shape *shape, int x)
|
||||
: CruStatGump(shape, x) {
|
||||
_frameNum = 3;
|
||||
}
|
||||
|
||||
CruEnergyGump::~CruEnergyGump() {
|
||||
}
|
||||
|
||||
void CruEnergyGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
CruStatGump::InitGump(newparent, take_focus);
|
||||
}
|
||||
|
||||
void CruEnergyGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
const Actor *a = getControlledActor();
|
||||
if (!a) {
|
||||
// avatar gone??
|
||||
return;
|
||||
}
|
||||
|
||||
int16 energy = a->getMana();
|
||||
int16 max_energy = a->getMaxMana();
|
||||
|
||||
// Don't display for NPCs without energy
|
||||
if (!max_energy)
|
||||
return;
|
||||
|
||||
CruStatGump::PaintThis(surf, lerp_factor, scaled);
|
||||
|
||||
int width = (energy * 67) / max_energy;
|
||||
const Palette *gamepal = PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game);
|
||||
if (!gamepal)
|
||||
return;
|
||||
|
||||
Common::Rect32 rect(34, 7, 34 + width, 21);
|
||||
surf->fillRect(rect, gamepal->_native[ENERGY_BAR_COLOR]);
|
||||
}
|
||||
|
||||
void CruEnergyGump::saveData(Common::WriteStream *ws) {
|
||||
CruStatGump::saveData(ws);
|
||||
}
|
||||
|
||||
bool CruEnergyGump::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
return CruStatGump::loadData(rs, version);
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
55
engines/ultima/ultima8/gumps/cru_energy_gump.h
Normal file
55
engines/ultima/ultima8/gumps/cru_energy_gump.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_CRUENERGYGUMP_H
|
||||
#define ULTIMA8_GUMPS_CRUENERGYGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/cru_stat_gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/**
|
||||
* Energy meter, the right-most box along the bottom of the screen.
|
||||
*/
|
||||
class CruEnergyGump : public CruStatGump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
CruEnergyGump();
|
||||
CruEnergyGump(Shape *shape, int x);
|
||||
~CruEnergyGump() override;
|
||||
|
||||
// Init the gump, call after construction
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
|
||||
// Paint this Gump
|
||||
void PaintThis(RenderSurface *, int32 lerp_factor, bool scaled) override;
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
80
engines/ultima/ultima8/gumps/cru_health_gump.cpp
Normal file
80
engines/ultima/ultima8/gumps/cru_health_gump.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/cru_health_gump.h"
|
||||
|
||||
#include "ultima/ultima8/world/actors/main_actor.h"
|
||||
#include "ultima/ultima8/gfx/palette.h"
|
||||
#include "ultima/ultima8/gfx/palette_manager.h"
|
||||
#include "ultima/ultima8/gfx/render_surface.h"
|
||||
#include "ultima/ultima8/gfx/texture.h"
|
||||
#include "ultima/ultima8/world/get_object.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
static const uint HEALTH_BAR_COLOR = 65;
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(CruHealthGump)
|
||||
|
||||
CruHealthGump::CruHealthGump() : CruStatGump() {
|
||||
|
||||
}
|
||||
|
||||
CruHealthGump::CruHealthGump(Shape *shape, int x)
|
||||
: CruStatGump(shape, x) {
|
||||
_frameNum = 2;
|
||||
}
|
||||
|
||||
CruHealthGump::~CruHealthGump() {
|
||||
}
|
||||
|
||||
void CruHealthGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
CruStatGump::InitGump(newparent, take_focus);
|
||||
}
|
||||
|
||||
void CruHealthGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
CruStatGump::PaintThis(surf, lerp_factor, scaled);
|
||||
|
||||
const Actor *a = getControlledActor();
|
||||
int current_hp = a ? a->getHP() : 0;
|
||||
int max_hp = a ? a->getMaxHP() : 1;
|
||||
// max width = 67
|
||||
int width = max_hp ? ((current_hp * 67) / max_hp) : 67;
|
||||
|
||||
const Palette *gamepal = PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game);
|
||||
if (!gamepal)
|
||||
return;
|
||||
|
||||
Common::Rect32 rect(34, 7, 34 + width, 21);
|
||||
surf->fillRect(rect, gamepal->_native[HEALTH_BAR_COLOR]);
|
||||
}
|
||||
|
||||
void CruHealthGump::saveData(Common::WriteStream *ws) {
|
||||
CruStatGump::saveData(ws);
|
||||
}
|
||||
|
||||
bool CruHealthGump::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
return CruStatGump::loadData(rs, version);
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
55
engines/ultima/ultima8/gumps/cru_health_gump.h
Normal file
55
engines/ultima/ultima8/gumps/cru_health_gump.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_CRUHEALTHGUMP_H
|
||||
#define ULTIMA8_GUMPS_CRUHEALTHGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/cru_stat_gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/**
|
||||
* Health bar, the 4th box along the bottom of the screen
|
||||
*/
|
||||
class CruHealthGump : public CruStatGump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
CruHealthGump();
|
||||
CruHealthGump(Shape *shape, int x);
|
||||
~CruHealthGump() override;
|
||||
|
||||
// Init the gump, call after construction
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
|
||||
// Paint this Gump
|
||||
void PaintThis(RenderSurface *, int32 lerp_factor, bool scaled) override;
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
139
engines/ultima/ultima8/gumps/cru_inventory_gump.cpp
Normal file
139
engines/ultima/ultima8/gumps/cru_inventory_gump.cpp
Normal file
@@ -0,0 +1,139 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/cru_inventory_gump.h"
|
||||
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/gfx/gump_shape_archive.h"
|
||||
#include "ultima/ultima8/gfx/shape.h"
|
||||
#include "ultima/ultima8/world/actors/main_actor.h"
|
||||
#include "ultima/ultima8/world/get_object.h"
|
||||
#include "ultima/ultima8/gumps/widgets/text_widget.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
static const int INVENTORY_TEXT_FONT = 12;
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(CruInventoryGump)
|
||||
CruInventoryGump::CruInventoryGump() : CruStatGump(), _inventoryItemGump(nullptr), _inventoryText(nullptr) {
|
||||
}
|
||||
|
||||
CruInventoryGump::CruInventoryGump(Shape *shape, int x)
|
||||
: CruStatGump(shape, x), _inventoryItemGump(nullptr), _inventoryText(nullptr) {
|
||||
_frameNum = 0;
|
||||
}
|
||||
|
||||
CruInventoryGump::~CruInventoryGump() {
|
||||
}
|
||||
|
||||
void CruInventoryGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
CruStatGump::InitGump(newparent, take_focus);
|
||||
|
||||
GumpShapeArchive *gumpshapes = GameData::get_instance()->getGumps();
|
||||
if (!gumpshapes) {
|
||||
warning("failed to init stat gump: no gump shape archive");
|
||||
return;
|
||||
}
|
||||
|
||||
_inventoryItemGump = new Gump();
|
||||
_inventoryItemGump->InitGump(this, false);
|
||||
// we'll set the shape for this gump later.
|
||||
|
||||
resetText();
|
||||
}
|
||||
|
||||
void CruInventoryGump::resetText() {
|
||||
if (_inventoryText) {
|
||||
RemoveChild(_inventoryText);
|
||||
_inventoryText->Close();
|
||||
}
|
||||
_inventoryText = new TextWidget();
|
||||
_inventoryText->InitGump(this, false);
|
||||
}
|
||||
|
||||
|
||||
void CruInventoryGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
const MainActor *a = getMainActor();
|
||||
if (!a) {
|
||||
// avatar gone??
|
||||
return;
|
||||
}
|
||||
|
||||
uint16 activeitem = a->getActiveInvItem();
|
||||
if (!activeitem || a != getControlledActor()) {
|
||||
resetText();
|
||||
_inventoryItemGump->SetShape(0, 0);
|
||||
} else {
|
||||
Item *item = getItem(activeitem);
|
||||
if (!item) {
|
||||
resetText();
|
||||
_inventoryItemGump->SetShape(0, 0);
|
||||
} else {
|
||||
GumpShapeArchive *gumpshapes = GameData::get_instance()->getGumps();
|
||||
if (!gumpshapes) {
|
||||
warning("failed to paint stat gump: no gump shape archive");
|
||||
return;
|
||||
}
|
||||
|
||||
const ShapeInfo *shapeinfo = item->getShapeInfo();
|
||||
if (!shapeinfo->_weaponInfo) {
|
||||
warning("no weapon info for active inventory item %d", item->getShape());
|
||||
return;
|
||||
}
|
||||
Shape *invshape = gumpshapes->getShape(shapeinfo->_weaponInfo->_displayGumpShape);
|
||||
_inventoryItemGump->SetShape(invshape, shapeinfo->_weaponInfo->_displayGumpFrame);
|
||||
_inventoryItemGump->UpdateDimsFromShape();
|
||||
_inventoryItemGump->setRelativePosition(CENTER);
|
||||
|
||||
uint16 q = item->getQuality();
|
||||
if (q > 1) {
|
||||
// This isn't the most efficient way to work out if we need to make new
|
||||
// text, but it works..
|
||||
const Std::string qtext = Std::string::format("%d", q);
|
||||
const Std::string ¤ttext = _inventoryText->getText();
|
||||
if (!qtext.equals(currenttext)) {
|
||||
RemoveChild(_inventoryText);
|
||||
_inventoryText->Close();
|
||||
_inventoryText = new TextWidget(_dims.width() / 2 + 22, _dims.height() / 2 + 3, qtext, true, INVENTORY_TEXT_FONT);
|
||||
_inventoryText->InitGump(this, false);
|
||||
}
|
||||
} else {
|
||||
if (!_inventoryText->getText().empty()) {
|
||||
resetText();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Now that the shape is configured, we can paint.
|
||||
CruStatGump::PaintThis(surf, lerp_factor, scaled);
|
||||
}
|
||||
}
|
||||
|
||||
void CruInventoryGump::saveData(Common::WriteStream *ws) {
|
||||
CruStatGump::saveData(ws);
|
||||
}
|
||||
|
||||
bool CruInventoryGump::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
return CruStatGump::loadData(rs, version);
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
63
engines/ultima/ultima8/gumps/cru_inventory_gump.h
Normal file
63
engines/ultima/ultima8/gumps/cru_inventory_gump.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_CRUINVENTORYGUMP_H
|
||||
#define ULTIMA8_GUMPS_CRUINVENTORYGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/cru_stat_gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class TextWidget;
|
||||
|
||||
/**
|
||||
* Inventory box, the 3rd box along the bottom of the screen
|
||||
*/
|
||||
class CruInventoryGump : public CruStatGump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
CruInventoryGump();
|
||||
CruInventoryGump(Shape *shape, int x);
|
||||
~CruInventoryGump() override;
|
||||
|
||||
// Init the gump, call after construction
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
|
||||
// Paint this Gump
|
||||
void PaintThis(RenderSurface *, int32 lerp_factor, bool scaled) override;
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
|
||||
private:
|
||||
Gump *_inventoryItemGump;
|
||||
TextWidget *_inventoryText;
|
||||
|
||||
void resetText();
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
238
engines/ultima/ultima8/gumps/cru_menu_gump.cpp
Normal file
238
engines/ultima/ultima8/gumps/cru_menu_gump.cpp
Normal file
@@ -0,0 +1,238 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/cru_menu_gump.h"
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/gfx/gump_shape_archive.h"
|
||||
#include "ultima/ultima8/gfx/shape.h"
|
||||
#include "ultima/ultima8/gfx/shape_frame.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
#include "ultima/ultima8/kernel/mouse.h"
|
||||
#include "ultima/ultima8/gumps/widgets/button_widget.h"
|
||||
#include "ultima/ultima8/gumps/quit_gump.h"
|
||||
#include "ultima/ultima8/gumps/difficulty_gump.h"
|
||||
#include "ultima/ultima8/games/cru_game.h"
|
||||
#include "ultima/ultima8/games/game.h"
|
||||
#include "ultima/ultima8/world/actors/main_actor.h"
|
||||
#include "ultima/ultima8/gfx/palette_manager.h"
|
||||
#include "ultima/ultima8/audio/music_process.h"
|
||||
#include "ultima/ultima8/world/get_object.h"
|
||||
#include "ultima/ultima8/metaengine.h"
|
||||
|
||||
#include "engines/dialogs.h"
|
||||
#include "gui/saveload.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(CruMenuGump)
|
||||
|
||||
static const int MENU_MUSIC_REMORSE = 20;
|
||||
static const int MENU_MUSIC_REGRET = 18;
|
||||
|
||||
CruMenuGump::CruMenuGump()
|
||||
: ModalGump(0, 0, 640, 480, 0, FLAG_DONT_SAVE) {
|
||||
|
||||
Mouse *mouse = Mouse::get_instance();
|
||||
mouse->pushMouseCursor(Mouse::MOUSE_HAND);
|
||||
|
||||
// Save old music state
|
||||
MusicProcess *musicprocess = MusicProcess::get_instance();
|
||||
if (musicprocess) {
|
||||
musicprocess->saveTrackState();
|
||||
|
||||
int track = GAME_IS_REMORSE ? MENU_MUSIC_REMORSE : MENU_MUSIC_REGRET;
|
||||
// Play the menu music
|
||||
musicprocess->playMusic(track);
|
||||
}
|
||||
}
|
||||
|
||||
CruMenuGump::~CruMenuGump() {
|
||||
}
|
||||
|
||||
void CruMenuGump::Close(bool no_del) {
|
||||
// Restore old music state and palette.
|
||||
// Music state can be changed by the Intro and Credits
|
||||
MusicProcess *musicprocess = MusicProcess::get_instance();
|
||||
if (musicprocess)
|
||||
musicprocess->restoreTrackState();
|
||||
|
||||
Mouse *mouse = Mouse::get_instance();
|
||||
mouse->popMouseCursor();
|
||||
|
||||
ModalGump::Close(no_del);
|
||||
}
|
||||
|
||||
static const int FRAME_TOP_LEFT = 54;
|
||||
static const int FIRST_MENU_ENTRY = 58;
|
||||
|
||||
static const int NUM_MENU_ENTRIES = 6;
|
||||
static const int MENU_ENTRY_X_REM[] = {45, 45, 45, 446, 488, 550};
|
||||
static const int MENU_ENTRY_Y_REM[] = {50, 101, 151, 58, 151, 198};
|
||||
static const int MENU_ENTRY_X_REG[] = {45, 45, 45, 446, 489, 550};
|
||||
static const int MENU_ENTRY_Y_REG[] = {95, 147, 197, 103, 196, 243};
|
||||
|
||||
void CruMenuGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
ModalGump::InitGump(newparent, take_focus);
|
||||
|
||||
GumpShapeArchive *shapeArchive = GameData::get_instance()->getGumps();
|
||||
|
||||
Shape *topLeft = shapeArchive->getShape(FRAME_TOP_LEFT);
|
||||
Shape *topRight = shapeArchive->getShape(FRAME_TOP_LEFT + 1);
|
||||
Shape *botLeft = shapeArchive->getShape(FRAME_TOP_LEFT + 2);
|
||||
Shape *botRight = shapeArchive->getShape(FRAME_TOP_LEFT + 3);
|
||||
|
||||
if (!topLeft || !topRight || !botLeft || !botRight) {
|
||||
error("Couldn't load shapes for menu background");
|
||||
return;
|
||||
}
|
||||
|
||||
PaletteManager *palman = PaletteManager::get_instance();
|
||||
assert(palman);
|
||||
const Palette *pal = palman->getPalette(PaletteManager::Pal_Misc);
|
||||
assert(pal);
|
||||
topLeft->setPalette(pal);
|
||||
topRight->setPalette(pal);
|
||||
botLeft->setPalette(pal);
|
||||
botRight->setPalette(pal);
|
||||
|
||||
const ShapeFrame *tlFrame = topLeft->getFrame(0);
|
||||
const ShapeFrame *trFrame = topRight->getFrame(0);
|
||||
const ShapeFrame *blFrame = botLeft->getFrame(0);
|
||||
const ShapeFrame *brFrame = botRight->getFrame(0);
|
||||
if (!tlFrame || !trFrame || !blFrame || !brFrame) {
|
||||
error("Couldn't load shape frames for menu background");
|
||||
return;
|
||||
}
|
||||
|
||||
_dims.left = 0;
|
||||
_dims.top = 0;
|
||||
_dims.setWidth(tlFrame->_width + trFrame->_width);
|
||||
_dims.setHeight(tlFrame->_height + brFrame->_height);
|
||||
|
||||
Gump *tlGump = new Gump(0, 0, tlFrame->_width, tlFrame->_height, 0, 0, _layer);
|
||||
tlGump->SetShape(topLeft, 0);
|
||||
tlGump->InitGump(this, false);
|
||||
Gump *trGump = new Gump(tlFrame->_width, 0, trFrame->_width, trFrame->_height, 0, 0, _layer);
|
||||
trGump->SetShape(topRight, 0);
|
||||
trGump->InitGump(this, false);
|
||||
Gump *blGump = new Gump(0, tlFrame->_height, blFrame->_width, blFrame->_height, 0, 0, _layer);
|
||||
blGump->SetShape(botLeft, 0);
|
||||
blGump->InitGump(this, false);
|
||||
Gump *brGump = new Gump(blFrame->_width, trFrame->_height, brFrame->_width, brFrame->_height, 0, 0, _layer);
|
||||
brGump->SetShape(botRight, 0);
|
||||
brGump->InitGump(this, false);
|
||||
|
||||
const int *MENU_ENTRY_X = GAME_IS_REMORSE ? MENU_ENTRY_X_REM : MENU_ENTRY_X_REG;
|
||||
const int *MENU_ENTRY_Y = GAME_IS_REMORSE ? MENU_ENTRY_Y_REM : MENU_ENTRY_Y_REG;
|
||||
|
||||
for (int i = 0; i < NUM_MENU_ENTRIES; i++) {
|
||||
uint32 entryShapeNum = FIRST_MENU_ENTRY + i;
|
||||
Shape *menuEntry = shapeArchive->getShape(entryShapeNum);
|
||||
if (!menuEntry) {
|
||||
error("Couldn't load shape for menu entry %d", i);
|
||||
return;
|
||||
}
|
||||
menuEntry->setPalette(pal);
|
||||
|
||||
const ShapeFrame *menuEntryFrame = menuEntry->getFrame(0);
|
||||
if (!menuEntryFrame || menuEntry->frameCount() != 2) {
|
||||
error("Couldn't load shape frame for menu entry %d", i);
|
||||
return;
|
||||
}
|
||||
|
||||
FrameID frame_up(GameData::GUMPS, entryShapeNum, 0);
|
||||
FrameID frame_down(GameData::GUMPS, entryShapeNum, 1);
|
||||
Gump *widget = new ButtonWidget(MENU_ENTRY_X[i], MENU_ENTRY_Y[i],
|
||||
frame_up, frame_down, true, _layer + 1);
|
||||
widget->InitGump(this, false);
|
||||
widget->SetIndex(i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void CruMenuGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
Gump::PaintThis(surf, lerp_factor, scaled);
|
||||
}
|
||||
|
||||
bool CruMenuGump::OnKeyDown(int key, int mod) {
|
||||
if (Gump::OnKeyDown(key, mod)) return true;
|
||||
|
||||
if (key == Common::KEYCODE_ESCAPE) {
|
||||
// FIXME: this check should probably be in Game or GUIApp
|
||||
MainActor *av = getMainActor();
|
||||
if (av && !av->hasActorFlags(Actor::ACT_DEAD))
|
||||
Close(); // don't allow closing if dead/game over
|
||||
} else if (key >= Common::KEYCODE_1 && key <= Common::KEYCODE_6) {
|
||||
selectEntry(key - Common::KEYCODE_1 + 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CruMenuGump::ChildNotify(Gump *child, uint32 message) {
|
||||
ButtonWidget *buttonWidget = dynamic_cast<ButtonWidget *>(child);
|
||||
if (buttonWidget && message == ButtonWidget::BUTTON_CLICK) {
|
||||
selectEntry(child->GetIndex());
|
||||
}
|
||||
}
|
||||
|
||||
void CruMenuGump::selectEntry(int entry) {
|
||||
switch (entry) {
|
||||
case 1: { // New Game
|
||||
Ultima8Engine::get_instance()->newGame(-1);
|
||||
// When starting a new game from the menu, we skip intro movies.
|
||||
CruGame *game = dynamic_cast<CruGame *>(Game::get_instance());
|
||||
assert(game);
|
||||
game->setSkipIntroMovie();
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
Ultima8Engine::get_instance()->loadGameDialog();
|
||||
break;
|
||||
case 3: // Load/Save Game
|
||||
Ultima8Engine::get_instance()->saveGameDialog();
|
||||
break;
|
||||
case 4: {
|
||||
// Options - show the ScummVM options dialog
|
||||
GUI::ConfigDialog dlg;
|
||||
dlg.runModal();
|
||||
}
|
||||
break;
|
||||
case 5: { // Credits
|
||||
CruGame *game = dynamic_cast<CruGame *>(Game::get_instance());
|
||||
assert(game);
|
||||
game->playCreditsNoMenu();
|
||||
break;
|
||||
}
|
||||
case 6: // Quit
|
||||
QuitGump::verifyQuit();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool CruMenuGump::OnTextInput(int unicode) {
|
||||
return Gump::OnTextInput(unicode);
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
60
engines/ultima/ultima8/gumps/cru_menu_gump.h
Normal file
60
engines/ultima/ultima8/gumps/cru_menu_gump.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_REMORSEMENUGUMP_H
|
||||
#define ULTIMA8_GUMPS_REMORSEMENUGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/modal_gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/**
|
||||
* The game menu for Crusader: No Remorse. Different enough to the U8 menu that it's implemented separately.
|
||||
*/
|
||||
class CruMenuGump : public ModalGump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
CruMenuGump();
|
||||
~CruMenuGump() override;
|
||||
|
||||
// Init the gump, call after construction
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
void Close(bool no_del = false) override;
|
||||
|
||||
// Paint the Gump
|
||||
void PaintThis(RenderSurface *, int32 lerp_factor, bool scaled) override;
|
||||
|
||||
bool OnKeyDown(int key, int mod) override;
|
||||
bool OnTextInput(int unicode) override;
|
||||
void ChildNotify(Gump *child, uint32 message) override;
|
||||
|
||||
protected:
|
||||
|
||||
virtual void selectEntry(int entry);
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
101
engines/ultima/ultima8/gumps/cru_pickup_area_gump.cpp
Normal file
101
engines/ultima/ultima8/gumps/cru_pickup_area_gump.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/cru_pickup_area_gump.h"
|
||||
#include "ultima/ultima8/gumps/cru_pickup_gump.h"
|
||||
|
||||
#include "ultima/ultima8/world/item.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
static const int PICKUP_GUMP_GAP = 5;
|
||||
static const int PICKUP_GUMP_HEIGHT = 30;
|
||||
|
||||
CruPickupAreaGump *CruPickupAreaGump::_instance = nullptr;
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(CruPickupAreaGump)
|
||||
|
||||
CruPickupAreaGump::CruPickupAreaGump() : Gump() { }
|
||||
|
||||
CruPickupAreaGump::CruPickupAreaGump(bool unused) : Gump(PICKUP_GUMP_GAP, PICKUP_GUMP_GAP, 200, 500, 0, 0, LAYER_ABOVE_NORMAL) {
|
||||
}
|
||||
|
||||
CruPickupAreaGump::~CruPickupAreaGump() {
|
||||
_instance = nullptr;
|
||||
}
|
||||
|
||||
void CruPickupAreaGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
Gump::InitGump(newparent, take_focus);
|
||||
assert(!_instance || _instance == this);
|
||||
_instance = this;
|
||||
}
|
||||
|
||||
void CruPickupAreaGump::addPickup(const Item *item, bool showCount) {
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
uint32 shapeno = item->getShape();
|
||||
|
||||
// Find the location to draw the gump for the new item,
|
||||
// or an existing gump to recycle if we have one already
|
||||
// for that shape
|
||||
int32 maxy = PICKUP_GUMP_GAP;
|
||||
for (auto *i : _children) {
|
||||
CruPickupGump *pug = dynamic_cast<CruPickupGump *>(i);
|
||||
if (!pug)
|
||||
continue;
|
||||
if (pug->getShapeNo() == shapeno) {
|
||||
// Already a notification for this object, update it
|
||||
pug->updateForNewItem(item);
|
||||
return;
|
||||
}
|
||||
int32 x, y;
|
||||
pug->getLocation(x, y);
|
||||
maxy = MAX(maxy, y + PICKUP_GUMP_GAP + PICKUP_GUMP_HEIGHT);
|
||||
}
|
||||
|
||||
// didn't find one, create a new one at the bottom.
|
||||
Gump *newgump = new CruPickupGump(item, maxy, showCount);
|
||||
newgump->InitGump(this, false);
|
||||
}
|
||||
|
||||
void CruPickupAreaGump::saveData(Common::WriteStream *ws) {
|
||||
Gump::saveData(ws);
|
||||
}
|
||||
|
||||
bool CruPickupAreaGump::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
if (!Gump::loadData(rs, version))
|
||||
return false;
|
||||
|
||||
if (_instance && _instance != this)
|
||||
delete _instance;
|
||||
_instance = this;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
CruPickupAreaGump *CruPickupAreaGump::get_instance() {
|
||||
return _instance;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
63
engines/ultima/ultima8/gumps/cru_pickup_area_gump.h
Normal file
63
engines/ultima/ultima8/gumps/cru_pickup_area_gump.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_CRUPICKUPAREAGUMP_H
|
||||
#define ULTIMA8_GUMPS_CRUPICKUPAREAGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class TextWidget;
|
||||
|
||||
/**
|
||||
* The area that manages all the "pickup" gumps (the notifications that a new
|
||||
* item has been picked up)
|
||||
*/
|
||||
class CruPickupAreaGump : public Gump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
// default constructor only for use when loading savegame
|
||||
CruPickupAreaGump();
|
||||
|
||||
// Normal constructor
|
||||
CruPickupAreaGump(bool unused);
|
||||
~CruPickupAreaGump();
|
||||
|
||||
void InitGump(Gump *newparent, bool take_focus = false) override;
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
|
||||
void addPickup(const Item *item, bool showCount);
|
||||
|
||||
static CruPickupAreaGump *get_instance();
|
||||
private:
|
||||
static CruPickupAreaGump *_instance;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
176
engines/ultima/ultima8/gumps/cru_pickup_gump.cpp
Normal file
176
engines/ultima/ultima8/gumps/cru_pickup_gump.cpp
Normal file
@@ -0,0 +1,176 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/cru_pickup_gump.h"
|
||||
|
||||
#include "ultima/ultima8/gumps/translucent_gump.h"
|
||||
#include "ultima/ultima8/kernel/kernel.h"
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/gfx/gump_shape_archive.h"
|
||||
#include "ultima/ultima8/gfx/shape.h"
|
||||
#include "ultima/ultima8/gfx/shape_frame.h"
|
||||
#include "ultima/ultima8/world/actors/main_actor.h"
|
||||
#include "ultima/ultima8/gumps/widgets/text_widget.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
static const int PICKUP_GUMP_SHAPE = 2;
|
||||
static const int COUNT_TEXT_FONT = 12;
|
||||
static const int ITEM_TEXT_FONT = 13;
|
||||
static const int ITEM_AREA_WIDTH = 60;
|
||||
|
||||
// A high "random" index so we can always find this..
|
||||
static const int COUNT_TEXT_INDEX = 0x100;
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(CruPickupGump)
|
||||
CruPickupGump::CruPickupGump() : Gump(), _startFrame(0), _itemShapeNo(0), _q(0),
|
||||
_gumpShapeNo(0), _gumpFrameNo(0), _showCount(false) {
|
||||
}
|
||||
|
||||
CruPickupGump::CruPickupGump(const Item *item, int y, bool showCount) : Gump(0, y, 5, 5, 0),
|
||||
_startFrame(0), _showCount(showCount) {
|
||||
const WeaponInfo *weaponInfo = item->getShapeInfo()->_weaponInfo;
|
||||
if (weaponInfo) {
|
||||
_itemShapeNo = item->getShape();
|
||||
if (item->getShapeInfo()->_family == ShapeInfo::SF_CRUAMMO)
|
||||
_q = 1;
|
||||
else
|
||||
_q = item->getQuality();
|
||||
_itemName = weaponInfo->_name;
|
||||
_gumpShapeNo = weaponInfo->_displayGumpShape;
|
||||
_gumpFrameNo = weaponInfo->_displayGumpFrame;
|
||||
// Special case for keycard - display depends on the card type
|
||||
if (_itemShapeNo == 0x111)
|
||||
_gumpFrameNo += item->getFrame();
|
||||
} else {
|
||||
_itemShapeNo = 0;
|
||||
_q = 0;
|
||||
_gumpShapeNo = 0;
|
||||
_gumpFrameNo = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CruPickupGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
Gump::InitGump(newparent, take_focus);
|
||||
|
||||
if (!_itemShapeNo)
|
||||
return;
|
||||
|
||||
_startFrame = Kernel::get_instance()->getFrameNum();
|
||||
|
||||
// Get the shapes we will need..
|
||||
GumpShapeArchive *gumpshapes = GameData::get_instance()->getGumps();
|
||||
if (!gumpshapes) {
|
||||
warning("failed to init stat gump: no gump shape archive");
|
||||
return;
|
||||
}
|
||||
|
||||
const Shape *background = gumpshapes->getShape(PICKUP_GUMP_SHAPE);
|
||||
if (!background || !background->getFrame(0)) {
|
||||
warning("failed to init stat gump: no pickup background shape");
|
||||
return;
|
||||
}
|
||||
const ShapeFrame *bgframe = background->getFrame(0);
|
||||
|
||||
Shape* itemshape = gumpshapes->getShape(_gumpShapeNo);
|
||||
if (!itemshape || !itemshape->getFrame(_gumpFrameNo)) {
|
||||
warning("failed to init stat gump: no item shape");
|
||||
return;
|
||||
}
|
||||
|
||||
// Paint a semi-transparent background
|
||||
const FrameID bfgrameid(GameData::GUMPS, PICKUP_GUMP_SHAPE, 0);
|
||||
// TODO: The game uses a variable number of these depending on the text length
|
||||
// For now 5 is ok.
|
||||
for (int i = 0; i < 5; i++) {
|
||||
Gump *gump = new TranslucentGump(i * bgframe->_width, 0, bgframe->_width, bgframe->_height);
|
||||
gump->SetShape(bfgrameid, false);
|
||||
gump->InitGump(this, false);
|
||||
}
|
||||
_dims.setWidth(bgframe->_width * 5);
|
||||
_dims.setHeight(bgframe->_height);
|
||||
|
||||
// Paint the item name text
|
||||
TextWidget *text = new TextWidget(ITEM_AREA_WIDTH, bgframe->_height / 2 - 5, _itemName, true, ITEM_TEXT_FONT);
|
||||
text->InitGump(this, false);
|
||||
|
||||
// Paint the count if needed
|
||||
addCountText();
|
||||
|
||||
// Paint the item in the mid-left item area.
|
||||
const ShapeFrame *itemframe = itemshape->getFrame(_gumpFrameNo);
|
||||
Gump *itemgump = new Gump(0, _dims.height() / 2 - itemframe->_height / 2, itemframe->_width, itemframe->_height, 0, 0, LAYER_ABOVE_NORMAL);
|
||||
itemgump->SetShape(itemshape, _gumpFrameNo);
|
||||
itemgump->InitGump(this, false);
|
||||
itemgump->UpdateDimsFromShape();
|
||||
itemgump->Move(ITEM_AREA_WIDTH / 2 - itemframe->_width / 2, _dims.height() / 2 - itemframe->_height / 2);
|
||||
}
|
||||
|
||||
void CruPickupGump::updateForNewItem(const Item *item) {
|
||||
assert(item);
|
||||
assert(item->getShape() == _itemShapeNo);
|
||||
TextWidget *oldtext = dynamic_cast<TextWidget *>(FindGump(&FindByIndex<COUNT_TEXT_INDEX>));
|
||||
if (oldtext) {
|
||||
RemoveChild(oldtext);
|
||||
oldtext->Close();
|
||||
}
|
||||
|
||||
// Always show count for repeat objects.
|
||||
_showCount = true;
|
||||
|
||||
// If we're updating the existing count, add 1 or special-case credits
|
||||
if (_itemShapeNo == 0x4ed)
|
||||
_q += item->getQuality();
|
||||
else
|
||||
_q++;
|
||||
|
||||
addCountText();
|
||||
}
|
||||
|
||||
void CruPickupGump::addCountText() {
|
||||
if (_q <= 1 || !_showCount)
|
||||
return;
|
||||
Std::string qstr = Std::string::format("%d", _q);
|
||||
TextWidget *count = new TextWidget(ITEM_AREA_WIDTH / 2 + 22, _dims.height() / 2 + 3, qstr, true, COUNT_TEXT_FONT);
|
||||
count->InitGump(this, false);
|
||||
count->SetIndex(COUNT_TEXT_INDEX);
|
||||
}
|
||||
|
||||
|
||||
void CruPickupGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
uint32 frameno = Kernel::get_instance()->getFrameNum();
|
||||
if (!_itemShapeNo || frameno - _startFrame > 90) {
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void CruPickupGump::saveData(Common::WriteStream *ws) {
|
||||
Gump::saveData(ws);
|
||||
}
|
||||
|
||||
bool CruPickupGump::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
return Gump::loadData(rs, version);
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
80
engines/ultima/ultima8/gumps/cru_pickup_gump.h
Normal file
80
engines/ultima/ultima8/gumps/cru_pickup_gump.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_CRUPICKUPGUMP_H
|
||||
#define ULTIMA8_GUMPS_CRUPICKUPGUMP_H
|
||||
|
||||
#include "ultima/shared/std/string.h"
|
||||
#include "ultima/ultima8/gumps/gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class TextWidget;
|
||||
|
||||
/**
|
||||
* Pickup box, the box that appears in the top left when a new item is picked up
|
||||
*/
|
||||
class CruPickupGump : public Gump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
CruPickupGump();
|
||||
CruPickupGump(const Item *item, int y, bool showCount);
|
||||
|
||||
~CruPickupGump() override {};
|
||||
|
||||
// Init the gump, call after construction
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
|
||||
// Paint this Gump
|
||||
void PaintThis(RenderSurface *, int32 lerp_factor, bool scaled) override;
|
||||
|
||||
uint32 getShapeNo() const {
|
||||
return _itemShapeNo;
|
||||
}
|
||||
|
||||
uint16 getQ() {
|
||||
return _q;
|
||||
}
|
||||
|
||||
//! Update for a second item pickup - updates existing count text.
|
||||
void updateForNewItem(const Item *item);
|
||||
void addCountText();
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
|
||||
private:
|
||||
uint32 _startFrame;
|
||||
uint32 _itemShapeNo;
|
||||
uint16 _gumpShapeNo;
|
||||
uint16 _gumpFrameNo;
|
||||
Std::string _itemName;
|
||||
uint16 _q;
|
||||
bool _showCount;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
57
engines/ultima/ultima8/gumps/cru_stat_gump.cpp
Normal file
57
engines/ultima/ultima8/gumps/cru_stat_gump.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/cru_stat_gump.h"
|
||||
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(CruStatGump)
|
||||
|
||||
CruStatGump::CruStatGump() : TranslucentGump() {
|
||||
|
||||
}
|
||||
|
||||
CruStatGump::CruStatGump(Shape *shape, int x)
|
||||
: TranslucentGump(x, 0, 5, 5, 0, FLAG_DONT_SAVE) {
|
||||
_shape = shape;
|
||||
}
|
||||
|
||||
CruStatGump::~CruStatGump() {
|
||||
}
|
||||
|
||||
void CruStatGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
TranslucentGump::InitGump(newparent, take_focus);
|
||||
|
||||
UpdateDimsFromShape();
|
||||
}
|
||||
|
||||
void CruStatGump::saveData(Common::WriteStream *ws) {
|
||||
TranslucentGump::saveData(ws);
|
||||
}
|
||||
|
||||
bool CruStatGump::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
return TranslucentGump::loadData(rs, version);
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
52
engines/ultima/ultima8/gumps/cru_stat_gump.h
Normal file
52
engines/ultima/ultima8/gumps/cru_stat_gump.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_CRUSTATGUMP_H
|
||||
#define ULTIMA8_GUMPS_CRUSTATGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/translucent_gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/**
|
||||
* Superclass for the 5 status boxes along the bottom of the screen
|
||||
*/
|
||||
class CruStatGump : public TranslucentGump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
CruStatGump();
|
||||
CruStatGump(Shape *shape, int x);
|
||||
~CruStatGump() override;
|
||||
|
||||
// Init the gump, call after construction
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
147
engines/ultima/ultima8/gumps/cru_status_gump.cpp
Normal file
147
engines/ultima/ultima8/gumps/cru_status_gump.cpp
Normal file
@@ -0,0 +1,147 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/cru_status_gump.h"
|
||||
#include "ultima/ultima8/gumps/cru_weapon_gump.h"
|
||||
#include "ultima/ultima8/gumps/cru_ammo_gump.h"
|
||||
#include "ultima/ultima8/gumps/cru_inventory_gump.h"
|
||||
#include "ultima/ultima8/gumps/cru_health_gump.h"
|
||||
#include "ultima/ultima8/gumps/cru_energy_gump.h"
|
||||
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/gfx/gump_shape_archive.h"
|
||||
#include "ultima/ultima8/gfx/shape.h"
|
||||
#include "ultima/ultima8/gfx/shape_frame.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(CruStatusGump)
|
||||
|
||||
static const int PX_FROM_BOTTOM = 2; //! gap (y) between bottom of screen and bottom of a single item
|
||||
static const int PX_FROM_LEFT = 15; //! gap (x) from left of screen to weapon box
|
||||
static const int PX_GAP = 17; //! gap (x) between boxes in status bar
|
||||
|
||||
static const int FRAME_GUMP_SHAPE = 1;
|
||||
|
||||
CruStatusGump *CruStatusGump::_instance = nullptr;
|
||||
|
||||
CruStatusGump::CruStatusGump() : Gump() { }
|
||||
|
||||
// Start with an approximate width/height which we will adjust later..
|
||||
CruStatusGump::CruStatusGump(bool unused) : Gump(PX_FROM_LEFT, PX_FROM_BOTTOM, 500, 100, 0, 0, LAYER_ABOVE_NORMAL) {
|
||||
assert(!_instance);
|
||||
_instance = this;
|
||||
}
|
||||
|
||||
CruStatusGump::~CruStatusGump() {
|
||||
assert(!_instance || _instance == this);
|
||||
_instance = nullptr;
|
||||
}
|
||||
|
||||
void CruStatusGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
Gump::InitGump(newparent, take_focus);
|
||||
|
||||
createStatusItems();
|
||||
}
|
||||
|
||||
void CruStatusGump::createStatusItems() {
|
||||
assert(_children.size() == 0);
|
||||
GumpShapeArchive *gumpshapes = GameData::get_instance()->getGumps();
|
||||
if (!gumpshapes) {
|
||||
warning("failed to init stats gump: no gump shape archive");
|
||||
return;
|
||||
}
|
||||
|
||||
Shape *frameShape = gumpshapes->getShape(FRAME_GUMP_SHAPE);
|
||||
if (!frameShape || !frameShape->getFrame(0)) {
|
||||
warning("failed to init stats gump: no gump frame");
|
||||
return;
|
||||
}
|
||||
|
||||
int w = frameShape->getFrame(0)->_width;
|
||||
int h = frameShape->getFrame(0)->_height;
|
||||
|
||||
int xoff = 0;
|
||||
Gump *weaponGump = new CruWeaponGump(frameShape, xoff);
|
||||
weaponGump->InitGump(this);
|
||||
Gump *ammoGump = new CruAmmoGump(frameShape, xoff + w + PX_GAP);
|
||||
ammoGump->InitGump(this);
|
||||
Gump *inventoryGump = new CruInventoryGump(frameShape, xoff + (w + PX_GAP) * 2);
|
||||
inventoryGump->InitGump(this);
|
||||
Gump *health = new CruHealthGump(frameShape, xoff + (w + PX_GAP) * 3);
|
||||
health->InitGump(this);
|
||||
Gump *energyGump = new CruEnergyGump(frameShape, xoff + (w + PX_GAP) * 4);
|
||||
energyGump->InitGump(this);
|
||||
|
||||
_dims.setWidth(w * 5 + PX_GAP * 4);
|
||||
_dims.setHeight(h);
|
||||
setRelativePosition(BOTTOM_LEFT, PX_FROM_LEFT, -PX_FROM_BOTTOM);
|
||||
}
|
||||
|
||||
void CruStatusGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
if (_children.empty()) {
|
||||
// children deliberately aren't saved, recreate them if needed.
|
||||
createStatusItems();
|
||||
}
|
||||
Gump::PaintThis(surf, lerp_factor, scaled);
|
||||
|
||||
// All the painting logic is in the children.
|
||||
}
|
||||
|
||||
void CruStatusGump::saveData(Common::WriteStream *ws) {
|
||||
Gump::saveData(ws);
|
||||
}
|
||||
|
||||
bool CruStatusGump::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
if (!Gump::loadData(rs, version))
|
||||
return false;
|
||||
|
||||
if (_instance && _instance != this)
|
||||
delete _instance;
|
||||
|
||||
_instance = this;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 CruStatusGump::I_hideStatusGump(const uint8 * /*args*/,
|
||||
unsigned int /*argsize*/) {
|
||||
CruStatusGump *instance = get_instance();
|
||||
if (instance) {
|
||||
instance->Close();
|
||||
_instance = nullptr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 CruStatusGump::I_showStatusGump(const uint8 * /*args*/,
|
||||
unsigned int /*argsize*/) {
|
||||
CruStatusGump *instance = get_instance();
|
||||
if (!instance) {
|
||||
instance = new CruStatusGump(true);
|
||||
instance->InitGump(nullptr, false);
|
||||
assert(_instance);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
73
engines/ultima/ultima8/gumps/cru_status_gump.h
Normal file
73
engines/ultima/ultima8/gumps/cru_status_gump.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_CRUSTATUSGUMP_H
|
||||
#define ULTIMA8_GUMPS_CRUSTATUSGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/gump.h"
|
||||
#include "ultima/ultima8/usecode/intrinsics.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/**
|
||||
* Represents the collection of status boxes along the bottom of the screen.
|
||||
* Each of the individual items is a class of CruStatGump.
|
||||
*/
|
||||
class CruStatusGump : public Gump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
// default constructor for save game loading
|
||||
CruStatusGump();
|
||||
|
||||
// need a parameter to differentiate the non-default constructor..
|
||||
CruStatusGump(bool unused);
|
||||
|
||||
~CruStatusGump() override;
|
||||
|
||||
// Init the gump, call after construction
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
|
||||
// Paint this Gump
|
||||
void PaintThis(RenderSurface *, int32 lerp_factor, bool scaled) override;
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
|
||||
void createStatusItems();
|
||||
|
||||
static CruStatusGump *get_instance() {
|
||||
return _instance;
|
||||
}
|
||||
|
||||
INTRINSIC(I_hideStatusGump);
|
||||
INTRINSIC(I_showStatusGump);
|
||||
|
||||
private:
|
||||
static CruStatusGump *_instance;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
120
engines/ultima/ultima8/gumps/cru_weapon_gump.cpp
Normal file
120
engines/ultima/ultima8/gumps/cru_weapon_gump.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/cru_weapon_gump.h"
|
||||
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/gfx/gump_shape_archive.h"
|
||||
#include "ultima/ultima8/gfx/shape.h"
|
||||
#include "ultima/ultima8/world/actors/main_actor.h"
|
||||
#include "ultima/ultima8/world/get_object.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
static const int WEAPON_GUMP_SHAPE = 3;
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(CruWeaponGump)
|
||||
|
||||
CruWeaponGump::CruWeaponGump() : CruStatGump(), _weaponShape(nullptr) {
|
||||
}
|
||||
|
||||
CruWeaponGump::CruWeaponGump(Shape *shape, int x)
|
||||
: CruStatGump(shape, x), _weaponShape(nullptr) {
|
||||
_frameNum = 0;
|
||||
|
||||
GumpShapeArchive *gumpshapes = GameData::get_instance()->getGumps();
|
||||
if (!gumpshapes) {
|
||||
warning("failed to init stat gump: no gump shape archive");
|
||||
return;
|
||||
}
|
||||
|
||||
_weaponShape = gumpshapes->getShape(WEAPON_GUMP_SHAPE);
|
||||
if (!_weaponShape || !_weaponShape->getFrame(0)) {
|
||||
warning("failed to init stat gump: no weapon shape");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CruWeaponGump::~CruWeaponGump() {
|
||||
}
|
||||
|
||||
void CruWeaponGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
CruStatGump::InitGump(newparent, take_focus);
|
||||
|
||||
// We will fill out the shape to paint for this later.
|
||||
Gump *weaponGump = new Gump();
|
||||
weaponGump->InitGump(this, false);
|
||||
weaponGump->SetIndex(1);
|
||||
}
|
||||
|
||||
void CruWeaponGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
const MainActor *a = getMainActor();
|
||||
if (!a) {
|
||||
// avatar gone??
|
||||
return;
|
||||
}
|
||||
|
||||
Gump *weaponGump = _children.front();
|
||||
|
||||
if (a != getControlledActor()) {
|
||||
// Only paint when controlling avatar
|
||||
weaponGump->HideGump();
|
||||
return;
|
||||
} else {
|
||||
weaponGump->UnhideGump();
|
||||
}
|
||||
|
||||
assert(weaponGump);
|
||||
uint16 active = a->getActiveWeapon();
|
||||
if (!active) {
|
||||
weaponGump->SetShape(0, 0);
|
||||
} else {
|
||||
Item *item = getItem(active);
|
||||
if (!item) {
|
||||
weaponGump->SetShape(0, 0);
|
||||
} else {
|
||||
const WeaponInfo *weaponinfo = item->getShapeInfo()->_weaponInfo;
|
||||
uint16 frameno = 0;
|
||||
if (weaponinfo) {
|
||||
// this should be a weapon, otherwise why are we here?
|
||||
assert(WEAPON_GUMP_SHAPE == weaponinfo->_displayGumpShape);
|
||||
frameno = weaponinfo->_displayGumpFrame;
|
||||
}
|
||||
weaponGump->SetShape(_weaponShape, frameno);
|
||||
weaponGump->UpdateDimsFromShape();
|
||||
weaponGump->setRelativePosition(CENTER);
|
||||
}
|
||||
}
|
||||
|
||||
CruStatGump::PaintThis(surf, lerp_factor, scaled);
|
||||
}
|
||||
|
||||
void CruWeaponGump::saveData(Common::WriteStream *ws) {
|
||||
CruStatGump::saveData(ws);
|
||||
}
|
||||
|
||||
bool CruWeaponGump::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
return CruStatGump::loadData(rs, version);
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
58
engines/ultima/ultima8/gumps/cru_weapon_gump.h
Normal file
58
engines/ultima/ultima8/gumps/cru_weapon_gump.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_CRUWEAPONGUMP_H
|
||||
#define ULTIMA8_GUMPS_CRUWEAPONGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/cru_stat_gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/**
|
||||
* Superclass for the 5 status boxes along the bottom of the screen
|
||||
*/
|
||||
class CruWeaponGump : public CruStatGump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
CruWeaponGump();
|
||||
CruWeaponGump(Shape *shape, int x);
|
||||
~CruWeaponGump() override;
|
||||
|
||||
// Init the gump, call after construction
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
|
||||
// Paint this Gump
|
||||
void PaintThis(RenderSurface *, int32 lerp_factor, bool scaled) override;
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
|
||||
private:
|
||||
Shape *_weaponShape;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
87
engines/ultima/ultima8/gumps/desktop_gump.cpp
Normal file
87
engines/ultima/ultima8/gumps/desktop_gump.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/desktop_gump.h"
|
||||
#include "ultima/ultima8/gfx/render_surface.h"
|
||||
#include "ultima/ultima8/gfx/texture.h"
|
||||
#include "ultima/ultima8/kernel/mouse.h"
|
||||
#include "ultima/ultima8/gumps/target_gump.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(DesktopGump)
|
||||
|
||||
bool DesktopGump::_fadedModal = true;
|
||||
|
||||
DesktopGump::DesktopGump()
|
||||
: Gump() {
|
||||
}
|
||||
|
||||
DesktopGump::DesktopGump(int32 x, int32 y, int32 width, int32 height) :
|
||||
Gump(x, y, width, height, 0, FLAG_DONT_SAVE | FLAG_CORE_GUMP,
|
||||
LAYER_DESKTOP) {
|
||||
}
|
||||
|
||||
DesktopGump::~DesktopGump(void) {
|
||||
}
|
||||
|
||||
void DesktopGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
}
|
||||
|
||||
void DesktopGump::PaintChildren(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
for (auto *g : _children) {
|
||||
// Paint if not closing
|
||||
if (!g->IsClosing()) {
|
||||
// If background blanking on modal is enabled...
|
||||
// Background is partially transparent
|
||||
if (_fadedModal && dynamic_cast<ModalGump *>(g) &&
|
||||
!dynamic_cast<TargetGump *>(g) && !g->IsHidden())
|
||||
surf->fillBlended(TEX32_PACK_RGBA(0, 0, 0, 0x80), _dims);
|
||||
|
||||
g->Paint(surf, lerp_factor, scaled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DesktopGump::RenderSurfaceChanged() {
|
||||
// Resize the desktop gump to match the parent
|
||||
if (_parent) {
|
||||
Common::Rect32 new_dims = _parent->getDims();
|
||||
_dims.setWidth(new_dims.width());
|
||||
_dims.setHeight(new_dims.height());
|
||||
}
|
||||
|
||||
Gump::RenderSurfaceChanged();
|
||||
}
|
||||
|
||||
void DesktopGump::saveData(Common::WriteStream *ws) {
|
||||
warning("Trying to save DesktopGump");
|
||||
}
|
||||
|
||||
bool DesktopGump::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
warning("Trying to load DesktopGump");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
59
engines/ultima/ultima8/gumps/desktop_gump.h
Normal file
59
engines/ultima/ultima8/gumps/desktop_gump.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_DESKTOPGUMP_H
|
||||
#define ULTIMA8_GUMPS_DESKTOPGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/**
|
||||
* A virtual gump which contains all the regular game components.
|
||||
*/
|
||||
class DesktopGump : public Gump {
|
||||
static bool _fadedModal;
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
DesktopGump();
|
||||
DesktopGump(int32 x, int32 y, int32 width, int32 height);
|
||||
~DesktopGump() override;
|
||||
|
||||
void RenderSurfaceChanged() override;
|
||||
|
||||
void PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) override;
|
||||
void PaintChildren(RenderSurface *surf, int32 lerp_factor, bool scaled) override;
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
|
||||
static void SetFadedModal(bool set) {
|
||||
_fadedModal = set;
|
||||
}
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
189
engines/ultima/ultima8/gumps/difficulty_gump.cpp
Normal file
189
engines/ultima/ultima8/gumps/difficulty_gump.cpp
Normal file
@@ -0,0 +1,189 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/difficulty_gump.h"
|
||||
#include "ultima/ultima8/gfx/render_surface.h"
|
||||
#include "ultima/ultima8/gfx/gump_shape_archive.h"
|
||||
#include "ultima/ultima8/gfx/palette_manager.h"
|
||||
#include "ultima/ultima8/gfx/texture.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/kernel/mouse.h"
|
||||
#include "ultima/ultima8/world/world.h"
|
||||
#include "ultima/ultima8/gfx/shape.h"
|
||||
#include "ultima/ultima8/gfx/shape_frame.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(DifficultyGump)
|
||||
|
||||
DifficultyGump::DifficultyGump()
|
||||
: ModalGump(0, 0, 5, 5), _highlighted(3), _buttonWidth(0),
|
||||
_buttonHeight(0) {
|
||||
}
|
||||
|
||||
DifficultyGump::~DifficultyGump() {
|
||||
}
|
||||
|
||||
static const int BUTTON_X = 158;
|
||||
static const int BUTTON_Y = 120;
|
||||
static const int BUTTON_SPACE = 17;
|
||||
static const int BUTTON_HEIGHT = 42;
|
||||
static const int RIGHT_FRAME_IDX_OFFSET = 16;
|
||||
|
||||
|
||||
// gumps: 73: "difficulty level"
|
||||
// 74-77: levels, 2 frames per level (left/right)
|
||||
|
||||
void DifficultyGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
ModalGump::InitGump(newparent, take_focus);
|
||||
|
||||
Mouse *mouse = Mouse::get_instance();
|
||||
mouse->pushMouseCursor(Mouse::MOUSE_HAND);
|
||||
|
||||
_dims.top = 0;
|
||||
_dims.left = 0;
|
||||
_dims.bottom = 480;
|
||||
_dims.right = 640;
|
||||
|
||||
GumpShapeArchive *shapeArchive = GameData::get_instance()->getGumps();
|
||||
|
||||
Shape *difficultyLevel = shapeArchive->getShape(73);
|
||||
|
||||
Shape *levelShape[4];
|
||||
for (int s = 74; s < 78; s++) {
|
||||
levelShape[s - 74] = shapeArchive->getShape(s);
|
||||
}
|
||||
|
||||
if (!difficultyLevel || !levelShape[0] || !levelShape[1] ||
|
||||
!levelShape[2] || !levelShape[3]) {
|
||||
error("Couldn't load shapes for difficulty level");
|
||||
return;
|
||||
}
|
||||
|
||||
PaletteManager *palman = PaletteManager::get_instance();
|
||||
assert(palman);
|
||||
const Palette *pal = palman->getPalette(PaletteManager::Pal_Diff);
|
||||
assert(pal);
|
||||
difficultyLevel->setPalette(pal);
|
||||
for (int s = 0; s < 4; s++) {
|
||||
levelShape[s]->setPalette(pal);
|
||||
}
|
||||
|
||||
const ShapeFrame *difficultyFrame = difficultyLevel->getFrame(0);
|
||||
if (!difficultyFrame) {
|
||||
error("Couldn't load shape frame for difficulty level");
|
||||
return;
|
||||
}
|
||||
Gump *diffGump = new Gump(185, 77, difficultyFrame->_width, difficultyFrame->_height);
|
||||
diffGump->SetShape(difficultyLevel, 0);
|
||||
diffGump->InitGump(this, false);
|
||||
|
||||
for (int s = 0; s < 4; s++) {
|
||||
const int y = BUTTON_Y + (BUTTON_SPACE + BUTTON_HEIGHT) * s;
|
||||
const ShapeFrame *leftFrame = levelShape[s]->getFrame(0);
|
||||
const ShapeFrame *rightFrame = levelShape[s]->getFrame(1);
|
||||
if (!leftFrame || !rightFrame) {
|
||||
error("Couldn't load shape frame for difficulty level %d", s);
|
||||
return;
|
||||
}
|
||||
Gump *lGump = new Gump(BUTTON_X, y, leftFrame->_width, leftFrame->_height);
|
||||
lGump->SetShape(levelShape[s], 0);
|
||||
lGump->InitGump(this, false);
|
||||
lGump->SetIndex(s + 1);
|
||||
Gump *rGump = new Gump(BUTTON_X + leftFrame->_width, y, rightFrame->_width, rightFrame->_height);
|
||||
rGump->SetShape(levelShape[s], 1);
|
||||
rGump->InitGump(this, false);
|
||||
rGump->SetIndex(s + 1 + RIGHT_FRAME_IDX_OFFSET);
|
||||
|
||||
_buttonHeight = MAX(_buttonHeight, leftFrame->_height);
|
||||
_buttonHeight = MAX(_buttonHeight, rightFrame->_height);
|
||||
_buttonWidth = MAX(_buttonWidth, static_cast<int16>(leftFrame->_width + rightFrame->_width));
|
||||
}
|
||||
|
||||
// remove focus from children (just in case)
|
||||
if (_focusChild) _focusChild->OnFocus(false);
|
||||
_focusChild = 0;
|
||||
}
|
||||
|
||||
void DifficultyGump::Close(bool no_del) {
|
||||
Mouse *mouse = Mouse::get_instance();
|
||||
mouse->popMouseCursor();
|
||||
ModalGump::Close(no_del);
|
||||
}
|
||||
|
||||
void DifficultyGump::OnFocus(bool gain) {
|
||||
}
|
||||
|
||||
void DifficultyGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
// Paint a highlight around the current level
|
||||
int highlihght_y = BUTTON_Y + ((_highlighted - 1) * (BUTTON_SPACE + BUTTON_HEIGHT));
|
||||
uint32 color = TEX32_PACK_RGB(0x80, 0x80, 0x80);
|
||||
surf->fill32(color, BUTTON_X - 1, highlihght_y - 1, _buttonWidth + 2, _buttonHeight + 2);
|
||||
ModalGump::PaintThis(surf, lerp_factor, scaled);
|
||||
}
|
||||
|
||||
void DifficultyGump::onMouseClick(int button, int32 mx, int32 my) {
|
||||
if (button == Mouse::BUTTON_LEFT) {
|
||||
Gump *gump = FindGump(mx, my);
|
||||
if (gump && gump->GetIndex() > 0) {
|
||||
int idx = gump->GetIndex();
|
||||
if (idx > RIGHT_FRAME_IDX_OFFSET)
|
||||
idx -= RIGHT_FRAME_IDX_OFFSET;
|
||||
selectEntry(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DifficultyGump::OnKeyDown(int key, int mod) {
|
||||
if (ModalGump::OnKeyDown(key, mod)) return true;
|
||||
|
||||
if (key == Common::KEYCODE_ESCAPE) {
|
||||
// Don't allow closing, we have to choose a difficulty.
|
||||
return true;
|
||||
} else if (key >= Common::KEYCODE_1 && key <= Common::KEYCODE_4) {
|
||||
selectEntry(key - Common::KEYCODE_1 + 1);
|
||||
} else if (key == Common::KEYCODE_UP) {
|
||||
_highlighted--;
|
||||
if (_highlighted < 1)
|
||||
_highlighted = 4;
|
||||
} else if (key == Common::KEYCODE_DOWN) {
|
||||
_highlighted++;
|
||||
if (_highlighted > 4)
|
||||
_highlighted = 1;
|
||||
} else if (key == Common::KEYCODE_RETURN) {
|
||||
selectEntry(_highlighted);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DifficultyGump::selectEntry(int num) {
|
||||
debug(6, "selected difficulty %d", num);
|
||||
World::get_instance()->setGameDifficulty(num);
|
||||
Close();
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
59
engines/ultima/ultima8/gumps/difficulty_gump.h
Normal file
59
engines/ultima/ultima8/gumps/difficulty_gump.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_DIFFICULTYGUMP_H
|
||||
#define ULTIMA8_GUMPS_DIFFICULTYGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/modal_gump.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/**
|
||||
* Difficulty selector menu for Crusader: No Remorse
|
||||
*/
|
||||
class DifficultyGump : public ModalGump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
DifficultyGump();
|
||||
~DifficultyGump() override;
|
||||
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
void Close(bool no_del = false) override;
|
||||
|
||||
void onMouseClick(int button, int32 mx, int32 my) override;
|
||||
bool OnKeyDown(int key, int mod) override;
|
||||
void OnFocus(bool gain) override;
|
||||
void PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) override;
|
||||
|
||||
private:
|
||||
int _highlighted;
|
||||
int16 _buttonWidth;
|
||||
int16 _buttonHeight;
|
||||
|
||||
void selectEntry(int num);
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
83
engines/ultima/ultima8/gumps/fast_area_vis_gump.cpp
Normal file
83
engines/ultima/ultima8/gumps/fast_area_vis_gump.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/fast_area_vis_gump.h"
|
||||
#include "ultima/ultima8/world/world.h"
|
||||
#include "ultima/ultima8/world/current_map.h"
|
||||
#include "ultima/ultima8/world/get_object.h"
|
||||
#include "ultima/ultima8/world/item.h"
|
||||
#include "ultima/ultima8/gfx/render_surface.h"
|
||||
#include "ultima/ultima8/gfx/texture.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(FastAreaVisGump)
|
||||
|
||||
FastAreaVisGump::FastAreaVisGump(void) : Gump(0, 0, MAP_NUM_CHUNKS + 2, MAP_NUM_CHUNKS + 2, 0, FLAG_DRAGGABLE | FLAG_DONT_SAVE, LAYER_NORMAL) {
|
||||
}
|
||||
|
||||
FastAreaVisGump::~FastAreaVisGump(void) {
|
||||
}
|
||||
|
||||
void FastAreaVisGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
World *world = World::get_instance();
|
||||
CurrentMap *currentmap = world->getCurrentMap();
|
||||
|
||||
uint32 color = TEX32_PACK_RGB(0xFF, 0, 0);
|
||||
surf->frameRect32(color, _dims);
|
||||
|
||||
color = TEX32_PACK_RGB(0, 0, 0);
|
||||
surf->fill32(color, 1, 1, MAP_NUM_CHUNKS, MAP_NUM_CHUNKS);
|
||||
|
||||
|
||||
color = TEX32_PACK_RGB(0xFF, 0xFF, 0xFF);
|
||||
for (int yp = 0; yp < MAP_NUM_CHUNKS; yp++)
|
||||
for (int xp = 0; xp < MAP_NUM_CHUNKS; xp++)
|
||||
if (currentmap->isChunkFast(xp, yp))
|
||||
surf->fill32(color, xp + 1, yp + 1, 1, 1);
|
||||
|
||||
// Put a red dot where the avatar is
|
||||
Item *avatar = getItem(1);
|
||||
if (avatar) {
|
||||
Point3 pt = avatar->getLocation();
|
||||
int chunksize = currentmap->getChunkSize();
|
||||
pt.x /= chunksize;
|
||||
pt.y /= chunksize;
|
||||
if (pt.x >= 0 && pt.x < MAP_NUM_CHUNKS && pt.y >= 0 && pt.y < MAP_NUM_CHUNKS) {
|
||||
color = TEX32_PACK_RGB(0xFF, 0x10, 0x10);
|
||||
surf->fill32(color, pt.x + 1, pt.y + 1, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16 FastAreaVisGump::TraceObjId(int32 mx, int32 my) {
|
||||
uint16 objId_ = Gump::TraceObjId(mx, my);
|
||||
|
||||
if (!objId_ || objId_ == 65535)
|
||||
if (PointOnGump(mx, my))
|
||||
objId_ = getObjId();
|
||||
|
||||
return objId_;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
49
engines/ultima/ultima8/gumps/fast_area_vis_gump.h
Normal file
49
engines/ultima/ultima8/gumps/fast_area_vis_gump.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_FASTAREAVISGUMP_H
|
||||
#define ULTIMA8_GUMPS_FASTAREAVISGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/**
|
||||
* A gump for debugging which shows all the things in the "fast" area (the area around the avatar
|
||||
* which is being calculated for pathfinding etc)
|
||||
*/
|
||||
class FastAreaVisGump : public Gump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
FastAreaVisGump();
|
||||
~FastAreaVisGump() override;
|
||||
|
||||
void PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) override;
|
||||
uint16 TraceObjId(int32 mx, int32 my) override;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
624
engines/ultima/ultima8/gumps/game_map_gump.cpp
Normal file
624
engines/ultima/ultima8/gumps/game_map_gump.cpp
Normal file
@@ -0,0 +1,624 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima.h"
|
||||
#include "ultima/ultima8/gumps/game_map_gump.h"
|
||||
#include "ultima/ultima8/gumps/gump_notify_process.h"
|
||||
#include "ultima/ultima8/gumps/slider_gump.h"
|
||||
#include "ultima/ultima8/kernel/kernel.h"
|
||||
#include "ultima/ultima8/misc/direction_util.h"
|
||||
#include "ultima/ultima8/world/world.h"
|
||||
#include "ultima/ultima8/world/current_map.h"
|
||||
#include "ultima/ultima8/world/actors/main_actor.h"
|
||||
#include "ultima/ultima8/world/item_factory.h"
|
||||
#include "ultima/ultima8/world/item_sorter.h"
|
||||
#include "ultima/ultima8/world/camera_process.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
#include "ultima/ultima8/world/get_object.h"
|
||||
#include "ultima/ultima8/world/actors/avatar_mover_process.h"
|
||||
#include "ultima/ultima8/world/actors/pathfinder_process.h"
|
||||
#include "ultima/ultima8/world/missile_tracker.h"
|
||||
#include "ultima/ultima8/world/split_item_process.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(GameMapGump)
|
||||
|
||||
bool GameMapGump::_highlightItems = false;
|
||||
bool GameMapGump::_showFootpads = false;
|
||||
int GameMapGump::_gridlines = 0;
|
||||
|
||||
GameMapGump::GameMapGump() :
|
||||
Gump(), _displayDragging(false), _displayList(0), _draggingShape(0),
|
||||
_draggingFrame(0), _draggingFlags(0) {
|
||||
_displayList = new ItemSorter(2048);
|
||||
}
|
||||
|
||||
GameMapGump::GameMapGump(int x, int y, int width, int height) :
|
||||
Gump(x, y, width, height, 0, FLAG_DONT_SAVE | FLAG_CORE_GUMP, LAYER_GAMEMAP),
|
||||
_displayList(0), _displayDragging(false), _draggingShape(0), _draggingFrame(0),
|
||||
_draggingFlags(0) {
|
||||
// Offset the gump. We want 0,0 to be the centre
|
||||
_dims.moveTo(-_dims.width() / 2, -_dims.height() / 2);
|
||||
|
||||
_displayList = new ItemSorter(2048);
|
||||
}
|
||||
|
||||
GameMapGump::~GameMapGump() {
|
||||
delete _displayList;
|
||||
}
|
||||
|
||||
Point3 GameMapGump::GetCameraLocation(int lerp_factor) {
|
||||
CameraProcess *camera = CameraProcess::GetCameraProcess();
|
||||
if (camera) {
|
||||
return camera->GetLerped(lerp_factor);
|
||||
}
|
||||
return CameraProcess::GetCameraLocation();
|
||||
}
|
||||
|
||||
void GameMapGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
World *world = World::get_instance();
|
||||
if (!world) return; // Is it possible the world doesn't exist?
|
||||
|
||||
CurrentMap *map = world->getCurrentMap();
|
||||
if (!map) return; // Is it possible the map doesn't exist?
|
||||
|
||||
|
||||
// Get the camera location
|
||||
Point3 loc = GetCameraLocation(lerp_factor);
|
||||
|
||||
CameraProcess *camera = CameraProcess::GetCameraProcess();
|
||||
|
||||
int zlimit = 1 << 16; // should be high enough
|
||||
|
||||
const Item *roof = nullptr;
|
||||
if (camera) {
|
||||
uint16 roofid = camera->findRoof(lerp_factor);
|
||||
roof = getItem(roofid);
|
||||
} else {
|
||||
const Actor *av = getMainActor();
|
||||
Box b = av->getWorldBox();
|
||||
PositionInfo info = map->getPositionInfo(b, b, 0, 1);
|
||||
roof = info.roof;
|
||||
}
|
||||
|
||||
if (roof) {
|
||||
zlimit = roof->getZ();
|
||||
}
|
||||
|
||||
Common::Rect32 clipWindow = surf->getClippingRect();
|
||||
_displayList->BeginDisplayList(clipWindow, loc);
|
||||
|
||||
uint32 gametick = Kernel::get_instance()->getFrameNum();
|
||||
|
||||
bool showEditorItems = Ultima8Engine::get_instance()->isShowEditorItems();
|
||||
|
||||
// Get all the required items
|
||||
for (int cy = 0; cy < MAP_NUM_CHUNKS; cy++) {
|
||||
for (int cx = 0; cx < MAP_NUM_CHUNKS; cx++) {
|
||||
// Not fast, ignore
|
||||
if (!map->isChunkFast(cx, cy)) continue;
|
||||
|
||||
const Std::list<Item *> *items = map->getItemList(cx, cy);
|
||||
|
||||
if (!items) continue;
|
||||
|
||||
Std::list<Item *>::const_iterator it = items->begin();
|
||||
Std::list<Item *>::const_iterator end = items->end();
|
||||
for (; it != end; ++it) {
|
||||
Item *item = *it;
|
||||
if (!item) continue;
|
||||
|
||||
item->setupLerp(gametick);
|
||||
item->doLerp(lerp_factor);
|
||||
|
||||
if (item->getZ() >= zlimit && !item->getShapeInfo()->is_draw())
|
||||
continue;
|
||||
if (!showEditorItems && item->getShapeInfo()->is_editor())
|
||||
continue;
|
||||
if (item->hasFlags(Item::FLG_INVISIBLE)) {
|
||||
// special case: invisible avatar _is_ drawn
|
||||
// HACK: unless EXT_TRANSPARENT is also set.
|
||||
// (Used for hiding the avatar when drawing a full area map)
|
||||
|
||||
if (item->getObjId() == kMainActorId) {
|
||||
if (item->hasExtFlags(Item::EXT_TRANSPARENT))
|
||||
continue;
|
||||
|
||||
_displayList->AddItem(item->getLerped(), item->getShape(), item->getFrame(),
|
||||
item->getFlags() & ~Item::FLG_INVISIBLE, item->getExtFlags() | Item::EXT_TRANSPARENT, 1);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
_displayList->AddItem(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dragging:
|
||||
|
||||
if (_displayDragging) {
|
||||
_displayList->AddItem(_draggingPos, _draggingShape, _draggingFrame,
|
||||
_draggingFlags, Item::EXT_TRANSPARENT);
|
||||
}
|
||||
|
||||
int gridlines = _gridlines;
|
||||
if (gridlines < 0) {
|
||||
gridlines = map->getChunkSize();
|
||||
}
|
||||
|
||||
_displayList->PaintDisplayList(surf, _highlightItems, _showFootpads, gridlines);
|
||||
}
|
||||
|
||||
// Trace a click, and return ObjId
|
||||
uint16 GameMapGump::TraceObjId(int32 mx, int32 my) {
|
||||
uint16 objId_ = Gump::TraceObjId(mx, my);
|
||||
if (objId_ && objId_ != 65535) return objId_;
|
||||
|
||||
ParentToGump(mx, my);
|
||||
return _displayList->Trace(mx, my, 0, _highlightItems);
|
||||
}
|
||||
|
||||
uint16 GameMapGump::TraceCoordinates(int mx, int my, Point3 &coords,
|
||||
int offsetx, int offsety, Item *item) {
|
||||
int32 dxd = 0, dyd = 0, dzd = 0;
|
||||
if (item)
|
||||
item->getFootpadWorld(dxd, dyd, dzd);
|
||||
|
||||
Point3 c = GetCameraLocation();
|
||||
|
||||
ItemSorter::HitFace face;
|
||||
ObjId trace = _displayList->Trace(mx, my, &face);
|
||||
|
||||
Item *hit = getItem(trace);
|
||||
if (!hit) // strange...
|
||||
return 0;
|
||||
|
||||
int32 hxd, hyd, hzd;
|
||||
Point3 h = hit->getLocation();
|
||||
hit->getFootpadWorld(hxd, hyd, hzd);
|
||||
|
||||
// adjust mx (if dragged item wasn't 'picked up' at its origin)
|
||||
mx -= offsetx;
|
||||
my -= offsety;
|
||||
|
||||
// mx = (coords.x - c.x - coords.y + c.y) / 4
|
||||
// my = (coords.x - c.x + coords.y - c.y) / 8 - coords.z + c.z
|
||||
|
||||
// the below expressions solve these two equations to two of the coords,
|
||||
// while fixing the other coord
|
||||
|
||||
switch (face) {
|
||||
case ItemSorter::Z_FACE:
|
||||
coords.x = 2 * mx + 4 * (my + h.z + hzd) + c.x - 4 * c.z;
|
||||
coords.y = -2 * mx + 4 * (my + h.z + hzd) + c.y - 4 * c.z;
|
||||
coords.z = h.z + hzd;
|
||||
break;
|
||||
case ItemSorter::X_FACE:
|
||||
coords.x = h.x + dxd;
|
||||
coords.y = -4 * mx + h.x + dxd - c.x + c.y;
|
||||
coords.z = -my + (h.x + dxd) / 4 - mx / 2 - c.x / 4 + c.z;
|
||||
break;
|
||||
case ItemSorter::Y_FACE:
|
||||
coords.x = 4 * mx + h.y + dyd + c.x - c.y;
|
||||
coords.y = h.y + dyd;
|
||||
coords.z = -my + mx / 2 + (h.y + dyd) / 4 - c.y / 4 + c.z;
|
||||
break;
|
||||
}
|
||||
|
||||
return trace;
|
||||
}
|
||||
|
||||
bool GameMapGump::GetLocationOfItem(uint16 itemid, int32 &gx, int32 &gy,
|
||||
int32 lerp_factor) {
|
||||
Item *item = getItem(itemid);
|
||||
if (!item)
|
||||
return false;
|
||||
|
||||
Container *root = item->getRootContainer();
|
||||
if (root)
|
||||
item = root;
|
||||
|
||||
if (item->hasFlags(Item::FLG_ETHEREAL))
|
||||
return false;
|
||||
|
||||
// Hacks be us. Force the item into the fast area
|
||||
item->setupLerp(Kernel::get_instance()->getFrameNum());
|
||||
item->doLerp(lerp_factor);
|
||||
Point3 i = item->getLerped();
|
||||
|
||||
// Get the camera's location
|
||||
Point3 c;
|
||||
CameraProcess *cam = CameraProcess::GetCameraProcess();
|
||||
if (cam)
|
||||
c = cam->GetLerped(lerp_factor, true);
|
||||
else
|
||||
c = CameraProcess::GetCameraLocation();
|
||||
|
||||
// Screenspace bounding box bottom x coord (RNB x coord)
|
||||
gx = (i.x - i.y) / 4;
|
||||
// Screenspace bounding box bottom extent (RNB y coord)
|
||||
gy = (i.x + i.y) / 8 - i.z;
|
||||
|
||||
// Screenspace bounding box bottom x coord (RNB x coord)
|
||||
gx -= (c.x - c.y) / 4;
|
||||
// Screenspace bounding box bottom extent (RNB y coord)
|
||||
gy -= (c.x + c.y) / 8 - c.z;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Gump *GameMapGump::onMouseDown(int button, int32 mx, int32 my) {
|
||||
int32 sx = mx, sy = my;
|
||||
ParentToGump(sx, sy);
|
||||
GumpToScreenSpace(sx, sy);
|
||||
|
||||
AvatarMoverProcess *amp = Ultima8Engine::get_instance()->getAvatarMoverProcess();
|
||||
if (button == Mouse::BUTTON_RIGHT || button == Mouse::BUTTON_LEFT) {
|
||||
amp->onMouseDown(button, sx, sy);
|
||||
}
|
||||
|
||||
if (button == Mouse::BUTTON_LEFT || button == Mouse::BUTTON_RIGHT ||
|
||||
button == Mouse::BUTTON_MIDDLE) {
|
||||
// we take all clicks
|
||||
return this;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void GameMapGump::onMouseUp(int button, int32 mx, int32 my) {
|
||||
AvatarMoverProcess *amp = Ultima8Engine::get_instance()->getAvatarMoverProcess();
|
||||
if (button == Mouse::BUTTON_RIGHT || button == Mouse::BUTTON_LEFT) {
|
||||
amp->onMouseUp(button);
|
||||
}
|
||||
}
|
||||
|
||||
void GameMapGump::onMouseClick(int button, int32 mx, int32 my) {
|
||||
MainActor *avatar = getMainActor();
|
||||
switch (button) {
|
||||
case Mouse::BUTTON_LEFT: {
|
||||
if (avatar->isInCombat()) break;
|
||||
|
||||
if (Mouse::get_instance()->isMouseDownEvent(Mouse::BUTTON_RIGHT)) break;
|
||||
|
||||
uint16 objID = TraceObjId(mx, my);
|
||||
Item *item = getItem(objID);
|
||||
if (item) {
|
||||
debugC(kDebugObject, "%s", item->dumpInfo().c_str());
|
||||
|
||||
if (Ultima8Engine::get_instance()->isAvatarInStasis()) {
|
||||
debugC(kDebugObject, "Can't look: avatarInStasis");
|
||||
} else {
|
||||
item->callUsecodeEvent_look();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Mouse::BUTTON_MIDDLE: {
|
||||
ParentToGump(mx, my);
|
||||
|
||||
Point3 coords;
|
||||
uint16 objID = TraceCoordinates(mx, my, coords);
|
||||
Item *item = getItem(objID);
|
||||
if (item) {
|
||||
debugC(kDebugObject, "%s", item->dumpInfo().c_str());
|
||||
|
||||
if (Ultima8Engine::get_instance()->isAvatarInStasis()) {
|
||||
debugC(kDebugObject, "Can't move: avatarInStasis");
|
||||
} else {
|
||||
Actor *avatarControlled = getControlledActor();
|
||||
PathfinderProcess *pfp = new PathfinderProcess(avatarControlled, coords);
|
||||
Kernel::get_instance()->killProcesses(avatarControlled->getObjId(), PathfinderProcess::PATHFINDER_PROC_TYPE, true);
|
||||
Kernel::get_instance()->addProcess(pfp);
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GameMapGump::onMouseDouble(int button, int32 mx, int32 my) {
|
||||
MainActor *avatar = getMainActor();
|
||||
switch (button) {
|
||||
case Mouse::BUTTON_LEFT: {
|
||||
if (avatar->isInCombat()) break;
|
||||
|
||||
if (Mouse::get_instance()->isMouseDownEvent(Mouse::BUTTON_RIGHT)) break;
|
||||
|
||||
uint16 objID = TraceObjId(mx, my);
|
||||
Item *item = getItem(objID);
|
||||
if (item) {
|
||||
debugC(kDebugObject, "%s", item->dumpInfo().c_str());
|
||||
|
||||
int range = 128; // CONSTANT!
|
||||
if (GAME_IS_CRUSADER) {
|
||||
range = 512;
|
||||
}
|
||||
|
||||
if (Ultima8Engine::get_instance()->isAvatarInStasis()) {
|
||||
debugC(kDebugObject, "Can't use: avatarInStasis");
|
||||
break;
|
||||
}
|
||||
|
||||
if (dynamic_cast<Actor *>(item) ||
|
||||
avatar->canReach(item, range)) {
|
||||
// call the 'use' event
|
||||
item->use();
|
||||
} else {
|
||||
Mouse::get_instance()->flashCrossCursor();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GameMapGump::IncSortOrder(int count) {
|
||||
_displayList->IncSortLimit(count);
|
||||
}
|
||||
|
||||
bool GameMapGump::StartDraggingItem(Item *item, int mx, int my) {
|
||||
// ParentToGump(mx, my);
|
||||
|
||||
bool hackMover = Ultima8Engine::get_instance()->isHackMoverEnabled();
|
||||
if (!hackMover) {
|
||||
if (!item->canDrag())
|
||||
return false;
|
||||
|
||||
MainActor *avatar = getMainActor();
|
||||
if (!avatar->canReach(item, 128))
|
||||
return false; // CONSTANT!
|
||||
}
|
||||
|
||||
// get item offset
|
||||
int32 itemx = 0;
|
||||
int32 itemy = 0;
|
||||
GetLocationOfItem(item->getObjId(), itemx, itemy);
|
||||
Mouse::get_instance()->setDraggingOffset(mx - itemx, my - itemy);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GameMapGump::DraggingItem(Item *item, int mx, int my) {
|
||||
// determine target location and set dragging_x/y/z
|
||||
int32 dox, doy;
|
||||
Mouse::get_instance()->getDraggingOffset(dox, doy);
|
||||
|
||||
_draggingShape = item->getShape();
|
||||
_draggingFrame = item->getFrame();
|
||||
_draggingFlags = item->getFlags();
|
||||
_displayDragging = true;
|
||||
|
||||
// determine if item can be dropped here
|
||||
|
||||
ObjId trace = TraceCoordinates(mx, my, _draggingPos, dox, doy, item);
|
||||
if (!trace)
|
||||
return false;
|
||||
|
||||
MainActor *avatar = getMainActor();
|
||||
if (trace == kMainActorId) { // dropping on self
|
||||
ObjId bp = avatar->getEquip(ShapeInfo::SE_BACKPACK);
|
||||
Container *backpack = getContainer(bp);
|
||||
return backpack->CanAddItem(item, true);
|
||||
}
|
||||
|
||||
bool hackMover = Ultima8Engine::get_instance()->isHackMoverEnabled();
|
||||
if (hackMover) {
|
||||
Mouse::get_instance()->setMouseCursor(Mouse::MOUSE_TARGET);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool throwing = false;
|
||||
if (!avatar->canReach(item, 128, // CONSTANT!
|
||||
_draggingPos.x, _draggingPos.y, _draggingPos.z)) {
|
||||
// can't reach, so see if we can throw
|
||||
int throwrange = item->getThrowRange();
|
||||
if (throwrange && avatar->canReach(item, throwrange, _draggingPos.x,
|
||||
_draggingPos.y, _draggingPos.z)) {
|
||||
int speed = 64 - item->getTotalWeight() + avatar->getStr();
|
||||
if (speed < 1) speed = 1;
|
||||
Point3 pt = avatar->getLocation();
|
||||
MissileTracker t(item, 1, pt.x, pt.y, pt.z,
|
||||
_draggingPos.x, _draggingPos.y, _draggingPos.z,
|
||||
speed, 4);
|
||||
if (t.isPathClear())
|
||||
throwing = true;
|
||||
else
|
||||
return false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!item->canExistAt(_draggingPos))
|
||||
return false;
|
||||
|
||||
if (throwing)
|
||||
Mouse::get_instance()->setMouseCursor(Mouse::MOUSE_TARGET);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GameMapGump::DraggingItemLeftGump(Item *item) {
|
||||
_displayDragging = false;
|
||||
}
|
||||
|
||||
|
||||
void GameMapGump::StopDraggingItem(Item *item, bool moved) {
|
||||
_displayDragging = false;
|
||||
|
||||
if (!moved) return; // nothing to do
|
||||
|
||||
// make items on top of item fall and call release on supporting items
|
||||
item->grab();
|
||||
}
|
||||
|
||||
void GameMapGump::DropItem(Item *item, int mx, int my) {
|
||||
int32 dox, doy;
|
||||
Mouse::get_instance()->getDraggingOffset(dox, doy);
|
||||
|
||||
_displayDragging = false;
|
||||
Actor *avatar = getMainActor();
|
||||
|
||||
ObjId trace = TraceCoordinates(mx, my, _draggingPos, dox, doy, item);
|
||||
Item *targetitem = getItem(trace);
|
||||
bool canReach = avatar->canReach(item, 128, // CONSTANT!
|
||||
_draggingPos.x, _draggingPos.y, _draggingPos.z);
|
||||
|
||||
bool hackMover = Ultima8Engine::get_instance()->isHackMoverEnabled();
|
||||
if (hackMover)
|
||||
canReach = true;
|
||||
|
||||
if (item->getShapeInfo()->hasQuantity()) {
|
||||
if (item->getQuality() > 1) {
|
||||
// more than one, so see if we should ask if we should split it up
|
||||
Item *splittarget = nullptr;
|
||||
|
||||
// also try to combine
|
||||
if (canReach && targetitem && item->canMergeWith(targetitem)) {
|
||||
splittarget = targetitem;
|
||||
}
|
||||
|
||||
if (!splittarget) {
|
||||
// create new item
|
||||
splittarget = ItemFactory::createItem(
|
||||
item->getShape(), item->getFrame(), 0,
|
||||
item->getFlags() & (Item::FLG_DISPOSABLE | Item::FLG_OWNED | Item::FLG_INVISIBLE | Item::FLG_FLIPPED | Item::FLG_FAST_ONLY | Item::FLG_LOW_FRICTION), item->getNpcNum(), item->getMapNum(),
|
||||
item->getExtFlags() & (Item::EXT_SPRITE | Item::EXT_HIGHLIGHT | Item::EXT_TRANSPARENT), true);
|
||||
if (!splittarget) {
|
||||
warning("ContainerGump failed to create item (%u,%u) while splitting",
|
||||
item->getShape(), item->getFrame());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SliderGump *slidergump = new SliderGump(100, 100,
|
||||
0, item->getQuality(),
|
||||
item->getQuality());
|
||||
slidergump->InitGump(0);
|
||||
slidergump->CreateNotifier(); // manually create notifier
|
||||
Process *notifier = slidergump->GetNotifyProcess();
|
||||
SplitItemProcess *splitproc = new SplitItemProcess(item, splittarget);
|
||||
Kernel::get_instance()->addProcess(splitproc);
|
||||
splitproc->waitFor(notifier);
|
||||
item = splittarget;
|
||||
} else {
|
||||
// try to combine items
|
||||
if (canReach && targetitem && item->canMergeWith(targetitem)) {
|
||||
uint16 newquant = targetitem->getQuality() + item->getQuality();
|
||||
if (newquant > Item::MAX_QUANTITY) {
|
||||
item->setQuality(newquant - Item::MAX_QUANTITY);
|
||||
targetitem->setQuality(Item::MAX_QUANTITY);
|
||||
// maybe this isn't needed? original doesn't do it here..
|
||||
targetitem->callUsecodeEvent_combine();
|
||||
} else {
|
||||
targetitem->setQuality(newquant);
|
||||
targetitem->callUsecodeEvent_combine();
|
||||
// combined, so delete other
|
||||
item->destroy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (trace == kMainActorId) { // dropping on self
|
||||
ObjId bp = avatar->getEquip(ShapeInfo::SE_BACKPACK);
|
||||
Container *backpack = getContainer(bp);
|
||||
if (backpack && item->moveToContainer(backpack)) {
|
||||
debugC(kDebugObject, "Dropped item in backpack");
|
||||
item->randomGumpLocation();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!canReach) {
|
||||
// can't reach, so throw
|
||||
debugC(kDebugObject, "Throwing item to (%d, %d, %d)",
|
||||
_draggingPos.x, _draggingPos.y, _draggingPos.z);
|
||||
int speed = 64 - item->getTotalWeight() + avatar->getStr();
|
||||
if (speed < 1)
|
||||
speed = 1;
|
||||
Point3 pt = avatar->getLocation();
|
||||
// CHECKME: correct position to throw from?
|
||||
// CHECKME: correct events triggered when doing this move?
|
||||
item->move(pt.x, pt.y, pt.z + 24);
|
||||
int32 tx, ty;
|
||||
tx = _draggingPos.x;
|
||||
ty = _draggingPos.y;
|
||||
int inaccuracy = 4 * (30 - avatar->getDex());
|
||||
if (inaccuracy < 20)
|
||||
inaccuracy = 20; // just in case dex > 25
|
||||
|
||||
Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
|
||||
tx += rs.getRandomNumberRngSigned(-inaccuracy, inaccuracy);
|
||||
ty += rs.getRandomNumberRngSigned(-inaccuracy, inaccuracy);
|
||||
MissileTracker t(item, 1, tx, ty, _draggingPos.z,
|
||||
speed, 4);
|
||||
t.launchItem();
|
||||
|
||||
Direction dir = Direction_GetWorldDir(_draggingPos.y - pt.y,
|
||||
_draggingPos.x - pt.x,
|
||||
dirmode_8dirs);
|
||||
avatar->doAnim(Animation::stand, dir);
|
||||
} else {
|
||||
debugC(kDebugObject, "Dropping item at (%d, %d, %d)",
|
||||
_draggingPos.x, _draggingPos.y, _draggingPos.z);
|
||||
|
||||
// CHECKME: collideMove and grab (in StopDraggingItem)
|
||||
// both call release on supporting items.
|
||||
|
||||
item->collideMove(_draggingPos.x, _draggingPos.y, _draggingPos.z,
|
||||
true, true); // teleport item
|
||||
item->fall();
|
||||
}
|
||||
}
|
||||
|
||||
void GameMapGump::RenderSurfaceChanged() {
|
||||
// Resize the desktop gump to match the parent
|
||||
Common::Rect32 new_dims = _parent->getDims();
|
||||
_dims.setWidth(new_dims.width());
|
||||
_dims.setHeight(new_dims.height());
|
||||
|
||||
// Offset the gump. We want 0,0 to be the centre
|
||||
_dims.moveTo(-_dims.width() / 2, -_dims.height() / 2);
|
||||
|
||||
Gump::RenderSurfaceChanged();
|
||||
}
|
||||
|
||||
void GameMapGump::saveData(Common::WriteStream *ws) {
|
||||
warning("Trying to save GameMapGump");
|
||||
}
|
||||
|
||||
bool GameMapGump::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
warning("Trying to load GameMapGump");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
118
engines/ultima/ultima8/gumps/game_map_gump.h
Normal file
118
engines/ultima/ultima8/gumps/game_map_gump.h
Normal file
@@ -0,0 +1,118 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_GAMEMAPGUMP_H
|
||||
#define ULTIMA8_GUMPS_GAMEMAPGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
#include "ultima/ultima8/misc/point3.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class ItemSorter;
|
||||
class CameraProcess;
|
||||
|
||||
/**
|
||||
* The gump which holds all the game map elements (floor, avatar, objects, etc)
|
||||
*/
|
||||
class GameMapGump : public Gump {
|
||||
protected:
|
||||
ItemSorter *_displayList;
|
||||
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
GameMapGump();
|
||||
GameMapGump(int x, int y, int w, int h);
|
||||
~GameMapGump() override;
|
||||
|
||||
void PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) override;
|
||||
|
||||
Point3 GetCameraLocation(int lerp_factor = 256);
|
||||
|
||||
// Trace a click, and return ObjId (_parent coord space)
|
||||
uint16 TraceObjId(int32 mx, int32 my) override;
|
||||
|
||||
// Trace a click, return ObjId, and the coordinates of the mouse click (gump coord space)
|
||||
virtual uint16 TraceCoordinates(int mx, int my, Point3 &coords,
|
||||
int offsetx = 0, int offsety = 0,
|
||||
Item *item = 0);
|
||||
|
||||
// Get the location of an item in the gump (coords relative to this).
|
||||
// Returns false on failure
|
||||
bool GetLocationOfItem(uint16 itemid, int32 &gx, int32 &gy,
|
||||
int32 lerp_factor = 256) override;
|
||||
|
||||
bool StartDraggingItem(Item *item, int mx, int my) override;
|
||||
bool DraggingItem(Item *item, int mx, int my) override;
|
||||
void DraggingItemLeftGump(Item *item) override;
|
||||
void StopDraggingItem(Item *item, bool moved) override;
|
||||
void DropItem(Item *item, int mx, int my) override;
|
||||
|
||||
Gump *onMouseDown(int button, int32 mx, int32 my) override;
|
||||
void onMouseUp(int button, int32 mx, int32 my) override;
|
||||
void onMouseClick(int button, int32 mx, int32 my) override;
|
||||
void onMouseDouble(int button, int32 mx, int32 my) override;
|
||||
|
||||
void IncSortOrder(int count);
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
|
||||
static void Set_highlightItems(bool highlight) {
|
||||
_highlightItems = highlight;
|
||||
}
|
||||
static bool is_highlightItems() {
|
||||
return _highlightItems;
|
||||
}
|
||||
static bool getShowFootpads() {
|
||||
return _showFootpads;
|
||||
}
|
||||
static void setShowFootpads(bool value) {
|
||||
_showFootpads = value;
|
||||
}
|
||||
static int getGridlines() {
|
||||
return _gridlines;
|
||||
}
|
||||
static void setGridlines(int gridlines) {
|
||||
_gridlines = gridlines;
|
||||
}
|
||||
|
||||
void RenderSurfaceChanged() override;
|
||||
|
||||
protected:
|
||||
bool _displayDragging;
|
||||
uint32 _draggingShape;
|
||||
uint32 _draggingFrame;
|
||||
uint32 _draggingFlags;
|
||||
Point3 _draggingPos;
|
||||
|
||||
static bool _highlightItems;
|
||||
static bool _showFootpads;
|
||||
static int _gridlines;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
866
engines/ultima/ultima8/gumps/gump.cpp
Normal file
866
engines/ultima/ultima8/gumps/gump.cpp
Normal file
@@ -0,0 +1,866 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/gump.h"
|
||||
#include "ultima/ultima8/gfx/render_surface.h"
|
||||
#include "ultima/ultima8/gfx/shape.h"
|
||||
#include "ultima/ultima8/gfx/shape_frame.h"
|
||||
#include "ultima/ultima8/gfx/shape_archive.h"
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/gumps/gump_notify_process.h"
|
||||
#include "ultima/ultima8/kernel/kernel.h"
|
||||
#include "ultima/ultima8/kernel/mouse.h"
|
||||
#include "ultima/ultima8/kernel/object_manager.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(Gump)
|
||||
|
||||
Gump::Gump() : Object(), _parent(nullptr), _owner(0),
|
||||
_x(0), _y(0), _flags(0), _layer(0), _index(-1),
|
||||
_shape(nullptr), _frameNum(0), _focusChild(nullptr),
|
||||
_notifier(0), _processResult(0) {
|
||||
}
|
||||
|
||||
Gump::Gump(int inX, int inY, int width, int height, uint16 inOwner,
|
||||
uint32 inFlags, int32 inLayer) :
|
||||
Object(), _owner(inOwner), _parent(nullptr), _x(inX), _y(inY),
|
||||
_dims(0, 0, width, height), _flags(inFlags), _layer(inLayer), _index(-1),
|
||||
_shape(nullptr), _frameNum(0), _children(), _focusChild(nullptr),
|
||||
_notifier(0), _processResult(0) {
|
||||
assignObjId(); // gumps always get an objid
|
||||
}
|
||||
|
||||
Gump::~Gump() {
|
||||
// Get rid of focus
|
||||
if (_focusChild) _focusChild->OnFocus(false);
|
||||
_focusChild = nullptr;
|
||||
|
||||
// Delete all children
|
||||
for (auto *g : _children) {
|
||||
delete g;
|
||||
}
|
||||
}
|
||||
|
||||
void Gump::InitGump(Gump *newparent, bool take_focus) {
|
||||
if (newparent)
|
||||
newparent->AddChild(this, take_focus);
|
||||
else
|
||||
Ultima8Engine::get_instance()->addGump(this);
|
||||
|
||||
if (_owner && !_notifier) CreateNotifier();
|
||||
}
|
||||
|
||||
void Gump::SetShape(FrameID frame, bool adjustsize) {
|
||||
_shape = GameData::get_instance()->getShape(frame);
|
||||
_frameNum = frame._frameNum;
|
||||
|
||||
if (adjustsize && _shape) {
|
||||
UpdateDimsFromShape();
|
||||
}
|
||||
}
|
||||
|
||||
void Gump::UpdateDimsFromShape() {
|
||||
const ShapeFrame *sf = _shape->getFrame(_frameNum);
|
||||
assert(sf);
|
||||
_dims.left = -sf->_xoff;
|
||||
_dims.top = -sf->_yoff;
|
||||
_dims.setWidth(sf->_width);
|
||||
_dims.setHeight(sf->_height);
|
||||
}
|
||||
|
||||
void Gump::CreateNotifier() {
|
||||
assert(_notifier == 0);
|
||||
|
||||
// Create us a GumpNotifyProcess
|
||||
GumpNotifyProcess *p = new GumpNotifyProcess(_owner);
|
||||
p->setGump(this);
|
||||
_notifier = Kernel::get_instance()->addProcess(p);
|
||||
}
|
||||
|
||||
void Gump::SetNotifyProcess(GumpNotifyProcess *proc) {
|
||||
assert(_notifier == 0);
|
||||
_notifier = proc->getPid();
|
||||
}
|
||||
|
||||
GumpNotifyProcess *Gump::GetNotifyProcess() {
|
||||
return dynamic_cast<GumpNotifyProcess *>(Kernel::get_instance()->
|
||||
getProcess(_notifier));
|
||||
}
|
||||
|
||||
|
||||
void Gump::Close(bool no_del) {
|
||||
GumpNotifyProcess *p = GetNotifyProcess();
|
||||
if (p) {
|
||||
p->notifyClosing(_processResult);
|
||||
}
|
||||
_notifier = 0;
|
||||
|
||||
_flags |= FLAG_CLOSING;
|
||||
if (!_parent) {
|
||||
if (!no_del)
|
||||
delete this;
|
||||
} else {
|
||||
_parent->ChildNotify(this, Gump::GUMP_CLOSING);
|
||||
if (!no_del)
|
||||
_flags |= FLAG_CLOSE_AND_DEL;
|
||||
}
|
||||
}
|
||||
|
||||
void Gump::RenderSurfaceChanged() {
|
||||
// Iterate all children
|
||||
Std::list<Gump *>::iterator it = _children.reverse_begin();
|
||||
Std::list<Gump *>::iterator end = _children.end();
|
||||
|
||||
while (it != end) {
|
||||
(*it)->RenderSurfaceChanged();
|
||||
--it;
|
||||
}
|
||||
}
|
||||
|
||||
void Gump::run() {
|
||||
// Iterate all children
|
||||
Std::list<Gump *>::iterator it = _children.begin();
|
||||
Std::list<Gump *>::iterator end = _children.end();
|
||||
|
||||
while (it != end) {
|
||||
Gump *g = *it;
|
||||
|
||||
// Run the child if it's not closing
|
||||
if (!(g->_flags & FLAG_CLOSING))
|
||||
g->run();
|
||||
|
||||
// If closing, we can kill it
|
||||
if (g->_flags & FLAG_CLOSING) {
|
||||
it = _children.erase(it);
|
||||
FindNewFocusChild();
|
||||
if (g->_flags & FLAG_CLOSE_AND_DEL) delete g;
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Gump::CloseItemDependents() {
|
||||
// Close it, and return
|
||||
if (_flags & FLAG_ITEM_DEPENDENT) {
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
// Pass the MapChanged message to all the children
|
||||
Std::list<Gump *>::iterator it = _children.begin();
|
||||
Std::list<Gump *>::iterator end = _children.end();
|
||||
|
||||
while (it != end) {
|
||||
Gump *g = *it;
|
||||
|
||||
// Pass to child if it's not closing
|
||||
if (!(g->_flags & FLAG_CLOSING)) g->CloseItemDependents();
|
||||
|
||||
// If closing, we can kill it
|
||||
if (g->_flags & FLAG_CLOSING) {
|
||||
it = _children.erase(it);
|
||||
FindNewFocusChild();
|
||||
if (g->_flags & FLAG_CLOSE_AND_DEL) delete g;
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Gump::GetMouseCursor(int32 mx, int32 my, Shape &shape, int32 &frame) {
|
||||
ParentToGump(mx, my);
|
||||
|
||||
bool ret = false;
|
||||
|
||||
// This reverse iterates the children
|
||||
Std::list<Gump *>::iterator it;
|
||||
for (it = _children.reverse_begin(); it != _children.end(); --it)
|
||||
{
|
||||
Gump *g = *it;
|
||||
|
||||
// Not if closing or hidden
|
||||
if (g->_flags & FLAG_CLOSING || g->IsHidden())
|
||||
continue;
|
||||
|
||||
// It's got the point
|
||||
if (g->PointOnGump(mx, my))
|
||||
ret = g->GetMouseCursor(mx, my, shape, frame);
|
||||
|
||||
if (ret) break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Gump::Paint(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
// Don't paint if hidden
|
||||
if (IsHidden()) return;
|
||||
|
||||
// Get old Origin
|
||||
int32 ox = 0, oy = 0;
|
||||
surf->GetOrigin(ox, oy);
|
||||
|
||||
// Set the new Origin
|
||||
int32 nx = 0, ny = 0;
|
||||
GumpToParent(nx, ny);
|
||||
surf->SetOrigin(ox + nx, oy + ny);
|
||||
|
||||
// Get Old Clipping Rect
|
||||
Common::Rect32 old_rect = surf->getClippingRect();
|
||||
|
||||
// Set new clipping rect
|
||||
Common::Rect32 new_rect(_dims);
|
||||
new_rect.clip(old_rect);
|
||||
surf->setClippingRect(new_rect);
|
||||
|
||||
// Paint This
|
||||
PaintThis(surf, lerp_factor, scaled);
|
||||
|
||||
// Paint children
|
||||
PaintChildren(surf, lerp_factor, scaled);
|
||||
|
||||
// Reset The Clipping Rect
|
||||
surf->setClippingRect(old_rect);
|
||||
|
||||
// Reset The Origin
|
||||
surf->SetOrigin(ox, oy);
|
||||
}
|
||||
|
||||
void Gump::PaintThis(RenderSurface *surf, int32 /*lerp_factor*/, bool /*scaled*/) {
|
||||
if (_shape)
|
||||
surf->Paint(_shape, _frameNum, 0, 0);
|
||||
}
|
||||
|
||||
void Gump::PaintChildren(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
for (auto *g : _children) {
|
||||
// Paint if not closing
|
||||
if (!(g->_flags & FLAG_CLOSING))
|
||||
g->Paint(surf, lerp_factor, scaled);
|
||||
}
|
||||
}
|
||||
|
||||
void Gump::PaintCompositing(RenderSurface *surf, int32 lerp_factor,
|
||||
int32 sx, int32 sy) {
|
||||
// Don't paint if hidden
|
||||
if (IsHidden()) return;
|
||||
|
||||
// Get old Origin
|
||||
int32 ox = 0, oy = 0;
|
||||
surf->GetOrigin(ox, oy);
|
||||
|
||||
// FIXME - Big accuracy problems here with the origin and clipping rect
|
||||
|
||||
// Set the new Origin
|
||||
surf->SetOrigin(0, 0);
|
||||
|
||||
// Get Old Clipping Rect
|
||||
Common::Rect32 old_rect = surf->getClippingRect();
|
||||
|
||||
// Set new clipping rect
|
||||
Common::Rect32 new_rect(_dims);
|
||||
GumpRectToScreenSpace(new_rect, ROUND_OUTSIDE);
|
||||
new_rect.clip(old_rect);
|
||||
surf->setClippingRect(new_rect);
|
||||
|
||||
// Iterate all children
|
||||
Std::list<Gump *>::iterator it = _children.reverse_begin();
|
||||
Std::list<Gump *>::iterator end = _children.end();
|
||||
|
||||
while (it != end) {
|
||||
Gump *g = *it;
|
||||
// Paint if not closing
|
||||
if (!g->IsClosing())
|
||||
g->PaintCompositing(surf, lerp_factor, sx, sy);
|
||||
|
||||
--it;
|
||||
}
|
||||
|
||||
// Paint This
|
||||
PaintComposited(surf, lerp_factor, sx, sy);
|
||||
|
||||
// Reset The Clipping Rect
|
||||
surf->setClippingRect(old_rect);
|
||||
|
||||
// Reset The Origin
|
||||
surf->SetOrigin(ox, oy);
|
||||
}
|
||||
|
||||
void Gump::PaintComposited(RenderSurface * /*surf*/, int32 /*lerp_factor*/, int32 /*scalex*/, int32 /*scaley*/) {
|
||||
}
|
||||
|
||||
Gump *Gump::FindGump(int mx, int my) {
|
||||
int32 gx = mx, gy = my;
|
||||
ParentToGump(gx, gy);
|
||||
Gump *gump = nullptr;
|
||||
|
||||
// Iterate all children
|
||||
Std::list<Gump *>::iterator it = _children.reverse_begin();
|
||||
Std::list<Gump *>::iterator end = _children.end();
|
||||
|
||||
while (it != end && !gump) {
|
||||
Gump *g = *it;
|
||||
gump = g->FindGump(gx, gy);
|
||||
--it;
|
||||
}
|
||||
|
||||
// it's over a child
|
||||
if (gump)
|
||||
return gump;
|
||||
|
||||
// it's over this gump
|
||||
if (PointOnGump(mx, my))
|
||||
return this;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Gump::setRelativePosition(Gump::Position pos, int xoffset, int yoffset) {
|
||||
if (_parent) {
|
||||
Common::Rect32 rect = _parent->getDims();
|
||||
|
||||
switch (pos) {
|
||||
case CENTER:
|
||||
Move(rect.width() / 2 - _dims.width() / 2 + xoffset,
|
||||
rect.height() / 2 - _dims.height() / 2 + yoffset);
|
||||
break;
|
||||
case TOP_LEFT:
|
||||
Move(xoffset, yoffset);
|
||||
break;
|
||||
case TOP_RIGHT:
|
||||
Move(rect.width() - _dims.width() + xoffset, yoffset);
|
||||
break;
|
||||
case BOTTOM_LEFT:
|
||||
Move(xoffset, rect.height() - _dims.height() + yoffset);
|
||||
break;
|
||||
case BOTTOM_RIGHT:
|
||||
Move(rect.width() - _dims.width() + xoffset, rect.height() - _dims.height() + yoffset);
|
||||
break;
|
||||
case TOP_CENTER:
|
||||
Move(rect.width() / 2 - _dims.width() / 2 + xoffset, yoffset);
|
||||
break;
|
||||
case BOTTOM_CENTER:
|
||||
Move(rect.width() / 2 - _dims.width() / 2 + xoffset, rect.height() - _dims.height() + yoffset);
|
||||
break;
|
||||
case LEFT_CENTER:
|
||||
Move(xoffset, rect.height() / 2 - _dims.height() / 2 + yoffset);
|
||||
break;
|
||||
case RIGHT_CENTER:
|
||||
Move(rect.width() - _dims.width() + xoffset, rect.height() / 2 - _dims.height() / 2 + yoffset);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Gump::PointOnGump(int mx, int my) {
|
||||
int32 gx = mx, gy = my;
|
||||
ParentToGump(gx, gy);
|
||||
|
||||
// First check again rectangle
|
||||
if (!_dims.contains(gx, gy)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_shape) {
|
||||
// no shape? Then if it's in the rectangle it's on the gump.
|
||||
return true;
|
||||
}
|
||||
|
||||
const ShapeFrame *sf = _shape->getFrame(_frameNum);
|
||||
assert(sf);
|
||||
if (sf->hasPoint(gx, gy)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// reverse-iterate children
|
||||
Std::list<Gump *>::iterator it;
|
||||
for (it = _children.reverse_begin(); it != _children.end(); --it) {
|
||||
Gump *g = *it;
|
||||
|
||||
// It's got the point
|
||||
if (g->PointOnGump(gx, gy)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Convert a screen space point to a gump point
|
||||
void Gump::ScreenSpaceToGump(int32 &sx, int32 &sy, PointRoundDir r) {
|
||||
// This is a recursive operation. We get each
|
||||
// parent to convert the point into their local
|
||||
// coords.
|
||||
if (_parent) _parent->ScreenSpaceToGump(sx, sy, r);
|
||||
|
||||
ParentToGump(sx, sy, r);
|
||||
}
|
||||
|
||||
// Convert a gump point to a screen space point
|
||||
void Gump::GumpToScreenSpace(int32 &gx, int32 &gy, PointRoundDir r) {
|
||||
// This is a recursive operation. We get each
|
||||
// gump to convert the point to their parent
|
||||
|
||||
GumpToParent(gx, gy, r);
|
||||
|
||||
if (_parent) _parent->GumpToScreenSpace(gx, gy, r);
|
||||
}
|
||||
|
||||
// Convert a parent relative point to a gump point
|
||||
void Gump::ParentToGump(int32 &px, int32 &py, PointRoundDir) {
|
||||
px -= _x;
|
||||
px += _dims.left;
|
||||
py -= _y;
|
||||
py += _dims.top;
|
||||
}
|
||||
|
||||
// Convert a gump point to parent relative point
|
||||
void Gump::GumpToParent(int32 &gx, int32 &gy, PointRoundDir) {
|
||||
gx -= _dims.left;
|
||||
gx += _x;
|
||||
gy -= _dims.top;
|
||||
gy += _y;
|
||||
}
|
||||
|
||||
// Transform a rectangle to screenspace from gumpspace
|
||||
void Gump::GumpRectToScreenSpace(Common::Rect32 &gr, RectRoundDir r) {
|
||||
PointRoundDir tl = (r == ROUND_INSIDE ? ROUND_BOTTOMRIGHT : ROUND_TOPLEFT);
|
||||
PointRoundDir br = (r == ROUND_OUTSIDE ? ROUND_BOTTOMRIGHT : ROUND_TOPLEFT);
|
||||
|
||||
int32 x1 = gr.left, y1 = gr.top;
|
||||
int32 x2 = gr.right, y2 = gr.bottom;
|
||||
GumpToScreenSpace(x1, y1, tl);
|
||||
GumpToScreenSpace(x2, y2, br);
|
||||
gr.moveTo(x1, y1);
|
||||
if (gr.width() != 0)
|
||||
gr.setWidth(x2 - x1);
|
||||
if (gr.height() != 0)
|
||||
gr.setHeight(y2 - y1);
|
||||
}
|
||||
|
||||
// Transform a rectangle to gumpspace from screenspace
|
||||
void Gump::ScreenSpaceToGumpRect(Common::Rect32 &sr, RectRoundDir r) {
|
||||
PointRoundDir tl = (r == ROUND_INSIDE ? ROUND_BOTTOMRIGHT : ROUND_TOPLEFT);
|
||||
PointRoundDir br = (r == ROUND_OUTSIDE ? ROUND_BOTTOMRIGHT : ROUND_TOPLEFT);
|
||||
|
||||
int32 x1 = sr.left, y1 = sr.top;
|
||||
int32 x2 = sr.right, y2 = sr.bottom;
|
||||
ScreenSpaceToGump(x1, y1, tl);
|
||||
ScreenSpaceToGump(x2, y2, br);
|
||||
sr.moveTo(x1, y1);
|
||||
if (sr.width() != 0)
|
||||
sr.setWidth(x2 - x1);
|
||||
if (sr.height() != 0)
|
||||
sr.setHeight(y2 - y1);
|
||||
}
|
||||
|
||||
uint16 Gump::TraceObjId(int32 mx, int32 my) {
|
||||
// Convert to local coords
|
||||
int32 gx = mx, gy = my;
|
||||
ParentToGump(gx, gy);
|
||||
|
||||
uint16 objId_ = 0;
|
||||
|
||||
// reverse-iterate children
|
||||
Std::list<Gump *>::iterator it;
|
||||
for (it = _children.reverse_begin(); it != _children.end(); --it) {
|
||||
Gump *g = *it;
|
||||
|
||||
// Not if closing or hidden
|
||||
if (g->_flags & FLAG_CLOSING || g->IsHidden())
|
||||
continue;
|
||||
|
||||
// It's got the point
|
||||
if (g->PointOnGump(gx, gy)) objId_ = g->TraceObjId(gx, gy);
|
||||
|
||||
if (objId_ && objId_ != 65535) break;
|
||||
}
|
||||
|
||||
// if (!objId_ || objId_ == 65535)
|
||||
// if (PointOnGump(mx,my))
|
||||
// objId_ = getObjId();
|
||||
|
||||
return objId_;
|
||||
}
|
||||
|
||||
bool Gump::GetLocationOfItem(uint16 itemid, int32 &gx, int32 &gy,
|
||||
int32 lerp_factor) {
|
||||
gx = 0;
|
||||
gy = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find a child gump that matches the matching function
|
||||
Gump *Gump::FindGump(const FindGumpPredicate predicate, bool recursive) {
|
||||
if (predicate(this))
|
||||
return this;
|
||||
|
||||
for (auto *g : _children) {
|
||||
// Not if closing
|
||||
if (g->_flags & FLAG_CLOSING)
|
||||
continue;
|
||||
|
||||
if (predicate(g))
|
||||
return g;
|
||||
}
|
||||
|
||||
if (!recursive)
|
||||
return nullptr;
|
||||
|
||||
// Recursive Iterate all children
|
||||
for (auto *g : _children) {
|
||||
// Not if closing
|
||||
if (g->_flags & FLAG_CLOSING)
|
||||
continue;
|
||||
|
||||
Gump *match = g->FindGump(predicate, recursive);
|
||||
|
||||
if (match)
|
||||
return match;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Makes this gump the focus
|
||||
void Gump::MakeFocus() {
|
||||
// By default we WON'T do anything
|
||||
if (_parent) {
|
||||
if (_parent->_focusChild) _parent->_focusChild->OnFocus(false);
|
||||
_parent->_focusChild = this;
|
||||
}
|
||||
OnFocus(true);
|
||||
}
|
||||
|
||||
void Gump::FindNewFocusChild() {
|
||||
if (_focusChild)
|
||||
_focusChild->OnFocus(false);
|
||||
_focusChild = nullptr;
|
||||
|
||||
// Now add the gump to use as the new focus
|
||||
Std::list<Gump *>::iterator it = _children.reverse_begin();
|
||||
|
||||
if (it != _children.end()) {
|
||||
(*it)->MakeFocus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Adds a child to the list
|
||||
void Gump::AddChild(Gump *gump, bool take_focus) {
|
||||
if (!gump) return;
|
||||
|
||||
// Remove it if required
|
||||
Gump *old_parent = gump->GetParent();
|
||||
if (old_parent) old_parent->RemoveChild(gump);
|
||||
|
||||
// Now add the gump in the correct spot
|
||||
Std::list<Gump *>::iterator it = _children.begin();
|
||||
Std::list<Gump *>::iterator end = _children.end();
|
||||
|
||||
for (; it != end; ++it) {
|
||||
Gump *other = *it;
|
||||
|
||||
// Why don't we check for FLAG_CLOSING here?
|
||||
// Because we want to make sure that the sort order is always valid
|
||||
|
||||
// If we are same layer as focus and we won't take it, we will not be
|
||||
// placed in front of it
|
||||
if (!take_focus && other == _focusChild && other->_layer == gump->_layer)
|
||||
break;
|
||||
|
||||
// Lower layers get placed before higher layers
|
||||
if (other->_layer > gump->_layer) break;
|
||||
}
|
||||
|
||||
// Now add it
|
||||
_children.insert(it, gump);
|
||||
gump->_parent = this;
|
||||
|
||||
// Make the gump the focus if needed
|
||||
if (take_focus || !_focusChild) {
|
||||
if (_focusChild) _focusChild->OnFocus(false);
|
||||
gump->OnFocus(true);
|
||||
_focusChild = gump;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove a gump from the list
|
||||
void Gump::RemoveChild(Gump *gump) {
|
||||
if (!gump) return;
|
||||
|
||||
// Remove it
|
||||
_children.remove(gump);
|
||||
gump->_parent = nullptr;
|
||||
|
||||
// Remove focus, the give upper most gump the focus
|
||||
if (gump == _focusChild) {
|
||||
FindNewFocusChild();
|
||||
}
|
||||
}
|
||||
|
||||
void Gump::MoveChildToFront(Gump *gump) {
|
||||
if (!gump) return;
|
||||
|
||||
_children.remove(gump);
|
||||
|
||||
Std::list<Gump *>::iterator it = _children.begin();
|
||||
Std::list<Gump *>::iterator end = _children.end();
|
||||
for (; it != end; ++it) {
|
||||
Gump *other = *it;
|
||||
|
||||
// Lower layers get placed before higher layers
|
||||
if (other->_layer > gump->_layer) break;
|
||||
}
|
||||
|
||||
_children.insert(it, gump);
|
||||
}
|
||||
|
||||
|
||||
Gump *Gump::GetRootGump() {
|
||||
if (!_parent) return this;
|
||||
return _parent->GetRootGump();
|
||||
}
|
||||
|
||||
|
||||
bool Gump::onDragStart(int32 mx, int32 my) {
|
||||
if (IsDraggable() && _parent) {
|
||||
ParentToGump(mx, my);
|
||||
Mouse::get_instance()->setDraggingOffset(mx, my);
|
||||
_parent->MoveChildToFront(this);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Gump::onDragStop(int32 mx, int32 my) {
|
||||
}
|
||||
|
||||
void Gump::onDrag(int32 mx, int32 my) {
|
||||
int32 dx, dy;
|
||||
Mouse::get_instance()->getDraggingOffset(dx, dy);
|
||||
Move(mx - dx, my - dy);
|
||||
}
|
||||
|
||||
//
|
||||
// Input handling
|
||||
//
|
||||
|
||||
Gump *Gump::onMouseDown(int button, int32 mx, int32 my) {
|
||||
// Convert to local coords
|
||||
ParentToGump(mx, my);
|
||||
|
||||
Gump *handled = nullptr;
|
||||
|
||||
// Iterate children backwards
|
||||
Std::list<Gump *>::iterator it;
|
||||
for (it = _children.reverse_begin(); it != _children.end(); --it) {
|
||||
Gump *g = *it;
|
||||
|
||||
// Not if closing or hidden
|
||||
if (g->_flags & FLAG_CLOSING || g->IsHidden())
|
||||
continue;
|
||||
|
||||
// It's got the point
|
||||
if (g->PointOnGump(mx, my)) handled = g->onMouseDown(button, mx, my);
|
||||
|
||||
if (handled) break;
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
Gump *Gump::onMouseMotion(int32 mx, int32 my) {
|
||||
// Convert to local coords
|
||||
ParentToGump(mx, my);
|
||||
|
||||
Gump *handled = nullptr;
|
||||
|
||||
// Iterate children backwards
|
||||
Std::list<Gump *>::iterator it;
|
||||
for (it = _children.reverse_begin(); it != _children.end(); --it) {
|
||||
Gump *g = *it;
|
||||
|
||||
// Not if closing or hidden
|
||||
if (g->_flags & FLAG_CLOSING || g->IsHidden())
|
||||
continue;
|
||||
|
||||
// It's got the point
|
||||
if (g->PointOnGump(mx, my)) handled = g->onMouseMotion(mx, my);
|
||||
|
||||
if (handled) break;
|
||||
}
|
||||
|
||||
// All gumps need to handle mouse motion
|
||||
if (!handled) handled = this;
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
//
|
||||
// KeyInput
|
||||
//
|
||||
bool Gump::OnKeyDown(int key, int mod) {
|
||||
bool handled = false;
|
||||
if (_focusChild) handled = _focusChild->OnKeyDown(key, mod);
|
||||
return handled;
|
||||
}
|
||||
|
||||
bool Gump::OnKeyUp(int key) {
|
||||
bool handled = false;
|
||||
if (_focusChild) handled = _focusChild->OnKeyUp(key);
|
||||
return handled;
|
||||
}
|
||||
|
||||
bool Gump::OnTextInput(int unicode) {
|
||||
bool handled = false;
|
||||
if (_focusChild) handled = _focusChild->OnTextInput(unicode);
|
||||
return handled;
|
||||
}
|
||||
|
||||
bool Gump::mustSave(bool toplevel) const {
|
||||
// DONT_SAVE flag
|
||||
if (_flags & FLAG_DONT_SAVE)
|
||||
return false;
|
||||
|
||||
// don't save when ready for deletion
|
||||
if (_flags & FLAG_CLOSE_AND_DEL)
|
||||
return false;
|
||||
|
||||
if (toplevel) {
|
||||
// don't save gumps with parents, unless parent is a core gump
|
||||
if (_parent && !(_parent->_flags & FLAG_CORE_GUMP))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Gump::saveData(Common::WriteStream *ws) {
|
||||
Object::saveData(ws);
|
||||
|
||||
ws->writeUint16LE(_owner);
|
||||
ws->writeUint32LE(static_cast<uint32>(_x));
|
||||
ws->writeUint32LE(static_cast<uint32>(_y));
|
||||
ws->writeUint32LE(static_cast<uint32>(_dims.left));
|
||||
ws->writeUint32LE(static_cast<uint32>(_dims.top));
|
||||
ws->writeUint32LE(static_cast<uint32>(_dims.width()));
|
||||
ws->writeUint32LE(static_cast<uint32>(_dims.height()));
|
||||
ws->writeUint32LE(_flags);
|
||||
ws->writeUint32LE(static_cast<uint32>(_layer));
|
||||
ws->writeUint32LE(static_cast<uint32>(_index));
|
||||
|
||||
uint16 flex = 0;
|
||||
uint32 shapenum = 0;
|
||||
if (_shape) {
|
||||
_shape->getShapeId(flex, shapenum);
|
||||
}
|
||||
ws->writeUint16LE(flex);
|
||||
ws->writeUint32LE(shapenum);
|
||||
|
||||
ws->writeUint32LE(_frameNum);
|
||||
if (_focusChild)
|
||||
ws->writeUint16LE(_focusChild->getObjId());
|
||||
else
|
||||
ws->writeUint16LE(0);
|
||||
ws->writeUint16LE(_notifier);
|
||||
ws->writeUint32LE(_processResult);
|
||||
|
||||
unsigned int childcount = 0;
|
||||
for (auto *g : _children) {
|
||||
if (!g->mustSave(false))
|
||||
continue;
|
||||
childcount++;
|
||||
}
|
||||
|
||||
// write children:
|
||||
ws->writeUint32LE(childcount);
|
||||
for (auto *g : _children) {
|
||||
if (!g->mustSave(false))
|
||||
continue;
|
||||
|
||||
ObjectManager::get_instance()->saveObject(ws, g);
|
||||
}
|
||||
}
|
||||
|
||||
bool Gump::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
if (!Object::loadData(rs, version)) return false;
|
||||
|
||||
_owner = rs->readUint16LE();
|
||||
_x = static_cast<int32>(rs->readUint32LE());
|
||||
_y = static_cast<int32>(rs->readUint32LE());
|
||||
|
||||
int dx = static_cast<int32>(rs->readUint32LE());
|
||||
int dy = static_cast<int32>(rs->readUint32LE());
|
||||
int dw = static_cast<int32>(rs->readUint32LE());
|
||||
int dh = static_cast<int32>(rs->readUint32LE());
|
||||
_dims.moveTo(dx, dy);
|
||||
_dims.setWidth(dw);
|
||||
_dims.setHeight(dh);
|
||||
|
||||
_flags = rs->readUint32LE();
|
||||
_layer = static_cast<int32>(rs->readUint32LE());
|
||||
_index = static_cast<int32>(rs->readUint32LE());
|
||||
|
||||
_shape = nullptr;
|
||||
ShapeArchive *flex = GameData::get_instance()->getShapeFlex(rs->readUint16LE());
|
||||
uint32 shapenum = rs->readUint32LE();
|
||||
if (flex) {
|
||||
_shape = flex->getShape(shapenum);
|
||||
if (shapenum > 0 && !_shape) {
|
||||
warning("Gump shape %d is not valid. Corrupt save?", shapenum);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_frameNum = rs->readUint32LE();
|
||||
uint16 focusid = rs->readUint16LE();
|
||||
_focusChild = nullptr;
|
||||
_notifier = rs->readUint16LE();
|
||||
_processResult = rs->readUint32LE();
|
||||
|
||||
// read children
|
||||
uint32 childcount = rs->readUint32LE();
|
||||
|
||||
if (childcount > 65535) {
|
||||
warning("Improbable gump child count %d. Corrupt save?", childcount);
|
||||
return false;
|
||||
}
|
||||
for (unsigned int i = 0; i < childcount; ++i) {
|
||||
Object *obj = ObjectManager::get_instance()->loadObject(rs, version);
|
||||
Gump *child = dynamic_cast<Gump *>(obj);
|
||||
if (!child) return false;
|
||||
|
||||
AddChild(child, false);
|
||||
|
||||
if (child->getObjId() == focusid)
|
||||
_focusChild = child;
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
490
engines/ultima/ultima8/gumps/gump.h
Normal file
490
engines/ultima/ultima8/gumps/gump.h
Normal file
@@ -0,0 +1,490 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_GUMP_H
|
||||
#define ULTIMA8_GUMPS_GUMP_H
|
||||
|
||||
#include "common/rect.h"
|
||||
#include "ultima/ultima8/kernel/object.h"
|
||||
#include "ultima/ultima8/gfx/frame_id.h"
|
||||
#include "ultima/shared/std/containers.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class RenderSurface;
|
||||
class Shape;
|
||||
class Item;
|
||||
class GumpNotifyProcess;
|
||||
|
||||
class Gump;
|
||||
typedef bool (*FindGumpPredicate)(const Gump *g);
|
||||
template<class T> inline bool IsOfType(const Gump *g) { return dynamic_cast<const T*>(g) != nullptr; }
|
||||
|
||||
/**
|
||||
* A Gump is a single GUI element within the game, like the backpack window, menu,
|
||||
* conversation text, etc. Like most windowing systems, gumps nest.
|
||||
*/
|
||||
class Gump : public Object {
|
||||
protected:
|
||||
uint16 _owner; // Owner item
|
||||
Gump *_parent; // Parent gump
|
||||
int32 _x, _y; // Gump's position in parent.
|
||||
// Always the upper left corner!
|
||||
|
||||
Common::Rect32 _dims; // The dimensions/coord space of the gump
|
||||
uint32 _flags; // Gump flags
|
||||
int32 _layer; // gump ordering layer
|
||||
|
||||
int32 _index; // 'Index'
|
||||
|
||||
const Shape *_shape; // The gumps shape (always painted at 0,0)
|
||||
uint32 _frameNum;
|
||||
|
||||
//! The Gump list for this gump. This will contain all child gumps,
|
||||
//! as well as all gump widgets.
|
||||
Std::list<Gump *> _children; // List of all gumps
|
||||
Gump *_focusChild; // The child that has focus
|
||||
|
||||
uint16 _notifier; // Process to notify when we're closing
|
||||
uint32 _processResult; // Result for the notifier process
|
||||
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
Gump();
|
||||
Gump(int x, int y, int width, int height, uint16 owner = 0,
|
||||
uint32 flags = 0, int32 layer = LAYER_NORMAL);
|
||||
~Gump() override;
|
||||
|
||||
public:
|
||||
|
||||
virtual void CreateNotifier();
|
||||
void SetNotifyProcess(GumpNotifyProcess *proc);
|
||||
GumpNotifyProcess *GetNotifyProcess();
|
||||
inline uint32 GetResult() {
|
||||
return _processResult;
|
||||
}
|
||||
void SetResult(uint32 res) {
|
||||
_processResult = res;
|
||||
}
|
||||
|
||||
//! Set the Gump's shape/frame
|
||||
inline void SetShape(const Shape *shape, uint32 frameNum) {
|
||||
_shape = shape;
|
||||
_frameNum = frameNum;
|
||||
}
|
||||
|
||||
void SetShape(FrameID frame, bool adjustsize = false);
|
||||
|
||||
//! Update the width/height to match the gump's current shape frame
|
||||
void UpdateDimsFromShape();
|
||||
|
||||
//! Set the Gump's frame
|
||||
inline void Set_frameNum(uint32 frameNum) {
|
||||
_frameNum = frameNum;
|
||||
}
|
||||
|
||||
//! Init the gump and add it to parent; call after construction
|
||||
//! When newparent is 0, this will call Ultima8Engine::addGump().
|
||||
//! \param newparent The Gump's new parent or 0.
|
||||
//! \param takefocus If true, set parent's _focusChild to this
|
||||
virtual void InitGump(Gump *newparent, bool take_focus = true);
|
||||
|
||||
//! Find a gump of that matches a predicate function (this or child)
|
||||
//! \param predicate Function to check if a gump is a match
|
||||
//! \param recursive Recursively search through children?
|
||||
//! \return the desired Gump, or NULL if not found
|
||||
virtual Gump *FindGump(FindGumpPredicate predicate, bool recursive = true);
|
||||
|
||||
//! Find a gump of the specified type (this or child)
|
||||
//! \param T Type of gump to look for
|
||||
//! \param recursive Recursively search through children?
|
||||
//! \return the desired Gump, or NULL if not found
|
||||
template<class T> Gump *FindGump(bool recursive = true) {
|
||||
return FindGump(&IsOfType<T>, recursive);
|
||||
}
|
||||
|
||||
//! A predicate to find a ui element by its index
|
||||
template<int T> static bool FindByIndex(const Gump *g) { return g->GetIndex() == T; }
|
||||
|
||||
//! Find gump (this, child or NULL) at parent coordinates (mx,my)
|
||||
//! \return the Gump at these coordinates, or NULL if none
|
||||
virtual Gump *FindGump(int mx, int my);
|
||||
|
||||
//! Get the mouse cursor for position mx, my relative to parents position.
|
||||
//! If this gump doesn't want to set the cursor, the gump list will
|
||||
//! attempt to get the cursor shape from the next lower gump.
|
||||
//! \return true if this gump wants to set the cursor, false otherwise
|
||||
virtual bool GetMouseCursor(int32 mx, int32 my, Shape &shape, int32 &frame);
|
||||
|
||||
// Notify gumps the render surface changed.
|
||||
virtual void RenderSurfaceChanged();
|
||||
|
||||
//! Run the gump
|
||||
virtual void run();
|
||||
|
||||
//! Close item-dependent gumps (recursively).
|
||||
//! Called when there is a map change (so the gumps can self terminate
|
||||
//! among other things), or when backspace is pressed by the user.
|
||||
virtual void CloseItemDependents();
|
||||
|
||||
//! Paint the Gump (RenderSurface is relative to parent).
|
||||
//! Calls PaintThis and PaintChildren
|
||||
// \param surf The RenderSurface to paint to
|
||||
// \param lerp_factor The lerp_factor to paint at (0-256)
|
||||
// \param scaled Set if the gump is being drawn scaled.
|
||||
virtual void Paint(RenderSurface *surf, int32 lerp_factor, bool scaled);
|
||||
|
||||
//! Paint the unscaled compontents of the Gump with compositing (RenderSurface is relative to parent).
|
||||
//! Calls PaintComposited on self and PaintCompositing on children
|
||||
// \param surf The RenderSurface to paint to
|
||||
// \param lerp_factor The lerp_factor to paint at (0-256)
|
||||
// \param scalex Fixed point scaling factor for x coord
|
||||
// \param scaley Fixed point scaling factor for y coord
|
||||
virtual void PaintCompositing(RenderSurface *surf, int32 lerp_factor, int32 scalex, int32 scaley);
|
||||
|
||||
protected:
|
||||
|
||||
//! Overloadable method to Paint just this Gump (RenderSurface is relative to this)
|
||||
// \param surf The RenderSurface to paint to
|
||||
// \param lerp_factor The lerp_factor to paint at (0-256)
|
||||
// \param scaled Set if the gump is being drawn scaled.
|
||||
virtual void PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled);
|
||||
|
||||
//! Paint the Gumps Children (RenderSurface is relative to this)
|
||||
// \param surf The RenderSurface to paint to
|
||||
// \param lerp_factor The lerp_factor to paint at (0-256)
|
||||
// \param scaled Set if the gump is being drawn scaled.
|
||||
virtual void PaintChildren(RenderSurface *surf, int32 lerp_factor, bool scaled);
|
||||
|
||||
//! Overloadable method to Paint just this gumps unscaled components that require compositing (RenderSurface is relative to parent).
|
||||
// \param surf The RenderSurface to paint to
|
||||
// \param lerp_factor The lerp_factor to paint at (0-256)
|
||||
// \param scalex Fixed point scaling factor for x coord
|
||||
// \param scaley Fixed point scaling factor for y coord
|
||||
virtual void PaintComposited(RenderSurface *surf, int32 lerp_factor, int32 scalex, int32 scaley);
|
||||
|
||||
static inline int32 ScaleCoord(int32 c, int32 factor) {
|
||||
return ((c * factor) + (1 << 15)) >> 16;
|
||||
}
|
||||
static inline int32 UnscaleCoord(int32 c, int32 factor) {
|
||||
return (c << 16) / factor;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
//! Close the gump
|
||||
//! \param no_del If true, do not delete after closing
|
||||
virtual void Close(bool no_del = false);
|
||||
|
||||
//! Check to see if a Gump is Closing
|
||||
bool IsClosing() const {
|
||||
return (_flags & FLAG_CLOSING) != 0;
|
||||
}
|
||||
|
||||
//! Move this gump
|
||||
virtual void Move(int32 x, int32 y) {
|
||||
_x = x;
|
||||
_y = y;
|
||||
}
|
||||
|
||||
//! Move this gump relative to its current position
|
||||
virtual void MoveRelative(int x, int y) {
|
||||
_x += x;
|
||||
_y += y;
|
||||
}
|
||||
|
||||
void getLocation(int32 &x, int32 &y) const {
|
||||
x = _x;
|
||||
y = _y;
|
||||
}
|
||||
|
||||
enum Position {
|
||||
CENTER = 1,
|
||||
TOP_LEFT = 2,
|
||||
TOP_RIGHT = 3,
|
||||
BOTTOM_LEFT = 4,
|
||||
BOTTOM_RIGHT = 5,
|
||||
TOP_CENTER = 6,
|
||||
BOTTOM_CENTER = 7,
|
||||
LEFT_CENTER = 8,
|
||||
RIGHT_CENTER = 9
|
||||
};
|
||||
|
||||
//! Moves this gump to a relative location on the parent gump
|
||||
// \param pos the postition on the parent gump
|
||||
// \param xoffset an offset from the position on the x-axis
|
||||
// \param yoffset an offset from the position on the y-axis
|
||||
virtual void setRelativePosition(Position pos, int xoffset = 0, int yoffset = 0);
|
||||
|
||||
//
|
||||
// Points and Coords
|
||||
//
|
||||
|
||||
//! Get the _dims
|
||||
const Common::Rect32 &getDims() const {
|
||||
return _dims;
|
||||
}
|
||||
|
||||
//! Set the _dims
|
||||
void setDims(const Common::Rect32 &d) {
|
||||
_dims = d;
|
||||
}
|
||||
|
||||
//! Detect if a point is on the gump
|
||||
virtual bool PointOnGump(int mx, int my);
|
||||
|
||||
enum PointRoundDir {
|
||||
ROUND_TOPLEFT = 0,
|
||||
ROUND_BOTTOMRIGHT = 1
|
||||
};
|
||||
enum RectRoundDir {
|
||||
ROUND_INSIDE,
|
||||
ROUND_OUTSIDE
|
||||
};
|
||||
|
||||
//! Convert a screen space point to a gump point
|
||||
virtual void ScreenSpaceToGump(int32 &sx, int32 &sy,
|
||||
PointRoundDir r = ROUND_TOPLEFT);
|
||||
|
||||
//! Convert a gump point to a screen space point
|
||||
virtual void GumpToScreenSpace(int32 &gx, int32 &gy,
|
||||
PointRoundDir r = ROUND_TOPLEFT);
|
||||
|
||||
//! Convert a parent relative point to a gump point
|
||||
virtual void ParentToGump(int32 &px, int32 &py,
|
||||
PointRoundDir r = ROUND_TOPLEFT);
|
||||
|
||||
//! Convert a gump point to parent relative point
|
||||
virtual void GumpToParent(int32 &gx, int32 &gy,
|
||||
PointRoundDir r = ROUND_TOPLEFT);
|
||||
|
||||
//! Transform a rectangle to screenspace from gumpspace
|
||||
virtual void GumpRectToScreenSpace(Common::Rect32 &gr, RectRoundDir r = ROUND_OUTSIDE);
|
||||
|
||||
//! Transform a rectangle to gumpspace from screenspace
|
||||
virtual void ScreenSpaceToGumpRect(Common::Rect32 &sr, RectRoundDir r = ROUND_OUTSIDE);
|
||||
|
||||
//! Trace a click, and return ObjId
|
||||
virtual uint16 TraceObjId(int32 mx, int32 my);
|
||||
|
||||
//! Get the location of an item in the gump (coords relative to this).
|
||||
//! \return false on failure
|
||||
virtual bool GetLocationOfItem(uint16 itemid, int32 &gx, int32 &gy,
|
||||
int32 lerp_factor = 256);
|
||||
|
||||
|
||||
//
|
||||
// Some event handlers. In theory they 'should' be able to be mapped to
|
||||
// Usecode classes.
|
||||
//
|
||||
// mx and my are relative to parents position
|
||||
//
|
||||
// onMouseDown returns the Gump that handled the Input, if it was handled.
|
||||
// The MouseUp,MouseDouble events will be sent to the same gump.
|
||||
//
|
||||
// onMouseMotion works like onMouseDown,
|
||||
// but independently of the other methods.
|
||||
//
|
||||
// Unhandled input will be passed down to the next lower gump.
|
||||
//
|
||||
// A mouse click on a gump will make it focus, IF it wants it.
|
||||
//
|
||||
// It is often preferrable to handle both click and double events
|
||||
// rather than only the up event to avoid unintended clicks after
|
||||
// performing intended action.
|
||||
|
||||
// Return Gump that handled event
|
||||
virtual Gump *onMouseDown(int button, int32 mx, int32 my);
|
||||
virtual void onMouseUp(int button, int32 mx, int32 my) { }
|
||||
virtual void onMouseClick(int button, int32 mx, int32 my) { }
|
||||
virtual void onMouseDouble(int button, int32 mx, int32 my) { }
|
||||
virtual Gump *onMouseMotion(int32 mx, int32 my);
|
||||
|
||||
// onMouseOver is only call when the mouse first passes over the gump
|
||||
// onMouseLeft is call as the mouse leaves the gump.
|
||||
virtual void onMouseOver() { };
|
||||
virtual void onMouseLeft() { };
|
||||
|
||||
// Keyboard input gets sent to the FocusGump. Or if there isn't one, it
|
||||
// will instead get sent to the default key handler. TextInput requires
|
||||
// that text mode be enabled. Return true if handled, false if not.
|
||||
// Default, returns false, unless handled by focus child
|
||||
virtual bool OnKeyDown(int key, int mod);
|
||||
virtual bool OnKeyUp(int key);
|
||||
virtual bool OnTextInput(int unicode);
|
||||
|
||||
// This is for detecting focus changes for keyboard input. Gets called true
|
||||
// when the this gump is being set as the focus focus gump. It is called
|
||||
// false when focus is being taken away.
|
||||
virtual void OnFocus(bool /*gain*/) { }
|
||||
|
||||
// Makes this gump the focus
|
||||
virtual void MakeFocus();
|
||||
|
||||
// Is this gump the focus?
|
||||
inline bool IsFocus() {
|
||||
return _parent ? _parent->_focusChild == this : false;
|
||||
}
|
||||
|
||||
// Get the child in focus
|
||||
inline Gump *GetFocusChild() {
|
||||
return _focusChild;
|
||||
}
|
||||
|
||||
// Find a new Child to be the focus
|
||||
void FindNewFocusChild();
|
||||
|
||||
|
||||
//
|
||||
// Child gump related
|
||||
//
|
||||
|
||||
//! Add a gump to the child list.
|
||||
virtual void AddChild(Gump *, bool take_focus = true);
|
||||
|
||||
//! Remove a gump from the child list
|
||||
virtual void RemoveChild(Gump *);
|
||||
|
||||
//! Move child to front (within its layer)
|
||||
virtual void MoveChildToFront(Gump *);
|
||||
|
||||
//! Get the parent
|
||||
inline Gump *GetParent() {
|
||||
return _parent;
|
||||
}
|
||||
|
||||
//! Get the root gump (or self)
|
||||
Gump *GetRootGump();
|
||||
|
||||
//! This function is used by our children to notifty us of 'something'
|
||||
//! Think of it as a generic call back function
|
||||
virtual void ChildNotify(Gump *child, uint32 message) { }
|
||||
void SetIndex(int32 i) {
|
||||
_index = i;
|
||||
}
|
||||
int32 GetIndex() const {
|
||||
return _index;
|
||||
}
|
||||
|
||||
//! Called when a gump starts to be dragged.
|
||||
//! \return false if the gump isn't allowed to be dragged.
|
||||
virtual bool onDragStart(int32 mx, int32 my);
|
||||
virtual void onDragStop(int32 mx, int32 my);
|
||||
virtual void onDrag(int32 mx, int32 my);
|
||||
|
||||
//! This will be called when an item in this gump starts to be dragged.
|
||||
//! \return false if the item isn't allowed to be dragged.
|
||||
virtual bool StartDraggingItem(Item *item, int mx, int my) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//! Called when an item is being dragged over the gump.
|
||||
//! Note: this may be called on a different gump than StartDraggingItem.
|
||||
//! \return false if the item can't be dragged to this location.
|
||||
virtual bool DraggingItem(Item *item, int mx, int my) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//! Called when an item that was being dragged over the gump left the gump
|
||||
virtual void DraggingItemLeftGump(Item *item) { }
|
||||
|
||||
//! Called when a drag operation finished.
|
||||
//! This is called on the same gump that received StartDraggingItem
|
||||
//! \param moved If true, the item was actually dragged somewhere else.
|
||||
//! If false, the drag was cancelled.
|
||||
virtual void StopDraggingItem(Item *item, bool moved) { }
|
||||
|
||||
//! Called when an item has been dropped on a gump.
|
||||
//! This is called after StopDraggingItem has been called, but possibly
|
||||
//! on a different gump.
|
||||
//! It's guaranteed that a gump will only receive a DropItem at a location
|
||||
//! if a DraggingItem there returned true.
|
||||
virtual void DropItem(Item *item, int mx, int my) { }
|
||||
|
||||
public:
|
||||
|
||||
//
|
||||
// Gump Flags
|
||||
//
|
||||
enum GumpFlags {
|
||||
FLAG_DRAGGABLE = 0x0001, // When set, the gump can be dragged
|
||||
FLAG_HIDDEN = 0x0002, // When set, the gump will not be drawn
|
||||
FLAG_CLOSING = 0x0004, // When set, the gump is closing
|
||||
FLAG_CLOSE_AND_DEL = 0x0008, // When set, the gump is closing and will be deleted
|
||||
FLAG_ITEM_DEPENDENT = 0x0010, // When set, the gump will be deleted on MapChange
|
||||
FLAG_DONT_SAVE = 0x0020, // When set, don't save this gump. Be very careful with this one!
|
||||
FLAG_CORE_GUMP = 0x0040, // core gump (only children are saved)
|
||||
FLAG_KEEP_VISIBLE = 0x0080, // Keep this gump on-screen. (only for ItemRelativeGumps)
|
||||
FLAG_PREVENT_SAVE = 0x0100 // When set, prevent game from saving
|
||||
};
|
||||
|
||||
//! Does this gump have any of the given flags mask set
|
||||
inline bool hasFlags(uint flags) const {
|
||||
return (_flags & flags) != 0;
|
||||
}
|
||||
|
||||
inline bool IsHidden() const {
|
||||
return (_flags & FLAG_HIDDEN) || (_parent && _parent->IsHidden());
|
||||
}
|
||||
bool IsDraggable() const {
|
||||
return _flags & FLAG_DRAGGABLE;
|
||||
}
|
||||
virtual void HideGump() {
|
||||
_flags |= FLAG_HIDDEN;
|
||||
}
|
||||
virtual void UnhideGump() {
|
||||
_flags &= ~FLAG_HIDDEN;
|
||||
}
|
||||
void SetVisibility(bool visible) {
|
||||
if (visible)
|
||||
UnhideGump();
|
||||
else
|
||||
HideGump();
|
||||
}
|
||||
|
||||
bool mustSave(bool toplevel) const;
|
||||
|
||||
//
|
||||
// Gump Layers
|
||||
//
|
||||
enum GumpLayers {
|
||||
LAYER_DESKTOP = -16, // Layer for Desktop 'bottom most'
|
||||
LAYER_GAMEMAP = -8, // Layer for the World Gump
|
||||
LAYER_NORMAL = 0, // Layer for Normal gumps
|
||||
LAYER_ABOVE_NORMAL = 8, // Layer for Always on top Gumps
|
||||
LAYER_MODAL = 12, // Layer for Modal Gumps
|
||||
LAYER_CONSOLE = 16 // Layer for the console
|
||||
};
|
||||
|
||||
enum Message {
|
||||
GUMP_CLOSING = 0x100
|
||||
};
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
88
engines/ultima/ultima8/gumps/gump_notify_process.cpp
Normal file
88
engines/ultima/ultima8/gumps/gump_notify_process.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/gump_notify_process.h"
|
||||
#include "ultima/ultima8/gumps/gump.h"
|
||||
#include "ultima/ultima8/world/get_object.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(GumpNotifyProcess)
|
||||
|
||||
GumpNotifyProcess::GumpNotifyProcess()
|
||||
: Process(), _gump(0) {
|
||||
|
||||
}
|
||||
|
||||
GumpNotifyProcess::GumpNotifyProcess(uint16 it) : Process(it), _gump(0) {
|
||||
_result = 0;
|
||||
_type = 0x200; // CONSTANT!
|
||||
}
|
||||
|
||||
GumpNotifyProcess::~GumpNotifyProcess(void) {
|
||||
}
|
||||
|
||||
void GumpNotifyProcess::setGump(Gump *g) {
|
||||
_gump = g->getObjId();
|
||||
}
|
||||
|
||||
|
||||
void GumpNotifyProcess::notifyClosing(int res) {
|
||||
_gump = 0;
|
||||
_result = res;
|
||||
if (!(_flags & PROC_TERMINATED)) terminate();
|
||||
}
|
||||
|
||||
void GumpNotifyProcess::terminate() {
|
||||
Process::terminate();
|
||||
|
||||
if (_gump) {
|
||||
Gump *g = Ultima8::getGump(_gump);
|
||||
assert(g);
|
||||
g->Close();
|
||||
}
|
||||
}
|
||||
|
||||
void GumpNotifyProcess::run() {
|
||||
}
|
||||
|
||||
Common::String GumpNotifyProcess::dumpInfo() const {
|
||||
return Process::dumpInfo() +
|
||||
Common::String::format(", gump: %u", _gump);
|
||||
}
|
||||
|
||||
void GumpNotifyProcess::saveData(Common::WriteStream *ws) {
|
||||
Process::saveData(ws);
|
||||
|
||||
ws->writeUint16LE(_gump);
|
||||
}
|
||||
|
||||
bool GumpNotifyProcess::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
if (!Process::loadData(rs, version)) return false;
|
||||
|
||||
_gump = rs->readUint16LE();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
63
engines/ultima/ultima8/gumps/gump_notify_process.h
Normal file
63
engines/ultima/ultima8/gumps/gump_notify_process.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_GUMPNOTIFYPROCESS_H
|
||||
#define ULTIMA8_GUMPS_GUMPNOTIFYPROCESS_H
|
||||
|
||||
#include "ultima/ultima8/kernel/process.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class Gump;
|
||||
|
||||
class GumpNotifyProcess : public Process {
|
||||
uint16 _gump;
|
||||
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
GumpNotifyProcess();
|
||||
GumpNotifyProcess(uint16 it);
|
||||
~GumpNotifyProcess() override;
|
||||
|
||||
void setGump(Gump *g);
|
||||
uint16 getGump() const {
|
||||
return _gump;
|
||||
}
|
||||
|
||||
virtual void notifyClosing(int res);
|
||||
|
||||
void terminate() override;
|
||||
|
||||
void run() override;
|
||||
|
||||
Common::String dumpInfo() const override;
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
138
engines/ultima/ultima8/gumps/inverter_gump.cpp
Normal file
138
engines/ultima/ultima8/gumps/inverter_gump.cpp
Normal file
@@ -0,0 +1,138 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/inverter_gump.h"
|
||||
|
||||
#include "ultima/ultima8/gfx/render_surface.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(InverterGump)
|
||||
|
||||
InverterGump::InverterGump(int32 x, int32 y, int32 width, int32 height)
|
||||
: DesktopGump(x, y, width, height) {
|
||||
_buffer = nullptr;
|
||||
}
|
||||
|
||||
InverterGump::~InverterGump() {
|
||||
delete _buffer;
|
||||
}
|
||||
|
||||
static inline int getLine(int index, int n) {
|
||||
index = index % (2 * n);
|
||||
|
||||
if (index >= n)
|
||||
return 2 * n - 1 - 2 * (index - n);
|
||||
else
|
||||
return 2 * index;
|
||||
}
|
||||
|
||||
static inline int getIndex(int line, int n) {
|
||||
if (line % 2 == 0)
|
||||
return line / 2;
|
||||
else
|
||||
return 2 * n - 1 - (line / 2);
|
||||
}
|
||||
|
||||
void InverterGump::Paint(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
// Skip the clipping rect/origin setting, since they will already be set
|
||||
// correctly by our parent.
|
||||
// (Or maybe I'm just to lazy to figure out the correct coordinates
|
||||
// to use to compensate for the flipping... -wjp :-) )
|
||||
|
||||
// Don't paint if hidden
|
||||
if (IsHidden()) return;
|
||||
|
||||
// Paint This
|
||||
PaintThis(surf, lerp_factor, scaled);
|
||||
|
||||
// Paint children
|
||||
PaintChildren(surf, lerp_factor, scaled);
|
||||
}
|
||||
|
||||
|
||||
void InverterGump::PaintChildren(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
unsigned int state = Ultima8Engine::get_instance()->getInversion();
|
||||
|
||||
if (state == 0) {
|
||||
DesktopGump::PaintChildren(surf, lerp_factor, scaled);
|
||||
return;
|
||||
} else if (state == 0x8000) {
|
||||
bool old_flipped = surf->IsFlipped();
|
||||
surf->SetFlipped(!old_flipped);
|
||||
|
||||
DesktopGump::PaintChildren(surf, lerp_factor, scaled);
|
||||
|
||||
surf->SetFlipped(old_flipped);
|
||||
return;
|
||||
}
|
||||
|
||||
int width = _dims.width(), height = _dims.height();
|
||||
|
||||
|
||||
// need a backbuffer
|
||||
if (!_buffer) {
|
||||
Graphics::Screen *screen = Ultima8Engine::get_instance()->getScreen();
|
||||
_buffer = new RenderSurface(width, height, screen->format);
|
||||
}
|
||||
|
||||
_buffer->BeginPainting();
|
||||
DesktopGump::PaintChildren(_buffer, lerp_factor, scaled);
|
||||
_buffer->EndPainting();
|
||||
|
||||
// now invert-blit _buffer to screen
|
||||
int t = (state * height) / 0x10000;
|
||||
|
||||
for (int i = 0; i < height; ++i) {
|
||||
int src = getLine(getIndex(i, height / 2) + t, height / 2);
|
||||
Common::Rect srcRect(0, src, width, src + 1);
|
||||
surf->Blit(*_buffer->getRawSurface(), srcRect, 0, i);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert a parent relative point to a gump point
|
||||
void InverterGump::ParentToGump(int32 &px, int32 &py, PointRoundDir) {
|
||||
px -= _x;
|
||||
px += _dims.left;
|
||||
py -= _y;
|
||||
if (Ultima8Engine::get_instance()->isInverted()) py = _dims.height() - py - 1;
|
||||
py += _dims.top;
|
||||
}
|
||||
|
||||
// Convert a gump point to parent relative point
|
||||
void InverterGump::GumpToParent(int32 &gx, int32 &gy, PointRoundDir) {
|
||||
gx -= _dims.left;
|
||||
gx += _x;
|
||||
gy -= _dims.top;
|
||||
if (Ultima8Engine::get_instance()->isInverted()) gy = _dims.height() - gy - 1;
|
||||
gy += _y;
|
||||
}
|
||||
|
||||
void InverterGump::RenderSurfaceChanged() {
|
||||
DesktopGump::RenderSurfaceChanged();
|
||||
delete _buffer;
|
||||
_buffer = nullptr;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
60
engines/ultima/ultima8/gumps/inverter_gump.h
Normal file
60
engines/ultima/ultima8/gumps/inverter_gump.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_INVERTERGUMP_H
|
||||
#define ULTIMA8_GUMPS_INVERTERGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/desktop_gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class RenderSurface;
|
||||
|
||||
/**
|
||||
* A gump to vertically invert the desktop contents - happens when certain switches in the game are switched.
|
||||
*/
|
||||
class InverterGump : public DesktopGump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
InverterGump(int32 x, int32 y, int32 width, int32 height);
|
||||
~InverterGump() override;
|
||||
|
||||
void Paint(RenderSurface *surf, int32 lerp_factor, bool scaled) override;
|
||||
void PaintChildren(RenderSurface *surf, int32 lerp_factor, bool scaled) override;
|
||||
|
||||
void ParentToGump(int32 &px, int32 &py,
|
||||
PointRoundDir r = ROUND_TOPLEFT) override;
|
||||
void GumpToParent(int32 &gx, int32 &gy,
|
||||
PointRoundDir r = ROUND_TOPLEFT) override;
|
||||
|
||||
void RenderSurfaceChanged() override;
|
||||
|
||||
protected:
|
||||
RenderSurface *_buffer;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
187
engines/ultima/ultima8/gumps/item_relative_gump.cpp
Normal file
187
engines/ultima/ultima8/gumps/item_relative_gump.cpp
Normal file
@@ -0,0 +1,187 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/item_relative_gump.h"
|
||||
#include "ultima/ultima8/gumps/game_map_gump.h"
|
||||
#include "ultima/ultima8/world/container.h"
|
||||
#include "ultima/ultima8/world/get_object.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(ItemRelativeGump)
|
||||
|
||||
ItemRelativeGump::ItemRelativeGump() : Gump(), _ix(0), _iy(0) {
|
||||
}
|
||||
|
||||
ItemRelativeGump::ItemRelativeGump(int32 x, int32 y, int32 width, int32 height,
|
||||
uint16 owner, uint32 flags, int32 layer)
|
||||
: Gump(x, y, width, height, owner, flags, layer), _ix(0), _iy(0) {
|
||||
}
|
||||
|
||||
ItemRelativeGump::~ItemRelativeGump(void) {
|
||||
}
|
||||
|
||||
void ItemRelativeGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
Gump::InitGump(newparent, take_focus);
|
||||
|
||||
GetItemLocation(0);
|
||||
|
||||
if (!newparent && _parent)
|
||||
MoveOnScreen();
|
||||
}
|
||||
|
||||
void ItemRelativeGump::MoveOnScreen() {
|
||||
assert(_parent);
|
||||
Common::Rect32 sd = _parent->getDims();
|
||||
|
||||
// first move back to our desired location
|
||||
_x = 0;
|
||||
_y = 0;
|
||||
|
||||
// get rectangle that gump occupies in desktops's coordinate space
|
||||
int32 left, right, top, bottom;
|
||||
left = -_dims.left;
|
||||
right = left + _dims.width();
|
||||
top = -_dims.top;
|
||||
bottom = top + _dims.height();
|
||||
GumpToParent(left, top);
|
||||
GumpToParent(right, bottom);
|
||||
|
||||
int32 movex = 0, movey = 0;
|
||||
|
||||
if (left < -sd.left)
|
||||
movex = -sd.left - left;
|
||||
else if (right > -sd.left + sd.width())
|
||||
movex = -sd.left + sd.width() - right;
|
||||
|
||||
if (top < -sd.top)
|
||||
movey = -sd.top - top;
|
||||
else if (bottom > -sd.top + sd.height())
|
||||
movey = -sd.top + sd.height() - bottom;
|
||||
|
||||
Move(left + movex, top + movey);
|
||||
}
|
||||
|
||||
// Paint the Gump (RenderSurface is relative to parent).
|
||||
// Calls PaintThis and PaintChildren
|
||||
void ItemRelativeGump::Paint(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
GetItemLocation(lerp_factor);
|
||||
Gump::Paint(surf, lerp_factor, scaled);
|
||||
}
|
||||
|
||||
|
||||
// Convert a parent relative point to a gump point
|
||||
void ItemRelativeGump::ParentToGump(int32 &px, int32 &py, PointRoundDir r) {
|
||||
px -= _ix;
|
||||
py -= _iy;
|
||||
Gump::ParentToGump(px, py, r);
|
||||
}
|
||||
|
||||
// Convert a gump point to parent relative point
|
||||
void ItemRelativeGump::GumpToParent(int32 &gx, int32 &gy, PointRoundDir r) {
|
||||
Gump::GumpToParent(gx, gy, r);
|
||||
gx += _ix;
|
||||
gy += _iy;
|
||||
}
|
||||
|
||||
void ItemRelativeGump::GetItemLocation(int32 lerp_factor) {
|
||||
Gump *gump = nullptr;
|
||||
|
||||
Item *it = getItem(_owner);
|
||||
|
||||
if (!it) {
|
||||
// This shouldn't ever happen, the GumpNotifyProcess should
|
||||
// close us before we get here
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
Item *next;
|
||||
Item *prev = nullptr;
|
||||
while ((next = it->getParentAsContainer()) != nullptr) {
|
||||
prev = it;
|
||||
it = next;
|
||||
gump = getGump(it->getGump());
|
||||
if (gump) break;
|
||||
}
|
||||
|
||||
int32 gx, gy;
|
||||
bool found;
|
||||
|
||||
if (!gump) {
|
||||
gump = GetRootGump()->FindGump<GameMapGump>();
|
||||
|
||||
if (!gump) {
|
||||
warning("ItemRelativeGump::GetItemLocation(): Unable to find GameMapGump");
|
||||
return;
|
||||
}
|
||||
|
||||
found = gump->GetLocationOfItem(_owner, gx, gy, lerp_factor);
|
||||
} else {
|
||||
assert(prev);
|
||||
found = gump->GetLocationOfItem(prev->getObjId(), gx, gy, lerp_factor);
|
||||
}
|
||||
|
||||
if (found) {
|
||||
// Convert the GumpSpaceCoord relative to the world/item gump
|
||||
// into screenspace coords
|
||||
gy = gy - it->getShapeInfo()->_z * 8 - 16;
|
||||
} else {
|
||||
// If location not found show near bottom center
|
||||
Common::Rect32 r = gump->getDims();
|
||||
gx = (r.left + r.right) / 2;
|
||||
gy = r.bottom - 8;
|
||||
}
|
||||
|
||||
gump->GumpToScreenSpace(gx, gy);
|
||||
|
||||
// Convert the screenspace coords into the coords of us
|
||||
if (_parent)
|
||||
_parent->ScreenSpaceToGump(gx, gy);
|
||||
|
||||
// Set x and y, and center us over it
|
||||
_ix = gx - _dims.width() / 2;
|
||||
_iy = gy - _dims.height();
|
||||
|
||||
|
||||
if (_flags & FLAG_KEEP_VISIBLE)
|
||||
MoveOnScreen();
|
||||
}
|
||||
|
||||
void ItemRelativeGump::Move(int32 x, int32 y) {
|
||||
ParentToGump(x, y);
|
||||
_x += x;
|
||||
_y += y;
|
||||
}
|
||||
|
||||
void ItemRelativeGump::saveData(Common::WriteStream *ws) {
|
||||
Gump::saveData(ws);
|
||||
}
|
||||
|
||||
bool ItemRelativeGump::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
if (!Gump::loadData(rs, version)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
71
engines/ultima/ultima8/gumps/item_relative_gump.h
Normal file
71
engines/ultima/ultima8/gumps/item_relative_gump.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_ITEMRELATIVEGUMP_H
|
||||
#define ULTIMA8_GUMPS_ITEMRELATIVEGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/**
|
||||
* Base class for gumps whose location is relative to an owning item (eg, inventory, bark, etc)
|
||||
*/
|
||||
class ItemRelativeGump : public Gump {
|
||||
protected:
|
||||
int32 _ix, _iy;
|
||||
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
ItemRelativeGump();
|
||||
ItemRelativeGump(int32 x, int32 y, int32 width, int32 height, uint16 owner, uint32 flags = 0, int32 layer = LAYER_NORMAL);
|
||||
~ItemRelativeGump() override;
|
||||
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
|
||||
// Paint the Gump (RenderSurface is relative to parent).
|
||||
// Calls PaintThis and PaintChildren.
|
||||
void Paint(RenderSurface *, int32 lerp_factor, bool scaled) override;
|
||||
|
||||
void ParentToGump(int32 &px, int32 &py,
|
||||
PointRoundDir r = ROUND_TOPLEFT) override;
|
||||
void GumpToParent(int32 &gx, int32 &gy,
|
||||
PointRoundDir r = ROUND_TOPLEFT) override;
|
||||
|
||||
void Move(int32 x, int32 y) override;
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
protected:
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
|
||||
virtual void GetItemLocation(int32 lerp_factor);
|
||||
|
||||
//! Move Gump so that it totally overlaps parent.
|
||||
void MoveOnScreen();
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
268
engines/ultima/ultima8/gumps/keypad_gump.cpp
Normal file
268
engines/ultima/ultima8/gumps/keypad_gump.cpp
Normal file
@@ -0,0 +1,268 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/events.h"
|
||||
|
||||
#include "ultima/ultima8/audio/audio_process.h"
|
||||
#include "ultima/ultima8/gumps/keypad_gump.h"
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/gfx/gump_shape_archive.h"
|
||||
#include "ultima/ultima8/kernel/kernel.h"
|
||||
#include "ultima/ultima8/kernel/mouse.h"
|
||||
#include "ultima/ultima8/gumps/widgets/button_widget.h"
|
||||
#include "ultima/ultima8/usecode/uc_process.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(KeypadGump)
|
||||
|
||||
static const int TXT_CONTAINER_IDX = 0x100;
|
||||
// Actually the max val where we will allow another digit to be entered
|
||||
static const int MAX_CODE_VAL = 9999999;
|
||||
static const int CHEAT_CODE_VAL = 74697689;
|
||||
|
||||
static const uint16 SFXNO_BUTTON = 0x3b;
|
||||
static const uint16 SFXNO_CORRECT = 0x32;
|
||||
static const uint16 SFXNO_WRONG = 0x31;
|
||||
static const uint16 SFXNO_DEL = 0x3a;
|
||||
|
||||
|
||||
KeypadGump::KeypadGump(int targetValue, uint16 ucnotifypid): ModalGump(0, 0, 5, 5),
|
||||
_value(0), _targetValue(targetValue), _ucNotifyPid(ucnotifypid) {
|
||||
Mouse *mouse = Mouse::get_instance();
|
||||
mouse->pushMouseCursor(Mouse::MOUSE_HAND);
|
||||
for (int i = 0; i < 12; i++) {
|
||||
_buttons[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
KeypadGump::~KeypadGump() {
|
||||
Mouse::get_instance()->popMouseCursor();
|
||||
}
|
||||
|
||||
void KeypadGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
ModalGump::InitGump(newparent, take_focus);
|
||||
|
||||
_shape = GameData::get_instance()->getGumps()->getShape(10);
|
||||
UpdateDimsFromShape();
|
||||
|
||||
static const int buttonShapeNum = 11;
|
||||
static const uint16 xoffs[] = {0xc, 0x27, 0x42};
|
||||
static const uint16 yoffs[] = {0x19, 0x32, 0x4a, 0x62};
|
||||
|
||||
for (int y = 0; y < 4; y++) {
|
||||
for (int x = 0; x < 3; x++) {
|
||||
int bnum = y * 3 + x;
|
||||
FrameID button_up(GameData::GUMPS, buttonShapeNum, bnum);
|
||||
FrameID button_down(GameData::GUMPS, buttonShapeNum, bnum + 12);
|
||||
Gump *widget = new ButtonWidget(xoffs[x], yoffs[y], button_up, button_down);
|
||||
widget->InitGump(this);
|
||||
widget->SetIndex(bnum);
|
||||
_buttons[bnum] = widget->getObjId();
|
||||
}
|
||||
}
|
||||
// Default result is 0xff
|
||||
SetResult(0xff);
|
||||
}
|
||||
|
||||
void KeypadGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
Gump::PaintThis(surf, lerp_factor, scaled);
|
||||
}
|
||||
|
||||
bool KeypadGump::OnKeyDown(int key, int mod) {
|
||||
uint16 sfxno = 0;
|
||||
bool shouldclose = false;
|
||||
|
||||
switch (key) {
|
||||
case Common::KEYCODE_ESCAPE:
|
||||
_value = -1;
|
||||
shouldclose = true;
|
||||
break;
|
||||
case Common::KEYCODE_BACKSPACE:
|
||||
_value /= 10;
|
||||
sfxno = SFXNO_DEL;
|
||||
break;
|
||||
case Common::KEYCODE_RETURN:
|
||||
if (_value == _targetValue || _value == CHEAT_CODE_VAL) {
|
||||
sfxno = SFXNO_CORRECT;
|
||||
_value = _targetValue;
|
||||
SetResult(_targetValue);
|
||||
} else {
|
||||
// wrong.
|
||||
sfxno = SFXNO_WRONG;
|
||||
SetResult(0);
|
||||
}
|
||||
shouldclose = true;
|
||||
break;
|
||||
case Common::KEYCODE_0:
|
||||
case Common::KEYCODE_1:
|
||||
case Common::KEYCODE_2:
|
||||
case Common::KEYCODE_3:
|
||||
case Common::KEYCODE_4:
|
||||
case Common::KEYCODE_5:
|
||||
case Common::KEYCODE_6:
|
||||
case Common::KEYCODE_7:
|
||||
case Common::KEYCODE_8:
|
||||
case Common::KEYCODE_9:
|
||||
onDigit(key - (int)Common::KEYCODE_0);
|
||||
updateDigitDisplay();
|
||||
sfxno = SFXNO_BUTTON;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
AudioProcess *audio = AudioProcess::get_instance();
|
||||
if (audio && sfxno)
|
||||
audio->playSFX(sfxno, 0x10, _objId, 1);
|
||||
|
||||
if (shouldclose)
|
||||
Close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void KeypadGump::onDigit(int digit) {
|
||||
assert(digit >= 0 && digit <= 9);
|
||||
if (_value < MAX_CODE_VAL) {
|
||||
_value *= 10;
|
||||
_value += digit;
|
||||
}
|
||||
}
|
||||
|
||||
void KeypadGump::ChildNotify(Gump *child, uint32 message) {
|
||||
bool update = true;
|
||||
bool shouldclose = false;
|
||||
if (message == ButtonWidget::BUTTON_CLICK) {
|
||||
uint16 sfxno = SFXNO_BUTTON;
|
||||
int buttonNo = child->GetIndex();
|
||||
if (buttonNo < 9) {
|
||||
onDigit(buttonNo + 1);
|
||||
} else if (buttonNo == 10) {
|
||||
onDigit(0);
|
||||
} else if (buttonNo == 9) {
|
||||
// Backspace key
|
||||
_value /= 10;
|
||||
sfxno = SFXNO_DEL;
|
||||
} else if (buttonNo == 11) {
|
||||
update = false;
|
||||
if (_value == _targetValue || _value == CHEAT_CODE_VAL) {
|
||||
sfxno = SFXNO_CORRECT;
|
||||
_value = _targetValue;
|
||||
SetResult(_targetValue);
|
||||
} else {
|
||||
// wrong.
|
||||
sfxno = SFXNO_WRONG;
|
||||
SetResult(0);
|
||||
}
|
||||
shouldclose = true;
|
||||
}
|
||||
AudioProcess *audio = AudioProcess::get_instance();
|
||||
if (audio && sfxno)
|
||||
audio->playSFX(sfxno, 0x10, _objId, 1);
|
||||
}
|
||||
if (update)
|
||||
updateDigitDisplay();
|
||||
if (shouldclose)
|
||||
Close();
|
||||
}
|
||||
|
||||
void KeypadGump::updateDigitDisplay() {
|
||||
Gump *txt = Gump::FindGump(&FindByIndex<TXT_CONTAINER_IDX>);
|
||||
if (txt)
|
||||
txt->Close();
|
||||
txt = new Gump(25, 12, 200, 12);
|
||||
txt->InitGump(this);
|
||||
txt->SetIndex(TXT_CONTAINER_IDX);
|
||||
|
||||
Std::vector<Gump *> digits;
|
||||
Shape *digitshape = GameData::get_instance()->getGumps()->getShape(12);
|
||||
int val = _value;
|
||||
while (val) {
|
||||
int digitval = val % 10;
|
||||
if (digitval == 0)
|
||||
digitval = 10;
|
||||
Gump *digit = new Gump(0, 0, 6, 12);
|
||||
digit->SetShape(digitshape, digitval - 1);
|
||||
digit->InitGump(txt);
|
||||
digits.push_back(digit);
|
||||
val /= 10;
|
||||
}
|
||||
|
||||
int xoff = 0;
|
||||
while (digits.size()) {
|
||||
Gump *digit = digits.back();
|
||||
digits.pop_back();
|
||||
digit->setRelativePosition(TOP_LEFT, xoff);
|
||||
xoff += 6;
|
||||
}
|
||||
}
|
||||
|
||||
void KeypadGump::Close(bool no_del) {
|
||||
_processResult = _value;
|
||||
|
||||
if (_ucNotifyPid) {
|
||||
UCProcess *ucp = dynamic_cast<UCProcess *>(Kernel::get_instance()->getProcess(_ucNotifyPid));
|
||||
assert(ucp);
|
||||
ucp->setReturnValue(_value);
|
||||
ucp->wakeUp(_value);
|
||||
}
|
||||
|
||||
ModalGump::Close(no_del);
|
||||
}
|
||||
|
||||
|
||||
bool KeypadGump::OnTextInput(int unicode) {
|
||||
if (!(unicode & 0xFF80)) {
|
||||
//char c = unicode & 0x7F;
|
||||
// Could also accept numeric keyboard inputs here.
|
||||
// For now we do it in OnKeyDown.
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 KeypadGump::I_showKeypad(const uint8 *args, unsigned int /*argsize*/) {
|
||||
ARG_UINT16(target)
|
||||
|
||||
UCProcess *current = dynamic_cast<UCProcess *>(Kernel::get_instance()->getRunningProcess());
|
||||
assert(current);
|
||||
|
||||
ModalGump *gump = new KeypadGump(target, current->getPid());
|
||||
gump->InitGump(0);
|
||||
gump->setRelativePosition(CENTER);
|
||||
|
||||
current->suspend();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool KeypadGump::loadData(Common::ReadStream *rs) {
|
||||
warning("Trying to load ModalGump");
|
||||
return true;
|
||||
}
|
||||
|
||||
void KeypadGump::saveData(Common::WriteStream *ws) {
|
||||
warning("Trying to save ModalGump");
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
72
engines/ultima/ultima8/gumps/keypad_gump.h
Normal file
72
engines/ultima/ultima8/gumps/keypad_gump.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_KEYPADGUMP_H
|
||||
#define ULTIMA8_GUMPS_KEYPADGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/modal_gump.h"
|
||||
#include "ultima/ultima8/usecode/intrinsics.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/**
|
||||
* The keypad with numbers gump
|
||||
*/
|
||||
class KeypadGump : public ModalGump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
KeypadGump(int targetValue, uint16 ucnotifypid);
|
||||
~KeypadGump() override;
|
||||
|
||||
void Close(bool no_del=false) override;
|
||||
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
|
||||
void PaintThis(RenderSurface *, int32 lerp_factor, bool scaled) override;
|
||||
|
||||
bool OnKeyDown(int key, int mod) override;
|
||||
bool OnTextInput(int unicode) override;
|
||||
void ChildNotify(Gump *child, uint32 message) override;
|
||||
|
||||
INTRINSIC(I_showKeypad);
|
||||
|
||||
bool loadData(Common::ReadStream *rs);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
|
||||
protected:
|
||||
void updateDigitDisplay();
|
||||
|
||||
void onDigit(int digit);
|
||||
|
||||
ObjId _buttons[12];
|
||||
|
||||
int _value;
|
||||
int _targetValue;
|
||||
uint16 _ucNotifyPid;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
64
engines/ultima/ultima8/gumps/main_menu_process.cpp
Normal file
64
engines/ultima/ultima8/gumps/main_menu_process.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "ultima/ultima8/gumps/main_menu_process.h"
|
||||
#include "ultima/ultima8/gumps/menu_gump.h"
|
||||
#include "ultima/ultima8/world/get_object.h"
|
||||
#include "ultima/ultima8/audio/music_process.h"
|
||||
#include "ultima/ultima8/world/actors/main_actor.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(MainMenuProcess)
|
||||
|
||||
MainMenuProcess::MainMenuProcess() : Process() {
|
||||
_flags |= PROC_PREVENT_SAVE;
|
||||
}
|
||||
|
||||
|
||||
void MainMenuProcess::run() {
|
||||
MainActor *avatar = getMainActor();
|
||||
if (avatar && avatar->isDead()) {
|
||||
// stop death music
|
||||
MusicProcess::get_instance()->playCombatMusic(0);
|
||||
}
|
||||
|
||||
MenuGump::showMenu();
|
||||
|
||||
terminate();
|
||||
}
|
||||
|
||||
void MainMenuProcess::saveData(Common::WriteStream *ws) {
|
||||
warning("Attempted save of process with prevent save flag");
|
||||
|
||||
Process::saveData(ws);
|
||||
}
|
||||
|
||||
bool MainMenuProcess::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
if (!Process::loadData(rs, version)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
48
engines/ultima/ultima8/gumps/main_menu_process.h
Normal file
48
engines/ultima/ultima8/gumps/main_menu_process.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_MAINMENUPROCESS_H
|
||||
#define ULTIMA8_GUMPS_MAINMENUPROCESS_H
|
||||
|
||||
#include "ultima/ultima8/kernel/process.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class Item;
|
||||
|
||||
class MainMenuProcess : public Process {
|
||||
public:
|
||||
MainMenuProcess();
|
||||
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
void run() override;
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
286
engines/ultima/ultima8/gumps/menu_gump.cpp
Normal file
286
engines/ultima/ultima8/gumps/menu_gump.cpp
Normal file
@@ -0,0 +1,286 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/config-manager.h"
|
||||
|
||||
#include "ultima/ultima8/gumps/menu_gump.h"
|
||||
#include "ultima/ultima8/gumps/cru_menu_gump.h"
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/gfx/gump_shape_archive.h"
|
||||
#include "ultima/ultima8/gfx/shape.h"
|
||||
#include "ultima/ultima8/gfx/shape_frame.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
#include "ultima/ultima8/kernel/mouse.h"
|
||||
#include "ultima/ultima8/gumps/widgets/button_widget.h"
|
||||
#include "ultima/ultima8/gumps/widgets/text_widget.h"
|
||||
#include "ultima/ultima8/gumps/quit_gump.h"
|
||||
#include "ultima/ultima8/games/game.h"
|
||||
#include "ultima/ultima8/world/actors/main_actor.h"
|
||||
#include "ultima/ultima8/gfx/palette_manager.h"
|
||||
#include "ultima/ultima8/audio/music_process.h"
|
||||
#include "ultima/ultima8/gumps/widgets/edit_widget.h"
|
||||
#include "ultima/ultima8/gumps/u8_save_gump.h"
|
||||
#include "ultima/ultima8/world/get_object.h"
|
||||
#include "ultima/ultima8/metaengine.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(MenuGump)
|
||||
|
||||
MenuGump::MenuGump(bool nameEntryMode)
|
||||
: ModalGump(0, 0, 5, 5, 0, FLAG_DONT_SAVE) {
|
||||
_nameEntryMode = nameEntryMode;
|
||||
|
||||
Mouse *mouse = Mouse::get_instance();
|
||||
if (!_nameEntryMode)
|
||||
mouse->pushMouseCursor(Mouse::MOUSE_HAND);
|
||||
else
|
||||
mouse->pushMouseCursor(Mouse::MOUSE_NONE);
|
||||
|
||||
// Save old music state
|
||||
MusicProcess *musicprocess = MusicProcess::get_instance();
|
||||
if (musicprocess) {
|
||||
musicprocess->saveTrackState();
|
||||
// Stop any playing music.
|
||||
musicprocess->playCombatMusic(0);
|
||||
}
|
||||
|
||||
// Save old palette transform
|
||||
PaletteManager *palman = PaletteManager::get_instance();
|
||||
palman->getTransformMatrix(_oldPalTransform, PaletteManager::Pal_Game);
|
||||
palman->untransformPalette(PaletteManager::Pal_Game);
|
||||
}
|
||||
|
||||
MenuGump::~MenuGump() {
|
||||
}
|
||||
|
||||
|
||||
void MenuGump::Close(bool no_del) {
|
||||
// Restore old music state and palette.
|
||||
// Music state can be changed by the Intro and Credits
|
||||
MusicProcess *musicprocess = MusicProcess::get_instance();
|
||||
if (musicprocess)
|
||||
musicprocess->restoreTrackState();
|
||||
PaletteManager *palman = PaletteManager::get_instance();
|
||||
palman->transformPalette(PaletteManager::Pal_Game, _oldPalTransform);
|
||||
|
||||
Mouse *mouse = Mouse::get_instance();
|
||||
mouse->popMouseCursor();
|
||||
|
||||
ModalGump::Close(no_del);
|
||||
}
|
||||
|
||||
static const int gumpShape = 35;
|
||||
static const int paganShape = 32;
|
||||
static const int menuEntryShape = 37;
|
||||
|
||||
static const char *MENU_TXT[] = {
|
||||
"1.Intro",
|
||||
"2.Read Diary",
|
||||
"3.Write Diary",
|
||||
"4.Options",
|
||||
"5.Credits",
|
||||
"6.Quit",
|
||||
"7.Quotes",
|
||||
"8.End Game"
|
||||
};
|
||||
|
||||
void MenuGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
ModalGump::InitGump(newparent, take_focus);
|
||||
|
||||
_shape = GameData::get_instance()->getGumps()->getShape(gumpShape);
|
||||
UpdateDimsFromShape();
|
||||
|
||||
Shape *logoShape;
|
||||
logoShape = GameData::get_instance()->getGumps()->getShape(paganShape);
|
||||
const ShapeFrame *sf = logoShape->getFrame(0);
|
||||
assert(sf);
|
||||
|
||||
Gump *logo = new Gump(42, 10, sf->_width, sf->_height);
|
||||
logo->SetShape(logoShape, 0);
|
||||
logo->InitGump(this, false);
|
||||
|
||||
if (!_nameEntryMode) {
|
||||
bool endgame = ConfMan.getBool("endgame");
|
||||
bool quotes = ConfMan.getBool("quotes");
|
||||
|
||||
int x = _dims.width() / 2 + 14;
|
||||
int y = 18;
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
if ((quotes || i != 6) && (endgame || i != 7)) {
|
||||
FrameID frame_up(GameData::GUMPS, menuEntryShape, i * 2);
|
||||
FrameID frame_down(GameData::GUMPS, menuEntryShape, i * 2 + 1);
|
||||
frame_up = _TL_SHP_(frame_up);
|
||||
frame_down = _TL_SHP_(frame_down);
|
||||
Gump *widget;
|
||||
if (frame_up._shapeNum) {
|
||||
widget = new ButtonWidget(x, y, frame_up, frame_down, true);
|
||||
} else {
|
||||
// JA U8 has text labels
|
||||
widget = new ButtonWidget(x, y, _TL_(MENU_TXT[i]), true, 0);
|
||||
}
|
||||
widget->InitGump(this, false);
|
||||
widget->SetIndex(i + 1);
|
||||
}
|
||||
|
||||
y += 14;
|
||||
}
|
||||
|
||||
const MainActor *av = getMainActor();
|
||||
Std::string name;
|
||||
if (av)
|
||||
name = av->getName();
|
||||
|
||||
if (!name.empty()) {
|
||||
Gump *widget = new TextWidget(0, 0, name, true, 6);
|
||||
widget->InitGump(this, false);
|
||||
Common::Rect32 rect = widget->getDims();
|
||||
widget->Move(90 - rect.width() / 2, _dims.height() - 40);
|
||||
}
|
||||
} else {
|
||||
Gump *widget;
|
||||
widget = new TextWidget(0, 0, _TL_("Give thy name:"), true, 6); // CONSTANT!
|
||||
widget->InitGump(this, false);
|
||||
widget->Move(_dims.width() / 2 + 6, 10);
|
||||
|
||||
Common::Rect32 textdims = widget->getDims();
|
||||
|
||||
widget = new EditWidget(0, 0, "", true, 6, 110, 40, 15); // CONSTANTS!
|
||||
widget->InitGump(this, true);
|
||||
widget->Move(_dims.width() / 2 + 6, 10 + textdims.height());
|
||||
widget->MakeFocus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MenuGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
Gump::PaintThis(surf, lerp_factor, scaled);
|
||||
}
|
||||
|
||||
void MenuGump::onMouseDouble(int button, int32 mx, int32 my) {
|
||||
// FIXME: this check should probably be in Game or GUIApp
|
||||
MainActor *av = getMainActor();
|
||||
if (av && !av->hasActorFlags(Actor::ACT_DEAD))
|
||||
Close(); // don't allow closing if dead/game over
|
||||
}
|
||||
|
||||
bool MenuGump::OnKeyDown(int key, int mod) {
|
||||
if (Gump::OnKeyDown(key, mod)) return true;
|
||||
|
||||
if (!_nameEntryMode) {
|
||||
|
||||
if (key == Common::KEYCODE_ESCAPE) {
|
||||
// FIXME: this check should probably be in Game or GUIApp
|
||||
MainActor *av = getMainActor();
|
||||
if (av && !av->hasActorFlags(Actor::ACT_DEAD))
|
||||
Close(); // don't allow closing if dead/game over
|
||||
} else if (key >= Common::KEYCODE_1 && key <= Common::KEYCODE_9) {
|
||||
selectEntry(key - Common::KEYCODE_1 + 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MenuGump::ChildNotify(Gump *child, uint32 message) {
|
||||
EditWidget *editwidget = dynamic_cast<EditWidget *>(child);
|
||||
if (editwidget && message == EditWidget::EDIT_ENTER) {
|
||||
Std::string name = editwidget->getText();
|
||||
if (!name.empty()) {
|
||||
MainActor *av = getMainActor();
|
||||
av->setName(name);
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
ButtonWidget *buttonWidget = dynamic_cast<ButtonWidget *>(child);
|
||||
if (buttonWidget) {
|
||||
if (message == ButtonWidget::BUTTON_CLICK || message == ButtonWidget::BUTTON_DOUBLE) {
|
||||
selectEntry(buttonWidget->GetIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MenuGump::selectEntry(int entry) {
|
||||
bool endgame = ConfMan.getBool("endgame");
|
||||
bool quotes = ConfMan.getBool("quotes");
|
||||
|
||||
switch (entry) {
|
||||
case 1: // Intro
|
||||
Game::get_instance()->playIntroMovie(true);
|
||||
break;
|
||||
case 2:
|
||||
case 3: // Read/Write Diary
|
||||
U8SaveGump::showLoadSaveGump(this, entry == 3);
|
||||
break;
|
||||
case 4: {
|
||||
Ultima8Engine::get_instance()->openConfigDialog();
|
||||
}
|
||||
break;
|
||||
case 5: // Credits
|
||||
Game::get_instance()->playCredits();
|
||||
break;
|
||||
case 6: // Quit
|
||||
QuitGump::verifyQuit();
|
||||
break;
|
||||
case 7: // Quotes
|
||||
if (quotes) Game::get_instance()->playQuotes();
|
||||
break;
|
||||
case 8: // End Game
|
||||
if (endgame) Game::get_instance()->playEndgameMovie(true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool MenuGump::OnTextInput(int unicode) {
|
||||
if (Gump::OnTextInput(unicode)) return true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//static
|
||||
void MenuGump::showMenu() {
|
||||
ModalGump *gump;
|
||||
if (GAME_IS_U8)
|
||||
gump = new MenuGump();
|
||||
else
|
||||
gump = new CruMenuGump();
|
||||
gump->InitGump(0);
|
||||
gump->setRelativePosition(CENTER);
|
||||
}
|
||||
|
||||
//static
|
||||
void MenuGump::inputName() {
|
||||
ModalGump *gump;
|
||||
if (GAME_IS_U8)
|
||||
gump = new MenuGump(true);
|
||||
else
|
||||
gump = new CruMenuGump();
|
||||
gump->InitGump(0);
|
||||
gump->setRelativePosition(CENTER);
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
69
engines/ultima/ultima8/gumps/menu_gump.h
Normal file
69
engines/ultima/ultima8/gumps/menu_gump.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_MENUGUMP_H
|
||||
#define ULTIMA8_GUMPS_MENUGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/modal_gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class RenderedText;
|
||||
|
||||
/**
|
||||
* The game menu - with entries like Read Diary, Write Diary, Credits, etc.
|
||||
*/
|
||||
class MenuGump : public ModalGump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
MenuGump(bool nameEntryMode = false);
|
||||
~MenuGump() override;
|
||||
|
||||
// Init the gump, call after construction
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
void Close(bool no_del = false) override;
|
||||
|
||||
// Paint the Gump
|
||||
void PaintThis(RenderSurface *, int32 lerp_factor, bool scaled) override;
|
||||
|
||||
void onMouseDouble(int button, int32 mx, int32 my) override;
|
||||
bool OnKeyDown(int key, int mod) override;
|
||||
bool OnTextInput(int unicode) override;
|
||||
void ChildNotify(Gump *child, uint32 message) override;
|
||||
|
||||
static void showMenu();
|
||||
|
||||
static void inputName();
|
||||
|
||||
protected:
|
||||
bool _nameEntryMode;
|
||||
int16 _oldPalTransform[12];
|
||||
|
||||
virtual void selectEntry(int entry);
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
168
engines/ultima/ultima8/gumps/message_box_gump.cpp
Normal file
168
engines/ultima/ultima8/gumps/message_box_gump.cpp
Normal file
@@ -0,0 +1,168 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/message_box_gump.h"
|
||||
#include "ultima/ultima8/gumps/widgets/text_widget.h"
|
||||
#include "ultima/ultima8/gumps/widgets/button_widget.h"
|
||||
#include "ultima/ultima8/gumps/gump_notify_process.h"
|
||||
#include "ultima/ultima8/gfx/fonts/font_manager.h"
|
||||
#include "ultima/ultima8/kernel/mouse.h"
|
||||
#include "ultima/ultima8/gfx/render_surface.h"
|
||||
#include "ultima/ultima8/gfx/texture.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(MessageBoxGump)
|
||||
|
||||
MessageBoxGump::MessageBoxGump()
|
||||
: ModalGump(), _titleColour(TEX32_PACK_RGB(0, 0, 0)) {
|
||||
|
||||
}
|
||||
|
||||
MessageBoxGump::MessageBoxGump(const Std::string &title, const Std::string &message, uint32 titleColour,
|
||||
Std::vector<Std::string> *buttons) :
|
||||
ModalGump(0, 0, 100, 100), _title(title), _message(message), _titleColour(titleColour) {
|
||||
if (buttons)
|
||||
buttons->swap(_buttons);
|
||||
|
||||
if (_buttons.empty())
|
||||
_buttons.push_back(Std::string("Ok"));
|
||||
}
|
||||
|
||||
MessageBoxGump::~MessageBoxGump(void) {
|
||||
}
|
||||
|
||||
#define MBG_PADDING 16
|
||||
|
||||
void MessageBoxGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
ModalGump::InitGump(newparent, take_focus);
|
||||
|
||||
// work out sizes of the text
|
||||
Font *font = FontManager::get_instance()->getTTFont(0);
|
||||
|
||||
int32 width, height;
|
||||
unsigned int rem;
|
||||
|
||||
// Title width
|
||||
font->getStringSize(_title, width, height);
|
||||
int title_w = width;
|
||||
|
||||
// Width of _buttons
|
||||
int buttons_w = MBG_PADDING;
|
||||
for (size_t i = 0; i < _buttons.size(); i++) {
|
||||
width = height = 0;
|
||||
font->getStringSize(_buttons[i], width, height);
|
||||
buttons_w += width + MBG_PADDING;
|
||||
}
|
||||
|
||||
// Message size
|
||||
font->getTextSize(_message, width, height, rem);
|
||||
|
||||
_dims.setWidth(MBG_PADDING + width + MBG_PADDING);
|
||||
if (_dims.width() < MBG_PADDING + title_w + MBG_PADDING) _dims.setWidth(MBG_PADDING + title_w + MBG_PADDING);
|
||||
if (_dims.width() < buttons_w) _dims.setWidth(buttons_w);
|
||||
|
||||
_dims.setHeight(23 + MBG_PADDING + height + MBG_PADDING + 28);
|
||||
|
||||
// Title
|
||||
Gump *w = new TextWidget(MBG_PADDING, 2, _title, false, 0);
|
||||
w->InitGump(this, false);
|
||||
|
||||
// Message
|
||||
w = new TextWidget(MBG_PADDING, 23 + MBG_PADDING, _message, false, 0, width, height);
|
||||
w->InitGump(this, false);
|
||||
|
||||
// Buttons (right aligned)
|
||||
int off = _dims.width() - buttons_w;
|
||||
for (size_t i = 0; i < _buttons.size(); i++) {
|
||||
w = new ButtonWidget(off, _dims.height() - 23, _buttons[i], false, 1, TEX32_PACK_RGBA(0xD0, 0x00, 0xD0, 0x80));
|
||||
w->SetIndex(static_cast<int32>(i));
|
||||
w->InitGump(this, false);
|
||||
width = height = 0;
|
||||
font->getStringSize(_buttons[i], width, height);
|
||||
off += width + MBG_PADDING;
|
||||
}
|
||||
|
||||
Mouse *mouse = Mouse::get_instance();
|
||||
mouse->pushMouseCursor(Mouse::MOUSE_HAND);
|
||||
}
|
||||
|
||||
void MessageBoxGump::Close(bool no_del) {
|
||||
Mouse *mouse = Mouse::get_instance();
|
||||
mouse->popMouseCursor();
|
||||
|
||||
ModalGump::Close(no_del);
|
||||
}
|
||||
|
||||
void MessageBoxGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool /*scaled*/) {
|
||||
// Background is partially transparent
|
||||
surf->fillBlended(TEX32_PACK_RGBA(0, 0, 0, 0x80), _dims);
|
||||
|
||||
uint32 color = TEX32_PACK_RGB(0xFF, 0xFF, 0xFF);
|
||||
if (!IsFocus())
|
||||
color = TEX32_PACK_RGB(0x7F, 0x7F, 0x7F);
|
||||
|
||||
// outer border
|
||||
surf->fill32(color, 0, 0, _dims.width(), 1);
|
||||
surf->fill32(color, 0, 0, 1, _dims.height());
|
||||
surf->fill32(color, 0, _dims.height() - 1, _dims.width(), 1);
|
||||
surf->fill32(color, _dims.width() - 1, 0, 1, _dims.height());
|
||||
|
||||
// line above _buttons
|
||||
surf->fill32(color, 0, _dims.height() - 28, _dims.width(), 1);
|
||||
|
||||
// line below _title
|
||||
surf->fill32(color, 0, 23, _dims.width(), 1);
|
||||
|
||||
// Highlight behind _message
|
||||
color = IsFocus() ? _titleColour : TEX32_PACK_RGB(0, 0, 0);
|
||||
surf->fill32(color, 1, 1, _dims.width() - 2, 22);
|
||||
}
|
||||
|
||||
void MessageBoxGump::ChildNotify(Gump *child, uint32 msg) {
|
||||
ButtonWidget *buttonWidget = dynamic_cast<ButtonWidget *>(child);
|
||||
if (buttonWidget && (msg == ButtonWidget::BUTTON_CLICK || msg == ButtonWidget::BUTTON_DOUBLE)) {
|
||||
_processResult = child->GetIndex();
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
ProcId MessageBoxGump::Show(Std::string _title, Std::string _message, uint32 titleColour, Std::vector<Std::string> *_buttons) {
|
||||
Gump *gump = new MessageBoxGump(_title, _message, titleColour, _buttons);
|
||||
gump->InitGump(0);
|
||||
gump->setRelativePosition(CENTER);
|
||||
gump->CreateNotifier();
|
||||
return gump->GetNotifyProcess()->getPid();
|
||||
}
|
||||
|
||||
void MessageBoxGump::saveData(Common::WriteStream *ws) {
|
||||
warning("Trying to save ModalGump");
|
||||
}
|
||||
|
||||
bool MessageBoxGump::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
warning("Trying to load ModalGump");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
78
engines/ultima/ultima8/gumps/message_box_gump.h
Normal file
78
engines/ultima/ultima8/gumps/message_box_gump.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_MESSAGEBOXGUMP_H
|
||||
#define ULTIMA8_GUMPS_MESSAGEBOXGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/modal_gump.h"
|
||||
#include "ultima/ultima8/usecode/intrinsics.h"
|
||||
|
||||
#include "ultima/shared/std/string.h"
|
||||
#include "ultima/shared/std/containers.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
#include "ultima/ultima8/gfx/texture.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/**
|
||||
* A modal message box (for errors, etc)
|
||||
* In Crusader, this should be used for things like the "Targeting reticle [in]active." message
|
||||
*/
|
||||
class MessageBoxGump : public ModalGump {
|
||||
Std::string _title;
|
||||
Std::string _message;
|
||||
Std::vector<Std::string> _buttons;
|
||||
int _titleColour;
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
MessageBoxGump();
|
||||
MessageBoxGump(const Std::string &title, const Std::string &message, uint32 title_colour, Std::vector<Std::string> *buttons);
|
||||
~MessageBoxGump() override;
|
||||
|
||||
// Init the gump, call after construction
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
void Close(bool no_del = false) override;
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
|
||||
void PaintThis(RenderSurface *, int32 lerp_factor, bool scaled) override;
|
||||
|
||||
//! Create a Message Box
|
||||
//! \param title Title of the message box
|
||||
//! \param message Message to be displayed in box
|
||||
//! \param titleColour The colour to be displayed behind the title bar
|
||||
//! \param buttons Array of button names to be displayed. Default is "Ok"
|
||||
//! \return Pid of process that will have the result when finished
|
||||
static ProcId Show(Std::string title, Std::string message, uint32 titleColour, Std::vector<Std::string> *buttons = 0);
|
||||
static ProcId Show(Std::string title, Std::string message, Std::vector<Std::string> *buttons) {
|
||||
return Show(title, message, TEX32_PACK_RGB(0x30, 0x30, 0x8F), buttons);
|
||||
}
|
||||
|
||||
void ChildNotify(Gump *child, uint32 msg) override;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
137
engines/ultima/ultima8/gumps/mini_stats_gump.cpp
Normal file
137
engines/ultima/ultima8/gumps/mini_stats_gump.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/mini_stats_gump.h"
|
||||
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/gfx/gump_shape_archive.h"
|
||||
#include "ultima/ultima8/gfx/palette.h"
|
||||
#include "ultima/ultima8/gfx/palette_manager.h"
|
||||
#include "ultima/ultima8/world/actors/main_actor.h"
|
||||
#include "ultima/ultima8/gfx/render_surface.h"
|
||||
#include "ultima/ultima8/gfx/texture.h"
|
||||
#include "ultima/ultima8/kernel/mouse.h"
|
||||
#include "ultima/ultima8/world/get_object.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(MiniStatsGump)
|
||||
|
||||
static const int gumpshape = 33;
|
||||
static const int hpx = 6;
|
||||
static const int manax = 13;
|
||||
static const int bary = 19;
|
||||
static const int barheight = 14;
|
||||
|
||||
// TODO: Confirm palette colors for use on mini stats gump
|
||||
// These values were closest to previously defined RGB values
|
||||
static const uint hpcolour[3] = {41, 39, 37};
|
||||
static const uint manacolour[3] = {138, 139, 141};
|
||||
|
||||
MiniStatsGump::MiniStatsGump() : Gump() {
|
||||
|
||||
}
|
||||
|
||||
MiniStatsGump::MiniStatsGump(int x, int y, uint32 flags, int32 layer)
|
||||
: Gump(x, y, 5, 5, 0, flags, layer) {
|
||||
}
|
||||
|
||||
MiniStatsGump::~MiniStatsGump() {
|
||||
}
|
||||
|
||||
void MiniStatsGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
Gump::InitGump(newparent, take_focus);
|
||||
|
||||
_shape = GameData::get_instance()->getGumps()->getShape(gumpshape);
|
||||
UpdateDimsFromShape();
|
||||
}
|
||||
|
||||
void MiniStatsGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
Gump::PaintThis(surf, lerp_factor, scaled);
|
||||
|
||||
Actor *a = getMainActor();
|
||||
assert(a);
|
||||
|
||||
int16 maxmana = a->getMaxMana();
|
||||
int16 mana = a->getMana();
|
||||
|
||||
uint16 maxhp = a->getMaxHP();
|
||||
uint16 hp = a->getHP();
|
||||
|
||||
int manaheight, hpheight;
|
||||
|
||||
|
||||
if (maxmana == 0)
|
||||
manaheight = 0;
|
||||
else
|
||||
manaheight = (mana * barheight) / maxmana;
|
||||
|
||||
if (maxhp == 0)
|
||||
hpheight = 0;
|
||||
else
|
||||
hpheight = (hp * barheight) / maxhp;
|
||||
|
||||
Palette *pal = PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game);
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
Common::Rect32 hprect(hpx + i, bary - hpheight + 1, hpx + i + 1, bary + 1);
|
||||
Common::Rect32 manarect(manax + i, bary - manaheight + 1, manax + i + 1, bary + 1);
|
||||
surf->fillRect(hprect, pal->_native[hpcolour[i]]);
|
||||
surf->fillRect(manarect, pal->_native[manacolour[i]]);
|
||||
}
|
||||
}
|
||||
|
||||
uint16 MiniStatsGump::TraceObjId(int32 mx, int32 my) {
|
||||
uint16 objId_ = Gump::TraceObjId(mx, my);
|
||||
if (objId_ && objId_ != 65535) return objId_;
|
||||
|
||||
if (PointOnGump(mx, my)) return getObjId();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Gump *MiniStatsGump::onMouseDown(int button, int32 mx, int32 my) {
|
||||
if (button == Mouse::BUTTON_LEFT)
|
||||
return this;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void MiniStatsGump::onMouseDouble(int button, int32 mx, int32 my) {
|
||||
// check if there already is an open PaperdollGump
|
||||
MainActor *av = getMainActor();
|
||||
if (!av->getGump()) {
|
||||
av->callUsecodeEvent_use();
|
||||
}
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
void MiniStatsGump::saveData(Common::WriteStream *ws) {
|
||||
Gump::saveData(ws);
|
||||
}
|
||||
|
||||
bool MiniStatsGump::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
return Gump::loadData(rs, version);
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
62
engines/ultima/ultima8/gumps/mini_stats_gump.h
Normal file
62
engines/ultima/ultima8/gumps/mini_stats_gump.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_MINISTATSGUMP_H
|
||||
#define ULTIMA8_GUMPS_MINISTATSGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/**
|
||||
* The tiny HP/mana bars shown on the desktop which can be activated from the paperdoll gump
|
||||
*/
|
||||
class MiniStatsGump : public Gump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
MiniStatsGump();
|
||||
MiniStatsGump(int x, int y, uint32 flags = FLAG_DRAGGABLE,
|
||||
int32 layer = LAYER_NORMAL);
|
||||
~MiniStatsGump() override;
|
||||
|
||||
// Init the gump, call after construction
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
|
||||
// Paint this Gump
|
||||
void PaintThis(RenderSurface *, int32 lerp_factor, bool scaled) override;
|
||||
|
||||
// Trace a click, and return ObjId
|
||||
uint16 TraceObjId(int32 mx, int32 my) override;
|
||||
|
||||
Gump *onMouseDown(int button, int32 mx, int32 my) override;
|
||||
void onMouseDouble(int button, int32 mx, int32 my) override;
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
249
engines/ultima/ultima8/gumps/minimap_gump.cpp
Normal file
249
engines/ultima/ultima8/gumps/minimap_gump.cpp
Normal file
@@ -0,0 +1,249 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/minimap_gump.h"
|
||||
#include "ultima/ultima8/world/minimap.h"
|
||||
#include "ultima/ultima8/world/current_map.h"
|
||||
#include "ultima/ultima8/world/world.h"
|
||||
#include "ultima/ultima8/world/actors/main_actor.h"
|
||||
#include "ultima/ultima8/gfx/palette.h"
|
||||
#include "ultima/ultima8/gfx/palette_manager.h"
|
||||
#include "ultima/ultima8/gfx/render_surface.h"
|
||||
#include "ultima/ultima8/gfx/texture.h"
|
||||
#include "ultima/ultima8/world/get_object.h"
|
||||
#include "ultima/ultima8/kernel/mouse.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(MiniMapGump)
|
||||
|
||||
static const uint BACKGROUND_COLOR = 0;
|
||||
static const uint NORMAL_COLOR = 53;
|
||||
static const uint HIGHLIGHT_COLOR = 52;
|
||||
static const uint KEY_COLOR = 255;
|
||||
|
||||
MiniMapGump::MiniMapGump(int x, int y) : ResizableGump(x, y, 120, 120), _minimaps(), _ax(0), _ay(0) {
|
||||
setMinSize(60, 60);
|
||||
}
|
||||
|
||||
MiniMapGump::MiniMapGump() : ResizableGump(), _minimaps(), _ax(0), _ay(0) {
|
||||
setMinSize(60, 60);
|
||||
}
|
||||
|
||||
MiniMapGump::~MiniMapGump(void) {
|
||||
for (auto &i : _minimaps) {
|
||||
delete i._value;
|
||||
}
|
||||
}
|
||||
|
||||
void MiniMapGump::run() {
|
||||
Gump::run();
|
||||
|
||||
World *world = World::get_instance();
|
||||
CurrentMap *currentmap = world->getCurrentMap();
|
||||
int mapChunkSize = currentmap->getChunkSize();
|
||||
|
||||
MainActor *actor = getMainActor();
|
||||
if (!actor || actor->isDead())
|
||||
return;
|
||||
|
||||
uint32 mapNum = currentmap->getNum();
|
||||
MiniMap *minimap = _minimaps[mapNum];
|
||||
if (!minimap) {
|
||||
minimap = new MiniMap(mapNum);
|
||||
_minimaps[mapNum] = minimap;
|
||||
}
|
||||
|
||||
Common::Point p = minimap->getItemLocation(*actor, mapChunkSize);
|
||||
|
||||
// Skip map update if location has not changed
|
||||
if (p.x == _ax && p.y == _ay)
|
||||
return;
|
||||
|
||||
_ax = p.x;
|
||||
_ay = p.y;
|
||||
|
||||
minimap->update(*currentmap);
|
||||
}
|
||||
|
||||
void MiniMapGump::generate() {
|
||||
World *world = World::get_instance();
|
||||
CurrentMap *currentmap = world->getCurrentMap();
|
||||
currentmap->setWholeMapFast();
|
||||
|
||||
uint32 mapNum = currentmap->getNum();
|
||||
|
||||
MiniMap *minimap = _minimaps[mapNum];
|
||||
if (!minimap) {
|
||||
minimap = new MiniMap(mapNum);
|
||||
_minimaps[mapNum] = minimap;
|
||||
}
|
||||
minimap->update(*currentmap);
|
||||
}
|
||||
|
||||
void MiniMapGump::clear() {
|
||||
for (auto &i : _minimaps) {
|
||||
delete i._value;
|
||||
}
|
||||
_minimaps.clear();
|
||||
}
|
||||
|
||||
bool MiniMapGump::dump(const Common::Path &filename) const {
|
||||
World *world = World::get_instance();
|
||||
CurrentMap *currentmap = world->getCurrentMap();
|
||||
|
||||
uint32 mapNum = currentmap->getNum();
|
||||
|
||||
MiniMap *minimap = _minimaps[mapNum];
|
||||
return minimap ? minimap->dump(filename) : false;
|
||||
}
|
||||
|
||||
void MiniMapGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
Palette *pal = PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game);
|
||||
uint32 *map = pal->_native;
|
||||
|
||||
uint32 color = map[NORMAL_COLOR];
|
||||
if (_dragPosition != Gump::CENTER || _mousePosition != Gump::CENTER)
|
||||
color = map[HIGHLIGHT_COLOR];
|
||||
|
||||
// Draw the border
|
||||
surf->frameRect(_dims, color);
|
||||
|
||||
// Dimensions minus border
|
||||
Common::Rect32 dims = _dims;
|
||||
dims.grow(-1);
|
||||
|
||||
// Fill the background
|
||||
surf->fillRect(dims, map[BACKGROUND_COLOR]);
|
||||
|
||||
// Center on avatar
|
||||
int sx = _ax - dims.width() / 2;
|
||||
int sy = _ay - dims.height() / 2;
|
||||
int dx = 1;
|
||||
int dy = 1;
|
||||
|
||||
World *world = World::get_instance();
|
||||
CurrentMap *currentmap = world->getCurrentMap();
|
||||
uint32 mapNum = currentmap->getNum();
|
||||
|
||||
MiniMap *minimap = _minimaps[mapNum];
|
||||
if (!minimap) {
|
||||
minimap = new MiniMap(mapNum);
|
||||
_minimaps[mapNum] = minimap;
|
||||
}
|
||||
|
||||
const Graphics::Surface *ms = minimap->getSurface();
|
||||
Common::Rect r(sx, sy, sx + dims.width(), sy + dims.height());
|
||||
|
||||
if (r.left < 0) {
|
||||
dx -= r.left;
|
||||
r.left = 0;
|
||||
}
|
||||
if (r.right > ms->w) {
|
||||
r.right = ms->w;
|
||||
}
|
||||
|
||||
if (r.top < 0) {
|
||||
dy -= r.top;
|
||||
r.top = 0;
|
||||
}
|
||||
if (r.bottom > ms->h) {
|
||||
r.bottom = ms->h;
|
||||
}
|
||||
|
||||
if (!r.isEmpty()) {
|
||||
surf->CrossKeyBlitMap(*ms, r, dx, dy, map, KEY_COLOR);
|
||||
}
|
||||
|
||||
int32 ax = _ax - sx;
|
||||
int32 ay = _ay - sy;
|
||||
|
||||
// Paint the avatar position marker
|
||||
surf->drawLine(ax - 1, ay + 1, ax, ay + 1, color);
|
||||
surf->drawLine(ax + 1, ay - 1, ax + 1, ay, color);
|
||||
surf->drawLine(ax + 2, ay + 1, ax + 3, ay + 1, color);
|
||||
surf->drawLine(ax + 1, ay + 2, ax + 1, ay + 3, color);
|
||||
}
|
||||
|
||||
Gump *MiniMapGump::onMouseDown(int button, int32 mx, int32 my) {
|
||||
Gump *handled = Gump::onMouseDown(button, mx, my);
|
||||
if (handled)
|
||||
return handled;
|
||||
|
||||
// only interested in left clicks
|
||||
if (button == Mouse::BUTTON_LEFT)
|
||||
return this;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void MiniMapGump::onMouseDouble(int button, int32 mx, int32 my) {
|
||||
if (button == Mouse::BUTTON_LEFT) {
|
||||
HideGump();
|
||||
}
|
||||
}
|
||||
|
||||
void MiniMapGump::saveData(Common::WriteStream *ws) {
|
||||
Gump::saveData(ws);
|
||||
|
||||
ws->writeUint32LE(static_cast<uint32>(_minimaps.size()));
|
||||
for (const auto &i : _minimaps) {
|
||||
const MiniMap *minimap = i._value;
|
||||
ws->writeUint32LE(i._key);
|
||||
minimap->save(ws);
|
||||
}
|
||||
}
|
||||
|
||||
bool MiniMapGump::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
if (!Gump::loadData(rs, version))
|
||||
return false;
|
||||
|
||||
_ax = 0;
|
||||
_ay = 0;
|
||||
|
||||
clear();
|
||||
|
||||
if (version >= 6) {
|
||||
uint32 mapcount = rs->readUint32LE();
|
||||
for (uint32 i = 0; i < mapcount; ++i) {
|
||||
uint32 mapNum = rs->readUint32LE();
|
||||
MiniMap *minimap = new MiniMap(mapNum);
|
||||
if (!minimap->load(rs, version))
|
||||
return false;
|
||||
_minimaps[mapNum] = minimap;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16 MiniMapGump::TraceObjId(int32 mx, int32 my) {
|
||||
uint16 objId = Gump::TraceObjId(mx, my);
|
||||
|
||||
if (!objId || objId == 65535)
|
||||
if (PointOnGump(mx, my))
|
||||
objId = getObjId();
|
||||
|
||||
return objId;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
68
engines/ultima/ultima8/gumps/minimap_gump.h
Normal file
68
engines/ultima/ultima8/gumps/minimap_gump.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_MINIMAPGUMP_H
|
||||
#define ULTIMA8_GUMPS_MINIMAPGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/resizable_gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Common {
|
||||
class Path;
|
||||
}
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class MiniMap;
|
||||
|
||||
class MiniMapGump : public ResizableGump {
|
||||
private:
|
||||
Common::HashMap<uint32, MiniMap *> _minimaps;
|
||||
int32 _ax, _ay;
|
||||
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
MiniMapGump();
|
||||
MiniMapGump(int x, int y);
|
||||
~MiniMapGump() override;
|
||||
|
||||
void run() override;
|
||||
|
||||
void generate();
|
||||
void clear();
|
||||
bool dump(const Common::Path &filename) const;
|
||||
|
||||
void PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) override;
|
||||
uint16 TraceObjId(int32 mx, int32 my) override;
|
||||
|
||||
Gump *onMouseDown(int button, int32 mx, int32 my) override;
|
||||
void onMouseDouble(int button, int32 mx, int32 my) override;
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
106
engines/ultima/ultima8/gumps/modal_gump.cpp
Normal file
106
engines/ultima/ultima8/gumps/modal_gump.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/modal_gump.h"
|
||||
|
||||
#include "ultima/ultima8/kernel/kernel.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
#include "ultima/ultima8/audio/audio_process.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(ModalGump)
|
||||
|
||||
ModalGump::ModalGump() : Gump() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
ModalGump::ModalGump(int x, int y, int width, int height, uint16 owner,
|
||||
uint32 flags, int32 layer, bool pauseGame)
|
||||
: Gump(x, y, width, height, owner, flags, layer), _pauseGame(pauseGame) {
|
||||
|
||||
}
|
||||
|
||||
ModalGump::~ModalGump() {
|
||||
}
|
||||
|
||||
void ModalGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
Gump::InitGump(newparent, take_focus);
|
||||
|
||||
if (_pauseGame) {
|
||||
Kernel::get_instance()->pause();
|
||||
|
||||
AudioProcess *ap = AudioProcess::get_instance();
|
||||
if (ap)
|
||||
ap->pauseAllSamples();
|
||||
}
|
||||
}
|
||||
|
||||
Gump *ModalGump::FindGump(int mx, int my) {
|
||||
Gump *ret = Gump::FindGump(mx, my);
|
||||
if (!ret) ret = this; // we take all mouse input
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ModalGump::PointOnGump(int mx, int my) {
|
||||
return true; // we take all mouse input
|
||||
}
|
||||
|
||||
uint16 ModalGump::TraceObjId(int32 mx, int32 my) {
|
||||
uint16 objId = Gump::TraceObjId(mx, my);
|
||||
if (!objId) objId = getObjId();
|
||||
|
||||
return objId;
|
||||
}
|
||||
|
||||
void ModalGump::Close(bool no_del) {
|
||||
if (_pauseGame) {
|
||||
Kernel::get_instance()->unpause();
|
||||
|
||||
AudioProcess *ap = AudioProcess::get_instance();
|
||||
if (ap)
|
||||
ap->unpauseAllSamples();
|
||||
}
|
||||
|
||||
Gump::Close(no_del);
|
||||
}
|
||||
|
||||
Gump *ModalGump::onMouseDown(int button, int32 mx, int32 my) {
|
||||
Gump *handled = Gump::onMouseDown(button, mx, my);
|
||||
if (!handled) handled = this;
|
||||
return handled;
|
||||
}
|
||||
|
||||
|
||||
void ModalGump::saveData(Common::WriteStream *ws) {
|
||||
warning("Trying to save ModalGump");
|
||||
}
|
||||
|
||||
bool ModalGump::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
warning("Trying to load ModalGump");
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
65
engines/ultima/ultima8/gumps/modal_gump.h
Normal file
65
engines/ultima/ultima8/gumps/modal_gump.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_MODALGUMP_H
|
||||
#define ULTIMA8_GUMPS_MODALGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/**
|
||||
* Base class for any gump which blocks the game (menu, credits, movie, etc)
|
||||
*/
|
||||
class ModalGump : public Gump {
|
||||
protected:
|
||||
bool _pauseGame;
|
||||
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
ModalGump();
|
||||
ModalGump(int x, int y, int width, int height, uint16 owner = 0,
|
||||
uint32 flags = FLAG_DONT_SAVE | FLAG_PREVENT_SAVE, int32 layer = LAYER_MODAL,
|
||||
bool pauseGame = true);
|
||||
|
||||
~ModalGump() override;
|
||||
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
|
||||
void Close(bool no_del = false) override;
|
||||
|
||||
bool PointOnGump(int mx, int my) override;
|
||||
Gump *FindGump(int mx, int my) override;
|
||||
uint16 TraceObjId(int32 mx, int32 my) override;
|
||||
|
||||
Gump *onMouseDown(int button, int32 mx, int32 my) override;
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
437
engines/ultima/ultima8/gumps/movie_gump.cpp
Normal file
437
engines/ultima/ultima8/gumps/movie_gump.cpp
Normal file
@@ -0,0 +1,437 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/file.h"
|
||||
|
||||
#include "ultima/ultima8/gumps/movie_gump.h"
|
||||
|
||||
#include "ultima/ultima8/gfx/avi_player.h"
|
||||
#include "ultima/ultima8/gfx/skf_player.h"
|
||||
#include "ultima/ultima8/gfx/gump_shape_archive.h"
|
||||
#include "ultima/ultima8/gfx/shape.h"
|
||||
#include "ultima/ultima8/gfx/shape_frame.h"
|
||||
#include "ultima/ultima8/gfx/palette.h"
|
||||
#include "ultima/ultima8/gfx/palette_manager.h"
|
||||
#include "ultima/ultima8/gfx/texture.h"
|
||||
#include "ultima/ultima8/gfx/fade_to_modal_process.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/games/game.h"
|
||||
#include "ultima/ultima8/kernel/mouse.h"
|
||||
#include "ultima/ultima8/kernel/kernel.h"
|
||||
#include "ultima/ultima8/usecode/uc_machine.h"
|
||||
#include "ultima/ultima8/world/get_object.h"
|
||||
#include "ultima/ultima8/world/item.h"
|
||||
#include "ultima/ultima8/gumps/gump_notify_process.h"
|
||||
#include "ultima/ultima8/gumps/cru_status_gump.h"
|
||||
#include "ultima/ultima8/gumps/widgets/text_widget.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
// Some fourCCs used in IFF files
|
||||
static const uint32 IFF_MAGIC = MKTAG('F', 'O', 'R', 'M');
|
||||
static const uint32 IFF_LANG = MKTAG('L', 'A', 'N', 'G');
|
||||
static const uint32 IFF_LANG_FR = MKTAG('F', 'R', 'E', 'N');
|
||||
static const uint32 IFF_LANG_EN = MKTAG('E', 'N', 'G', 'L');
|
||||
static const uint32 IFF_LANG_DE = MKTAG('G', 'E', 'R', 'M');
|
||||
|
||||
static Std::string _fixCrusaderMovieName(const Std::string &s) {
|
||||
/*
|
||||
HACK! The game comes with movies MVA01.AVI etc, but the usecode mentions both
|
||||
MVA01 and MVA1. We do a translation here. These are the strings we need to fix:
|
||||
008E: 0D push string "mva1"
|
||||
036D: 0D push string "mva3a"
|
||||
04E3: 0D push string "mva4"
|
||||
0656: 0D push string "mva5a"
|
||||
07BD: 0D push string "mva6"
|
||||
0944: 0D push string "mva7"
|
||||
0A68: 0D push string "mva8"
|
||||
0B52: 0D push string "mva9"
|
||||
*/
|
||||
if (s.size() == 4)
|
||||
return Std::string::format("mva0%c", s[3]);
|
||||
else if (s.equals("mva3a"))
|
||||
return "mva03a";
|
||||
else if (s.equals("mva5a"))
|
||||
return "mva05a";
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static Common::SeekableReadStream *_tryLoadCruMovieFile(const Std::string &filename, const char *extn) {
|
||||
const Std::string path = Std::string::format("flics/%s.%s", filename.c_str(), extn);
|
||||
auto *rs = new Common::File();
|
||||
if (!rs->open(path.c_str())) {
|
||||
// Try with a "0" in the name
|
||||
const Std::string adjustedfn = Std::string::format("flics/0%s.%s", filename.c_str(), extn);
|
||||
if (!rs->open(adjustedfn.c_str())) {
|
||||
delete rs;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return rs;
|
||||
}
|
||||
|
||||
static Common::SeekableReadStream *_tryLoadCruAVI(const Std::string &filename) {
|
||||
Common::SeekableReadStream *rs = _tryLoadCruMovieFile(filename, "avi");
|
||||
if (!rs)
|
||||
warning("movie %s not found", filename.c_str());
|
||||
return rs;
|
||||
}
|
||||
|
||||
// Convenience function that tries to open both TXT (No Remorse)
|
||||
// and IFF (No Regret) subtitle formats.
|
||||
static Common::SeekableReadStream *_tryLoadCruSubtitle(const Std::string &filename) {
|
||||
Common::SeekableReadStream *txtfile = _tryLoadCruMovieFile(filename, "txt");
|
||||
if (txtfile)
|
||||
return txtfile;
|
||||
return _tryLoadCruMovieFile(filename, "iff");
|
||||
}
|
||||
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(MovieGump)
|
||||
|
||||
MovieGump::MovieGump() : ModalGump(), _player(nullptr), _subtitleWidget(0), _lastFrameNo(-1) {
|
||||
|
||||
}
|
||||
|
||||
MovieGump::MovieGump(int width, int height, Common::SeekableReadStream *rs,
|
||||
bool introMusicHack, bool noScale, const byte *overridePal,
|
||||
uint32 flags, int32 layer)
|
||||
: ModalGump(50, 50, width, height, 0, flags, layer), _subtitleWidget(0), _lastFrameNo(-1) {
|
||||
uint32 stream_id = rs->readUint32BE();
|
||||
rs->seek(-4, SEEK_CUR);
|
||||
if (stream_id == 0x52494646) {// 'RIFF' - crusader AVIs
|
||||
_player = new AVIPlayer(rs, width, height, overridePal, noScale);
|
||||
} else {
|
||||
_player = new SKFPlayer(rs, width, height, introMusicHack);
|
||||
}
|
||||
}
|
||||
|
||||
MovieGump::~MovieGump() {
|
||||
delete _player;
|
||||
}
|
||||
|
||||
void MovieGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
ModalGump::InitGump(newparent, take_focus);
|
||||
|
||||
_player->start();
|
||||
|
||||
Mouse::get_instance()->pushMouseCursor(Mouse::MOUSE_NONE);
|
||||
|
||||
CruStatusGump *statusgump = CruStatusGump::get_instance();
|
||||
if (statusgump) {
|
||||
statusgump->HideGump();
|
||||
}
|
||||
}
|
||||
|
||||
void MovieGump::Close(bool no_del) {
|
||||
Mouse::get_instance()->popMouseCursor();
|
||||
|
||||
CruStatusGump *statusgump = CruStatusGump::get_instance();
|
||||
if (statusgump) {
|
||||
statusgump->UnhideGump();
|
||||
}
|
||||
|
||||
_player->stop();
|
||||
|
||||
ModalGump::Close(no_del);
|
||||
}
|
||||
|
||||
void MovieGump::run() {
|
||||
ModalGump::run();
|
||||
|
||||
_player->run();
|
||||
|
||||
// TODO: It would be nice to refactor this
|
||||
AVIPlayer *aviplayer = dynamic_cast<AVIPlayer *>(_player);
|
||||
if (aviplayer) {
|
||||
// The AVI player can skip frame numbers, so search back from the
|
||||
// last frame to make sure we don't miss subtitles
|
||||
const int frameno = aviplayer->getFrameNo();
|
||||
for (int f = _lastFrameNo + 1; f <= frameno; f++) {
|
||||
if (_subtitles.contains(f)) {
|
||||
TextWidget *subtitle = dynamic_cast<TextWidget *>(getGump(_subtitleWidget));
|
||||
if (subtitle)
|
||||
subtitle->Close();
|
||||
// Create a new TextWidget. No Regret uses font 3
|
||||
int subtitle_font = GAME_IS_REMORSE ? 4 : 3;
|
||||
TextWidget *widget = new TextWidget(0, 0, _subtitles[f], true, subtitle_font, 640, 10);
|
||||
widget->InitGump(this);
|
||||
widget->setRelativePosition(BOTTOM_CENTER, 0, -10);
|
||||
// Subtitles should be white.
|
||||
widget->setBlendColour(TEX32_PACK_RGBA(0xFF, 0xFF, 0xFF, 0xFF));
|
||||
_subtitleWidget = widget->getObjId();
|
||||
}
|
||||
}
|
||||
_lastFrameNo = frameno;
|
||||
}
|
||||
|
||||
if (!_player->isPlaying()) {
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
void MovieGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
Gump::PaintThis(surf, lerp_factor, scaled);
|
||||
_player->paint(surf, lerp_factor);
|
||||
|
||||
// If displaying subtitles, put a black box behind them. The box should be ~600px across.
|
||||
if (_subtitleWidget) {
|
||||
TextWidget *subtitle = dynamic_cast<TextWidget *>(getGump(_subtitleWidget));
|
||||
if (subtitle) {
|
||||
int32 x, y;
|
||||
|
||||
subtitle->getLocation(x, y);
|
||||
Common::Rect32 textdims = subtitle->getDims();
|
||||
Common::Rect32 screendims = surf->getSurfaceDims();
|
||||
surf->fill32(TEX32_PACK_RGB(0, 0, 0),
|
||||
screendims.width() / 2 - 300 - screendims.left,
|
||||
y - 3,
|
||||
600,
|
||||
textdims.height() + 5);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool MovieGump::OnKeyDown(int key, int mod) {
|
||||
switch (key) {
|
||||
case Common::KEYCODE_ESCAPE: {
|
||||
Close();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MovieGump::ClearPlayerOffset() {
|
||||
if (!_shape || !_player)
|
||||
return;
|
||||
_player->setOffset(0, 0);
|
||||
}
|
||||
|
||||
/*static*/
|
||||
ProcId MovieGump::U8MovieViewer(Common::SeekableReadStream *rs, bool fade, bool introMusicHack, bool noScale) {
|
||||
ModalGump *gump;
|
||||
if (GAME_IS_U8)
|
||||
gump = new MovieGump(320, 200, rs, introMusicHack, noScale);
|
||||
else
|
||||
gump = new MovieGump(640, 480, rs, introMusicHack, noScale);
|
||||
|
||||
if (fade) {
|
||||
FadeToModalProcess *p = new FadeToModalProcess(gump);
|
||||
Kernel::get_instance()->addProcess(p);
|
||||
return p->getPid();
|
||||
}
|
||||
else
|
||||
{
|
||||
gump->InitGump(nullptr);
|
||||
gump->setRelativePosition(CENTER);
|
||||
gump->CreateNotifier();
|
||||
return gump->GetNotifyProcess()->getPid();
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ MovieGump *MovieGump::CruMovieViewer(const Std::string fname, int x, int y, const byte *pal, Gump *parent, uint16 frameshape) {
|
||||
Common::SeekableReadStream *rs = _tryLoadCruAVI(fname);
|
||||
if (!rs)
|
||||
return nullptr;
|
||||
|
||||
MovieGump *gump = new MovieGump(x, y, rs, false, false, pal);
|
||||
|
||||
gump->InitGump(parent, true);
|
||||
|
||||
if (frameshape) {
|
||||
GumpShapeArchive *gumpshapes = GameData::get_instance()->getGumps();
|
||||
if (!gumpshapes) {
|
||||
warning("failed to add movie frame: no gump shape archive");
|
||||
} else {
|
||||
gump->SetShape(gumpshapes->getShape(frameshape), 0);
|
||||
gump->UpdateDimsFromShape();
|
||||
gump->ClearPlayerOffset();
|
||||
}
|
||||
}
|
||||
|
||||
gump->setRelativePosition(CENTER);
|
||||
gump->loadSubtitles(_tryLoadCruSubtitle(fname));
|
||||
return gump;
|
||||
}
|
||||
|
||||
void MovieGump::loadSubtitles(Common::SeekableReadStream *rs) {
|
||||
if (!rs)
|
||||
return;
|
||||
|
||||
const uint32 id = rs->readUint32BE();
|
||||
rs->seek(0);
|
||||
|
||||
if (id == IFF_MAGIC) {
|
||||
loadIFFSubs(rs);
|
||||
} else {
|
||||
loadTXTSubs(rs);
|
||||
}
|
||||
}
|
||||
|
||||
void MovieGump::loadTXTSubs(Common::SeekableReadStream *rs) {
|
||||
int frameno = 0;
|
||||
while (!rs->eos()) {
|
||||
Common::String line = rs->readLine();
|
||||
if (line.hasPrefix("@frame ")) {
|
||||
if (frameno > 0) {
|
||||
// two @frame directives in a row means that the last
|
||||
// subtitle should be turned *off* at the first frame
|
||||
_subtitles[frameno] = "";
|
||||
}
|
||||
frameno = atoi(line.c_str() + 7);
|
||||
} else if (frameno >= 0) {
|
||||
_subtitles[frameno] = line;
|
||||
frameno = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MovieGump::loadIFFSubs(Common::SeekableReadStream *rs) {
|
||||
uint32 magic = rs->readUint32BE();
|
||||
if (magic != IFF_MAGIC) {
|
||||
warning("Error loading IFF file, invalid magic.");
|
||||
return;
|
||||
}
|
||||
|
||||
rs->skip(2);
|
||||
uint16 totalsize = rs->readUint16BE();
|
||||
if (totalsize != rs->size() - rs->pos()) {
|
||||
warning("Error loading IFF file: size invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 lang_magic = rs->readUint32BE();
|
||||
if (lang_magic != IFF_LANG) {
|
||||
warning("Error loading IFF file: invalid magic.");
|
||||
return;
|
||||
}
|
||||
|
||||
const Common::Language lang = Ultima8Engine::get_instance()->getLanguage();
|
||||
while (rs->pos() < rs->size()) {
|
||||
uint32 lang_code = rs->readUint32BE();
|
||||
uint32 lang_len = rs->readUint32BE();
|
||||
uint32 lang_end = rs->pos() + lang_len;
|
||||
if ((lang == Common::FR_FRA && lang_code == IFF_LANG_FR)
|
||||
|| (lang == Common::DE_DEU && lang_code == IFF_LANG_DE)
|
||||
|| (lang == Common::EN_ANY && lang_code == IFF_LANG_EN)) {
|
||||
while (rs->pos() < lang_end) {
|
||||
// Take care of the mix of LE and BE.
|
||||
uint16 frameoff = rs->readUint16LE();
|
||||
rs->skip(1); // what's this?
|
||||
uint32 slen = rs->readUint16BE();
|
||||
const Common::String line = rs->readString('\0', slen);
|
||||
_subtitles[frameoff] = line;
|
||||
}
|
||||
} else {
|
||||
rs->skip(lang_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MovieGump::loadData(Common::ReadStream *rs) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void MovieGump::saveData(Common::WriteStream *ws) {
|
||||
|
||||
}
|
||||
|
||||
uint32 MovieGump::I_playMovieOverlay(const uint8 *args,
|
||||
unsigned int /*argsize*/) {
|
||||
ARG_ITEM_FROM_PTR(item);
|
||||
ARG_STRING(name);
|
||||
ARG_UINT16(x);
|
||||
ARG_UINT16(y);
|
||||
|
||||
PaletteManager *palman = PaletteManager::get_instance();
|
||||
|
||||
if (item && palman) {
|
||||
if (name.hasPrefix("mva")) {
|
||||
name = _fixCrusaderMovieName(name);
|
||||
}
|
||||
|
||||
const Palette *pal = palman->getPalette(PaletteManager::Pal_Game);
|
||||
assert(pal);
|
||||
|
||||
CruMovieViewer(name, x, y, pal->data(), nullptr, 52);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 MovieGump::I_playMovieCutscene(const uint8 *args, unsigned int /*argsize*/) {
|
||||
ARG_ITEM_FROM_PTR(item);
|
||||
ARG_STRING(name);
|
||||
ARG_UINT16(x);
|
||||
ARG_UINT16(y);
|
||||
|
||||
if (item) {
|
||||
CruMovieViewer(name, x * 3, y * 3, nullptr, nullptr, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 MovieGump::I_playMovieCutsceneAlt(const uint8 *args, unsigned int /*argsize*/) {
|
||||
ARG_ITEM_FROM_PTR(item); // TODO: Unused? Center on this first?
|
||||
ARG_STRING(name);
|
||||
ARG_UINT16(x);
|
||||
ARG_UINT16(y);
|
||||
|
||||
if (!x)
|
||||
x = 640;
|
||||
else
|
||||
x *= 3;
|
||||
|
||||
if (!y)
|
||||
y = 480;
|
||||
else
|
||||
y *= 3;
|
||||
|
||||
warning("MovieGump::I_playMovieCutsceneAlt: TODO: This intrinsic should pause and fade the background to grey (%s, %d)",
|
||||
name.c_str(), item ? item->getObjId() : 0);
|
||||
|
||||
CruMovieViewer(name, x, y, nullptr, nullptr, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 MovieGump::I_playMovieCutsceneRegret(const uint8 *args, unsigned int /*argsize*/) {
|
||||
ARG_STRING(name);
|
||||
ARG_UINT8(fade);
|
||||
|
||||
warning("MovieGump::I_playMovieCutsceneRegret: TODO: use fade argument %d", fade);
|
||||
|
||||
CruMovieViewer(name, 640, 480, nullptr, nullptr, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
97
engines/ultima/ultima8/gumps/movie_gump.h
Normal file
97
engines/ultima/ultima8/gumps/movie_gump.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_MOVIEGUMP_H
|
||||
#define ULTIMA8_GUMPS_MOVIEGUMP_H
|
||||
|
||||
#include "ultima/shared/std/string.h"
|
||||
#include "ultima/ultima8/gumps/modal_gump.h"
|
||||
#include "ultima/ultima8/usecode/intrinsics.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class RawArchive;
|
||||
class MoviePlayer;
|
||||
|
||||
class MovieGump : public ModalGump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
MovieGump();
|
||||
MovieGump(int width, int height, Common::SeekableReadStream *rs,
|
||||
bool introMusicHack = false, bool noScale = false,
|
||||
const byte *overridePal = nullptr,
|
||||
uint32 flags = FLAG_PREVENT_SAVE, int32 layer = LAYER_MODAL);
|
||||
~MovieGump() override;
|
||||
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
|
||||
void Close(bool no_del = false) override;
|
||||
|
||||
void run() override;
|
||||
|
||||
void PaintThis(RenderSurface *, int32 lerp_factor, bool scaled) override;
|
||||
|
||||
bool OnKeyDown(int key, int mod) override;
|
||||
|
||||
static ProcId U8MovieViewer(Common::SeekableReadStream *rs, bool fade, bool introMusicHack, bool noScale);
|
||||
static MovieGump *CruMovieViewer(const Std::string fname, int x, int y, const byte *pal, Gump *parent, uint16 frameshape);
|
||||
|
||||
bool loadData(Common::ReadStream *rs);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
|
||||
INTRINSIC(I_playMovieOverlay);
|
||||
INTRINSIC(I_playMovieCutscene);
|
||||
INTRINSIC(I_playMovieCutsceneAlt);
|
||||
INTRINSIC(I_playMovieCutsceneRegret);
|
||||
|
||||
protected:
|
||||
MoviePlayer *_player;
|
||||
|
||||
/// Load subtitles with format detection
|
||||
void loadSubtitles(Common::SeekableReadStream *rs);
|
||||
|
||||
/// Load subtitles from a txt file (No Remorse format)
|
||||
void loadTXTSubs(Common::SeekableReadStream *rs);
|
||||
|
||||
/// Load subtitles from a iff file (No Regret format)
|
||||
void loadIFFSubs(Common::SeekableReadStream *rs);
|
||||
|
||||
/// Update the offset of the player if a shape has been set
|
||||
void ClearPlayerOffset();
|
||||
|
||||
/// Subtitles, by frame number. Only used for Crusader movies.
|
||||
Common::HashMap<int, Common::String> _subtitles;
|
||||
|
||||
/// Last widget used for displaying subtitles.
|
||||
uint16 _subtitleWidget;
|
||||
|
||||
/// Last frame that was displayed, so we can catch up subtitles.
|
||||
int _lastFrameNo;
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
186
engines/ultima/ultima8/gumps/paged_gump.cpp
Normal file
186
engines/ultima/ultima8/gumps/paged_gump.cpp
Normal file
@@ -0,0 +1,186 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/events.h"
|
||||
|
||||
#include "ultima/ultima8/gumps/paged_gump.h"
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/gfx/gump_shape_archive.h"
|
||||
#include "ultima/ultima8/kernel/mouse.h"
|
||||
#include "ultima/ultima8/gumps/widgets/button_widget.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(PagedGump)
|
||||
|
||||
PagedGump::PagedGump(int left, int right, int top, int shape):
|
||||
ModalGump(0, 0, 5, 5), _leftOff(left), _rightOff(right), _topOff(top),
|
||||
_gumpShape(shape), _nextButton(nullptr), _prevButton(nullptr),
|
||||
_current(0), _buttonsEnabled(true) {
|
||||
}
|
||||
|
||||
PagedGump::~PagedGump(void) {
|
||||
}
|
||||
|
||||
void PagedGump::Close(bool no_del) {
|
||||
Mouse::get_instance()->popMouseCursor();
|
||||
for (auto *g : _gumps) {
|
||||
g->Close(no_del); // CHECKME: no_del?
|
||||
}
|
||||
|
||||
ModalGump::Close(no_del);
|
||||
}
|
||||
|
||||
static const int pageOverShape = 34;
|
||||
|
||||
void PagedGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
ModalGump::InitGump(newparent, take_focus);
|
||||
|
||||
_shape = GameData::get_instance()->getGumps()->getShape(_gumpShape);
|
||||
UpdateDimsFromShape();
|
||||
|
||||
FrameID buttonleft(GameData::GUMPS, pageOverShape, 0);
|
||||
FrameID buttonright(GameData::GUMPS, pageOverShape, 1);
|
||||
|
||||
//!! Hardcoded gump
|
||||
_nextButton = new ButtonWidget(0, 0, buttonright, buttonright, false,
|
||||
LAYER_ABOVE_NORMAL);
|
||||
_nextButton->InitGump(this);
|
||||
_nextButton->setRelativePosition(TOP_RIGHT, _rightOff, _topOff);
|
||||
|
||||
_prevButton = new ButtonWidget(0, 0, buttonleft, buttonleft, false,
|
||||
LAYER_ABOVE_NORMAL);
|
||||
_prevButton->InitGump(this);
|
||||
_prevButton->setRelativePosition(TOP_LEFT, _leftOff, _topOff);
|
||||
_prevButton->HideGump();
|
||||
|
||||
Mouse *mouse = Mouse::get_instance();
|
||||
mouse->pushMouseCursor(Mouse::MOUSE_HAND);
|
||||
}
|
||||
|
||||
void PagedGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
Gump::PaintThis(surf, lerp_factor, scaled);
|
||||
}
|
||||
|
||||
void PagedGump::onMouseDouble(int button, int32 mx, int32 my) {
|
||||
Close();
|
||||
}
|
||||
|
||||
bool PagedGump::OnKeyDown(int key, int mod) {
|
||||
if (_current < _gumps.size())
|
||||
if (_gumps[_current]->OnKeyDown(key, mod))
|
||||
return true;
|
||||
|
||||
switch (key) {
|
||||
case Common::KEYCODE_ESCAPE:
|
||||
Close();
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PagedGump::ChildNotify(Gump *child, uint32 message) {
|
||||
if (!_buttonsEnabled) return;
|
||||
if (_gumps.empty()) return;
|
||||
|
||||
ObjId cid = child->getObjId();
|
||||
|
||||
if (message == ButtonWidget::BUTTON_UP) {
|
||||
if (cid == _nextButton->getObjId()) {
|
||||
if (_current + 1 < _gumps.size()) {
|
||||
_gumps[_current]->HideGump();
|
||||
++_current;
|
||||
_gumps[_current]->UnhideGump();
|
||||
_gumps[_current]->MakeFocus();
|
||||
|
||||
if (_current + 1 == _gumps.size())
|
||||
_nextButton->HideGump();
|
||||
|
||||
_prevButton->UnhideGump();
|
||||
}
|
||||
} else if (cid == _prevButton->getObjId()) {
|
||||
if (_current > 0) {
|
||||
_gumps[_current]->HideGump();
|
||||
--_current;
|
||||
_gumps[_current]->UnhideGump();
|
||||
_gumps[_current]->MakeFocus();
|
||||
|
||||
if (_current == 0)
|
||||
_prevButton->HideGump();
|
||||
|
||||
_nextButton->UnhideGump();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PagedGump::addPage(Gump *g) {
|
||||
assert(g->GetParent() == this);
|
||||
g->setRelativePosition(TOP_CENTER, 0, 3 + _topOff);
|
||||
g->HideGump();
|
||||
_gumps.push_back(g);
|
||||
|
||||
_current = 0;
|
||||
_gumps[_current]->UnhideGump();
|
||||
if (_focusChild != _gumps[_current])
|
||||
_gumps[_current]->MakeFocus();
|
||||
|
||||
if (_current + 1 == _gumps.size())
|
||||
_nextButton->HideGump();
|
||||
else
|
||||
_nextButton->UnhideGump();
|
||||
}
|
||||
|
||||
void PagedGump::showPage(uint index) {
|
||||
if (index >= _gumps.size())
|
||||
return;
|
||||
|
||||
_gumps[_current]->HideGump();
|
||||
_current = index;
|
||||
_gumps[_current]->UnhideGump();
|
||||
_gumps[_current]->MakeFocus();
|
||||
|
||||
if (_current + 1 == _gumps.size())
|
||||
_nextButton->HideGump();
|
||||
else
|
||||
_nextButton->UnhideGump();
|
||||
|
||||
if (_current == 0)
|
||||
_prevButton->HideGump();
|
||||
else
|
||||
_prevButton->UnhideGump();
|
||||
}
|
||||
|
||||
bool PagedGump::loadData(Common::ReadStream *rs) {
|
||||
warning("Trying to load ModalGump");
|
||||
return false;
|
||||
}
|
||||
|
||||
void PagedGump::saveData(Common::WriteStream *ws) {
|
||||
warning("Trying to save ModalGump");
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
75
engines/ultima/ultima8/gumps/paged_gump.h
Normal file
75
engines/ultima/ultima8/gumps/paged_gump.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_PAGEDGUMP_H
|
||||
#define ULTIMA8_GUMPS_PAGEDGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/modal_gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/**
|
||||
* Base class for gumps which have multiple pages (books, save/load game)
|
||||
*/
|
||||
class PagedGump : public ModalGump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
PagedGump(int left, int right, int top, int shape);
|
||||
~PagedGump() override;
|
||||
|
||||
// Init the gump, call after construction
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
void Close(bool no_del = false) override;
|
||||
|
||||
// Paint the Gump
|
||||
void PaintThis(RenderSurface *, int32 lerp_factor, bool scaled) override;
|
||||
|
||||
void onMouseDouble(int button, int32 mx, int32 my) override;
|
||||
bool OnKeyDown(int key, int mod) override;
|
||||
void ChildNotify(Gump *child, uint32 message) override;
|
||||
|
||||
//! add a page. Note: g already has to be a child gump.
|
||||
void addPage(Gump *g);
|
||||
void showPage(uint index);
|
||||
|
||||
void enableButtons(bool enabled) {
|
||||
_buttonsEnabled = enabled;
|
||||
}
|
||||
|
||||
bool loadData(Common::ReadStream *rs);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
|
||||
protected:
|
||||
int _leftOff, _rightOff, _topOff, _gumpShape;
|
||||
Common::Array<Gump *> _gumps;
|
||||
Gump *_nextButton;
|
||||
Gump *_prevButton;
|
||||
uint _current;
|
||||
bool _buttonsEnabled;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
450
engines/ultima/ultima8/gumps/paperdoll_gump.cpp
Normal file
450
engines/ultima/ultima8/gumps/paperdoll_gump.cpp
Normal file
@@ -0,0 +1,450 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/paperdoll_gump.h"
|
||||
#include "ultima/ultima8/gfx/shape.h"
|
||||
#include "ultima/ultima8/gfx/shape_frame.h"
|
||||
#include "ultima/ultima8/world/actors/actor.h"
|
||||
#include "ultima/ultima8/gfx/render_surface.h"
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/gfx/main_shape_archive.h"
|
||||
#include "ultima/ultima8/gfx/fonts/font.h"
|
||||
#include "ultima/ultima8/gfx/fonts/font_manager.h"
|
||||
#include "ultima/ultima8/gfx/fonts/rendered_text.h"
|
||||
#include "ultima/ultima8/gumps/widgets/button_widget.h"
|
||||
#include "ultima/ultima8/gumps/mini_stats_gump.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
#include "ultima/ultima8/kernel/mouse.h"
|
||||
#include "ultima/ultima8/world/get_object.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(PaperdollGump)
|
||||
|
||||
|
||||
|
||||
// lots of CONSTANTS...
|
||||
const struct equipcoords_struct {
|
||||
int x, y;
|
||||
} equipcoords[] = {
|
||||
{ 0, 0 },
|
||||
{ 24, 60 }, // shield
|
||||
{ 36, 50 }, // arm
|
||||
{ 40, 26 }, // head
|
||||
{ 40, 63 }, // body
|
||||
{ 40, 92 }, // legs
|
||||
{ 16, 18 } // weapon
|
||||
};
|
||||
|
||||
const struct statcords_struct {
|
||||
|
||||
int xd, x, y;
|
||||
} statcoords[] = {
|
||||
{ 90, 130, 24 },
|
||||
{ 90, 130, 33 },
|
||||
{ 90, 130, 42 },
|
||||
{ 90, 130, 51 },
|
||||
{ 90, 130, 60 },
|
||||
{ 90, 130, 69 },
|
||||
{ 90, 130, 78 }
|
||||
};
|
||||
|
||||
static const int statdescwidth = 29;
|
||||
static const int statwidth = 15;
|
||||
static const int statheight = 8;
|
||||
static const int statfont = 7;
|
||||
static const int statdescfont = 0;
|
||||
static const int statbuttonshape = 38;
|
||||
static const int statbuttonx = 81;
|
||||
static const int statbuttony = 84;
|
||||
|
||||
|
||||
PaperdollGump::PaperdollGump() : ContainerGump(), _statButtonId(0),
|
||||
_draggingArmourClass(0), _draggingWeight(0),
|
||||
_backpackRect(49, 25, 59, 50) {
|
||||
Common::fill(_cachedText, _cachedText + 14, (RenderedText *)nullptr);
|
||||
Common::fill(_cachedVal, _cachedVal + 7, 0);
|
||||
}
|
||||
|
||||
PaperdollGump::PaperdollGump(const Shape *shape, uint32 frameNum, uint16 owner,
|
||||
uint32 Flags, int32 layer)
|
||||
: ContainerGump(shape, frameNum, owner, Flags, layer),
|
||||
_statButtonId(0), _draggingArmourClass(0), _draggingWeight(0),
|
||||
_backpackRect(49, 25, 59, 50) {
|
||||
_statButtonId = 0;
|
||||
|
||||
Common::fill(_cachedText, _cachedText + 14, (RenderedText *)nullptr);
|
||||
Common::fill(_cachedVal, _cachedVal + 7, 0);
|
||||
}
|
||||
|
||||
PaperdollGump::~PaperdollGump() {
|
||||
for (int i = 0; i < 14; ++i) { // ! constant
|
||||
delete _cachedText[i];
|
||||
}
|
||||
}
|
||||
|
||||
void PaperdollGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
ContainerGump::InitGump(newparent, take_focus);
|
||||
|
||||
FrameID button_up(GameData::GUMPS, statbuttonshape, 0);
|
||||
FrameID button_down(GameData::GUMPS, statbuttonshape, 1);
|
||||
|
||||
Gump *widget = new ButtonWidget(statbuttonx, statbuttony,
|
||||
button_up, button_down);
|
||||
_statButtonId = widget->getObjId();
|
||||
widget->InitGump(this);
|
||||
}
|
||||
|
||||
void PaperdollGump::Close(bool no_del) {
|
||||
// NOTE: this does _not_ call its direct parent's Close function
|
||||
// because we do not want to close the Gumps of our contents.
|
||||
|
||||
// Make every item leave the fast area
|
||||
Container *c = getContainer(_owner);
|
||||
if (!c) return; // Container gone!?
|
||||
|
||||
for (auto *item : c->_contents) {
|
||||
item->leaveFastArea(); // Can destroy the item
|
||||
}
|
||||
|
||||
Item *o = getItem(_owner);
|
||||
if (o)
|
||||
o->clearGump(); //!! is this the appropriate place?
|
||||
|
||||
ItemRelativeGump::Close(no_del);
|
||||
}
|
||||
|
||||
void PaperdollGump::PaintStat(RenderSurface *surf, unsigned int n,
|
||||
Std::string text, int val) {
|
||||
assert(n < 7); // constant!
|
||||
|
||||
Font *font, *descfont;
|
||||
|
||||
font = FontManager::get_instance()->getGameFont(statfont);
|
||||
descfont = FontManager::get_instance()->getGameFont(statdescfont);
|
||||
char buf[16]; // enough for uint32
|
||||
unsigned int remaining;
|
||||
|
||||
if (!_cachedText[2 * n])
|
||||
_cachedText[2 * n] = descfont->renderText(text, remaining,
|
||||
statdescwidth, statheight,
|
||||
Font::TEXT_RIGHT);
|
||||
_cachedText[2 * n]->draw(surf, statcoords[n].xd, statcoords[n].y);
|
||||
|
||||
if (!_cachedText[2 * n + 1] || _cachedVal[n] != val) {
|
||||
delete _cachedText[2 * n + 1];
|
||||
Common::sprintf_s(buf, "%d", val);
|
||||
_cachedText[2 * n + 1] = font->renderText(buf, remaining,
|
||||
statwidth, statheight,
|
||||
Font::TEXT_RIGHT);
|
||||
_cachedVal[n] = val;
|
||||
}
|
||||
_cachedText[2 * n + 1]->draw(surf, statcoords[n].x, statcoords[n].y);
|
||||
}
|
||||
|
||||
void PaperdollGump::PaintStats(RenderSurface *surf, int32 lerp_factor) {
|
||||
Actor *a = getActor(_owner);
|
||||
assert(a);
|
||||
|
||||
int armour = a->getArmourClass();
|
||||
int weight = a->getTotalWeight();
|
||||
if (_displayDragging) {
|
||||
armour += _draggingArmourClass;
|
||||
weight += _draggingWeight;
|
||||
}
|
||||
|
||||
PaintStat(surf, 0, _TL_("STR"), a->getStr());
|
||||
PaintStat(surf, 1, _TL_("INT"), a->getInt());
|
||||
PaintStat(surf, 2, _TL_("DEX"), a->getDex());
|
||||
PaintStat(surf, 3, _TL_("ARMR"), armour);
|
||||
PaintStat(surf, 4, _TL_("HITS"), a->getHP());
|
||||
PaintStat(surf, 5, _TL_("MANA"), a->getMana());
|
||||
PaintStat(surf, 6, _TL_("WGHT"), weight / 10);
|
||||
}
|
||||
|
||||
void PaperdollGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
// paint self
|
||||
ItemRelativeGump::PaintThis(surf, lerp_factor, scaled);
|
||||
|
||||
Actor *a = getActor(_owner);
|
||||
|
||||
if (!a) {
|
||||
// Actor gone!?
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
PaintStats(surf, lerp_factor);
|
||||
|
||||
for (int i = 6; i >= 1; --i) { // constants
|
||||
Item *item = getItem(a->getEquip(i));
|
||||
if (!item) continue;
|
||||
int32 itemx, itemy;
|
||||
uint32 frame = item->getFrame() + 1;
|
||||
|
||||
itemx = equipcoords[i].x;
|
||||
itemy = equipcoords[i].y;
|
||||
itemx += _itemArea.left;
|
||||
itemy += _itemArea.top;
|
||||
const Shape *s = item->getShapeObject();
|
||||
assert(s);
|
||||
surf->Paint(s, frame, itemx, itemy);
|
||||
}
|
||||
|
||||
if (_displayDragging) {
|
||||
int32 itemx, itemy;
|
||||
itemx = _draggingX + _itemArea.left;
|
||||
itemy = _draggingY + _itemArea.top;
|
||||
Shape *s = GameData::get_instance()->getMainShapes()->
|
||||
getShape(_draggingShape);
|
||||
assert(s);
|
||||
surf->PaintInvisible(s, _draggingFrame, itemx, itemy, false, (_draggingFlags & Item::FLG_FLIPPED) != 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Find object (if any) at (mx,my)
|
||||
// (mx,my) are relative to parent
|
||||
uint16 PaperdollGump::TraceObjId(int32 mx, int32 my) {
|
||||
uint16 objId_ = Gump::TraceObjId(mx, my);
|
||||
if (objId_ && objId_ != 65535) return objId_;
|
||||
|
||||
ParentToGump(mx, my);
|
||||
|
||||
Actor *a = getActor(_owner);
|
||||
|
||||
if (!a)
|
||||
return 0; // Container gone!?
|
||||
|
||||
for (int i = 1; i <= 6; ++i) {
|
||||
Item *item = getItem(a->getEquip(i));
|
||||
if (!item) continue;
|
||||
int32 itemx, itemy;
|
||||
|
||||
itemx = equipcoords[i].x;
|
||||
itemy = equipcoords[i].y;
|
||||
itemx += _itemArea.left;
|
||||
itemy += _itemArea.top;
|
||||
const Shape *s = item->getShapeObject();
|
||||
assert(s);
|
||||
const ShapeFrame *frame = s->getFrame(item->getFrame() + 1);
|
||||
|
||||
if (frame->hasPoint(mx - itemx, my - itemy)) {
|
||||
// found it
|
||||
return item->getObjId();
|
||||
}
|
||||
}
|
||||
|
||||
// try backpack
|
||||
if (_backpackRect.contains(mx - _itemArea.left, my - _itemArea.top)) {
|
||||
ObjId bp = a->getEquip(ShapeInfo::SE_BACKPACK);
|
||||
if (bp)
|
||||
return bp;
|
||||
}
|
||||
|
||||
// didn't find anything, so return self
|
||||
return getObjId();
|
||||
}
|
||||
|
||||
// get item coords relative to self
|
||||
bool PaperdollGump::GetLocationOfItem(uint16 itemid, int32 &gx, int32 &gy,
|
||||
int32 lerp_factor) {
|
||||
|
||||
Item *item = getItem(itemid);
|
||||
if (!item)
|
||||
return false; // item gone - shouldn't happen?
|
||||
Item *parent = item->getParentAsContainer();
|
||||
if (!parent || parent->getObjId() != _owner)
|
||||
return false;
|
||||
|
||||
//!!! need to use lerp_factor
|
||||
|
||||
if (item->getShape() == 529) { //!! constant
|
||||
gx = _backpackRect.left;
|
||||
gy = _backpackRect.top;
|
||||
} else {
|
||||
int equiptype = item->getZ();
|
||||
assert(equiptype >= 0 && equiptype <= 6); //!! constants
|
||||
gx = equipcoords[equiptype].x;
|
||||
gy = equipcoords[equiptype].y;
|
||||
}
|
||||
gx += _itemArea.left;
|
||||
gy += _itemArea.top;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PaperdollGump::StartDraggingItem(Item *item, int mx, int my) {
|
||||
// can't drag backpack
|
||||
if (item->getShape() == 529) { //!! constant
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ret = ContainerGump::StartDraggingItem(item, mx, my);
|
||||
|
||||
// set dragging offset to center of item
|
||||
const Shape *s = item->getShapeObject();
|
||||
assert(s);
|
||||
const ShapeFrame *frame = s->getFrame(item->getFrame());
|
||||
assert(frame);
|
||||
|
||||
Mouse::get_instance()->setDraggingOffset(frame->_width / 2 - frame->_xoff,
|
||||
frame->_height / 2 - frame->_yoff);
|
||||
|
||||
// Remove equipment and clear owner on drag start for better drag feedback
|
||||
// NOTE: This original game appears to equip/unequip the item during drag instead of on drop
|
||||
if (_owner == item->getParent() && item->hasFlags(Item::FLG_EQUIPPED)) {
|
||||
Actor *a = getActor(_owner);
|
||||
if (a && a->removeItem(item)) {
|
||||
item->setParent(0);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool PaperdollGump::DraggingItem(Item *item, int mx, int my) {
|
||||
if (!_itemArea.contains(mx, my)) {
|
||||
_displayDragging = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
Actor *a = getActor(_owner);
|
||||
assert(a);
|
||||
|
||||
bool over_backpack = false;
|
||||
Container *backpack = getContainer(a->getEquip(7)); // constant!
|
||||
|
||||
if (backpack && _backpackRect.contains(mx - _itemArea.left, my - _itemArea.top)) {
|
||||
over_backpack = true;
|
||||
}
|
||||
|
||||
_displayDragging = true;
|
||||
|
||||
_draggingShape = item->getShape();
|
||||
_draggingFrame = item->getFrame();
|
||||
_draggingFlags = item->getFlags();
|
||||
_draggingArmourClass = 0;
|
||||
_draggingWeight = 0;
|
||||
|
||||
Container *root = item->getRootContainer();
|
||||
if (!root || root->getObjId() != _owner)
|
||||
_draggingWeight = item->getWeight();
|
||||
|
||||
const ShapeInfo *si = item->getShapeInfo();
|
||||
int equiptype = si->_equipType;
|
||||
// determine target location and set dragging_x/y
|
||||
if (!over_backpack && equiptype) {
|
||||
// check if item will fit (weight/volume/etc...)
|
||||
if (!a->CanAddItem(item, true)) {
|
||||
_displayDragging = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (si->_armourInfo) {
|
||||
_draggingArmourClass += si->_armourInfo[_draggingFrame]._armourClass;
|
||||
}
|
||||
if (si->_weaponInfo) {
|
||||
_draggingArmourClass += si->_weaponInfo->_armourBonus;
|
||||
}
|
||||
|
||||
_draggingFrame++;
|
||||
_draggingX = equipcoords[equiptype].x;
|
||||
_draggingY = equipcoords[equiptype].y;
|
||||
} else {
|
||||
// drop in backpack
|
||||
if (backpack && !backpack->CanAddItem(item, true)) {
|
||||
_displayDragging = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
_draggingX = _backpackRect.left + _backpackRect.width() / 2;
|
||||
_draggingY = _backpackRect.top + _backpackRect.height() / 2;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PaperdollGump::DropItem(Item *item, int mx, int my) {
|
||||
_displayDragging = false;
|
||||
_draggingArmourClass = 0;
|
||||
_draggingWeight = 0;
|
||||
|
||||
Actor *a = getActor(_owner);
|
||||
assert(a);
|
||||
|
||||
bool over_backpack = false;
|
||||
Container *backpack = getContainer(a->getEquip(7)); // constant!
|
||||
|
||||
if (backpack && _backpackRect.contains(mx - _itemArea.left, my - _itemArea.top)) {
|
||||
over_backpack = true;
|
||||
}
|
||||
|
||||
int equiptype = item->getShapeInfo()->_equipType;
|
||||
if (!over_backpack && equiptype) {
|
||||
item->moveToContainer(a);
|
||||
} else {
|
||||
item->moveToContainer(backpack);
|
||||
item->randomGumpLocation();
|
||||
}
|
||||
}
|
||||
|
||||
void PaperdollGump::ChildNotify(Gump *child, uint32 message) {
|
||||
if (child->getObjId() == _statButtonId &&
|
||||
(message == ButtonWidget::BUTTON_CLICK || message == ButtonWidget::BUTTON_DOUBLE)) {
|
||||
// check if there already is an open MiniStatsGump
|
||||
Gump *desktop = Ultima8Engine::get_instance()->getDesktopGump();
|
||||
Gump *statsgump = desktop->FindGump<MiniStatsGump>();
|
||||
|
||||
if (!statsgump) {
|
||||
Gump *gump = new MiniStatsGump(0, 0);
|
||||
gump->InitGump(0);
|
||||
gump->setRelativePosition(BOTTOM_RIGHT, -5, -5);
|
||||
} else {
|
||||
// check if it is off-screen. If so, move it back
|
||||
Common::Rect32 rect = desktop->getDims();
|
||||
Common::Rect32 sr = statsgump->getDims();
|
||||
sr.grow(-2);
|
||||
statsgump->GumpRectToScreenSpace(sr);
|
||||
if (!sr.intersects(rect))
|
||||
statsgump->setRelativePosition(BOTTOM_RIGHT, -5, -5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PaperdollGump::saveData(Common::WriteStream *ws) {
|
||||
ContainerGump::saveData(ws);
|
||||
|
||||
ws->writeUint16LE(_statButtonId);
|
||||
}
|
||||
|
||||
bool PaperdollGump::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
if (!ContainerGump::loadData(rs, version)) return false;
|
||||
|
||||
_statButtonId = rs->readUint16LE();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
95
engines/ultima/ultima8/gumps/paperdoll_gump.h
Normal file
95
engines/ultima/ultima8/gumps/paperdoll_gump.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_PAPERDOLLGUMP_H
|
||||
#define ULTIMA8_GUMPS_PAPERDOLLGUMP_H
|
||||
|
||||
#include "ultima/shared/std/string.h"
|
||||
#include "ultima/ultima8/gumps/container_gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class RenderedText;
|
||||
|
||||
/**
|
||||
* The gump activated by 'Z', which shows the avatar with current armor, and stats
|
||||
*/
|
||||
class PaperdollGump : public ContainerGump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
PaperdollGump();
|
||||
PaperdollGump(const Shape *shape, uint32 frameNum, uint16 owner,
|
||||
uint32 flags = FLAG_DRAGGABLE, int32 layer = LAYER_NORMAL);
|
||||
~PaperdollGump() override;
|
||||
|
||||
// Init the gump, call after construction
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
|
||||
// Close the gump
|
||||
void Close(bool no_del = false) override;
|
||||
|
||||
// Paint this Gump
|
||||
void PaintThis(RenderSurface *, int32 lerp_factor, bool scaled) override;
|
||||
|
||||
void ChildNotify(Gump *child, uint32 message) override;
|
||||
|
||||
// Trace a click, and return ObjId
|
||||
uint16 TraceObjId(int32 mx, int32 my) override;
|
||||
|
||||
// Get the location of an item in the gump (coords relative to this).
|
||||
// Returns false on failure.
|
||||
bool GetLocationOfItem(uint16 itemid, int32 &gx, int32 &gy,
|
||||
int32 lerp_factor = 256) override;
|
||||
|
||||
bool StartDraggingItem(Item *item, int mx, int my) override;
|
||||
bool DraggingItem(Item *item, int mx, int my) override;
|
||||
void DropItem(Item *item, int mx, int my) override;
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
|
||||
protected:
|
||||
//! Paint the stats
|
||||
void PaintStats(RenderSurface *, int32 lerp_factor);
|
||||
|
||||
//! Paint a single stat
|
||||
void PaintStat(RenderSurface *surf, unsigned int n,
|
||||
Std::string text, int val);
|
||||
|
||||
RenderedText *_cachedText[14]; // constant!!
|
||||
int _cachedVal[7]; // constant!!
|
||||
|
||||
uint16 _statButtonId;
|
||||
|
||||
uint32 _draggingArmourClass;
|
||||
uint32 _draggingWeight;
|
||||
|
||||
private:
|
||||
const Common::Rect32 _backpackRect;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
206
engines/ultima/ultima8/gumps/quit_gump.cpp
Normal file
206
engines/ultima/ultima8/gumps/quit_gump.cpp
Normal file
@@ -0,0 +1,206 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/audio/audio_process.h"
|
||||
#include "ultima/ultima8/gumps/quit_gump.h"
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/gfx/gump_shape_archive.h"
|
||||
#include "ultima/ultima8/gfx/shape.h"
|
||||
#include "ultima/ultima8/gfx/shape_frame.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
#include "ultima/ultima8/kernel/mouse.h"
|
||||
#include "ultima/ultima8/gumps/widgets/button_widget.h"
|
||||
#include "ultima/ultima8/gumps/widgets/text_widget.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(QuitGump)
|
||||
|
||||
static const int u8GumpShape = 17;
|
||||
static const int u8AskShapeId = 18;
|
||||
static const int u8YesShapeId = 47;
|
||||
static const int u8NoShapeId = 50;
|
||||
|
||||
static const int remGumpShape = 21;
|
||||
static const int remAskShapeId = 0;
|
||||
static const int remYesShapeId = 19;
|
||||
static const int remNoShapeId = 20;
|
||||
static const int remQuitSound = 0x109;
|
||||
|
||||
static const int regGumpShape = 21;
|
||||
static const int regAskShapeId = 0;
|
||||
static const int regYesShapeId = 19;
|
||||
static const int regNoShapeId = 20;
|
||||
static const int regQuitSound = 0; // TODO: Work out what sound id
|
||||
|
||||
QuitGump::QuitGump(): ModalGump(0, 0, 5, 5), _yesWidget(0), _noWidget(0) {
|
||||
Mouse *mouse = Mouse::get_instance();
|
||||
mouse->pushMouseCursor(Mouse::MOUSE_HAND);
|
||||
if (GAME_IS_U8) {
|
||||
_gumpShape = u8GumpShape;
|
||||
_askShape = u8AskShapeId;
|
||||
_yesShape = u8YesShapeId;
|
||||
_noShape = u8NoShapeId;
|
||||
_buttonXOff = 16;
|
||||
_buttonYOff = 38;
|
||||
_playSound = 0;
|
||||
} else if (GAME_IS_REMORSE) {
|
||||
_gumpShape = remGumpShape;
|
||||
_askShape = remAskShapeId;
|
||||
_yesShape = remYesShapeId;
|
||||
_noShape = remNoShapeId;
|
||||
_buttonXOff = 55;
|
||||
_buttonYOff = 47;
|
||||
_playSound = remQuitSound;
|
||||
} else if (GAME_IS_REGRET) {
|
||||
_gumpShape = regGumpShape;
|
||||
_askShape = regAskShapeId;
|
||||
_yesShape = regYesShapeId;
|
||||
_noShape = regNoShapeId;
|
||||
// TODO: These are pretty approximate, need adjusting.
|
||||
_buttonXOff = 50;
|
||||
_buttonYOff = 70;
|
||||
_playSound = regQuitSound;
|
||||
} else {
|
||||
error("unsupported game type");
|
||||
}
|
||||
}
|
||||
|
||||
QuitGump::~QuitGump() {
|
||||
Mouse::get_instance()->popMouseCursor();
|
||||
}
|
||||
|
||||
void QuitGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
ModalGump::InitGump(newparent, take_focus);
|
||||
|
||||
_shape = GameData::get_instance()->getGumps()->getShape(_gumpShape);
|
||||
UpdateDimsFromShape();
|
||||
|
||||
if (_askShape != 0) {
|
||||
FrameID askshape(GameData::GUMPS, _askShape, 0);
|
||||
askshape = _TL_SHP_(askshape);
|
||||
|
||||
if (askshape._shapeNum == 0) {
|
||||
// In JP U8, the ask gump is replaced with text
|
||||
// confirming quit
|
||||
Std::string askstr = _TL_("Quit the game?");
|
||||
Gump *widget = new TextWidget(0, 0, askstr, true, 6); // CONSTANT!
|
||||
widget->InitGump(this, false);
|
||||
widget->setRelativePosition(TOP_CENTER, 0, 13);
|
||||
} else {
|
||||
const Shape *askShape = GameData::get_instance()->getShape(askshape);
|
||||
const ShapeFrame *sf = askShape->getFrame(askshape._frameNum);
|
||||
assert(sf);
|
||||
|
||||
Gump *ask = new Gump(0, 0, sf->_width, sf->_height);
|
||||
ask->SetShape(askShape, askshape._frameNum);
|
||||
ask->InitGump(this);
|
||||
ask->setRelativePosition(TOP_CENTER, 0, 5);
|
||||
}
|
||||
}
|
||||
|
||||
FrameID yesbutton_up(GameData::GUMPS, _yesShape, 0);
|
||||
FrameID yesbutton_down(GameData::GUMPS, _yesShape, 1);
|
||||
yesbutton_up = _TL_SHP_(yesbutton_up);
|
||||
yesbutton_down = _TL_SHP_(yesbutton_down);
|
||||
|
||||
Gump *widget;
|
||||
widget = new ButtonWidget(0, 0, yesbutton_up, yesbutton_down);
|
||||
widget->InitGump(this);
|
||||
widget->setRelativePosition(TOP_LEFT, _buttonXOff, _buttonYOff);
|
||||
_yesWidget = widget->getObjId();
|
||||
|
||||
FrameID nobutton_up(GameData::GUMPS, _noShape, 0);
|
||||
FrameID nobutton_down(GameData::GUMPS, _noShape, 1);
|
||||
nobutton_up = _TL_SHP_(nobutton_up);
|
||||
nobutton_down = _TL_SHP_(nobutton_down);
|
||||
|
||||
widget = new ButtonWidget(0, 0, nobutton_up, nobutton_down);
|
||||
widget->InitGump(this);
|
||||
widget->setRelativePosition(TOP_RIGHT, -(int)_buttonXOff, _buttonYOff);
|
||||
_noWidget = widget->getObjId();
|
||||
|
||||
if (_playSound) {
|
||||
AudioProcess *audioproc = AudioProcess::get_instance();
|
||||
audioproc->playSFX(_playSound, 0x10, _objId, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void QuitGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
Gump::PaintThis(surf, lerp_factor, scaled);
|
||||
}
|
||||
|
||||
bool QuitGump::OnKeyDown(int key, int mod) {
|
||||
switch (key) {
|
||||
case Common::KEYCODE_ESCAPE: {
|
||||
Close();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void QuitGump::ChildNotify(Gump *child, uint32 message) {
|
||||
ObjId cid = child->getObjId();
|
||||
if (message == ButtonWidget::BUTTON_CLICK || message == ButtonWidget::BUTTON_DOUBLE) {
|
||||
if (cid == _yesWidget) {
|
||||
Ultima8Engine::get_instance()->quitGame();
|
||||
} else if (cid == _noWidget) {
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool QuitGump::OnTextInput(int unicode) {
|
||||
if (!(unicode & 0xFF80)) {
|
||||
char c = unicode & 0x7F;
|
||||
if (_TL_("Yy").find(c) != Std::string::npos) {
|
||||
Ultima8Engine::get_instance()->quitGame();
|
||||
} else if (_TL_("Nn").find(c) != Std::string::npos) {
|
||||
Close();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//static
|
||||
void QuitGump::verifyQuit() {
|
||||
ModalGump *gump = new QuitGump();
|
||||
gump->InitGump(0);
|
||||
gump->setRelativePosition(CENTER);
|
||||
}
|
||||
|
||||
bool QuitGump::loadData(Common::ReadStream *rs) {
|
||||
warning("Trying to load ModalGump");
|
||||
return true;
|
||||
}
|
||||
|
||||
void QuitGump::saveData(Common::WriteStream *ws) {
|
||||
warning("Trying to save ModalGump");
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
69
engines/ultima/ultima8/gumps/quit_gump.h
Normal file
69
engines/ultima/ultima8/gumps/quit_gump.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_QUITGUMP_H
|
||||
#define ULTIMA8_GUMPS_QUITGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/modal_gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/**
|
||||
* The "are you sure you want to quit?" gump
|
||||
*/
|
||||
class QuitGump : public ModalGump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
QuitGump();
|
||||
~QuitGump() override;
|
||||
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
|
||||
void PaintThis(RenderSurface *, int32 lerp_factor, bool scaled) override;
|
||||
|
||||
bool OnKeyDown(int key, int mod) override;
|
||||
bool OnTextInput(int unicode) override;
|
||||
void ChildNotify(Gump *child, uint32 message) override;
|
||||
|
||||
static void verifyQuit();
|
||||
|
||||
bool loadData(Common::ReadStream *rs);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
|
||||
protected:
|
||||
ObjId _yesWidget, _noWidget;
|
||||
|
||||
uint32 _gumpShape; //! shape number for the dialog
|
||||
uint32 _yesShape; //! shape number for "yes" button
|
||||
uint32 _noShape; //! shape number for "no" button
|
||||
uint32 _askShape; //! shape number for "are you sure?"
|
||||
uint32 _buttonXOff; //! x offset from either edge of yes/no buttons
|
||||
uint32 _buttonYOff; //! y offset from bottom of yes/no buttons
|
||||
uint32 _playSound; //! sound to play on open
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
128
engines/ultima/ultima8/gumps/readable_gump.cpp
Normal file
128
engines/ultima/ultima8/gumps/readable_gump.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/readable_gump.h"
|
||||
#include "ultima/ultima8/gumps/widgets/text_widget.h"
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/gfx/gump_shape_archive.h"
|
||||
#include "ultima/ultima8/usecode/uc_machine.h"
|
||||
#include "ultima/ultima8/gumps/gump_notify_process.h"
|
||||
#include "ultima/ultima8/world/item.h"
|
||||
#include "ultima/ultima8/world/get_object.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(ReadableGump)
|
||||
|
||||
const int jpsub_font = 6;
|
||||
|
||||
ReadableGump::ReadableGump()
|
||||
: ModalGump(), _shapeNum(0), _fontNum(0) {
|
||||
|
||||
}
|
||||
|
||||
ReadableGump::ReadableGump(ObjId owner, uint16 shape, int font, const Std::string &msg) :
|
||||
ModalGump(0, 0, 100, 100, owner), _shapeNum(shape), _fontNum(font), _text(msg) {
|
||||
}
|
||||
|
||||
ReadableGump::~ReadableGump(void) {
|
||||
}
|
||||
|
||||
void ReadableGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
ModalGump::InitGump(newparent, take_focus);
|
||||
|
||||
const Shape *shape = GameData::get_instance()->getGumps()->getShape(_shapeNum);
|
||||
|
||||
SetShape(shape, 0);
|
||||
|
||||
UpdateDimsFromShape();
|
||||
|
||||
if (Ultima8Engine::get_instance()->getGameInfo()->_language ==
|
||||
GameInfo::GAMELANG_JAPANESE) {
|
||||
// Japanese subtitles
|
||||
Std::string::size_type pos;
|
||||
pos = _text.find('%');
|
||||
if (pos != Std::string::npos) {
|
||||
Std::string jpsub = _text.substr(pos + 1);
|
||||
_text = _text.substr(0, pos);
|
||||
|
||||
Gump *subwidget = new TextWidget(0, 0, jpsub, true, jpsub_font, 0, 0, Font::TEXT_CENTER);
|
||||
subwidget->InitGump(this);
|
||||
subwidget->setRelativePosition(BOTTOM_CENTER, 0, -8);
|
||||
}
|
||||
}
|
||||
|
||||
Gump *widget = new TextWidget(0, 0, _text, true, _fontNum, _dims.width() - 16, 0, Font::TEXT_CENTER);
|
||||
widget->InitGump(this);
|
||||
widget->setRelativePosition(CENTER);
|
||||
}
|
||||
|
||||
Gump *ReadableGump::onMouseDown(int button, int32 mx, int32 my) {
|
||||
Close();
|
||||
return this;
|
||||
}
|
||||
|
||||
bool ReadableGump::OnKeyDown(int key, int mod) {
|
||||
Close();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint32 ReadableGump::I_readGrave(const uint8 *args, unsigned int /*argsize*/) {
|
||||
ARG_ITEM_FROM_PTR(item);
|
||||
ARG_UINT16(shape);
|
||||
ARG_STRING(str);
|
||||
assert(item);
|
||||
|
||||
Gump *gump = new ReadableGump(item->getObjId(), shape, 11, str);
|
||||
gump->InitGump(0);
|
||||
gump->setRelativePosition(CENTER);
|
||||
|
||||
return gump->GetNotifyProcess()->getPid();
|
||||
}
|
||||
|
||||
uint32 ReadableGump::I_readPlaque(const uint8 *args, unsigned int /*argsize*/) {
|
||||
ARG_ITEM_FROM_PTR(item);
|
||||
ARG_UINT16(shape);
|
||||
ARG_STRING(str);
|
||||
assert(item);
|
||||
|
||||
Gump *gump = new ReadableGump(item->getObjId(), shape, 10, str);
|
||||
gump->InitGump(0);
|
||||
gump->setRelativePosition(CENTER);
|
||||
|
||||
return gump->GetNotifyProcess()->getPid();
|
||||
}
|
||||
|
||||
void ReadableGump::saveData(Common::WriteStream *ws) {
|
||||
warning("Trying to load ModalGump");
|
||||
}
|
||||
|
||||
bool ReadableGump::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
warning("Trying to load ModalGump");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
64
engines/ultima/ultima8/gumps/readable_gump.h
Normal file
64
engines/ultima/ultima8/gumps/readable_gump.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_READABLEGUMP_H
|
||||
#define ULTIMA8_GUMPS_READABLEGUMP_H
|
||||
|
||||
#include "ultima/shared/std/string.h"
|
||||
#include "ultima/ultima8/gumps/modal_gump.h"
|
||||
#include "ultima/ultima8/usecode/intrinsics.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/**
|
||||
* The gump for popping up text in the game you can read (plaques and gravestones)
|
||||
*/
|
||||
class ReadableGump : public ModalGump {
|
||||
uint16 _shapeNum;
|
||||
int _fontNum;
|
||||
Std::string _text;
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
ReadableGump();
|
||||
ReadableGump(ObjId owner, uint16 shape, int font, const Std::string &msg);
|
||||
~ReadableGump() override;
|
||||
|
||||
// Close on mouse click on key press
|
||||
Gump *onMouseDown(int button, int32 mx, int32 my) override;
|
||||
bool OnKeyDown(int key, int mod) override;
|
||||
|
||||
// Init the gump, call after construction
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
|
||||
INTRINSIC(I_readGrave);
|
||||
INTRINSIC(I_readPlaque);
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
154
engines/ultima/ultima8/gumps/resizable_gump.cpp
Normal file
154
engines/ultima/ultima8/gumps/resizable_gump.cpp
Normal file
@@ -0,0 +1,154 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/resizable_gump.h"
|
||||
#include "ultima/ultima8/kernel/mouse.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
#define RESIZE_BORDER 5
|
||||
|
||||
ResizableGump::ResizableGump(int x, int y, int width, int height)
|
||||
: Gump(x, y, width, height, 0, FLAG_DRAGGABLE, LAYER_NORMAL),
|
||||
_dragPosition(Gump::CENTER), _mousePosition(Gump::CENTER), _minWidth(20), _minHeight(20) {
|
||||
}
|
||||
|
||||
ResizableGump::ResizableGump() : Gump(),
|
||||
_dragPosition(Gump::CENTER), _mousePosition(Gump::CENTER), _minWidth(20), _minHeight(20) {
|
||||
}
|
||||
|
||||
ResizableGump::~ResizableGump() {
|
||||
}
|
||||
|
||||
|
||||
Gump *ResizableGump::onMouseMotion(int32 mx, int32 my) {
|
||||
_mousePosition = getPosition(mx, my);
|
||||
return Gump::onMouseMotion(mx, my);
|
||||
}
|
||||
|
||||
void ResizableGump::onMouseLeft() {
|
||||
_mousePosition = Gump::CENTER;
|
||||
}
|
||||
|
||||
bool ResizableGump::onDragStart(int32 mx, int32 my) {
|
||||
if (Gump::onDragStart(mx, my)) {
|
||||
_dragPosition = getPosition(mx, my);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ResizableGump::onDragStop(int32 mx, int32 my) {
|
||||
_dragPosition = Gump::CENTER;
|
||||
}
|
||||
|
||||
void ResizableGump::onDrag(int32 mx, int32 my) {
|
||||
int32 x = _x;
|
||||
int32 y = _y;
|
||||
int32 w = _dims.width();
|
||||
int32 h = _dims.height();
|
||||
|
||||
int32 dx, dy;
|
||||
Mouse::get_instance()->getDraggingOffset(dx, dy);
|
||||
|
||||
int32 px = mx, py = my;
|
||||
ParentToGump(px, py);
|
||||
|
||||
switch (_dragPosition) {
|
||||
case Gump::CENTER:
|
||||
x = mx - dx;
|
||||
y = my - dy;
|
||||
break;
|
||||
case Gump::TOP_LEFT:
|
||||
w -= px - dx;
|
||||
h -= py - dy;
|
||||
x = mx - dx;
|
||||
y = my - dy;
|
||||
break;
|
||||
case Gump::TOP_RIGHT:
|
||||
w = px;
|
||||
h -= py - dy;
|
||||
y = my - dy;
|
||||
break;
|
||||
case Gump::BOTTOM_LEFT:
|
||||
w -= px - dx;
|
||||
h = py;
|
||||
x = mx - dx;
|
||||
break;
|
||||
case Gump::BOTTOM_RIGHT:
|
||||
w = px;
|
||||
h = py;
|
||||
break;
|
||||
case Gump::TOP_CENTER:
|
||||
h -= py - dy;
|
||||
y = my - dy;
|
||||
break;
|
||||
case Gump::BOTTOM_CENTER:
|
||||
h = py;
|
||||
break;
|
||||
case Gump::LEFT_CENTER:
|
||||
w -= px - dx;
|
||||
x = mx - dx;
|
||||
break;
|
||||
case Gump::RIGHT_CENTER:
|
||||
w = px;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (w >= _minWidth) {
|
||||
_dims.setWidth(w);
|
||||
_x = x;
|
||||
}
|
||||
|
||||
if (h >= _minHeight) {
|
||||
_dims.setHeight(h);
|
||||
_y = y;
|
||||
}
|
||||
}
|
||||
|
||||
Gump::Position ResizableGump::getPosition(int32 mx, int32 my) {
|
||||
Gump::Position position = Gump::CENTER;
|
||||
ParentToGump(mx, my);
|
||||
if (mx < _dims.left + RESIZE_BORDER && my < _dims.top + RESIZE_BORDER) {
|
||||
position = Gump::TOP_LEFT;
|
||||
} else if (mx >= _dims.right - RESIZE_BORDER && my < _dims.top + RESIZE_BORDER) {
|
||||
position = Gump::TOP_RIGHT;
|
||||
} else if (mx < _dims.left + RESIZE_BORDER && my >= _dims.bottom - RESIZE_BORDER) {
|
||||
position = Gump::BOTTOM_LEFT;
|
||||
} else if (mx >= _dims.right - RESIZE_BORDER && my >= _dims.bottom - RESIZE_BORDER) {
|
||||
position = Gump::BOTTOM_RIGHT;
|
||||
} else if (my < _dims.top + RESIZE_BORDER) {
|
||||
position = Gump::TOP_CENTER;
|
||||
} else if (my >= _dims.bottom - RESIZE_BORDER) {
|
||||
position = Gump::BOTTOM_CENTER;
|
||||
} else if (mx < _dims.left + RESIZE_BORDER) {
|
||||
position = Gump::LEFT_CENTER;
|
||||
} else if (mx >= _dims.right - RESIZE_BORDER) {
|
||||
position = Gump::RIGHT_CENTER;
|
||||
}
|
||||
return position;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
64
engines/ultima/ultima8/gumps/resizable_gump.h
Normal file
64
engines/ultima/ultima8/gumps/resizable_gump.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_RESIZABLEGUMP_H
|
||||
#define ULTIMA8_GUMPS_RESIZABLEGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/gump.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/**
|
||||
* Base class for gumps that can doesn't have a static size.
|
||||
* An example of such would be the Console and the GameMap gumps
|
||||
*/
|
||||
class ResizableGump : public Gump {
|
||||
protected:
|
||||
Gump::Position _dragPosition, _mousePosition;
|
||||
int32 _minWidth;
|
||||
int32 _minHeight;
|
||||
|
||||
public:
|
||||
ResizableGump();
|
||||
ResizableGump(int x, int y, int width, int height);
|
||||
~ResizableGump() override;
|
||||
|
||||
void setMinSize(int minWidth, int minHeight) {
|
||||
_minWidth = minWidth;
|
||||
_minHeight = minHeight;
|
||||
}
|
||||
|
||||
Gump *onMouseMotion(int32 mx, int32 my) override;
|
||||
void onMouseLeft() override;
|
||||
|
||||
bool onDragStart(int32 mx, int32 my) override;
|
||||
void onDragStop(int32 mx, int32 my) override;
|
||||
void onDrag(int32 mx, int32 my) override;
|
||||
|
||||
private:
|
||||
Gump::Position getPosition(int32 mx, int32 my);
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
122
engines/ultima/ultima8/gumps/scroll_gump.cpp
Normal file
122
engines/ultima/ultima8/gumps/scroll_gump.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/keyboard.h"
|
||||
#include "ultima/ultima8/gumps/scroll_gump.h"
|
||||
#include "ultima/ultima8/gumps/widgets/text_widget.h"
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/gfx/gump_shape_archive.h"
|
||||
#include "ultima/ultima8/usecode/uc_machine.h"
|
||||
#include "ultima/ultima8/gumps/gump_notify_process.h"
|
||||
#include "ultima/ultima8/world/item.h"
|
||||
#include "ultima/ultima8/world/get_object.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(ScrollGump)
|
||||
|
||||
// TODO: Remove all the hacks
|
||||
|
||||
ScrollGump::ScrollGump()
|
||||
: ModalGump(), _textWidget(0) {
|
||||
|
||||
}
|
||||
|
||||
ScrollGump::ScrollGump(ObjId owner, const Std::string &msg) :
|
||||
ModalGump(0, 0, 100, 100, owner), _text(msg), _textWidget(0) {
|
||||
}
|
||||
|
||||
ScrollGump::~ScrollGump(void) {
|
||||
}
|
||||
|
||||
void ScrollGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
ModalGump::InitGump(newparent, take_focus);
|
||||
|
||||
// Create the TextWidget
|
||||
Gump *widget = new TextWidget(22, 29, _text, true, 9, 204, 115, Font::TEXT_LEFT, true); //!! constants
|
||||
widget->InitGump(this);
|
||||
_textWidget = widget->getObjId();
|
||||
|
||||
_text.clear(); // no longer need this
|
||||
|
||||
const Shape *shape = GameData::get_instance()->getGumps()->getShape(19);
|
||||
|
||||
SetShape(shape, 0);
|
||||
UpdateDimsFromShape();
|
||||
}
|
||||
|
||||
void ScrollGump::NextText() {
|
||||
TextWidget *widget = dynamic_cast<TextWidget *>(getGump(_textWidget));
|
||||
assert(widget);
|
||||
if (!widget->setupNextText()) {
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
void ScrollGump::onMouseClick(int button, int32 mx, int32 my) {
|
||||
// Scroll to next _text, if possible
|
||||
NextText();
|
||||
}
|
||||
|
||||
void ScrollGump::onMouseDouble(int button, int32 mx, int32 my) {
|
||||
Close();
|
||||
}
|
||||
|
||||
bool ScrollGump::OnKeyDown(int key, int mod) {
|
||||
switch (key) {
|
||||
case Common::KEYCODE_ESCAPE:
|
||||
Close();
|
||||
break;
|
||||
case Common::KEYCODE_SPACE:
|
||||
NextText();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 ScrollGump::I_readScroll(const uint8 *args, unsigned int /*argsize*/) {
|
||||
ARG_ITEM_FROM_PTR(item);
|
||||
ARG_STRING(str);
|
||||
assert(item);
|
||||
|
||||
Gump *gump = new ScrollGump(item->getObjId(), str);
|
||||
gump->InitGump(0);
|
||||
gump->setRelativePosition(CENTER);
|
||||
|
||||
return gump->GetNotifyProcess()->getPid();
|
||||
}
|
||||
|
||||
void ScrollGump::saveData(Common::WriteStream *ws) {
|
||||
warning("Trying to save ModalGump");
|
||||
}
|
||||
|
||||
bool ScrollGump::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
warning("Trying to load ModalGump");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
70
engines/ultima/ultima8/gumps/scroll_gump.h
Normal file
70
engines/ultima/ultima8/gumps/scroll_gump.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_SCROLLGUMP_H
|
||||
#define ULTIMA8_GUMPS_SCROLLGUMP_H
|
||||
|
||||
#include "ultima/shared/std/string.h"
|
||||
#include "ultima/ultima8/gumps/modal_gump.h"
|
||||
#include "ultima/ultima8/usecode/intrinsics.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/**
|
||||
* A paper scroll (with a spell, etc)
|
||||
*/
|
||||
class ScrollGump : public ModalGump {
|
||||
Std::string _text;
|
||||
ObjId _textWidget;
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
ScrollGump();
|
||||
ScrollGump(ObjId owner, const Std::string &msg);
|
||||
~ScrollGump() override;
|
||||
|
||||
// Go to the next page on mouse click
|
||||
void onMouseClick(int button, int32 mx, int32 my) override;
|
||||
|
||||
// Close on double click
|
||||
void onMouseDouble(int button, int32 mx, int32 my) override;
|
||||
|
||||
bool OnKeyDown(int key, int mod) override;
|
||||
|
||||
// Init the gump, call after construction
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
|
||||
INTRINSIC(I_readScroll);
|
||||
|
||||
protected:
|
||||
void NextText();
|
||||
|
||||
public:
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
411
engines/ultima/ultima8/gumps/shape_viewer_gump.cpp
Normal file
411
engines/ultima/ultima8/gumps/shape_viewer_gump.cpp
Normal file
@@ -0,0 +1,411 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/file.h"
|
||||
|
||||
#include "ultima/ultima8/gumps/shape_viewer_gump.h"
|
||||
|
||||
#include "ultima/ultima8/gfx/render_surface.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
#include "ultima/ultima8/kernel/mouse.h"
|
||||
#include "ultima/ultima8/gfx/shape.h"
|
||||
#include "ultima/ultima8/gfx/shape_frame.h"
|
||||
#include "ultima/ultima8/gfx/shape_info.h"
|
||||
|
||||
#include "ultima/ultima8/gfx/fonts/rendered_text.h"
|
||||
#include "ultima/ultima8/gfx/fonts/font.h"
|
||||
#include "ultima/ultima8/gfx/fonts/font_manager.h"
|
||||
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/gfx/fonts/font_shape_archive.h"
|
||||
#include "ultima/ultima8/gfx/main_shape_archive.h"
|
||||
#include "ultima/ultima8/gfx/gump_shape_archive.h"
|
||||
#include "ultima/ultima8/gfx/mouse_shape_archive.h"
|
||||
#include "ultima/ultima8/gfx/texture.h"
|
||||
|
||||
#include "ultima/ultima8/convert/u8/convert_shape_u8.h"
|
||||
#include "ultima/ultima8/gfx/palette.h"
|
||||
#include "ultima/ultima8/gfx/palette_manager.h"
|
||||
#include "ultima/ultima8/usecode/usecode.h"
|
||||
|
||||
#include "ultima/ultima8/metaengine.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(ShapeViewerGump)
|
||||
|
||||
static const uint32 background_colors[] = {
|
||||
TEX32_PACK_RGB(0x10, 0x10, 0x10),
|
||||
TEX32_PACK_RGB(0x90, 0x90, 0x90)
|
||||
};
|
||||
|
||||
static const uint32 grid_colors[] = {
|
||||
TEX32_PACK_RGB(0x20, 0x20, 0x20),
|
||||
TEX32_PACK_RGB(0xA0, 0xA0, 0xA0)
|
||||
};
|
||||
|
||||
static const uint32 axis_colors[] = {
|
||||
TEX32_PACK_RGB(0x10, 0x30, 0x10),
|
||||
TEX32_PACK_RGB(0x90, 0xB0, 0x90)
|
||||
};
|
||||
|
||||
ShapeViewerGump::ShapeViewerGump()
|
||||
: ModalGump(), _curArchive(0), _curShape(0), _curFrame(0),
|
||||
_background(0), _fontNo(0), _showGrid(false), _mirrored(false),
|
||||
_shapeW(0), _shapeH(0), _shapeX(0), _shapeY(0) {
|
||||
|
||||
}
|
||||
|
||||
ShapeViewerGump::ShapeViewerGump(int x, int y, int width, int height,
|
||||
Common::Array<ShapeArchiveEntry> &archives,
|
||||
uint32 flags, int32 layer)
|
||||
: ModalGump(x, y, width, height, 0, flags, layer), _archives(archives),
|
||||
_curArchive(0), _curShape(0), _curFrame(0),
|
||||
_background(0), _fontNo(0), _showGrid(false), _mirrored(false),
|
||||
_shapeW(0), _shapeH(0), _shapeX(0), _shapeY(0) {
|
||||
|
||||
if (GAME_IS_CRUSADER) {
|
||||
// Default to a decent font on Crusader
|
||||
_fontNo = 6;
|
||||
}
|
||||
}
|
||||
|
||||
ShapeViewerGump::~ShapeViewerGump() {
|
||||
for (auto &entry : _archives) {
|
||||
if (entry._disposeAfterUse == DisposeAfterUse::YES) {
|
||||
delete entry._archive;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ShapeViewerGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
ModalGump::InitGump(newparent, take_focus);
|
||||
}
|
||||
|
||||
void ShapeViewerGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool /*scaled*/) {
|
||||
if (_archives.empty()) {
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 color = background_colors[_background];
|
||||
surf->fill32(color, _dims);
|
||||
|
||||
int32 posx = (_dims.width() - _shapeW) / 2 + _shapeX;
|
||||
int32 posy = (_dims.height() - _shapeH) / 2 + _shapeY - 25;
|
||||
|
||||
if (_showGrid) {
|
||||
const int step = 16;
|
||||
|
||||
color = grid_colors[_background];
|
||||
for (int i = step; i < _dims.width(); i += step) {
|
||||
int32 x = posx + i;
|
||||
if (x < _dims.right)
|
||||
surf->drawLine32(color, x, _dims.top, x, _dims.bottom - 1);
|
||||
|
||||
x = posx - i;
|
||||
if (x > _dims.left)
|
||||
surf->drawLine32(color, x, _dims.top, x, _dims.bottom - 1);
|
||||
}
|
||||
|
||||
for (int i = step; i < _dims.height(); i += step) {
|
||||
int32 y = posy + i;
|
||||
if (y < _dims.bottom)
|
||||
surf->drawLine32(color, _dims.left, y, _dims.right - 1, y);
|
||||
|
||||
y = posy - i;
|
||||
if (y > _dims.top)
|
||||
surf->drawLine32(color, _dims.left, y, _dims.right - 1, y);
|
||||
}
|
||||
|
||||
color = axis_colors[_background];
|
||||
surf->drawLine32(color, posx, _dims.top, posx, _dims.bottom - 1);
|
||||
surf->drawLine32(color, _dims.left, posy, _dims.right - 1, posy);
|
||||
}
|
||||
|
||||
ShapeArchive *archive = _archives[_curArchive]._archive;
|
||||
const Shape *shape = archive->getShape(_curShape);
|
||||
if (shape && _curFrame < shape->frameCount()) {
|
||||
surf->Paint(shape, _curFrame, posx, posy, _mirrored);
|
||||
}
|
||||
|
||||
RenderedText *rendtext;
|
||||
Font *font = FontManager::get_instance()->getGameFont(_fontNo, true);
|
||||
if (!font)
|
||||
return;
|
||||
|
||||
unsigned int remaining;
|
||||
|
||||
{
|
||||
// Basic shape/frame information
|
||||
char buf1[50];
|
||||
char buf2[200];
|
||||
if (!shape) {
|
||||
Common::sprintf_s(buf1, "NULL");
|
||||
} else {
|
||||
Common::sprintf_s(buf1, "Frame %d of %d", _curFrame+1, shape->frameCount());
|
||||
}
|
||||
Common::sprintf_s(buf2, "%s: Shape %d, %s %s", _archives[_curArchive]._name.c_str(),
|
||||
_curShape, buf1, _mirrored ? "(Mirrored)" : "");
|
||||
rendtext = font->renderText(buf2, remaining);
|
||||
rendtext->draw(surf, 8, 10);
|
||||
delete rendtext;
|
||||
}
|
||||
|
||||
if (!_mirrored) {
|
||||
// Dump the pixel val under the mouse cursor:
|
||||
int32 mx = 0;
|
||||
int32 my = 0;
|
||||
char buf2[200];
|
||||
|
||||
Mouse::get_instance()->getMouseCoords(mx, my);
|
||||
ScreenSpaceToGump(mx, my);
|
||||
|
||||
int32 relx = mx - (posx - _shapeX);
|
||||
int32 rely = my - (posy - _shapeY);
|
||||
if (shape && relx >= 0 && rely >= 0 && relx < _shapeW && rely < _shapeH) {
|
||||
// get color
|
||||
relx -= _shapeX;
|
||||
rely -= _shapeY;
|
||||
const ShapeFrame *frame = shape->getFrame(_curFrame);
|
||||
if (frame && frame->hasPoint(relx, rely)) {
|
||||
uint8 rawpx = frame->getPixel(relx, rely);
|
||||
uint8 px_r, px_g, px_b;
|
||||
shape->getPalette()->get(rawpx, px_r, px_g, px_b);
|
||||
|
||||
Common::sprintf_s(buf2, "px: (%d, %d)(%d, %d): %d (%d, %d, %d)", relx, rely, frame->_xoff, frame->_yoff, rawpx, px_r, px_g, px_b);
|
||||
rendtext = font->renderText(buf2, remaining);
|
||||
rendtext->draw(surf, 8, 25);
|
||||
delete rendtext;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
// Additional shapeinfo (only in main shapes archive)
|
||||
MainShapeArchive *mainshapes = dynamic_cast<MainShapeArchive *>(archive);
|
||||
if (!mainshapes || !shape) return;
|
||||
|
||||
char buf3[128];
|
||||
char buf4[128];
|
||||
char buf5[128];
|
||||
char buf6[512];
|
||||
const ShapeInfo *info = mainshapes->getShapeInfo(_curShape);
|
||||
if (info) {
|
||||
Common::sprintf_s(buf3, "x: %d, y: %d, z: %d\n flags: 0x%04X, family: %d",
|
||||
info->_x, info->_y, info->_z, info->_flags, info->_family);
|
||||
Common::sprintf_s(buf4, "equip type: %d, weight: %d, vol: %d",
|
||||
info->_equipType, info->_weight, info->_volume);
|
||||
Common::sprintf_s(buf5, "anim: type: %d, data: %d, speed: %d",
|
||||
info->_animType, info->_animData, info->_animSpeed);
|
||||
Common::sprintf_s(buf6, "ShapeInfo: %s\n%s\n%s\nUsecode: %s",
|
||||
buf3, buf4, buf5, GameData::get_instance()->getMainUsecode()->get_class_name(_curShape));
|
||||
rendtext = font->renderText(buf6, remaining);
|
||||
|
||||
int x, y;
|
||||
rendtext->getSize(x, y);
|
||||
rendtext->draw(surf, 8, _dims.height() - y);
|
||||
delete rendtext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ShapeViewerGump::OnKeyDown(int key, int mod) {
|
||||
ShapeArchive *archive = _archives[_curArchive]._archive;
|
||||
bool shapechanged = false;
|
||||
unsigned int delta = 1;
|
||||
if (mod & Common::KBD_SHIFT) delta = 10;
|
||||
|
||||
switch (key) {
|
||||
case Common::KEYCODE_UP:
|
||||
case Common::KEYCODE_k:
|
||||
if (delta >= archive->getCount())
|
||||
delta = 1;
|
||||
if (_curShape < delta)
|
||||
_curShape = archive->getCount() + _curShape - delta;
|
||||
else
|
||||
_curShape -= delta;
|
||||
shapechanged = true;
|
||||
_curFrame = 0;
|
||||
break;
|
||||
case Common::KEYCODE_DOWN:
|
||||
case Common::KEYCODE_j:
|
||||
if (delta >= archive->getCount())
|
||||
delta = 1;
|
||||
if (_curShape + delta >= archive->getCount())
|
||||
_curShape = _curShape + delta - archive->getCount();
|
||||
else
|
||||
_curShape += delta;
|
||||
_curFrame = 0;
|
||||
shapechanged = true;
|
||||
break;
|
||||
case Common::KEYCODE_LEFT:
|
||||
case Common::KEYCODE_h: {
|
||||
const Shape *shape = archive->getShape(_curShape);
|
||||
if (shape && shape->frameCount()) {
|
||||
if (delta >= shape->frameCount()) delta = 1;
|
||||
if (_curFrame < delta)
|
||||
_curFrame = shape->frameCount() + _curFrame - delta;
|
||||
else
|
||||
_curFrame -= delta;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Common::KEYCODE_RIGHT:
|
||||
case Common::KEYCODE_l: {
|
||||
const Shape *shape = archive->getShape(_curShape);
|
||||
if (shape && shape->frameCount()) {
|
||||
if (delta >= shape->frameCount()) delta = 1;
|
||||
if (_curFrame + delta >= shape->frameCount())
|
||||
_curFrame = _curFrame + delta - shape->frameCount();
|
||||
else
|
||||
_curFrame += delta;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Common::KEYCODE_COMMA:
|
||||
case Common::KEYCODE_PAGEUP: {
|
||||
if (_curArchive == 0)
|
||||
_curArchive = _archives.size() - 1;
|
||||
else
|
||||
_curArchive--;
|
||||
|
||||
archive = _archives[_curArchive]._archive;
|
||||
shapechanged = true;
|
||||
_curShape = 0;
|
||||
_curFrame = 0;
|
||||
}
|
||||
break;
|
||||
case Common::KEYCODE_PERIOD:
|
||||
case Common::KEYCODE_PAGEDOWN: {
|
||||
if (_curArchive + 1 == _archives.size())
|
||||
_curArchive = 0;
|
||||
else
|
||||
_curArchive++;
|
||||
|
||||
archive = _archives[_curArchive]._archive;
|
||||
shapechanged = true;
|
||||
_curShape = 0;
|
||||
_curFrame = 0;
|
||||
}
|
||||
break;
|
||||
case Common::KEYCODE_f: {
|
||||
_fontNo++;
|
||||
if (_fontNo >= GameData::get_instance()->getFonts()->getCount() ||
|
||||
_fontNo > 17) {
|
||||
_fontNo = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Common::KEYCODE_m: {
|
||||
_mirrored = !_mirrored;
|
||||
}
|
||||
break;
|
||||
case Common::KEYCODE_g: {
|
||||
_showGrid = !_showGrid;
|
||||
}
|
||||
break;
|
||||
case Common::KEYCODE_b: {
|
||||
_background = _background ? 0 : 1;
|
||||
} break;
|
||||
case Common::KEYCODE_ESCAPE: {
|
||||
Close();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (shapechanged) {
|
||||
const Shape *shape = archive->getShape(_curShape);
|
||||
if (shape)
|
||||
shape->getTotalDimensions(_shapeW, _shapeH, _shapeX, _shapeY);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//static
|
||||
void ShapeViewerGump::U8ShapeViewer() {
|
||||
GameData *gamedata = GameData::get_instance();
|
||||
|
||||
Common::Array<ShapeArchiveEntry> archives;
|
||||
archives.push_back(ShapeArchiveEntry("shapes", gamedata->getMainShapes()));
|
||||
archives.push_back(ShapeArchiveEntry("gumps", gamedata->getGumps()));
|
||||
archives.push_back(ShapeArchiveEntry("fonts", gamedata->getFonts()));
|
||||
|
||||
ShapeArchive *mouseShapes = new MouseShapeArchive(gamedata->getMouse(), GameData::OTHER);
|
||||
archives.push_back(ShapeArchiveEntry("mouse", mouseShapes, DisposeAfterUse::YES));
|
||||
|
||||
auto *eintro = new Common::File();
|
||||
if (eintro->open("static/eintro.skf")) {
|
||||
ShapeArchive *eintroshapes = new ShapeArchive(eintro, GameData::OTHER,
|
||||
PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game),
|
||||
&U8SKFShapeFormat);
|
||||
archives.push_back(ShapeArchiveEntry("eintro", eintroshapes, DisposeAfterUse::YES));
|
||||
} else {
|
||||
delete eintro;
|
||||
}
|
||||
|
||||
auto *endgame = new Common::File();
|
||||
if (endgame->open("static/endgame.skf")) {
|
||||
ShapeArchive *endgameshapes = new ShapeArchive(endgame, GameData::OTHER,
|
||||
PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game),
|
||||
&U8SKFShapeFormat);
|
||||
archives.push_back(ShapeArchiveEntry("endgame", endgameshapes, DisposeAfterUse::YES));
|
||||
} else {
|
||||
delete endgame;
|
||||
}
|
||||
|
||||
Gump *desktopGump = Ultima8Engine::get_instance()->getDesktopGump();
|
||||
Common::Rect32 res = desktopGump->getDims();
|
||||
|
||||
int xoff, yoff, width, height;
|
||||
|
||||
if (res.height() > 240) {
|
||||
width = (res.width() * 4) / 5;
|
||||
height = (res.height() * 5) / 6;
|
||||
xoff = res.width() / 10;
|
||||
yoff = res.height() / 12;
|
||||
} else {
|
||||
width = (res.width() * 9) / 10;
|
||||
height = (res.height() * 11) / 12;
|
||||
xoff = res.width() / 20;
|
||||
yoff = res.height() / 24;
|
||||
}
|
||||
|
||||
ModalGump *gump = new ShapeViewerGump(xoff, yoff, width, height, archives);
|
||||
gump->InitGump(0);
|
||||
}
|
||||
|
||||
bool ShapeViewerGump::loadData(Common::ReadStream *rs) {
|
||||
warning("Trying to load ModalGump");
|
||||
return false;
|
||||
}
|
||||
|
||||
void ShapeViewerGump::saveData(Common::WriteStream *ws) {
|
||||
warning("Trying to save ModalGump");
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
89
engines/ultima/ultima8/gumps/shape_viewer_gump.h
Normal file
89
engines/ultima/ultima8/gumps/shape_viewer_gump.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_SHAPEVIEWERGUMP_H
|
||||
#define ULTIMA8_GUMPS_SHAPEVIEWERGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/modal_gump.h"
|
||||
|
||||
#include "ultima/shared/std/containers.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class ShapeArchive;
|
||||
|
||||
/**
|
||||
* A tool for viewing the shapes in the game, for debugging purposes.
|
||||
*/
|
||||
class ShapeViewerGump : public ModalGump {
|
||||
public:
|
||||
struct ShapeArchiveEntry {
|
||||
Common::String _name;
|
||||
ShapeArchive *_archive;
|
||||
DisposeAfterUse::Flag _disposeAfterUse;
|
||||
|
||||
ShapeArchiveEntry(const char *name, ShapeArchive *archive, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::NO)
|
||||
: _name(name), _archive(archive), _disposeAfterUse(disposeAfterUse) {}
|
||||
};
|
||||
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
ShapeViewerGump();
|
||||
ShapeViewerGump(int x, int y, int width, int height,
|
||||
Common::Array<ShapeArchiveEntry> &archives,
|
||||
uint32 flags = FLAG_PREVENT_SAVE, int32 layer = LAYER_MODAL);
|
||||
~ShapeViewerGump() override;
|
||||
|
||||
void PaintThis(RenderSurface *, int32 lerp_factor, bool scaled) override;
|
||||
|
||||
bool OnKeyDown(int key, int mod) override;
|
||||
|
||||
// Init the gump, call after construction
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
|
||||
static void U8ShapeViewer();
|
||||
|
||||
bool loadData(Common::ReadStream *rs);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
|
||||
protected:
|
||||
Common::Array<ShapeArchiveEntry> _archives;
|
||||
unsigned int _curArchive;
|
||||
uint32 _curShape;
|
||||
uint32 _curFrame;
|
||||
|
||||
uint32 _background;
|
||||
|
||||
//! The font used in the shape viewer
|
||||
uint32 _fontNo;
|
||||
|
||||
bool _showGrid;
|
||||
bool _mirrored;
|
||||
|
||||
int32 _shapeW, _shapeH, _shapeX, _shapeY;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
232
engines/ultima/ultima8/gumps/slider_gump.cpp
Normal file
232
engines/ultima/ultima8/gumps/slider_gump.cpp
Normal file
@@ -0,0 +1,232 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/slider_gump.h"
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/gfx/gump_shape_archive.h"
|
||||
#include "ultima/ultima8/gumps/widgets/sliding_widget.h"
|
||||
#include "ultima/ultima8/gfx/fonts/font.h"
|
||||
#include "ultima/ultima8/gfx/fonts/rendered_text.h"
|
||||
#include "ultima/ultima8/gfx/fonts/font_manager.h"
|
||||
#include "ultima/ultima8/gumps/widgets/button_widget.h"
|
||||
#include "ultima/ultima8/usecode/uc_process.h"
|
||||
#include "ultima/ultima8/kernel/kernel.h"
|
||||
#include "ultima/ultima8/kernel/mouse.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(SliderGump)
|
||||
|
||||
SliderGump::SliderGump() : ModalGump(), _renderedText(nullptr), _min(0), _max(0),
|
||||
_delta(0), _value(0), _usecodeNotifyPID(0), _renderedValue(-1) {
|
||||
}
|
||||
|
||||
|
||||
SliderGump::SliderGump(int x, int y, int16 min, int16 max,
|
||||
int16 value, int16 delta)
|
||||
: ModalGump(x, y, 5, 5), _min(min), _max(max), _delta(delta), _value(value),
|
||||
_usecodeNotifyPID(0), _renderedText(nullptr), _renderedValue(-1) {
|
||||
}
|
||||
|
||||
SliderGump::~SliderGump() {
|
||||
}
|
||||
|
||||
/*
|
||||
41:0 = slider gump
|
||||
42:0,1 = ok button
|
||||
43:0,1 = left button
|
||||
44:0,1 = right button
|
||||
45:0 = slider
|
||||
*/
|
||||
|
||||
static const int gumpshape = 41;
|
||||
static const int okshape = 42;
|
||||
static const int leftshape = 43;
|
||||
static const int rightshape = 44;
|
||||
static const int slidershape = 45;
|
||||
static const int sliderframe = 0;
|
||||
static const int slidery = 17;
|
||||
static const int sliderminx = 55;
|
||||
static const int slidermaxx = 140;
|
||||
static const int labelx = 18;
|
||||
static const int labely = 26;
|
||||
static const int labelfont = 0;
|
||||
|
||||
static const int OK_INDEX = 1;
|
||||
static const int LEFT_INDEX = 2;
|
||||
static const int RIGHT_INDEX = 3;
|
||||
static const int SLIDER_INDEX = 4;
|
||||
|
||||
void SliderGump::setSliderPos() {
|
||||
SlidingWidget *slider = dynamic_cast<SlidingWidget *>(Gump::FindGump<SlidingWidget>());
|
||||
assert(slider);
|
||||
slider->setValueForRange(_value, _min, _max);
|
||||
}
|
||||
|
||||
void SliderGump::drawText(RenderSurface *surf) {
|
||||
if (!_renderedText || _value != _renderedValue) {
|
||||
Font *font;
|
||||
font = FontManager::get_instance()->getGameFont(labelfont);
|
||||
char buf[10]; // more than enough for a int16
|
||||
Common::sprintf_s(buf, "%d", _value);
|
||||
|
||||
unsigned int remaining;
|
||||
delete _renderedText;
|
||||
_renderedText = font->renderText(buf, remaining);
|
||||
_renderedValue = _value;
|
||||
}
|
||||
|
||||
_renderedText->draw(surf, labelx, labely);
|
||||
}
|
||||
|
||||
void SliderGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
Gump::PaintThis(surf, lerp_factor, scaled);
|
||||
|
||||
drawText(surf);
|
||||
}
|
||||
|
||||
|
||||
void SliderGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
ModalGump::InitGump(newparent, take_focus);
|
||||
|
||||
_shape = GameData::get_instance()->getGumps()->getShape(gumpshape);
|
||||
UpdateDimsFromShape();
|
||||
|
||||
// Create the SlidingWidget
|
||||
FrameID frame(GameData::GUMPS, slidershape, sliderframe);
|
||||
SlidingWidget *slider = new SlidingWidget(sliderminx, slidery, frame, Common::Rect32(sliderminx, slidery, slidermaxx, slidery));
|
||||
slider->SetIndex(SLIDER_INDEX);
|
||||
slider->InitGump(this);
|
||||
slider->setValueForRange(_value, _min, _max);
|
||||
|
||||
FrameID button_up(GameData::GUMPS, okshape, 0);
|
||||
FrameID button_down(GameData::GUMPS, okshape, 1);
|
||||
|
||||
Gump *widget = new ButtonWidget(158, 17, button_up, button_down);
|
||||
widget->SetIndex(OK_INDEX);
|
||||
widget->InitGump(this);
|
||||
|
||||
FrameID buttonleft_up(GameData::GUMPS, leftshape, 0);
|
||||
FrameID buttonleft_down(GameData::GUMPS, leftshape, 0);
|
||||
|
||||
widget = new ButtonWidget(36, 17, buttonleft_up, buttonleft_down);
|
||||
widget->SetIndex(LEFT_INDEX);
|
||||
widget->InitGump(this);
|
||||
|
||||
|
||||
FrameID buttonright_up(GameData::GUMPS, rightshape, 0);
|
||||
FrameID buttonright_down(GameData::GUMPS, rightshape, 0);
|
||||
|
||||
widget = new ButtonWidget(141, 17, buttonright_up, buttonright_down);
|
||||
widget->SetIndex(RIGHT_INDEX);
|
||||
widget->InitGump(this);
|
||||
}
|
||||
|
||||
void SliderGump::ChildNotify(Gump *child, uint32 message) {
|
||||
switch (child->GetIndex()) {
|
||||
case OK_INDEX:
|
||||
if (message == ButtonWidget::BUTTON_CLICK || message == ButtonWidget::BUTTON_DOUBLE)
|
||||
Close();
|
||||
break;
|
||||
case LEFT_INDEX:
|
||||
if (message == ButtonWidget::BUTTON_UP) {
|
||||
_value -= _delta;
|
||||
if (_value < _min)
|
||||
_value = _min;
|
||||
setSliderPos();
|
||||
}
|
||||
break;
|
||||
case RIGHT_INDEX:
|
||||
if (message == ButtonWidget::BUTTON_UP) {
|
||||
_value += _delta;
|
||||
if (_value > _max)
|
||||
_value = _max;
|
||||
setSliderPos();
|
||||
}
|
||||
break;
|
||||
case SLIDER_INDEX:
|
||||
if (message == SlidingWidget::DRAGGING) {
|
||||
SlidingWidget *slider = dynamic_cast<SlidingWidget *>(child);
|
||||
assert(slider);
|
||||
_value = slider->getValueForRange(_min, _max);
|
||||
_value = _min + _delta * (static_cast<int16>(_value / _delta));
|
||||
|
||||
// Set value to force slider to snap to increment
|
||||
slider->setValueForRange(_value, _min, _max);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SliderGump::Close(bool no_del) {
|
||||
_processResult = _value;
|
||||
|
||||
if (_usecodeNotifyPID) {
|
||||
UCProcess *ucp = dynamic_cast<UCProcess *>(Kernel::get_instance()->getProcess(_usecodeNotifyPID));
|
||||
assert(ucp);
|
||||
ucp->setReturnValue(_value);
|
||||
ucp->wakeUp(_value);
|
||||
}
|
||||
|
||||
ModalGump::Close(no_del);
|
||||
}
|
||||
|
||||
bool SliderGump::OnKeyDown(int key, int mod) {
|
||||
switch (key) {
|
||||
case Common::KEYCODE_LEFT:
|
||||
_value -= _delta;
|
||||
if (_value < _min) _value = _min;
|
||||
setSliderPos();
|
||||
break;
|
||||
case Common::KEYCODE_RIGHT:
|
||||
_value += _delta;
|
||||
if (_value > _max) _value = _max;
|
||||
setSliderPos();
|
||||
break;
|
||||
case Common::KEYCODE_RETURN:
|
||||
Close();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SliderGump::setUsecodeNotify(UCProcess *ucp) {
|
||||
assert(ucp);
|
||||
_usecodeNotifyPID = ucp->getPid();
|
||||
}
|
||||
|
||||
void SliderGump::saveData(Common::WriteStream *ws) {
|
||||
warning("Trying to save ModalGump");
|
||||
}
|
||||
|
||||
bool SliderGump::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
warning("Trying to load ModalGump");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
76
engines/ultima/ultima8/gumps/slider_gump.h
Normal file
76
engines/ultima/ultima8/gumps/slider_gump.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_SLIDERGUMP_H
|
||||
#define ULTIMA8_GUMPS_SLIDERGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/modal_gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class UCProcess;
|
||||
class RenderedText;
|
||||
|
||||
/**
|
||||
* A slider that lets you choose how many things to move (eg, when moving stacked items in the backpack)
|
||||
*/
|
||||
class SliderGump : public ModalGump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
SliderGump();
|
||||
SliderGump(int x, int y, int16 min, int16 max,
|
||||
int16 value, int16 delta = 1);
|
||||
~SliderGump() override;
|
||||
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
void PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) override;
|
||||
void Close(bool no_del = false) override;
|
||||
void ChildNotify(Gump *child, uint32 message) override;
|
||||
|
||||
void setUsecodeNotify(UCProcess *ucp);
|
||||
|
||||
bool OnKeyDown(int key, int mod) override;
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
|
||||
protected:
|
||||
int16 _min;
|
||||
int16 _max;
|
||||
int16 _delta;
|
||||
int16 _value;
|
||||
|
||||
uint16 _usecodeNotifyPID;
|
||||
|
||||
int16 _renderedValue;
|
||||
RenderedText *_renderedText;
|
||||
|
||||
void setSliderPos();
|
||||
void drawText(RenderSurface *surf);
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
129
engines/ultima/ultima8/gumps/target_gump.cpp
Normal file
129
engines/ultima/ultima8/gumps/target_gump.cpp
Normal file
@@ -0,0 +1,129 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima.h"
|
||||
#include "ultima/ultima8/gumps/target_gump.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
#include "ultima/ultima8/kernel/mouse.h"
|
||||
#include "ultima/ultima8/gumps/gump_notify_process.h"
|
||||
#include "ultima/ultima8/world/item.h"
|
||||
#include "ultima/ultima8/world/get_object.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(TargetGump)
|
||||
|
||||
TargetGump::TargetGump() : ModalGump(), _targetTracing(false) {
|
||||
|
||||
}
|
||||
|
||||
// Skip pause as usecode processes need to complete & matches original game
|
||||
TargetGump::TargetGump(int x, int y)
|
||||
: ModalGump(x, y, 0, 0, 0, FLAG_DONT_SAVE | FLAG_PREVENT_SAVE, LAYER_MODAL, false),
|
||||
_targetTracing(false) {
|
||||
|
||||
}
|
||||
|
||||
TargetGump::~TargetGump() {
|
||||
}
|
||||
|
||||
void TargetGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
// we're invisible
|
||||
}
|
||||
|
||||
void TargetGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
ModalGump::InitGump(newparent, take_focus);
|
||||
|
||||
// we need a notifier process
|
||||
CreateNotifier();
|
||||
|
||||
Mouse *mouse = Mouse::get_instance();
|
||||
mouse->pushMouseCursor(Mouse::MOUSE_TARGET);
|
||||
}
|
||||
|
||||
void TargetGump::Close(bool no_del) {
|
||||
Mouse *mouse = Mouse::get_instance();
|
||||
mouse->popMouseCursor();
|
||||
|
||||
ModalGump::Close(no_del);
|
||||
}
|
||||
|
||||
bool TargetGump::PointOnGump(int mx, int my) {
|
||||
// HACK alert: if we're currently tracing from TargetGump::onMouseUp,
|
||||
// then we do NOT want to intercept the trace
|
||||
if (_targetTracing) return false;
|
||||
|
||||
return ModalGump::PointOnGump(mx, my);
|
||||
}
|
||||
|
||||
void TargetGump::onMouseUp(int button, int32 mx, int32 my) {
|
||||
if (button == Mouse::BUTTON_LEFT) {
|
||||
_targetTracing = true;
|
||||
|
||||
_parent->GumpToScreenSpace(mx, my);
|
||||
|
||||
Gump *desktopgump = _parent;
|
||||
ObjId objId = desktopgump->TraceObjId(mx, my);
|
||||
Item *item = getItem(objId);
|
||||
|
||||
if (item) {
|
||||
// done
|
||||
debugC(kDebugObject, "Target result: %s", item->dumpInfo().c_str());
|
||||
|
||||
_processResult = objId;
|
||||
Close();
|
||||
}
|
||||
|
||||
_targetTracing = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool TargetGump::OnKeyDown(int key, int mod) {
|
||||
switch (key) {
|
||||
case Common::KEYCODE_ESCAPE: {
|
||||
Close();
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 TargetGump::I_target(const uint8 * /*args*/, unsigned int /*argsize*/) {
|
||||
TargetGump *targetgump = new TargetGump(0, 0);
|
||||
targetgump->InitGump(0);
|
||||
|
||||
return targetgump->GetNotifyProcess()->getPid();
|
||||
}
|
||||
|
||||
void TargetGump::saveData(Common::WriteStream *ws) {
|
||||
warning("Trying to save ModalGump");
|
||||
}
|
||||
|
||||
bool TargetGump::loadData(Common::ReadStream *rs, uint32 versin) {
|
||||
warning("Trying to load ModalGump");
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
62
engines/ultima/ultima8/gumps/target_gump.h
Normal file
62
engines/ultima/ultima8/gumps/target_gump.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_TARGETGUMP_H
|
||||
#define ULTIMA8_GUMPS_TARGETGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/modal_gump.h"
|
||||
#include "ultima/ultima8/usecode/intrinsics.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class UCProcess;
|
||||
|
||||
class TargetGump : public ModalGump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
TargetGump();
|
||||
TargetGump(int x, int y);
|
||||
|
||||
~TargetGump() override;
|
||||
|
||||
bool PointOnGump(int mx, int my) override;
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
void Close(bool no_del = false) override;
|
||||
void PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) override;
|
||||
void onMouseUp(int button, int32 mx, int32 my) override;
|
||||
bool OnKeyDown(int key, int mod) override;
|
||||
|
||||
INTRINSIC(I_target);
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
|
||||
private:
|
||||
bool _targetTracing;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
55
engines/ultima/ultima8/gumps/translucent_gump.cpp
Normal file
55
engines/ultima/ultima8/gumps/translucent_gump.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/translucent_gump.h"
|
||||
#include "ultima/ultima8/gfx/render_surface.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(TranslucentGump)
|
||||
TranslucentGump::TranslucentGump() : Gump() {
|
||||
}
|
||||
|
||||
TranslucentGump::TranslucentGump(int x, int y, int width, int height,
|
||||
uint16 owner, uint32 flags, int32 layer) :
|
||||
Gump(x, y, width, height, owner, flags, layer) {
|
||||
}
|
||||
|
||||
TranslucentGump::~TranslucentGump() {
|
||||
}
|
||||
|
||||
void TranslucentGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
if (_shape) {
|
||||
surf->PaintTranslucent(_shape, _frameNum, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void TranslucentGump::saveData(Common::WriteStream *ws) {
|
||||
Gump::saveData(ws);
|
||||
}
|
||||
|
||||
bool TranslucentGump::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
return Gump::loadData(rs, version);
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
53
engines/ultima/ultima8/gumps/translucent_gump.h
Normal file
53
engines/ultima/ultima8/gumps/translucent_gump.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_TRANSLUCENTGUMP_H
|
||||
#define ULTIMA8_GUMPS_TRANSLUCENTGUMP_H
|
||||
|
||||
#include "ultima/ultima8/gumps/gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/**
|
||||
* A regular gump that paints itself translucent
|
||||
*/
|
||||
class TranslucentGump : public Gump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
TranslucentGump();
|
||||
TranslucentGump(int x, int y, int width, int height, uint16 owner = 0,
|
||||
uint32 flags = 0, int32 layer = LAYER_NORMAL);
|
||||
~TranslucentGump() override;
|
||||
|
||||
// Paint this Gump
|
||||
void PaintThis(RenderSurface *, int32 lerp_factor, bool scaled) override;
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
342
engines/ultima/ultima8/gumps/u8_save_gump.cpp
Normal file
342
engines/ultima/ultima8/gumps/u8_save_gump.cpp
Normal file
@@ -0,0 +1,342 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/u8_save_gump.h"
|
||||
#include "ultima/ultima8/gumps/widgets/edit_widget.h"
|
||||
#include "ultima/ultima8/gumps/widgets/text_widget.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
#include "ultima/ultima8/kernel/mouse.h"
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/gfx/shape.h"
|
||||
#include "ultima/ultima8/gfx/shape_frame.h"
|
||||
#include "ultima/ultima8/filesys/savegame.h"
|
||||
#include "ultima/ultima8/gumps/paged_gump.h"
|
||||
#include "ultima/ultima8/world/get_object.h"
|
||||
#include "ultima/ultima8/world/actors/main_actor.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/translation.h"
|
||||
#include "gui/message.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
static const int entryfont = 4;
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(U8SaveGump)
|
||||
|
||||
U8SaveGump::U8SaveGump(bool saveMode, int page)
|
||||
: Gump(0, 0, 5, 5), _save(saveMode), _page(page) {
|
||||
}
|
||||
|
||||
U8SaveGump::~U8SaveGump() {
|
||||
}
|
||||
|
||||
|
||||
// gumps: 36/0-11: number 1-12
|
||||
// 46/0: "Entry"
|
||||
|
||||
void U8SaveGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
Gump::InitGump(newparent, take_focus);
|
||||
|
||||
_dims.setWidth(220);
|
||||
_dims.setHeight(170);
|
||||
|
||||
FrameID entry_id(GameData::GUMPS, 46, 0);
|
||||
entry_id = _TL_SHP_(entry_id);
|
||||
|
||||
const Shape *entryShape = GameData::get_instance()->getShape(entry_id);
|
||||
const ShapeFrame *sf = entryShape->getFrame(entry_id._frameNum);
|
||||
int entrywidth = sf->_width;
|
||||
int entryheight = sf->_height;
|
||||
|
||||
if (_save)
|
||||
_editWidgets.resize(6); // constant!
|
||||
|
||||
loadDescriptions();
|
||||
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
int index = _page * 6 + i;
|
||||
|
||||
|
||||
int xbase = 3;
|
||||
int yi = i;
|
||||
if (i >= 3) {
|
||||
xbase += _dims.width() / 2 + 9;
|
||||
yi -= 3;
|
||||
}
|
||||
|
||||
Gump *gump = new Gump(xbase, 3 + 40 * yi, 1, 1);
|
||||
gump->SetShape(entry_id, true);
|
||||
gump->InitGump(this, false);
|
||||
|
||||
int x = xbase + 2 + entrywidth;
|
||||
|
||||
if (index >= 9) { // index 9 is labelled "10"
|
||||
FrameID entrynum1_id(GameData::GUMPS, 36, (index + 1) / 10 - 1);
|
||||
entrynum1_id = _TL_SHP_(entrynum1_id);
|
||||
entryShape = GameData::get_instance()->getShape(entrynum1_id);
|
||||
sf = entryShape->getFrame(entrynum1_id._frameNum);
|
||||
x += 1 + sf->_width;
|
||||
|
||||
gump = new Gump(xbase + 2 + entrywidth, 3 + 40 * yi, 1, 1);
|
||||
gump->SetShape(entrynum1_id, true);
|
||||
gump->InitGump(this, false);
|
||||
}
|
||||
|
||||
FrameID entrynum_id(GameData::GUMPS, 36, index % 10);
|
||||
entrynum_id = _TL_SHP_(entrynum_id);
|
||||
|
||||
gump = new Gump(x, 3 + 40 * yi, 1, 1);
|
||||
gump->SetShape(entrynum_id, true);
|
||||
|
||||
if (index % 10 == 9) {
|
||||
// HACK: There is no frame for '0', so we re-use part of the
|
||||
// frame for '10', cutting off the first 6 pixels.
|
||||
Common::Rect32 rect = gump->getDims();
|
||||
rect.translate(6, 0);
|
||||
gump->setDims(rect);
|
||||
}
|
||||
gump->InitGump(this, false);
|
||||
|
||||
if (index == 0) {
|
||||
// special case for 'The Beginning...' _save
|
||||
Gump *widget = new TextWidget(xbase, entryheight + 4 + 40 * yi,
|
||||
_TL_("The Beginning..."),
|
||||
true, entryfont, 95);
|
||||
widget->InitGump(this, false);
|
||||
|
||||
} else {
|
||||
|
||||
if (_save) {
|
||||
EditWidget *ew = new EditWidget(xbase, entryheight + 4 + 40 * yi,
|
||||
_descriptions[i],
|
||||
true, entryfont,
|
||||
95, 38 - entryheight, 0, true);
|
||||
ew->SetIndex(i + 1);
|
||||
ew->InitGump(this, false);
|
||||
_editWidgets[i] = ew;
|
||||
} else {
|
||||
// load
|
||||
Gump *widget = new TextWidget(xbase, entryheight + 4 + 40 * yi,
|
||||
_descriptions[i], true, entryfont,
|
||||
95, 38 - entryheight);
|
||||
widget->InitGump(this, false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// remove focus from children (just in case)
|
||||
if (_focusChild) _focusChild->OnFocus(false);
|
||||
_focusChild = 0;
|
||||
}
|
||||
|
||||
void U8SaveGump::Close(bool no_del) {
|
||||
Gump::Close(no_del);
|
||||
}
|
||||
|
||||
void U8SaveGump::OnFocus(bool gain) {
|
||||
if (gain) {
|
||||
if (_save)
|
||||
Mouse::get_instance()->setMouseCursor(Mouse::MOUSE_QUILL);
|
||||
else
|
||||
Mouse::get_instance()->setMouseCursor(Mouse::MOUSE_MAGGLASS);
|
||||
}
|
||||
}
|
||||
|
||||
Gump *U8SaveGump::onMouseDown(int button, int32 mx, int32 my) {
|
||||
// take all clicks
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
void U8SaveGump::onMouseClick(int button, int32 mx, int32 my) {
|
||||
if (button != Mouse::BUTTON_LEFT) return;
|
||||
|
||||
ParentToGump(mx, my);
|
||||
|
||||
int x;
|
||||
if (mx >= 3 && mx <= 100)
|
||||
x = 0;
|
||||
else if (mx >= _dims.width() / 2 + 10)
|
||||
x = 1;
|
||||
else
|
||||
return;
|
||||
|
||||
int y;
|
||||
if (my >= 3 && my <= 40)
|
||||
y = 0;
|
||||
else if (my >= 43 && my <= 80)
|
||||
y = 1;
|
||||
else if (my >= 83 && my <= 120)
|
||||
y = 2;
|
||||
else
|
||||
return;
|
||||
|
||||
int i = 3 * x + y;
|
||||
int index = 6 * _page + i + 1;
|
||||
|
||||
if (_save && !_focusChild && _editWidgets[i]) {
|
||||
_editWidgets[i]->MakeFocus();
|
||||
PagedGump *p = dynamic_cast<PagedGump *>(_parent);
|
||||
if (p) p->enableButtons(false);
|
||||
}
|
||||
|
||||
if (!_save) {
|
||||
// If our parent has a notifiy process, we'll put our result in it and won't actually load the game
|
||||
GumpNotifyProcess *p = _parent ? _parent->GetNotifyProcess() : nullptr;
|
||||
if (p) {
|
||||
// Do nothing in this case
|
||||
if (index != 1 && _descriptions[i].empty()) return;
|
||||
|
||||
_parent->SetResult(index);
|
||||
_parent->Close(); // close PagedGump (and us)
|
||||
return;
|
||||
}
|
||||
|
||||
loadgame(index); // 'this' will be deleted here!
|
||||
}
|
||||
}
|
||||
|
||||
void U8SaveGump::onMouseDouble(int button, int32 mx, int32 my) {
|
||||
onMouseClick(button, mx, my);
|
||||
}
|
||||
|
||||
void U8SaveGump::ChildNotify(Gump *child, uint32 message) {
|
||||
EditWidget *widget = dynamic_cast<EditWidget *>(child);
|
||||
if (widget && message == EditWidget::EDIT_ENTER) {
|
||||
// save
|
||||
assert(_save);
|
||||
|
||||
Std::string name = widget->getText();
|
||||
if (name.empty()) return;
|
||||
|
||||
// Note: this might close us, so we should return right after.
|
||||
savegame(widget->GetIndex() + 6 * _page, name);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (widget && message == EditWidget::EDIT_ESCAPE) {
|
||||
// cancel edit
|
||||
assert(_save);
|
||||
|
||||
// remove focus
|
||||
if (_focusChild) _focusChild->OnFocus(false);
|
||||
_focusChild = 0;
|
||||
|
||||
PagedGump *p = dynamic_cast<PagedGump *>(_parent);
|
||||
if (p) p->enableButtons(true);
|
||||
|
||||
widget->setText(_descriptions[widget->GetIndex() - 1]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool U8SaveGump::OnKeyDown(int key, int mod) {
|
||||
if (Gump::OnKeyDown(key, mod)) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool U8SaveGump::loadgame(int saveIndex) {
|
||||
if (saveIndex == 1) {
|
||||
return Ultima8Engine::get_instance()->newGame();
|
||||
}
|
||||
|
||||
Common::Error loadError = Ultima8Engine::get_instance()->loadGameState(saveIndex);
|
||||
if (loadError.getCode() != Common::kNoError) {
|
||||
GUI::MessageDialog errorDialog(loadError.getDesc());
|
||||
errorDialog.runModal();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool U8SaveGump::savegame(int saveIndex, const Std::string &name) {
|
||||
if (name.empty())
|
||||
return false;
|
||||
|
||||
// We are saving, close parent (and ourselves) first so it doesn't
|
||||
// block the save or appear in the screenshot
|
||||
_parent->Close();
|
||||
|
||||
if (!Ultima8Engine::get_instance()->canSaveGameStateCurrently())
|
||||
return false;
|
||||
|
||||
return Ultima8Engine::get_instance()->saveGameState(saveIndex, name).getCode() == Common::kNoError;
|
||||
}
|
||||
|
||||
void U8SaveGump::loadDescriptions() {
|
||||
_descriptions.resize( 6);
|
||||
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
int saveIndex = 6 * _page + i + 1;
|
||||
|
||||
Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading(
|
||||
Ultima8Engine::get_instance()->getSaveStateName(saveIndex));
|
||||
if (!saveFile)
|
||||
continue;
|
||||
|
||||
const SavegameReader *sg = new SavegameReader(saveFile, true);
|
||||
_descriptions[i] = sg->getDescription();
|
||||
delete sg;
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
Gump *U8SaveGump::showLoadSaveGump(Gump *parent, bool save) {
|
||||
if (!ConfMan.getBool("originalsaveload")) {
|
||||
if (save)
|
||||
Ultima8Engine::get_instance()->saveGameDialog();
|
||||
else
|
||||
Ultima8Engine::get_instance()->loadGameDialog();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (save && !Ultima8Engine::get_instance()->canSaveGameStateCurrently()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PagedGump *gump = new PagedGump(34, -38, 3, 35);
|
||||
gump->InitGump(parent);
|
||||
|
||||
for (int page = 0; page < 16; ++page) {
|
||||
U8SaveGump *s = new U8SaveGump(save, page);
|
||||
s->InitGump(gump, false);
|
||||
gump->addPage(s);
|
||||
}
|
||||
|
||||
int lastSave = ConfMan.hasKey("lastSave") ? ConfMan.getInt("lastSave") : -1;
|
||||
if (lastSave > 0) {
|
||||
gump->showPage((lastSave - 1) / 6);
|
||||
}
|
||||
|
||||
gump->setRelativePosition(CENTER);
|
||||
|
||||
return gump;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
72
engines/ultima/ultima8/gumps/u8_save_gump.h
Normal file
72
engines/ultima/ultima8/gumps/u8_save_gump.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_U8SAVEGUMP_H
|
||||
#define ULTIMA8_GUMPS_U8SAVEGUMP_H
|
||||
|
||||
#include "ultima/shared/std/string.h"
|
||||
#include "ultima/ultima8/gumps/gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class EditWidget;
|
||||
|
||||
/**
|
||||
* U8-style load/save gump (a single number + editable widget entry in the paged save/load gump)
|
||||
*/
|
||||
class U8SaveGump : public Gump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
U8SaveGump(bool save, int page);
|
||||
~U8SaveGump() override;
|
||||
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
void Close(bool no_del = false) override;
|
||||
|
||||
Gump *onMouseDown(int button, int32 mx, int32 my) override;
|
||||
void onMouseClick(int button, int32 mx, int32 my) override;
|
||||
void onMouseDouble(int button, int32 mx, int32 my) override;
|
||||
bool OnKeyDown(int key, int mod) override;
|
||||
void ChildNotify(Gump *child, uint32 message) override;
|
||||
void OnFocus(bool gain) override;
|
||||
|
||||
static Gump *showLoadSaveGump(Gump *parent, bool save);
|
||||
|
||||
protected:
|
||||
bool _save;
|
||||
int _page;
|
||||
|
||||
Std::vector<EditWidget *> _editWidgets;
|
||||
Std::vector<Std::string> _descriptions;
|
||||
|
||||
void loadDescriptions();
|
||||
|
||||
bool loadgame(int saveIndex);
|
||||
bool savegame(int saveIndex, const Std::string &name);
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
78
engines/ultima/ultima8/gumps/weasel_dat.cpp
Normal file
78
engines/ultima/ultima8/gumps/weasel_dat.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/weasel_dat.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
static const int BLOCKS = 20;
|
||||
|
||||
WeaselDat::WeaselDat(Common::ReadStream *rs) {
|
||||
uint16 numentries = rs->readUint16LE();
|
||||
if (numentries > BLOCKS)
|
||||
numentries = BLOCKS;
|
||||
|
||||
// each block is 16 bytes
|
||||
for (uint i = 0; i < numentries; i++) {
|
||||
WeaselEntry entry;
|
||||
// 4 byte string ID
|
||||
for (int j = 0; j < 4; j++)
|
||||
entry._id[j] = rs->readByte();
|
||||
|
||||
// Unknown 4 bytes
|
||||
rs->readUint16LE();
|
||||
rs->readUint16LE();
|
||||
|
||||
// Shapeno (2 bytes)
|
||||
entry._shapeNo = rs->readUint16LE();
|
||||
// Cost (2 bytes)
|
||||
entry._cost = rs->readUint16LE();
|
||||
entry._entryNo = rs->readUint16LE();
|
||||
entry._unk = rs->readUint16LE();
|
||||
if (entry._id[0] == 'W')
|
||||
entry._type = kWeapon;
|
||||
else if (entry._id[0] == 'I')
|
||||
entry._type = kItem;
|
||||
else
|
||||
entry._type = kUnknown;
|
||||
|
||||
if (entry._shapeNo)
|
||||
_items.push_back(entry);
|
||||
}
|
||||
|
||||
const uint skip = (BLOCKS - numentries) * 16;
|
||||
for (uint i = 0; i < skip; i++)
|
||||
rs->readByte();
|
||||
}
|
||||
|
||||
uint16 WeaselDat::getNumOfType(WeaselType type) const {
|
||||
int count = 0;
|
||||
for (const auto &item : _items) {
|
||||
if (item._type == type)
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
72
engines/ultima/ultima8/gumps/weasel_dat.h
Normal file
72
engines/ultima/ultima8/gumps/weasel_dat.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_WEASELDAT_H
|
||||
#define ULTIMA8_GUMPS_WEASELDAT_H
|
||||
|
||||
#include "common/stream.h"
|
||||
#include "ultima/shared/std/containers.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/**
|
||||
* Data for the Weasel (shop) gump on a single level. Contains a list of things you can buy.
|
||||
*/
|
||||
class WeaselDat {
|
||||
public:
|
||||
|
||||
enum WeaselType {
|
||||
kUnknown,
|
||||
kWeapon,
|
||||
kItem
|
||||
};
|
||||
|
||||
/** A single item in the shop */
|
||||
struct WeaselEntry {
|
||||
char _id[4]; // eg, "W01", "I02", etc
|
||||
uint16 _shapeNo;
|
||||
uint32 _cost;
|
||||
uint16 _entryNo;
|
||||
uint16 _unk;
|
||||
enum WeaselType _type;
|
||||
};
|
||||
|
||||
WeaselDat(Common::ReadStream *rs);
|
||||
|
||||
uint16 getNumItems() const {
|
||||
return _items.size();
|
||||
}
|
||||
|
||||
uint16 getNumOfType(WeaselType type) const;
|
||||
|
||||
const Std::vector<WeaselEntry> &getItems() const {
|
||||
return _items;
|
||||
}
|
||||
|
||||
private:
|
||||
Std::vector<WeaselEntry> _items;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
565
engines/ultima/ultima8/gumps/weasel_gump.cpp
Normal file
565
engines/ultima/ultima8/gumps/weasel_gump.cpp
Normal file
@@ -0,0 +1,565 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/weasel_gump.h"
|
||||
#include "ultima/ultima8/gumps/weasel_dat.h"
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/gfx/gump_shape_archive.h"
|
||||
#include "ultima/ultima8/gfx/main_shape_archive.h"
|
||||
#include "ultima/ultima8/gfx/shape.h"
|
||||
#include "ultima/ultima8/gfx/shape_frame.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
#include "ultima/ultima8/kernel/mouse.h"
|
||||
#include "ultima/ultima8/gumps/widgets/button_widget.h"
|
||||
#include "ultima/ultima8/gumps/widgets/text_widget.h"
|
||||
#include "ultima/ultima8/gumps/movie_gump.h"
|
||||
#include "ultima/ultima8/world/actors/main_actor.h"
|
||||
#include "ultima/ultima8/audio/audio_process.h"
|
||||
#include "ultima/ultima8/world/get_object.h"
|
||||
#include "ultima/ultima8/world/item_factory.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(WeaselGump)
|
||||
|
||||
static const uint16 WEASEL_CANT_BUY_SFXNO = 0xb0;
|
||||
static const int WEASEL_FONT = 6;
|
||||
static const int WEASEL_SHAPE_TOP = 22;
|
||||
|
||||
enum WeaselUiElements {
|
||||
kBtnLeft = 0,
|
||||
kBtnBlank = 1,
|
||||
kBtnRight = 2,
|
||||
kBtnYes = 3,
|
||||
kBtnNo = 4,
|
||||
kBtnBuy = 5,
|
||||
kBtnAmmo = 6,
|
||||
kBtnWeapons = 7,
|
||||
kBtnExit = 8,
|
||||
kTxtCredits = 9,
|
||||
kIconItem = 10,
|
||||
kTxtItemName = 11,
|
||||
kTxtItemCost = 12,
|
||||
kTxtItemPurch = 13,
|
||||
kTxtItemOwned = 14,
|
||||
kTxtQuestion = 15
|
||||
};
|
||||
// Coords and shapes for above list of buttons
|
||||
static const int WEASEL_BTN_X[] = { 14, 76, 138, 18, 113, 20, 19, 19, 44};
|
||||
static const int WEASEL_BTN_Y[] = {213, 213, 213, 237, 237, 280, 319, 319, 368};
|
||||
static const int WEASEL_BTN_SHAPES[] = {13, 26, 14, 16, 15, 28, 27, 83, 29};
|
||||
|
||||
static const char *const FIRST_INTRO_MOVIE = "17A";
|
||||
static const char *const INTRO_MOVIES[] = {"18A", "18B", "18C"};
|
||||
static const char *const BUYMORE_MOVIES[] = {"21A", "21B"};
|
||||
static const char *const CONFIRM_BUY_MOVIES[] = {"21A", "21B"};
|
||||
static const char *const CANCELLED_PURCHASE_MOVIES[] = {"19C", "19D"};
|
||||
static const char *const COMPLETED_PURCHASE_MOVIES[] = {"21C", "21D"};
|
||||
static const char *const INSUFFICIENT_FUND_MOVIES[] = {"20C", "20D"};
|
||||
|
||||
|
||||
namespace {
|
||||
// A small container gump that doesn't do anything except pass notifications to the parent
|
||||
class WeaselUIContainerGump : public Gump {
|
||||
void ChildNotify(Gump *child, uint32 message) override {
|
||||
_parent->ChildNotify(child, message);
|
||||
}
|
||||
};
|
||||
|
||||
static void _closeIfExists(Gump *gump) {
|
||||
if (gump)
|
||||
gump->Close();
|
||||
}
|
||||
|
||||
static const char *_getRandomMovie(const char *const *movies, int nmovies) {
|
||||
Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
|
||||
int offset = rs.getRandomNumber(nmovies - 1);
|
||||
return movies[offset];
|
||||
}
|
||||
}
|
||||
|
||||
bool WeaselGump::_playedIntroMovie = false;
|
||||
|
||||
WeaselGump::WeaselGump(uint16 level)
|
||||
: ModalGump(0, 0, 640, 480), _credits(0), _level(level),
|
||||
_state(kWeaselStart), _curItem(0), _ammoMode(false), _curItemCost(1),
|
||||
_curItemShape(0), _ui(nullptr), _movie(nullptr), _weaselDat(nullptr) {
|
||||
Mouse *mouse = Mouse::get_instance();
|
||||
mouse->pushMouseCursor(Mouse::MOUSE_HAND);
|
||||
}
|
||||
|
||||
WeaselGump::~WeaselGump() {
|
||||
}
|
||||
|
||||
|
||||
void WeaselGump::Close(bool no_del) {
|
||||
Mouse *mouse = Mouse::get_instance();
|
||||
mouse->popMouseCursor();
|
||||
ModalGump::Close(no_del);
|
||||
}
|
||||
|
||||
void WeaselGump::InitGump(Gump *newparent, bool take_focus) {
|
||||
ModalGump::InitGump(newparent, take_focus);
|
||||
|
||||
GumpShapeArchive *shapeArchive = GameData::get_instance()->getGumps();
|
||||
|
||||
const Shape *top = shapeArchive->getShape(WEASEL_SHAPE_TOP);
|
||||
const Shape *midhi = shapeArchive->getShape(WEASEL_SHAPE_TOP + 1);
|
||||
const Shape *midlo = shapeArchive->getShape(WEASEL_SHAPE_TOP + 2);
|
||||
const Shape *bot = shapeArchive->getShape(WEASEL_SHAPE_TOP + 3);
|
||||
|
||||
if (!top || !midhi || !midlo || !bot) {
|
||||
error("Couldn't load shapes for weasel");
|
||||
return;
|
||||
}
|
||||
|
||||
const ShapeFrame *tFrame = top->getFrame(0);
|
||||
const ShapeFrame *mhFrame = midhi->getFrame(0);
|
||||
const ShapeFrame *mlFrame = midlo->getFrame(0);
|
||||
const ShapeFrame *bFrame = bot->getFrame(0);
|
||||
if (!tFrame || !mhFrame || !mlFrame || !bFrame) {
|
||||
error("Couldn't load shape frames for weasel");
|
||||
return;
|
||||
}
|
||||
|
||||
_ui = new WeaselUIContainerGump();
|
||||
_ui->setDims(Common::Rect32(0, 0, mhFrame->_width,
|
||||
tFrame->_height + mhFrame->_height + mlFrame->_height + bFrame->_height));
|
||||
_ui->InitGump(this, false);
|
||||
_ui->setRelativePosition(CENTER);
|
||||
|
||||
Gump *tGump = new Gump(3, 0, tFrame->_width, tFrame->_height);
|
||||
tGump->SetShape(top, 0);
|
||||
tGump->InitGump(_ui, false);
|
||||
Gump *mhGump = new Gump(0, tFrame->_height, mhFrame->_width, mhFrame->_height);
|
||||
mhGump->SetShape(midhi, 0);
|
||||
mhGump->InitGump(_ui, false);
|
||||
Gump *mlGump = new Gump(5, tFrame->_height + mhFrame->_height, mlFrame->_width, mlFrame->_height);
|
||||
mlGump->SetShape(midlo, 0);
|
||||
mlGump->InitGump(_ui, false);
|
||||
Gump *bGump = new Gump(9, tFrame->_height + mhFrame->_height + mlFrame->_height, bFrame->_width, bFrame->_height);
|
||||
bGump->SetShape(bot, 0);
|
||||
bGump->InitGump(_ui, false);
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(WEASEL_BTN_X); i++) {
|
||||
uint32 buttonShapeNum = WEASEL_BTN_SHAPES[i];
|
||||
const Shape *buttonShape = shapeArchive->getShape(buttonShapeNum);
|
||||
if (!buttonShape) {
|
||||
error("Couldn't load shape for weasel button %d", i);
|
||||
return;
|
||||
}
|
||||
|
||||
const ShapeFrame *buttonFrame = buttonShape->getFrame(0);
|
||||
if (!buttonFrame || buttonShape->frameCount() != 2) {
|
||||
error("Couldn't load shape frame for weasel button %d", i);
|
||||
return;
|
||||
}
|
||||
|
||||
FrameID frame_up(GameData::GUMPS, buttonShapeNum, 0);
|
||||
FrameID frame_down(GameData::GUMPS, buttonShapeNum, 1);
|
||||
Gump *widget = new ButtonWidget(WEASEL_BTN_X[i], WEASEL_BTN_Y[i], frame_up, frame_down, false);
|
||||
widget->InitGump(_ui, false);
|
||||
widget->SetIndex(i);
|
||||
// some buttons start hidden, the browsingMode() call below does that.
|
||||
}
|
||||
|
||||
MainActor *av = getMainActor();
|
||||
assert(av);
|
||||
Item *item = av->getFirstItemWithShape(0x4ed, true);
|
||||
if (item)
|
||||
_credits = item->getQuality();
|
||||
|
||||
_weaselDat = GameData::get_instance()->getWeaselDat(_level);
|
||||
if (!_weaselDat || _weaselDat->getNumItems() == 0)
|
||||
Close();
|
||||
}
|
||||
|
||||
Gump *WeaselGump::playMovie(const Std::string &filename) {
|
||||
MovieGump *gump = MovieGump::CruMovieViewer(filename, 600, 450, nullptr, this, 0);
|
||||
if (!gump) {
|
||||
warning("Couldn't load flic %s", filename.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
gump->CreateNotifier();
|
||||
return gump;
|
||||
}
|
||||
|
||||
void WeaselGump::run() {
|
||||
ModalGump::run();
|
||||
// Don't do much while a movie is playing.
|
||||
if (_movie)
|
||||
return;
|
||||
_ui->UnhideGump();
|
||||
switch (_state) {
|
||||
case kWeaselStart:
|
||||
_state = kWeaselShowIntro;
|
||||
break;
|
||||
case kWeaselShowIntro: {
|
||||
if (_level == 2 && !_playedIntroMovie) {
|
||||
_movie = playMovie(FIRST_INTRO_MOVIE);
|
||||
_playedIntroMovie = true;
|
||||
} else {
|
||||
_movie = playMovie(_getRandomMovie(INTRO_MOVIES, ARRAYSIZE(INTRO_MOVIES)));
|
||||
}
|
||||
_state = kWeaselBrowsing;
|
||||
browsingMode(true);
|
||||
break;
|
||||
}
|
||||
case kWeaselCheckBuyMoreMovie:
|
||||
_movie = playMovie(_getRandomMovie(BUYMORE_MOVIES, ARRAYSIZE(BUYMORE_MOVIES)));
|
||||
_state = kWeaselCheckBuyMoreText;
|
||||
break;
|
||||
case kWeaselCheckBuyMoreText:
|
||||
checkBuyMore();
|
||||
break;
|
||||
case kWeaselClosing:
|
||||
Close();
|
||||
break;
|
||||
case kWeaselConfirmPurchaseMovie:
|
||||
_movie = playMovie(_getRandomMovie(CONFIRM_BUY_MOVIES, ARRAYSIZE(CONFIRM_BUY_MOVIES)));
|
||||
_state = kWeaselConfirmPurchaseText;
|
||||
break;
|
||||
case kWeaselConfirmPurchaseText:
|
||||
confirmPurchase();
|
||||
break;
|
||||
case kWeaselCancelledPurchaseMovie:
|
||||
browsingMode(true);
|
||||
_movie = playMovie(_getRandomMovie(CANCELLED_PURCHASE_MOVIES, ARRAYSIZE(CANCELLED_PURCHASE_MOVIES)));
|
||||
_state = kWeaselBrowsing;
|
||||
break;
|
||||
case kWeaselCompletedPurchase:
|
||||
_movie = playMovie(_getRandomMovie(COMPLETED_PURCHASE_MOVIES, ARRAYSIZE(COMPLETED_PURCHASE_MOVIES)));
|
||||
_state = kWeaselCheckBuyMoreText;
|
||||
break;
|
||||
case kWeaselInsufficientFunds:
|
||||
// TODO: how does it get to this situation?
|
||||
_movie = playMovie(_getRandomMovie(INSUFFICIENT_FUND_MOVIES, ARRAYSIZE(INSUFFICIENT_FUND_MOVIES)));
|
||||
break;
|
||||
case kWeaselBrowsing:
|
||||
_ui->UnhideGump();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (_movie) {
|
||||
_ui->HideGump();
|
||||
}
|
||||
}
|
||||
|
||||
void WeaselGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
Gump::PaintThis(surf, lerp_factor, scaled);
|
||||
}
|
||||
|
||||
bool WeaselGump::OnKeyDown(int key, int mod) {
|
||||
if (Gump::OnKeyDown(key, mod)) return true;
|
||||
|
||||
// TODO: support more keyboard input
|
||||
switch (key) {
|
||||
case Common::KEYCODE_LEFT:
|
||||
if (_state == kWeaselBrowsing)
|
||||
prevItem();
|
||||
break;
|
||||
case Common::KEYCODE_RIGHT:
|
||||
if (_state == kWeaselBrowsing)
|
||||
nextItem();
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WeaselGump::ChildNotify(Gump *child, uint32 message) {
|
||||
ButtonWidget *buttonWidget = dynamic_cast<ButtonWidget *>(child);
|
||||
MovieGump *movieGump = dynamic_cast<MovieGump *>(child);
|
||||
if (buttonWidget && message == ButtonWidget::BUTTON_CLICK) {
|
||||
onButtonClick(child->GetIndex());
|
||||
} else if (movieGump && message == Gump::GUMP_CLOSING) {
|
||||
// Movie has finished.
|
||||
_movie = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void WeaselGump::onButtonClick(int entry) {
|
||||
switch (entry) {
|
||||
case kBtnWeapons:
|
||||
_ammoMode = false;
|
||||
updateForAmmoMode();
|
||||
break;
|
||||
case kBtnAmmo:
|
||||
_ammoMode = true;
|
||||
updateForAmmoMode();
|
||||
break;
|
||||
case kBtnLeft:
|
||||
prevItem();
|
||||
break;
|
||||
case kBtnRight:
|
||||
nextItem();
|
||||
break;
|
||||
case kBtnBuy:
|
||||
buyItem();
|
||||
break;
|
||||
case kBtnExit:
|
||||
checkClose();
|
||||
break;
|
||||
case kBtnYes:
|
||||
if (_state == kWeaselConfirmPurchaseText)
|
||||
completePurchase();
|
||||
else if (_state == kWeaselCheckBuyMoreText)
|
||||
browsingMode(true);
|
||||
break;
|
||||
case kBtnNo:
|
||||
if (_state == kWeaselConfirmPurchaseText)
|
||||
abortPurchase();
|
||||
else if (_state == kWeaselCheckBuyMoreText)
|
||||
Close();
|
||||
break;
|
||||
case kBtnBlank:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void WeaselGump::updateForAmmoMode() {
|
||||
Gump *ammobtn = _ui->FindGump(&FindByIndex<kBtnAmmo>);
|
||||
Gump *wpnbtn = _ui->FindGump(&FindByIndex<kBtnWeapons>);
|
||||
assert(ammobtn && wpnbtn);
|
||||
ammobtn->SetVisibility(!_ammoMode);
|
||||
wpnbtn->SetVisibility(_ammoMode);
|
||||
_curItem = 0;
|
||||
|
||||
_weaselDat = GameData::get_instance()->getWeaselDat(_ammoMode ? 1 : _level);
|
||||
if (!_weaselDat || _weaselDat->getNumItems() == 0)
|
||||
Close();
|
||||
|
||||
updateItemDisplay();
|
||||
}
|
||||
|
||||
|
||||
void WeaselGump::prevItem() {
|
||||
_curItem--;
|
||||
if (_curItem < 0)
|
||||
_curItem = _weaselDat->getNumItems() - 1;
|
||||
updateItemDisplay();
|
||||
}
|
||||
|
||||
void WeaselGump::nextItem() {
|
||||
_curItem++;
|
||||
if (_curItem >= _weaselDat->getNumItems())
|
||||
_curItem = 0;
|
||||
updateItemDisplay();
|
||||
}
|
||||
|
||||
void WeaselGump::buyItem() {
|
||||
if (_curItemCost < _credits) {
|
||||
_purchases.push_back(_curItemShape);
|
||||
_credits -= _curItemCost;
|
||||
} else {
|
||||
AudioProcess::get_instance()->playSFX(WEASEL_CANT_BUY_SFXNO, 0x80, 0, 0);
|
||||
}
|
||||
updateItemDisplay();
|
||||
}
|
||||
|
||||
void WeaselGump::confirmPurchase() {
|
||||
static const char *confirm = "Are you sure you want to buy this?";
|
||||
setYesNoQuestion(confirm);
|
||||
}
|
||||
|
||||
void WeaselGump::checkClose() {
|
||||
if (_purchases.size()) {
|
||||
_state = kWeaselConfirmPurchaseMovie;
|
||||
} else {
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
void WeaselGump::completePurchase() {
|
||||
assert(_state == kWeaselConfirmPurchaseText);
|
||||
MainActor *av = getMainActor();
|
||||
uint16 mapno = av->getMapNum();
|
||||
assert(av);
|
||||
Item *item = av->getFirstItemWithShape(0x4ed, true);
|
||||
if (item)
|
||||
item->setQuality(_credits);
|
||||
for (const auto &purchase : _purchases) {
|
||||
Item *newitem = ItemFactory::createItem(purchase, 0, 0, 0, 0, mapno, 0, true);
|
||||
av->addItemCru(newitem, false);
|
||||
}
|
||||
_state = kWeaselCompletedPurchase;
|
||||
}
|
||||
|
||||
void WeaselGump::checkBuyMore() {
|
||||
static const char *buymore = "Do you want anything else?";
|
||||
setYesNoQuestion(buymore);
|
||||
}
|
||||
|
||||
void WeaselGump::setYesNoQuestion(const Std::string &msg) {
|
||||
browsingMode(false);
|
||||
_closeIfExists(_ui->FindGump(&FindByIndex<kTxtQuestion>));
|
||||
TextWidget *textWidget = new TextWidget(30, 100, msg, true, WEASEL_FONT, 150);
|
||||
textWidget->InitGump(_ui);
|
||||
textWidget->SetIndex(kTxtQuestion);
|
||||
}
|
||||
|
||||
void WeaselGump::browsingMode(bool browsing) {
|
||||
_ui->UnhideGump();
|
||||
|
||||
updateForAmmoMode();
|
||||
updateItemDisplay();
|
||||
|
||||
// Note: all these searches are not super effieient but it's
|
||||
// not a time-sensitive function and the search is relatively short
|
||||
Gump *yesbtn = _ui->FindGump(&FindByIndex<kBtnYes>);
|
||||
Gump *nobtn = _ui->FindGump(&FindByIndex<kBtnNo>);
|
||||
Gump *qtxt = _ui->FindGump(&FindByIndex<kTxtQuestion>);
|
||||
|
||||
Gump *buybtn = _ui->FindGump(&FindByIndex<kBtnBuy>);
|
||||
Gump *wpnbtn = _ui->FindGump(&FindByIndex<kBtnWeapons>);
|
||||
Gump *ammobtn = _ui->FindGump(&FindByIndex<kBtnAmmo>);
|
||||
Gump *exitbtn = _ui->FindGump(&FindByIndex<kBtnExit>);
|
||||
Gump *blankbtn = _ui->FindGump(&FindByIndex<kBtnBlank>);
|
||||
Gump *leftbtn = _ui->FindGump(&FindByIndex<kBtnLeft>);
|
||||
Gump *rightbtn = _ui->FindGump(&FindByIndex<kBtnRight>);
|
||||
Gump *credtxt = _ui->FindGump(&FindByIndex<kTxtCredits>);
|
||||
Gump *nametxt = _ui->FindGump(&FindByIndex<kTxtItemName>);
|
||||
Gump *costtxt = _ui->FindGump(&FindByIndex<kTxtItemCost>);
|
||||
Gump *purchtxt = _ui->FindGump(&FindByIndex<kTxtItemPurch>);
|
||||
Gump *ownedtxt = _ui->FindGump(&FindByIndex<kTxtItemOwned>);
|
||||
Gump *icon = _ui->FindGump(&FindByIndex<kIconItem>);
|
||||
|
||||
yesbtn->SetVisibility(!browsing);
|
||||
nobtn->SetVisibility(!browsing);
|
||||
if (qtxt)
|
||||
qtxt->SetVisibility(!browsing);
|
||||
|
||||
buybtn->SetVisibility(browsing);
|
||||
wpnbtn->SetVisibility(browsing && _ammoMode);
|
||||
ammobtn->SetVisibility(browsing && !_ammoMode);
|
||||
exitbtn->SetVisibility(browsing);
|
||||
blankbtn->SetVisibility(browsing);
|
||||
leftbtn->SetVisibility(browsing);
|
||||
rightbtn->SetVisibility(browsing);
|
||||
credtxt->SetVisibility(browsing);
|
||||
nametxt->SetVisibility(browsing);
|
||||
costtxt->SetVisibility(browsing);
|
||||
purchtxt->SetVisibility(browsing);
|
||||
ownedtxt->SetVisibility(browsing);
|
||||
icon->SetVisibility(browsing);
|
||||
}
|
||||
|
||||
void WeaselGump::abortPurchase() {
|
||||
assert(_state == kWeaselConfirmPurchaseText);
|
||||
_state = kWeaselCancelledPurchaseMovie;
|
||||
_purchases.clear();
|
||||
}
|
||||
|
||||
int WeaselGump::purchasedCount(uint16 shape) const {
|
||||
int count = 0;
|
||||
for (const auto &purchase : _purchases) {
|
||||
if (purchase == shape)
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void WeaselGump::updateItemDisplay() {
|
||||
const Std::vector<WeaselDat::WeaselEntry> &items = _weaselDat->getItems();
|
||||
|
||||
// should always have the item..
|
||||
assert(_curItem < (int)items.size());
|
||||
|
||||
_curItemCost = items[_curItem]._cost;
|
||||
_curItemShape = items[_curItem]._shapeNo;
|
||||
|
||||
const ShapeInfo *shapeinfo = GameData::get_instance()->getMainShapes()->getShapeInfo(_curItemShape);
|
||||
if (!shapeinfo || !shapeinfo->_weaponInfo) {
|
||||
warning("Weasel: no info for shape %d", _curItemShape);
|
||||
return;
|
||||
}
|
||||
const Shape *shape = GameData::get_instance()->getGumps()->getShape(shapeinfo->_weaponInfo->_displayGumpShape);
|
||||
|
||||
_closeIfExists(_ui->FindGump(&FindByIndex<kTxtCredits>));
|
||||
_closeIfExists(_ui->FindGump(&FindByIndex<kTxtItemName>));
|
||||
_closeIfExists(_ui->FindGump(&FindByIndex<kTxtItemCost>));
|
||||
_closeIfExists(_ui->FindGump(&FindByIndex<kTxtItemPurch>));
|
||||
_closeIfExists(_ui->FindGump(&FindByIndex<kTxtItemOwned>));
|
||||
_closeIfExists(_ui->FindGump(&FindByIndex<kIconItem>));
|
||||
|
||||
Std::string credstr = Std::string::format("Credits:%d", _credits);
|
||||
TextWidget *textWidget = new TextWidget(30, 57, credstr, true, WEASEL_FONT);
|
||||
textWidget->InitGump(_ui);
|
||||
textWidget->SetIndex(kTxtCredits);
|
||||
|
||||
const ShapeFrame *frame = shape->getFrame(shapeinfo->_weaponInfo->_displayGumpFrame);
|
||||
Gump *icon = new Gump(105 - frame->_xoff, 120 - frame->_yoff, 200, 200);
|
||||
icon->SetShape(shape, shapeinfo->_weaponInfo->_displayGumpFrame);
|
||||
icon->UpdateDimsFromShape();
|
||||
icon->setRelativePosition(CENTER);
|
||||
icon->InitGump(_ui, false);
|
||||
icon->SetIndex(kIconItem);
|
||||
|
||||
Std::string coststr = Std::string::format("Cost:%d", _curItemCost);
|
||||
Std::string purchstr = Std::string::format("Purchased:%02d", purchasedCount(_curItemShape));
|
||||
|
||||
MainActor *av = getMainActor();
|
||||
const Item *item = av->getFirstItemWithShape(_curItemShape, true);
|
||||
int count = 0;
|
||||
if (item) {
|
||||
if (shapeinfo->_family == ShapeInfo::SF_CRUWEAPON) {
|
||||
count = 1;
|
||||
} else {
|
||||
count = item->getQuality();
|
||||
}
|
||||
}
|
||||
Std::string ownedstr = Std::string::format("Owned:%02d", count);
|
||||
|
||||
TextWidget *nametxt = new TextWidget(27, 161, shapeinfo->_weaponInfo->_name, true, WEASEL_FONT);
|
||||
nametxt->InitGump(_ui, false);
|
||||
nametxt->SetIndex(kTxtItemName);
|
||||
TextWidget *costtxt = new TextWidget(27, 171, coststr, true, WEASEL_FONT);
|
||||
costtxt->InitGump(_ui, false);
|
||||
costtxt->SetIndex(kTxtItemCost);
|
||||
TextWidget *purchtxt = new TextWidget(27, 181, purchstr, true, WEASEL_FONT);
|
||||
purchtxt->InitGump(_ui, false);
|
||||
purchtxt->SetIndex(kTxtItemPurch);
|
||||
TextWidget *ownedtxt = new TextWidget(27, 191, ownedstr, true, WEASEL_FONT);
|
||||
ownedtxt->InitGump(_ui, false);
|
||||
ownedtxt->SetIndex(kTxtItemOwned);
|
||||
}
|
||||
|
||||
bool WeaselGump::OnTextInput(int unicode) {
|
||||
if (Gump::OnTextInput(unicode)) return true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//static
|
||||
uint32 WeaselGump::I_showWeaselGump(const uint8 *args, unsigned int /*argsize*/) {
|
||||
ARG_UINT16(level);
|
||||
|
||||
WeaselGump *gump = new WeaselGump(level);
|
||||
gump->InitGump(0);
|
||||
gump->setRelativePosition(CENTER);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
141
engines/ultima/ultima8/gumps/weasel_gump.h
Normal file
141
engines/ultima/ultima8/gumps/weasel_gump.h
Normal file
@@ -0,0 +1,141 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_REMORSEMENUGUMP_H
|
||||
#define ULTIMA8_GUMPS_REMORSEMENUGUMP_H
|
||||
|
||||
#include "ultima/shared/std/string.h"
|
||||
#include "ultima/ultima8/gumps/modal_gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class WeaselDat;
|
||||
|
||||
/**
|
||||
* Weasel weapon seller Crusader.
|
||||
*/
|
||||
class WeaselGump : public ModalGump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
enum WeaselGumpState {
|
||||
kWeaselStart,
|
||||
kWeaselConfirmPurchaseMovie,
|
||||
kWeaselConfirmPurchaseText,
|
||||
kWeaselCancelledPurchaseMovie,
|
||||
kWeaselCancelledPurchaseText,
|
||||
kWeaselCompletedPurchase,
|
||||
kWeaselInsufficientFunds,
|
||||
kWeaselBrowsing,
|
||||
kWeaselClosing,
|
||||
kWeaselCheckBuyMoreMovie,
|
||||
kWeaselCheckBuyMoreText,
|
||||
kWeaselShowIntro
|
||||
};
|
||||
|
||||
WeaselGump(uint16 level);
|
||||
~WeaselGump() override;
|
||||
|
||||
// Init the gump, call after construction
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
void Close(bool no_del = false) override;
|
||||
|
||||
void run() override;
|
||||
|
||||
// Paint the Gump
|
||||
void PaintThis(RenderSurface *, int32 lerp_factor, bool scaled) override;
|
||||
|
||||
bool OnKeyDown(int key, int mod) override;
|
||||
bool OnTextInput(int unicode) override;
|
||||
void ChildNotify(Gump *child, uint32 message) override;
|
||||
|
||||
static uint32 I_showWeaselGump(const uint8 *args, unsigned int /*argsize*/);
|
||||
|
||||
private:
|
||||
|
||||
void onButtonClick(int entry);
|
||||
|
||||
void prevItem();
|
||||
void nextItem();
|
||||
void buyItem();
|
||||
void updateForAmmoMode();
|
||||
void checkClose();
|
||||
void completePurchase();
|
||||
void abortPurchase();
|
||||
void checkBuyMore();
|
||||
void confirmPurchase();
|
||||
void setYesNoQuestion(const Std::string &msg);
|
||||
void browsingMode(bool browsing);
|
||||
int purchasedCount(uint16 shape) const;
|
||||
|
||||
void updateItemDisplay();
|
||||
Gump *playMovie(const Std::string &filename);
|
||||
|
||||
/// Gump to hold all the UI items (not the movies)
|
||||
Gump *_ui;
|
||||
|
||||
/// Gump for playing movies
|
||||
Gump *_movie;
|
||||
|
||||
/// The menu of items on offer
|
||||
uint16 _level;
|
||||
|
||||
/// Current gump state
|
||||
WeaselGumpState _state;
|
||||
|
||||
const WeaselDat *_weaselDat;
|
||||
|
||||
/// Remaining balance including pending purchases
|
||||
int32 _credits;
|
||||
|
||||
/// The list of pending purchases (shape nums)
|
||||
Std::vector<uint16> _purchases;
|
||||
|
||||
/// The current item num being browsed
|
||||
int _curItem;
|
||||
|
||||
/// Whether we're browsing ammo or weapons
|
||||
bool _ammoMode;
|
||||
|
||||
/// Cost of current item
|
||||
int32 _curItemCost;
|
||||
|
||||
/// Shape of current item
|
||||
uint16 _curItemShape;
|
||||
|
||||
/**
|
||||
* Whether the first intro movie has been played. Remember this between
|
||||
* displays of the gump, but don't save.
|
||||
*
|
||||
* It only ever shows on level 1 so there is only a single way it can be re-shown
|
||||
* (save during the first time at the base and reload after restarting the game).
|
||||
*
|
||||
* TODO: test if original does this to be perfectly faithful
|
||||
*/
|
||||
static bool _playedIntroMovie;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
256
engines/ultima/ultima8/gumps/widgets/button_widget.cpp
Normal file
256
engines/ultima/ultima8/gumps/widgets/button_widget.cpp
Normal file
@@ -0,0 +1,256 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/widgets/button_widget.h"
|
||||
#include "ultima/ultima8/gumps/widgets/text_widget.h"
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/gfx/shape_archive.h"
|
||||
#include "ultima/ultima8/gfx/shape.h"
|
||||
#include "ultima/ultima8/kernel/mouse.h"
|
||||
#include "ultima/ultima8/world/get_object.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
// p_dynamic_class stuff
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(ButtonWidget)
|
||||
|
||||
ButtonWidget::ButtonWidget() : Gump(), _shapeUp(nullptr), _shapeDown(nullptr),
|
||||
_mouseOver(false), _origW(0), _origH(0), _frameNumUp(0),
|
||||
_frameNumDown(0), _mouseOverBlendCol(0), _textWidget(0) {
|
||||
}
|
||||
|
||||
ButtonWidget::ButtonWidget(int x, int y, Std::string txt, bool gamefont,
|
||||
int font, uint32 mouseOverBlendCol,
|
||||
int w, int h, int32 layer) :
|
||||
Gump(x, y, w, h, 0, 0, layer), _shapeUp(nullptr), _shapeDown(nullptr),
|
||||
_mouseOver(false), _origW(w), _origH(h), _frameNumUp(0), _frameNumDown(0) {
|
||||
TextWidget *widget = new TextWidget(0, 0, txt, gamefont, font, w, h);
|
||||
// FIXME: Do we ever free this widget?
|
||||
_textWidget = widget->getObjId();
|
||||
_mouseOverBlendCol = mouseOverBlendCol;
|
||||
_mouseOver = (_mouseOverBlendCol != 0);
|
||||
}
|
||||
|
||||
ButtonWidget::ButtonWidget(int x, int y, FrameID frame_up, FrameID frame_down,
|
||||
bool mouseOver, int32 layer)
|
||||
: Gump(x, y, 5, 5, 0, 0, layer), _textWidget(0), _mouseOver(mouseOver),
|
||||
_origW(0), _origH(0), _mouseOverBlendCol(0) {
|
||||
_shapeUp = GameData::get_instance()->getShape(frame_up);
|
||||
_shapeDown = GameData::get_instance()->getShape(frame_down);
|
||||
_frameNumUp = frame_up._frameNum;
|
||||
_frameNumDown = frame_down._frameNum;
|
||||
}
|
||||
|
||||
|
||||
ButtonWidget::~ButtonWidget(void) {
|
||||
}
|
||||
|
||||
void ButtonWidget::InitGump(Gump *newparent, bool take_focus) {
|
||||
Gump::InitGump(newparent, take_focus);
|
||||
|
||||
if (_textWidget != 0) {
|
||||
Gump *widget = getGump(_textWidget);
|
||||
assert(widget);
|
||||
widget->InitGump(this);
|
||||
_dims = widget->getDims(); // transfer child dimension to self
|
||||
widget->Move(0, _dims.top); // move it to the correct height
|
||||
} else {
|
||||
assert(_shapeUp != nullptr);
|
||||
assert(_shapeDown != nullptr);
|
||||
|
||||
SetShape(_shapeUp, _frameNumUp);
|
||||
UpdateDimsFromShape();
|
||||
}
|
||||
}
|
||||
|
||||
int ButtonWidget::getVlead() {
|
||||
if (_textWidget != 0) {
|
||||
Gump *widget = getGump(_textWidget);
|
||||
TextWidget *txtWidget = dynamic_cast<TextWidget *>(widget);
|
||||
assert(txtWidget);
|
||||
return txtWidget->getVlead();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool ButtonWidget::PointOnGump(int mx, int my) {
|
||||
// CHECKME: this makes the ButtonWidget accept any point in its rectangle,
|
||||
// effectively ignoring shape transparency. For some buttons (like those
|
||||
// in U8's diary), this is desirable. For others it may not be, so this
|
||||
// behaviour may need to be changed. (bool ignoreShapeTransparency or
|
||||
// something)
|
||||
|
||||
int32 gx = mx, gy = my;
|
||||
ParentToGump(gx, gy);
|
||||
|
||||
return _dims.contains(gx, gy);
|
||||
}
|
||||
|
||||
Gump *ButtonWidget::onMouseDown(int button, int32 mx, int32 my) {
|
||||
Gump *ret = Gump::onMouseDown(button, mx, my);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (button == Mouse::BUTTON_LEFT) {
|
||||
// CHECKME: change dimensions or not?
|
||||
if (!_mouseOver) {
|
||||
_shape = _shapeDown;
|
||||
_frameNum = _frameNumDown;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint16 ButtonWidget::TraceObjId(int32 mx, int32 my) {
|
||||
if (PointOnGump(mx, my))
|
||||
return getObjId();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void ButtonWidget::onMouseUp(int button, int32 mx, int32 my) {
|
||||
if (button == Mouse::BUTTON_LEFT) {
|
||||
if (!_mouseOver) {
|
||||
_shape = _shapeUp;
|
||||
_frameNum = _frameNumUp;
|
||||
}
|
||||
if (PointOnGump(mx, my))
|
||||
_parent->ChildNotify(this, BUTTON_UP);
|
||||
}
|
||||
}
|
||||
|
||||
void ButtonWidget::onMouseClick(int button, int32 mx, int32 my) {
|
||||
if (PointOnGump(mx, my))
|
||||
_parent->ChildNotify(this, BUTTON_CLICK);
|
||||
}
|
||||
|
||||
void ButtonWidget::onMouseDouble(int button, int32 mx, int32 my) {
|
||||
if (PointOnGump(mx, my))
|
||||
_parent->ChildNotify(this, BUTTON_DOUBLE);
|
||||
}
|
||||
|
||||
void ButtonWidget::onMouseOver() {
|
||||
if (_mouseOver) {
|
||||
if (_textWidget) {
|
||||
Gump *widget = getGump(_textWidget);
|
||||
TextWidget *txtWidget = dynamic_cast<TextWidget *>(widget);
|
||||
assert(txtWidget);
|
||||
txtWidget->setBlendColour(_mouseOverBlendCol);
|
||||
} else {
|
||||
_shape = _shapeDown;
|
||||
_frameNum = _frameNumDown;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ButtonWidget::onMouseLeft() {
|
||||
if (_mouseOver) {
|
||||
if (_textWidget) {
|
||||
Gump *widget = getGump(_textWidget);
|
||||
TextWidget *txtWidget = dynamic_cast<TextWidget *>(widget);
|
||||
assert(txtWidget);
|
||||
txtWidget->setBlendColour(0);
|
||||
} else {
|
||||
_shape = _shapeUp;
|
||||
_frameNum = _frameNumUp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ButtonWidget::saveData(Common::WriteStream *ws) {
|
||||
// HACK ALERT
|
||||
int w = 0, h = 0;
|
||||
if (_textWidget != 0) {
|
||||
w = _dims.width();
|
||||
h = _dims.height();
|
||||
_dims.setWidth(_origW);
|
||||
_dims.setHeight(_origH);
|
||||
}
|
||||
|
||||
Gump::saveData(ws);
|
||||
|
||||
// HACK ALERT
|
||||
if (_textWidget != 0) {
|
||||
_dims.setWidth(w);
|
||||
_dims.setHeight(h);
|
||||
}
|
||||
|
||||
uint16 flex = 0;
|
||||
uint32 shapenum = 0;
|
||||
if (_shapeUp) {
|
||||
_shapeUp->getShapeId(flex, shapenum);
|
||||
}
|
||||
ws->writeUint16LE(flex);
|
||||
ws->writeUint32LE(shapenum);
|
||||
ws->writeUint32LE(_frameNumUp);
|
||||
|
||||
flex = 0;
|
||||
shapenum = 0;
|
||||
if (_shapeDown) {
|
||||
_shapeDown->getShapeId(flex, shapenum);
|
||||
}
|
||||
ws->writeUint16LE(flex);
|
||||
ws->writeUint32LE(shapenum);
|
||||
ws->writeUint32LE(_frameNumDown);
|
||||
ws->writeUint16LE(_textWidget);
|
||||
ws->writeUint32LE(_mouseOverBlendCol);
|
||||
|
||||
uint8 m = (_mouseOver ? 1 : 0);
|
||||
ws->writeByte(m);
|
||||
}
|
||||
|
||||
bool ButtonWidget::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
if (!Gump::loadData(rs, version)) return false;
|
||||
|
||||
_shapeUp = nullptr;
|
||||
ShapeArchive *flex = GameData::get_instance()->getShapeFlex(rs->readUint16LE());
|
||||
uint32 shapenum = rs->readUint32LE();
|
||||
if (flex) {
|
||||
_shapeUp = flex->getShape(shapenum);
|
||||
}
|
||||
_frameNumUp = rs->readUint32LE();
|
||||
|
||||
_shapeDown = nullptr;
|
||||
flex = GameData::get_instance()->getShapeFlex(rs->readUint16LE());
|
||||
shapenum = rs->readUint32LE();
|
||||
if (flex) {
|
||||
_shapeDown = flex->getShape(shapenum);
|
||||
}
|
||||
_frameNumDown = rs->readUint32LE();
|
||||
_textWidget = rs->readUint16LE();
|
||||
_mouseOverBlendCol = rs->readUint32LE();
|
||||
_mouseOver = (rs->readByte() != 0);
|
||||
|
||||
// HACK ALERT
|
||||
if (_textWidget != 0) {
|
||||
Gump *widget = getGump(_textWidget);
|
||||
_dims = widget->getDims(); // transfer child dimension to self
|
||||
widget->Move(0, _dims.top); // move it to the correct height
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
88
engines/ultima/ultima8/gumps/widgets/button_widget.h
Normal file
88
engines/ultima/ultima8/gumps/widgets/button_widget.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_WIDGETS_BUTTONWIDGET_H
|
||||
#define ULTIMA8_GUMPS_WIDGETS_BUTTONWIDGET_H
|
||||
|
||||
#include "ultima/shared/std/string.h"
|
||||
#include "ultima/ultima8/gumps/gump.h"
|
||||
#include "ultima/ultima8/gfx/frame_id.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class ButtonWidget : public Gump {
|
||||
public:
|
||||
// p_dynamic_class stuff
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
ButtonWidget();
|
||||
ButtonWidget(int x, int y, Std::string txt, bool gamefont, int font,
|
||||
uint32 mouseOverBlendCol = 0, int width = 0, int height = 0,
|
||||
int32 layer = LAYER_NORMAL);
|
||||
ButtonWidget(int x, int y, FrameID frame_up, FrameID frame_down,
|
||||
bool mouseOver = false, int32 layer = LAYER_NORMAL);
|
||||
~ButtonWidget() override;
|
||||
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
uint16 TraceObjId(int32 mx, int32 my) override;
|
||||
bool PointOnGump(int mx, int my) override;
|
||||
|
||||
Gump *onMouseDown(int button, int32 mx, int32 my) override;
|
||||
void onMouseUp(int button, int32 mx, int32 my) override;
|
||||
void onMouseClick(int button, int32 mx, int32 my) override;
|
||||
void onMouseDouble(int button, int32 mx, int32 my) override;
|
||||
|
||||
void onMouseOver() override;
|
||||
void onMouseLeft() override;
|
||||
|
||||
//! return the textwidget's vlead, or 0 for an image button
|
||||
int getVlead();
|
||||
|
||||
//void SetShapeDown(Shape *_shape, uint32 frameNum);
|
||||
//void SetShapeUp(Shape *_shape, uint32 frameNum);
|
||||
|
||||
enum Message {
|
||||
BUTTON_CLICK = 0,
|
||||
BUTTON_UP = 1,
|
||||
BUTTON_DOUBLE = 2
|
||||
};
|
||||
|
||||
protected:
|
||||
Shape *_shapeUp;
|
||||
uint32 _frameNumUp;
|
||||
Shape *_shapeDown;
|
||||
uint32 _frameNumDown;
|
||||
uint16 _textWidget;
|
||||
uint32 _mouseOverBlendCol;
|
||||
bool _mouseOver;
|
||||
int _origW, _origH;
|
||||
|
||||
public:
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
273
engines/ultima/ultima8/gumps/widgets/edit_widget.cpp
Normal file
273
engines/ultima/ultima8/gumps/widgets/edit_widget.cpp
Normal file
@@ -0,0 +1,273 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/widgets/edit_widget.h"
|
||||
#include "ultima/ultima8/gfx/fonts/rendered_text.h"
|
||||
#include "ultima/ultima8/gfx/render_surface.h"
|
||||
#include "ultima/ultima8/gfx/fonts/font_manager.h"
|
||||
#include "common/system.h"
|
||||
#include "common/events.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(EditWidget)
|
||||
|
||||
EditWidget::EditWidget(int x, int y, Std::string txt, bool gamefont, int font,
|
||||
int w, int h, unsigned int maxlength, bool multiline)
|
||||
: Gump(x, y, w, h), _text(txt), _gameFont(gamefont), _fontNum(font),
|
||||
_maxLength(maxlength), _multiLine(multiline),
|
||||
_cursorChanged(0), _cursorVisible(true), _cachedText(nullptr) {
|
||||
_cursor = _text.size();
|
||||
}
|
||||
|
||||
EditWidget::~EditWidget(void) {
|
||||
delete _cachedText;
|
||||
}
|
||||
|
||||
// Init the gump, call after construction
|
||||
void EditWidget::InitGump(Gump *newparent, bool take_focus) {
|
||||
Gump::InitGump(newparent, take_focus);
|
||||
|
||||
Font *font = getFont();
|
||||
|
||||
// Y offset is always baseline
|
||||
_dims.moveTo(0, -font->getBaseline());
|
||||
|
||||
if (_gameFont && getFont()->isHighRes()) {
|
||||
Common::Rect32 rect(_dims);
|
||||
ScreenSpaceToGumpRect(rect, ROUND_OUTSIDE);
|
||||
_dims.moveTo(0, rect.top);
|
||||
}
|
||||
}
|
||||
|
||||
Font *EditWidget::getFont() const {
|
||||
if (_gameFont)
|
||||
return FontManager::get_instance()->getGameFont(_fontNum, true);
|
||||
else
|
||||
return FontManager::get_instance()->getTTFont(_fontNum);
|
||||
}
|
||||
|
||||
void EditWidget::setText(const Std::string &t) {
|
||||
_text = t;
|
||||
_cursor = _text.size();
|
||||
delete _cachedText;
|
||||
_cachedText = nullptr;
|
||||
}
|
||||
|
||||
void EditWidget::ensureCursorVisible() {
|
||||
_cursorVisible = true;
|
||||
_cursorChanged = g_system->getMillis();
|
||||
}
|
||||
|
||||
bool EditWidget::textFits(Std::string &t) {
|
||||
Font *font = getFont();
|
||||
|
||||
unsigned int remaining;
|
||||
int32 width, height;
|
||||
|
||||
int32 max_width = _multiLine ? _dims.width() : 0;
|
||||
int32 max_height = _dims.height();
|
||||
if (_gameFont && font->isHighRes()) {
|
||||
Common::Rect32 rect(0, 0, max_width, max_height);
|
||||
GumpRectToScreenSpace(rect, ROUND_INSIDE);
|
||||
|
||||
max_width = rect.width();
|
||||
max_height = rect.height();
|
||||
}
|
||||
|
||||
font->getTextSize(t, width, height, remaining,
|
||||
max_width, max_height,
|
||||
Font::TEXT_LEFT, false);
|
||||
|
||||
if (_gameFont && font->isHighRes()) {
|
||||
Common::Rect32 rect(0, 0, width, height);
|
||||
ScreenSpaceToGumpRect(rect, ROUND_OUTSIDE);
|
||||
|
||||
width = rect.width();
|
||||
height = rect.height();
|
||||
}
|
||||
|
||||
if (_multiLine)
|
||||
return (remaining >= t.size());
|
||||
else
|
||||
return (width <= _dims.width());
|
||||
}
|
||||
|
||||
void EditWidget::renderText() {
|
||||
bool cv = _cursorVisible;
|
||||
if (!IsFocus()) {
|
||||
cv = false;
|
||||
} else {
|
||||
uint32 now = g_system->getMillis();
|
||||
if (now > _cursorChanged + 750) {
|
||||
cv = !_cursorVisible;
|
||||
_cursorChanged = now;
|
||||
}
|
||||
}
|
||||
|
||||
if (cv != _cursorVisible) {
|
||||
delete _cachedText;
|
||||
_cachedText = nullptr;
|
||||
_cursorVisible = cv;
|
||||
}
|
||||
|
||||
if (!_cachedText) {
|
||||
Font *font = getFont();
|
||||
|
||||
int32 max_width = _multiLine ? _dims.width() : 0;
|
||||
int32 max_height = _dims.height();
|
||||
if (_gameFont && font->isHighRes()) {
|
||||
Common::Rect32 rect(0, 0, max_width, max_height);
|
||||
GumpRectToScreenSpace(rect, ROUND_INSIDE);
|
||||
|
||||
max_width = rect.width();
|
||||
max_height = rect.height();
|
||||
}
|
||||
|
||||
unsigned int remaining;
|
||||
_cachedText = font->renderText(_text, remaining,
|
||||
max_width, max_height,
|
||||
Font::TEXT_LEFT,
|
||||
false, false,
|
||||
cv ? _cursor : Std::string::npos);
|
||||
|
||||
// Trim text to fit
|
||||
if (remaining < _text.size()) {
|
||||
_text.erase(remaining);
|
||||
_cursor = _text.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Overloadable method to Paint just this Gump (RenderSurface is relative to this)
|
||||
void EditWidget::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
||||
Gump::PaintThis(surf, lerp_factor, scaled);
|
||||
|
||||
renderText();
|
||||
|
||||
if (scaled && _gameFont && getFont()->isHighRes()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_cachedText->draw(surf, 0, 0);
|
||||
}
|
||||
|
||||
// Overloadable method to Paint just this gumps unscaled components that require compositing (RenderSurface is relative to parent).
|
||||
void EditWidget::PaintComposited(RenderSurface *surf, int32 lerp_factor, int32 sx, int32 sy) {
|
||||
Font *font = getFont();
|
||||
|
||||
if (!_gameFont || !font->isHighRes()) return;
|
||||
|
||||
int32 x = 0, y = 0;
|
||||
GumpToScreenSpace(x, y, ROUND_BOTTOMRIGHT);
|
||||
|
||||
_cachedText->draw(surf, x, y, true);
|
||||
|
||||
Common::Rect32 rect(_dims);
|
||||
GumpRectToScreenSpace(rect, ROUND_OUTSIDE);
|
||||
}
|
||||
|
||||
// don't handle any mouse motion events, so let parent handle them for us.
|
||||
Gump *EditWidget::onMouseMotion(int32 mx, int32 my) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool EditWidget::OnKeyDown(int key, int mod) {
|
||||
switch (key) {
|
||||
case Common::KEYCODE_RETURN:
|
||||
case Common::KEYCODE_KP_ENTER:
|
||||
_parent->ChildNotify(this, EDIT_ENTER);
|
||||
break;
|
||||
case Common::KEYCODE_ESCAPE:
|
||||
_parent->ChildNotify(this, EDIT_ESCAPE);
|
||||
break;
|
||||
case Common::KEYCODE_BACKSPACE:
|
||||
if (_cursor > 0) {
|
||||
_text.erase(--_cursor, 1);
|
||||
delete _cachedText;
|
||||
_cachedText = nullptr;
|
||||
ensureCursorVisible();
|
||||
}
|
||||
break;
|
||||
case Common::KEYCODE_DELETE:
|
||||
if (_cursor != _text.size()) {
|
||||
_text.erase(_cursor, 1);
|
||||
delete _cachedText;
|
||||
_cachedText = nullptr;
|
||||
}
|
||||
break;
|
||||
case Common::KEYCODE_LEFT:
|
||||
if (_cursor > 0) {
|
||||
_cursor--;
|
||||
delete _cachedText;
|
||||
_cachedText = nullptr;
|
||||
ensureCursorVisible();
|
||||
}
|
||||
break;
|
||||
case Common::KEYCODE_RIGHT:
|
||||
if (_cursor < _text.size()) {
|
||||
_cursor++;
|
||||
delete _cachedText;
|
||||
_cachedText = nullptr;
|
||||
ensureCursorVisible();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EditWidget::OnKeyUp(int key) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool EditWidget::OnTextInput(int unicode) {
|
||||
if (_maxLength > 0 && _text.size() >= _maxLength)
|
||||
return true;
|
||||
|
||||
char c = 0;
|
||||
if (unicode >= 0 && unicode < 256)
|
||||
c = reverse_encoding[unicode];
|
||||
if (!c) return true;
|
||||
|
||||
Std::string newtext = _text;
|
||||
newtext.insertChar(c, _cursor);
|
||||
|
||||
if (textFits(newtext)) {
|
||||
_text = newtext;
|
||||
_cursor++;
|
||||
delete _cachedText;
|
||||
_cachedText = nullptr;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void EditWidget::OnFocus(bool gain) {
|
||||
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, gain);
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
95
engines/ultima/ultima8/gumps/widgets/edit_widget.h
Normal file
95
engines/ultima/ultima8/gumps/widgets/edit_widget.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_WIDGETS_EDITWIDGET_H
|
||||
#define ULTIMA8_GUMPS_WIDGETS_EDITWIDGET_H
|
||||
|
||||
//
|
||||
// EditWidget. Widget for text input (single or multi-line)
|
||||
//
|
||||
|
||||
#include "ultima/ultima8/gumps/gump.h"
|
||||
|
||||
#include "ultima/ultima8/gfx/fonts/font.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class RenderedText;
|
||||
|
||||
class EditWidget : public Gump {
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
EditWidget(int x, int y, Std::string txt, bool gamefont, int fontnum,
|
||||
int width, int height, unsigned int maxlength = 0,
|
||||
bool multiline = false);
|
||||
~EditWidget() override;
|
||||
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
|
||||
void PaintThis(RenderSurface *, int32 lerp_factor, bool scaled) override;
|
||||
void PaintComposited(RenderSurface *surf, int32 lerp_factor, int32 sx, int32 sy) override;
|
||||
|
||||
Gump *onMouseMotion(int32 mx, int32 my) override;
|
||||
bool OnKeyDown(int key, int mod) override;
|
||||
bool OnKeyUp(int key) override;
|
||||
bool OnTextInput(int unicode) override;
|
||||
|
||||
void OnFocus(bool gain) override;
|
||||
|
||||
//! get the current text
|
||||
Std::string getText() const {
|
||||
return _text;
|
||||
}
|
||||
void setText(const Std::string &t);
|
||||
|
||||
enum Message {
|
||||
EDIT_ENTER = 16,
|
||||
EDIT_ESCAPE = 17
|
||||
};
|
||||
|
||||
|
||||
protected:
|
||||
Std::string _text;
|
||||
Std::string::size_type _cursor;
|
||||
bool _gameFont;
|
||||
int _fontNum;
|
||||
unsigned int _maxLength;
|
||||
bool _multiLine;
|
||||
|
||||
uint32 _cursorChanged;
|
||||
bool _cursorVisible;
|
||||
|
||||
void ensureCursorVisible();
|
||||
bool textFits(Std::string &t);
|
||||
void renderText();
|
||||
Font *getFont() const;
|
||||
|
||||
RenderedText *_cachedText;
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
107
engines/ultima/ultima8/gumps/widgets/sliding_widget.cpp
Normal file
107
engines/ultima/ultima8/gumps/widgets/sliding_widget.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/gumps/widgets/sliding_widget.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(SlidingWidget)
|
||||
|
||||
SlidingWidget::SlidingWidget()
|
||||
: Gump(), _dragBounds() {
|
||||
}
|
||||
|
||||
SlidingWidget::SlidingWidget(int x, int y, FrameID frame, const Common::Rect32 &dragBounds)
|
||||
: Gump(x, y, 5, 5, 0, FLAG_DRAGGABLE), _dragBounds(dragBounds) {
|
||||
SetShape(frame, true);
|
||||
if (_dragBounds.width() < _dims.width())
|
||||
_dragBounds.setWidth(_dims.width());
|
||||
if (_dragBounds.height() < _dims.height())
|
||||
_dragBounds.setHeight(_dims.height());
|
||||
}
|
||||
|
||||
SlidingWidget::~SlidingWidget() {
|
||||
}
|
||||
|
||||
int SlidingWidget::getValueForRange(int min, int max) {
|
||||
int val = min;
|
||||
if (_dragBounds.isValidRect()) {
|
||||
val = min + (_x - _dragBounds.left) * (max - min) / (_dragBounds.width() - _dims.width());
|
||||
if (val < min)
|
||||
val = min;
|
||||
if (val > max)
|
||||
val = max;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
void SlidingWidget::setValueForRange(int value, int min, int max) {
|
||||
assert(_dragBounds.isValidRect());
|
||||
_x = _dragBounds.left + (value - min) * (_dragBounds.width() - _dims.width()) / (max - min);
|
||||
}
|
||||
|
||||
void SlidingWidget::InitGump(Gump *newparent, bool take_focus) {
|
||||
Gump::InitGump(newparent, take_focus);
|
||||
|
||||
UpdateDimsFromShape();
|
||||
}
|
||||
|
||||
uint16 SlidingWidget::TraceObjId(int32 mx, int32 my) {
|
||||
if (PointOnGump(mx, my))
|
||||
return getObjId();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SlidingWidget::Move(int32 x, int32 y) {
|
||||
if (_dragBounds.isValidRect()) {
|
||||
if (x < _dragBounds.left)
|
||||
x = _dragBounds.left;
|
||||
if (x > _dragBounds.right - _dims.width())
|
||||
x = _dragBounds.right - _dims.width();
|
||||
if (y < _dragBounds.top)
|
||||
y = _dragBounds.top;
|
||||
if (y > _dragBounds.bottom - _dims.height())
|
||||
y = _dragBounds.bottom - _dims.height();
|
||||
}
|
||||
|
||||
_x = x;
|
||||
_y = y;
|
||||
}
|
||||
|
||||
void SlidingWidget::onDrag(int32 mx, int32 my) {
|
||||
Gump::onDrag(mx, my);
|
||||
_parent->ChildNotify(this, DRAGGING);
|
||||
}
|
||||
|
||||
void SlidingWidget::saveData(Common::WriteStream *ws) {
|
||||
Gump::saveData(ws);
|
||||
}
|
||||
|
||||
bool SlidingWidget::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
if (!Gump::loadData(rs, version)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
62
engines/ultima/ultima8/gumps/widgets/sliding_widget.h
Normal file
62
engines/ultima/ultima8/gumps/widgets/sliding_widget.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GUMPS_WIDGETS_SLIDINGWIDGET_H
|
||||
#define ULTIMA8_GUMPS_WIDGETS_SLIDINGWIDGET_H
|
||||
|
||||
#include "ultima/ultima8/gumps/gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class SlidingWidget : public Gump {
|
||||
protected:
|
||||
Common::Rect32 _dragBounds;
|
||||
|
||||
public:
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
SlidingWidget();
|
||||
SlidingWidget(int x, int y, FrameID frame, const Common::Rect32 &dragBounds);
|
||||
~SlidingWidget() override;
|
||||
|
||||
int getValueForRange(int min, int max);
|
||||
void setValueForRange(int value, int min, int max);
|
||||
|
||||
void InitGump(Gump *newparent, bool take_focus = true) override;
|
||||
uint16 TraceObjId(int32 mx, int32 my) override;
|
||||
|
||||
void Move(int32 x, int32 y) override;
|
||||
void onDrag(int32 mx, int32 my) override;
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
|
||||
enum Message {
|
||||
DRAGGING = 0
|
||||
};
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user