ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

item.cpp

Go to the documentation of this file.
00001 /* ResidualVM - A 3D game interpreter
00002  *
00003  * ResidualVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the AUTHORS
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "engines/stark/resources/item.h"
00024 
00025 #include "engines/stark/formats/xrc.h"
00026 #include "engines/stark/gfx/renderentry.h"
00027 #include "engines/stark/model/animhandler.h"
00028 #include "engines/stark/movement/movement.h"
00029 #include "engines/stark/visual/actor.h"
00030 
00031 #include "engines/stark/resources/anim.h"
00032 #include "engines/stark/resources/animhierarchy.h"
00033 #include "engines/stark/resources/bonesmesh.h"
00034 #include "engines/stark/resources/bookmark.h"
00035 #include "engines/stark/resources/floor.h"
00036 #include "engines/stark/resources/floorface.h"
00037 #include "engines/stark/resources/knowledgeset.h"
00038 #include "engines/stark/resources/location.h"
00039 #include "engines/stark/resources/pattable.h"
00040 #include "engines/stark/resources/script.h"
00041 #include "engines/stark/resources/textureset.h"
00042 
00043 #include "engines/stark/services/global.h"
00044 #include "engines/stark/services/services.h"
00045 #include "engines/stark/services/stateprovider.h"
00046 #include "engines/stark/services/userinterface.h"
00047 #include "engines/stark/services/settings.h"
00048 
00049 namespace Stark {
00050 namespace Resources {
00051 
00052 Object *Item::construct(Object *parent, byte subType, uint16 index, const Common::String &name) {
00053     switch (subType) {
00054     case kItemGlobalTemplate:
00055         return new GlobalItemTemplate(parent, subType, index, name);
00056     case kItemInventory:
00057         return new InventoryItem(parent, subType, index, name);
00058     case kItemLevelTemplate:
00059         return new LevelItemTemplate(parent, subType, index, name);
00060     case kItemStaticProp:
00061     case kItemAnimatedProp:
00062         return new FloorPositionedImageItem(parent, subType, index, name);
00063     case kItemBackgroundElement:
00064     case kItemBackground:
00065         return new ImageItem(parent, subType, index, name);
00066     case kItemModel:
00067         return new ModelItem(parent, subType, index, name);
00068     default:
00069         error("Unknown item subtype %d", subType);
00070     }
00071 }
00072 
00073 Item::Item(Object *parent, byte subType, uint16 index, const Common::String &name) :
00074         Object(parent, subType, index, name),
00075         _enabled(true),
00076         _characterIndex(0),
00077         _movement(nullptr),
00078         _movementSuspendedScript(nullptr) {
00079     _type = TYPE;
00080 }
00081 
00082 Item::~Item() {
00083     delete _movement;
00084 }
00085 
00086 void Item::readData(Formats::XRCReadStream *stream) {
00087     _enabled = stream->readBool();
00088     _characterIndex = stream->readSint32LE();
00089 }
00090 
00091 void Item::onGameLoop() {
00092     Object::onGameLoop();
00093 
00094     if (_enabled && _movement) {
00095         _movement->onGameLoop();
00096 
00097         if (_movement && _movement->hasEnded()) {
00098             setMovement(nullptr);
00099         }
00100     }
00101 }
00102 
00103 bool Item::isEnabled() const {
00104     return _enabled;
00105 }
00106 
00107 void Item::setEnabled(bool enabled) {
00108     if (_enabled && !enabled) {
00109         setMovement(nullptr);
00110     }
00111 
00112     _enabled = enabled;
00113 }
00114 
00115 int32 Item::getCharacterIndex() const {
00116     return _characterIndex;
00117 }
00118 
00119 Gfx::RenderEntry *Item::getRenderEntry(const Common::Point &positionOffset) {
00120     return nullptr;
00121 }
00122 
00123 Movement *Item::getMovement() const {
00124     return _movement;
00125 }
00126 
00127 void Item::setMovement(Movement *movement) {
00128     if (_movementSuspendedScript) {
00129         if (_movement && _movement->hasReachedDestination()) {
00130             _movementSuspendedScript->setResumeStatus(Script::kResumeComplete);
00131         } else {
00132             _movementSuspendedScript->setResumeStatus(Script::kResumeAbort);
00133         }
00134         _movementSuspendedScript = nullptr;
00135     }
00136 
00137     if (_movement && !_movement->hasEnded()) {
00138         _movement->stop(true);
00139     }
00140 
00141     delete _movement;
00142     _movement = movement;
00143 }
00144 
00145 void Item::setMovementSuspendedScript(Script *script) {
00146     _movementSuspendedScript = script;
00147 }
00148 
00149 void Item::printData() {
00150     debug("enabled: %d", _enabled);
00151     debug("character: %d", _characterIndex);
00152 }
00153 
00154 void Item::saveLoad(ResourceSerializer *serializer) {
00155     serializer->syncAsSint32LE(_enabled);
00156 }
00157 
00158 void Item::saveLoadCurrent(ResourceSerializer *serializer) {
00159     bool hasMovement = _movement != nullptr && !_movement->hasEnded();
00160     serializer->syncAsUint32LE(hasMovement, 8);
00161 
00162     if (hasMovement) {
00163         uint32 movementType = _movement != nullptr ? _movement->getType() : 0;
00164         serializer->syncAsUint32LE(movementType);
00165 
00166         if (serializer->isLoading()) {
00167             _movement = Movement::construct(movementType, Object::cast<ItemVisual>(this));
00168         }
00169 
00170         _movement->saveLoad(serializer);
00171         serializer->syncAsResourceReference(&_movementSuspendedScript);
00172 
00173         if (serializer->isLoading()) {
00174             _movement->start();
00175         }
00176     }
00177 }
00178 
00179 Common::Array<Common::Point> Item::listExitPositions() {
00180     return Common::Array<Common::Point>();
00181 }
00182 
00183 ItemVisual::~ItemVisual() {
00184     delete _renderEntry;
00185 }
00186 
00187 ItemVisual::ItemVisual(Object *parent, byte subType, uint16 index, const Common::String &name) :
00188                 Item(parent, subType, index, name),
00189                 _renderEntry(nullptr),
00190                 _actionAnim(nullptr),
00191                 _animHierarchy(nullptr),
00192                 _currentAnimActivity(-1),
00193                 _clickable(true) {
00194     _renderEntry = new Gfx::RenderEntry(this, getName());
00195 }
00196 
00197 void ItemVisual::readData(Formats::XRCReadStream *stream) {
00198     Item::readData(stream);
00199 
00200     _clickable = stream->readBool();
00201 }
00202 
00203 void ItemVisual::onAllLoaded() {
00204     Item::onAllLoaded();
00205 
00206     _animHierarchy = findChild<AnimHierarchy>(false);
00207 
00208     _renderEntry->setClickable(_clickable);
00209 
00210     if (_subType != kItemModel) {
00211         setAnimActivity(Anim::kActionUsagePassive);
00212     }
00213 
00214     if (!_enabled) {
00215         setEnabled(false);
00216     }
00217 
00218     Location *location = findParent<Location>();
00219     if (location) {
00220         location->registerCharacterItem(_characterIndex, this);
00221     }
00222 }
00223 
00224 void ItemVisual::saveLoad(ResourceSerializer *serializer) {
00225     Item::saveLoad(serializer);
00226 
00227     serializer->syncAsSint32LE(_currentAnimActivity);
00228 
00229     serializer->syncAsResourceReference(&_animHierarchy);
00230     if (serializer->isLoading() && _animHierarchy) {
00231         setAnimHierarchy(_animHierarchy);
00232     }
00233 
00234     serializer->syncAsResourceReference(&_actionAnim);
00235     if (serializer->isLoading()) {
00236         if (_actionAnim) {
00237             _actionAnim->applyToItem(this);
00238         } else {
00239             setAnimActivity(_currentAnimActivity);
00240         }
00241     }
00242 }
00243 
00244 void ItemVisual::saveLoadCurrent(ResourceSerializer *serializer) {
00245     Item::saveLoadCurrent(serializer);
00246 
00247     // Apply the animation once again now the data from the item templates has been loaded.
00248     // This ensures template level textures and models are applied when loading.
00249 
00250     serializer->syncAsSint32LE(_currentAnimActivity, 11);
00251     serializer->syncAsResourceReference(&_animHierarchy, 11);
00252     if (serializer->isLoading()) {
00253         if (_animHierarchy) {
00254             setAnimHierarchy(_animHierarchy);
00255         }
00256     }
00257 
00258     serializer->syncAsResourceReference(&_actionAnim, 11);
00259     if (serializer->isLoading()) {
00260         if (_actionAnim) {
00261             _actionAnim->applyToItem(this);
00262         } else {
00263             setAnimActivity(_currentAnimActivity);
00264         }
00265     }
00266 }
00267 
00268 void ItemVisual::setEnabled(bool enabled) {
00269     Item::setEnabled(enabled);
00270 
00271     if (enabled) {
00272         // If an action animation was selected while the item was disabled,
00273         // honor it. This is not what the original engine did, but seems
00274         // logical and fixes the Gribbler hurting animation in the forest.
00275         if (!_actionAnim) {
00276             _animHierarchy->selectItemAnim(this);
00277         }
00278     } else {
00279         resetActionAnim();
00280         _animHierarchy->unselectItemAnim(this);
00281     }
00282 }
00283 
00284 ItemVisual *ItemVisual::getSceneInstance() {
00285     return this;
00286 }
00287 
00288 int32 ItemVisual::getAnimActivity() const {
00289     return _currentAnimActivity;
00290 }
00291 
00292 void ItemVisual::setAnimActivity(int32 activity) {
00293     bool animNeedsUpdate = activity != _currentAnimActivity || _actionAnim != nullptr || _animHierarchy->getCurrentAnim() == nullptr;
00294 
00295     resetActionAnim();
00296 
00297     _currentAnimActivity = activity;
00298     if (animNeedsUpdate && _animHierarchy) {
00299         _animHierarchy->setItemAnim(this, activity);
00300     }
00301 }
00302 
00303 void ItemVisual::printData() {
00304     Item::printData();
00305 
00306     debug("clickable: %d", _clickable);
00307 }
00308 
00309 Anim *ItemVisual::getAnim() const {
00310     if (_actionAnim) {
00311         return _actionAnim;
00312     }
00313 
00314     return _animHierarchy->getCurrentAnim();
00315 }
00316 
00317 Anim *ItemVisual::getActionAnim() const {
00318     return _actionAnim;
00319 }
00320 
00321 void ItemVisual::setAnimHierarchy(AnimHierarchy *animHierarchy) {
00322     resetActionAnim();
00323 
00324     if (_animHierarchy) {
00325         _animHierarchy->unselectItemAnim(this);
00326     }
00327 
00328     _animHierarchy = animHierarchy;
00329 }
00330 
00331 Visual *ItemVisual::getVisual() {
00332     Anim *anim = getAnim();
00333 
00334     if (!anim) {
00335         return nullptr;
00336     }
00337 
00338     return anim->getVisual();
00339 }
00340 
00341 int ItemVisual::getHotspotIndexForPoint(const Common::Point &point) {
00342     Anim *anim = getAnim();
00343     if (anim) {
00344         return anim->getPointHotspotIndex(point);
00345     }
00346     return -1;
00347 }
00348 
00349 bool ItemVisual::canPerformAction(uint32 action, uint32 hotspotIndex) {
00350     PATTable *table = findChildWithOrder<PATTable>(hotspotIndex);
00351     return table && table->canPerformAction(action);
00352 }
00353 
00354 bool ItemVisual::doAction(uint32 action, uint32 hotspotIndex) {
00355     PATTable *table = findChildWithOrder<PATTable>(hotspotIndex);
00356     if (table && table->canPerformAction(action)) {
00357         return table->runScriptForAction(action);
00358     }
00359 
00360     return false;
00361 }
00362 
00363 void ItemVisual::playActionAnim(Anim *anim) {
00364     resetActionAnim();
00365 
00366     _animHierarchy->unselectItemAnim(this);
00367     _actionAnim = anim;
00368     anim->applyToItem(this);
00369     anim->playAsAction(this);
00370 }
00371 
00372 void ItemVisual::resetActionAnim() {
00373     if (_actionAnim) {
00374         _actionAnim->removeFromItem(this);
00375         _actionAnim = nullptr;
00376 
00377         // TODO: Add a condition to this?
00378         _animHierarchy->selectItemAnim(this);
00379         if (_subType == kItemModel) {
00380             _animHierarchy->setItemAnim(this, Anim::kActorActivityIdle);
00381         }
00382     }
00383 }
00384 
00385 void ItemVisual::setPosition2D(const Common::Point &position) {
00386     warning("ItemVisual::setPosition2D is not implemented for this item type: %d (%s)", _subType, _name.c_str());
00387 }
00388 
00389 Common::String ItemVisual::getHotspotTitle(uint32 hotspotIndex) {
00390     PATTable *table = findChildWithOrder<PATTable>(hotspotIndex);
00391     Common::String title;
00392     if (table) {
00393         title = table->getName();
00394     } else {
00395         title = getName();
00396     }
00397 
00398     if (title.equalsIgnoreCase("Default April PAT")) {
00399         return "April"; // The same hack exists in the original
00400     }
00401 
00402     return title;
00403 }
00404 
00405 Common::Array<Common::Point> ItemVisual::listExitPositionsImpl() {
00406     Common::Array<PATTable *> pattables = listChildrenRecursive<PATTable>();
00407     
00408     Common::Array<Common::Point> positions;
00409     Common::Point invalidPosition(-1, -1);
00410 
00411     for (uint i = 0; i < pattables.size(); ++i) {
00412         if (pattables[i]->getDefaultAction() != PATTable::kActionExit) continue;
00413 
00414         Anim *anim = getAnim();
00415         if (!anim) continue;
00416 
00417         Common::Point hotspot = anim->getHotspotPosition(i);
00418         if (hotspot != invalidPosition) {
00419             hotspot += _renderEntry->getPosition();
00420             positions.push_back(hotspot);
00421         }
00422     }
00423 
00424     return positions;
00425 }
00426 
00427 ItemTemplate::~ItemTemplate() {
00428 }
00429 
00430 ItemTemplate::ItemTemplate(Object *parent, byte subType, uint16 index, const Common::String &name) :
00431         Item(parent, subType, index, name),
00432         _meshIndex(-1),
00433         _textureNormalIndex(-1),
00434         _textureFaceIndex(-1),
00435         _animHierarchyIndex(-1),
00436         _referencedItem(nullptr),
00437         _instanciatedItem(nullptr) {
00438 }
00439 
00440 void ItemTemplate::onAllLoaded() {
00441     Item::onAllLoaded();
00442 
00443     BonesMesh *bonesMesh = findChild<BonesMesh>(false);
00444     if (bonesMesh) {
00445         _meshIndex = bonesMesh->getIndex();
00446     }
00447 
00448     TextureSet *textureNormal = findChildWithSubtype<TextureSet>(TextureSet::kTextureNormal, false);
00449     if (textureNormal) {
00450         _textureNormalIndex = textureNormal->getIndex();
00451     }
00452 
00453     TextureSet *textureFace = findChildWithSubtype<TextureSet>(TextureSet::kTextureFace, false);
00454     if (textureFace) {
00455         _textureFaceIndex = textureFace->getIndex();
00456     }
00457 }
00458 
00459 void ItemTemplate::saveLoadCurrent(ResourceSerializer *serializer) {
00460     Item::saveLoadCurrent(serializer);
00461 
00462     serializer->syncAsSint32LE(_meshIndex);
00463     serializer->syncAsSint32LE(_textureNormalIndex);
00464     serializer->syncAsSint32LE(_textureFaceIndex);
00465     serializer->syncAsSint32LE(_animHierarchyIndex);
00466 }
00467 
00468 void ItemTemplate::setInstanciatedItem(Item *instance) {
00469     _instanciatedItem = instance;
00470 }
00471 
00472 ItemVisual *ItemTemplate::getSceneInstance() {
00473     if (_instanciatedItem) {
00474         return _instanciatedItem->getSceneInstance();
00475     }
00476 
00477     return nullptr;
00478 }
00479 
00480 void ItemTemplate::setStockAnimHierachy(AnimHierarchy *animHierarchy) {
00481     Object *animHierarchyParent = animHierarchy->findParent<Object>();
00482 
00483     if (animHierarchyParent == this) {
00484         _animHierarchyIndex = animHierarchy->getIndex();
00485     } else {
00486         _animHierarchyIndex = -1;
00487     }
00488 }
00489 
00490 void ItemTemplate::setBonesMesh(int32 index) {
00491     _meshIndex = index;
00492 }
00493 
00494 void ItemTemplate::setTexture(int32 index, uint32 textureType) {
00495     if (textureType == TextureSet::kTextureNormal) {
00496         _textureNormalIndex = index;
00497     } else if (textureType == TextureSet::kTextureFace) {
00498         _textureFaceIndex = index;
00499     } else {
00500         error("Unknown texture type %d", textureType);
00501     }
00502 
00503     // Reset the animation to apply the changes
00504     ModelItem *sceneInstance = Resources::Object::cast<Resources::ModelItem>(getSceneInstance());
00505     sceneInstance->updateAnim();
00506 }
00507 
00508 void ItemTemplate::setAnimHierarchy(AnimHierarchy *animHierarchy) {
00509     setStockAnimHierachy(animHierarchy);
00510 
00511     if (_instanciatedItem) {
00512         _instanciatedItem->setAnimHierarchy(animHierarchy);
00513     }
00514 }
00515 
00516 GlobalItemTemplate::~GlobalItemTemplate() {
00517 }
00518 
00519 GlobalItemTemplate::GlobalItemTemplate(Object *parent, byte subType, uint16 index, const Common::String &name) :
00520         ItemTemplate(parent, subType, index, name) {
00521     _animHierarchyIndex = 0;
00522 }
00523 
00524 BonesMesh *GlobalItemTemplate::findBonesMesh() {
00525     if (_meshIndex == -1) {
00526         return nullptr;
00527     } else {
00528         BonesMesh *mesh = findChildWithIndex<BonesMesh>(_meshIndex);
00529         if (mesh && !StarkSettings->getBoolSetting(Settings::kHighModel)) {
00530             BonesMesh *lowMesh = findChildWithName<BonesMesh>(mesh->getName() + "_LO_RES");
00531             if (lowMesh) {
00532                 mesh = lowMesh;
00533             }
00534         }
00535         return mesh;
00536     }
00537 }
00538 
00539 TextureSet *GlobalItemTemplate::findTextureSet(uint32 textureType) {
00540     if (textureType == TextureSet::kTextureNormal) {
00541         if (_textureNormalIndex == -1) {
00542             return nullptr;
00543         } else {
00544             return findChildWithIndex<TextureSet>(_textureNormalIndex);
00545         }
00546     } else if (textureType == TextureSet::kTextureFace) {
00547         if (_textureFaceIndex == -1) {
00548             return nullptr;
00549         } else {
00550             return findChildWithIndex<TextureSet>(_textureFaceIndex);
00551         }
00552     } else {
00553         error("Unknown texture type %d", textureType);
00554     }
00555 }
00556 
00557 AnimHierarchy *GlobalItemTemplate::findStockAnimHierarchy() {
00558     if (_animHierarchyIndex == -1) {
00559         return nullptr;
00560     } else {
00561         return findChildWithIndex<AnimHierarchy>(_animHierarchyIndex);
00562     }
00563 }
00564 
00565 InventoryItem::~InventoryItem() {
00566 }
00567 
00568 InventoryItem::InventoryItem(Object *parent, byte subType, uint16 index, const Common::String &name) :
00569         ItemVisual(parent, subType, index, name) {
00570 }
00571 
00572 Gfx::RenderEntry *InventoryItem::getRenderEntry(const Common::Point &positionOffset) {
00573     if (_enabled) {
00574         setAnimActivity(Anim::kUIUsageInventory);
00575 
00576         Visual *visual = getVisual();
00577 
00578         _renderEntry->setVisual(visual);
00579         _renderEntry->setPosition(Common::Point());
00580     } else {
00581         _renderEntry->setVisual(nullptr);
00582     }
00583 
00584     return _renderEntry;
00585 }
00586 
00587 void InventoryItem::setEnabled(bool enabled) {
00588     ItemVisual::setEnabled(enabled);
00589 
00590     // Deselect the item in the inventory when removing it
00591     int16 selectedInventoryItem = StarkUserInterface->getSelectedInventoryItem();
00592     if (!enabled && selectedInventoryItem == getIndex()) {
00593         StarkUserInterface->selectInventoryItem(-1);
00594     }
00595 
00596     KnowledgeSet *inventory = StarkGlobal->getInventory();
00597     if (inventory) {
00598         if (enabled) {
00599             inventory->addItem(this);
00600         } else {
00601             inventory->removeItem(this);
00602         }
00603     }
00604 }
00605 
00606 Visual *InventoryItem::getActionVisual(bool active) const {
00607     if (active) {
00608         return _animHierarchy->getVisualForUsage(Anim::kActionUsageActive);
00609     } else {
00610         return _animHierarchy->getVisualForUsage(Anim::kActionUsagePassive);
00611     }
00612 }
00613 
00614 Visual *InventoryItem::getCursorVisual() const {
00615     Visual *visual = _animHierarchy->getVisualForUsage(Anim::kUIUsageUseCursorPassive);
00616 
00617     if (!visual) {
00618         visual = _animHierarchy->getVisualForUsage(Anim::kUIUsageUseCursorActive);
00619     }
00620 
00621     if (!visual) {
00622         visual = _animHierarchy->getVisualForUsage(Anim::kUIUsageInventory);
00623     }
00624 
00625     return visual;
00626 }
00627 
00628 
00629 LevelItemTemplate::~LevelItemTemplate() {
00630 }
00631 
00632 LevelItemTemplate::LevelItemTemplate(Object *parent, byte subType, uint16 index, const Common::String &name) :
00633         ItemTemplate(parent, subType, index, name) {
00634 }
00635 
00636 void LevelItemTemplate::readData(Formats::XRCReadStream *stream) {
00637     ItemTemplate::readData(stream);
00638 
00639     _reference = stream->readResourceReference();
00640 }
00641 
00642 void LevelItemTemplate::onAllLoaded() {
00643     ItemTemplate::onAllLoaded();
00644 
00645     _referencedItem = _reference.resolve<ItemTemplate>();
00646     if (_referencedItem) {
00647         _referencedItem->setInstanciatedItem(this);
00648     }
00649 }
00650 
00651 BonesMesh *LevelItemTemplate::findBonesMesh() {
00652     if (_meshIndex == -1) {
00653         return _referencedItem->findBonesMesh();
00654     } else {
00655         BonesMesh *mesh = findChildWithIndex<BonesMesh>(_meshIndex);
00656         if (mesh && !StarkSettings->getBoolSetting(Settings::kHighModel)) {
00657             BonesMesh *lowMesh = findChildWithName<BonesMesh>(mesh->getName() + "_LO_RES");
00658             if (lowMesh) {
00659                 mesh = lowMesh;
00660             }
00661         }
00662         return mesh;
00663     }
00664 }
00665 
00666 TextureSet *LevelItemTemplate::findTextureSet(uint32 textureType) {
00667     if (textureType == TextureSet::kTextureNormal) {
00668         if (_textureNormalIndex == -1) {
00669             return _referencedItem->findTextureSet(textureType);
00670         } else {
00671             return findChildWithIndex<TextureSet>(_textureNormalIndex);
00672         }
00673     } else if (textureType == TextureSet::kTextureFace) {
00674         if (_textureFaceIndex == -1) {
00675             if (_referencedItem) {
00676                 return _referencedItem->findTextureSet(textureType);
00677             } else {
00678                 return nullptr;
00679             }
00680         } else {
00681             return findChildWithIndex<TextureSet>(_textureFaceIndex);
00682         }
00683     } else {
00684         error("Unknown texture type %d", textureType);
00685     }
00686 }
00687 
00688 AnimHierarchy *LevelItemTemplate::findStockAnimHierarchy() {
00689     if (_animHierarchyIndex == -1 && !_referencedItem) {
00690         _animHierarchyIndex = 0; // Prefer referenced anim to local
00691     }
00692 
00693     if (_animHierarchyIndex == -1) {
00694         return _referencedItem->findStockAnimHierarchy();
00695     } else {
00696         return findChildWithIndex<AnimHierarchy>(_animHierarchyIndex);
00697     }
00698 }
00699 
00700 ItemTemplate *LevelItemTemplate::getItemTemplate() const {
00701     return _referencedItem;
00702 }
00703 
00704 void LevelItemTemplate::printData() {
00705     ItemTemplate::printData();
00706 
00707     debug("reference: %s", _reference.describe().c_str());
00708 }
00709 
00710 FloorPositionedItem::~FloorPositionedItem() {
00711 }
00712 
00713 FloorPositionedItem::FloorPositionedItem(Object *parent, byte subType, uint16 index, const Common::String &name) :
00714         ItemVisual(parent, subType, index, name),
00715         _direction3D(0.0),
00716         _floorFaceIndex(-1),
00717         _sortKeyOverride(false),
00718         _sortKeyOverridenValue(0.0) {
00719 }
00720 
00721 Math::Vector3d FloorPositionedItem::getPosition3D() const {
00722     return _position3D;
00723 }
00724 
00725 void FloorPositionedItem::setPosition3D(const Math::Vector3d &position) {
00726     _position3D = position;
00727 }
00728 
00729 int32 FloorPositionedItem::getFloorFaceIndex() const {
00730     return _floorFaceIndex;
00731 }
00732 
00733 void FloorPositionedItem::setFloorFaceIndex(int32 faceIndex) {
00734     _floorFaceIndex = faceIndex;
00735     _sortKeyOverride = false;
00736 }
00737 
00738 void FloorPositionedItem::placeOnBookmark(Bookmark *target) {
00739     Floor *floor = StarkGlobal->getCurrent()->getFloor();
00740 
00741     _position3D = target->getPosition();
00742 
00743     // Find the floor face index the item is on
00744     setFloorFaceIndex(floor->findFaceContainingPoint(_position3D));
00745 
00746     // Set the z coordinate using the floor height at that position
00747     if (_floorFaceIndex < 0) {
00748         warning("Item '%s' has been placed out of the floor field", getName().c_str());
00749     }
00750 }
00751 
00752 void FloorPositionedItem::placeDefaultPosition() {
00753     Floor *floor = StarkGlobal->getCurrent()->getFloor();
00754     FloorFace *face = floor->getFace(0);
00755 
00756     _position3D = face->getCenter();
00757 
00758     // Find the floor face index the item is on
00759     setFloorFaceIndex(0);
00760 
00761     // Set the z coordinate using the floor height at that position
00762     floor->computePointHeightInFace(_position3D, 0);
00763 }
00764 
00765 Math::Vector3d FloorPositionedItem::getDirectionVector() const {
00766     Math::Matrix3 rot;
00767     rot.buildAroundZ(-_direction3D);
00768 
00769     Math::Vector3d direction(1.0, 0.0, 0.0);
00770     rot.transformVector(&direction);
00771 
00772     return direction;
00773 }
00774 
00775 void FloorPositionedItem::setDirection(const Math::Angle &direction) {
00776     _direction3D = direction.getDegrees(0.0);
00777 }
00778 
00779 void FloorPositionedItem::overrideSortKey(float sortKey) {
00780     _sortKeyOverride = true;
00781     _sortKeyOverridenValue = sortKey;
00782 }
00783 
00784 float FloorPositionedItem::getSortKey() const {
00785     if (_sortKeyOverride) {
00786         return _sortKeyOverridenValue;
00787     }
00788 
00789     Floor *floor = StarkGlobal->getCurrent()->getFloor();
00790 
00791     if (_floorFaceIndex == -1) {
00792 //      warning("Undefined floor face index for item '%s'", getName().c_str());
00793         return floor->getDistanceFromCamera(0);
00794     }
00795 
00796     return floor->getDistanceFromCamera(_floorFaceIndex);
00797 }
00798 
00799 void FloorPositionedItem::saveLoad(ResourceSerializer *serializer) {
00800     ItemVisual::saveLoad(serializer);
00801     serializer->syncAsVector3d(_position3D);
00802     serializer->syncAsFloat(_direction3D);
00803     serializer->syncAsSint32LE(_floorFaceIndex);
00804 }
00805 
00806 FloorPositionedImageItem::~FloorPositionedImageItem() {
00807 }
00808 
00809 FloorPositionedImageItem::FloorPositionedImageItem(Object *parent, byte subType, uint16 index, const Common::String &name) :
00810         FloorPositionedItem(parent, subType, index, name) {
00811 }
00812 
00813 void FloorPositionedImageItem::readData(Formats::XRCReadStream *stream) {
00814     FloorPositionedItem::readData(stream);
00815 
00816     setFloorFaceIndex(stream->readSint32LE());
00817     _position = stream->readPoint();
00818 
00819     // WORKAROUND: Fix the position of various items being incorrect in the game datafiles
00820     Location *location = findParent<Location>();
00821     if (_name == "Shelves" && location && location->getName() == "April's Room") {
00822         _position = Common::Point(543, 77);
00823     } else if (_name == "Door" && location && location->getName() == "Hallway") {
00824         _position = Common::Point(328, 44);
00825     } else if (_name == "Bench" && location && location->getName() == "Outside Border House") {
00826         _position = Common::Point(707, 255);
00827     } else if (_name == "Printer" && location && location->getName() == "Archives") {
00828         _position = Common::Point(260, 119);
00829     } else if (_name == "Prop04_chair01" && location && location->getName() == "Inn Night") {
00830         _position = Common::Point(185, 324);
00831     } else if (_name == "Prop05_chair02" && location && location->getName() == "Inn Night") {
00832         _position = Common::Point(381, 329);
00833     } else if (_name == "Gargoyle" && location && location->getName() == "Below Floating Mountain") {
00834         _position = Common::Point(352, 0);
00835     } else if (_name == "Computer" && location && location->getName() == "Vanguard Laboratory") {
00836         _position = Common::Point(411, 141);
00837     }
00838 }
00839 
00840 Gfx::RenderEntry *FloorPositionedImageItem::getRenderEntry(const Common::Point &positionOffset) {
00841     if (_enabled) {
00842         Visual *visual = getVisual();
00843         _renderEntry->setVisual(visual);
00844 
00845         if (getAnim() && getAnim()->getSubType() == Anim::kAnimVideo) {
00846             // AnimVideos override the _position, but still need to move according to scroll-offsets
00847             _renderEntry->setPosition(positionOffset);
00848         } else {
00849             _renderEntry->setPosition(_position - positionOffset);
00850         }
00851         _renderEntry->setSortKey(getSortKey());
00852     } else {
00853         _renderEntry->setVisual(nullptr);
00854     }
00855 
00856     return _renderEntry;
00857 }
00858 
00859 Common::Array<Common::Point> FloorPositionedImageItem::listExitPositions() {
00860     return listExitPositionsImpl();
00861 }
00862 
00863 void FloorPositionedImageItem::setPosition2D(const Common::Point &position) {
00864     _position = position;
00865 }
00866 
00867 void FloorPositionedImageItem::printData() {
00868     FloorPositionedItem::printData();
00869 
00870     debug("floorFaceIndex: %d", _floorFaceIndex);
00871     debug("position: x %d, y %d", _position.x, _position.y);
00872 }
00873 
00874 ImageItem::~ImageItem() {
00875 }
00876 
00877 ImageItem::ImageItem(Object *parent, byte subType, uint16 index, const Common::String &name) :
00878         ItemVisual(parent, subType, index, name) {
00879 }
00880 
00881 void ImageItem::readData(Formats::XRCReadStream *stream) {
00882     ItemVisual::readData(stream);
00883 
00884     _position = stream->readPoint();
00885     _reference = stream->readResourceReference();
00886 }
00887 
00888 Gfx::RenderEntry *ImageItem::getRenderEntry(const Common::Point &positionOffset) {
00889     if (_enabled) {
00890         Visual *visual = getVisual();
00891         _renderEntry->setVisual(visual);
00892 
00893         if (getAnim() && getAnim()->getSubType() == Anim::kAnimVideo) {
00894             // AnimVideos override the _position, but still need to move according to scroll-offsets
00895             _renderEntry->setPosition(positionOffset);
00896         } else {
00897             _renderEntry->setPosition(_position - positionOffset);
00898         }
00899     } else {
00900         _renderEntry->setVisual(nullptr);
00901     }
00902 
00903     return _renderEntry;
00904 }
00905 
00906 void ImageItem::setPosition2D(const Common::Point &position) {
00907     _position = position;
00908 }
00909 
00910 void ImageItem::printData() {
00911     ItemVisual::printData();
00912 
00913     debug("reference: %s", _reference.describe().c_str());
00914     debug("position: x %d, y %d", _position.x, _position.y);
00915 }
00916 
00917 Common::Array<Common::Point> ImageItem::listExitPositions() {
00918     return listExitPositionsImpl();
00919 }
00920 
00921 ModelItem::~ModelItem() {
00922     delete _animHandler;
00923 }
00924 
00925 ModelItem::ModelItem(Object *parent, byte subType, uint16 index, const Common::String &name) :
00926         FloorPositionedItem(parent, subType, index, name),
00927         _meshIndex(-1),
00928         _textureNormalIndex(-1),
00929         _textureFaceIndex(-1),
00930         _referencedItem(nullptr),
00931         _animHandler(nullptr) {
00932 }
00933 
00934 void ModelItem::readData(Formats::XRCReadStream *stream) {
00935     FloorPositionedItem::readData(stream);
00936 
00937     _reference = stream->readResourceReference();
00938 }
00939 
00940 void ModelItem::onAllLoaded() {
00941     FloorPositionedItem::onAllLoaded();
00942 
00943     BonesMesh *bonesMesh = findChild<BonesMesh>(false);
00944     if (bonesMesh) {
00945         _meshIndex = bonesMesh->getIndex();
00946     }
00947 
00948     TextureSet *textureNormal = findChildWithSubtype<TextureSet>(TextureSet::kTextureNormal, false);
00949     if (textureNormal) {
00950         _textureNormalIndex = textureNormal->getIndex();
00951     }
00952 
00953     TextureSet *textureFace = findChildWithSubtype<TextureSet>(TextureSet::kTextureFace, false);
00954     if (textureFace) {
00955         _textureFaceIndex = textureFace->getIndex();
00956     }
00957 
00958     _referencedItem = _reference.resolve<ItemTemplate>();
00959     if (_referencedItem) {
00960         _referencedItem->setInstanciatedItem(this);
00961     }
00962 
00963     _animHandler = new AnimHandler();
00964 }
00965 
00966 void ModelItem::onEnterLocation() {
00967     FloorPositionedItem::onEnterLocation();
00968 
00969     if (_referencedItem) {
00970         _referencedItem->setInstanciatedItem(this);
00971     }
00972 
00973     if (_referencedItem) {
00974         _animHierarchy = _referencedItem->findStockAnimHierarchy();
00975     }
00976 
00977     setAnimActivity(Anim::kActorActivityIdle);
00978 }
00979 
00980 void ModelItem::onExitLocation() {
00981     FloorPositionedItem::onExitLocation();
00982 
00983     resetActionAnim();
00984     if (_animHierarchy) {
00985         _animHierarchy->unselectItemAnim(this);
00986     }
00987 }
00988 
00989 void ModelItem::setBonesMesh(int32 index) {
00990     _meshIndex = index;
00991 
00992     if (_meshIndex != -1) {
00993         updateAnim();
00994     }
00995 }
00996 
00997 BonesMesh *ModelItem::findBonesMesh() {
00998     // Prefer retrieving the mesh from the anim hierarchy
00999     BonesMesh *bonesMesh = _animHierarchy->findBonesMesh();
01000 
01001     // Otherwise, use a children mesh, or a referenced mesh
01002     if (!bonesMesh) {
01003         if (_meshIndex == -1) {
01004             bonesMesh = _referencedItem->findBonesMesh();
01005         } else {
01006             bonesMesh = findChildWithIndex<BonesMesh>(_meshIndex);
01007             if (bonesMesh && !StarkSettings->getBoolSetting(Settings::kHighModel)) {
01008                 BonesMesh *lowMesh = findChildWithName<BonesMesh>(bonesMesh->getName() + "_LO_RES");
01009                 if (lowMesh) {
01010                     bonesMesh = lowMesh;
01011                 }
01012             }
01013         }
01014     }
01015 
01016     return bonesMesh;
01017 }
01018 
01019 void ModelItem::setTexture(int32 index, uint32 textureType) {
01020     if (textureType == TextureSet::kTextureNormal) {
01021         _textureNormalIndex = index;
01022     } else if (textureType == TextureSet::kTextureFace) {
01023         _textureFaceIndex = index;
01024     } else {
01025         error("Unknown texture type %d", textureType);
01026     }
01027 }
01028 
01029 TextureSet *ModelItem::findTextureSet(uint32 textureType) {
01030     // Prefer retrieving the mesh from the anim hierarchy
01031     TextureSet *textureSet = _animHierarchy->findTextureSet(textureType);
01032 
01033     // Otherwise, use a children mesh, or a referenced mesh
01034     if (!textureSet) {
01035         if (textureType == TextureSet::kTextureNormal) {
01036             if (_textureNormalIndex == -1) {
01037                 textureSet = _referencedItem->findTextureSet(textureType);
01038             } else {
01039                 textureSet = findChildWithIndex<TextureSet>(_textureNormalIndex);
01040             }
01041         } else if (textureType == TextureSet::kTextureFace) {
01042             if (_textureFaceIndex == -1) {
01043                 if (_referencedItem) {
01044                     textureSet = _referencedItem->findTextureSet(textureType);
01045                 }
01046             } else {
01047                 textureSet = findChildWithIndex<TextureSet>(_textureFaceIndex);
01048             }
01049         } else {
01050             error("Unknown texture type %d", textureType);
01051         }
01052     }
01053 
01054     return textureSet;
01055 }
01056 
01057 void ModelItem::updateAnim() {
01058     Anim *anim = getAnim();
01059     if (anim && anim->getSubType() == Anim::kAnimSkeleton) {
01060         anim->removeFromItem(this);
01061         anim->applyToItem(this);
01062     }
01063 }
01064 
01065 Gfx::RenderEntry *ModelItem::getRenderEntry(const Common::Point &positionOffset) {
01066     if (_enabled) {
01067         Visual *visual = getVisual();
01068 
01069         if (!visual) {
01070             _animHierarchy->selectItemAnim(this);
01071             visual = getVisual();
01072         }
01073 
01074         _renderEntry->setVisual(visual);
01075         _renderEntry->setPosition3D(_position3D, _direction3D);
01076         _renderEntry->setSortKey(getSortKey());
01077     } else {
01078         _renderEntry->setVisual(nullptr);
01079     }
01080 
01081     return _renderEntry;
01082 }
01083 
01084 ItemTemplate *ModelItem::getItemTemplate() const {
01085     return _referencedItem;
01086 }
01087 
01088 Anim *ModelItem::getIdleActionAnim() const {
01089     if (_animHierarchy) {
01090         return _animHierarchy->getIdleActionAnim();
01091     }
01092 
01093     return nullptr;
01094 }
01095 
01096 void ModelItem::saveLoadCurrent(ResourceSerializer *serializer) {
01097     FloorPositionedItem::saveLoadCurrent(serializer);
01098 
01099     serializer->syncAsSint32LE(_meshIndex);
01100     serializer->syncAsSint32LE(_textureNormalIndex);
01101     serializer->syncAsSint32LE(_textureFaceIndex);
01102 }
01103 
01104 void ModelItem::printData() {
01105     FloorPositionedItem::printData();
01106 
01107     debug("reference: %s", _reference.describe().c_str());
01108 }
01109 
01110 void ModelItem::resetAnimationBlending() {
01111     _animHandler->resetBlending();
01112 }
01113 
01114 AnimHandler *ModelItem::getAnimHandler() const {
01115     return _animHandler;
01116 }
01117 
01118 void ItemTemplate::onEnterLocation() {
01119     Object::onEnterLocation();
01120 
01121     if (_referencedItem) {
01122         _referencedItem->setInstanciatedItem(this);
01123     }
01124 }
01125 } // End of namespace Resources
01126 } // End of namespace Stark


Generated on Sat May 18 2019 05:01:06 for ResidualVM by doxygen 1.7.1
curved edge   curved edge