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) {
00413             Common::Point hotspot = getAnim()->getHotspotPosition(i);
00414             if (hotspot != invalidPosition) {
00415                 hotspot += _renderEntry->getPosition();
00416                 positions.push_back(hotspot);
00417             }
00418         }
00419     }
00420 
00421     return positions;
00422 }
00423 
00424 ItemTemplate::~ItemTemplate() {
00425 }
00426 
00427 ItemTemplate::ItemTemplate(Object *parent, byte subType, uint16 index, const Common::String &name) :
00428         Item(parent, subType, index, name),
00429         _meshIndex(-1),
00430         _textureNormalIndex(-1),
00431         _textureFaceIndex(-1),
00432         _animHierarchyIndex(-1),
00433         _referencedItem(nullptr),
00434         _instanciatedItem(nullptr) {
00435 }
00436 
00437 void ItemTemplate::onAllLoaded() {
00438     Item::onAllLoaded();
00439 
00440     BonesMesh *bonesMesh = findChild<BonesMesh>(false);
00441     if (bonesMesh) {
00442         _meshIndex = bonesMesh->getIndex();
00443     }
00444 
00445     TextureSet *textureNormal = findChildWithSubtype<TextureSet>(TextureSet::kTextureNormal, false);
00446     if (textureNormal) {
00447         _textureNormalIndex = textureNormal->getIndex();
00448     }
00449 
00450     TextureSet *textureFace = findChildWithSubtype<TextureSet>(TextureSet::kTextureFace, false);
00451     if (textureFace) {
00452         _textureFaceIndex = textureFace->getIndex();
00453     }
00454 }
00455 
00456 void ItemTemplate::saveLoadCurrent(ResourceSerializer *serializer) {
00457     Item::saveLoadCurrent(serializer);
00458 
00459     serializer->syncAsSint32LE(_meshIndex);
00460     serializer->syncAsSint32LE(_textureNormalIndex);
00461     serializer->syncAsSint32LE(_textureFaceIndex);
00462     serializer->syncAsSint32LE(_animHierarchyIndex);
00463 }
00464 
00465 void ItemTemplate::setInstanciatedItem(Item *instance) {
00466     _instanciatedItem = instance;
00467 }
00468 
00469 ItemVisual *ItemTemplate::getSceneInstance() {
00470     if (_instanciatedItem) {
00471         return _instanciatedItem->getSceneInstance();
00472     }
00473 
00474     return nullptr;
00475 }
00476 
00477 void ItemTemplate::setStockAnimHierachy(AnimHierarchy *animHierarchy) {
00478     Object *animHierarchyParent = animHierarchy->findParent<Object>();
00479 
00480     if (animHierarchyParent == this) {
00481         _animHierarchyIndex = animHierarchy->getIndex();
00482     } else {
00483         _animHierarchyIndex = -1;
00484     }
00485 }
00486 
00487 void ItemTemplate::setBonesMesh(int32 index) {
00488     _meshIndex = index;
00489 }
00490 
00491 void ItemTemplate::setTexture(int32 index, uint32 textureType) {
00492     if (textureType == TextureSet::kTextureNormal) {
00493         _textureNormalIndex = index;
00494     } else if (textureType == TextureSet::kTextureFace) {
00495         _textureFaceIndex = index;
00496     } else {
00497         error("Unknown texture type %d", textureType);
00498     }
00499 
00500     // Reset the animation to apply the changes
00501     ModelItem *sceneInstance = Resources::Object::cast<Resources::ModelItem>(getSceneInstance());
00502     sceneInstance->updateAnim();
00503 }
00504 
00505 void ItemTemplate::setAnimHierarchy(AnimHierarchy *animHierarchy) {
00506     setStockAnimHierachy(animHierarchy);
00507 
00508     if (_instanciatedItem) {
00509         _instanciatedItem->setAnimHierarchy(animHierarchy);
00510     }
00511 }
00512 
00513 GlobalItemTemplate::~GlobalItemTemplate() {
00514 }
00515 
00516 GlobalItemTemplate::GlobalItemTemplate(Object *parent, byte subType, uint16 index, const Common::String &name) :
00517         ItemTemplate(parent, subType, index, name) {
00518     _animHierarchyIndex = 0;
00519 }
00520 
00521 BonesMesh *GlobalItemTemplate::findBonesMesh() {
00522     if (_meshIndex == -1) {
00523         return nullptr;
00524     } else {
00525         BonesMesh *mesh = findChildWithIndex<BonesMesh>(_meshIndex);
00526         if (mesh && !StarkSettings->getBoolSetting(Settings::kHighModel)) {
00527             BonesMesh *lowMesh = findChildWithName<BonesMesh>(mesh->getName() + "_LO_RES");
00528             if (lowMesh) {
00529                 mesh = lowMesh;
00530             }
00531         }
00532         return mesh;
00533     }
00534 }
00535 
00536 TextureSet *GlobalItemTemplate::findTextureSet(uint32 textureType) {
00537     if (textureType == TextureSet::kTextureNormal) {
00538         if (_textureNormalIndex == -1) {
00539             return nullptr;
00540         } else {
00541             return findChildWithIndex<TextureSet>(_textureNormalIndex);
00542         }
00543     } else if (textureType == TextureSet::kTextureFace) {
00544         if (_textureFaceIndex == -1) {
00545             return nullptr;
00546         } else {
00547             return findChildWithIndex<TextureSet>(_textureFaceIndex);
00548         }
00549     } else {
00550         error("Unknown texture type %d", textureType);
00551     }
00552 }
00553 
00554 AnimHierarchy *GlobalItemTemplate::findStockAnimHierarchy() {
00555     if (_animHierarchyIndex == -1) {
00556         return nullptr;
00557     } else {
00558         return findChildWithIndex<AnimHierarchy>(_animHierarchyIndex);
00559     }
00560 }
00561 
00562 InventoryItem::~InventoryItem() {
00563 }
00564 
00565 InventoryItem::InventoryItem(Object *parent, byte subType, uint16 index, const Common::String &name) :
00566         ItemVisual(parent, subType, index, name) {
00567 }
00568 
00569 Gfx::RenderEntry *InventoryItem::getRenderEntry(const Common::Point &positionOffset) {
00570     if (_enabled) {
00571         setAnimActivity(Anim::kUIUsageInventory);
00572 
00573         Visual *visual = getVisual();
00574 
00575         _renderEntry->setVisual(visual);
00576         _renderEntry->setPosition(Common::Point());
00577     } else {
00578         _renderEntry->setVisual(nullptr);
00579     }
00580 
00581     return _renderEntry;
00582 }
00583 
00584 void InventoryItem::setEnabled(bool enabled) {
00585     ItemVisual::setEnabled(enabled);
00586 
00587     // Deselect the item in the inventory when removing it
00588     int16 selectedInventoryItem = StarkUserInterface->getSelectedInventoryItem();
00589     if (!enabled && selectedInventoryItem == getIndex()) {
00590         StarkUserInterface->selectInventoryItem(-1);
00591     }
00592 
00593     KnowledgeSet *inventory = StarkGlobal->getInventory();
00594     if (inventory) {
00595         if (enabled) {
00596             inventory->addItem(this);
00597         } else {
00598             inventory->removeItem(this);
00599         }
00600     }
00601 }
00602 
00603 Visual *InventoryItem::getActionVisual(bool active) const {
00604     if (active) {
00605         return _animHierarchy->getVisualForUsage(Anim::kActionUsageActive);
00606     } else {
00607         return _animHierarchy->getVisualForUsage(Anim::kActionUsagePassive);
00608     }
00609 }
00610 
00611 Visual *InventoryItem::getCursorVisual() const {
00612     Visual *visual = _animHierarchy->getVisualForUsage(Anim::kUIUsageUseCursorPassive);
00613 
00614     if (!visual) {
00615         visual = _animHierarchy->getVisualForUsage(Anim::kUIUsageUseCursorActive);
00616     }
00617 
00618     if (!visual) {
00619         visual = _animHierarchy->getVisualForUsage(Anim::kUIUsageInventory);
00620     }
00621 
00622     return visual;
00623 }
00624 
00625 
00626 LevelItemTemplate::~LevelItemTemplate() {
00627 }
00628 
00629 LevelItemTemplate::LevelItemTemplate(Object *parent, byte subType, uint16 index, const Common::String &name) :
00630         ItemTemplate(parent, subType, index, name) {
00631 }
00632 
00633 void LevelItemTemplate::readData(Formats::XRCReadStream *stream) {
00634     ItemTemplate::readData(stream);
00635 
00636     _reference = stream->readResourceReference();
00637 }
00638 
00639 void LevelItemTemplate::onAllLoaded() {
00640     ItemTemplate::onAllLoaded();
00641 
00642     _referencedItem = _reference.resolve<ItemTemplate>();
00643     if (_referencedItem) {
00644         _referencedItem->setInstanciatedItem(this);
00645     }
00646 }
00647 
00648 BonesMesh *LevelItemTemplate::findBonesMesh() {
00649     if (_meshIndex == -1) {
00650         return _referencedItem->findBonesMesh();
00651     } else {
00652         BonesMesh *mesh = findChildWithIndex<BonesMesh>(_meshIndex);
00653         if (mesh && !StarkSettings->getBoolSetting(Settings::kHighModel)) {
00654             BonesMesh *lowMesh = findChildWithName<BonesMesh>(mesh->getName() + "_LO_RES");
00655             if (lowMesh) {
00656                 mesh = lowMesh;
00657             }
00658         }
00659         return mesh;
00660     }
00661 }
00662 
00663 TextureSet *LevelItemTemplate::findTextureSet(uint32 textureType) {
00664     if (textureType == TextureSet::kTextureNormal) {
00665         if (_textureNormalIndex == -1) {
00666             return _referencedItem->findTextureSet(textureType);
00667         } else {
00668             return findChildWithIndex<TextureSet>(_textureNormalIndex);
00669         }
00670     } else if (textureType == TextureSet::kTextureFace) {
00671         if (_textureFaceIndex == -1) {
00672             if (_referencedItem) {
00673                 return _referencedItem->findTextureSet(textureType);
00674             } else {
00675                 return nullptr;
00676             }
00677         } else {
00678             return findChildWithIndex<TextureSet>(_textureFaceIndex);
00679         }
00680     } else {
00681         error("Unknown texture type %d", textureType);
00682     }
00683 }
00684 
00685 AnimHierarchy *LevelItemTemplate::findStockAnimHierarchy() {
00686     if (_animHierarchyIndex == -1 && !_referencedItem) {
00687         _animHierarchyIndex = 0; // Prefer referenced anim to local
00688     }
00689 
00690     if (_animHierarchyIndex == -1) {
00691         return _referencedItem->findStockAnimHierarchy();
00692     } else {
00693         return findChildWithIndex<AnimHierarchy>(_animHierarchyIndex);
00694     }
00695 }
00696 
00697 ItemTemplate *LevelItemTemplate::getItemTemplate() const {
00698     return _referencedItem;
00699 }
00700 
00701 void LevelItemTemplate::printData() {
00702     ItemTemplate::printData();
00703 
00704     debug("reference: %s", _reference.describe().c_str());
00705 }
00706 
00707 FloorPositionedItem::~FloorPositionedItem() {
00708 }
00709 
00710 FloorPositionedItem::FloorPositionedItem(Object *parent, byte subType, uint16 index, const Common::String &name) :
00711         ItemVisual(parent, subType, index, name),
00712         _direction3D(0.0),
00713         _floorFaceIndex(-1),
00714         _sortKeyOverride(false),
00715         _sortKeyOverridenValue(0.0) {
00716 }
00717 
00718 Math::Vector3d FloorPositionedItem::getPosition3D() const {
00719     return _position3D;
00720 }
00721 
00722 void FloorPositionedItem::setPosition3D(const Math::Vector3d &position) {
00723     _position3D = position;
00724 }
00725 
00726 int32 FloorPositionedItem::getFloorFaceIndex() const {
00727     return _floorFaceIndex;
00728 }
00729 
00730 void FloorPositionedItem::setFloorFaceIndex(int32 faceIndex) {
00731     _floorFaceIndex = faceIndex;
00732     _sortKeyOverride = false;
00733 }
00734 
00735 void FloorPositionedItem::placeOnBookmark(Bookmark *target) {
00736     Floor *floor = StarkGlobal->getCurrent()->getFloor();
00737 
00738     _position3D = target->getPosition();
00739 
00740     // Find the floor face index the item is on
00741     setFloorFaceIndex(floor->findFaceContainingPoint(_position3D));
00742 
00743     // Set the z coordinate using the floor height at that position
00744     if (_floorFaceIndex < 0) {
00745         warning("Item '%s' has been placed out of the floor field", getName().c_str());
00746     }
00747 }
00748 
00749 void FloorPositionedItem::placeDefaultPosition() {
00750     Floor *floor = StarkGlobal->getCurrent()->getFloor();
00751     FloorFace *face = floor->getFace(0);
00752 
00753     _position3D = face->getCenter();
00754 
00755     // Find the floor face index the item is on
00756     setFloorFaceIndex(0);
00757 
00758     // Set the z coordinate using the floor height at that position
00759     floor->computePointHeightInFace(_position3D, 0);
00760 }
00761 
00762 Math::Vector3d FloorPositionedItem::getDirectionVector() const {
00763     Math::Matrix3 rot;
00764     rot.buildAroundZ(-_direction3D);
00765 
00766     Math::Vector3d direction(1.0, 0.0, 0.0);
00767     rot.transformVector(&direction);
00768 
00769     return direction;
00770 }
00771 
00772 void FloorPositionedItem::setDirection(const Math::Angle &direction) {
00773     _direction3D = direction.getDegrees(0.0);
00774 }
00775 
00776 void FloorPositionedItem::overrideSortKey(float sortKey) {
00777     _sortKeyOverride = true;
00778     _sortKeyOverridenValue = sortKey;
00779 }
00780 
00781 float FloorPositionedItem::getSortKey() const {
00782     if (_sortKeyOverride) {
00783         return _sortKeyOverridenValue;
00784     }
00785 
00786     Floor *floor = StarkGlobal->getCurrent()->getFloor();
00787 
00788     if (_floorFaceIndex == -1) {
00789 //      warning("Undefined floor face index for item '%s'", getName().c_str());
00790         return floor->getDistanceFromCamera(0);
00791     }
00792 
00793     return floor->getDistanceFromCamera(_floorFaceIndex);
00794 }
00795 
00796 void FloorPositionedItem::saveLoad(ResourceSerializer *serializer) {
00797     ItemVisual::saveLoad(serializer);
00798     serializer->syncAsVector3d(_position3D);
00799     serializer->syncAsFloat(_direction3D);
00800     serializer->syncAsSint32LE(_floorFaceIndex);
00801 }
00802 
00803 FloorPositionedImageItem::~FloorPositionedImageItem() {
00804 }
00805 
00806 FloorPositionedImageItem::FloorPositionedImageItem(Object *parent, byte subType, uint16 index, const Common::String &name) :
00807         FloorPositionedItem(parent, subType, index, name) {
00808 }
00809 
00810 void FloorPositionedImageItem::readData(Formats::XRCReadStream *stream) {
00811     FloorPositionedItem::readData(stream);
00812 
00813     setFloorFaceIndex(stream->readSint32LE());
00814     _position = stream->readPoint();
00815 
00816     // WORKAROUND: For the shelves having an incorrect position in the game datafiles
00817     Location *location = findParent<Location>();
00818     if (_name == "Shelves" && location && location->getName() == "April's Room") {
00819         _position = Common::Point(543, 77);
00820     }
00821 }
00822 
00823 Gfx::RenderEntry *FloorPositionedImageItem::getRenderEntry(const Common::Point &positionOffset) {
00824     if (_enabled) {
00825         Visual *visual = getVisual();
00826         _renderEntry->setVisual(visual);
00827 
00828         if (getAnim() && getAnim()->getSubType() == Anim::kAnimVideo) {
00829             // AnimVideos override the _position, but still need to move according to scroll-offsets
00830             _renderEntry->setPosition(positionOffset);
00831         } else {
00832             _renderEntry->setPosition(_position - positionOffset);
00833         }
00834         _renderEntry->setSortKey(getSortKey());
00835     } else {
00836         _renderEntry->setVisual(nullptr);
00837     }
00838 
00839     return _renderEntry;
00840 }
00841 
00842 Common::Array<Common::Point> FloorPositionedImageItem::listExitPositions() {
00843     return listExitPositionsImpl();
00844 }
00845 
00846 void FloorPositionedImageItem::setPosition2D(const Common::Point &position) {
00847     _position = position;
00848 }
00849 
00850 void FloorPositionedImageItem::printData() {
00851     FloorPositionedItem::printData();
00852 
00853     debug("floorFaceIndex: %d", _floorFaceIndex);
00854     debug("position: x %d, y %d", _position.x, _position.y);
00855 }
00856 
00857 ImageItem::~ImageItem() {
00858 }
00859 
00860 ImageItem::ImageItem(Object *parent, byte subType, uint16 index, const Common::String &name) :
00861         ItemVisual(parent, subType, index, name) {
00862 }
00863 
00864 void ImageItem::readData(Formats::XRCReadStream *stream) {
00865     ItemVisual::readData(stream);
00866 
00867     _position = stream->readPoint();
00868     _reference = stream->readResourceReference();
00869 }
00870 
00871 Gfx::RenderEntry *ImageItem::getRenderEntry(const Common::Point &positionOffset) {
00872     if (_enabled) {
00873         Visual *visual = getVisual();
00874         _renderEntry->setVisual(visual);
00875 
00876         if (getAnim() && getAnim()->getSubType() == Anim::kAnimVideo) {
00877             // AnimVideos override the _position, but still need to move according to scroll-offsets
00878             _renderEntry->setPosition(positionOffset);
00879         } else {
00880             _renderEntry->setPosition(_position - positionOffset);
00881         }
00882     } else {
00883         _renderEntry->setVisual(nullptr);
00884     }
00885 
00886     return _renderEntry;
00887 }
00888 
00889 void ImageItem::setPosition2D(const Common::Point &position) {
00890     _position = position;
00891 }
00892 
00893 void ImageItem::printData() {
00894     ItemVisual::printData();
00895 
00896     debug("reference: %s", _reference.describe().c_str());
00897     debug("position: x %d, y %d", _position.x, _position.y);
00898 }
00899 
00900 Common::Array<Common::Point> ImageItem::listExitPositions() {
00901     return listExitPositionsImpl();
00902 }
00903 
00904 ModelItem::~ModelItem() {
00905     delete _animHandler;
00906 }
00907 
00908 ModelItem::ModelItem(Object *parent, byte subType, uint16 index, const Common::String &name) :
00909         FloorPositionedItem(parent, subType, index, name),
00910         _meshIndex(-1),
00911         _textureNormalIndex(-1),
00912         _textureFaceIndex(-1),
00913         _referencedItem(nullptr),
00914         _animHandler(nullptr) {
00915 }
00916 
00917 void ModelItem::readData(Formats::XRCReadStream *stream) {
00918     FloorPositionedItem::readData(stream);
00919 
00920     _reference = stream->readResourceReference();
00921 }
00922 
00923 void ModelItem::onAllLoaded() {
00924     FloorPositionedItem::onAllLoaded();
00925 
00926     BonesMesh *bonesMesh = findChild<BonesMesh>(false);
00927     if (bonesMesh) {
00928         _meshIndex = bonesMesh->getIndex();
00929     }
00930 
00931     TextureSet *textureNormal = findChildWithSubtype<TextureSet>(TextureSet::kTextureNormal, false);
00932     if (textureNormal) {
00933         _textureNormalIndex = textureNormal->getIndex();
00934     }
00935 
00936     TextureSet *textureFace = findChildWithSubtype<TextureSet>(TextureSet::kTextureFace, false);
00937     if (textureFace) {
00938         _textureFaceIndex = textureFace->getIndex();
00939     }
00940 
00941     _referencedItem = _reference.resolve<ItemTemplate>();
00942     if (_referencedItem) {
00943         _referencedItem->setInstanciatedItem(this);
00944     }
00945 
00946     _animHandler = new AnimHandler();
00947 }
00948 
00949 void ModelItem::onEnterLocation() {
00950     FloorPositionedItem::onEnterLocation();
00951 
00952     if (_referencedItem) {
00953         _referencedItem->setInstanciatedItem(this);
00954     }
00955 
00956     if (_referencedItem) {
00957         _animHierarchy = _referencedItem->findStockAnimHierarchy();
00958     }
00959 
00960     setAnimActivity(Anim::kActorActivityIdle);
00961 }
00962 
00963 void ModelItem::onExitLocation() {
00964     FloorPositionedItem::onExitLocation();
00965 
00966     resetActionAnim();
00967     if (_animHierarchy) {
00968         _animHierarchy->unselectItemAnim(this);
00969     }
00970 }
00971 
00972 void ModelItem::setBonesMesh(int32 index) {
00973     _meshIndex = index;
00974 
00975     if (_meshIndex != -1) {
00976         updateAnim();
00977     }
00978 }
00979 
00980 BonesMesh *ModelItem::findBonesMesh() {
00981     // Prefer retrieving the mesh from the anim hierarchy
00982     BonesMesh *bonesMesh = _animHierarchy->findBonesMesh();
00983 
00984     // Otherwise, use a children mesh, or a referenced mesh
00985     if (!bonesMesh) {
00986         if (_meshIndex == -1) {
00987             bonesMesh = _referencedItem->findBonesMesh();
00988         } else {
00989             bonesMesh = findChildWithIndex<BonesMesh>(_meshIndex);
00990             if (bonesMesh && !StarkSettings->getBoolSetting(Settings::kHighModel)) {
00991                 BonesMesh *lowMesh = findChildWithName<BonesMesh>(bonesMesh->getName() + "_LO_RES");
00992                 if (lowMesh) {
00993                     bonesMesh = lowMesh;
00994                 }
00995             }
00996         }
00997     }
00998 
00999     return bonesMesh;
01000 }
01001 
01002 void ModelItem::setTexture(int32 index, uint32 textureType) {
01003     if (textureType == TextureSet::kTextureNormal) {
01004         _textureNormalIndex = index;
01005     } else if (textureType == TextureSet::kTextureFace) {
01006         _textureFaceIndex = index;
01007     } else {
01008         error("Unknown texture type %d", textureType);
01009     }
01010 }
01011 
01012 TextureSet *ModelItem::findTextureSet(uint32 textureType) {
01013     // Prefer retrieving the mesh from the anim hierarchy
01014     TextureSet *textureSet = _animHierarchy->findTextureSet(textureType);
01015 
01016     // Otherwise, use a children mesh, or a referenced mesh
01017     if (!textureSet) {
01018         if (textureType == TextureSet::kTextureNormal) {
01019             if (_textureNormalIndex == -1) {
01020                 textureSet = _referencedItem->findTextureSet(textureType);
01021             } else {
01022                 textureSet = findChildWithIndex<TextureSet>(_textureNormalIndex);
01023             }
01024         } else if (textureType == TextureSet::kTextureFace) {
01025             if (_textureFaceIndex == -1) {
01026                 if (_referencedItem) {
01027                     textureSet = _referencedItem->findTextureSet(textureType);
01028                 }
01029             } else {
01030                 textureSet = findChildWithIndex<TextureSet>(_textureFaceIndex);
01031             }
01032         } else {
01033             error("Unknown texture type %d", textureType);
01034         }
01035     }
01036 
01037     return textureSet;
01038 }
01039 
01040 void ModelItem::updateAnim() {
01041     Anim *anim = getAnim();
01042     if (anim && anim->getSubType() == Anim::kAnimSkeleton) {
01043         anim->removeFromItem(this);
01044         anim->applyToItem(this);
01045     }
01046 }
01047 
01048 Gfx::RenderEntry *ModelItem::getRenderEntry(const Common::Point &positionOffset) {
01049     if (_enabled) {
01050         Visual *visual = getVisual();
01051 
01052         if (!visual) {
01053             _animHierarchy->selectItemAnim(this);
01054             visual = getVisual();
01055         }
01056 
01057         _renderEntry->setVisual(visual);
01058         _renderEntry->setPosition3D(_position3D, _direction3D);
01059         _renderEntry->setSortKey(getSortKey());
01060     } else {
01061         _renderEntry->setVisual(nullptr);
01062     }
01063 
01064     return _renderEntry;
01065 }
01066 
01067 ItemTemplate *ModelItem::getItemTemplate() const {
01068     return _referencedItem;
01069 }
01070 
01071 Anim *ModelItem::getIdleActionAnim() const {
01072     if (_animHierarchy) {
01073         return _animHierarchy->getIdleActionAnim();
01074     }
01075 
01076     return nullptr;
01077 }
01078 
01079 void ModelItem::saveLoadCurrent(ResourceSerializer *serializer) {
01080     FloorPositionedItem::saveLoadCurrent(serializer);
01081 
01082     serializer->syncAsSint32LE(_meshIndex);
01083     serializer->syncAsSint32LE(_textureNormalIndex);
01084     serializer->syncAsSint32LE(_textureFaceIndex);
01085 }
01086 
01087 void ModelItem::printData() {
01088     FloorPositionedItem::printData();
01089 
01090     debug("reference: %s", _reference.describe().c_str());
01091 }
01092 
01093 void ModelItem::resetAnimationBlending() {
01094     _animHandler->resetBlending();
01095 }
01096 
01097 AnimHandler *ModelItem::getAnimHandler() const {
01098     return _animHandler;
01099 }
01100 
01101 void ItemTemplate::onEnterLocation() {
01102     Object::onEnterLocation();
01103 
01104     if (_referencedItem) {
01105         _referencedItem->setInstanciatedItem(this);
01106     }
01107 }
01108 } // End of namespace Resources
01109 } // End of namespace Stark


Generated on Sat Mar 16 2019 05:01:39 for ResidualVM by doxygen 1.7.1
curved edge   curved edge