forked from teamnwah/openmw-tes3coop
Merge remote-tracking branch 'zini/master' into animation2
Conflicts: components/nifogre/ogre_nif_loader.cpp
This commit is contained in:
commit
94e30199d1
37 changed files with 598 additions and 289 deletions
|
@ -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.
|
|
99
Dejavu_lgc_font_license.txt
Normal file
99
Dejavu_lgc_font_license.txt
Normal file
|
@ -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 $
|
|
@ -240,18 +240,9 @@ void OMW::Engine::setNewGame(bool newGame)
|
||||||
mNewGame = newGame;
|
mNewGame = newGame;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialise and enter main loop.
|
std::string OMW::Engine::loadSettings (Settings::Manager & settings)
|
||||||
|
|
||||||
void OMW::Engine::go()
|
|
||||||
{
|
{
|
||||||
assert (!mCellName.empty());
|
|
||||||
assert (!mMaster.empty());
|
|
||||||
assert (!mOgre);
|
|
||||||
|
|
||||||
mOgre = new OEngine::Render::OgreRenderer;
|
|
||||||
|
|
||||||
// Create the settings manager and load default settings file
|
// 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 localdefault = mCfgMgr.getLocalPath().string() + "/settings-default.cfg";
|
||||||
const std::string globaldefault = mCfgMgr.getGlobalPath().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))
|
else if (boost::filesystem::exists(globaldefault))
|
||||||
settings.loadUser(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");
|
mFpsLevel = settings.getInt("fps", "HUD");
|
||||||
|
|
||||||
// load nif overrides
|
// load nif overrides
|
||||||
|
@ -285,6 +272,13 @@ void OMW::Engine::go()
|
||||||
else if (boost::filesystem::exists(mCfgMgr.getGlobalPath().string() + "/transparency-overrides.cfg"))
|
else if (boost::filesystem::exists(mCfgMgr.getGlobalPath().string() + "/transparency-overrides.cfg"))
|
||||||
nifOverrides.loadTransparencyOverrides(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");
|
std::string renderSystem = settings.getString("render system", "Video");
|
||||||
if (renderSystem == "")
|
if (renderSystem == "")
|
||||||
{
|
{
|
||||||
|
@ -294,6 +288,9 @@ void OMW::Engine::go()
|
||||||
renderSystem = "OpenGL Rendering Subsystem";
|
renderSystem = "OpenGL Rendering Subsystem";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mOgre = new OEngine::Render::OgreRenderer;
|
||||||
|
|
||||||
mOgre->configure(
|
mOgre->configure(
|
||||||
mCfgMgr.getLogPath().string(),
|
mCfgMgr.getLogPath().string(),
|
||||||
renderSystem,
|
renderSystem,
|
||||||
|
@ -328,16 +325,13 @@ void OMW::Engine::go()
|
||||||
// cursor replacer (converts the cursor from the bsa so they can be used by mygui)
|
// cursor replacer (converts the cursor from the bsa so they can be used by mygui)
|
||||||
MWGui::CursorReplace replacer;
|
MWGui::CursorReplace replacer;
|
||||||
|
|
||||||
// Create encoder
|
|
||||||
ToUTF8::Utf8Encoder encoder (mEncoding);
|
|
||||||
|
|
||||||
// Create the world
|
// Create the world
|
||||||
mEnvironment.setWorld (new MWWorld::World (*mOgre, mFileCollections, mMaster,
|
mEnvironment.setWorld (new MWWorld::World (*mOgre, mFileCollections, mMaster,
|
||||||
mResDir, mCfgMgr.getCachePath(), mNewGame, &encoder, mFallbackMap,
|
mResDir, mCfgMgr.getCachePath(), mNewGame, mEncoder, mFallbackMap,
|
||||||
mActivationDistanceOverride));
|
mActivationDistanceOverride));
|
||||||
|
|
||||||
//Load translation data
|
//Load translation data
|
||||||
mTranslationDataStorage.setEncoder(&encoder);
|
mTranslationDataStorage.setEncoder(mEncoder);
|
||||||
mTranslationDataStorage.loadTranslationData(mFileCollections, mMaster);
|
mTranslationDataStorage.loadTranslationData(mFileCollections, mMaster);
|
||||||
|
|
||||||
// Create window manager - this manages all the MW-specific GUI windows
|
// 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));
|
mEnvironment.setDialogueManager (new MWDialogue::DialogueManager (mExtensions, mVerboseScripts, mTranslationDataStorage));
|
||||||
|
|
||||||
// Sets up the input system
|
// 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,
|
mEnvironment.setInputManager (new MWInput::InputManager (*mOgre,
|
||||||
MWBase::Environment::get().getWorld()->getPlayer(),
|
MWBase::Environment::get().getWorld()->getPlayer(),
|
||||||
*MWBase::Environment::get().getWindowManager(), mDebug, *this, keybinderUser, keybinderUserExists));
|
*MWBase::Environment::get().getWindowManager(), mDebug, *this, keybinderUser, keybinderUserExists));
|
||||||
|
@ -388,13 +387,8 @@ void OMW::Engine::go()
|
||||||
MWBase::Environment::get().getWorld()->changeToInteriorCell (mCellName, pos);
|
MWBase::Environment::get().getWorld()->changeToInteriorCell (mCellName, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "\nPress Q/ESC or close window to exit.\n";
|
|
||||||
|
|
||||||
mOgre->getRoot()->addFrameListener (this);
|
mOgre->getRoot()->addFrameListener (this);
|
||||||
|
|
||||||
// Play some good 'ol tunes
|
|
||||||
MWBase::Environment::get().getSoundManager()->playPlaylist(std::string("Explore"));
|
|
||||||
|
|
||||||
// scripts
|
// scripts
|
||||||
if (mCompileAll)
|
if (mCompileAll)
|
||||||
{
|
{
|
||||||
|
@ -407,10 +401,35 @@ void OMW::Engine::go()
|
||||||
<< "%)"
|
<< "%)"
|
||||||
<< std::endl;
|
<< 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())
|
if (!mStartupScript.empty())
|
||||||
MWBase::Environment::get().getWindowManager()->executeInConsole (mStartupScript);
|
MWBase::Environment::get().getWindowManager()->executeInConsole (mStartupScript);
|
||||||
|
|
||||||
|
std::cout << "\nPress Q/ESC or close window to exit.\n";
|
||||||
|
|
||||||
// Start the main rendering loop
|
// Start the main rendering loop
|
||||||
mOgre->start();
|
mOgre->start();
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <components/compiler/extensions.hpp>
|
#include <components/compiler/extensions.hpp>
|
||||||
#include <components/files/collections.hpp>
|
#include <components/files/collections.hpp>
|
||||||
#include <components/translation/translation.hpp>
|
#include <components/translation/translation.hpp>
|
||||||
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
#include "mwbase/environment.hpp"
|
#include "mwbase/environment.hpp"
|
||||||
|
|
||||||
|
@ -61,6 +62,7 @@ namespace OMW
|
||||||
{
|
{
|
||||||
MWBase::Environment mEnvironment;
|
MWBase::Environment mEnvironment;
|
||||||
ToUTF8::FromType mEncoding;
|
ToUTF8::FromType mEncoding;
|
||||||
|
ToUTF8::Utf8Encoder* mEncoder;
|
||||||
Files::PathContainer mDataDirs;
|
Files::PathContainer mDataDirs;
|
||||||
boost::filesystem::path mResDir;
|
boost::filesystem::path mResDir;
|
||||||
OEngine::Render::OgreRenderer *mOgre;
|
OEngine::Render::OgreRenderer *mOgre;
|
||||||
|
@ -103,6 +105,12 @@ namespace OMW
|
||||||
|
|
||||||
virtual bool frameRenderingQueued (const Ogre::FrameEvent& evt);
|
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:
|
public:
|
||||||
Engine(Files::ConfigurationManager& configurationManager);
|
Engine(Files::ConfigurationManager& configurationManager);
|
||||||
virtual ~Engine();
|
virtual ~Engine();
|
||||||
|
|
|
@ -280,7 +280,7 @@ namespace MWBase
|
||||||
/// @param cursor Y (relative 0-1)
|
/// @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
|
/// @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;
|
virtual bool canPlaceObject (float cursorX, float cursorY) = 0;
|
||||||
///< @return true if it is possible to place on object at specified cursor location
|
///< @return true if it is possible to place on object at specified cursor location
|
||||||
|
|
|
@ -12,6 +12,9 @@
|
||||||
#include "../mwworld/cellstore.hpp"
|
#include "../mwworld/cellstore.hpp"
|
||||||
#include "../mwworld/physicssystem.hpp"
|
#include "../mwworld/physicssystem.hpp"
|
||||||
#include "../mwworld/actioneat.hpp"
|
#include "../mwworld/actioneat.hpp"
|
||||||
|
#include "../mwworld/player.hpp"
|
||||||
|
|
||||||
|
#include "../mwmechanics/npcstats.hpp"
|
||||||
|
|
||||||
#include "../mwgui/tooltips.hpp"
|
#include "../mwgui/tooltips.hpp"
|
||||||
|
|
||||||
|
@ -154,6 +157,10 @@ namespace MWClass
|
||||||
text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script");
|
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;
|
MWGui::Widgets::SpellEffectList list;
|
||||||
for (int i=0; i<4; ++i)
|
for (int i=0; i<4; ++i)
|
||||||
{
|
{
|
||||||
|
@ -163,6 +170,12 @@ namespace MWClass
|
||||||
params.mEffectID = ref->mBase->mData.mEffectID[i];
|
params.mEffectID = ref->mBase->mData.mEffectID[i];
|
||||||
params.mAttribute = ref->mBase->mData.mAttributes[i];
|
params.mAttribute = ref->mBase->mData.mAttributes[i];
|
||||||
params.mSkill = ref->mBase->mData.mSkills[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);
|
list.push_back(params);
|
||||||
}
|
}
|
||||||
info.effects = list;
|
info.effects = list;
|
||||||
|
|
|
@ -220,7 +220,7 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender)
|
||||||
if (world->canPlaceObject(mouseX, mouseY))
|
if (world->canPlaceObject(mouseX, mouseY))
|
||||||
world->placeObject(object, mouseX, mouseY);
|
world->placeObject(object, mouseX, mouseY);
|
||||||
else
|
else
|
||||||
world->dropObjectOnGround(object);
|
world->dropObjectOnGround(world->getPlayer().getPlayer(), object);
|
||||||
|
|
||||||
MyGUI::PointerManager::getInstance().setPointer("arrow");
|
MyGUI::PointerManager::getInstance().setPointer("arrow");
|
||||||
|
|
||||||
|
|
|
@ -440,7 +440,7 @@ namespace MWGui
|
||||||
|
|
||||||
for (MWMechanics::Spells::TIterator it = spells.begin(); it != spells.end(); ++it)
|
for (MWMechanics::Spells::TIterator it = spells.begin(); it != spells.end(); ++it)
|
||||||
{
|
{
|
||||||
spellList.push_back(*it);
|
spellList.push_back (it->first);
|
||||||
}
|
}
|
||||||
|
|
||||||
const MWWorld::ESMStore &esmStore =
|
const MWWorld::ESMStore &esmStore =
|
||||||
|
|
|
@ -102,7 +102,7 @@ namespace MWGui
|
||||||
for (MWMechanics::Spells::TIterator iter = merchantSpells.begin(); iter!=merchantSpells.end(); ++iter)
|
for (MWMechanics::Spells::TIterator iter = merchantSpells.begin(); iter!=merchantSpells.end(); ++iter)
|
||||||
{
|
{
|
||||||
const ESM::Spell* spell =
|
const ESM::Spell* spell =
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find (*iter);
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find (iter->first);
|
||||||
|
|
||||||
if (spell->mData.mType!=ESM::Spell::ST_Spell)
|
if (spell->mData.mType!=ESM::Spell::ST_Spell)
|
||||||
continue; // don't try to sell diseases, curses or powers
|
continue; // don't try to sell diseases, curses or powers
|
||||||
|
@ -110,7 +110,7 @@ namespace MWGui
|
||||||
if (std::find (playerSpells.begin(), playerSpells.end(), *iter)!=playerSpells.end())
|
if (std::find (playerSpells.begin(), playerSpells.end(), *iter)!=playerSpells.end())
|
||||||
continue; // we have that spell already
|
continue; // we have that spell already
|
||||||
|
|
||||||
addSpell (*iter);
|
addSpell (iter->first);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateLabels();
|
updateLabels();
|
||||||
|
|
|
@ -436,7 +436,7 @@ namespace MWGui
|
||||||
for (MWMechanics::Spells::TIterator it = spells.begin(); it != spells.end(); ++it)
|
for (MWMechanics::Spells::TIterator it = spells.begin(); it != spells.end(); ++it)
|
||||||
{
|
{
|
||||||
const ESM::Spell* spell =
|
const ESM::Spell* spell =
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(*it);
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find (it->first);
|
||||||
|
|
||||||
// only normal spells count
|
// only normal spells count
|
||||||
if (spell->mData.mType != ESM::Spell::ST_Spell)
|
if (spell->mData.mType != ESM::Spell::ST_Spell)
|
||||||
|
|
|
@ -139,7 +139,7 @@ namespace MWGui
|
||||||
|
|
||||||
for (MWMechanics::Spells::TIterator it = spells.begin(); it != spells.end(); ++it)
|
for (MWMechanics::Spells::TIterator it = spells.begin(); it != spells.end(); ++it)
|
||||||
{
|
{
|
||||||
spellList.push_back(*it);
|
spellList.push_back (it->first);
|
||||||
}
|
}
|
||||||
|
|
||||||
const MWWorld::ESMStore &esmStore =
|
const MWWorld::ESMStore &esmStore =
|
||||||
|
|
|
@ -390,8 +390,13 @@ void MWSpellEffect::setSpellEffect(const SpellEffectParams& params)
|
||||||
|
|
||||||
void MWSpellEffect::updateWidgets()
|
void MWSpellEffect::updateWidgets()
|
||||||
{
|
{
|
||||||
if (!mWindowManager)
|
if (!mEffectParams.mKnown)
|
||||||
|
{
|
||||||
|
mTextWidget->setCaption ("?");
|
||||||
|
mRequestedWidth = mTextWidget->getTextSize().width + 24;
|
||||||
|
mImageWidget->setImageTexture ("");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const MWWorld::ESMStore &store =
|
const MWWorld::ESMStore &store =
|
||||||
MWBase::Environment::get().getWorld()->getStore();
|
MWBase::Environment::get().getWorld()->getStore();
|
||||||
|
@ -400,7 +405,6 @@ void MWSpellEffect::updateWidgets()
|
||||||
store.get<ESM::MagicEffect>().search(mEffectParams.mEffectID);
|
store.get<ESM::MagicEffect>().search(mEffectParams.mEffectID);
|
||||||
|
|
||||||
assert(magicEffect);
|
assert(magicEffect);
|
||||||
assert(mWindowManager);
|
|
||||||
|
|
||||||
std::string pt = mWindowManager->getGameSettingString("spoint", "");
|
std::string pt = mWindowManager->getGameSettingString("spoint", "");
|
||||||
std::string pts = mWindowManager->getGameSettingString("spoints", "");
|
std::string pts = mWindowManager->getGameSettingString("spoints", "");
|
||||||
|
|
|
@ -37,12 +37,15 @@ namespace MWGui
|
||||||
, mEffectID(-1)
|
, mEffectID(-1)
|
||||||
, mNoTarget(false)
|
, mNoTarget(false)
|
||||||
, mIsConstant(false)
|
, mIsConstant(false)
|
||||||
|
, mKnown(true)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mNoTarget; // potion effects for example have no target (target is always the player)
|
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 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
|
// value of -1 here means the effect is unknown to the player
|
||||||
short mEffectID;
|
short mEffectID;
|
||||||
|
|
||||||
|
|
|
@ -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<ESM::ENAMstruct>::const_iterator iter (list.mList.begin()); iter!=list.mList.end();
|
for (std::vector<ESM::ENAMstruct>::const_iterator iter (list.mList.begin()); iter!=list.mList.end();
|
||||||
++iter)
|
++iter)
|
||||||
|
@ -78,9 +78,13 @@ namespace MWMechanics
|
||||||
if (iter->mMagnMin>=iter->mMagnMax)
|
if (iter->mMagnMin>=iter->mMagnMax)
|
||||||
param.mMagnitude = iter->mMagnMin;
|
param.mMagnitude = iter->mMagnMin;
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (magnitude==-1)
|
||||||
|
magnitude = static_cast<float> (std::rand()) / RAND_MAX;
|
||||||
|
|
||||||
param.mMagnitude = static_cast<int> (
|
param.mMagnitude = static_cast<int> (
|
||||||
(iter->mMagnMax-iter->mMagnMin+1)*
|
(iter->mMagnMax-iter->mMagnMin+1)*magnitude + iter->mMagnMin);
|
||||||
(static_cast<float> (std::rand()) / RAND_MAX) + iter->mMagnMin);
|
}
|
||||||
|
|
||||||
add (*iter, param);
|
add (*iter, param);
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,8 @@ namespace MWMechanics
|
||||||
|
|
||||||
void add (const EffectKey& key, const EffectParam& param);
|
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);
|
MagicEffects& operator+= (const MagicEffects& effects);
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,19 @@
|
||||||
|
|
||||||
#include "spells.hpp"
|
#include "spells.hpp"
|
||||||
|
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include <cstdlib>
|
||||||
|
|
||||||
#include <components/esm/loadspel.hpp>
|
#include <components/esm/loadspel.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
#include "magiceffects.hpp"
|
#include "magiceffects.hpp"
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
void Spells::addSpell (const ESM::Spell *spell, MagicEffects& effects) const
|
|
||||||
{
|
|
||||||
effects.add (spell->mEffects);
|
|
||||||
}
|
|
||||||
|
|
||||||
Spells::TIterator Spells::begin() const
|
Spells::TIterator Spells::begin() const
|
||||||
{
|
{
|
||||||
return mSpells.begin();
|
return mSpells.begin();
|
||||||
|
@ -29,13 +26,13 @@ namespace MWMechanics
|
||||||
|
|
||||||
void Spells::add (const std::string& spellId)
|
void Spells::add (const std::string& spellId)
|
||||||
{
|
{
|
||||||
if (std::find (mSpells.begin(), mSpells.end(), spellId)==mSpells.end())
|
if (mSpells.find (spellId)==mSpells.end())
|
||||||
mSpells.push_back (spellId);
|
mSpells.insert (std::make_pair (spellId, static_cast<float> (std::rand()) / RAND_MAX));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Spells::remove (const std::string& spellId)
|
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())
|
if (iter!=mSpells.end())
|
||||||
mSpells.erase (iter);
|
mSpells.erase (iter);
|
||||||
|
@ -51,11 +48,11 @@ namespace MWMechanics
|
||||||
for (TIterator iter = mSpells.begin(); iter!=mSpells.end(); ++iter)
|
for (TIterator iter = mSpells.begin(); iter!=mSpells.end(); ++iter)
|
||||||
{
|
{
|
||||||
const ESM::Spell *spell =
|
const ESM::Spell *spell =
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find (*iter);
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find (iter->first);
|
||||||
|
|
||||||
if (spell->mData.mType==ESM::Spell::ST_Ability || spell->mData.mType==ESM::Spell::ST_Blight ||
|
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)
|
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;
|
return effects;
|
||||||
|
@ -81,7 +78,7 @@ namespace MWMechanics
|
||||||
for (TIterator iter = mSpells.begin(); iter!=mSpells.end(); ++iter)
|
for (TIterator iter = mSpells.begin(); iter!=mSpells.end(); ++iter)
|
||||||
{
|
{
|
||||||
const ESM::Spell *spell =
|
const ESM::Spell *spell =
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find (*iter);
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find (iter->first);
|
||||||
|
|
||||||
if (spell->mData.mFlags & ESM::Spell::ST_Disease)
|
if (spell->mData.mFlags & ESM::Spell::ST_Disease)
|
||||||
return true;
|
return true;
|
||||||
|
@ -95,7 +92,7 @@ namespace MWMechanics
|
||||||
for (TIterator iter = mSpells.begin(); iter!=mSpells.end(); ++iter)
|
for (TIterator iter = mSpells.begin(); iter!=mSpells.end(); ++iter)
|
||||||
{
|
{
|
||||||
const ESM::Spell *spell =
|
const ESM::Spell *spell =
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find (*iter);
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find (iter->first);
|
||||||
|
|
||||||
if (spell->mData.mFlags & ESM::Spell::ST_Blight)
|
if (spell->mData.mFlags & ESM::Spell::ST_Blight)
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef GAME_MWMECHANICS_SPELLS_H
|
#ifndef GAME_MWMECHANICS_SPELLS_H
|
||||||
#define GAME_MWMECHANICS_SPELLS_H
|
#define GAME_MWMECHANICS_SPELLS_H
|
||||||
|
|
||||||
#include <vector>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
|
@ -21,16 +21,14 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef std::vector<std::string> TContainer;
|
typedef std::map<std::string, float> TContainer; // ID, normalised magnitude
|
||||||
typedef TContainer::const_iterator TIterator;
|
typedef TContainer::const_iterator TIterator;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::vector<std::string> mSpells;
|
TContainer mSpells;
|
||||||
std::string mSelectedSpell;
|
std::string mSelectedSpell;
|
||||||
|
|
||||||
void addSpell (const ESM::Spell *, MagicEffects& effects) const;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
TIterator begin() const;
|
TIterator begin() const;
|
||||||
|
|
|
@ -181,10 +181,14 @@ namespace MWScript
|
||||||
runtime.pop();
|
runtime.pop();
|
||||||
|
|
||||||
std::vector<int> idleList;
|
std::vector<int> idleList;
|
||||||
for (unsigned int i=0; i<arg0; ++i) {
|
idleList.push_back (0); // why MW, why?
|
||||||
|
|
||||||
|
for (int i=2; i<10 && arg0; ++i)
|
||||||
|
{
|
||||||
Interpreter::Type_Integer idleValue = runtime[0].mFloat;
|
Interpreter::Type_Integer idleValue = runtime[0].mFloat;
|
||||||
idleList.push_back(idleValue);
|
idleList.push_back(idleValue);
|
||||||
runtime.pop();
|
runtime.pop();
|
||||||
|
--arg0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// discard additional arguments (reset), because we have no idea what they mean.
|
// discard additional arguments (reset), because we have no idea what they mean.
|
||||||
|
|
|
@ -311,4 +311,9 @@ op 0x20001f4: AddSoulGem, explicit reference
|
||||||
op 0x20001f5: RemoveSoulGem
|
op 0x20001f5: RemoveSoulGem
|
||||||
op 0x20001f6: RemoveSoulGem, explicit reference
|
op 0x20001f6: RemoveSoulGem, explicit reference
|
||||||
op 0x20001f7: PlayBink
|
op 0x20001f7: PlayBink
|
||||||
opcodes 0x20001f8-0x3ffffff unused
|
op 0x20001f8: Drop
|
||||||
|
op 0x20001f9: Drop, explicit reference
|
||||||
|
op 0x20001fa: DropSoulGem
|
||||||
|
op 0x20001fb: DropSoulGem, explicit reference
|
||||||
|
|
||||||
|
opcodes 0x20001fa-0x3ffffff unused
|
||||||
|
|
|
@ -383,6 +383,88 @@ namespace MWScript
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<class R>
|
||||||
|
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 R>
|
||||||
|
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 R>
|
template <class R>
|
||||||
class OpGetAttacked : public Interpreter::Opcode0
|
class OpGetAttacked : public Interpreter::Opcode0
|
||||||
{
|
{
|
||||||
|
@ -495,6 +577,10 @@ namespace MWScript
|
||||||
const int opcodeAddSoulGemExplicit = 0x20001f4;
|
const int opcodeAddSoulGemExplicit = 0x20001f4;
|
||||||
const int opcodeRemoveSoulGem = 0x20001f5;
|
const int opcodeRemoveSoulGem = 0x20001f5;
|
||||||
const int opcodeRemoveSoulGemExplicit = 0x20001f6;
|
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 opcodeGetAttacked = 0x20001d3;
|
||||||
const int opcodeGetAttackedExplicit = 0x20001d4;
|
const int opcodeGetAttackedExplicit = 0x20001d4;
|
||||||
const int opcodeGetWeaponDrawn = 0x20001d7;
|
const int opcodeGetWeaponDrawn = 0x20001d7;
|
||||||
|
@ -538,6 +624,8 @@ namespace MWScript
|
||||||
extensions.registerFunction ("geteffect", 'l', "l", opcodeGetEffect, opcodeGetEffectExplicit);
|
extensions.registerFunction ("geteffect", 'l', "l", opcodeGetEffect, opcodeGetEffectExplicit);
|
||||||
extensions.registerInstruction ("addsoulgem", "cc", opcodeAddSoulGem, opcodeAddSoulGemExplicit);
|
extensions.registerInstruction ("addsoulgem", "cc", opcodeAddSoulGem, opcodeAddSoulGemExplicit);
|
||||||
extensions.registerInstruction ("removesoulgem", "c", opcodeRemoveSoulGem, opcodeRemoveSoulGemExplicit);
|
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 ("getattacked", 'l', "", opcodeGetAttacked, opcodeGetAttackedExplicit);
|
||||||
extensions.registerFunction ("getweapondrawn", 'l', "", opcodeGetWeaponDrawn, opcodeGetWeaponDrawnExplicit);
|
extensions.registerFunction ("getweapondrawn", 'l', "", opcodeGetWeaponDrawn, opcodeGetWeaponDrawnExplicit);
|
||||||
extensions.registerFunction ("getspelleffects", 'l', "c", opcodeGetSpellEffects, opcodeGetSpellEffectsExplicit);
|
extensions.registerFunction ("getspelleffects", 'l', "c", opcodeGetSpellEffects, opcodeGetSpellEffectsExplicit);
|
||||||
|
@ -576,6 +664,10 @@ namespace MWScript
|
||||||
interpreter.installSegment5 (opcodeAddSoulGemExplicit, new OpAddSoulGem<ExplicitRef>);
|
interpreter.installSegment5 (opcodeAddSoulGemExplicit, new OpAddSoulGem<ExplicitRef>);
|
||||||
interpreter.installSegment5 (opcodeRemoveSoulGem, new OpRemoveSoulGem<ImplicitRef>);
|
interpreter.installSegment5 (opcodeRemoveSoulGem, new OpRemoveSoulGem<ImplicitRef>);
|
||||||
interpreter.installSegment5 (opcodeRemoveSoulGemExplicit, new OpRemoveSoulGem<ExplicitRef>);
|
interpreter.installSegment5 (opcodeRemoveSoulGemExplicit, new OpRemoveSoulGem<ExplicitRef>);
|
||||||
|
interpreter.installSegment5 (opcodeDrop, new OpDrop<ImplicitRef>);
|
||||||
|
interpreter.installSegment5 (opcodeDropExplicit, new OpDrop<ExplicitRef>);
|
||||||
|
interpreter.installSegment5 (opcodeDropSoulGem, new OpDropSoulGem<ImplicitRef>);
|
||||||
|
interpreter.installSegment5 (opcodeDropSoulGemExplicit, new OpDropSoulGem<ExplicitRef>);
|
||||||
interpreter.installSegment5 (opcodeGetAttacked, new OpGetAttacked<ImplicitRef>);
|
interpreter.installSegment5 (opcodeGetAttacked, new OpGetAttacked<ImplicitRef>);
|
||||||
interpreter.installSegment5 (opcodeGetAttackedExplicit, new OpGetAttacked<ExplicitRef>);
|
interpreter.installSegment5 (opcodeGetAttackedExplicit, new OpGetAttacked<ExplicitRef>);
|
||||||
interpreter.installSegment5 (opcodeGetWeaponDrawn, new OpGetWeaponDrawn<ImplicitRef>);
|
interpreter.installSegment5 (opcodeGetWeaponDrawn, new OpGetWeaponDrawn<ImplicitRef>);
|
||||||
|
|
|
@ -485,7 +485,7 @@ namespace MWScript
|
||||||
for (MWMechanics::Spells::TIterator iter (
|
for (MWMechanics::Spells::TIterator iter (
|
||||||
MWWorld::Class::get (ptr).getCreatureStats (ptr).getSpells().begin());
|
MWWorld::Class::get (ptr).getCreatureStats (ptr).getSpells().begin());
|
||||||
iter!=MWWorld::Class::get (ptr).getCreatureStats (ptr).getSpells().end(); ++iter)
|
iter!=MWWorld::Class::get (ptr).getCreatureStats (ptr).getSpells().end(); ++iter)
|
||||||
if (*iter==id)
|
if (iter->first==id)
|
||||||
{
|
{
|
||||||
value = 1;
|
value = 1;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -173,6 +173,8 @@ namespace MWWorld
|
||||||
|
|
||||||
void Scene::changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos)
|
void Scene::changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos)
|
||||||
{
|
{
|
||||||
|
Nif::NIFFile::CacheLock cachelock;
|
||||||
|
|
||||||
mRendering.preCellChange(mCurrentCell);
|
mRendering.preCellChange(mCurrentCell);
|
||||||
|
|
||||||
// remove active
|
// remove active
|
||||||
|
|
|
@ -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 =
|
ESM::Position pos =
|
||||||
getPlayer().getPlayer().getRefData().getPosition();
|
actor.getRefData().getPosition();
|
||||||
|
|
||||||
Ogre::Vector3 orig =
|
Ogre::Vector3 orig =
|
||||||
Ogre::Vector3(pos.pos[0], pos.pos[1], pos.pos[2]);
|
Ogre::Vector3(pos.pos[0], pos.pos[1], pos.pos[2]);
|
||||||
|
|
|
@ -311,7 +311,7 @@ namespace MWWorld
|
||||||
/// @param cursor Y (relative 0-1)
|
/// @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
|
/// @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);
|
virtual bool canPlaceObject(float cursorX, float cursorY);
|
||||||
///< @return true if it is possible to place on object at specified cursor location
|
///< @return true if it is possible to place on object at specified cursor location
|
||||||
|
|
|
@ -6,11 +6,6 @@
|
||||||
namespace Files {
|
namespace Files {
|
||||||
|
|
||||||
bool loadOgrePlugin(const std::string &pluginDir, std::string pluginName, Ogre::Root &ogreRoot) {
|
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
|
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
|
||||||
std::ostringstream verStream;
|
std::ostringstream verStream;
|
||||||
verStream << "." << OGRE_VERSION_MAJOR << "." << OGRE_VERSION_MINOR << "." << OGRE_VERSION_PATCH;
|
verStream << "." << OGRE_VERSION_MAJOR << "." << OGRE_VERSION_MINOR << "." << OGRE_VERSION_PATCH;
|
||||||
|
@ -28,7 +23,22 @@ bool loadOgrePlugin(const std::string &pluginDir, std::string pluginName, Ogre::
|
||||||
pluginExt = ".so";
|
pluginExt = ".so";
|
||||||
#endif
|
#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;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
#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)) {
|
if (boost::filesystem::exists(pluginPath)) {
|
||||||
ogreRoot.loadPlugin(pluginPath);
|
ogreRoot.loadPlugin(pluginPath);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -34,9 +34,159 @@
|
||||||
#include "controller.hpp"
|
#include "controller.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
using namespace std;
|
|
||||||
using namespace Nif;
|
//TODO: when threading is needed, enable these
|
||||||
using namespace Misc;
|
//#include <boost/mutex.hpp>
|
||||||
|
//#include <boost/thread/locks.hpp>
|
||||||
|
|
||||||
|
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 <mutex> lock_guard;
|
||||||
|
typedef std::map < std::string, boost::weak_ptr <NIFFile> > loaded_map;
|
||||||
|
typedef std::vector < boost::shared_ptr <NIFFile> > 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 <NIFFile> (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 <NIFFile> (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 <NIFFile> (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 <NIFFile> (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; i<records.size(); i++)
|
||||||
|
delete records[i];
|
||||||
|
}
|
||||||
|
|
||||||
/* This file implements functions from the NIFFile class. It is also
|
/* This file implements functions from the NIFFile class. It is also
|
||||||
where we stash all the functions we couldn't add as inline
|
where we stash all the functions we couldn't add as inline
|
||||||
|
@ -56,7 +206,7 @@ void NIFFile::parse()
|
||||||
fail("Unsupported NIF version");
|
fail("Unsupported NIF version");
|
||||||
|
|
||||||
// Number of records
|
// Number of records
|
||||||
int recNum = getInt();
|
size_t recNum = getInt();
|
||||||
records.resize(recNum);
|
records.resize(recNum);
|
||||||
|
|
||||||
/* The format for 10.0.1.0 seems to be a bit different. After the
|
/* The format for 10.0.1.0 seems to be a bit different. After the
|
||||||
|
@ -68,7 +218,7 @@ void NIFFile::parse()
|
||||||
we do not support or plan to support other versions yet.
|
we do not support or plan to support other versions yet.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for(int i=0;i<recNum;i++)
|
for(size_t i = 0;i < recNum;i++)
|
||||||
{
|
{
|
||||||
std::string rec = getString();
|
std::string rec = getString();
|
||||||
//cout << i << ": " << rec.toString() << endl;
|
//cout << i << ": " << rec.toString() << endl;
|
||||||
|
@ -160,6 +310,7 @@ void NIFFile::parse()
|
||||||
assert(r != NULL);
|
assert(r != NULL);
|
||||||
assert(r->recType != RC_MISSING);
|
assert(r->recType != RC_MISSING);
|
||||||
r->recName = rec;
|
r->recName = rec;
|
||||||
|
r->recIndex = i;
|
||||||
records[i] = r;
|
records[i] = r;
|
||||||
r->read(this);
|
r->read(this);
|
||||||
|
|
||||||
|
@ -178,11 +329,8 @@ void NIFFile::parse()
|
||||||
tree, but for the moment we ignore it.
|
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.
|
// Once parsing is done, do post-processing.
|
||||||
for(int i=0; i<recNum; i++)
|
for(size_t i=0; i<recNum; i++)
|
||||||
records[i]->post(this);
|
records[i]->post(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);
|
Ogre::Matrix4 mat4(Ogre::Matrix4::IDENTITY);
|
||||||
mat4.makeTransform(trafo.pos, Ogre::Vector3(trafo.scale), Ogre::Quaternion(trafo.rotation));
|
mat4.makeTransform(trafo.pos, Ogre::Vector3(trafo.scale), Ogre::Quaternion(trafo.rotation));
|
||||||
return mat4;
|
return mat4;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ogre::Matrix4 Node::getWorldTransform()
|
Ogre::Matrix4 Node::getWorldTransform() const
|
||||||
{
|
{
|
||||||
if(parent != NULL)
|
if(parent != NULL)
|
||||||
return parent->getWorldTransform() * getLocalTransform();
|
return parent->getWorldTransform() * getLocalTransform();
|
||||||
return getLocalTransform();
|
return getLocalTransform();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -37,6 +37,11 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
#include <boost/weak_ptr.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
|
#include <boost/detail/endian.hpp>
|
||||||
|
|
||||||
#include <libs/platform/stdint.h>
|
#include <libs/platform/stdint.h>
|
||||||
|
|
||||||
#include "record.hpp"
|
#include "record.hpp"
|
||||||
|
@ -93,6 +98,14 @@ class NIFFile
|
||||||
return u.f;
|
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:
|
public:
|
||||||
/// Used for error handling
|
/// Used for error handling
|
||||||
void fail(const std::string &msg)
|
void fail(const std::string &msg)
|
||||||
|
@ -108,19 +121,21 @@ public:
|
||||||
<< "File: "<<filename <<std::endl;
|
<< "File: "<<filename <<std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Open a NIF stream. The name is used for error messages.
|
typedef boost::shared_ptr <NIFFile> ptr;
|
||||||
NIFFile(const std::string &name)
|
|
||||||
: filename(name)
|
|
||||||
{
|
|
||||||
inp = Ogre::ResourceGroupManager::getSingleton().openResource(name);
|
|
||||||
parse();
|
|
||||||
}
|
|
||||||
|
|
||||||
~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; i<records.size(); i++)
|
CacheLock () { lockCache (); }
|
||||||
delete records[i];
|
~CacheLock () { unlockCache (); }
|
||||||
}
|
};
|
||||||
|
|
||||||
/// Get a given record
|
/// Get a given record
|
||||||
Record *getRecord(size_t index)
|
Record *getRecord(size_t index)
|
||||||
|
@ -131,7 +146,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Number of records
|
/// Number of records
|
||||||
int numRecords() { return records.size(); }
|
size_t numRecords() { return records.size(); }
|
||||||
|
|
||||||
/*************************************************
|
/*************************************************
|
||||||
Parser functions
|
Parser functions
|
||||||
|
|
|
@ -111,8 +111,8 @@ public:
|
||||||
boneIndex = ind;
|
boneIndex = ind;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ogre::Matrix4 getLocalTransform();
|
Ogre::Matrix4 getLocalTransform() const;
|
||||||
Ogre::Matrix4 getWorldTransform();
|
Ogre::Matrix4 getWorldTransform() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiNode : Node
|
struct NiNode : Node
|
||||||
|
|
|
@ -91,8 +91,9 @@ struct Record
|
||||||
// Record type and type name
|
// Record type and type name
|
||||||
int recType;
|
int recType;
|
||||||
std::string recName;
|
std::string recName;
|
||||||
|
size_t recIndex;
|
||||||
|
|
||||||
Record() : recType(RC_MISSING) {}
|
Record() : recType(RC_MISSING), recIndex(~(size_t)0) {}
|
||||||
|
|
||||||
/// Parses the record from file
|
/// Parses the record from file
|
||||||
virtual void read(NIFFile *nif) = 0;
|
virtual void read(NIFFile *nif) = 0;
|
||||||
|
|
|
@ -51,7 +51,7 @@ ManualBulletShapeLoader::~ManualBulletShapeLoader()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
btQuaternion ManualBulletShapeLoader::getbtQuat(Ogre::Matrix3 &m)
|
btQuaternion ManualBulletShapeLoader::getbtQuat(Ogre::Matrix3 const &m)
|
||||||
{
|
{
|
||||||
Ogre::Quaternion oquat(m);
|
Ogre::Quaternion oquat(m);
|
||||||
btQuaternion quat;
|
btQuaternion quat;
|
||||||
|
@ -62,7 +62,7 @@ btQuaternion ManualBulletShapeLoader::getbtQuat(Ogre::Matrix3 &m)
|
||||||
return quat;
|
return quat;
|
||||||
}
|
}
|
||||||
|
|
||||||
btVector3 ManualBulletShapeLoader::getbtVector(Ogre::Vector3 &v)
|
btVector3 ManualBulletShapeLoader::getbtVector(Ogre::Vector3 const &v)
|
||||||
{
|
{
|
||||||
return btVector3(v[0], v[1], v[2]);
|
return btVector3(v[0], v[1], v[2]);
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,8 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource)
|
||||||
// of the early stages of development. Right now we WANT to catch
|
// of the early stages of development. Right now we WANT to catch
|
||||||
// every error as early and intrusively as possible, as it's most
|
// every error as early and intrusively as possible, as it's most
|
||||||
// likely a sign of incomplete code rather than faulty input.
|
// likely a sign of incomplete code rather than faulty input.
|
||||||
Nif::NIFFile nif(resourceName.substr(0, resourceName.length()-7));
|
Nif::NIFFile::ptr pnif (Nif::NIFFile::create (resourceName.substr(0, resourceName.length()-7)));
|
||||||
|
Nif::NIFFile & nif = *pnif.get ();
|
||||||
if (nif.numRecords() < 1)
|
if (nif.numRecords() < 1)
|
||||||
{
|
{
|
||||||
warn("Found no records in NIF.");
|
warn("Found no records in NIF.");
|
||||||
|
@ -138,7 +139,7 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ManualBulletShapeLoader::hasRootCollisionNode(Nif::Node* node)
|
bool ManualBulletShapeLoader::hasRootCollisionNode(Nif::Node const * node)
|
||||||
{
|
{
|
||||||
if (node->recType == Nif::RC_NiNode)
|
if (node->recType == Nif::RC_NiNode)
|
||||||
{
|
{
|
||||||
|
@ -164,8 +165,8 @@ bool ManualBulletShapeLoader::hasRootCollisionNode(Nif::Node* node)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags,
|
void ManualBulletShapeLoader::handleNode(Nif::Node const *node, int flags,
|
||||||
const Nif::Transformation *trafo,bool hasCollisionNode,bool isCollisionNode,bool raycastingOnly)
|
const Nif::Transformation *parentTrafo,bool hasCollisionNode,bool isCollisionNode,bool raycastingOnly)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Accumulate the flags from all the child nodes. This works for all
|
// 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
|
// Check for extra data
|
||||||
Nif::Extra *e = node;
|
Nif::Extra const *e = node;
|
||||||
while (!e->extra.empty())
|
while (!e->extra.empty())
|
||||||
{
|
{
|
||||||
// Get the next extra data in the list
|
// 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
|
// Get a non-const reference to the node's data, since we're
|
||||||
// overwriting it. TODO: Is this necessary?
|
// overwriting it. TODO: Is this necessary?
|
||||||
Nif::Transformation &final = node->trafo;
|
|
||||||
|
|
||||||
// For both position and rotation we have that:
|
// For both position and rotation we have that:
|
||||||
// final_vector = old_vector + old_rotation*new_vector*old_scale
|
// 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
|
// Merge the rotations together
|
||||||
final.rotation = trafo->rotation * final.rotation;
|
childTrafo.rotation = parentTrafo->rotation * childTrafo.rotation;
|
||||||
|
|
||||||
// Scale
|
// 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->boxTranslation = node->boundPos;
|
||||||
cShape->boxRotation = node->boundRot;
|
cShape->boxRotation = node->boundRot;
|
||||||
|
|
||||||
|
@ -243,20 +244,20 @@ void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags,
|
||||||
// For NiNodes, loop through children
|
// For NiNodes, loop through children
|
||||||
if (node->recType == Nif::RC_NiNode)
|
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();
|
int n = list.length();
|
||||||
for (int i=0; i<n; i++)
|
for (int i=0; i<n; i++)
|
||||||
{
|
{
|
||||||
if (!list[i].empty())
|
if (!list[i].empty())
|
||||||
{
|
{
|
||||||
handleNode(list[i].getPtr(), flags,&node->trafo,hasCollisionNode,isCollisionNode,raycastingOnly);
|
handleNode(list[i].getPtr(), flags,&childTrafo,hasCollisionNode,isCollisionNode,raycastingOnly);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (node->recType == Nif::RC_NiTriShape && (isCollisionNode || !hasCollisionNode))
|
else if (node->recType == Nif::RC_NiTriShape && (isCollisionNode || !hasCollisionNode))
|
||||||
{
|
{
|
||||||
cShape->mCollide = !(flags&0x800);
|
cShape->mCollide = !(flags&0x800);
|
||||||
handleNiTriShape(dynamic_cast<Nif::NiTriShape*>(node), flags,node->trafo.rotation,node->trafo.pos,node->trafo.scale,raycastingOnly);
|
handleNiTriShape(dynamic_cast<Nif::NiTriShape const *>(node), flags,childTrafo.rotation,childTrafo.pos,childTrafo.scale,raycastingOnly);
|
||||||
}
|
}
|
||||||
else if(node->recType == Nif::RC_RootCollisionNode)
|
else if(node->recType == Nif::RC_RootCollisionNode)
|
||||||
{
|
{
|
||||||
|
@ -265,12 +266,12 @@ void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags,
|
||||||
for (int i=0; i<n; i++)
|
for (int i=0; i<n; i++)
|
||||||
{
|
{
|
||||||
if (!list[i].empty())
|
if (!list[i].empty())
|
||||||
handleNode(list[i].getPtr(), flags,&node->trafo, 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)
|
bool raycastingOnly)
|
||||||
{
|
{
|
||||||
assert(shape != NULL);
|
assert(shape != NULL);
|
||||||
|
|
|
@ -79,25 +79,25 @@ public:
|
||||||
void load(const std::string &name,const std::string &group);
|
void load(const std::string &name,const std::string &group);
|
||||||
|
|
||||||
private:
|
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.
|
*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);
|
const Nif::Transformation *trafo, bool hasCollisionNode,bool isCollisionNode,bool raycastingOnly);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*Helper function
|
*Helper function
|
||||||
*/
|
*/
|
||||||
bool hasRootCollisionNode(Nif::Node* node);
|
bool hasRootCollisionNode(Nif::Node const * node);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*convert a NiTriShape to a bullet trishape.
|
*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 resourceName;
|
||||||
std::string resourceGroup;
|
std::string resourceGroup;
|
||||||
|
|
|
@ -167,16 +167,16 @@ static void fail(const std::string &msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void buildAnimation(Ogre::Skeleton *skel, const std::string &name, const std::vector<Nif::NiKeyframeController*> &ctrls, const std::vector<std::string> &targets, float startTime, float stopTime)
|
static void buildAnimation(Ogre::Skeleton *skel, const std::string &name, const std::vector<const Nif::NiKeyframeController*> &ctrls, const std::vector<std::string> &targets, float startTime, float stopTime)
|
||||||
{
|
{
|
||||||
Ogre::Animation *anim = skel->createAnimation(name, stopTime-startTime);
|
Ogre::Animation *anim = skel->createAnimation(name, stopTime-startTime);
|
||||||
|
|
||||||
for(size_t i = 0;i < ctrls.size();i++)
|
for(size_t i = 0;i < ctrls.size();i++)
|
||||||
{
|
{
|
||||||
Nif::NiKeyframeController *kfc = ctrls[i];
|
const Nif::NiKeyframeController *kfc = ctrls[i];
|
||||||
if(kfc->data.empty())
|
if(kfc->data.empty())
|
||||||
continue;
|
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 */
|
/* Get the keyframes and make sure they're sorted first to last */
|
||||||
const Nif::QuaternionKeyList &quatkeys = kf->mRotations;
|
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<Nif::NiKeyframeController*> &ctrls, Ogre::Bone *parent=NULL)
|
void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, std::vector<Nif::NiKeyframeController const*> &ctrls, Ogre::Bone *parent=NULL)
|
||||||
{
|
{
|
||||||
if(node->recType == Nif::RC_NiTriShape)
|
if(node->recType == Nif::RC_NiTriShape)
|
||||||
return;
|
return;
|
||||||
|
@ -377,10 +377,11 @@ void loadResource(Ogre::Resource *resource)
|
||||||
Ogre::Skeleton *skel = dynamic_cast<Ogre::Skeleton*>(resource);
|
Ogre::Skeleton *skel = dynamic_cast<Ogre::Skeleton*>(resource);
|
||||||
OgreAssert(skel, "Attempting to load a skeleton into a non-skeleton 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<const Nif::Node*>(nif.getRecord(0));
|
const Nif::Node *node = dynamic_cast<const Nif::Node*>(nif.getRecord(0));
|
||||||
|
|
||||||
std::vector<Nif::NiKeyframeController*> ctrls;
|
std::vector<const Nif::NiKeyframeController*> ctrls;
|
||||||
try {
|
try {
|
||||||
buildBones(skel, node, ctrls);
|
buildBones(skel, node, ctrls);
|
||||||
}
|
}
|
||||||
|
@ -398,7 +399,7 @@ void loadResource(Ogre::Resource *resource)
|
||||||
float maxtime = 0.0f;
|
float maxtime = 0.0f;
|
||||||
for(size_t i = 0;i < ctrls.size();i++)
|
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);
|
maxtime = std::max(maxtime, ctrl->timeStop);
|
||||||
Nif::Named *target = dynamic_cast<Nif::Named*>(ctrl->target.getPtr());
|
Nif::Named *target = dynamic_cast<Nif::Named*>(ctrl->target.getPtr());
|
||||||
if(target != NULL)
|
if(target != NULL)
|
||||||
|
@ -764,9 +765,10 @@ class NIFMeshLoader : Ogre::ManualResourceLoader
|
||||||
{
|
{
|
||||||
std::string mName;
|
std::string mName;
|
||||||
std::string mGroup;
|
std::string mGroup;
|
||||||
std::string mShapeName;
|
size_t mShapeIndex;
|
||||||
std::string mMaterialName;
|
|
||||||
std::string mSkelName;
|
std::string mSkelName;
|
||||||
|
std::string mMaterialName;
|
||||||
|
std::string mShapeName;
|
||||||
|
|
||||||
void warn(const std::string &msg)
|
void warn(const std::string &msg)
|
||||||
{
|
{
|
||||||
|
@ -781,7 +783,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader
|
||||||
|
|
||||||
|
|
||||||
// Convert NiTriShape to Ogre::SubMesh
|
// 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;
|
Ogre::SkeletonPtr skel;
|
||||||
const Nif::NiTriShapeData *data = shape->data.getPtr();
|
const Nif::NiTriShapeData *data = shape->data.getPtr();
|
||||||
|
@ -871,7 +873,8 @@ class NIFMeshLoader : Ogre::ManualResourceLoader
|
||||||
Ogre::VertexDeclaration *decl;
|
Ogre::VertexDeclaration *decl;
|
||||||
int nextBuf = 0;
|
int nextBuf = 0;
|
||||||
|
|
||||||
Ogre::SubMesh *sub = mesh->createSubMesh(shape->name);
|
Ogre::SubMesh *sub = ((mShapeName.length() > 0) ? mesh->createSubMesh(mShapeName) :
|
||||||
|
mesh->createSubMesh());
|
||||||
|
|
||||||
// Add vertices
|
// Add vertices
|
||||||
sub->useSharedVertices = false;
|
sub->useSharedVertices = false;
|
||||||
|
@ -976,18 +979,18 @@ class NIFMeshLoader : Ogre::ManualResourceLoader
|
||||||
sub->setMaterialName(mMaterialName);
|
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<Nif::NiTriShape*>(node));
|
handleNiTriShape(mesh, dynamic_cast<const Nif::NiTriShape*>(node));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Nif::NiNode *ninode = dynamic_cast<Nif::NiNode*>(node);
|
const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(node);
|
||||||
if(ninode)
|
if(ninode)
|
||||||
{
|
{
|
||||||
Nif::NodeList &children = ninode->children;
|
Nif::NodeList const &children = ninode->children;
|
||||||
for(size_t i = 0;i < children.length();i++)
|
for(size_t i = 0;i < children.length();i++)
|
||||||
{
|
{
|
||||||
if(!children[i].empty())
|
if(!children[i].empty())
|
||||||
|
@ -1008,7 +1011,7 @@ public:
|
||||||
NIFMeshLoader()
|
NIFMeshLoader()
|
||||||
{ }
|
{ }
|
||||||
NIFMeshLoader(const std::string &name, const std::string &group, const std::string skelName)
|
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)
|
virtual void loadResource(Ogre::Resource *resource)
|
||||||
|
@ -1016,15 +1019,14 @@ public:
|
||||||
Ogre::Mesh *mesh = dynamic_cast<Ogre::Mesh*>(resource);
|
Ogre::Mesh *mesh = dynamic_cast<Ogre::Mesh*>(resource);
|
||||||
OgreAssert(mesh, "Attempting to load a mesh into a non-mesh 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Nif::NIFFile nif(mName);
|
Nif::Node const *node = dynamic_cast<const Nif::Node*>(nif->getRecord(mShapeIndex));
|
||||||
Nif::Node *node = dynamic_cast<Nif::Node*>(nif.getRecord(0));
|
|
||||||
findTriShape(mesh, node);
|
findTriShape(mesh, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1065,9 +1067,12 @@ public:
|
||||||
if(node->recType == Nif::RC_NiTriShape)
|
if(node->recType == Nif::RC_NiTriShape)
|
||||||
{
|
{
|
||||||
const Nif::NiTriShape *shape = dynamic_cast<const Nif::NiTriShape*>(node);
|
const Nif::NiTriShape *shape = dynamic_cast<const Nif::NiTriShape*>(node);
|
||||||
|
mShapeName = shape->name;
|
||||||
|
|
||||||
Ogre::MeshManager &meshMgr = Ogre::MeshManager::getSingleton();
|
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)
|
if(mSkelName.length() > 0 && mName != mSkelName)
|
||||||
fullname += "@skel="+mSkelName;
|
fullname += "@skel="+mSkelName;
|
||||||
|
|
||||||
|
@ -1079,7 +1084,7 @@ public:
|
||||||
*loader = *this;
|
*loader = *this;
|
||||||
if(!(flags&0x01)) // Not hidden
|
if(!(flags&0x01)) // Not hidden
|
||||||
{
|
{
|
||||||
loader->mShapeName = shape->name;
|
loader->mShapeIndex = shape->recIndex;
|
||||||
loader->mMaterialName = NIFMaterialLoader::getMaterial(shape, fullname, mGroup);
|
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;
|
return meshiter->second;
|
||||||
|
|
||||||
MeshInfoList &meshes = sMeshInfoMap[name+"@skel="+skelName];
|
MeshInfoList &meshes = sMeshInfoMap[name+"@skel="+skelName];
|
||||||
Nif::NIFFile nif(name);
|
Nif::NIFFile::ptr pnif = Nif::NIFFile::create(name);
|
||||||
if (nif.numRecords() < 1)
|
Nif::NIFFile &nif = *pnif.get();
|
||||||
|
if(nif.numRecords() < 1)
|
||||||
{
|
{
|
||||||
nif.warn("Found no NIF records in "+name+".");
|
nif.warn("Found no NIF records in "+name+".");
|
||||||
return meshes;
|
return meshes;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The first record is assumed to be the root node
|
// 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);
|
assert(r != NULL);
|
||||||
|
|
||||||
Nif::Node *node = dynamic_cast<Nif::Node*>(r);
|
Nif::Node const *node = dynamic_cast<Nif::Node const *>(r);
|
||||||
if(node == NULL)
|
if(node == NULL)
|
||||||
{
|
{
|
||||||
nif.warn("First record in "+name+" was not a node, but a "+
|
nif.warn("First record in "+name+" was not a node, but a "+
|
||||||
|
|
|
@ -118,5 +118,5 @@ for the open-source EB Garamond fontface.
|
||||||
Thanks to Dongle,
|
Thanks to Dongle,
|
||||||
for his Daedric fontface, see Daedric Font License.txt for his license terms.
|
for his Daedric fontface, see Daedric Font License.txt for his license terms.
|
||||||
|
|
||||||
Thanks to Bitstream Inc.
|
Thanks to DejaVu team,
|
||||||
for their Bitstream Vera fontface, see Bitstream Vera License.txt for their license terms.
|
for their DejaVuLGCSansMono fontface, see Dejavu_lgc_font_license.txt for their license terms.
|
||||||
|
|
|
@ -80,7 +80,7 @@ set(MYGUI_FILES
|
||||||
openmw_travel_window.layout
|
openmw_travel_window.layout
|
||||||
openmw_persuasion_dialog.layout
|
openmw_persuasion_dialog.layout
|
||||||
smallbars.png
|
smallbars.png
|
||||||
VeraMono.ttf
|
DejaVuLGCSansMono.ttf
|
||||||
markers.png
|
markers.png
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
BIN
files/mygui/DejaVuLGCSansMono.ttf
Normal file
BIN
files/mygui/DejaVuLGCSansMono.ttf
Normal file
Binary file not shown.
Binary file not shown.
|
@ -35,7 +35,7 @@
|
||||||
</Resource>
|
</Resource>
|
||||||
|
|
||||||
<Resource type="ResourceTrueTypeFont" name="MonoFont">
|
<Resource type="ResourceTrueTypeFont" name="MonoFont">
|
||||||
<Property key="Source" value="VeraMono.ttf"/>
|
<Property key="Source" value="DejaVuLGCSansMono.ttf"/>
|
||||||
<Property key="Size" value="18"/>
|
<Property key="Size" value="18"/>
|
||||||
<Property key="Resolution" value="50"/>
|
<Property key="Resolution" value="50"/>
|
||||||
<Property key="Antialias" value="false"/>
|
<Property key="Antialias" value="false"/>
|
||||||
|
|
Loading…
Reference in a new issue