mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-07 02:12:14 +00:00
289 lines
6.9 KiB
C++
289 lines
6.9 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include "titanic/core/tree_item.h"
|
|
#include "titanic/core/dont_save_file_item.h"
|
|
#include "titanic/core/file_item.h"
|
|
#include "titanic/core/game_object.h"
|
|
#include "titanic/core/game_object_desc_item.h"
|
|
#include "titanic/core/link_item.h"
|
|
#include "titanic/core/mail_man.h"
|
|
#include "titanic/core/named_item.h"
|
|
#include "titanic/core/node_item.h"
|
|
#include "titanic/core/project_item.h"
|
|
#include "titanic/core/view_item.h"
|
|
#include "titanic/core/room_item.h"
|
|
#include "titanic/pet_control/pet_control.h"
|
|
#include "titanic/game_manager.h"
|
|
#include "titanic/game/placeholder/place_holder.h"
|
|
|
|
namespace Titanic {
|
|
|
|
EMPTY_MESSAGE_MAP(CTreeItem, CMessageTarget);
|
|
|
|
CTreeItem::CTreeItem() : _parent(nullptr), _firstChild(nullptr),
|
|
_nextSibling(nullptr), _priorSibling(nullptr), _field14(0) {
|
|
}
|
|
|
|
void CTreeItem::dump(int indent) {
|
|
CString line = dumpItem(indent);
|
|
debug("%s", line.c_str());
|
|
|
|
CTreeItem *item = getFirstChild();
|
|
while (item) {
|
|
item->dump(indent + 1);
|
|
|
|
item = item->getNextSibling();
|
|
}
|
|
}
|
|
|
|
CString CTreeItem::dumpItem(int indent) const {
|
|
CString result;
|
|
for (int idx = 0; idx < indent; ++idx)
|
|
result += '\t';
|
|
result += getType()->_className;
|
|
|
|
return result;
|
|
}
|
|
|
|
void CTreeItem::save(SimpleFile *file, int indent) {
|
|
file->writeNumberLine(0, indent);
|
|
CMessageTarget::save(file, indent);
|
|
}
|
|
|
|
void CTreeItem::load(SimpleFile *file) {
|
|
file->readNumber();
|
|
CMessageTarget::load(file);
|
|
}
|
|
|
|
bool CTreeItem::isFileItem() const {
|
|
return isInstanceOf(CFileItem::_type);
|
|
}
|
|
|
|
bool CTreeItem::isRoomItem() const {
|
|
return isInstanceOf(CRoomItem::_type);
|
|
}
|
|
|
|
bool CTreeItem::isNodeItem() const {
|
|
return isInstanceOf(CNodeItem::_type);
|
|
}
|
|
|
|
bool CTreeItem::isViewItem() const {
|
|
return isInstanceOf(CViewItem::_type);
|
|
}
|
|
|
|
bool CTreeItem::isLinkItem() const {
|
|
return isInstanceOf(CLinkItem::_type);
|
|
}
|
|
|
|
bool CTreeItem::isPlaceHolderItem() const {
|
|
return isInstanceOf(CPlaceHolder::_type);
|
|
}
|
|
|
|
bool CTreeItem::isNamedItem() const {
|
|
return isInstanceOf(CNamedItem::_type);
|
|
}
|
|
|
|
bool CTreeItem::isGameObject() const {
|
|
return isInstanceOf(CGameObject::_type);
|
|
}
|
|
|
|
bool CTreeItem::isGameObjectDescItem() const {
|
|
return isInstanceOf(CGameObjectDescItem::_type);
|
|
}
|
|
|
|
CGameManager *CTreeItem::getGameManager() const {
|
|
return _parent ? _parent->getGameManager() : nullptr;
|
|
}
|
|
|
|
CProjectItem *CTreeItem::getRoot() const {
|
|
CTreeItem *parent = getParent();
|
|
|
|
if (parent) {
|
|
do {
|
|
parent = parent->getParent();
|
|
} while (parent->getParent());
|
|
}
|
|
|
|
return dynamic_cast<CProjectItem *>(parent);
|
|
}
|
|
|
|
CTreeItem *CTreeItem::getLastSibling() {
|
|
CTreeItem *item = this;
|
|
while (item->getNextSibling())
|
|
item = item->getNextSibling();
|
|
|
|
return item;
|
|
}
|
|
|
|
CTreeItem *CTreeItem::getLastChild() const {
|
|
if (!_firstChild)
|
|
return nullptr;
|
|
return _firstChild->getLastSibling();
|
|
}
|
|
|
|
CTreeItem *CTreeItem::scan(CTreeItem *item) const {
|
|
if (_firstChild)
|
|
return _firstChild;
|
|
|
|
const CTreeItem *treeItem = this;
|
|
while (treeItem != item) {
|
|
if (treeItem->_nextSibling)
|
|
return treeItem->_nextSibling;
|
|
|
|
treeItem = treeItem->_parent;
|
|
if (!treeItem)
|
|
break;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
CTreeItem *CTreeItem::findChildInstanceOf(ClassDef *classDef) const {
|
|
for (CTreeItem *treeItem = _firstChild; treeItem; treeItem = treeItem->getNextSibling()) {
|
|
if (treeItem->isInstanceOf(classDef))
|
|
return treeItem;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
CTreeItem *CTreeItem::findNextInstanceOf(ClassDef *classDef, CTreeItem *startItem) const {
|
|
CTreeItem *treeItem = startItem ? startItem->getNextSibling() : getFirstChild();
|
|
|
|
for (; treeItem; treeItem = treeItem->getNextSibling()) {
|
|
if (treeItem->isInstanceOf(classDef))
|
|
return treeItem;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
void CTreeItem::addUnder(CTreeItem *newParent) {
|
|
if (newParent->_firstChild)
|
|
addSibling(newParent->_firstChild->getLastSibling());
|
|
else
|
|
setParent(newParent);
|
|
}
|
|
|
|
void CTreeItem::setParent(CTreeItem *newParent) {
|
|
_parent = newParent;
|
|
_priorSibling = nullptr;
|
|
_nextSibling = newParent->_firstChild;
|
|
|
|
if (newParent->_firstChild)
|
|
newParent->_firstChild->_priorSibling = this;
|
|
newParent->_firstChild = this;
|
|
}
|
|
|
|
void CTreeItem::addSibling(CTreeItem *item) {
|
|
_priorSibling = item;
|
|
_nextSibling = item->_nextSibling;
|
|
_parent = item->_parent;
|
|
|
|
if (item->_nextSibling)
|
|
item->_nextSibling->_priorSibling = this;
|
|
item->_nextSibling = this;
|
|
}
|
|
|
|
void CTreeItem::moveUnder(CTreeItem *newParent) {
|
|
if (newParent) {
|
|
detach();
|
|
addUnder(newParent);
|
|
}
|
|
}
|
|
|
|
void CTreeItem::destroyAll() {
|
|
destroyChildren();
|
|
detach();
|
|
delete this;
|
|
}
|
|
|
|
int CTreeItem::destroyChildren() {
|
|
if (!_firstChild)
|
|
return 0;
|
|
|
|
CTreeItem *item = _firstChild, *child, *nextSibling;
|
|
int total = 0;
|
|
|
|
do {
|
|
child = item->_firstChild;
|
|
nextSibling = item->_nextSibling;
|
|
|
|
if (child)
|
|
total += item->destroyChildren();
|
|
item->detach();
|
|
delete item;
|
|
++total;
|
|
} while ((item = nextSibling) != nullptr);
|
|
|
|
return total;
|
|
}
|
|
|
|
void CTreeItem::detach() {
|
|
// Delink this item from any prior and/or next siblings
|
|
if (_priorSibling)
|
|
_priorSibling->_nextSibling = _nextSibling;
|
|
if (_nextSibling)
|
|
_nextSibling->_priorSibling = _priorSibling;
|
|
|
|
if (_parent && _parent->_firstChild == this)
|
|
_parent->_firstChild = _nextSibling;
|
|
|
|
_priorSibling = _nextSibling = _parent = nullptr;
|
|
}
|
|
|
|
void CTreeItem::attach(CTreeItem *item) {
|
|
_nextSibling = item;
|
|
_priorSibling = item->_priorSibling;
|
|
_parent = item->_parent;
|
|
|
|
if (item->_priorSibling)
|
|
item->_priorSibling->_nextSibling = this;
|
|
|
|
item->_priorSibling = this;
|
|
if (item->_parent && !item->_parent->_firstChild)
|
|
item->_parent->_firstChild = this;
|
|
}
|
|
|
|
CNamedItem *CTreeItem::findByName(const CString &name, bool subMatch) {
|
|
CString nameLower = name;
|
|
nameLower.toLowercase();
|
|
|
|
for (CTreeItem *treeItem = this; treeItem; treeItem = treeItem->scan(this)) {
|
|
CString itemName = treeItem->getName();
|
|
itemName.toLowercase();
|
|
|
|
if (subMatch) {
|
|
if (!itemName.left(nameLower.size()).compareTo(nameLower))
|
|
return dynamic_cast<CNamedItem *>(treeItem);
|
|
} else {
|
|
if (!itemName.compareTo(nameLower))
|
|
return dynamic_cast<CNamedItem *>(treeItem);
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
} // End of namespace Titanic
|