diff --git a/Bitstream Vera License.txt b/Bitstream Vera License.txt deleted file mode 100644 index 2b37cc1df2..0000000000 --- a/Bitstream Vera License.txt +++ /dev/null @@ -1,123 +0,0 @@ -Bitstream Vera Fonts Copyright - -The fonts have a generous copyright, allowing derivative works (as -long as "Bitstream" or "Vera" are not in the names), and full -redistribution (so long as they are not *sold* by themselves). They -can be be bundled, redistributed and sold with any software. - -The fonts are distributed under the following copyright: - -Copyright -========= - -Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream -Vera is a trademark of Bitstream, Inc. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of the fonts accompanying this license ("Fonts") and associated -documentation files (the "Font Software"), to reproduce and distribute -the Font Software, including without limitation the rights to use, -copy, merge, publish, distribute, and/or sell copies of the Font -Software, and to permit persons to whom the Font Software is furnished -to do so, subject to the following conditions: - -The above copyright and trademark notices and this permission notice -shall be included in all copies of one or more of the Font Software -typefaces. - -The Font Software may be modified, altered, or added to, and in -particular the designs of glyphs or characters in the Fonts may be -modified and additional glyphs or characters may be added to the -Fonts, only if the fonts are renamed to names not containing either -the words "Bitstream" or the word "Vera". - -This License becomes null and void to the extent applicable to Fonts -or Font Software that has been modified and is distributed under the -"Bitstream Vera" names. - -The Font Software may be sold as part of a larger software package but -no copy of one or more of the Font Software typefaces may be sold by -itself. - -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL -BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, -OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR -OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT -SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. - -Except as contained in this notice, the names of Gnome, the Gnome -Foundation, and Bitstream Inc., shall not be used in advertising or -otherwise to promote the sale, use or other dealings in this Font -Software without prior written authorization from the Gnome Foundation -or Bitstream Inc., respectively. For further information, contact: -fonts at gnome dot org. - -Copyright FAQ -============= - - 1. I don't understand the resale restriction... What gives? - - Bitstream is giving away these fonts, but wishes to ensure its - competitors can't just drop the fonts as is into a font sale system - and sell them as is. It seems fair that if Bitstream can't make money - from the Bitstream Vera fonts, their competitors should not be able to - do so either. You can sell the fonts as part of any software package, - however. - - 2. I want to package these fonts separately for distribution and - sale as part of a larger software package or system. Can I do so? - - Yes. A RPM or Debian package is a "larger software package" to begin - with, and you aren't selling them independently by themselves. - See 1. above. - - 3. Are derivative works allowed? - Yes! - - 4. Can I change or add to the font(s)? - Yes, but you must change the name(s) of the font(s). - - 5. Under what terms are derivative works allowed? - - You must change the name(s) of the fonts. This is to ensure the - quality of the fonts, both to protect Bitstream and Gnome. We want to - ensure that if an application has opened a font specifically of these - names, it gets what it expects (though of course, using fontconfig, - substitutions could still could have occurred during font - opening). You must include the Bitstream copyright. Additional - copyrights can be added, as per copyright law. Happy Font Hacking! - - 6. If I have improvements for Bitstream Vera, is it possible they might get - adopted in future versions? - - Yes. The contract between the Gnome Foundation and Bitstream has - provisions for working with Bitstream to ensure quality additions to - the Bitstream Vera font family. Please contact us if you have such - additions. Note, that in general, we will want such additions for the - entire family, not just a single font, and that you'll have to keep - both Gnome and Jim Lyles, Vera's designer, happy! To make sense to add - glyphs to the font, they must be stylistically in keeping with Vera's - design. Vera cannot become a "ransom note" font. Jim Lyles will be - providing a document describing the design elements used in Vera, as a - guide and aid for people interested in contributing to Vera. - - 7. I want to sell a software package that uses these fonts: Can I do so? - - Sure. Bundle the fonts with your software and sell your software - with the fonts. That is the intent of the copyright. - - 8. If applications have built the names "Bitstream Vera" into them, - can I override this somehow to use fonts of my choosing? - - This depends on exact details of the software. Most open source - systems and software (e.g., Gnome, KDE, etc.) are now converting to - use fontconfig (see www.fontconfig.org) to handle font configuration, - selection and substitution; it has provisions for overriding font - names and subsituting alternatives. An example is provided by the - supplied local.conf file, which chooses the family Bitstream Vera for - "sans", "serif" and "monospace". Other software (e.g., the XFree86 - core server) has other mechanisms for font substitution. diff --git a/Dejavu_lgc_font_license.txt b/Dejavu_lgc_font_license.txt new file mode 100644 index 0000000000..254e2cc42a --- /dev/null +++ b/Dejavu_lgc_font_license.txt @@ -0,0 +1,99 @@ +Fonts are (c) Bitstream (see below). DejaVu changes are in public domain. +Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below) + +Bitstream Vera Fonts Copyright +------------------------------ + +Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is +a trademark of Bitstream, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of the fonts accompanying this license ("Fonts") and associated +documentation files (the "Font Software"), to reproduce and distribute the +Font Software, including without limitation the rights to use, copy, merge, +publish, distribute, and/or sell copies of the Font Software, and to permit +persons to whom the Font Software is furnished to do so, subject to the +following conditions: + +The above copyright and trademark notices and this permission notice shall +be included in all copies of one or more of the Font Software typefaces. + +The Font Software may be modified, altered, or added to, and in particular +the designs of glyphs or characters in the Fonts may be modified and +additional glyphs or characters may be added to the Fonts, only if the fonts +are renamed to names not containing either the words "Bitstream" or the word +"Vera". + +This License becomes null and void to the extent applicable to Fonts or Font +Software that has been modified and is distributed under the "Bitstream +Vera" names. + +The Font Software may be sold as part of a larger software package but no +copy of one or more of the Font Software typefaces may be sold by itself. + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, +TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME +FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING +ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE +FONT SOFTWARE. + +Except as contained in this notice, the names of Gnome, the Gnome +Foundation, and Bitstream Inc., shall not be used in advertising or +otherwise to promote the sale, use or other dealings in this Font Software +without prior written authorization from the Gnome Foundation or Bitstream +Inc., respectively. For further information, contact: fonts at gnome dot +org. + +Arev Fonts Copyright +------------------------------ + +Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of the fonts accompanying this license ("Fonts") and +associated documentation files (the "Font Software"), to reproduce +and distribute the modifications to the Bitstream Vera Font Software, +including without limitation the rights to use, copy, merge, publish, +distribute, and/or sell copies of the Font Software, and to permit +persons to whom the Font Software is furnished to do so, subject to +the following conditions: + +The above copyright and trademark notices and this permission notice +shall be included in all copies of one or more of the Font Software +typefaces. + +The Font Software may be modified, altered, or added to, and in +particular the designs of glyphs or characters in the Fonts may be +modified and additional glyphs or characters may be added to the +Fonts, only if the fonts are renamed to names not containing either +the words "Tavmjong Bah" or the word "Arev". + +This License becomes null and void to the extent applicable to Fonts +or Font Software that has been modified and is distributed under the +"Tavmjong Bah Arev" names. + +The Font Software may be sold as part of a larger software package but +no copy of one or more of the Font Software typefaces may be sold by +itself. + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL +TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + +Except as contained in this notice, the name of Tavmjong Bah shall not +be used in advertising or otherwise to promote the sale, use or other +dealings in this Font Software without prior written authorization +from Tavmjong Bah. For further information, contact: tavmjong @ free +. fr. + +$Id: LICENSE 2133 2007-11-28 02:46:28Z lechimp $ diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index b19cafab7a..4f149efa14 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -240,18 +240,9 @@ void OMW::Engine::setNewGame(bool newGame) mNewGame = newGame; } -// Initialise and enter main loop. - -void OMW::Engine::go() +std::string OMW::Engine::loadSettings (Settings::Manager & settings) { - assert (!mCellName.empty()); - assert (!mMaster.empty()); - assert (!mOgre); - - mOgre = new OEngine::Render::OgreRenderer; - // Create the settings manager and load default settings file - Settings::Manager settings; const std::string localdefault = mCfgMgr.getLocalPath().string() + "/settings-default.cfg"; const std::string globaldefault = mCfgMgr.getGlobalPath().string() + "/settings-default.cfg"; @@ -272,10 +263,6 @@ void OMW::Engine::go() else if (boost::filesystem::exists(globaldefault)) settings.loadUser(globaldefault); - // Get the path for the keybinder xml file - std::string keybinderUser = (mCfgMgr.getUserPath() / "input.xml").string(); - bool keybinderUserExists = boost::filesystem::exists(keybinderUser); - mFpsLevel = settings.getInt("fps", "HUD"); // load nif overrides @@ -285,6 +272,13 @@ void OMW::Engine::go() else if (boost::filesystem::exists(mCfgMgr.getGlobalPath().string() + "/transparency-overrides.cfg")) nifOverrides.loadTransparencyOverrides(mCfgMgr.getGlobalPath().string() + "/transparency-overrides.cfg"); + return settingspath; +} + +void OMW::Engine::prepareEngine (Settings::Manager & settings) +{ + Nif::NIFFile::CacheLock cachelock; + std::string renderSystem = settings.getString("render system", "Video"); if (renderSystem == "") { @@ -294,6 +288,9 @@ void OMW::Engine::go() renderSystem = "OpenGL Rendering Subsystem"; #endif } + + mOgre = new OEngine::Render::OgreRenderer; + mOgre->configure( mCfgMgr.getLogPath().string(), renderSystem, @@ -328,16 +325,13 @@ void OMW::Engine::go() // cursor replacer (converts the cursor from the bsa so they can be used by mygui) MWGui::CursorReplace replacer; - // Create encoder - ToUTF8::Utf8Encoder encoder (mEncoding); - // Create the world mEnvironment.setWorld (new MWWorld::World (*mOgre, mFileCollections, mMaster, - mResDir, mCfgMgr.getCachePath(), mNewGame, &encoder, mFallbackMap, + mResDir, mCfgMgr.getCachePath(), mNewGame, mEncoder, mFallbackMap, mActivationDistanceOverride)); //Load translation data - mTranslationDataStorage.setEncoder(&encoder); + mTranslationDataStorage.setEncoder(mEncoder); mTranslationDataStorage.loadTranslationData(mFileCollections, mMaster); // Create window manager - this manages all the MW-specific GUI windows @@ -365,6 +359,11 @@ void OMW::Engine::go() mEnvironment.setDialogueManager (new MWDialogue::DialogueManager (mExtensions, mVerboseScripts, mTranslationDataStorage)); // Sets up the input system + + // Get the path for the keybinder xml file + std::string keybinderUser = (mCfgMgr.getUserPath() / "input.xml").string(); + bool keybinderUserExists = boost::filesystem::exists(keybinderUser); + mEnvironment.setInputManager (new MWInput::InputManager (*mOgre, MWBase::Environment::get().getWorld()->getPlayer(), *MWBase::Environment::get().getWindowManager(), mDebug, *this, keybinderUser, keybinderUserExists)); @@ -388,13 +387,8 @@ void OMW::Engine::go() MWBase::Environment::get().getWorld()->changeToInteriorCell (mCellName, pos); } - std::cout << "\nPress Q/ESC or close window to exit.\n"; - mOgre->getRoot()->addFrameListener (this); - // Play some good 'ol tunes - MWBase::Environment::get().getSoundManager()->playPlaylist(std::string("Explore")); - // scripts if (mCompileAll) { @@ -407,10 +401,35 @@ void OMW::Engine::go() << "%)" << std::endl; } +} + +// Initialise and enter main loop. + +void OMW::Engine::go() +{ + assert (!mCellName.empty()); + assert (!mMaster.empty()); + assert (!mOgre); + + Settings::Manager settings; + std::string settingspath; + + settingspath = loadSettings (settings); + + // Create encoder + ToUTF8::Utf8Encoder encoder (mEncoding); + mEncoder = &encoder; + + prepareEngine (settings); + + // Play some good 'ol tunes + MWBase::Environment::get().getSoundManager()->playPlaylist(std::string("Explore")); if (!mStartupScript.empty()) MWBase::Environment::get().getWindowManager()->executeInConsole (mStartupScript); + std::cout << "\nPress Q/ESC or close window to exit.\n"; + // Start the main rendering loop mOgre->start(); diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index 601cc7765c..e320c6991b 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "mwbase/environment.hpp" @@ -61,6 +62,7 @@ namespace OMW { MWBase::Environment mEnvironment; ToUTF8::FromType mEncoding; + ToUTF8::Utf8Encoder* mEncoder; Files::PathContainer mDataDirs; boost::filesystem::path mResDir; OEngine::Render::OgreRenderer *mOgre; @@ -103,6 +105,12 @@ namespace OMW virtual bool frameRenderingQueued (const Ogre::FrameEvent& evt); + /// Load settings from various files, returns the path to the user settings file + std::string loadSettings (Settings::Manager & settings); + + /// Prepare engine for game play + void prepareEngine (Settings::Manager & settings); + public: Engine(Files::ConfigurationManager& configurationManager); virtual ~Engine(); diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 7a365eb8e4..b8557368d0 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -280,7 +280,7 @@ namespace MWBase /// @param cursor Y (relative 0-1) /// @return true if the object was placed, or false if it was rejected because the position is too far away - virtual void dropObjectOnGround (const MWWorld::Ptr& object) = 0; + virtual void dropObjectOnGround (const MWWorld::Ptr& actor, const MWWorld::Ptr& object) = 0; virtual bool canPlaceObject (float cursorX, float cursorY) = 0; ///< @return true if it is possible to place on object at specified cursor location diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index 1be8d66b32..7ad8f1b47c 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -12,6 +12,9 @@ #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" #include "../mwworld/actioneat.hpp" +#include "../mwworld/player.hpp" + +#include "../mwmechanics/npcstats.hpp" #include "../mwgui/tooltips.hpp" @@ -154,6 +157,10 @@ namespace MWClass text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); } + MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer(); + MWMechanics::NpcStats& npcStats = MWWorld::Class::get(player).getNpcStats (player); + int alchemySkill = npcStats.getSkill (ESM::Skill::Alchemy).getBase(); + MWGui::Widgets::SpellEffectList list; for (int i=0; i<4; ++i) { @@ -163,6 +170,12 @@ namespace MWClass params.mEffectID = ref->mBase->mData.mEffectID[i]; params.mAttribute = ref->mBase->mData.mAttributes[i]; params.mSkill = ref->mBase->mData.mSkills[i]; + + params.mKnown = ( (i == 0 && alchemySkill >= 15) + || (i == 1 && alchemySkill >= 30) + || (i == 2 && alchemySkill >= 45) + || (i == 3 && alchemySkill >= 60)); + list.push_back(params); } info.effects = list; diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 5ea1d13388..a2c3a318ba 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -220,7 +220,7 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender) if (world->canPlaceObject(mouseX, mouseY)) world->placeObject(object, mouseX, mouseY); else - world->dropObjectOnGround(object); + world->dropObjectOnGround(world->getPlayer().getPlayer(), object); MyGUI::PointerManager::getInstance().setPointer("arrow"); diff --git a/apps/openmw/mwgui/quickkeysmenu.cpp b/apps/openmw/mwgui/quickkeysmenu.cpp index 02512425de..6d51420f01 100644 --- a/apps/openmw/mwgui/quickkeysmenu.cpp +++ b/apps/openmw/mwgui/quickkeysmenu.cpp @@ -440,7 +440,7 @@ namespace MWGui for (MWMechanics::Spells::TIterator it = spells.begin(); it != spells.end(); ++it) { - spellList.push_back(*it); + spellList.push_back (it->first); } const MWWorld::ESMStore &esmStore = diff --git a/apps/openmw/mwgui/spellbuyingwindow.cpp b/apps/openmw/mwgui/spellbuyingwindow.cpp index a41f401a57..11f0904943 100644 --- a/apps/openmw/mwgui/spellbuyingwindow.cpp +++ b/apps/openmw/mwgui/spellbuyingwindow.cpp @@ -98,19 +98,19 @@ namespace MWGui MWMechanics::Spells& playerSpells = MWWorld::Class::get (player).getCreatureStats (player).getSpells(); MWMechanics::Spells& merchantSpells = MWWorld::Class::get (actor).getCreatureStats (actor).getSpells(); - + for (MWMechanics::Spells::TIterator iter = merchantSpells.begin(); iter!=merchantSpells.end(); ++iter) { const ESM::Spell* spell = - MWBase::Environment::get().getWorld()->getStore().get().find (*iter); - + MWBase::Environment::get().getWorld()->getStore().get().find (iter->first); + if (spell->mData.mType!=ESM::Spell::ST_Spell) continue; // don't try to sell diseases, curses or powers - + if (std::find (playerSpells.begin(), playerSpells.end(), *iter)!=playerSpells.end()) continue; // we have that spell already - - addSpell (*iter); + + addSpell (iter->first); } updateLabels(); diff --git a/apps/openmw/mwgui/spellcreationdialog.cpp b/apps/openmw/mwgui/spellcreationdialog.cpp index 69d69519f9..8395864521 100644 --- a/apps/openmw/mwgui/spellcreationdialog.cpp +++ b/apps/openmw/mwgui/spellcreationdialog.cpp @@ -436,7 +436,7 @@ namespace MWGui for (MWMechanics::Spells::TIterator it = spells.begin(); it != spells.end(); ++it) { const ESM::Spell* spell = - MWBase::Environment::get().getWorld()->getStore().get().find(*it); + MWBase::Environment::get().getWorld()->getStore().get().find (it->first); // only normal spells count if (spell->mData.mType != ESM::Spell::ST_Spell) diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index d62b23de47..47e1d739a7 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -139,7 +139,7 @@ namespace MWGui for (MWMechanics::Spells::TIterator it = spells.begin(); it != spells.end(); ++it) { - spellList.push_back(*it); + spellList.push_back (it->first); } const MWWorld::ESMStore &esmStore = diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp index 82e1128263..f932c1f034 100644 --- a/apps/openmw/mwgui/widgets.cpp +++ b/apps/openmw/mwgui/widgets.cpp @@ -390,8 +390,13 @@ void MWSpellEffect::setSpellEffect(const SpellEffectParams& params) void MWSpellEffect::updateWidgets() { - if (!mWindowManager) + if (!mEffectParams.mKnown) + { + mTextWidget->setCaption ("?"); + mRequestedWidth = mTextWidget->getTextSize().width + 24; + mImageWidget->setImageTexture (""); return; + } const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); @@ -400,7 +405,6 @@ void MWSpellEffect::updateWidgets() store.get().search(mEffectParams.mEffectID); assert(magicEffect); - assert(mWindowManager); std::string pt = mWindowManager->getGameSettingString("spoint", ""); std::string pts = mWindowManager->getGameSettingString("spoints", ""); diff --git a/apps/openmw/mwgui/widgets.hpp b/apps/openmw/mwgui/widgets.hpp index 4ac5383f7a..7cbb5e53ac 100644 --- a/apps/openmw/mwgui/widgets.hpp +++ b/apps/openmw/mwgui/widgets.hpp @@ -37,12 +37,15 @@ namespace MWGui , mEffectID(-1) , mNoTarget(false) , mIsConstant(false) + , mKnown(true) { } bool mNoTarget; // potion effects for example have no target (target is always the player) bool mIsConstant; // constant effect means that duration will not be displayed + bool mKnown; // is this effect known to the player? (If not, will display as a question mark instead) + // value of -1 here means the effect is unknown to the player short mEffectID; diff --git a/apps/openmw/mwmechanics/magiceffects.cpp b/apps/openmw/mwmechanics/magiceffects.cpp index 94363cb790..1a7b348170 100644 --- a/apps/openmw/mwmechanics/magiceffects.cpp +++ b/apps/openmw/mwmechanics/magiceffects.cpp @@ -68,7 +68,7 @@ namespace MWMechanics } } - void MagicEffects::add (const ESM::EffectList& list) + void MagicEffects::add (const ESM::EffectList& list, float magnitude) { for (std::vector::const_iterator iter (list.mList.begin()); iter!=list.mList.end(); ++iter) @@ -78,9 +78,13 @@ namespace MWMechanics if (iter->mMagnMin>=iter->mMagnMax) param.mMagnitude = iter->mMagnMin; else + { + if (magnitude==-1) + magnitude = static_cast (std::rand()) / RAND_MAX; + param.mMagnitude = static_cast ( - (iter->mMagnMax-iter->mMagnMin+1)* - (static_cast (std::rand()) / RAND_MAX) + iter->mMagnMin); + (iter->mMagnMax-iter->mMagnMin+1)*magnitude + iter->mMagnMin); + } add (*iter, param); } diff --git a/apps/openmw/mwmechanics/magiceffects.hpp b/apps/openmw/mwmechanics/magiceffects.hpp index 2f61d7eeb4..b80b5a863d 100644 --- a/apps/openmw/mwmechanics/magiceffects.hpp +++ b/apps/openmw/mwmechanics/magiceffects.hpp @@ -67,7 +67,8 @@ namespace MWMechanics void add (const EffectKey& key, const EffectParam& param); - void add (const ESM::EffectList& list); + void add (const ESM::EffectList& list, float magnitude = -1); + ///< \param magnitude normalised magnitude (-1: random) MagicEffects& operator+= (const MagicEffects& effects); diff --git a/apps/openmw/mwmechanics/spells.cpp b/apps/openmw/mwmechanics/spells.cpp index ef084f4795..e2da7cdc86 100644 --- a/apps/openmw/mwmechanics/spells.cpp +++ b/apps/openmw/mwmechanics/spells.cpp @@ -1,22 +1,19 @@ #include "spells.hpp" -#include "../mwworld/esmstore.hpp" +#include #include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwworld/esmstore.hpp" + #include "magiceffects.hpp" namespace MWMechanics { - void Spells::addSpell (const ESM::Spell *spell, MagicEffects& effects) const - { - effects.add (spell->mEffects); - } - Spells::TIterator Spells::begin() const { return mSpells.begin(); @@ -29,13 +26,13 @@ namespace MWMechanics void Spells::add (const std::string& spellId) { - if (std::find (mSpells.begin(), mSpells.end(), spellId)==mSpells.end()) - mSpells.push_back (spellId); + if (mSpells.find (spellId)==mSpells.end()) + mSpells.insert (std::make_pair (spellId, static_cast (std::rand()) / RAND_MAX)); } void Spells::remove (const std::string& spellId) { - TContainer::iterator iter = std::find (mSpells.begin(), mSpells.end(), spellId); + TContainer::iterator iter = mSpells.find (spellId); if (iter!=mSpells.end()) mSpells.erase (iter); @@ -51,11 +48,11 @@ namespace MWMechanics for (TIterator iter = mSpells.begin(); iter!=mSpells.end(); ++iter) { const ESM::Spell *spell = - MWBase::Environment::get().getWorld()->getStore().get().find (*iter); + MWBase::Environment::get().getWorld()->getStore().get().find (iter->first); if (spell->mData.mType==ESM::Spell::ST_Ability || spell->mData.mType==ESM::Spell::ST_Blight || spell->mData.mType==ESM::Spell::ST_Disease || spell->mData.mType==ESM::Spell::ST_Curse) - addSpell (spell, effects); + effects.add (spell->mEffects, iter->second); } return effects; @@ -75,18 +72,18 @@ namespace MWMechanics { return mSelectedSpell; } - + bool Spells::hasCommonDisease() const { for (TIterator iter = mSpells.begin(); iter!=mSpells.end(); ++iter) { const ESM::Spell *spell = - MWBase::Environment::get().getWorld()->getStore().get().find (*iter); - + MWBase::Environment::get().getWorld()->getStore().get().find (iter->first); + if (spell->mData.mFlags & ESM::Spell::ST_Disease) return true; } - + return false; } @@ -95,12 +92,12 @@ namespace MWMechanics for (TIterator iter = mSpells.begin(); iter!=mSpells.end(); ++iter) { const ESM::Spell *spell = - MWBase::Environment::get().getWorld()->getStore().get().find (*iter); - + MWBase::Environment::get().getWorld()->getStore().get().find (iter->first); + if (spell->mData.mFlags & ESM::Spell::ST_Blight) return true; } - - return false; + + return false; } } diff --git a/apps/openmw/mwmechanics/spells.hpp b/apps/openmw/mwmechanics/spells.hpp index 12308661ba..e00ac259f1 100644 --- a/apps/openmw/mwmechanics/spells.hpp +++ b/apps/openmw/mwmechanics/spells.hpp @@ -1,7 +1,7 @@ #ifndef GAME_MWMECHANICS_SPELLS_H #define GAME_MWMECHANICS_SPELLS_H -#include +#include #include namespace ESM @@ -21,16 +21,14 @@ namespace MWMechanics { public: - typedef std::vector TContainer; + typedef std::map TContainer; // ID, normalised magnitude typedef TContainer::const_iterator TIterator; private: - std::vector mSpells; + TContainer mSpells; std::string mSelectedSpell; - void addSpell (const ESM::Spell *, MagicEffects& effects) const; - public: TIterator begin() const; @@ -55,10 +53,10 @@ namespace MWMechanics const std::string getSelectedSpell() const; ///< May return an empty string. - + bool hasCommonDisease() const; - bool hasBlightDisease() const; + bool hasBlightDisease() const; }; } diff --git a/apps/openmw/mwscript/aiextensions.cpp b/apps/openmw/mwscript/aiextensions.cpp index 35243533c8..8402a5b4cd 100644 --- a/apps/openmw/mwscript/aiextensions.cpp +++ b/apps/openmw/mwscript/aiextensions.cpp @@ -181,10 +181,14 @@ namespace MWScript runtime.pop(); std::vector idleList; - for (unsigned int i=0; i + class OpDrop : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + + MWWorld::Ptr ptr = R()(runtime); + + std::string item = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + Interpreter::Type_Integer amount = runtime[0].mInteger; + runtime.pop(); + + MWWorld::ContainerStore& store = MWWorld::Class::get (ptr).getContainerStore (ptr); + + + for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter) + { + if (::Misc::StringUtils::ciEqual(iter->getCellRef().mRefID, item)) + { + if(iter->getRefData().getCount() <= amount) + { + MWBase::Environment::get().getWorld()->dropObjectOnGround(ptr, *iter); + iter->getRefData().setCount(0); + } + else + { + int original = iter->getRefData().getCount(); + iter->getRefData().setCount(amount); + MWBase::Environment::get().getWorld()->dropObjectOnGround(ptr, *iter); + iter->getRefData().setCount(original - amount); + } + + break; + } + } + } + }; + + template + class OpDropSoulGem : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + + MWWorld::Ptr ptr = R()(runtime); + + std::string soul = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + MWWorld::ContainerStore& store = MWWorld::Class::get (ptr).getContainerStore (ptr); + + + for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter) + { + if (::Misc::StringUtils::ciEqual(iter->getCellRef().mSoul, soul)) + { + + if(iter->getRefData().getCount() <= 1) + { + MWBase::Environment::get().getWorld()->dropObjectOnGround(ptr, *iter); + iter->getRefData().setCount(0); + } + else + { + int original = iter->getRefData().getCount(); + iter->getRefData().setCount(1); + MWBase::Environment::get().getWorld()->dropObjectOnGround(ptr, *iter); + iter->getRefData().setCount(original - 1); + } + + break; + } + } + } + }; + template class OpGetAttacked : public Interpreter::Opcode0 { @@ -495,6 +577,10 @@ namespace MWScript const int opcodeAddSoulGemExplicit = 0x20001f4; const int opcodeRemoveSoulGem = 0x20001f5; const int opcodeRemoveSoulGemExplicit = 0x20001f6; + const int opcodeDrop = 0x20001f8; + const int opcodeDropExplicit = 0x20001f9; + const int opcodeDropSoulGem = 0x20001fa; + const int opcodeDropSoulGemExplicit = 0x20001fb; const int opcodeGetAttacked = 0x20001d3; const int opcodeGetAttackedExplicit = 0x20001d4; const int opcodeGetWeaponDrawn = 0x20001d7; @@ -538,6 +624,8 @@ namespace MWScript extensions.registerFunction ("geteffect", 'l', "l", opcodeGetEffect, opcodeGetEffectExplicit); extensions.registerInstruction ("addsoulgem", "cc", opcodeAddSoulGem, opcodeAddSoulGemExplicit); extensions.registerInstruction ("removesoulgem", "c", opcodeRemoveSoulGem, opcodeRemoveSoulGemExplicit); + extensions.registerInstruction ("drop", "cl", opcodeDrop, opcodeDropExplicit); + extensions.registerInstruction ("dropsoulgem", "c", opcodeDropSoulGem, opcodeDropSoulGemExplicit); extensions.registerFunction ("getattacked", 'l', "", opcodeGetAttacked, opcodeGetAttackedExplicit); extensions.registerFunction ("getweapondrawn", 'l', "", opcodeGetWeaponDrawn, opcodeGetWeaponDrawnExplicit); extensions.registerFunction ("getspelleffects", 'l', "c", opcodeGetSpellEffects, opcodeGetSpellEffectsExplicit); @@ -576,6 +664,10 @@ namespace MWScript interpreter.installSegment5 (opcodeAddSoulGemExplicit, new OpAddSoulGem); interpreter.installSegment5 (opcodeRemoveSoulGem, new OpRemoveSoulGem); interpreter.installSegment5 (opcodeRemoveSoulGemExplicit, new OpRemoveSoulGem); + interpreter.installSegment5 (opcodeDrop, new OpDrop); + interpreter.installSegment5 (opcodeDropExplicit, new OpDrop); + interpreter.installSegment5 (opcodeDropSoulGem, new OpDropSoulGem); + interpreter.installSegment5 (opcodeDropSoulGemExplicit, new OpDropSoulGem); interpreter.installSegment5 (opcodeGetAttacked, new OpGetAttacked); interpreter.installSegment5 (opcodeGetAttackedExplicit, new OpGetAttacked); interpreter.installSegment5 (opcodeGetWeaponDrawn, new OpGetWeaponDrawn); diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index 31ea7518b9..530d44c9dd 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -485,7 +485,7 @@ namespace MWScript for (MWMechanics::Spells::TIterator iter ( MWWorld::Class::get (ptr).getCreatureStats (ptr).getSpells().begin()); iter!=MWWorld::Class::get (ptr).getCreatureStats (ptr).getSpells().end(); ++iter) - if (*iter==id) + if (iter->first==id) { value = 1; break; @@ -1188,7 +1188,7 @@ namespace MWScript extensions.registerFunction ("getpccrimelevel", 'f', "", opcodeGetPCCrimeLevel); extensions.registerInstruction ("setpccrimelevel", "f", opcodeSetPCCrimeLevel); extensions.registerInstruction ("modpccrimelevel", "f", opcodeModPCCrimeLevel); - + extensions.registerInstruction ("addspell", "c", opcodeAddSpell, opcodeAddSpellExplicit); extensions.registerInstruction ("removespell", "c", opcodeRemoveSpell, opcodeRemoveSpellExplicit); @@ -1286,7 +1286,7 @@ namespace MWScript interpreter.installSegment5 (opcodeGetPCCrimeLevel, new OpGetPCCrimeLevel); interpreter.installSegment5 (opcodeSetPCCrimeLevel, new OpSetPCCrimeLevel); interpreter.installSegment5 (opcodeModPCCrimeLevel, new OpModPCCrimeLevel); - + interpreter.installSegment5 (opcodeAddSpell, new OpAddSpell); interpreter.installSegment5 (opcodeAddSpellExplicit, new OpAddSpell); interpreter.installSegment5 (opcodeRemoveSpell, new OpRemoveSpell); diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 6a6ad92d75..2368ada6a0 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -173,6 +173,8 @@ namespace MWWorld void Scene::changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos) { + Nif::NIFFile::CacheLock cachelock; + mRendering.preCellChange(mCurrentCell); // remove active diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 7e0f1d7d38..f49b4bf9b5 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1286,12 +1286,12 @@ namespace MWWorld } } - void World::dropObjectOnGround (const Ptr& object) + void World::dropObjectOnGround (const Ptr& actor, const Ptr& object) { - MWWorld::Ptr::CellStore* cell = getPlayer().getPlayer().getCell(); + MWWorld::Ptr::CellStore* cell = actor.getCell(); ESM::Position pos = - getPlayer().getPlayer().getRefData().getPosition(); + actor.getRefData().getPosition(); Ogre::Vector3 orig = Ogre::Vector3(pos.pos[0], pos.pos[1], pos.pos[2]); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index e6d377e605..7e89c1d871 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -311,7 +311,7 @@ namespace MWWorld /// @param cursor Y (relative 0-1) /// @return true if the object was placed, or false if it was rejected because the position is too far away - virtual void dropObjectOnGround (const Ptr& object); + virtual void dropObjectOnGround (const Ptr& actor, const Ptr& object); virtual bool canPlaceObject(float cursorX, float cursorY); ///< @return true if it is possible to place on object at specified cursor location diff --git a/components/files/ogreplugin.cpp b/components/files/ogreplugin.cpp index ca90fd30e1..c319f77589 100644 --- a/components/files/ogreplugin.cpp +++ b/components/files/ogreplugin.cpp @@ -6,11 +6,6 @@ namespace Files { bool loadOgrePlugin(const std::string &pluginDir, std::string pluginName, Ogre::Root &ogreRoot) { - // Append plugin suffix if debugging. -#if defined(DEBUG) - pluginName = pluginName + OGRE_PLUGIN_DEBUG_SUFFIX; -#endif - #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE std::ostringstream verStream; verStream << "." << OGRE_VERSION_MAJOR << "." << OGRE_VERSION_MINOR << "." << OGRE_VERSION_PATCH; @@ -28,13 +23,28 @@ bool loadOgrePlugin(const std::string &pluginDir, std::string pluginName, Ogre:: pluginExt = ".so"; #endif - std::string pluginPath = pluginDir + "/" + pluginName + pluginExt; + // Append plugin suffix if debugging. + std::string pluginPath; +#if defined(DEBUG) + pluginPath = pluginDir + "/" + pluginName + OGRE_PLUGIN_DEBUG_SUFFIX + pluginExt; if (boost::filesystem::exists(pluginPath)) { - ogreRoot.loadPlugin(pluginPath); - return true; + ogreRoot.loadPlugin(pluginPath); + return true; } else { - return false; +#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 + return false; +#endif //OGRE_PLATFORM == OGRE_PLATFORM_WIN32 + } +#endif //defined(DEBUG) + + pluginPath = pluginDir + "/" + pluginName + pluginExt; + if (boost::filesystem::exists(pluginPath)) { + ogreRoot.loadPlugin(pluginPath); + return true; + } + else { + return false; } } diff --git a/components/nif/nif_file.cpp b/components/nif/nif_file.cpp index 3313d89ab1..e6d3182eda 100644 --- a/components/nif/nif_file.cpp +++ b/components/nif/nif_file.cpp @@ -34,9 +34,159 @@ #include "controller.hpp" #include -using namespace std; -using namespace Nif; -using namespace Misc; + +//TODO: when threading is needed, enable these +//#include +//#include + +namespace Nif +{ + +class NIFFile::LoadedCache +{ + //TODO: enable this to make cache thread safe... + //typedef boost::mutex mutex; + + struct mutex + { + void lock () {}; + void unlock () {} + }; + + typedef boost::lock_guard lock_guard; + typedef std::map < std::string, boost::weak_ptr > loaded_map; + typedef std::vector < boost::shared_ptr > locked_files; + + static int sLockLevel; + static mutex sProtector; + static loaded_map sLoadedMap; + static locked_files sLockedFiles; + +public: + + static ptr create (const std::string &name) + { + lock_guard _ (sProtector); + + ptr result; + + // lookup the resource + loaded_map::iterator i = sLoadedMap.find (name); + + if (i == sLoadedMap.end ()) // it doesn't existing currently, + { // or hasn't in the very near past + + // create it now, for smoother threading if needed, the + // loading should be performed outside of the sLoaderMap + // lock and an alternate mechanism should be used to + // synchronize threads competing to load the same resource + result = boost::make_shared (name, psudo_private_modifier()); + + // if we are locking the cache add an extra reference + // to keep the file in memory + if (sLockLevel > 0) + sLockedFiles.push_back (result); + + // stash a reference to the resource so that future + // calls can benefit + sLoadedMap [name] = boost::weak_ptr (result); + } + else // it may (probably) still exists + { + // attempt to get the reference + result = i->second.lock (); + + if (!result) // resource is in the process of being destroyed + { + // create a new instance, to replace the one that has + // begun the irreversible process of being destroyed + result = boost::make_shared (name, psudo_private_modifier()); + + // respect the cache lock... + if (sLockLevel > 0) + sLockedFiles.push_back (result); + + // we potentially overwrite an expired pointer here + // but the other thread performing the delete on + // the previous copy of this resource will detect it + // and make sure not to erase the new reference + sLoadedMap [name] = boost::weak_ptr (result); + } + } + + // we made it! + return result; + } + + static void release (NIFFile * file) + { + lock_guard _ (sProtector); + + loaded_map::iterator i = sLoadedMap.find (file->filename); + + // its got to be in here, it just might not be us... + assert (i != sLoadedMap.end ()); + + // if weak_ptr is still expired, this resource hasn't been recreated + // between the initiation of the final release due to destruction + // of the last shared pointer and this thread acquiring the lock on + // the loader map + if (i->second.expired ()) + sLoadedMap.erase (i); + } + + static void lockCache () + { + lock_guard _ (sProtector); + + sLockLevel++; + } + + static void unlockCache () + { + locked_files resetList; + + { + lock_guard _ (sProtector); + + if (--sLockLevel) + sLockedFiles.swap(resetList); + } + + // this not necessary, but makes it clear that the + // deletion of the locked cache entries is being done + // outside the protection of sProtector + resetList.clear (); + } +}; + +int NIFFile::LoadedCache::sLockLevel = 0; +NIFFile::LoadedCache::mutex NIFFile::LoadedCache::sProtector; +NIFFile::LoadedCache::loaded_map NIFFile::LoadedCache::sLoadedMap; +NIFFile::LoadedCache::locked_files NIFFile::LoadedCache::sLockedFiles; + +// these three calls are forwarded to the cache implementation... +void NIFFile::lockCache () { LoadedCache::lockCache (); } +void NIFFile::unlockCache () { LoadedCache::unlockCache (); } +NIFFile::ptr NIFFile::create (const std::string &name) { return LoadedCache::create (name); } + +/// Open a NIF stream. The name is used for error messages. +NIFFile::NIFFile(const std::string &name, psudo_private_modifier) + : filename(name) +{ + inp = Ogre::ResourceGroupManager::getSingleton().openResource(name); + parse(); + // Make sure to close the file after it was loaded into memory + inp.setNull(); +} + +NIFFile::~NIFFile() +{ + LoadedCache::release (this); + + for(std::size_t i=0; irecType != RC_MISSING); r->recName = rec; + r->recIndex = i; records[i] = r; r->read(this); @@ -178,11 +329,8 @@ void NIFFile::parse() tree, but for the moment we ignore it. */ - // TODO: Set up kf file here first, if applicable. It needs its own - // code to link it up with the main NIF structure. - // Once parsing is done, do post-processing. - for(int i=0; ipost(this); } @@ -211,16 +359,18 @@ void NiSkinInstance::post(NIFFile *nif) } } -Ogre::Matrix4 Node::getLocalTransform() +Ogre::Matrix4 Node::getLocalTransform() const { Ogre::Matrix4 mat4(Ogre::Matrix4::IDENTITY); mat4.makeTransform(trafo.pos, Ogre::Vector3(trafo.scale), Ogre::Quaternion(trafo.rotation)); return mat4; } -Ogre::Matrix4 Node::getWorldTransform() +Ogre::Matrix4 Node::getWorldTransform() const { if(parent != NULL) return parent->getWorldTransform() * getLocalTransform(); return getLocalTransform(); } + +} diff --git a/components/nif/nif_file.hpp b/components/nif/nif_file.hpp index 23bccb0fe0..e8884cd4d4 100644 --- a/components/nif/nif_file.hpp +++ b/components/nif/nif_file.hpp @@ -37,6 +37,11 @@ #include #include +#include +#include +#include +#include + #include #include "record.hpp" @@ -93,6 +98,14 @@ class NIFFile return u.f; } + class LoadedCache; + friend class LoadedCache; + + // attempt to protect NIFFile from misuse... + struct psudo_private_modifier {}; // this dirty little trick should optimize out + NIFFile (NIFFile const &); + void operator = (NIFFile const &); + public: /// Used for error handling void fail(const std::string &msg) @@ -108,19 +121,21 @@ public: << "File: "< ptr; - ~NIFFile() + /// Open a NIF stream. The name is used for error messages. + NIFFile(const std::string &name, psudo_private_modifier); + ~NIFFile(); + + static ptr create (const std::string &name); + static void lockCache (); + static void unlockCache (); + + struct CacheLock { - for(std::size_t i=0; irecType == Nif::RC_NiNode) { @@ -164,8 +165,8 @@ bool ManualBulletShapeLoader::hasRootCollisionNode(Nif::Node* node) return false; } -void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags, - const Nif::Transformation *trafo,bool hasCollisionNode,bool isCollisionNode,bool raycastingOnly) +void ManualBulletShapeLoader::handleNode(Nif::Node const *node, int flags, + const Nif::Transformation *parentTrafo,bool hasCollisionNode,bool isCollisionNode,bool raycastingOnly) { // Accumulate the flags from all the child nodes. This works for all @@ -181,7 +182,7 @@ void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags, } // Check for extra data - Nif::Extra *e = node; + Nif::Extra const *e = node; while (!e->extra.empty()) { // Get the next extra data in the list @@ -208,23 +209,23 @@ void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags, } } + Nif::Transformation childTrafo = node->trafo; - if (trafo) + if (parentTrafo) { // Get a non-const reference to the node's data, since we're // overwriting it. TODO: Is this necessary? - Nif::Transformation &final = node->trafo; // For both position and rotation we have that: // final_vector = old_vector + old_rotation*new_vector*old_scale - final.pos = trafo->pos + trafo->rotation*final.pos*trafo->scale; + childTrafo.pos = parentTrafo->pos + parentTrafo->rotation*childTrafo.pos*parentTrafo->scale; // Merge the rotations together - final.rotation = trafo->rotation * final.rotation; + childTrafo.rotation = parentTrafo->rotation * childTrafo.rotation; // Scale - final.scale *= trafo->scale; + childTrafo.scale *= parentTrafo->scale; } @@ -232,7 +233,7 @@ void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags, { - btVector3 boxsize = getbtVector((node->boundXYZ)); + btVector3 boxsize = getbtVector(node->boundXYZ); cShape->boxTranslation = node->boundPos; cShape->boxRotation = node->boundRot; @@ -243,20 +244,20 @@ void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags, // For NiNodes, loop through children if (node->recType == Nif::RC_NiNode) { - Nif::NodeList &list = ((Nif::NiNode*)node)->children; + Nif::NodeList const &list = ((Nif::NiNode const *)node)->children; int n = list.length(); for (int i=0; itrafo,hasCollisionNode,isCollisionNode,raycastingOnly); + handleNode(list[i].getPtr(), flags,&childTrafo,hasCollisionNode,isCollisionNode,raycastingOnly); } } } else if (node->recType == Nif::RC_NiTriShape && (isCollisionNode || !hasCollisionNode)) { cShape->mCollide = !(flags&0x800); - handleNiTriShape(dynamic_cast(node), flags,node->trafo.rotation,node->trafo.pos,node->trafo.scale,raycastingOnly); + handleNiTriShape(dynamic_cast(node), flags,childTrafo.rotation,childTrafo.pos,childTrafo.scale,raycastingOnly); } else if(node->recType == Nif::RC_RootCollisionNode) { @@ -265,12 +266,12 @@ void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags, for (int i=0; itrafo, hasCollisionNode,true,raycastingOnly); + handleNode(list[i].getPtr(), flags,&childTrafo, hasCollisionNode,true,raycastingOnly); } } } -void ManualBulletShapeLoader::handleNiTriShape(Nif::NiTriShape *shape, int flags,Ogre::Matrix3 parentRot,Ogre::Vector3 parentPos,float parentScale, +void ManualBulletShapeLoader::handleNiTriShape(Nif::NiTriShape const *shape, int flags,Ogre::Matrix3 parentRot,Ogre::Vector3 parentPos,float parentScale, bool raycastingOnly) { assert(shape != NULL); diff --git a/components/nifbullet/bullet_nif_loader.hpp b/components/nifbullet/bullet_nif_loader.hpp index 2190fda1b8..520878ce1c 100644 --- a/components/nifbullet/bullet_nif_loader.hpp +++ b/components/nifbullet/bullet_nif_loader.hpp @@ -79,25 +79,25 @@ public: void load(const std::string &name,const std::string &group); private: - btQuaternion getbtQuat(Ogre::Matrix3 &m); + btQuaternion getbtQuat(Ogre::Matrix3 const &m); - btVector3 getbtVector(Ogre::Vector3 &v); + btVector3 getbtVector(Ogre::Vector3 const &v); /** *Parse a node. */ - void handleNode(Nif::Node *node, int flags, + void handleNode(Nif::Node const *node, int flags, const Nif::Transformation *trafo, bool hasCollisionNode,bool isCollisionNode,bool raycastingOnly); /** *Helper function */ - bool hasRootCollisionNode(Nif::Node* node); + bool hasRootCollisionNode(Nif::Node const * node); /** *convert a NiTriShape to a bullet trishape. */ - void handleNiTriShape(Nif::NiTriShape *shape, int flags,Ogre::Matrix3 parentRot,Ogre::Vector3 parentPos,float parentScales,bool raycastingOnly); + void handleNiTriShape(Nif::NiTriShape const *shape, int flags,Ogre::Matrix3 parentRot,Ogre::Vector3 parentPos,float parentScales,bool raycastingOnly); std::string resourceName; std::string resourceGroup; diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 6607bb0501..372c38e0fd 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -167,16 +167,16 @@ static void fail(const std::string &msg) } -static void buildAnimation(Ogre::Skeleton *skel, const std::string &name, const std::vector &ctrls, const std::vector &targets, float startTime, float stopTime) +static void buildAnimation(Ogre::Skeleton *skel, const std::string &name, const std::vector &ctrls, const std::vector &targets, float startTime, float stopTime) { Ogre::Animation *anim = skel->createAnimation(name, stopTime-startTime); for(size_t i = 0;i < ctrls.size();i++) { - Nif::NiKeyframeController *kfc = ctrls[i]; + const Nif::NiKeyframeController *kfc = ctrls[i]; if(kfc->data.empty()) continue; - Nif::NiKeyframeData *kf = kfc->data.getPtr(); + const Nif::NiKeyframeData *kf = kfc->data.getPtr(); /* Get the keyframes and make sure they're sorted first to last */ const Nif::QuaternionKeyList &quatkeys = kf->mRotations; @@ -308,7 +308,7 @@ static TextKeyMap extractTextKeys(const Nif::NiTextKeyExtraData *tk) } -void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, std::vector &ctrls, Ogre::Bone *parent=NULL) +void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, std::vector &ctrls, Ogre::Bone *parent=NULL) { if(node->recType == Nif::RC_NiTriShape) return; @@ -377,10 +377,11 @@ void loadResource(Ogre::Resource *resource) Ogre::Skeleton *skel = dynamic_cast(resource); OgreAssert(skel, "Attempting to load a skeleton into a non-skeleton resource!"); - Nif::NIFFile nif(skel->getName()); + Nif::NIFFile::ptr pnif(Nif::NIFFile::create (skel->getName())); + Nif::NIFFile & nif = *pnif.get (); const Nif::Node *node = dynamic_cast(nif.getRecord(0)); - std::vector ctrls; + std::vector ctrls; try { buildBones(skel, node, ctrls); } @@ -398,7 +399,7 @@ void loadResource(Ogre::Resource *resource) float maxtime = 0.0f; for(size_t i = 0;i < ctrls.size();i++) { - Nif::NiKeyframeController *ctrl = ctrls[i]; + const Nif::NiKeyframeController *ctrl = ctrls[i]; maxtime = std::max(maxtime, ctrl->timeStop); Nif::Named *target = dynamic_cast(ctrl->target.getPtr()); if(target != NULL) @@ -764,9 +765,10 @@ class NIFMeshLoader : Ogre::ManualResourceLoader { std::string mName; std::string mGroup; - std::string mShapeName; - std::string mMaterialName; + size_t mShapeIndex; std::string mSkelName; + std::string mMaterialName; + std::string mShapeName; void warn(const std::string &msg) { @@ -781,7 +783,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader // Convert NiTriShape to Ogre::SubMesh - void handleNiTriShape(Ogre::Mesh *mesh, Nif::NiTriShape *shape) + void handleNiTriShape(Ogre::Mesh *mesh, Nif::NiTriShape const *shape) { Ogre::SkeletonPtr skel; const Nif::NiTriShapeData *data = shape->data.getPtr(); @@ -871,7 +873,8 @@ class NIFMeshLoader : Ogre::ManualResourceLoader Ogre::VertexDeclaration *decl; int nextBuf = 0; - Ogre::SubMesh *sub = mesh->createSubMesh(shape->name); + Ogre::SubMesh *sub = ((mShapeName.length() > 0) ? mesh->createSubMesh(mShapeName) : + mesh->createSubMesh()); // Add vertices sub->useSharedVertices = false; @@ -976,18 +979,18 @@ class NIFMeshLoader : Ogre::ManualResourceLoader sub->setMaterialName(mMaterialName); } - bool findTriShape(Ogre::Mesh *mesh, Nif::Node *node) + bool findTriShape(Ogre::Mesh *mesh, Nif::Node const *node) { - if(node->recType == Nif::RC_NiTriShape && mShapeName == node->name) + if(node->recType == Nif::RC_NiTriShape && mShapeIndex == node->recIndex) { - handleNiTriShape(mesh, dynamic_cast(node)); + handleNiTriShape(mesh, dynamic_cast(node)); return true; } - Nif::NiNode *ninode = dynamic_cast(node); + const Nif::NiNode *ninode = dynamic_cast(node); if(ninode) { - Nif::NodeList &children = ninode->children; + Nif::NodeList const &children = ninode->children; for(size_t i = 0;i < children.length();i++) { if(!children[i].empty()) @@ -1008,7 +1011,7 @@ public: NIFMeshLoader() { } NIFMeshLoader(const std::string &name, const std::string &group, const std::string skelName) - : mName(name), mGroup(group), mSkelName(skelName) + : mName(name), mGroup(group), mShapeIndex(~(size_t)0), mSkelName(skelName) { } virtual void loadResource(Ogre::Resource *resource) @@ -1016,15 +1019,14 @@ public: Ogre::Mesh *mesh = dynamic_cast(resource); OgreAssert(mesh, "Attempting to load a mesh into a non-mesh resource!"); - if(!mShapeName.length()) + Nif::NIFFile::ptr nif = Nif::NIFFile::create(mName); + if(mShapeIndex >= nif->numRecords()) { - if(mSkelName.length() > 0) - mesh->setSkeletonName(mSkelName); + mesh->setSkeletonName(mSkelName); return; } - Nif::NIFFile nif(mName); - Nif::Node *node = dynamic_cast(nif.getRecord(0)); + Nif::Node const *node = dynamic_cast(nif->getRecord(mShapeIndex)); findTriShape(mesh, node); } @@ -1065,9 +1067,12 @@ public: if(node->recType == Nif::RC_NiTriShape) { const Nif::NiTriShape *shape = dynamic_cast(node); + mShapeName = shape->name; Ogre::MeshManager &meshMgr = Ogre::MeshManager::getSingleton(); - std::string fullname = mName+"@shape="+shape->name; + std::string fullname = mName+"@index="+Ogre::StringConverter::toString(shape->recIndex); + if(mShapeName.length() > 0) + fullname += "@shape="+mShapeName; if(mSkelName.length() > 0 && mName != mSkelName) fullname += "@skel="+mSkelName; @@ -1079,7 +1084,7 @@ public: *loader = *this; if(!(flags&0x01)) // Not hidden { - loader->mShapeName = shape->name; + loader->mShapeIndex = shape->recIndex; loader->mMaterialName = NIFMaterialLoader::getMaterial(shape, fullname, mGroup); } @@ -1119,18 +1124,19 @@ MeshInfoList Loader::load(const std::string &name, const std::string &skelName, return meshiter->second; MeshInfoList &meshes = sMeshInfoMap[name+"@skel="+skelName]; - Nif::NIFFile nif(name); - if (nif.numRecords() < 1) + Nif::NIFFile::ptr pnif = Nif::NIFFile::create(name); + Nif::NIFFile &nif = *pnif.get(); + if(nif.numRecords() < 1) { nif.warn("Found no NIF records in "+name+"."); return meshes; } // The first record is assumed to be the root node - Nif::Record *r = nif.getRecord(0); + Nif::Record const *r = nif.getRecord(0); assert(r != NULL); - Nif::Node *node = dynamic_cast(r); + Nif::Node const *node = dynamic_cast(r); if(node == NULL) { nif.warn("First record in "+name+" was not a node, but a "+ diff --git a/credits.txt b/credits.txt index e1905c88b5..878cbf9153 100644 --- a/credits.txt +++ b/credits.txt @@ -118,5 +118,5 @@ for the open-source EB Garamond fontface. Thanks to Dongle, for his Daedric fontface, see Daedric Font License.txt for his license terms. -Thanks to Bitstream Inc. -for their Bitstream Vera fontface, see Bitstream Vera License.txt for their license terms. +Thanks to DejaVu team, +for their DejaVuLGCSansMono fontface, see Dejavu_lgc_font_license.txt for their license terms. diff --git a/files/mygui/CMakeLists.txt b/files/mygui/CMakeLists.txt index 871be93d1d..e7e5b695e1 100644 --- a/files/mygui/CMakeLists.txt +++ b/files/mygui/CMakeLists.txt @@ -80,7 +80,7 @@ set(MYGUI_FILES openmw_travel_window.layout openmw_persuasion_dialog.layout smallbars.png - VeraMono.ttf + DejaVuLGCSansMono.ttf markers.png ) diff --git a/files/mygui/DejaVuLGCSansMono.ttf b/files/mygui/DejaVuLGCSansMono.ttf new file mode 100644 index 0000000000..80c45b73e9 Binary files /dev/null and b/files/mygui/DejaVuLGCSansMono.ttf differ diff --git a/files/mygui/VeraMono.ttf b/files/mygui/VeraMono.ttf deleted file mode 100644 index 139f0b4311..0000000000 Binary files a/files/mygui/VeraMono.ttf and /dev/null differ diff --git a/files/mygui/openmw_font.xml b/files/mygui/openmw_font.xml index cb5dd648f8..0383c99427 100644 --- a/files/mygui/openmw_font.xml +++ b/files/mygui/openmw_font.xml @@ -35,7 +35,7 @@ - +