Files
2026-02-02 04:50:13 +01:00

550 lines
12 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 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 "titanic/pet_control/pet_glyphs.h"
#include "titanic/pet_control/pet_section.h"
#include "titanic/pet_control/pet_control.h"
namespace Titanic {
bool CPetGlyph::setup(CPetControl *petControl, CPetGlyphs *owner) {
_element.setBounds(Rect(0, 0, 52, 50));
_owner = owner;
return true;
}
void CPetGlyph::drawAt(CScreenManager *screenManager, const Point &pt, bool isHighlighted_) {
_element.translate(pt.x, pt.y);
_element.draw(screenManager);
_element.translate(-pt.x, -pt.y);
}
void CPetGlyph::updateTooltip() {
CTextControl *petText = getPetSection()->getText();
if (petText) {
petText->setColor(getPetSection()->getColor(0));
getTooltip(petText);
if (_owner)
getPetSection()->stopTextTimer();
}
}
bool CPetGlyph::contains(const Point &delta, const Point &pt) {
translate(delta);
bool result = _element.contains2(pt);
translateBack(delta);
return result;
}
CPetSection *CPetGlyph::getPetSection() const {
return _owner ? _owner->getOwner() : nullptr;
}
CPetControl *CPetGlyph::getPetControl() const {
return _owner ? _owner->getPetControl() : nullptr;
}
void CPetGlyph::setName(const CString &name, CPetControl *petControl) {
Rect r(0, 0, 52, 52);
_element.setBounds(r);
_element.reset(name, petControl, MODE_UNSELECTED);
}
bool CPetGlyph::isHighlighted() const {
return _owner->isGlyphHighlighted(this);
}
/*------------------------------------------------------------------------*/
CPetGlyphs::CPetGlyphs() : _firstVisibleIndex(0), _numVisibleGlyphs(TOTAL_GLYPHS),
_highlightIndex(-1), _field1C(-1), _flags(0),
_dragGlyph(nullptr), _owner(nullptr) {
}
void CPetGlyphs::setNumVisible(int total) {
if (total > 0)
_numVisibleGlyphs = total;
}
void CPetGlyphs::clear() {
changeHighlight(-1);
destroyContents();
_firstVisibleIndex = 0;
}
void CPetGlyphs::setup(int numVisible, CPetSection *owner) {
setNumVisible(numVisible);
_owner = owner;
_selection.setBounds(Rect(0, 0, 76, 76));
int buttonsLeft = numVisible * 70 + 21;
_scrollLeft.setBounds(Rect(0, 0, 31, 15));
_scrollLeft.translate(buttonsLeft + 7, 373);
_scrollRight.setBounds(Rect(0, 0, 31, 15));
_scrollRight.translate(buttonsLeft + 7, 413);
}
void CPetGlyphs::reset() {
if (_owner && _owner->_petControl) {
CPetControl *pet = _owner->_petControl;
_scrollLeft.reset("PetScrollLeft", pet, MODE_UNSELECTED);
_scrollRight.reset("PetScrollRight", pet, MODE_UNSELECTED);
_selection.reset("PetSelection", pet, MODE_UNSELECTED);
for (iterator i = begin(); i != end(); ++i) {
(*i)->reset();
}
}
}
void CPetGlyphs::enter() {
if (_highlightIndex != -1) {
CPetGlyph *glyph = getGlyph(_highlightIndex);
if (glyph)
glyph->enter();
}
}
void CPetGlyphs::leave() {
if (_highlightIndex != -1) {
CPetGlyph *glyph = getGlyph(_highlightIndex);
if (glyph)
glyph->leave();
}
}
void CPetGlyphs::draw(CScreenManager *screenManager) {
if (_highlightIndex != -1) {
int index = getHighlightedIndex(_highlightIndex);
if (index != -1) {
Point pt = getPosition(index);
pt -= Point(12, 13);
_selection.translate(pt.x, pt.y);
_selection.draw(screenManager);
_selection.translate(-pt.x, -pt.y);
}
}
// Iterate through displaying glyphs on the screen
int listSize = size();
for (int index = 0; index < _numVisibleGlyphs; ++index) {
int itemIndex = getItemIndex(index);
if (itemIndex >= 0 && itemIndex < listSize) {
Point pt = getPosition(index);
CPetGlyph *glyph = getGlyph(itemIndex);
if (glyph)
glyph->drawAt(screenManager, pt, itemIndex == _highlightIndex);
}
}
// Draw scrolling arrows if more than a screen's worth of items are showing
if (listSize > _numVisibleGlyphs || (_flags & GFLAG_16)) {
_scrollLeft.draw(screenManager);
_scrollRight.draw(screenManager);
}
// Handle secondary highlight
if (_highlightIndex != -1) {
CPetGlyph *glyph = getGlyph(_highlightIndex);
if (glyph)
glyph->draw2(screenManager);
}
}
Point CPetGlyphs::getPosition(int index) const {
Point tempPoint(37 + index * 70, 375);
return tempPoint;
}
Rect CPetGlyphs::getRect(int index) const {
Point pt = getPosition(index);
return Rect(pt.x, pt.y, pt.x + 52, pt.y + 52);
}
void CPetGlyphs::changeHighlight(int index) {
if (index == _highlightIndex)
return;
if (_highlightIndex >= 0 && (_flags & GFLAG_4)) {
CPetGlyph *glyph = getGlyph(_highlightIndex);
if (glyph)
glyph->unhighlightCurrent();
}
_highlightIndex = index;
if (index >= 0) {
CPetGlyph *glyph = getGlyph(_highlightIndex);
if (glyph) {
if (_flags & GFLAG_4) {
Point pt;
int idx = getHighlightedIndex(_highlightIndex);
if (idx >= 0)
pt = getPosition(idx);
glyph->highlightCurrent(pt);
}
glyph->updateTooltip();
}
} else if (_owner) {
_owner->removeText();
}
}
void CPetGlyphs::highlight(int index) {
if (index >= 0) {
setSelectedIndex(index);
changeHighlight(index);
makePetDirty();
}
}
void CPetGlyphs::highlight(const CPetGlyph *glyph) {
highlight(indexOf(glyph));
}
int CPetGlyphs::getHighlightedIndex(int index) const {
int idx = index - _firstVisibleIndex;
return (idx >= 0 && idx < _numVisibleGlyphs) ? idx : -1;
}
int CPetGlyphs::getItemIndex(int index) const {
return _firstVisibleIndex + index;
}
void CPetGlyphs::setSelectedIndex(int index) {
if (index >= 0 && index < (int)size() && getHighlightedIndex(index) == -1) {
if (_firstVisibleIndex <= index)
index -= _numVisibleGlyphs - 1;
setFirstVisible(index);
}
}
CPetGlyph *CPetGlyphs::getGlyph(int index) const {
for (const_iterator i = begin(); i != end(); ++i) {
if (index-- == 0)
return *i;
}
return nullptr;
}
CPetControl *CPetGlyphs::getPetControl() const {
return _owner ? _owner->getPetControl() : nullptr;
}
void CPetGlyphs::setFirstVisible(int index) {
if (index != _firstVisibleIndex) {
_firstVisibleIndex = index;
if ((_flags & GFLAG_8) && _highlightIndex != -1) {
CPetGlyph *glyph = getGlyph(_highlightIndex);
if (glyph) {
int idx = getHighlightedIndex(_highlightIndex);
if (idx != -1) {
Point tempPt = getPosition(idx);
glyph->glyphFocused(tempPt, true);
}
}
}
}
}
void CPetGlyphs::scrollLeft() {
if (_firstVisibleIndex > 0) {
setFirstVisible(_firstVisibleIndex - 1);
if (_highlightIndex != -1) {
int index = getHighlightedIndex(_highlightIndex);
if (index == -1)
changeHighlight(_highlightIndex - 1);
}
makePetDirty();
}
}
void CPetGlyphs::scrollRight() {
int count = size();
int right = count - _numVisibleGlyphs;
if (_firstVisibleIndex < right) {
setFirstVisible(_firstVisibleIndex + 1);
if (_highlightIndex != -1) {
int index = getHighlightedIndex(_highlightIndex);
if (index == -1)
changeHighlight(_highlightIndex + 1);
}
makePetDirty();
}
}
void CPetGlyphs::makePetDirty() {
if (_owner && _owner->_petControl)
_owner->_petControl->makeDirty();
}
bool CPetGlyphs::MouseButtonDownMsg(const Point &pt) {
if (_scrollLeft.contains2(pt)) {
scrollLeft();
return true;
}
if (_scrollRight.contains2(pt)) {
scrollRight();
return true;
}
for (int idx = 0; idx < _numVisibleGlyphs; ++idx) {
Rect glyphRect = getRect(idx);
if (glyphRect.contains(pt)) {
int index = getItemIndex(idx);
CPetGlyph *glyph = getGlyph(index);
if (glyph) {
if (_highlightIndex == index) {
glyph->selectGlyph(glyphRect, pt);
glyph->updateTooltip();
} else {
changeHighlight(index);
makePetDirty();
}
return true;
}
}
}
if (_highlightIndex != -1) {
CPetGlyph *glyph = getGlyph(_highlightIndex);
if (glyph) {
if (glyph->MouseButtonDownMsg(pt))
return true;
if (!(_flags & GFLAG_2)) {
changeHighlight(-1);
makePetDirty();
}
}
}
return false;
}
bool CPetGlyphs::MouseButtonUpMsg(const Point &pt) {
if (_highlightIndex >= 0) {
CPetGlyph *glyph = getGlyph(_highlightIndex);
if (glyph) {
if (glyph->MouseButtonUpMsg(pt))
return true;
}
}
return false;
}
bool CPetGlyphs::MouseDragStartMsg(CMouseDragStartMsg *msg) {
if (!(_flags & GFLAG_1) && _highlightIndex >= 0) {
CPetGlyph *glyph = getGlyph(_highlightIndex);
int index = getHighlightedIndex(_highlightIndex);
Rect glyphRect = getRect(index);
if (glyphRect.contains(msg->_mousePos))
return glyph->dragGlyph(glyphRect, msg);
else
return glyph->MouseDragStartMsg(msg);
}
return false;
}
bool CPetGlyphs::MouseDragMoveMsg(CMouseDragMoveMsg *msg) {
if (_dragGlyph) {
return _dragGlyph->MouseDragMoveMsg(msg);
} else {
return false;
}
}
bool CPetGlyphs::MouseDragEndMsg(CMouseDragEndMsg *msg) {
if (_dragGlyph) {
return _dragGlyph->MouseDragEndMsg(msg);
} else {
return false;
}
}
bool CPetGlyphs::KeyCharMsg(int key) {
if (_highlightIndex >= 0) {
CPetGlyph *glyph = getGlyph(_highlightIndex);
if (glyph && glyph->KeyCharMsg(key))
return true;
}
return false;
}
bool CPetGlyphs::ActionMsg(CActionMsg *msg) {
if (_highlightIndex >= 0) {
CPetGlyph *glyph = getGlyph(_highlightIndex);
if (glyph && glyph->ActionMsg(msg))
return true;
}
return false;
}
bool CPetGlyphs::enterHighlighted() {
if (_highlightIndex >= 0)
return getGlyph(_highlightIndex)->enterHighlighted();
else
return false;
}
void CPetGlyphs::leaveHighlighted() {
if (_highlightIndex >= 0)
getGlyph(_highlightIndex)->leaveHighlighted();
}
void CPetGlyphs::startDragging(CPetGlyph *glyph, CMouseDragStartMsg *msg) {
if (glyph) {
_dragGlyph = glyph;
msg->_dragItem = getPetControl();
}
}
void CPetGlyphs::endDragging() {
_dragGlyph = nullptr;
}
bool CPetGlyphs::highlighted14() {
if (_highlightIndex != -1) {
CPetGlyph *pet = getGlyph(_highlightIndex);
if (pet) {
pet->updateTooltip();
return true;
}
}
return false;
}
int CPetGlyphs::indexOf(const CPetGlyph *glyph) const {
int index = 0;
for (const_iterator i = begin(); i != end(); ++i, ++index) {
if (*i == glyph)
return index;
}
return -1;
}
void CPetGlyphs::incSelection() {
if (_highlightIndex >= 0 && _highlightIndex < ((int)size() - 1)) {
if (getHighlightedIndex(_highlightIndex) >= (_numVisibleGlyphs - 1))
scrollRight();
changeHighlight(_highlightIndex + 1);
makePetDirty();
}
}
void CPetGlyphs::decSelection() {
if (_highlightIndex > 0) {
if (getHighlightedIndex(_highlightIndex) == 0)
scrollLeft();
changeHighlight(_highlightIndex - 1);
makePetDirty();
}
}
CGameObject *CPetGlyphs::getObjectAt(const Point &pt) const {
for (int idx = 0; idx < _numVisibleGlyphs; ++idx) {
Rect glyphRect = getRect(idx);
if (glyphRect.contains(pt)) {
CPetGlyph *glyph = getGlyph(getItemIndex(idx));
if (glyph)
return glyph->getObjectAt();
}
}
return nullptr;
}
bool CPetGlyphs::isGlyphHighlighted(const CPetGlyph *glyph) const {
if (_highlightIndex == -1)
return false;
return indexOf(glyph) == _highlightIndex;
}
Point CPetGlyphs::getHighlightedGlyphPos() const {
if (_highlightIndex != -1) {
int idx = getHighlightedIndex(_highlightIndex);
if (idx >= 0)
return getPosition(idx);
}
return Point(0, 0);
}
bool CPetGlyphs::areItemsValid() const {
for (const_iterator i = begin(); i != end(); ++i) {
if (!(*i)->isValid())
return false;
}
return true;
}
void CPetGlyphs::removeInvalid() {
if (!areItemsValid()) {
changeHighlight(-1);
for (iterator i = begin(); i != end(); ) {
CPetGlyph *glyph = *i;
if (!glyph->isValid()) {
i = erase(i);
delete glyph;
} else {
++i;
}
}
int max = MAX((int)size() - _numVisibleGlyphs, 0);
_firstVisibleIndex = CLIP(_firstVisibleIndex, 0, max);
}
}
} // End of namespace Titanic