diff --git a/.gitignore b/.gitignore index e37fc7721..1d6b337a4 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ Doxygen .settings .directory .idea +cmake-build-* files/windows/*.aps cmake-build-* ## qt-creator diff --git a/.travis.yml b/.travis.yml index 52793ed65..2a72f9284 100644 --- a/.travis.yml +++ b/.travis.yml @@ -43,7 +43,7 @@ addons: name: "TES3MP/openmw-tes3mp" description: "" notification_email: stas5978@gmail.com - build_command_prepend: "cmake . -DBUILD_UNITTESTS=FALSE" + build_command_prepend: "cmake . -DBUILD_UNITTESTS=FALSE -DBUILD_OPENCS=FALSE -DBUILD_BSATOOL=FALSE -DBUILD_ESMTOOL=FALSE -DBUILD_MWINIIMPORTER=FALSE -DBUILD_LAUNCHER=FALSE" build_command: "make -j3" branch_pattern: coverity_scan matrix: diff --git a/AUTHORS.md b/AUTHORS.md index 02eb30da0..839a04e42 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -88,6 +88,7 @@ Programmers lazydev Leon Krieg (lkrieg) Leon Saunders (emoose) + Łukasz Gołębiewski (lukago) logzero lohikaarme Lukasz Gromanowski (lgro) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 14998a3c6..a7f30d7ed 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -750,19 +750,4 @@ if [ -z $VERBOSE ]; then fi fi -if [ -z $CI ]; then - echo "- Copying Runtime Resources/Config Files" - echo " gamecontrollerdb.txt" - cp gamecontrollerdb.txt $BUILD_CONFIG/gamecontrollerdb.txt - echo " openmw.cfg" - cp openmw.cfg.install $BUILD_CONFIG/openmw.cfg - echo " openmw-cs.cfg" - cp openmw-cs.cfg $BUILD_CONFIG/openmw-cs.cfg - echo " settings-default.cfg" - cp settings-default.cfg $BUILD_CONFIG/settings-default.cfg - echo " resources/" - cp -r resources $BUILD_CONFIG/resources - echo -fi - exit $RET diff --git a/CMakeLists.txt b/CMakeLists.txt index 1dff0f58f..9fe0e44c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -327,33 +327,33 @@ endif (APPLE) # Other files -configure_file(${OpenMW_SOURCE_DIR}/files/tes3mp/tes3mp-client-default.cfg - "${OpenMW_BINARY_DIR}/tes3mp-client-default.cfg") +configure_resource_file(${OpenMW_SOURCE_DIR}/files/tes3mp/tes3mp-client-default.cfg + "${OpenMW_BINARY_DIR}" "tes3mp-client-default.cfg") -configure_file(${OpenMW_SOURCE_DIR}/files/tes3mp/tes3mp-server-default.cfg - "${OpenMW_BINARY_DIR}/tes3mp-server-default.cfg") +configure_resource_file(${OpenMW_SOURCE_DIR}/files/tes3mp/tes3mp-server-default.cfg + "${OpenMW_BINARY_DIR}" "tes3mp-server-default.cfg") -configure_file(${OpenMW_SOURCE_DIR}/files/settings-default.cfg - "${OpenMW_BINARY_DIR}/settings-default.cfg") +configure_resource_file(${OpenMW_SOURCE_DIR}/files/settings-default.cfg + "${OpenMW_BINARY_DIR}" "settings-default.cfg") if (NOT APPLE) - configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg.local - "${OpenMW_BINARY_DIR}/openmw.cfg") - configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg - "${OpenMW_BINARY_DIR}/openmw.cfg.install") + configure_resource_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg.local + "${OpenMW_BINARY_DIR}" "openmw.cfg") + configure_resource_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg + "${OpenMW_BINARY_DIR}" "openmw.cfg.install") else () configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg "${OpenMW_BINARY_DIR}/openmw.cfg") endif () -configure_file(${OpenMW_SOURCE_DIR}/files/openmw-cs.cfg - "${OpenMW_BINARY_DIR}/openmw-cs.cfg") +configure_resource_file(${OpenMW_SOURCE_DIR}/files/openmw-cs.cfg + "${OpenMW_BINARY_DIR}" "openmw-cs.cfg") -configure_file(${OpenMW_SOURCE_DIR}/files/opencs/defaultfilters - "${OpenMW_BINARY_DIR}/resources/defaultfilters" COPYONLY) +configure_resource_file(${OpenMW_SOURCE_DIR}/files/opencs/defaultfilters + "${OpenMW_BINARY_DIR}" "resources/defaultfilters" COPYONLY) -configure_file(${OpenMW_SOURCE_DIR}/files/gamecontrollerdb.txt - "${OpenMW_BINARY_DIR}/gamecontrollerdb.txt") +configure_resource_file(${OpenMW_SOURCE_DIR}/files/gamecontrollerdb.txt + "${OpenMW_BINARY_DIR}" "gamecontrollerdb.txt") if (NOT WIN32 AND NOT APPLE) configure_file(${OpenMW_SOURCE_DIR}/files/openmw.desktop diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp index 97a0e8b37..5e362e9b5 100644 --- a/apps/openmw/mwgui/dialogue.hpp +++ b/apps/openmw/mwgui/dialogue.hpp @@ -155,8 +155,6 @@ namespace MWGui void restock(); void deleteLater(); - bool mEnabled; - bool mIsCompanion; std::list mKeywords; diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 3cd800989..d5e315c35 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -120,7 +120,6 @@ namespace MWGui , mSpellStatus(NULL) , mEffectBox(NULL) , mMinimap(NULL) - , mCompass(NULL) , mCrosshair(NULL) , mCellNameBox(NULL) , mDrowningFrame(NULL) diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index 3542f3ebf..73428c034 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -69,7 +69,6 @@ namespace MWGui MyGUI::Widget *mEffectBox, *mMinimapBox; MyGUI::Button* mMinimapButton; MyGUI::ScrollView* mMinimap; - MyGUI::ImageBox* mCompass; MyGUI::ImageBox* mCrosshair; MyGUI::TextBox* mCellNameBox; MyGUI::TextBox* mWeaponSpellBox; diff --git a/apps/openmw/mwgui/jailscreen.cpp b/apps/openmw/mwgui/jailscreen.cpp index a994c8840..7267912ae 100644 --- a/apps/openmw/mwgui/jailscreen.cpp +++ b/apps/openmw/mwgui/jailscreen.cpp @@ -86,7 +86,10 @@ namespace MWGui Prevent teleportation to jail if specified */ if (!mwmp::Main::get().getLocalPlayer()->ignoreJailTeleportation) + { MWBase::Environment::get().getWorld()->teleportToClosestMarker(player, "prisonmarker"); + MWBase::Environment::get().getWindowManager()->fadeScreenOut(0.f); // override fade-in caused by cell transition + } /* End of tes3mp change (minor) */ diff --git a/apps/openmw/mwgui/savegamedialog.cpp b/apps/openmw/mwgui/savegamedialog.cpp index 6a290bef1..43e511144 100644 --- a/apps/openmw/mwgui/savegamedialog.cpp +++ b/apps/openmw/mwgui/savegamedialog.cpp @@ -84,6 +84,7 @@ namespace MWGui dialog->eventOkClicked.clear(); dialog->eventOkClicked += MyGUI::newDelegate(this, &SaveGameDialog::onDeleteSlotConfirmed); dialog->eventCancelClicked.clear(); + dialog->eventCancelClicked += MyGUI::newDelegate(this, &SaveGameDialog::onDeleteSlotCancel); } void SaveGameDialog::onDeleteSlotConfirmed() diff --git a/apps/openmw/mwgui/spellbuyingwindow.hpp b/apps/openmw/mwgui/spellbuyingwindow.hpp index 649aab3f2..3414c1b94 100644 --- a/apps/openmw/mwgui/spellbuyingwindow.hpp +++ b/apps/openmw/mwgui/spellbuyingwindow.hpp @@ -46,7 +46,7 @@ namespace MWGui void onMouseWheel(MyGUI::Widget* _sender, int _rel); void addSpell(const ESM::Spell& spell); void clearSpells(); - int mLastPos,mCurrentY; + int mCurrentY; static const int sLineHeight; diff --git a/apps/openmw/mwgui/statswindow.cpp b/apps/openmw/mwgui/statswindow.cpp index bf505b00f..d3d487579 100644 --- a/apps/openmw/mwgui/statswindow.cpp +++ b/apps/openmw/mwgui/statswindow.cpp @@ -105,7 +105,7 @@ namespace MWGui std::stringstream out; out << val << "/" << max; - setText(tname, out.str().c_str()); + setText(tname, out.str()); pt->setProgressRange(std::max(0, max)); pt->setProgressPosition(std::max(0, val)); diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index b80571ad8..acdbf20cb 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -442,6 +442,7 @@ namespace MWInput MyGUI::InputManager::getInstance().injectMouseMove(static_cast(mGuiCursorX), static_cast(mGuiCursorY), mMouseWheel); mInputManager->warpMouse(static_cast(mGuiCursorX/mInvUiScalingFactor), static_cast(mGuiCursorY/mInvUiScalingFactor)); + MWBase::Environment::get().getWindowManager()->setCursorActive(true); } } if (mMouseLookEnabled) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 7f412b4d2..255874d88 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -451,11 +451,10 @@ namespace MWMechanics // Check if an idle actor is too close to a door - if so start walking storage.mDoorCheckDuration += duration; - static float distance = MWBase::Environment::get().getWorld()->getMaxActivationDistance(); - if (storage.mDoorCheckDuration >= DOOR_CHECK_INTERVAL) { storage.mDoorCheckDuration = 0; // restart timer + static float distance = MWBase::Environment::get().getWorld()->getMaxActivationDistance(); if (mDistance && // actor is not intended to be stationary proximityToDoor(actor, distance*1.6f)) { @@ -531,11 +530,10 @@ namespace MWMechanics void AiWander::evadeObstacles(const MWWorld::Ptr& actor, AiWanderStorage& storage, float duration, ESM::Position& pos) { - static float distance = MWBase::Environment::get().getWorld()->getMaxActivationDistance(); - if (mObstacleCheck.isEvading()) { // first check if we're walking into a door + static float distance = MWBase::Environment::get().getWorld()->getMaxActivationDistance(); if (proximityToDoor(actor, distance)) { // remove allowed points then select another random destination diff --git a/apps/openmw/mwmechanics/combat.cpp b/apps/openmw/mwmechanics/combat.cpp index d59bddc90..071f61ab0 100644 --- a/apps/openmw/mwmechanics/combat.cpp +++ b/apps/openmw/mwmechanics/combat.cpp @@ -497,26 +497,6 @@ namespace MWMechanics } } - bool isEnvironmentCompatible(const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim) - { - const MWWorld::Class& attackerClass = attacker.getClass(); - MWBase::World* world = MWBase::Environment::get().getWorld(); - - // If attacker is fish, victim must be in water - if (attackerClass.isPureWaterCreature(attacker)) - { - return world->isWading(victim); - } - - // If attacker can't swim, victim must not be in water - if (!attackerClass.canSwim(attacker)) - { - return !world->isSwimming(victim); - } - - return true; - } - float getFightDistanceBias(const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2) { osg::Vec3f pos1 (actor1.getRefData().getPosition().asVec3()); diff --git a/apps/openmw/mwmechanics/combat.hpp b/apps/openmw/mwmechanics/combat.hpp index 12961dc4b..8b93ca204 100644 --- a/apps/openmw/mwmechanics/combat.hpp +++ b/apps/openmw/mwmechanics/combat.hpp @@ -39,10 +39,6 @@ void getHandToHandDamage (const MWWorld::Ptr& attacker, const MWWorld::Ptr& vict /// Apply the fatigue loss incurred by attacking with the given weapon (weapon may be empty = hand-to-hand) void applyFatigueLoss(const MWWorld::Ptr& attacker, const MWWorld::Ptr& weapon, float attackStrength); -/// Can attacker operate in victim's environment? -/// e.g. If attacker is a fish, is victim in water? Or, if attacker can't swim, is victim on land? -bool isEnvironmentCompatible(const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim); - float getFightDistanceBias(const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2); } diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index a1c9723ef..a361f5c93 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -1160,6 +1160,10 @@ namespace MWMechanics End of tes3mp addition */ + // NPC will complain about theft even if he will do nothing about it + if (type == OT_Theft || type == OT_Pickpocket) + MWBase::Environment::get().getDialogueManager()->say(*it, "thief"); + crimeSeen = true; } } @@ -1280,9 +1284,7 @@ namespace MWMechanics { reported = true; - if (type == OT_Theft || type == OT_Pickpocket) - MWBase::Environment::get().getDialogueManager()->say(*it, "thief"); - else if (type == OT_Trespassing) + if (type == OT_Trespassing) MWBase::Environment::get().getDialogueManager()->say(*it, "intruder"); } diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 462fae50b..2632647ed 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -552,6 +552,13 @@ namespace MWMechanics appliedLastingEffects.push_back(effect); + // Unequip all items, if a spell with the ExtraSpell effect was casted + if (effectIt->mEffectID == ESM::MagicEffect::ExtraSpell && target.getClass().hasInventoryStore(target)) + { + MWWorld::InventoryStore& store = target.getClass().getInventoryStore(target); + store.unequipAll(target); + } + // Command spells should have their effect, including taking the target out of combat, each time the spell successfully affects the target if (((effectIt->mEffectID == ESM::MagicEffect::CommandHumanoid && target.getClass().isNpc()) || (effectIt->mEffectID == ESM::MagicEffect::CommandCreature && target.getTypeName() == typeid(ESM::Creature).name())) diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 887189a85..34932e360 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -702,8 +702,6 @@ namespace MWPhysics const char* env = getenv("OPENMW_PHYSICS_FPS"); if (env) { - std::string str(env); - float physFramerate = std::atof(env); if (physFramerate > 0) { @@ -1046,7 +1044,7 @@ namespace MWPhysics bool PhysicsSystem::isOnGround(const MWWorld::Ptr &actor) { Actor* physactor = getActor(actor); - return physactor->getOnGround(); + return physactor && physactor->getOnGround(); } bool PhysicsSystem::canMoveToWaterSurface(const MWWorld::ConstPtr &actor, const float waterlevel) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 3826fd5f6..aa7b35b44 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -256,6 +256,7 @@ namespace MWRender mRootNode->getOrCreateStateSet()->addUniform(mUniformRainIntensity); mSky.reset(new SkyManager(sceneRoot, resourceSystem->getSceneManager())); + mSky->setCamera(mViewer->getCamera()); source->setStateSetModes(*mRootNode->getOrCreateStateSet(), osg::StateAttribute::ON); diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 178c753c6..1338a127c 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -25,6 +25,9 @@ #include #include +#include +#include + #include #include @@ -48,7 +51,6 @@ namespace { - osg::ref_ptr createAlphaTrackingUnlitMaterial() { osg::ref_ptr mat = new osg::Material; @@ -1093,6 +1095,7 @@ private: SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneManager) : mSceneManager(sceneManager) + , mCamera(NULL) , mAtmosphereNightRoll(0.f) , mCreated(false) , mIsStorm(false) @@ -1337,6 +1340,87 @@ protected: osg::Uniform* mRainIntensityUniform; }; +void SkyManager::setCamera(osg::Camera *camera) +{ + mCamera = camera; +} + +class WrapAroundOperator : public osgParticle::Operator +{ +public: + WrapAroundOperator(osg::Camera *camera, const osg::Vec3 &wrapRange): osgParticle::Operator() + { + mCamera = camera; + mWrapRange = wrapRange; + mHalfWrapRange = mWrapRange / 2.0; + mPreviousCameraPosition = getCameraPosition(); + } + + virtual osg::Object *cloneType() const override + { + return NULL; + } + + virtual osg::Object *clone(const osg::CopyOp &op) const override + { + return NULL; + } + + virtual void operate(osgParticle::Particle *P, double dt) override + { + } + + virtual void operateParticles(osgParticle::ParticleSystem *ps, double dt) override + { + osg::Vec3 position = getCameraPosition(); + osg::Vec3 positionDifference = position - mPreviousCameraPosition; + + osg::Matrix toWorld, toLocal; + + std::vector worldMatrices = ps->getWorldMatrices(); + + if (!worldMatrices.empty()) + { + toWorld = worldMatrices[0]; + toLocal.invert(toWorld); + } + + for (int i = 0; i < ps->numParticles(); ++i) + { + osgParticle::Particle *p = ps->getParticle(i); + p->setPosition(toWorld.preMult(p->getPosition())); + p->setPosition(p->getPosition() - positionDifference); + + for (int j = 0; j < 3; ++j) // wrap-around in all 3 dimensions + { + osg::Vec3 pos = p->getPosition(); + + if (pos[j] < -mHalfWrapRange[j]) + pos[j] = mHalfWrapRange[j] + fmod(pos[j] - mHalfWrapRange[j],mWrapRange[j]); + else if (pos[j] > mHalfWrapRange[j]) + pos[j] = fmod(pos[j] + mHalfWrapRange[j],mWrapRange[j]) - mHalfWrapRange[j]; + + p->setPosition(pos); + } + + p->setPosition(toLocal.preMult(p->getPosition())); + } + + mPreviousCameraPosition = position; + } + +protected: + osg::Camera *mCamera; + osg::Vec3 mPreviousCameraPosition; + osg::Vec3 mWrapRange; + osg::Vec3 mHalfWrapRange; + + osg::Vec3 getCameraPosition() + { + return mCamera->getInverseViewMatrix().getTrans(); + } +}; + void SkyManager::createRain() { if (mRainNode) @@ -1345,6 +1429,8 @@ void SkyManager::createRain() mRainNode = new osg::Group; mRainParticleSystem = new osgParticle::ParticleSystem; + osg::Vec3 rainRange = osg::Vec3(600,600,600); + mRainParticleSystem->setParticleAlignment(osgParticle::ParticleSystem::FIXED); mRainParticleSystem->setAlignVectorX(osg::Vec3f(0.1,0,0)); mRainParticleSystem->setAlignVectorY(osg::Vec3f(0,0,1)); @@ -1370,8 +1456,8 @@ void SkyManager::createRain() emitter->setParticleSystem(mRainParticleSystem); osg::ref_ptr placer (new osgParticle::BoxPlacer); - placer->setXRange(-300, 300); // Rain_Diameter - placer->setYRange(-300, 300); + placer->setXRange(-rainRange.x() / 2, rainRange.x() / 2); // Rain_Diameter + placer->setYRange(-rainRange.y() / 2, rainRange.y() / 2); placer->setZRange(300, 300); emitter->setPlacer(placer); @@ -1386,6 +1472,11 @@ void SkyManager::createRain() osg::ref_ptr updater (new osgParticle::ParticleSystemUpdater); updater->addParticleSystem(mRainParticleSystem); + osg::ref_ptr program (new osgParticle::ModularProgram); + program->addOperator(new WrapAroundOperator(mCamera,rainRange)); + program->setParticleSystem(mRainParticleSystem); + mRainNode->addChild(program); + mRainNode->addChild(emitter); mRainNode->addChild(mRainParticleSystem); mRainNode->addChild(updater); @@ -1452,6 +1543,7 @@ void SkyManager::update(float duration) if (mParticleNode) mParticleNode->setAttitude(quat); + mCloudNode->setAttitude(quat); } else @@ -1559,6 +1651,22 @@ void SkyManager::setWeather(const WeatherResult& weather) SceneUtil::DisableFreezeOnCullVisitor disableFreezeOnCullVisitor; mParticleEffect->accept(disableFreezeOnCullVisitor); + + if (!weather.mIsStorm) + { + SceneUtil::FindByClassVisitor findPSVisitor(std::string("ParticleSystem")); + mParticleEffect->accept(findPSVisitor); + + for (unsigned int i = 0; i < findPSVisitor.mFoundNodes.size(); ++i) + { + osgParticle::ParticleSystem *ps = static_cast(findPSVisitor.mFoundNodes[i]); + + osg::ref_ptr program (new osgParticle::ModularProgram); + program->addOperator(new WrapAroundOperator(mCamera,osg::Vec3(1024,1024,800))); + program->setParticleSystem(ps); + mParticleNode->addChild(program); + } + } } } diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index 59a8ddc4e..097405b24 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -9,6 +9,11 @@ #include #include +namespace osg +{ + class Camera; +} + namespace osg { class Group; @@ -161,6 +166,8 @@ namespace MWRender void listAssetsToPreload(std::vector& models, std::vector& textures); + void setCamera(osg::Camera *camera); + private: void create(); ///< no need to call this, automatically done on first enable() @@ -171,6 +178,8 @@ namespace MWRender Resource::SceneManager* mSceneManager; + osg::Camera* mCamera; + osg::ref_ptr mRootNode; osg::ref_ptr mEarlyRenderBinRoot; diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 67595792a..456ed8d1f 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -289,7 +289,6 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor) // Autoequip clothing, armor and weapons. // Equipping lights is handled in Actors::updateEquippedLight based on environment light. - for (ContainerStoreIterator iter (begin(ContainerStore::Type_Clothing | ContainerStore::Type_Armor)); iter!=end(); ++iter) { Ptr test = *iter; @@ -314,9 +313,12 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor) std::pair, bool> itemsSlots = iter->getClass().getEquipmentSlots (*iter); + // checking if current item poited by iter can be equipped for (std::vector::const_iterator iter2 (itemsSlots.first.begin()); iter2!=itemsSlots.first.end(); ++iter2) { + // if true then it means slot is equipped already + // check if slot may require swapping if current item is more valueable if (slots_.at (*iter2)!=end()) { Ptr old = *slots_.at (*iter2); @@ -339,6 +341,26 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor) } else if (iter.getType() == ContainerStore::Type_Clothing) { + // if left ring is equipped + if (*iter2 == Slot_LeftRing) + { + // if there is a place for right ring dont swap it + if (slots_.at(Slot_RightRing) == end()) + { + continue; + } + else // if right ring is equipped too + { + Ptr rightRing = *slots_.at(Slot_RightRing); + + // we want to swap cheaper ring only if both are equipped + if (rightRing.getClass().getValue(rightRing) < old.getClass().getValue(old)) + { + continue; + } + } + } + if (old.getTypeName() == typeid(ESM::Clothing).name()) { // check value @@ -361,6 +383,7 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor) } } + // if we are here it means item can be equipped or swapped slots_[*iter2] = iter; break; } diff --git a/cmake/GitVersion.cmake b/cmake/GitVersion.cmake index 32abbbfbf..ff719d72a 100644 --- a/cmake/GitVersion.cmake +++ b/cmake/GitVersion.cmake @@ -26,4 +26,6 @@ else () message(WARNING "Failed to get valid version information from Git") endif () -configure_file(${VERSION_IN_FILE} ${VERSION_FILE}) +include(${MACROSFILE}) + +configure_resource_file(${VERSION_IN_FILE} ${VERSION_FILE_PATH_BASE} ${VERSION_FILE_PATH_RELATIVE}) diff --git a/cmake/OpenMWMacros.cmake b/cmake/OpenMWMacros.cmake index 12420d103..c3b0f5033 100644 --- a/cmake/OpenMWMacros.cmake +++ b/cmake/OpenMWMacros.cmake @@ -91,13 +91,6 @@ endforeach (u) source_group ("components\\${dir}" FILES ${files}) endmacro (add_component_qt_dir) -macro (copy_all_files source_dir destination_dir files) -foreach (f ${files}) -get_filename_component(filename ${f} NAME) -configure_file(${source_dir}/${f} ${destination_dir}/${filename} COPYONLY) -endforeach (f) -endmacro (copy_all_files) - macro (add_file project type file) list (APPEND ${project}${type} ${file}) endmacro (add_file) @@ -174,3 +167,40 @@ macro (openmw_add_executable target) endif (CMAKE_VERSION VERSION_GREATER 3.8 OR CMAKE_VERSION VERSION_EQUAL 3.8) endif (MSVC) endmacro (openmw_add_executable) + +macro (get_generator_is_multi_config VALUE) + if (CMAKE_VERSION VERSION_GREATER 3.9 OR CMAKE_VERSION VERSION_EQUAL 3.9) + get_cmake_property(${VALUE} GENERATOR_IS_MULTI_CONFIG) + else (CMAKE_VERSION VERSION_GREATER 3.9 OR CMAKE_VERSION VERSION_EQUAL 3.9) + list(LENGTH "${CMAKE_CONFIGURATION_TYPES}" ${VALUE}) + endif (CMAKE_VERSION VERSION_GREATER 3.9 OR CMAKE_VERSION VERSION_EQUAL 3.9) +endmacro (get_generator_is_multi_config) + +macro (copy_resource_file source_path destination_dir_base dest_path_relative) + get_generator_is_multi_config(multi_config) + if (multi_config) + foreach(cfgtype ${CMAKE_CONFIGURATION_TYPES}) + configure_file(${source_path} "${destination_dir_base}/${cfgtype}/${dest_path_relative}" COPYONLY) + endforeach(cfgtype) + else (multi_config) + configure_file(${source_path} "${destination_dir_base}/${dest_path_relative}" COPYONLY) + endif (multi_config) +endmacro (copy_resource_file) + +macro (configure_resource_file source_path destination_dir_base dest_path_relative) + get_generator_is_multi_config(multi_config) + if (multi_config) + foreach(cfgtype ${CMAKE_CONFIGURATION_TYPES}) + configure_file(${source_path} "${destination_dir_base}/${cfgtype}/${dest_path_relative}") + endforeach(cfgtype) + else (multi_config) + configure_file(${source_path} "${destination_dir_base}/${dest_path_relative}") + endif (multi_config) +endmacro (configure_resource_file) + +macro (copy_all_resource_files source_dir destination_dir_base destination_dir_relative files) + foreach (f ${files}) + get_filename_component(filename ${f} NAME) + copy_resource_file("${source_dir}/${f}" "${destination_dir_base}" "${destination_dir_relative}/${filename}") + endforeach (f) +endmacro (copy_all_resource_files) \ No newline at end of file diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index b25adbbd1..18d0899aa 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -2,22 +2,25 @@ project (Components) # Version file set (VERSION_IN_FILE "${OpenMW_SOURCE_DIR}/files/version.in") -set (VERSION_FILE "${OpenMW_BINARY_DIR}/resources/version") +set (VERSION_FILE_PATH_BASE "${OpenMW_BINARY_DIR}") +set (VERSION_FILE_PATH_RELATIVE resources/version) if (GIT_CHECKOUT) add_custom_target (git-version COMMAND ${CMAKE_COMMAND} -DGIT_EXECUTABLE=${GIT_EXECUTABLE} -DPROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR} -DVERSION_IN_FILE=${VERSION_IN_FILE} - -DVERSION_FILE=${VERSION_FILE} + -DVERSION_FILE_PATH_BASE=${VERSION_FILE_PATH_BASE} + -DVERSION_FILE_PATH_RELATIVE=${VERSION_FILE_PATH_RELATIVE} -DOPENMW_VERSION_MAJOR=${OPENMW_VERSION_MAJOR} -DOPENMW_VERSION_MINOR=${OPENMW_VERSION_MINOR} -DOPENMW_VERSION_RELEASE=${OPENMW_VERSION_RELEASE} -DOPENMW_VERSION=${OPENMW_VERSION} + -DMACROSFILE=${CMAKE_SOURCE_DIR}/cmake/OpenMWMacros.cmake -P ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/GitVersion.cmake VERBATIM) else (GIT_CHECKOUT) - configure_file(${VERSION_IN_FILE} ${VERSION_FILE}) + configure_resource_file(${VERSION_IN_FILE} ${VERSION_FILE_PATH_BASE} ${VERSION_FILE_PATH_RELATIVE}) endif (GIT_CHECKOUT) if(BUILD_OPENMW OR BUILD_OPENCS) diff --git a/components/esm/loadmgef.cpp b/components/esm/loadmgef.cpp index 3a918cf19..9f8ad94e1 100644 --- a/components/esm/loadmgef.cpp +++ b/components/esm/loadmgef.cpp @@ -380,6 +380,7 @@ static std::map genNameMap() names[131] ="sEffectBoundGloves"; names[128] ="sEffectBoundHelm"; names[125] ="sEffectBoundLongbow"; + names[126] ="sEffectExtraSpell"; names[121] ="sEffectBoundLongsword"; names[122] ="sEffectBoundMace"; names[130] ="sEffectBoundShield"; diff --git a/components/nifbullet/bulletnifloader.cpp b/components/nifbullet/bulletnifloader.cpp index 3865b17a5..9e9fe3759 100644 --- a/components/nifbullet/bulletnifloader.cpp +++ b/components/nifbullet/bulletnifloader.cpp @@ -49,7 +49,7 @@ BulletNifLoader::~BulletNifLoader() { } -osg::ref_ptr BulletNifLoader::load(const Nif::NIFFilePtr nif) +osg::ref_ptr BulletNifLoader::load(const Nif::NIFFilePtr& nif) { mShape = new Resource::BulletShape; diff --git a/components/nifbullet/bulletnifloader.hpp b/components/nifbullet/bulletnifloader.hpp index a30bf8fdf..fff51933f 100644 --- a/components/nifbullet/bulletnifloader.hpp +++ b/components/nifbullet/bulletnifloader.hpp @@ -50,7 +50,7 @@ public: abort(); } - osg::ref_ptr load(const Nif::NIFFilePtr file); + osg::ref_ptr load(const Nif::NIFFilePtr& file); private: bool findBoundingBox(const Nif::Node* node, int flags = 0); diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 8810f171a..a3b81338e 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -1191,8 +1191,8 @@ namespace NifOsg if (pixelData->mipmaps.empty()) return NULL; - unsigned int width = 0; - unsigned int height = 0; + int width = 0; + int height = 0; std::vector mipmapVector; for (unsigned int i=0; imipmaps.size()-3; ++i) diff --git a/components/resource/bulletshapemanager.cpp b/components/resource/bulletshapemanager.cpp index c1a7eb8f3..a3d09311a 100644 --- a/components/resource/bulletshapemanager.cpp +++ b/components/resource/bulletshapemanager.cpp @@ -63,7 +63,7 @@ class NodeToShapeVisitor : public osg::NodeVisitor public: NodeToShapeVisitor() : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) - , mTriangleMesh(NULL) + , mTriangleMesh(nullptr) { } @@ -71,11 +71,11 @@ public: virtual void apply(osg::Drawable &drawable) { if (!mTriangleMesh) - mTriangleMesh = new btTriangleMesh; + mTriangleMesh.reset(new btTriangleMesh); osg::Matrixf worldMat = osg::computeLocalToWorld(getNodePath()); osg::TriangleFunctor functor; - functor.setTriMesh(mTriangleMesh); + functor.setTriMesh(mTriangleMesh.get()); functor.setMatrix(worldMat); drawable.accept(functor); } @@ -86,14 +86,12 @@ public: return osg::ref_ptr(); osg::ref_ptr shape (new BulletShape); - TriangleMeshShape* meshShape = new TriangleMeshShape(mTriangleMesh, true); - shape->mCollisionShape = meshShape; - mTriangleMesh = NULL; + shape->mCollisionShape = new TriangleMeshShape(mTriangleMesh.release(), true); return shape; } private: - btTriangleMesh* mTriangleMesh; + std::unique_ptr mTriangleMesh; }; BulletShapeManager::BulletShapeManager(const VFS::Manager* vfs, SceneManager* sceneMgr, NifFileManager* nifFileManager) @@ -141,10 +139,7 @@ osg::ref_ptr BulletShapeManager::getShape(const std::string & node->accept(visitor); shape = visitor.getShape(); if (!shape) - { - mCache->addEntryToObjectCache(normalized, NULL); return osg::ref_ptr(); - } } mCache->addEntryToObjectCache(normalized, shape); @@ -158,7 +153,8 @@ osg::ref_ptr BulletShapeManager::cacheInstance(const std::s mVFS->normalizeFilename(normalized); osg::ref_ptr instance = createInstance(normalized); - mInstanceCache->addEntryToObjectCache(normalized, instance.get()); + if (instance) + mInstanceCache->addEntryToObjectCache(normalized, instance.get()); return instance; } diff --git a/components/resource/imagemanager.cpp b/components/resource/imagemanager.cpp index 441fd8212..000a833cf 100644 --- a/components/resource/imagemanager.cpp +++ b/components/resource/imagemanager.cpp @@ -69,7 +69,6 @@ namespace Resource // This one works too. Should it be included in isTextureCompressionS3TCSupported()? Submitted as a patch to OSG. && !osg::isGLExtensionSupported(0, "GL_S3_s3tc")) { - std::cerr << "Error loading " << filename << ": no S3TC texture compression support installed" << std::endl; return false; } break; @@ -123,12 +122,31 @@ namespace Resource return mWarningImage; } - osg::Image* image = result.getImage(); + osg::ref_ptr image = result.getImage(); + image->setFileName(normalized); if (!checkSupported(image, filename)) { - mCache->addEntryToObjectCache(normalized, mWarningImage); - return mWarningImage; + static bool uncompress = (getenv("OPENMW_DECOMPRESS_TEXTURES") != 0); + if (!uncompress) + { + std::cerr << "Error loading " << filename << ": no S3TC texture compression support installed" << std::endl; + mCache->addEntryToObjectCache(normalized, mWarningImage); + return mWarningImage; + } + else + { + // decompress texture in software if not supported by GPU + // requires update to getColor() to be released with OSG 3.6 + osg::ref_ptr newImage = new osg::Image; + newImage->setFileName(image->getFileName()); + newImage->allocateImage(image->s(), image->t(), image->r(), image->isImageTranslucent() ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE); + for (int s=0; ss(); ++s) + for (int t=0; tt(); ++t) + for (int r=0; rr(); ++r) + newImage->setColor(image->getColor(s,t,r), s,t,r); + image = newImage; + } } mCache->addEntryToObjectCache(normalized, image); diff --git a/components/resource/multiobjectcache.cpp b/components/resource/multiobjectcache.cpp index 266139f3c..d6639d3ae 100644 --- a/components/resource/multiobjectcache.cpp +++ b/components/resource/multiobjectcache.cpp @@ -51,6 +51,11 @@ namespace Resource void MultiObjectCache::addEntryToObjectCache(const std::string &filename, osg::Object *object) { + if (!object) + { + OSG_ALWAYS << " trying to add NULL object to cache for " << filename << std::endl; + return; + } OpenThreads::ScopedLock lock(_objectCacheMutex); _objectCache.insert(std::make_pair(filename, object)); } diff --git a/components/resource/objectcache.cpp b/components/resource/objectcache.cpp index de0fa7a40..e8c082f91 100644 --- a/components/resource/objectcache.cpp +++ b/components/resource/objectcache.cpp @@ -34,6 +34,11 @@ ObjectCache::~ObjectCache() void ObjectCache::addEntryToObjectCache(const std::string& filename, osg::Object* object, double timestamp) { + if (!object) + { + OSG_ALWAYS << " trying to add NULL object to cache for " << filename << std::endl; + return; + } OpenThreads::ScopedLock lock(_objectCacheMutex); _objectCache[filename]=ObjectTimeStampPair(object,timestamp); } diff --git a/components/resource/scenemanager.cpp b/components/resource/scenemanager.cpp index ab801ab82..9c5a2a14e 100644 --- a/components/resource/scenemanager.cpp +++ b/components/resource/scenemanager.cpp @@ -244,12 +244,9 @@ namespace Resource void SceneManager::recreateShaders(osg::ref_ptr node) { - Shader::ShaderVisitor shaderVisitor(*mShaderManager.get(), *mImageManager, "objects_vertex.glsl", "objects_fragment.glsl"); - shaderVisitor.setForceShaders(mForceShaders); - shaderVisitor.setClampLighting(mClampLighting); - shaderVisitor.setForcePerPixelLighting(mForcePerPixelLighting); - shaderVisitor.setAllowedToModifyStateSets(false); - node->accept(shaderVisitor); + osg::ref_ptr shaderVisitor(createShaderVisitor()); + shaderVisitor->setAllowedToModifyStateSets(false); + node->accept(*shaderVisitor); } void SceneManager::setClampLighting(bool clamp) @@ -516,16 +513,8 @@ namespace Resource SetFilterSettingsControllerVisitor setFilterSettingsControllerVisitor(mMinFilter, mMagFilter, mMaxAnisotropy); loaded->accept(setFilterSettingsControllerVisitor); - Shader::ShaderVisitor shaderVisitor(*mShaderManager.get(), *mImageManager, "objects_vertex.glsl", "objects_fragment.glsl"); - shaderVisitor.setForceShaders(mForceShaders); - shaderVisitor.setClampLighting(mClampLighting); - shaderVisitor.setForcePerPixelLighting(mForcePerPixelLighting); - shaderVisitor.setAutoUseNormalMaps(mAutoUseNormalMaps); - shaderVisitor.setNormalMapPattern(mNormalMapPattern); - shaderVisitor.setNormalHeightMapPattern(mNormalHeightMapPattern); - shaderVisitor.setAutoUseSpecularMaps(mAutoUseSpecularMaps); - shaderVisitor.setSpecularMapPattern(mSpecularMapPattern); - loaded->accept(shaderVisitor); + osg::ref_ptr shaderVisitor (createShaderVisitor()); + loaded->accept(*shaderVisitor); // share state // do this before optimizing so the optimizer will be able to combine nodes more aggressively @@ -748,4 +737,18 @@ namespace Resource stats->setAttribute(frameNumber, "Node Instance", mInstanceCache->getCacheSize()); } + Shader::ShaderVisitor *SceneManager::createShaderVisitor() + { + Shader::ShaderVisitor* shaderVisitor = new Shader::ShaderVisitor(*mShaderManager.get(), *mImageManager, "objects_vertex.glsl", "objects_fragment.glsl"); + shaderVisitor->setForceShaders(mForceShaders); + shaderVisitor->setClampLighting(mClampLighting); + shaderVisitor->setForcePerPixelLighting(mForcePerPixelLighting); + shaderVisitor->setAutoUseNormalMaps(mAutoUseNormalMaps); + shaderVisitor->setNormalMapPattern(mNormalMapPattern); + shaderVisitor->setNormalHeightMapPattern(mNormalHeightMapPattern); + shaderVisitor->setAutoUseSpecularMaps(mAutoUseSpecularMaps); + shaderVisitor->setSpecularMapPattern(mSpecularMapPattern); + return shaderVisitor; + } + } diff --git a/components/resource/scenemanager.hpp b/components/resource/scenemanager.hpp index b223353c2..4f1523ece 100644 --- a/components/resource/scenemanager.hpp +++ b/components/resource/scenemanager.hpp @@ -31,6 +31,7 @@ namespace osgDB namespace Shader { class ShaderManager; + class ShaderVisitor; } namespace Resource @@ -149,6 +150,8 @@ namespace Resource private: + Shader::ShaderVisitor* createShaderVisitor(); + std::unique_ptr mShaderManager; bool mForceShaders; bool mClampLighting; diff --git a/components/sceneutil/util.cpp b/components/sceneutil/util.cpp index 3add3bb23..eec302965 100644 --- a/components/sceneutil/util.cpp +++ b/components/sceneutil/util.cpp @@ -42,13 +42,4 @@ osg::Vec4f colourFromRGB(unsigned int clr) return colour; } -osg::Vec4f colourFromRGBA(unsigned int clr) -{ - osg::Vec4f colour(((clr >> 0) & 0xFF) / 255.0f, - ((clr >> 8) & 0xFF) / 255.0f, - ((clr >> 16) & 0xFF) / 255.0f, - ((clr >> 24) & 0xFF) / 255.0f); - return colour; -} - } diff --git a/components/sceneutil/util.hpp b/components/sceneutil/util.hpp index d8fefdb29..109099740 100644 --- a/components/sceneutil/util.hpp +++ b/components/sceneutil/util.hpp @@ -15,8 +15,6 @@ namespace SceneUtil osg::Vec4f colourFromRGB (unsigned int clr); - osg::Vec4f colourFromRGBA (unsigned int clr); - } #endif diff --git a/components/sceneutil/visitor.cpp b/components/sceneutil/visitor.cpp index 74b9be63d..2f6123e34 100644 --- a/components/sceneutil/visitor.cpp +++ b/components/sceneutil/visitor.cpp @@ -19,6 +19,14 @@ namespace SceneUtil return false; } + void FindByClassVisitor::apply(osg::Node &node) + { + if (Misc::StringUtils::ciEqual(node.className(), mNameToFind)) + mFoundNodes.push_back(&node); + + traverse(node); + } + void FindByNameVisitor::apply(osg::Group &group) { if (!checkGroup(group)) diff --git a/components/sceneutil/visitor.hpp b/components/sceneutil/visitor.hpp index 209f2d9bd..265fd6d02 100644 --- a/components/sceneutil/visitor.hpp +++ b/components/sceneutil/visitor.hpp @@ -20,7 +20,6 @@ namespace SceneUtil } virtual void apply(osg::Group& group); - virtual void apply(osg::MatrixTransform& node); virtual void apply(osg::Geometry& node); @@ -30,6 +29,21 @@ namespace SceneUtil osg::Group* mFoundNode; }; + class FindByClassVisitor : public osg::NodeVisitor + { + public: + FindByClassVisitor(const std::string& nameToFind) + : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) + , mNameToFind(nameToFind) + { + } + + virtual void apply(osg::Node &node); + + std::string mNameToFind; + std::vector mFoundNodes; + }; + // Disable freezeOnCull for all visited particlesystems class DisableFreezeOnCullVisitor : public osg::NodeVisitor { diff --git a/components/sceneutil/workqueue.cpp b/components/sceneutil/workqueue.cpp index cc40506f0..2cd1ec806 100644 --- a/components/sceneutil/workqueue.cpp +++ b/components/sceneutil/workqueue.cpp @@ -119,6 +119,7 @@ unsigned int WorkQueue::getNumActiveThreads() const WorkThread::WorkThread(WorkQueue *workQueue) : mWorkQueue(workQueue) + , mActive(false) { } diff --git a/extern/osg-ffmpeg-videoplayer/License.txt b/extern/osg-ffmpeg-videoplayer/License.txt index 49f534065..bb70d7d37 100644 --- a/extern/osg-ffmpeg-videoplayer/License.txt +++ b/extern/osg-ffmpeg-videoplayer/License.txt @@ -1,4 +1,4 @@ -Copyright (c) 2014 Jannik Heller , Chris Robinson +Copyright (c) 2014 scrawl, Chris Robinson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/files/mygui/CMakeLists.txt b/files/mygui/CMakeLists.txt index 0f5e7b5e5..3ff8a1b2b 100644 --- a/files/mygui/CMakeLists.txt +++ b/files/mygui/CMakeLists.txt @@ -4,7 +4,7 @@ endif() # Copy resource files into the build directory set(SDIR ${CMAKE_CURRENT_SOURCE_DIR}) -set(DDIR ${OPENMW_MYGUI_FILES_ROOT}/resources/mygui) +set(DDIRRELATIVE resources/mygui) set(MYGUI_FILES core.skin @@ -105,4 +105,4 @@ set(MYGUI_FILES ) -copy_all_files(${CMAKE_CURRENT_SOURCE_DIR} ${DDIR} "${MYGUI_FILES}") +copy_all_resource_files(${CMAKE_CURRENT_SOURCE_DIR} ${OPENMW_MYGUI_FILES_ROOT} ${DDIRRELATIVE} "${MYGUI_FILES}") diff --git a/files/shaders/CMakeLists.txt b/files/shaders/CMakeLists.txt index 5ca0d1e83..5833a592f 100644 --- a/files/shaders/CMakeLists.txt +++ b/files/shaders/CMakeLists.txt @@ -4,7 +4,7 @@ endif() # Copy resource files into the build directory set(SDIR ${CMAKE_CURRENT_SOURCE_DIR}) -set(DDIR ${OPENMW_SHADERS_ROOT}/resources/shaders) +set(DDIRRELATIVE resources/shaders) set(SHADER_FILES water_vertex.glsl @@ -18,4 +18,4 @@ set(SHADER_FILES parallax.glsl ) -copy_all_files(${CMAKE_CURRENT_SOURCE_DIR} ${DDIR} "${SHADER_FILES}") +copy_all_resource_files(${CMAKE_CURRENT_SOURCE_DIR} ${OPENMW_SHADERS_ROOT} ${DDIRRELATIVE} "${SHADER_FILES}")