1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-26 09:35:28 +00:00

Merge remote-tracking branch 'upstream/master' into static

This commit is contained in:
Brother Brick 2012-09-17 11:57:38 +02:00
commit 05c3936797
67 changed files with 1475 additions and 213 deletions

View File

@ -103,6 +103,7 @@ set(OENGINE_OGRE
${LIBDIR}/openengine/ogre/fader.cpp ${LIBDIR}/openengine/ogre/fader.cpp
${LIBDIR}/openengine/ogre/imagerotate.cpp ${LIBDIR}/openengine/ogre/imagerotate.cpp
${LIBDIR}/openengine/ogre/atlas.cpp ${LIBDIR}/openengine/ogre/atlas.cpp
${LIBDIR}/openengine/ogre/selectionbuffer.cpp
) )
set(OENGINE_GUI set(OENGINE_GUI
${LIBDIR}/openengine/gui/manager.cpp ${LIBDIR}/openengine/gui/manager.cpp
@ -512,6 +513,7 @@ if (WIN32)
4309 # Variable overflow, trying to store 128 in a signed char for example 4309 # Variable overflow, trying to store 128 in a signed char for example
4355 # Using 'this' in member initialization list 4355 # Using 'this' in member initialization list
4701 # Potentially uninitialized local variable used 4701 # Potentially uninitialized local variable used
4800 # Boolean optimization warning, e.g. myBool = (myInt != 0) instead of myBool = myInt
) )
foreach(d ${WARNINGS_DISABLE}) foreach(d ${WARNINGS_DISABLE})
@ -523,6 +525,7 @@ if (WIN32)
set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS ${WARNINGS}) set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS ${WARNINGS})
endif (BUILD_LAUNCHER) endif (BUILD_LAUNCHER)
set_target_properties(openmw PROPERTIES COMPILE_FLAGS ${WARNINGS}) set_target_properties(openmw PROPERTIES COMPILE_FLAGS ${WARNINGS})
set_target_properties(esmtool PROPERTIES COMPILE_FLAGS ${WARNINGS})
endif(MSVC) endif(MSVC)
# Same for MinGW # Same for MinGW

View File

@ -189,73 +189,8 @@ void DataFilesPage::setupConfig()
} }
bool DataFilesPage::setupDataFiles() void DataFilesPage::addDataFiles(Files::Collections &fileCollections, const QString &encoding)
{ {
// We use the Configuration Manager to retrieve the configuration values
boost::program_options::variables_map variables;
boost::program_options::options_description desc;
desc.add_options()
("data", boost::program_options::value<Files::PathContainer>()->default_value(Files::PathContainer(), "data")->multitoken())
("data-local", boost::program_options::value<std::string>()->default_value(""))
("fs-strict", boost::program_options::value<bool>()->implicit_value(true)->default_value(false))
("encoding", boost::program_options::value<std::string>()->default_value("win1252"));
mCfgMgr.readConfiguration(variables, desc);
// Put the paths in a boost::filesystem vector to use with Files::Collections
mDataDirs = Files::PathContainer(variables["data"].as<Files::PathContainer>());
std::string local = variables["data-local"].as<std::string>();
if (!local.empty()) {
mDataLocal.push_back(Files::PathContainer::value_type(local));
}
if (mDataDirs.size()>1)
mDataDirs.resize (1);
mCfgMgr.processPaths(mDataDirs);
while (mDataDirs.empty()) {
QMessageBox msgBox;
msgBox.setWindowTitle("Error detecting Morrowind installation");
msgBox.setIcon(QMessageBox::Warning);
msgBox.setStandardButtons(QMessageBox::Cancel);
msgBox.setText(tr("<br><b>Could not find the Data Files location</b><br><br> \
The directory containing the data files was not found.<br><br> \
Press \"Browse...\" to specify the location manually.<br>"));
QAbstractButton *dirSelectButton =
msgBox.addButton(tr("B&rowse..."), QMessageBox::ActionRole);
msgBox.exec();
if (msgBox.clickedButton() == dirSelectButton) {
// Show a custom dir selection dialog which only accepts valid dirs
QString selectedDir = FileDialog::getExistingDirectory(
this, tr("Select Data Files Directory"),
QDir::currentPath(),
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
// Add the user selected data directory
if (!selectedDir.isEmpty()) {
mDataDirs.push_back(Files::PathContainer::value_type(selectedDir.toStdString()));
mCfgMgr.processPaths(mDataDirs);
} else {
// Cancel from within the dir selection dialog
return false;
}
} else {
// Cancel
return false;
}
}
// Create a file collection for the data dirs
Files::Collections fileCollections(mDataDirs, !variables["fs-strict"].as<bool>());
// First we add all the master files // First we add all the master files
const Files::MultiDirCollection &esm = fileCollections.getCollection(".esm"); const Files::MultiDirCollection &esm = fileCollections.getCollection(".esm");
unsigned int i = 0; // Row number unsigned int i = 0; // Row number
@ -283,7 +218,7 @@ bool DataFilesPage::setupDataFiles()
ESMReader fileReader; ESMReader fileReader;
QStringList availableMasters; // Will contain all found masters QStringList availableMasters; // Will contain all found masters
fileReader.setEncoding(variables["encoding"].as<std::string>()); fileReader.setEncoding(encoding.toStdString());
fileReader.open(iter->second.string()); fileReader.open(iter->second.string());
// First we fill the availableMasters and the mMastersWidget // First we fill the availableMasters and the mMastersWidget
@ -350,10 +285,86 @@ bool DataFilesPage::setupDataFiles()
} catch(std::runtime_error &e) { } catch(std::runtime_error &e) {
// An error occurred while reading the .esp // An error occurred while reading the .esp
std::cerr << "Error reading .esp: " << e.what() << std::endl;
continue; continue;
} }
} }
}
bool DataFilesPage::setupDataFiles()
{
// We use the Configuration Manager to retrieve the configuration values
boost::program_options::variables_map variables;
boost::program_options::options_description desc;
desc.add_options()
("data", boost::program_options::value<Files::PathContainer>()->default_value(Files::PathContainer(), "data")->multitoken())
("data-local", boost::program_options::value<std::string>()->default_value(""))
("fs-strict", boost::program_options::value<bool>()->implicit_value(true)->default_value(false))
("encoding", boost::program_options::value<std::string>()->default_value("win1252"));
mCfgMgr.readConfiguration(variables, desc);
// Put the paths in a boost::filesystem vector to use with Files::Collections
mDataDirs = Files::PathContainer(variables["data"].as<Files::PathContainer>());
std::string local = variables["data-local"].as<std::string>();
if (!local.empty()) {
mDataLocal.push_back(Files::PathContainer::value_type(local));
}
mCfgMgr.processPaths(mDataDirs);
mCfgMgr.processPaths(mDataLocal);
while (mDataDirs.empty()) {
QMessageBox msgBox;
msgBox.setWindowTitle("Error detecting Morrowind installation");
msgBox.setIcon(QMessageBox::Warning);
msgBox.setStandardButtons(QMessageBox::Cancel);
msgBox.setText(tr("<br><b>Could not find the Data Files location</b><br><br> \
The directory containing the data files was not found.<br><br> \
Press \"Browse...\" to specify the location manually.<br>"));
QAbstractButton *dirSelectButton =
msgBox.addButton(tr("B&rowse..."), QMessageBox::ActionRole);
msgBox.exec();
if (msgBox.clickedButton() == dirSelectButton) {
// Show a custom dir selection dialog which only accepts valid dirs
QString selectedDir = FileDialog::getExistingDirectory(
this, tr("Select Data Files Directory"),
QDir::currentPath(),
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
// Add the user selected data directory
if (!selectedDir.isEmpty()) {
mDataDirs.push_back(Files::PathContainer::value_type(selectedDir.toStdString()));
mCfgMgr.processPaths(mDataDirs);
} else {
// Cancel from within the dir selection dialog
return false;
}
} else {
// Cancel
return false;
}
}
// Add the plugins in the data directories
Files::Collections dataCollections(mDataDirs, !variables["fs-strict"].as<bool>());
Files::Collections dataLocalCollections(mDataLocal, !variables["fs-strict"].as<bool>());
addDataFiles(dataCollections, QString::fromStdString(variables["encoding"].as<std::string>()));
addDataFiles(dataLocalCollections, QString::fromStdString(variables["encoding"].as<std::string>()));
mDataFilesModel->sort(0);
readConfig(); readConfig();
return true; return true;
} }
@ -1139,11 +1150,13 @@ void DataFilesPage::writeConfig(QString profile)
path = QString::fromStdString(it->string()); path = QString::fromStdString(it->string());
path.remove(QChar('\"')); path.remove(QChar('\"'));
QDir dir(path);
// Make sure the string is quoted when it contains spaces // Make sure the string is quoted when it contains spaces
if (path.contains(" ")) { if (path.contains(" ")) {
gameConfig << "data=\"" << path << "\"" << endl; gameConfig << "data=\"" << dir.absolutePath() << "\"" << endl;
} else { } else {
gameConfig << "data=" << path << endl; gameConfig << "data=" << dir.absolutePath() << endl;
} }
} }
@ -1152,10 +1165,12 @@ void DataFilesPage::writeConfig(QString profile)
path = QString::fromStdString(mDataLocal.front().string()); path = QString::fromStdString(mDataLocal.front().string());
path.remove(QChar('\"')); path.remove(QChar('\"'));
QDir dir(path);
if (path.contains(" ")) { if (path.contains(" ")) {
gameConfig << "data-local=\"" << path << "\"" << endl; gameConfig << "data-local=\"" << dir.absolutePath() << "\"" << endl;
} else { } else {
gameConfig << "data-local=" << path << endl; gameConfig << "data-local=" << dir.absolutePath() << endl;
} }
} }

View File

@ -89,6 +89,7 @@ private:
const QStringList checkedPlugins(); const QStringList checkedPlugins();
const QStringList selectedMasters(); const QStringList selectedMasters();
void addDataFiles(Files::Collections &fileCollections, const QString &encoding);
void addPlugins(const QModelIndex &index); void addPlugins(const QModelIndex &index);
void removePlugins(const QModelIndex &index); void removePlugins(const QModelIndex &index);
void uncheckPlugins(); void uncheckPlugins();

View File

@ -16,7 +16,7 @@ source_group(game FILES ${GAME} ${GAME_HEADER})
add_openmw_dir (mwrender add_openmw_dir (mwrender
renderingmanager debugging sky player animation npcanimation creatureanimation actors objects renderingmanager debugging sky player animation npcanimation creatureanimation actors objects
renderinginterface localmap occlusionquery terrain terrainmaterial water shadows renderinginterface localmap occlusionquery terrain terrainmaterial water shadows
compositors compositors characterpreview externalrendering
) )
add_openmw_dir (mwinput add_openmw_dir (mwinput
@ -29,7 +29,7 @@ add_openmw_dir (mwgui
map_window window_pinnable_base cursorreplace tooltips scrollwindow bookwindow list map_window window_pinnable_base cursorreplace tooltips scrollwindow bookwindow list
formatting inventorywindow container hud countdialog tradewindow settingswindow formatting inventorywindow container hud countdialog tradewindow settingswindow
confirmationdialog alchemywindow referenceinterface spellwindow mainmenu quickkeysmenu confirmationdialog alchemywindow referenceinterface spellwindow mainmenu quickkeysmenu
itemselection spellbuyingwindow loadingscreen itemselection spellbuyingwindow loadingscreen levelupdialog
) )
add_openmw_dir (mwdialogue add_openmw_dir (mwdialogue

View File

@ -118,7 +118,7 @@ namespace MWBase
/// Set value for the given ID. /// Set value for the given ID.
virtual void setValue (const std::string& id, const MWMechanics::Stat<int>& value) = 0; virtual void setValue (const std::string& id, const MWMechanics::Stat<int>& value) = 0;
virtual void setValue (int parSkill, const MWMechanics::Stat<float>& value) = 0; virtual void setValue (int parSkill, const MWMechanics::Stat<float>& value) = 0;
virtual void setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value) = 0; virtual void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value) = 0;
virtual void setValue (const std::string& id, const std::string& value) = 0; virtual void setValue (const std::string& id, const std::string& value) = 0;
virtual void setValue (const std::string& id, int value) = 0; virtual void setValue (const std::string& id, int value) = 0;
@ -219,6 +219,9 @@ namespace MWBase
virtual void setLoadingProgress (const std::string& stage, int depth, int current, int total) = 0; virtual void setLoadingProgress (const std::string& stage, int depth, int current, int total) = 0;
virtual void loadingDone() = 0; virtual void loadingDone() = 0;
virtual void enableRest() = 0;
virtual bool getRestEnabled() = 0;
}; };
} }

View File

@ -35,6 +35,11 @@ namespace ESMS
struct ESMStore; struct ESMStore;
} }
namespace MWRender
{
class ExternalRendering;
}
namespace MWWorld namespace MWWorld
{ {
class CellStore; class CellStore;
@ -271,6 +276,8 @@ namespace MWBase
virtual void togglePlayerLooking(bool enable) = 0; virtual void togglePlayerLooking(bool enable) = 0;
virtual void renderPlayer() = 0; virtual void renderPlayer() = 0;
virtual void setupExternalRendering (MWRender::ExternalRendering& rendering) = 0;
}; };
} }

View File

@ -151,7 +151,7 @@ void CharacterCreation::setValue (const std::string& id, const MWMechanics::Stat
} }
} }
void CharacterCreation::setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value) void CharacterCreation::setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value)
{ {
if (mReviewDialog) if (mReviewDialog)
{ {
@ -294,17 +294,17 @@ void CharacterCreation::spawnDialog(const char id)
} }
} }
void CharacterCreation::setPlayerHealth (const MWMechanics::DynamicStat<int>& value) void CharacterCreation::setPlayerHealth (const MWMechanics::DynamicStat<float>& value)
{ {
mPlayerHealth = value; mPlayerHealth = value;
} }
void CharacterCreation::setPlayerMagicka (const MWMechanics::DynamicStat<int>& value) void CharacterCreation::setPlayerMagicka (const MWMechanics::DynamicStat<float>& value)
{ {
mPlayerMagicka = value; mPlayerMagicka = value;
} }
void CharacterCreation::setPlayerFatigue (const MWMechanics::DynamicStat<int>& value) void CharacterCreation::setPlayerFatigue (const MWMechanics::DynamicStat<float>& value)
{ {
mPlayerFatigue = value; mPlayerFatigue = value;
} }

View File

@ -35,14 +35,14 @@ namespace MWGui
//Show a dialog //Show a dialog
void spawnDialog(const char id); void spawnDialog(const char id);
void setPlayerHealth (const MWMechanics::DynamicStat<int>& value); void setPlayerHealth (const MWMechanics::DynamicStat<float>& value);
void setPlayerMagicka (const MWMechanics::DynamicStat<int>& value); void setPlayerMagicka (const MWMechanics::DynamicStat<float>& value);
void setPlayerFatigue (const MWMechanics::DynamicStat<int>& value); void setPlayerFatigue (const MWMechanics::DynamicStat<float>& value);
void setValue (const std::string& id, const MWMechanics::Stat<int>& value); void setValue (const std::string& id, const MWMechanics::Stat<int>& value);
void setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value); void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value);
void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value); void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value);
void configureSkills (const SkillList& major, const SkillList& minor); void configureSkills (const SkillList& major, const SkillList& minor);
@ -65,9 +65,9 @@ namespace MWGui
std::string mPlayerRaceId; std::string mPlayerRaceId;
std::string mPlayerBirthSignId; std::string mPlayerBirthSignId;
ESM::Class mPlayerClass; ESM::Class mPlayerClass;
MWMechanics::DynamicStat<int> mPlayerHealth; MWMechanics::DynamicStat<float> mPlayerHealth;
MWMechanics::DynamicStat<int> mPlayerMagicka; MWMechanics::DynamicStat<float> mPlayerMagicka;
MWMechanics::DynamicStat<int> mPlayerFatigue; MWMechanics::DynamicStat<float> mPlayerFatigue;
//Class generation vars //Class generation vars
unsigned mGenerateClassStep; // Keeps track of current step in Generate Class dialog unsigned mGenerateClassStep; // Keeps track of current step in Generate Class dialog

View File

@ -161,7 +161,7 @@ void HUD::setEffect(const char *img)
mEffect1->setImageTexture(img); mEffect1->setImageTexture(img);
} }
void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat<int>& value) void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat<float>& value)
{ {
static const char *ids[] = static const char *ids[] =
{ {

View File

@ -14,7 +14,7 @@ namespace MWGui
public: public:
HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop); HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop);
void setEffect(const char *img); void setEffect(const char *img);
void setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value); void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value);
void setFPS(float fps); void setFPS(float fps);
void setTriangleCount(unsigned int count); void setTriangleCount(unsigned int count);
void setBatchCount(unsigned int count); void setBatchCount(unsigned int count);

View File

@ -44,10 +44,14 @@ namespace MWGui
: ContainerBase(dragAndDrop) : ContainerBase(dragAndDrop)
, WindowPinnableBase("openmw_inventory_window.layout", parWindowManager) , WindowPinnableBase("openmw_inventory_window.layout", parWindowManager)
, mTrading(false) , mTrading(false)
, mLastXSize(0)
, mLastYSize(0)
, mPreview(MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer ())
{ {
static_cast<MyGUI::Window*>(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &InventoryWindow::onWindowResize); static_cast<MyGUI::Window*>(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &InventoryWindow::onWindowResize);
getWidget(mAvatar, "Avatar"); getWidget(mAvatar, "Avatar");
getWidget(mAvatarImage, "AvatarImage");
getWidget(mEncumbranceBar, "EncumbranceBar"); getWidget(mEncumbranceBar, "EncumbranceBar");
getWidget(mEncumbranceText, "EncumbranceBarT"); getWidget(mEncumbranceText, "EncumbranceBarT");
getWidget(mFilterAll, "AllButton"); getWidget(mFilterAll, "AllButton");
@ -76,6 +80,8 @@ namespace MWGui
setCoord(0, 342, 498, 258); setCoord(0, 342, 498, 258);
MWBase::Environment::get().getWorld ()->setupExternalRendering (mPreview);
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
openContainer(player); openContainer(player);
} }
@ -89,6 +95,7 @@ namespace MWGui
mBoughtItems.clear(); mBoughtItems.clear();
onWindowResize(static_cast<MyGUI::Window*>(mMainWidget)); onWindowResize(static_cast<MyGUI::Window*>(mMainWidget));
drawItems();
} }
void InventoryWindow::onWindowResize(MyGUI::Window* _sender) void InventoryWindow::onWindowResize(MyGUI::Window* _sender)
@ -99,7 +106,13 @@ namespace MWGui
mRightPane->getPosition().top, mRightPane->getPosition().top,
_sender->getSize().width - 12 - (_sender->getSize().height-44) * aspect - 15, _sender->getSize().width - 12 - (_sender->getSize().height-44) * aspect - 15,
_sender->getSize().height-44 ); _sender->getSize().height-44 );
drawItems();
if (mMainWidget->getSize().width != mLastXSize || mMainWidget->getSize().height != mLastYSize)
{
drawItems();
mLastXSize = mMainWidget->getSize().width;
mLastYSize = mMainWidget->getSize().height;
}
} }
void InventoryWindow::onFilterChanged(MyGUI::Widget* _sender) void InventoryWindow::onFilterChanged(MyGUI::Widget* _sender)
@ -171,15 +184,45 @@ namespace MWGui
drawItems(); drawItems();
// update selected weapon icon notifyContentChanged();
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
MWWorld::ContainerStoreIterator weaponSlot = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
if (weaponSlot == invStore.end())
mWindowManager.unsetSelectedWeapon();
else
mWindowManager.setSelectedWeapon(*weaponSlot, 100); /// \todo track weapon durability
} }
else
{
MyGUI::IntPoint mousePos = MyGUI::InputManager::getInstance ().getLastPressedPosition (MyGUI::MouseButton::Left);
MyGUI::IntPoint relPos = mousePos - mAvatar->getAbsolutePosition ();
int realX = int(float(relPos.left) / float(mAvatar->getSize().width) * 512.f );
int realY = int(float(relPos.top) / float(mAvatar->getSize().height) * 1024.f );
MWWorld::Ptr itemSelected = getAvatarSelectedItem (realX, realY);
if (itemSelected.isEmpty ())
return;
for (unsigned int i=0; i < mContainerWidget->getChildCount (); ++i)
{
MyGUI::Widget* w = mContainerWidget->getChildAt (i);
if (*w->getUserData<MWWorld::Ptr>() == itemSelected)
{
onSelectedItem(w);
return;
}
}
}
}
MWWorld::Ptr InventoryWindow::getAvatarSelectedItem(int x, int y)
{
int slot = mPreview.getSlotSelected (x, y);
if (slot == -1)
return MWWorld::Ptr();
MWWorld::Ptr player = mPtr;
MWWorld::InventoryStore& invStore = MWWorld::Class::get(player).getInventoryStore(player);
if (invStore.getSlot(slot) != invStore.end())
return *invStore.getSlot (slot);
else
return MWWorld::Ptr();
} }
std::vector<MWWorld::Ptr> InventoryWindow::getEquippedItems() std::vector<MWWorld::Ptr> InventoryWindow::getEquippedItems()
@ -265,6 +308,12 @@ namespace MWGui
mWindowManager.unsetSelectedWeapon(); mWindowManager.unsetSelectedWeapon();
else else
mWindowManager.setSelectedWeapon(*weaponSlot, 100); /// \todo track weapon durability mWindowManager.setSelectedWeapon(*weaponSlot, 100); /// \todo track weapon durability
MyGUI::IntSize size = mAvatar->getSize();
mPreview.update (size.width, size.height);
mAvatarImage->setSize(MyGUI::IntSize(std::max(mAvatar->getSize().width, 512), std::max(mAvatar->getSize().height, 1024)));
mAvatarImage->setImageTexture("CharacterPreview");
} }
void InventoryWindow::pickUpObject (MWWorld::Ptr object) void InventoryWindow::pickUpObject (MWWorld::Ptr object)
@ -329,4 +378,9 @@ namespace MWGui
text->setCaption(getCountString(count)); text->setCaption(getCountString(count));
mDragAndDrop->mDraggedFrom = this; mDragAndDrop->mDraggedFrom = this;
} }
MyGUI::IntCoord InventoryWindow::getAvatarScreenCoord ()
{
return mAvatar->getAbsoluteCoord ();
}
} }

View File

@ -1,6 +1,8 @@
#ifndef MGUI_Inventory_H #ifndef MGUI_Inventory_H
#define MGUI_Inventory_H #define MGUI_Inventory_H
#include "../mwrender/characterpreview.hpp"
#include "container.hpp" #include "container.hpp"
#include "window_pinnable_base.hpp" #include "window_pinnable_base.hpp"
@ -22,8 +24,13 @@ namespace MWGui
int getPlayerGold(); int getPlayerGold();
MyGUI::IntCoord getAvatarScreenCoord();
MWWorld::Ptr getAvatarSelectedItem(int x, int y);
protected: protected:
MyGUI::Widget* mAvatar; MyGUI::Widget* mAvatar;
MyGUI::ImageBox* mAvatarImage;
MyGUI::TextBox* mArmorRating; MyGUI::TextBox* mArmorRating;
MyGUI::ProgressBar* mEncumbranceBar; MyGUI::ProgressBar* mEncumbranceBar;
MyGUI::TextBox* mEncumbranceText; MyGUI::TextBox* mEncumbranceText;
@ -37,6 +44,11 @@ namespace MWGui
MyGUI::Button* mFilterMagic; MyGUI::Button* mFilterMagic;
MyGUI::Button* mFilterMisc; MyGUI::Button* mFilterMisc;
int mLastXSize;
int mLastYSize;
MWRender::InventoryPreview mPreview;
bool mTrading; bool mTrading;
void onWindowResize(MyGUI::Window* _sender); void onWindowResize(MyGUI::Window* _sender);

View File

@ -0,0 +1,197 @@
#include "levelupdialog.hpp"
#include <boost/lexical_cast.hpp>
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/class.hpp"
#include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/npcstats.hpp"
#include "../mwmechanics/stat.hpp"
#include <components/esm_store/reclists.hpp>
#include <components/esm_store/store.hpp>
namespace MWGui
{
LevelupDialog::LevelupDialog(MWBase::WindowManager &parWindowManager)
: WindowBase("openmw_levelup_dialog.layout", parWindowManager)
{
getWidget(mOkButton, "OkButton");
getWidget(mClassImage, "ClassImage");
getWidget(mLevelText, "LevelText");
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &LevelupDialog::onOkButtonClicked);
for (int i=1; i<9; ++i)
{
MyGUI::TextBox* t;
getWidget(t, "AttribVal" + boost::lexical_cast<std::string>(i));
MyGUI::Button* b;
getWidget(b, "Attrib" + boost::lexical_cast<std::string>(i));
b->setUserData (i-1);
b->eventMouseButtonClick += MyGUI::newDelegate(this, &LevelupDialog::onAttributeClicked);
mAttributes.push_back(b);
mAttributeValues.push_back(t);
getWidget(t, "AttribMultiplier" + boost::lexical_cast<std::string>(i));
mAttributeMultipliers.push_back(t);
}
int curX = mMainWidget->getWidth()/2 - (16 + 2) * 1.5;
for (int i=0; i<3; ++i)
{
MyGUI::ImageBox* image = mMainWidget->createWidget<MyGUI::ImageBox>("ImageBox", MyGUI::IntCoord(curX,250,16,16), MyGUI::Align::Default);
image->setImageTexture ("icons\\tx_goldicon.dds");
curX += 24+2;
mCoins.push_back(image);
}
center();
}
void LevelupDialog::setAttributeValues()
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayer().getPlayer();
MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get(player).getCreatureStats (player);
MWMechanics::NpcStats& pcStats = MWWorld::Class::get(player).getNpcStats (player);
for (int i=0; i<8; ++i)
{
int val = creatureStats.getAttribute (i).getBase ();
if (std::find(mSpentAttributes.begin(), mSpentAttributes.end(), i) != mSpentAttributes.end())
{
val += pcStats.getLevelupAttributeMultiplier (i);
}
if (val >= 100)
val = 100;
mAttributeValues[i]->setCaption(boost::lexical_cast<std::string>(val));
}
}
void LevelupDialog::resetCoins ()
{
int curX = mMainWidget->getWidth()/2 - (16 + 2) * 1.5;
for (int i=0; i<3; ++i)
{
MyGUI::ImageBox* image = mCoins[i];
image->setCoord(MyGUI::IntCoord(curX,250,16,16));
curX += 24+2;
}
}
void LevelupDialog::assignCoins ()
{
resetCoins();
for (unsigned int i=0; i<mSpentAttributes.size(); ++i)
{
MyGUI::ImageBox* image = mCoins[i];
int attribute = mSpentAttributes[i];
int xdiff = mAttributeMultipliers[attribute]->getCaption() == "" ? 0 : 30;
MyGUI::IntPoint pos = mAttributes[attribute]->getAbsolutePosition() - mMainWidget->getAbsolutePosition() - MyGUI::IntPoint(24+xdiff,-4);
image->setPosition(pos);
}
setAttributeValues();
}
void LevelupDialog::open()
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayer().getPlayer();
MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get(player).getCreatureStats (player);
MWMechanics::NpcStats& pcStats = MWWorld::Class::get(player).getNpcStats (player);
center();
mSpentAttributes.clear();
resetCoins();
setAttributeValues();
// set class image
const ESM::Class& playerClass = MWBase::Environment::get().getWorld ()->getPlayer ().getClass ();
// retrieve the ID to this class
std::string classId;
std::map<std::string, ESM::Class> list = MWBase::Environment::get().getWorld()->getStore ().classes.list;
for (std::map<std::string, ESM::Class>::iterator it = list.begin(); it != list.end(); ++it)
{
if (playerClass.name == it->second.name)
classId = it->first;
}
mClassImage->setImageTexture ("textures\\levelup\\" + classId + ".dds");
/// \todo replace this with INI-imported texts
int level = creatureStats.getLevel ()+1;
mLevelText->setCaptionWithReplacing("#{sLevelUpMenu1} " + boost::lexical_cast<std::string>(level));
for (int i=0; i<8; ++i)
{
MyGUI::TextBox* text = mAttributeMultipliers[i];
int mult = pcStats.getLevelupAttributeMultiplier (i);
text->setCaption(mult <= 1 ? "" : "x" + boost::lexical_cast<std::string>(mult));
}
}
void LevelupDialog::onOkButtonClicked (MyGUI::Widget* sender)
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayer().getPlayer();
MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get(player).getCreatureStats (player);
MWMechanics::NpcStats& pcStats = MWWorld::Class::get(player).getNpcStats (player);
if (mSpentAttributes.size() < 3)
MWBase::Environment::get().getWindowManager ()->messageBox("#{sNotifyMessage36}", std::vector<std::string>());
else
{
// increase attributes
for (int i=0; i<3; ++i)
{
MWMechanics::Stat<int>& attribute = creatureStats.getAttribute(mSpentAttributes[i]);
attribute.setBase (attribute.getBase () + pcStats.getLevelupAttributeMultiplier (mSpentAttributes[i]));
if (attribute.getBase() >= 100)
attribute.setBase(100);
}
// "When you gain a level, in addition to increasing three primary attributes, your Health
// will automatically increase by 10% of your Endurance attribute. If you increased Endurance this level,
// the Health increase is calculated from the increased Endurance"
creatureStats.increaseLevelHealthBonus (creatureStats.getAttribute(ESM::Attribute::Endurance).getBase() * 0.1f);
creatureStats.setLevel (creatureStats.getLevel()+1);
pcStats.levelUp ();
mWindowManager.removeGuiMode (GM_Rest);
}
}
void LevelupDialog::onAttributeClicked (MyGUI::Widget *sender)
{
int attribute = *sender->getUserData<int>();
std::vector<int>::iterator found = std::find(mSpentAttributes.begin(), mSpentAttributes.end(), attribute);
if (found != mSpentAttributes.end())
mSpentAttributes.erase (found);
else
{
if (mSpentAttributes.size() == 3)
mSpentAttributes[2] = attribute;
else
mSpentAttributes.push_back(attribute);
}
assignCoins();
}
}

View File

@ -0,0 +1,39 @@
#ifndef MWGUI_LEVELUPDIALOG_H
#define MWGUI_LEVELUPDIALOG_H
#include "window_base.hpp"
namespace MWGui
{
class LevelupDialog : public WindowBase
{
public:
LevelupDialog(MWBase::WindowManager& parWindowManager);
virtual void open();
private:
MyGUI::Button* mOkButton;
MyGUI::ImageBox* mClassImage;
MyGUI::TextBox* mLevelText;
std::vector<MyGUI::Button*> mAttributes;
std::vector<MyGUI::TextBox*> mAttributeValues;
std::vector<MyGUI::TextBox*> mAttributeMultipliers;
std::vector<MyGUI::ImageBox*> mCoins;
std::vector<int> mSpentAttributes;
void onOkButtonClicked (MyGUI::Widget* sender);
void onAttributeClicked (MyGUI::Widget* sender);
void assignCoins();
void resetCoins();
void setAttributeValues();
};
}
#endif

View File

@ -22,6 +22,8 @@ namespace MWGui
GM_Rest, GM_Rest,
GM_SpellBuying, GM_SpellBuying,
GM_Levelup,
// Startup character creation dialogs // Startup character creation dialogs
GM_Name, GM_Name,
GM_Race, GM_Race,

View File

@ -25,15 +25,18 @@ RaceDialog::RaceDialog(MWBase::WindowManager& parWindowManager)
, mHairIndex(0) , mHairIndex(0)
, mFaceCount(10) , mFaceCount(10)
, mHairCount(14) , mHairCount(14)
, mCurrentAngle(0)
{ {
// Centre dialog // Centre dialog
center(); center();
// These are just demo values, you should replace these with
// real calls from outside the class later.
setText("AppearanceT", mWindowManager.getGameSettingString("sRaceMenu1", "Appearance")); setText("AppearanceT", mWindowManager.getGameSettingString("sRaceMenu1", "Appearance"));
getWidget(mAppearanceBox, "AppearanceBox"); getWidget(mPreviewImage, "PreviewImage");
MWBase::Environment::get().getWorld ()->setupExternalRendering (mPreview);
mPreview.update (0);
mPreviewImage->setImageTexture ("CharacterHeadPreview");
getWidget(mHeadRotate, "HeadRotate"); getWidget(mHeadRotate, "HeadRotate");
mHeadRotate->setScrollRange(50); mHeadRotate->setScrollRange(50);
@ -149,7 +152,10 @@ void RaceDialog::onBackClicked(MyGUI::Widget* _sender)
void RaceDialog::onHeadRotate(MyGUI::ScrollBar*, size_t _position) void RaceDialog::onHeadRotate(MyGUI::ScrollBar*, size_t _position)
{ {
// TODO: Rotate head float angle = (float(_position) / 49.f - 0.5) * 3.14 * 2;
float diff = angle - mCurrentAngle;
mPreview.update (diff);
mCurrentAngle += diff;
} }
void RaceDialog::onSelectPreviousGender(MyGUI::Widget*) void RaceDialog::onSelectPreviousGender(MyGUI::Widget*)

View File

@ -1,11 +1,15 @@
#ifndef MWGUI_RACE_H #ifndef MWGUI_RACE_H
#define MWGUI_RACE_H #define MWGUI_RACE_H
#include <boost/array.hpp>
#include <components/esm_store/store.hpp> #include <components/esm_store/store.hpp>
#include "../mwrender/characterpreview.hpp"
#include "window_base.hpp" #include "window_base.hpp"
#include <boost/array.hpp>
namespace MWGui namespace MWGui
{ {
@ -73,7 +77,7 @@ namespace MWGui
void updateSkills(); void updateSkills();
void updateSpellPowers(); void updateSpellPowers();
MyGUI::CanvasPtr mAppearanceBox; MyGUI::ImageBox* mPreviewImage;
MyGUI::ListBox* mRaceList; MyGUI::ListBox* mRaceList;
MyGUI::ScrollBar* mHeadRotate; MyGUI::ScrollBar* mHeadRotate;
@ -87,6 +91,10 @@ namespace MWGui
int mFaceCount, mHairCount; int mFaceCount, mHairCount;
std::string mCurrentRaceId; std::string mCurrentRaceId;
float mCurrentAngle;
MWRender::RaceSelectionPreview mPreview;
}; };
} }
#endif #endif

View File

@ -134,21 +134,21 @@ void ReviewDialog::setBirthSign(const std::string& signId)
} }
} }
void ReviewDialog::setHealth(const MWMechanics::DynamicStat<int>& value) void ReviewDialog::setHealth(const MWMechanics::DynamicStat<float>& value)
{ {
mHealth->setValue(value.getCurrent(), value.getModified()); mHealth->setValue(value.getCurrent(), value.getModified());
std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified()); std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified());
mHealth->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr); mHealth->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr);
} }
void ReviewDialog::setMagicka(const MWMechanics::DynamicStat<int>& value) void ReviewDialog::setMagicka(const MWMechanics::DynamicStat<float>& value)
{ {
mMagicka->setValue(value.getCurrent(), value.getModified()); mMagicka->setValue(value.getCurrent(), value.getModified());
std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified()); std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified());
mMagicka->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr); mMagicka->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr);
} }
void ReviewDialog::setFatigue(const MWMechanics::DynamicStat<int>& value) void ReviewDialog::setFatigue(const MWMechanics::DynamicStat<float>& value)
{ {
mFatigue->setValue(value.getCurrent(), value.getModified()); mFatigue->setValue(value.getCurrent(), value.getModified());
std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified()); std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified());

View File

@ -35,9 +35,9 @@ namespace MWGui
void setClass(const ESM::Class& class_); void setClass(const ESM::Class& class_);
void setBirthSign (const std::string &signId); void setBirthSign (const std::string &signId);
void setHealth(const MWMechanics::DynamicStat<int>& value); void setHealth(const MWMechanics::DynamicStat<float>& value);
void setMagicka(const MWMechanics::DynamicStat<int>& value); void setMagicka(const MWMechanics::DynamicStat<float>& value);
void setFatigue(const MWMechanics::DynamicStat<int>& value); void setFatigue(const MWMechanics::DynamicStat<float>& value);
void setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::Stat<int>& value); void setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::Stat<int>& value);

View File

@ -137,7 +137,7 @@ void StatsWindow::setValue (const std::string& id, const MWMechanics::Stat<int>&
} }
} }
void StatsWindow::setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value) void StatsWindow::setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value)
{ {
static const char *ids[] = static const char *ids[] =
{ {
@ -150,7 +150,7 @@ void StatsWindow::setValue (const std::string& id, const MWMechanics::DynamicSta
if (ids[i]==id) if (ids[i]==id)
{ {
std::string id (ids[i]); std::string id (ids[i]);
setBar (id, id + "T", value.getCurrent(), value.getModified()); setBar (id, id + "T", static_cast<int>(value.getCurrent()), static_cast<int>(value.getModified()));
// health, magicka, fatigue tooltip // health, magicka, fatigue tooltip
MyGUI::Widget* w; MyGUI::Widget* w;
@ -236,12 +236,21 @@ void StatsWindow::configureSkills (const std::vector<int>& major, const std::vec
void StatsWindow::onFrame () void StatsWindow::onFrame ()
{ {
if (mMainWidget->getVisible()) if (!mMainWidget->getVisible())
return; return;
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWMechanics::NpcStats PCstats = MWWorld::Class::get(player).getNpcStats(player); MWMechanics::NpcStats PCstats = MWWorld::Class::get(player).getNpcStats(player);
// level progress
MyGUI::Widget* levelWidget;
for (int i=0; i<2; ++i)
{
getWidget(levelWidget, i==0 ? "Level_str" : "LevelText");
levelWidget->setUserString("RangePosition_LevelProgress", boost::lexical_cast<std::string>(PCstats.getLevelProgress()));
levelWidget->setUserString("Caption_LevelProgressText", boost::lexical_cast<std::string>(PCstats.getLevelProgress()) + "/10");
}
setFactions(PCstats.getFactionRanks()); setFactions(PCstats.getFactionRanks());
setBirthSign(MWBase::Environment::get().getWorld()->getPlayer().getBirthsign()); setBirthSign(MWBase::Environment::get().getWorld()->getPlayer().getBirthsign());

View File

@ -32,7 +32,7 @@ namespace MWGui
/// Set value for the given ID. /// Set value for the given ID.
void setValue (const std::string& id, const MWMechanics::Stat<int>& value); void setValue (const std::string& id, const MWMechanics::Stat<int>& value);
void setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value); void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value);
void setValue (const std::string& id, const std::string& value); void setValue (const std::string& id, const std::string& value);
void setValue (const std::string& id, int value); void setValue (const std::string& id, int value);
void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value); void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value);

View File

@ -14,6 +14,7 @@
#include "map_window.hpp" #include "map_window.hpp"
#include "widgets.hpp" #include "widgets.hpp"
#include "inventorywindow.hpp"
using namespace MWGui; using namespace MWGui;
using namespace MyGUI; using namespace MyGUI;
@ -162,12 +163,23 @@ void ToolTips::onFrame(float frameDuration)
return; return;
} }
if (type == "ItemPtr") if (type == "ItemPtr")
{ {
mFocusObject = *focus->getUserData<MWWorld::Ptr>(); mFocusObject = *focus->getUserData<MWWorld::Ptr>();
tooltipSize = getToolTipViaPtr(false); tooltipSize = getToolTipViaPtr(false);
} }
else if (type == "AvatarItemSelection")
{
MyGUI::IntCoord avatarPos = mWindowManager->getInventoryWindow ()->getAvatarScreenCoord ();
MyGUI::IntPoint relMousePos = MyGUI::InputManager::getInstance ().getMousePosition () - MyGUI::IntPoint(avatarPos.left, avatarPos.top);
int realX = int(float(relMousePos.left) / float(avatarPos.width) * 512.f );
int realY = int(float(relMousePos.top) / float(avatarPos.height) * 1024.f );
MWWorld::Ptr item = mWindowManager->getInventoryWindow ()->getAvatarSelectedItem (realX, realY);
mFocusObject = item;
if (!mFocusObject.isEmpty ())
tooltipSize = getToolTipViaPtr(false);
}
else if (type == "Spell") else if (type == "Spell")
{ {
ToolTipInfo info; ToolTipInfo info;

View File

@ -44,6 +44,7 @@
#include "spellwindow.hpp" #include "spellwindow.hpp"
#include "quickkeysmenu.hpp" #include "quickkeysmenu.hpp"
#include "loadingscreen.hpp" #include "loadingscreen.hpp"
#include "levelupdialog.hpp"
using namespace MWGui; using namespace MWGui;
@ -84,6 +85,7 @@ WindowManager::WindowManager(
, mGarbageDialogs() , mGarbageDialogs()
, mShown(GW_ALL) , mShown(GW_ALL)
, mAllowed(newGame ? GW_None : GW_ALL) , mAllowed(newGame ? GW_None : GW_ALL)
, mRestAllowed(newGame ? false : true)
, mShowFPSLevel(fpsLevel) , mShowFPSLevel(fpsLevel)
, mFPS(0.0f) , mFPS(0.0f)
, mTriangleCount(0) , mTriangleCount(0)
@ -147,6 +149,7 @@ WindowManager::WindowManager(
mAlchemyWindow = new AlchemyWindow(*this); mAlchemyWindow = new AlchemyWindow(*this);
mSpellWindow = new SpellWindow(*this); mSpellWindow = new SpellWindow(*this);
mQuickKeysMenu = new QuickKeysMenu(*this); mQuickKeysMenu = new QuickKeysMenu(*this);
mLevelupDialog = new LevelupDialog(*this);
mLoadingScreen = new LoadingScreen(mOgre->getScene (), mOgre->getWindow (), *this); mLoadingScreen = new LoadingScreen(mOgre->getScene (), mOgre->getWindow (), *this);
mLoadingScreen->onResChange (w,h); mLoadingScreen->onResChange (w,h);
@ -200,6 +203,7 @@ WindowManager::~WindowManager()
delete mAlchemyWindow; delete mAlchemyWindow;
delete mSpellWindow; delete mSpellWindow;
delete mLoadingScreen; delete mLoadingScreen;
delete mLevelupDialog;
cleanupGarbage(); cleanupGarbage();
@ -247,6 +251,7 @@ void WindowManager::updateVisible()
mAlchemyWindow->setVisible(false); mAlchemyWindow->setVisible(false);
mSpellWindow->setVisible(false); mSpellWindow->setVisible(false);
mQuickKeysMenu->setVisible(false); mQuickKeysMenu->setVisible(false);
mLevelupDialog->setVisible(false);
mHud->setVisible(true); mHud->setVisible(true);
@ -298,6 +303,9 @@ void WindowManager::updateVisible()
case GM_Alchemy: case GM_Alchemy:
mAlchemyWindow->setVisible(true); mAlchemyWindow->setVisible(true);
break; break;
case GM_Rest:
mLevelupDialog->setVisible(true);
break;
case GM_Name: case GM_Name:
case GM_Race: case GM_Race:
case GM_Class: case GM_Class:
@ -395,7 +403,7 @@ void WindowManager::setValue (int parSkill, const MWMechanics::Stat<float>& valu
mPlayerSkillValues[parSkill] = value; mPlayerSkillValues[parSkill] = value;
} }
void WindowManager::setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value) void WindowManager::setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value)
{ {
mStatsWindow->setValue (id, value); mStatsWindow->setValue (id, value);
mHud->setValue (id, value); mHud->setValue (id, value);

View File

@ -62,6 +62,7 @@ namespace MWGui
class AlchemyWindow; class AlchemyWindow;
class QuickKeysMenu; class QuickKeysMenu;
class LoadingScreen; class LoadingScreen;
class LevelupDialog;
class WindowManager : public MWBase::WindowManager class WindowManager : public MWBase::WindowManager
{ {
@ -117,7 +118,7 @@ namespace MWGui
///< Set value for the given ID. ///< Set value for the given ID.
virtual void setValue (const std::string& id, const MWMechanics::Stat<int>& value); virtual void setValue (const std::string& id, const MWMechanics::Stat<int>& value);
virtual void setValue (int parSkill, const MWMechanics::Stat<float>& value); virtual void setValue (int parSkill, const MWMechanics::Stat<float>& value);
virtual void setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value); virtual void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value);
virtual void setValue (const std::string& id, const std::string& value); virtual void setValue (const std::string& id, const std::string& value);
virtual void setValue (const std::string& id, int value); virtual void setValue (const std::string& id, int value);
@ -199,6 +200,9 @@ namespace MWGui
virtual void setLoadingProgress (const std::string& stage, int depth, int current, int total); virtual void setLoadingProgress (const std::string& stage, int depth, int current, int total);
virtual void loadingDone(); virtual void loadingDone();
virtual void enableRest() { mRestAllowed = true; }
virtual bool getRestEnabled() { return mRestAllowed; }
private: private:
OEngine::GUI::MyGUIManager *mGuiManager; OEngine::GUI::MyGUIManager *mGuiManager;
HUD *mHud; HUD *mHud;
@ -224,6 +228,7 @@ namespace MWGui
SpellWindow* mSpellWindow; SpellWindow* mSpellWindow;
QuickKeysMenu* mQuickKeysMenu; QuickKeysMenu* mQuickKeysMenu;
LoadingScreen* mLoadingScreen; LoadingScreen* mLoadingScreen;
LevelupDialog* mLevelupDialog;
CharacterCreation* mCharGen; CharacterCreation* mCharGen;
@ -241,7 +246,7 @@ namespace MWGui
std::map<int, MWMechanics::Stat<int> > mPlayerAttributes; std::map<int, MWMechanics::Stat<int> > mPlayerAttributes;
SkillList mPlayerMajorSkills, mPlayerMinorSkills; SkillList mPlayerMajorSkills, mPlayerMinorSkills;
std::map<int, MWMechanics::Stat<float> > mPlayerSkillValues; std::map<int, MWMechanics::Stat<float> > mPlayerSkillValues;
MWMechanics::DynamicStat<int> mPlayerHealth, mPlayerMagicka, mPlayerFatigue; MWMechanics::DynamicStat<float> mPlayerHealth, mPlayerMagicka, mPlayerFatigue;
MyGUI::Gui *mGui; // Gui MyGUI::Gui *mGui; // Gui
@ -258,6 +263,8 @@ namespace MWGui
allow() and disableAll(). allow() and disableAll().
*/ */
GuiWindow mAllowed; GuiWindow mAllowed;
// is the rest window allowed?
bool mRestAllowed;
void updateVisible(); // Update visibility of all windows based on mode, shown and allowed settings void updateVisible(); // Update visibility of all windows based on mode, shown and allowed settings

View File

@ -190,6 +190,9 @@ namespace MWInput
case A_ToggleWeapon: case A_ToggleWeapon:
toggleWeapon (); toggleWeapon ();
break; break;
case A_Rest:
rest();
break;
case A_ToggleSpell: case A_ToggleSpell:
toggleSpell (); toggleSpell ();
break; break;
@ -543,6 +546,15 @@ namespace MWInput
} }
} }
void InputManager::rest()
{
if (!mWindows.getRestEnabled () || mWindows.isGuiMode ())
return;
/// \todo check if resting is currently allowed (enemies nearby?)
mWindows.pushGuiMode (MWGui::GM_Rest);
}
void InputManager::screenshot() void InputManager::screenshot()
{ {
mEngine.screenshot(); mEngine.screenshot();

View File

@ -168,6 +168,7 @@ namespace MWInput
void toggleWalking(); void toggleWalking();
void toggleAutoMove(); void toggleAutoMove();
void exitNow(); void exitNow();
void rest();
void quickKey (int index); void quickKey (int index);
void showQuickKeysMenu(); void showQuickKeysMenu();

View File

@ -68,7 +68,7 @@ namespace MWMechanics
creatureStats.getMagicEffects().get (EffectKey (84)).mMagnitude * 0.1 + 0.5; creatureStats.getMagicEffects().get (EffectKey (84)).mMagnitude * 0.1 + 0.5;
creatureStats.getHealth().setBase( creatureStats.getHealth().setBase(
static_cast<int> (0.5 * (strength + endurance))); static_cast<int> (0.5 * (strength + endurance)) + creatureStats.getLevelHealthBonus ());
creatureStats.getMagicka().setBase( creatureStats.getMagicka().setBase(
static_cast<int> (intelligence + magickaFactor * intelligence)); static_cast<int> (intelligence + magickaFactor * intelligence));

View File

@ -9,6 +9,21 @@
namespace MWMechanics namespace MWMechanics
{ {
CreatureStats::CreatureStats()
: mLevelHealthBonus(0.f)
{
}
void CreatureStats::increaseLevelHealthBonus (float value)
{
mLevelHealthBonus += value;
}
float CreatureStats::getLevelHealthBonus () const
{
return mLevelHealthBonus;
}
const AiSequence& CreatureStats::getAiSequence() const const AiSequence& CreatureStats::getAiSequence() const
{ {
return mAiSequence; return mAiSequence;
@ -40,17 +55,17 @@ namespace MWMechanics
return mAttributes[index]; return mAttributes[index];
} }
const DynamicStat<int> &CreatureStats::getHealth() const const DynamicStat<float> &CreatureStats::getHealth() const
{ {
return mDynamic[0]; return mDynamic[0];
} }
const DynamicStat<int> &CreatureStats::getMagicka() const const DynamicStat<float> &CreatureStats::getMagicka() const
{ {
return mDynamic[1]; return mDynamic[1];
} }
const DynamicStat<int> &CreatureStats::getFatigue() const const DynamicStat<float> &CreatureStats::getFatigue() const
{ {
return mDynamic[2]; return mDynamic[2];
} }
@ -103,22 +118,22 @@ namespace MWMechanics
return mAttributes[index]; return mAttributes[index];
} }
DynamicStat<int> &CreatureStats::getHealth() DynamicStat<float> &CreatureStats::getHealth()
{ {
return mDynamic[0]; return mDynamic[0];
} }
DynamicStat<int> &CreatureStats::getMagicka() DynamicStat<float> &CreatureStats::getMagicka()
{ {
return mDynamic[1]; return mDynamic[1];
} }
DynamicStat<int> &CreatureStats::getFatigue() DynamicStat<float> &CreatureStats::getFatigue()
{ {
return mDynamic[2]; return mDynamic[2];
} }
DynamicStat<int> &CreatureStats::getDynamic(int index) DynamicStat<float> &CreatureStats::getDynamic(int index)
{ {
if (index < 0 || index > 2) { if (index < 0 || index > 2) {
throw std::runtime_error("dynamic stat index is out of range"); throw std::runtime_error("dynamic stat index is out of range");
@ -154,17 +169,17 @@ namespace MWMechanics
mAttributes[index] = value; mAttributes[index] = value;
} }
void CreatureStats::setHealth(const DynamicStat<int> &value) void CreatureStats::setHealth(const DynamicStat<float> &value)
{ {
mDynamic[0] = value; mDynamic[0] = value;
} }
void CreatureStats::setMagicka(const DynamicStat<int> &value) void CreatureStats::setMagicka(const DynamicStat<float> &value)
{ {
mDynamic[1] = value; mDynamic[1] = value;
} }
void CreatureStats::setFatigue(const DynamicStat<int> &value) void CreatureStats::setFatigue(const DynamicStat<float> &value)
{ {
mDynamic[2] = value; mDynamic[2] = value;
} }

View File

@ -19,7 +19,7 @@ namespace MWMechanics
class CreatureStats class CreatureStats
{ {
Stat<int> mAttributes[8]; Stat<int> mAttributes[8];
DynamicStat<int> mDynamic[3]; // health, magicka, fatigue DynamicStat<float> mDynamic[3]; // health, magicka, fatigue
int mLevel; int mLevel;
Spells mSpells; Spells mSpells;
ActiveSpells mActiveSpells; ActiveSpells mActiveSpells;
@ -30,15 +30,18 @@ namespace MWMechanics
int mAlarm; int mAlarm;
AiSequence mAiSequence; AiSequence mAiSequence;
float mLevelHealthBonus;
public: public:
CreatureStats();
const Stat<int> & getAttribute(int index) const; const Stat<int> & getAttribute(int index) const;
const DynamicStat<int> & getHealth() const; const DynamicStat<float> & getHealth() const;
const DynamicStat<int> & getMagicka() const; const DynamicStat<float> & getMagicka() const;
const DynamicStat<int> & getFatigue() const; const DynamicStat<float> & getFatigue() const;
const Spells & getSpells() const; const Spells & getSpells() const;
@ -59,13 +62,13 @@ namespace MWMechanics
Stat<int> & getAttribute(int index); Stat<int> & getAttribute(int index);
DynamicStat<int> & getHealth(); DynamicStat<float> & getHealth();
DynamicStat<int> & getMagicka(); DynamicStat<float> & getMagicka();
DynamicStat<int> & getFatigue(); DynamicStat<float> & getFatigue();
DynamicStat<int> & getDynamic(int index); DynamicStat<float> & getDynamic(int index);
Spells & getSpells(); Spells & getSpells();
@ -76,11 +79,11 @@ namespace MWMechanics
void setAttribute(int index, const Stat<int> &value); void setAttribute(int index, const Stat<int> &value);
void setHealth(const DynamicStat<int> &value); void setHealth(const DynamicStat<float> &value);
void setMagicka(const DynamicStat<int> &value); void setMagicka(const DynamicStat<float> &value);
void setFatigue(const DynamicStat<int> &value); void setFatigue(const DynamicStat<float> &value);
void setSpells(const Spells &spells); void setSpells(const Spells &spells);
@ -104,6 +107,10 @@ namespace MWMechanics
float getFatigueTerm() const; float getFatigueTerm() const;
///< Return effective fatigue ///< Return effective fatigue
// small hack to allow the fact that Health permanently increases by 10% of endurance on each level up
void increaseLevelHealthBonus(float value);
float getLevelHealthBonus() const;
}; };
} }

View File

@ -4,6 +4,8 @@
#include <cmath> #include <cmath>
#include <stdexcept> #include <stdexcept>
#include <boost/format.hpp>
#include <components/esm/loadskil.hpp> #include <components/esm/loadskil.hpp>
#include <components/esm/loadclas.hpp> #include <components/esm/loadclas.hpp>
#include <components/esm/loadgmst.hpp> #include <components/esm/loadgmst.hpp>
@ -12,10 +14,17 @@
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/soundmanager.hpp"
MWMechanics::NpcStats::NpcStats() MWMechanics::NpcStats::NpcStats()
: mMovementFlags (0), mDrawState (DrawState_Nothing) : mMovementFlags (0), mDrawState (DrawState_Nothing)
{} , mLevelProgress(0)
{
mSkillIncreases.resize (ESM::Attribute::Length);
for (int i=0; i<ESM::Attribute::Length; ++i)
mSkillIncreases[i] = 0;
}
MWMechanics::DrawState_ MWMechanics::NpcStats::getDrawState() const MWMechanics::DrawState_ MWMechanics::NpcStats::getDrawState() const
{ {
@ -122,7 +131,7 @@ float MWMechanics::NpcStats::getSkillGain (int skillIndex, const ESM::Class& cla
throw std::runtime_error ("invalid skill specialisation factor"); throw std::runtime_error ("invalid skill specialisation factor");
} }
return 1.0 / (level +1) * (1.0 / skillFactor) * typeFactor * specialisationFactor; return 1.0 / (level +1) * (1.0 / (skillFactor)) * typeFactor * specialisationFactor;
} }
void MWMechanics::NpcStats::useSkill (int skillIndex, const ESM::Class& class_, int usageType) void MWMechanics::NpcStats::useSkill (int skillIndex, const ESM::Class& class_, int usageType)
@ -134,7 +143,87 @@ void MWMechanics::NpcStats::useSkill (int skillIndex, const ESM::Class& class_,
base += getSkillGain (skillIndex, class_, usageType); base += getSkillGain (skillIndex, class_, usageType);
if (static_cast<int> (base)!=level) if (static_cast<int> (base)!=level)
{
// skill leveled up
increaseSkill(skillIndex, class_, false);
}
else
getSkill (skillIndex).setBase (base);
}
void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &class_, bool preserveProgress)
{
float base = getSkill (skillIndex).getBase();
int level = static_cast<int> (base);
if (level >= 100)
return;
if (preserveProgress)
base += 1;
else
base = level+1; base = level+1;
// if this is a major or minor skill of the class, increase level progress
bool levelProgress = false;
for (int i=0; i<2; ++i)
for (int j=0; j<5; ++j)
{
int skill = class_.data.skills[j][i];
if (skill == skillIndex)
levelProgress = true;
}
mLevelProgress += levelProgress;
// check the attribute this skill belongs to
const ESM::Skill* skill = MWBase::Environment::get().getWorld ()->getStore ().skills.find(skillIndex);
++mSkillIncreases[skill->data.attribute];
// Play sound & skill progress notification
/// \todo check if character is the player, if levelling is ever implemented for NPCs
MWBase::Environment::get().getSoundManager ()->playSound ("skillraise", 1, 1);
std::stringstream message;
message << boost::format(MWBase::Environment::get().getWindowManager ()->getGameSettingString ("sNotifyMessage39", ""))
% std::string("#{" + ESM::Skill::sSkillNameIds[skillIndex] + "}")
% base;
MWBase::Environment::get().getWindowManager ()->messageBox(message.str(), std::vector<std::string>());
if (mLevelProgress >= 10)
{
// levelup is possible now
MWBase::Environment::get().getWindowManager ()->messageBox ("#{sLevelUpMsg}", std::vector<std::string>());
}
getSkill (skillIndex).setBase (base); getSkill (skillIndex).setBase (base);
} }
int MWMechanics::NpcStats::getLevelProgress () const
{
return mLevelProgress;
}
void MWMechanics::NpcStats::levelUp()
{
mLevelProgress -= 10;
for (int i=0; i<ESM::Attribute::Length; ++i)
mSkillIncreases[i] = 0;
}
int MWMechanics::NpcStats::getLevelupAttributeMultiplier(int attribute) const
{
// Source: http://www.uesp.net/wiki/Morrowind:Level#How_to_Level_Up
int num = mSkillIncreases[attribute];
if (num <= 1)
return 1;
else if (num <= 4)
return 2;
else if (num <= 7)
return 3;
else if (num <= 9)
return 4;
else
return 5;
}

View File

@ -4,6 +4,7 @@
#include <map> #include <map>
#include <set> #include <set>
#include <string> #include <string>
#include <vector>
#include "stat.hpp" #include "stat.hpp"
#include "drawstate.hpp" #include "drawstate.hpp"
@ -45,6 +46,10 @@ namespace MWMechanics
unsigned int mMovementFlags; unsigned int mMovementFlags;
Stat<float> mSkill[27]; Stat<float> mSkill[27];
int mLevelProgress; // 0-10
std::vector<int> mSkillIncreases; // number of skill increases for each attribute
public: public:
NpcStats(); NpcStats();
@ -73,6 +78,14 @@ namespace MWMechanics
void useSkill (int skillIndex, const ESM::Class& class_, int usageType = -1); void useSkill (int skillIndex, const ESM::Class& class_, int usageType = -1);
///< Increase skill by usage. ///< Increase skill by usage.
void increaseSkill (int skillIndex, const ESM::Class& class_, bool preserveProgress);
int getLevelProgress() const;
int getLevelupAttributeMultiplier(int attribute) const;
void levelUp();
}; };
} }

View File

@ -3,6 +3,8 @@
#include <OgreSceneNode.h> #include <OgreSceneNode.h>
#include <OgreSceneManager.h> #include <OgreSceneManager.h>
#include "renderconst.hpp"
using namespace Ogre; using namespace Ogre;
using namespace MWRender; using namespace MWRender;
@ -23,7 +25,7 @@ void Actors::setMwRoot(Ogre::SceneNode* root){
void Actors::insertNPC(const MWWorld::Ptr& ptr, MWWorld::InventoryStore& inv){ void Actors::insertNPC(const MWWorld::Ptr& ptr, MWWorld::InventoryStore& inv){
insertBegin(ptr, true, true); insertBegin(ptr, true, true);
NpcAnimation* anim = new MWRender::NpcAnimation(ptr, mRend, inv); NpcAnimation* anim = new MWRender::NpcAnimation(ptr, ptr.getRefData ().getBaseNode (), inv, RV_Actors);
mAllActors[ptr] = anim; mAllActors[ptr] = anim;
} }
@ -68,7 +70,7 @@ void Actors::insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_){
void Actors::insertCreature (const MWWorld::Ptr& ptr){ void Actors::insertCreature (const MWWorld::Ptr& ptr){
insertBegin(ptr, true, true); insertBegin(ptr, true, true);
CreatureAnimation* anim = new MWRender::CreatureAnimation(ptr, mRend); CreatureAnimation* anim = new MWRender::CreatureAnimation(ptr);
//mAllActors.insert(std::pair<MWWorld::Ptr, Animation*>(ptr,anim)); //mAllActors.insert(std::pair<MWWorld::Ptr, Animation*>(ptr,anim));
delete mAllActors[ptr]; delete mAllActors[ptr];
mAllActors[ptr] = anim; mAllActors[ptr] = anim;

View File

@ -11,9 +11,8 @@
namespace MWRender namespace MWRender
{ {
Animation::Animation(OEngine::Render::OgreRenderer& _rend) Animation::Animation()
: mInsert(NULL) : mInsert(NULL)
, mRend(_rend)
, mTime(0.0f) , mTime(0.0f)
, mSkipFrame(false) , mSkipFrame(false)
{ {

View File

@ -31,7 +31,6 @@ class Animation {
protected: protected:
Ogre::SceneNode* mInsert; Ogre::SceneNode* mInsert;
OEngine::Render::OgreRenderer &mRend;
float mTime; float mTime;
GroupTimes mCurGroup; GroupTimes mCurGroup;
@ -45,7 +44,7 @@ protected:
bool findGroupTimes(const std::string &groupname, GroupTimes *times); bool findGroupTimes(const std::string &groupname, GroupTimes *times);
public: public:
Animation(OEngine::Render::OgreRenderer& _rend); Animation();
virtual ~Animation(); virtual ~Animation();
void playGroup(std::string groupname, int mode, int loops); void playGroup(std::string groupname, int mode, int loops);

View File

@ -0,0 +1,135 @@
#include "characterpreview.hpp"
#include <OgreSceneManager.h>
#include <OgreHardwarePixelBuffer.h>
#include <libs/openengine/ogre/selectionbuffer.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/player.hpp"
#include "renderconst.hpp"
#include "npcanimation.hpp"
namespace MWRender
{
CharacterPreview::CharacterPreview(MWWorld::Ptr character, int sizeX, int sizeY, const std::string& name,
Ogre::Vector3 position, Ogre::Vector3 lookAt)
: mSizeX(sizeX)
, mSizeY(sizeY)
, mName(name)
, mPosition(position)
, mLookAt(lookAt)
, mCharacter(character)
{
}
void CharacterPreview::onSetup()
{
}
void CharacterPreview::setup (Ogre::SceneManager *sceneManager)
{
mSceneMgr = sceneManager;
mCamera = mSceneMgr->createCamera (mName);
mCamera->setAspectRatio (float(mSizeX) / float(mSizeY));
mNode = static_cast<Ogre::SceneNode*>(mSceneMgr->getRootSceneNode()->getChild("mwRoot"))->createChildSceneNode ();
mAnimation = new NpcAnimation(mCharacter, mNode,
MWWorld::Class::get(mCharacter).getInventoryStore (mCharacter), RV_PlayerPreview);
mNode->setVisible (false);
mCamera->setPosition(mPosition);
mCamera->lookAt(mLookAt);
mCamera->setNearClipDistance (0.01);
mCamera->setFarClipDistance (1000);
mTexture = Ogre::TextureManager::getSingleton().createManual(mName,
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, mSizeX, mSizeY, 0, Ogre::PF_A8R8G8B8, Ogre::TU_RENDERTARGET);
mRenderTarget = mTexture->getBuffer()->getRenderTarget();
mViewport = mRenderTarget->addViewport(mCamera);
mViewport->setOverlaysEnabled(false);
mViewport->setBackgroundColour(Ogre::ColourValue(0, 0, 0, 0));
mViewport->setShadowsEnabled(false);
mViewport->setMaterialScheme("local_map");
mViewport->setVisibilityMask (RV_PlayerPreview);
mRenderTarget->setActive(true);
mRenderTarget->setAutoUpdated (false);
onSetup ();
}
CharacterPreview::~CharacterPreview ()
{
Ogre::TextureManager::getSingleton().remove(mName);
}
// --------------------------------------------------------------------------------------------------
InventoryPreview::InventoryPreview(MWWorld::Ptr character)
: CharacterPreview(character, 512, 1024, "CharacterPreview", Ogre::Vector3(0, 65, -180), Ogre::Vector3(0,65,0))
{
}
InventoryPreview::~InventoryPreview()
{
delete mSelectionBuffer;
}
void InventoryPreview::update(int sizeX, int sizeY)
{
mAnimation->forceUpdate ();
mViewport->setDimensions (0, 0, std::min(1.f, float(sizeX) / float(512)), std::min(1.f, float(sizeY) / float(1024)));
mNode->setOrientation (Ogre::Quaternion::IDENTITY);
mNode->setVisible (true);
mRenderTarget->update();
mSelectionBuffer->update();
mNode->setVisible (false);
}
int InventoryPreview::getSlotSelected (int posX, int posY)
{
return mSelectionBuffer->getSelected (posX, posY);
}
void InventoryPreview::onSetup ()
{
mSelectionBuffer = new OEngine::Render::SelectionBuffer(mCamera, 512, 1024, RV_PlayerPreview);
}
// --------------------------------------------------------------------------------------------------
RaceSelectionPreview::RaceSelectionPreview()
: CharacterPreview(MWBase::Environment::get().getWorld()->getPlayer().getPlayer(),
512, 512, "CharacterHeadPreview", Ogre::Vector3(0, 120, -35), Ogre::Vector3(0,125,0))
{
}
void RaceSelectionPreview::update(float angle)
{
mNode->roll(Ogre::Radian(angle), Ogre::SceneNode::TS_LOCAL);
mNode->setVisible (true);
mRenderTarget->update();
mNode->setVisible (false);
}
}

View File

@ -0,0 +1,88 @@
#ifndef MWRENDER_CHARACTERPREVIEW_H
#define MWRENDER_CHARACTERPREVIEW_H
#include <OgreRenderTarget.h>
#include <OgreMaterialManager.h>
#include "externalrendering.hpp"
#include "../mwworld/ptr.hpp"
namespace OEngine
{
namespace Render
{
class SelectionBuffer;
}
}
namespace MWRender
{
class NpcAnimation;
class CharacterPreview : public ExternalRendering
{
public:
CharacterPreview(MWWorld::Ptr character, int sizeX, int sizeY, const std::string& name,
Ogre::Vector3 position, Ogre::Vector3 lookAt);
virtual ~CharacterPreview();
virtual void setup (Ogre::SceneManager *sceneManager);
virtual void onSetup();
protected:
Ogre::TexturePtr mTexture;
Ogre::RenderTarget* mRenderTarget;
Ogre::Viewport* mViewport;
Ogre::Camera* mCamera;
Ogre::SceneManager* mSceneMgr;
Ogre::SceneNode* mNode;
Ogre::Vector3 mPosition;
Ogre::Vector3 mLookAt;
MWWorld::Ptr mCharacter;
MWRender::NpcAnimation* mAnimation;
std::string mName;
int mSizeX;
int mSizeY;
};
class InventoryPreview : public CharacterPreview
{
public:
InventoryPreview(MWWorld::Ptr character);
virtual ~InventoryPreview();
virtual void onSetup();
void update(int sizeX, int sizeY);
int getSlotSelected(int posX, int posY);
void setNpcAnimation (NpcAnimation* anim);
private:
OEngine::Render::SelectionBuffer* mSelectionBuffer;
};
class RaceSelectionPreview : public CharacterPreview
{
public:
RaceSelectionPreview();
void update(float angle);
};
}
#endif

View File

@ -16,7 +16,7 @@ CreatureAnimation::~CreatureAnimation()
{ {
} }
CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRenderer& _rend): Animation(_rend) CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr): Animation()
{ {
mInsert = ptr.getRefData().getBaseNode(); mInsert = ptr.getRefData().getBaseNode();
MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>(); MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>();

View File

@ -8,13 +8,13 @@
namespace MWRender{ namespace MWRender{
class CreatureAnimation: public Animation{ class CreatureAnimation: public Animation
{
public: public:
virtual ~CreatureAnimation(); virtual ~CreatureAnimation();
CreatureAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRenderer& _rend); CreatureAnimation(const MWWorld::Ptr& ptr);
virtual void runAnimation(float timepassed); virtual void runAnimation(float timepassed);
}; };
} }
#endif #endif

View File

@ -0,0 +1,23 @@
#ifndef GAME_RENDERING_EXTERNALRENDERING_H
#define GAME_RENDERING_EXTERNALRENDERING_H
namespace Ogre
{
class SceneManager;
}
namespace MWRender
{
/// \brief Base class for out of world rendering
class ExternalRendering
{
public:
virtual void setup (Ogre::SceneManager *sceneManager) = 0;
virtual ~ExternalRendering() {}
};
}
#endif

View File

@ -45,8 +45,8 @@ NpcAnimation::~NpcAnimation()
} }
NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRenderer& _rend, MWWorld::InventoryStore& _inv) NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWorld::InventoryStore& _inv, int visibilityFlags)
: Animation(_rend), mStateID(-1), mInv(_inv), timeToChange(0), : Animation(), mStateID(-1), mInv(_inv), timeToChange(0), mVisibilityFlags(visibilityFlags),
robe(mInv.end()), helmet(mInv.end()), shirt(mInv.end()), robe(mInv.end()), helmet(mInv.end()), shirt(mInv.end()),
cuirass(mInv.end()), greaves(mInv.end()), cuirass(mInv.end()), greaves(mInv.end()),
leftpauldron(mInv.end()), rightpauldron(mInv.end()), leftpauldron(mInv.end()), rightpauldron(mInv.end()),
@ -84,7 +84,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRendere
std::cout << " Sex: Male" << " Height: " << race->data.height.male << "\n"; std::cout << " Sex: Male" << " Height: " << race->data.height.male << "\n";
*/ */
mInsert = ptr.getRefData().getBaseNode(); mInsert = node;
assert(mInsert); assert(mInsert);
std::string smodel = (!isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif"); std::string smodel = (!isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif");
@ -94,7 +94,9 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRendere
{ {
Ogre::Entity *base = mEntityList.mEntities[i]; Ogre::Entity *base = mEntityList.mEntities[i];
base->setVisibilityFlags(RV_Actors); base->getUserObjectBindings ().setUserAny (Ogre::Any(-1));
base->setVisibilityFlags(mVisibilityFlags);
bool transparent = false; bool transparent = false;
for(unsigned int j=0;j < base->getNumSubEntities();++j) for(unsigned int j=0;j < base->getNumSubEntities();++j)
{ {
@ -351,13 +353,16 @@ void NpcAnimation::updateParts()
} }
} }
NifOgre::EntityList NpcAnimation::insertBoundedPart(const std::string &mesh, const std::string &bonename) NifOgre::EntityList NpcAnimation::insertBoundedPart(const std::string &mesh, int group, const std::string &bonename)
{ {
NifOgre::EntityList entities = NIFLoader::createEntities(mEntityList.mSkelBase, bonename, NifOgre::EntityList entities = NIFLoader::createEntities(mEntityList.mSkelBase, bonename,
mInsert, mesh); mInsert, mesh);
std::vector<Ogre::Entity*> &parts = entities.mEntities; std::vector<Ogre::Entity*> &parts = entities.mEntities;
for(size_t i = 0;i < parts.size();i++) for(size_t i = 0;i < parts.size();i++)
parts[i]->setVisibilityFlags(RV_Actors); {
parts[i]->setVisibilityFlags(mVisibilityFlags);
parts[i]->getUserObjectBindings ().setUserAny (Ogre::Any(group));
}
return entities; return entities;
} }
@ -480,83 +485,83 @@ bool NpcAnimation::addOrReplaceIndividualPart(int type, int group, int priority,
switch(type) switch(type)
{ {
case ESM::PRT_Head: //0 case ESM::PRT_Head: //0
head = insertBoundedPart(mesh, "Head"); head = insertBoundedPart(mesh, group, "Head");
break; break;
case ESM::PRT_Hair: //1 case ESM::PRT_Hair: //1
hair = insertBoundedPart(mesh, "Head"); hair = insertBoundedPart(mesh, group, "Head");
break; break;
case ESM::PRT_Neck: //2 case ESM::PRT_Neck: //2
neck = insertBoundedPart(mesh, "Neck"); neck = insertBoundedPart(mesh, group, "Neck");
break; break;
case ESM::PRT_Cuirass: //3 case ESM::PRT_Cuirass: //3
chest = insertBoundedPart(mesh, "Chest"); chest = insertBoundedPart(mesh, group, "Chest");
break; break;
case ESM::PRT_Groin: //4 case ESM::PRT_Groin: //4
groin = insertBoundedPart(mesh, "Groin"); groin = insertBoundedPart(mesh, group, "Groin");
break; break;
case ESM::PRT_Skirt: //5 case ESM::PRT_Skirt: //5
skirt = insertBoundedPart(mesh, "Groin"); skirt = insertBoundedPart(mesh, group, "Groin");
break; break;
case ESM::PRT_RHand: //6 case ESM::PRT_RHand: //6
rHand = insertBoundedPart(mesh, "Right Hand"); rHand = insertBoundedPart(mesh, group, "Right Hand");
break; break;
case ESM::PRT_LHand: //7 case ESM::PRT_LHand: //7
lHand = insertBoundedPart(mesh, "Left Hand"); lHand = insertBoundedPart(mesh, group, "Left Hand");
break; break;
case ESM::PRT_RWrist: //8 case ESM::PRT_RWrist: //8
rWrist = insertBoundedPart(mesh, "Right Wrist"); rWrist = insertBoundedPart(mesh, group, "Right Wrist");
break; break;
case ESM::PRT_LWrist: //9 case ESM::PRT_LWrist: //9
lWrist = insertBoundedPart(mesh, "Left Wrist"); lWrist = insertBoundedPart(mesh, group, "Left Wrist");
break; break;
case ESM::PRT_Shield: //10 case ESM::PRT_Shield: //10
break; break;
case ESM::PRT_RForearm: //11 case ESM::PRT_RForearm: //11
rForearm = insertBoundedPart(mesh, "Right Forearm"); rForearm = insertBoundedPart(mesh, group, "Right Forearm");
break; break;
case ESM::PRT_LForearm: //12 case ESM::PRT_LForearm: //12
lForearm = insertBoundedPart(mesh, "Left Forearm"); lForearm = insertBoundedPart(mesh, group, "Left Forearm");
break; break;
case ESM::PRT_RUpperarm: //13 case ESM::PRT_RUpperarm: //13
rupperArm = insertBoundedPart(mesh, "Right Upper Arm"); rupperArm = insertBoundedPart(mesh, group, "Right Upper Arm");
break; break;
case ESM::PRT_LUpperarm: //14 case ESM::PRT_LUpperarm: //14
lupperArm = insertBoundedPart(mesh, "Left Upper Arm"); lupperArm = insertBoundedPart(mesh, group, "Left Upper Arm");
break; break;
case ESM::PRT_RFoot: //15 case ESM::PRT_RFoot: //15
rfoot = insertBoundedPart(mesh, "Right Foot"); rfoot = insertBoundedPart(mesh, group, "Right Foot");
break; break;
case ESM::PRT_LFoot: //16 case ESM::PRT_LFoot: //16
lfoot = insertBoundedPart(mesh, "Left Foot"); lfoot = insertBoundedPart(mesh, group, "Left Foot");
break; break;
case ESM::PRT_RAnkle: //17 case ESM::PRT_RAnkle: //17
rAnkle = insertBoundedPart(mesh, "Right Ankle"); rAnkle = insertBoundedPart(mesh, group, "Right Ankle");
break; break;
case ESM::PRT_LAnkle: //18 case ESM::PRT_LAnkle: //18
lAnkle = insertBoundedPart(mesh, "Left Ankle"); lAnkle = insertBoundedPart(mesh, group, "Left Ankle");
break; break;
case ESM::PRT_RKnee: //19 case ESM::PRT_RKnee: //19
rKnee = insertBoundedPart(mesh, "Right Knee"); rKnee = insertBoundedPart(mesh, group, "Right Knee");
break; break;
case ESM::PRT_LKnee: //20 case ESM::PRT_LKnee: //20
lKnee = insertBoundedPart(mesh, "Left Knee"); lKnee = insertBoundedPart(mesh, group, "Left Knee");
break; break;
case ESM::PRT_RLeg: //21 case ESM::PRT_RLeg: //21
rUpperLeg = insertBoundedPart(mesh, "Right Upper Leg"); rUpperLeg = insertBoundedPart(mesh, group, "Right Upper Leg");
break; break;
case ESM::PRT_LLeg: //22 case ESM::PRT_LLeg: //22
lUpperLeg = insertBoundedPart(mesh, "Left Upper Leg"); lUpperLeg = insertBoundedPart(mesh, group, "Left Upper Leg");
break; break;
case ESM::PRT_RPauldron: //23 case ESM::PRT_RPauldron: //23
rclavicle = insertBoundedPart(mesh , "Right Clavicle"); rclavicle = insertBoundedPart(mesh , group, "Right Clavicle");
break; break;
case ESM::PRT_LPauldron: //24 case ESM::PRT_LPauldron: //24
lclavicle = insertBoundedPart(mesh, "Left Clavicle"); lclavicle = insertBoundedPart(mesh, group, "Left Clavicle");
break; break;
case ESM::PRT_Weapon: //25 case ESM::PRT_Weapon: //25
break; break;
case ESM::PRT_Tail: //26 case ESM::PRT_Tail: //26
tail = insertBoundedPart(mesh, "Tail"); tail = insertBoundedPart(mesh, group, "Tail");
break; break;
} }
return true; return true;
@ -575,10 +580,15 @@ void NpcAnimation::addPartGroup(int group, int priority, std::vector<ESM::PartRe
bodypart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search(part.male); bodypart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search(part.male);
if(bodypart) if(bodypart)
addOrReplaceIndividualPart(part.part, group,priority,"meshes\\" + bodypart->model); addOrReplaceIndividualPart(part.part, group, priority,"meshes\\" + bodypart->model);
else else
reserveIndividualPart(part.part, group, priority); reserveIndividualPart(part.part, group, priority);
} }
} }
void NpcAnimation::forceUpdate ()
{
updateParts();
}
} }

View File

@ -65,10 +65,13 @@ private:
MWWorld::ContainerStoreIterator rightglove; MWWorld::ContainerStoreIterator rightglove;
MWWorld::ContainerStoreIterator skirtiter; MWWorld::ContainerStoreIterator skirtiter;
int mVisibilityFlags;
public: public:
NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRenderer& _rend, MWWorld::InventoryStore& _inv); NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node,
MWWorld::InventoryStore& _inv, int visibilityFlags);
virtual ~NpcAnimation(); virtual ~NpcAnimation();
NifOgre::EntityList insertBoundedPart(const std::string &mesh, const std::string &bonename); NifOgre::EntityList insertBoundedPart(const std::string &mesh, int group, const std::string &bonename);
virtual void runAnimation(float timepassed); virtual void runAnimation(float timepassed);
void updateParts(); void updateParts();
void removeEntities(NifOgre::EntityList &entities); void removeEntities(NifOgre::EntityList &entities);
@ -78,6 +81,8 @@ public:
bool addOrReplaceIndividualPart(int type, int group, int priority, const std::string &mesh); bool addOrReplaceIndividualPart(int type, int group, int priority, const std::string &mesh);
void removePartGroup(int group); void removePartGroup(int group);
void addPartGroup(int group, int priority, std::vector<ESM::PartReference>& parts); void addPartGroup(int group, int priority, std::vector<ESM::PartReference>& parts);
void forceUpdate();
}; };
} }

View File

@ -35,6 +35,11 @@ namespace MWRender
mPreviewCam.yaw = 0.f; mPreviewCam.yaw = 0.f;
mPreviewCam.offset = 400.f; mPreviewCam.offset = 400.f;
} }
Player::~Player()
{
delete mAnimation;
}
bool Player::rotate(const Ogre::Vector3 &rot, bool adjust) bool Player::rotate(const Ogre::Vector3 &rot, bool adjust)
{ {

View File

@ -63,6 +63,7 @@ namespace MWRender
public: public:
Player (Ogre::Camera *camera, Ogre::SceneNode* mNode); Player (Ogre::Camera *camera, Ogre::SceneNode* mNode);
~Player();
/// Set where the player is looking at. Uses Morrowind (euler) angles /// Set where the player is looking at. Uses Morrowind (euler) angles
/// \param rot Rotation angles in radians /// \param rot Rotation angles in radians

View File

@ -41,7 +41,7 @@ enum VisibilityFlags
// Water // Water
RV_Water = 8, RV_Water = 8,
// Actors (player, npcs, creatures) // Actors (npcs, creatures)
RV_Actors = 16, RV_Actors = 16,
// Misc objects (containers, dynamic objects) // Misc objects (containers, dynamic objects)
@ -54,6 +54,8 @@ enum VisibilityFlags
RV_OcclusionQuery = 256, RV_OcclusionQuery = 256,
RV_PlayerPreview = 512,
RV_Map = RV_Terrain + RV_Statics + RV_StaticsSmall + RV_Misc + RV_Water RV_Map = RV_Terrain + RV_Statics + RV_StaticsSmall + RV_Misc + RV_Water
/// \todo markers (normally hidden) /// \todo markers (normally hidden)

View File

@ -34,6 +34,7 @@
#include "water.hpp" #include "water.hpp"
#include "compositors.hpp" #include "compositors.hpp"
#include "npcanimation.hpp" #include "npcanimation.hpp"
#include "externalrendering.hpp"
using namespace MWRender; using namespace MWRender;
using namespace Ogre; using namespace Ogre;
@ -94,7 +95,7 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
if (filter == "anisotropic") tfo = TFO_ANISOTROPIC; if (filter == "anisotropic") tfo = TFO_ANISOTROPIC;
else if (filter == "trilinear") tfo = TFO_TRILINEAR; else if (filter == "trilinear") tfo = TFO_TRILINEAR;
else if (filter == "bilinear") tfo = TFO_BILINEAR; else if (filter == "bilinear") tfo = TFO_BILINEAR;
else if (filter == "none") tfo = TFO_NONE; else /*if (filter == "none")*/ tfo = TFO_NONE;
MaterialManager::getSingleton().setDefaultTextureFiltering(tfo); MaterialManager::getSingleton().setDefaultTextureFiltering(tfo);
MaterialManager::getSingleton().setDefaultAnisotropy( (filter == "anisotropic") ? Settings::Manager::getInt("anisotropy", "General") : 1 ); MaterialManager::getSingleton().setDefaultAnisotropy( (filter == "anisotropic") ? Settings::Manager::getInt("anisotropy", "General") : 1 );
@ -137,7 +138,7 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
// Morrowind uses, and it automagically makes everything work as it // Morrowind uses, and it automagically makes everything work as it
// should. // should.
SceneNode *rt = mRendering.getScene()->getRootSceneNode(); SceneNode *rt = mRendering.getScene()->getRootSceneNode();
mMwRoot = rt->createChildSceneNode(); mMwRoot = rt->createChildSceneNode("mwRoot");
mMwRoot->pitch(Degree(-90)); mMwRoot->pitch(Degree(-90));
mObjects.setMwRoot(mMwRoot); mObjects.setMwRoot(mMwRoot);
@ -723,7 +724,7 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec
if (filter == "anisotropic") tfo = TFO_ANISOTROPIC; if (filter == "anisotropic") tfo = TFO_ANISOTROPIC;
else if (filter == "trilinear") tfo = TFO_TRILINEAR; else if (filter == "trilinear") tfo = TFO_TRILINEAR;
else if (filter == "bilinear") tfo = TFO_BILINEAR; else if (filter == "bilinear") tfo = TFO_BILINEAR;
else if (filter == "none") tfo = TFO_NONE; else /*if (filter == "none")*/ tfo = TFO_NONE;
MaterialManager::getSingleton().setDefaultTextureFiltering(tfo); MaterialManager::getSingleton().setDefaultTextureFiltering(tfo);
MaterialManager::getSingleton().setDefaultAnisotropy( (filter == "anisotropic") ? Settings::Manager::getInt("anisotropy", "General") : 1 ); MaterialManager::getSingleton().setDefaultAnisotropy( (filter == "anisotropic") ? Settings::Manager::getInt("anisotropy", "General") : 1 );
@ -858,9 +859,8 @@ void RenderingManager::renderPlayer(const MWWorld::Ptr &ptr)
{ {
MWRender::NpcAnimation *anim = MWRender::NpcAnimation *anim =
new MWRender::NpcAnimation( new MWRender::NpcAnimation(
ptr, ptr, ptr.getRefData ().getBaseNode (),
mRendering, MWWorld::Class::get(ptr).getInventoryStore(ptr), RV_Actors
MWWorld::Class::get(ptr).getInventoryStore(ptr)
); );
mPlayer->setAnimation(anim); mPlayer->setAnimation(anim);
} }
@ -882,4 +882,9 @@ bool RenderingManager::isPositionExplored (float nX, float nY, int x, int y, boo
return mLocalMap->isPositionExplored(nX, nY, x, y, interior); return mLocalMap->isPositionExplored(nX, nY, x, y, interior);
} }
void RenderingManager::setupExternalRendering (MWRender::ExternalRendering& rendering)
{
rendering.setup (mRendering.getScene());
}
} // namespace } // namespace

View File

@ -43,6 +43,7 @@ namespace MWRender
class LocalMap; class LocalMap;
class Water; class Water;
class Compositors; class Compositors;
class ExternalRendering;
class RenderingManager: private RenderingInterface, public Ogre::WindowEventListener { class RenderingManager: private RenderingInterface, public Ogre::WindowEventListener {
@ -185,12 +186,14 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList
static bool waterShaderSupported(); static bool waterShaderSupported();
virtual void getInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y); void getInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y);
///< see MWRender::LocalMap::getInteriorMapPosition ///< see MWRender::LocalMap::getInteriorMapPosition
virtual bool isPositionExplored (float nX, float nY, int x, int y, bool interior); bool isPositionExplored (float nX, float nY, int x, int y, bool interior);
///< see MWRender::LocalMap::isPositionExplored ///< see MWRender::LocalMap::isPositionExplored
void setupExternalRendering (MWRender::ExternalRendering& rendering);
protected: protected:
virtual void windowResized(Ogre::RenderWindow* rw); virtual void windowResized(Ogre::RenderWindow* rw);
virtual void windowClosed(Ogre::RenderWindow* rw); virtual void windowClosed(Ogre::RenderWindow* rw);

View File

@ -183,4 +183,8 @@ op 0x2000172: GetStartingAngle
op 0x2000173: GetStartingAngle, explicit reference op 0x2000173: GetStartingAngle, explicit reference
op 0x2000174: ToggleVanityMode op 0x2000174: ToggleVanityMode
op 0x2000175-0x200018B: Get controls disabled op 0x2000175-0x200018B: Get controls disabled
opcodes 0x200018C-0x3ffffff unused op 0x200018C: GetLevel
op 0x200018D: GetLevel, explicit reference
op 0x200018E: SetLevel
op 0x200018F: SetLevel, explicit reference
opcodes 0x200018F-0x3ffffff unused

View File

@ -30,6 +30,16 @@ namespace MWScript
} }
}; };
class OpEnableRest : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWBase::Environment::get().getWindowManager()->enableRest();
}
};
class OpShowDialogue : public Interpreter::Opcode0 class OpShowDialogue : public Interpreter::Opcode0
{ {
MWGui::GuiMode mDialogue; MWGui::GuiMode mDialogue;
@ -146,12 +156,8 @@ opcodeEnableStatsReviewMenu);
interpreter.installSegment5 (opcodeEnableStatsMenu, interpreter.installSegment5 (opcodeEnableStatsMenu,
new OpEnableWindow (MWGui::GW_Stats)); new OpEnableWindow (MWGui::GW_Stats));
/* Not done yet. Enabling rest mode is not really a gui
issue, it's a gameplay issue.
interpreter.installSegment5 (opcodeEnableRest, interpreter.installSegment5 (opcodeEnableRest,
new OpEnableDialogue (MWGui::GM_Rest)); new OpEnableRest ());
*/
interpreter.installSegment5 (opcodeShowRestMenu, interpreter.installSegment5 (opcodeShowRestMenu,
new OpShowDialogue (MWGui::GM_Rest)); new OpShowDialogue (MWGui::GM_Rest));

View File

@ -32,6 +32,42 @@ namespace MWScript
{ {
namespace Stats namespace Stats
{ {
template<class R>
class OpGetLevel : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Integer value =
MWWorld::Class::get (ptr)
.getCreatureStats (ptr)
.getLevel();
runtime.push (value);
}
};
template<class R>
class OpSetLevel : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Integer value = runtime[0].mInteger;
runtime.pop();
MWWorld::Class::get (ptr)
.getCreatureStats (ptr)
.setLevel(value);
}
};
template<class R> template<class R>
class OpGetAttribute : public Interpreter::Opcode0 class OpGetAttribute : public Interpreter::Opcode0
{ {
@ -592,6 +628,11 @@ namespace MWScript
const int opcodeModDisposition = 0x200014d; const int opcodeModDisposition = 0x200014d;
const int opcodeModDispositionExplicit = 0x200014e; const int opcodeModDispositionExplicit = 0x200014e;
const int opcodeGetLevel = 0x200018c;
const int opcodeGetLevelExplicit = 0x200018d;
const int opcodeSetLevel = 0x200018e;
const int opcodeSetLevelExplicit = 0x200018f;
void registerExtensions (Compiler::Extensions& extensions) void registerExtensions (Compiler::Extensions& extensions)
{ {
static const char *attributes[numberOfAttributes] = static const char *attributes[numberOfAttributes] =
@ -674,6 +715,9 @@ namespace MWScript
extensions.registerInstruction("moddisposition","l",opcodeModDisposition, extensions.registerInstruction("moddisposition","l",opcodeModDisposition,
opcodeModDispositionExplicit); opcodeModDispositionExplicit);
extensions.registerFunction("getpcrank",'l',"/S",opcodeGetPCRank,opcodeGetPCRankExplicit); extensions.registerFunction("getpcrank",'l',"/S",opcodeGetPCRank,opcodeGetPCRankExplicit);
extensions.registerInstruction("setlevel", "l", opcodeSetLevel, opcodeSetLevelExplicit);
extensions.registerFunction("getlevel", 'l', "", opcodeGetLevel, opcodeGetLevelExplicit);
} }
void installOpcodes (Interpreter::Interpreter& interpreter) void installOpcodes (Interpreter::Interpreter& interpreter)
@ -745,6 +789,12 @@ namespace MWScript
interpreter.installSegment5(opcodeModDispositionExplicit,new OpModDisposition<ExplicitRef>); interpreter.installSegment5(opcodeModDispositionExplicit,new OpModDisposition<ExplicitRef>);
interpreter.installSegment3(opcodeGetPCRank,new OpGetPCRank<ImplicitRef>); interpreter.installSegment3(opcodeGetPCRank,new OpGetPCRank<ImplicitRef>);
interpreter.installSegment3(opcodeGetPCRankExplicit,new OpGetPCRank<ExplicitRef>); interpreter.installSegment3(opcodeGetPCRankExplicit,new OpGetPCRank<ExplicitRef>);
interpreter.installSegment5 (opcodeGetLevel, new OpGetLevel<ImplicitRef>);
interpreter.installSegment5 (opcodeGetLevelExplicit, new OpGetLevel<ExplicitRef>);
interpreter.installSegment5 (opcodeSetLevel, new OpSetLevel<ImplicitRef>);
interpreter.installSegment5 (opcodeSetLevelExplicit, new OpSetLevel<ExplicitRef>);
} }
} }
} }

View File

@ -2,10 +2,18 @@
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/class.hpp"
#include "../mwmechanics/npcstats.hpp"
#include "../mwgui/bookwindow.hpp" #include "../mwgui/bookwindow.hpp"
#include "../mwgui/scrollwindow.hpp" #include "../mwgui/scrollwindow.hpp"
#include <components/esm_store/store.hpp>
namespace MWWorld namespace MWWorld
{ {
ActionRead::ActionRead (const MWWorld::Ptr& object) : Action (false, object) ActionRead::ActionRead (const MWWorld::Ptr& object) : Action (false, object)
@ -26,5 +34,23 @@ namespace MWWorld
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Book); MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Book);
MWBase::Environment::get().getWindowManager()->getBookWindow()->open(getTarget()); MWBase::Environment::get().getWindowManager()->getBookWindow()->open(getTarget());
} }
/*
// Skill gain from books
if (ref->base->data.skillID >= 0 && ref->base->data.skillID < ESM::Skill::Length)
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayer().getPlayer();
MWMechanics::NpcStats& npcStats = MWWorld::Class::get(player).getNpcStats (player);
MWWorld::LiveCellRef<ESM::NPC> *playerRef = player.get<ESM::NPC>();
const ESM::Class *class_ = MWBase::Environment::get().getWorld()->getStore().classes.find (
playerRef->base->cls);
npcStats.increaseSkill (ref->base->data.skillID, *class_, true);
/// \todo Remove skill from the book. Right now you can read as many times as you want
/// and the skill will still increase.
}
*/
} }
} }

View File

@ -1222,4 +1222,9 @@ namespace MWWorld
{ {
mRendering->renderPlayer(mPlayer->getPlayer()); mRendering->renderPlayer(mPlayer->getPlayer());
} }
void World::setupExternalRendering (MWRender::ExternalRendering& rendering)
{
mRendering->setupExternalRendering (rendering);
}
} }

View File

@ -307,6 +307,8 @@ namespace MWWorld
} }
virtual void renderPlayer(); virtual void renderPlayer();
virtual void setupExternalRendering (MWRender::ExternalRendering& rendering);
}; };
} }

2
extern/shiny vendored

@ -1 +1 @@
Subproject commit 7168415233905de2864eec71ed4312cb8f83059b Subproject commit 4750676ac46a7aaa86bca53dc68c5a1ba11f3bc1

View File

@ -40,7 +40,9 @@ set(MATERIAL_FILES
water.mat water.mat
water.shader water.shader
water.shaderset water.shaderset
selection.mat
selection.shader
selection.shaderset
) )
copy_all_files(${CMAKE_CURRENT_SOURCE_DIR}/water "${OpenMW_BINARY_DIR}/resources/water/" "${WATER_FILES}") copy_all_files(${CMAKE_CURRENT_SOURCE_DIR}/water "${OpenMW_BINARY_DIR}/resources/water/" "${WATER_FILES}")

View File

@ -0,0 +1,8 @@
material SelectionColour
{
pass
{
vertex_program selection_vertex
fragment_program selection_fragment
}
}

View File

@ -0,0 +1,24 @@
#include "core.h"
#ifdef SH_VERTEX_SHADER
SH_BEGIN_PROGRAM
shUniform(float4x4, wvp) @shAutoConstant(wvp, worldviewproj_matrix)
SH_START_PROGRAM
{
shOutputPosition = shMatrixMult(wvp, shInputPosition);
}
#else
SH_BEGIN_PROGRAM
shUniform(float4, colour) @shAutoConstant(colour, custom, 1)
SH_START_PROGRAM
{
shOutputColour(0) = colour;
//shOutputColour(0) = float4(1,0,0,1);
}
#endif

View File

@ -0,0 +1,15 @@
shader_set selection_vertex
{
source selection.shader
type vertex
profiles_cg vs_2_0 arbvp1
profiles_hlsl vs_2_0
}
shader_set selection_fragment
{
source selection.shader
type fragment
profiles_cg ps_2_x ps_2_0 ps arbfp1
profiles_hlsl ps_2_0
}

View File

@ -35,7 +35,7 @@ set(MYGUI_FILES
openmw_dialogue_window.layout openmw_dialogue_window.layout
openmw_dialogue_window_skin.xml openmw_dialogue_window_skin.xml
openmw_edit.skin.xml openmw_edit.skin.xml
openmw.font.xml openmw_font.xml
openmw_hud_box.skin.xml openmw_hud_box.skin.xml
openmw_hud_energybar.skin.xml openmw_hud_energybar.skin.xml
openmw_hud.layout openmw_hud.layout
@ -51,7 +51,7 @@ set(MYGUI_FILES
openmw_map_window.layout openmw_map_window.layout
openmw_map_window_skin.xml openmw_map_window_skin.xml
openmw_messagebox.layout openmw_messagebox.layout
openmw.pointer.xml openmw_pointer.xml
openmw_progress.skin.xml openmw_progress.skin.xml
openmw_resources.xml openmw_resources.xml
openmw_scroll.layout openmw_scroll.layout
@ -72,6 +72,7 @@ set(MYGUI_FILES
openmw_magicselection_dialog.layout openmw_magicselection_dialog.layout
openmw_spell_buying_window.layout openmw_spell_buying_window.layout
openmw_loading_screen.layout openmw_loading_screen.layout
openmw_levelup_dialog.layout
smallbars.png smallbars.png
VeraMono.ttf VeraMono.ttf
markers.png markers.png

View File

@ -4,8 +4,8 @@
<List file="core.skin" /> <List file="core.skin" />
<List file="openmw_resources.xml" /> <List file="openmw_resources.xml" />
<List file="openmw_layers.xml" /> <List file="openmw_layers.xml" />
<List file="openmw.pointer.xml" /> <List file="openmw_pointer.xml" />
<List file="openmw.font.xml" /> <List file="openmw_font.xml" />
<List file="openmw_text.skin.xml" /> <List file="openmw_text.skin.xml" />
<List file="openmw_windows.skin.xml" /> <List file="openmw_windows.skin.xml" />
<List file="openmw_button.skin.xml" /> <List file="openmw_button.skin.xml" />

View File

@ -8,11 +8,13 @@
<Property key="Caption" value="Appearance"/> <Property key="Caption" value="Appearance"/>
<Property key="TextAlign" value="ALIGN_LEFT ALIGN_TOP"/> <Property key="TextAlign" value="ALIGN_LEFT ALIGN_TOP"/>
</Widget> </Widget>
<Widget type="Canvas" skin="MW_Box" position="8 39 241 230" name="AppearanceBox"/> <Widget type="Widget" skin="MW_Box" position="8 39 241 230">
<Widget type="ImageBox" skin="ImageBox" position_real="0 0 1 1" align="Stretch" name="PreviewImage"/>
</Widget>
<!-- Sliders --> <!-- Sliders -->
<!-- Rotation of head --> <!-- Rotation of head -->
<Widget type="HScroll" skin="MW_HScroll" position="8 276 241 14" name="HeadRotate"/> <Widget type="ScrollBar" skin="MW_HScroll" position="8 276 241 14" name="HeadRotate"/>
<!-- Gender choice --> <!-- Gender choice -->
<Widget type="Button" skin="MW_ScrollLeft" position="8 298 14 14" name="PrevGenderButton"/> <Widget type="Button" skin="MW_ScrollLeft" position="8 298 14 14" name="PrevGenderButton"/>

View File

@ -12,8 +12,13 @@
<!-- Avatar --> <!-- Avatar -->
<Widget type="Widget" skin="MW_Box" position="8 38 212 185" name="Avatar" align="Left Top Stretch"> <Widget type="Widget" skin="MW_Box" position="8 38 212 185" name="Avatar" align="Left Top Stretch">
<UserString key="ToolTipType" value="AvatarItemSelection"/>
<Widget type="ImageBox" skin="ImageBox" position="0 0 212 185" align="Stretch" name="AvatarImage">
<Property key="NeedMouse" value="false"/>
</Widget>
<Widget type="TextBox" skin="ProgressText" position="0 150 212 24" align="HCenter Bottom" name="ArmorRating"> <Widget type="TextBox" skin="ProgressText" position="0 150 212 24" align="HCenter Bottom" name="ArmorRating">
<Property key="Caption" value="Armor Rating"/> <Property key="Caption" value="Armor Rating"/>
<Property key="NeedMouse" value="false"/>
</Widget> </Widget>
</Widget> </Widget>

View File

@ -0,0 +1,138 @@
<?xml version="1.0" encoding="UTF-8"?>
<MyGUI type="Layout">
<Widget type="Window" skin="MW_Dialog" layer="Windows" position="0 0 440 438" name="_Main">
<Widget type="Widget" skin="MW_Box" position="28 14 391 198">
<Widget type="ImageBox" skin="ImageBox" name="ClassImage" position="4 4 383 190">
</Widget>
</Widget>
<Widget type="TextBox" skin="SandText" position="28 218 391 24" name="LevelText">
</Widget>
<Widget type="Widget" skin="" position="36 280 400 400">
<Widget type="TextBox" skin="SandText" position="0 0 100 24" name="AttribMultiplier1"/>
<Widget type="TextBox" skin="SandText" position="0 24 100 24" name="AttribMultiplier2"/>
<Widget type="TextBox" skin="SandText" position="0 48 100 24" name="AttribMultiplier3"/>
<Widget type="TextBox" skin="SandText" position="0 72 100 24" name="AttribMultiplier4"/>
<Widget type="TextBox" skin="SandText" position="200 0 100 24" name="AttribMultiplier5"/>
<Widget type="TextBox" skin="SandText" position="200 24 100 24" name="AttribMultiplier6"/>
<Widget type="TextBox" skin="SandText" position="200 48 100 24" name="AttribMultiplier7"/>
<Widget type="TextBox" skin="SandText" position="200 72 100 24" name="AttribMultiplier8"/>
<Widget type="HBox" position="22 0 200 24">
<Widget type="AutoSizedButton" skin="SandTextButton" name="Attrib1">
<UserString key="ToolTipType" value="Layout"/>
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
<UserString key="Caption_AttributeName" value="#{sAttributeStrength}"/>
<UserString key="Caption_AttributeDescription" value="#{sStrDesc}"/>
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_strength.dds"/>
<Property key="Caption" value="#{sAttributeStrength}"/>
</Widget>
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal1">
</Widget>
</Widget>
<Widget type="HBox" position="22 24 200 24">
<Widget type="AutoSizedButton" skin="SandTextButton" name="Attrib2">
<UserString key="ToolTipType" value="Layout"/>
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
<UserString key="Caption_AttributeName" value="#{sAttributeIntelligence}"/>
<UserString key="Caption_AttributeDescription" value="#{sIntDesc}"/>
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_int.dds"/>
<Property key="Caption" value="#{sAttributeIntelligence}"/>
</Widget>
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal2">
</Widget>
</Widget>
<Widget type="HBox" position="22 48 200 24">
<Widget type="AutoSizedButton" skin="SandTextButton" name="Attrib3">
<UserString key="ToolTipType" value="Layout"/>
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
<UserString key="Caption_AttributeName" value="#{sAttributeWillpower}"/>
<UserString key="Caption_AttributeDescription" value="#{sWilDesc}"/>
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_wilpower.dds"/>
<Property key="Caption" value="#{sAttributeWillpower}"/>
</Widget>
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal3">
</Widget>
</Widget>
<Widget type="HBox" position="22 72 200 24">
<Widget type="AutoSizedButton" skin="SandTextButton" name="Attrib4">
<UserString key="ToolTipType" value="Layout"/>
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
<UserString key="Caption_AttributeName" value="#{sAttributeAgility}"/>
<UserString key="Caption_AttributeDescription" value="#{sAgiDesc}"/>
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_agility.dds"/>
<Property key="Caption" value="#{sAttributeAgility}"/>
</Widget>
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal4">
</Widget>
</Widget>
<Widget type="HBox" position="222 0 200 24">
<Widget type="AutoSizedButton" skin="SandTextButton" name="Attrib5">
<UserString key="ToolTipType" value="Layout"/>
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
<UserString key="Caption_AttributeName" value="#{sAttributeSpeed}"/>
<UserString key="Caption_AttributeDescription" value="#{sSpdDesc}"/>
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_speed.dds"/>
<Property key="Caption" value="#{sAttributeSpeed}"/>
</Widget>
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal5">
</Widget>
</Widget>
<Widget type="HBox" position="222 24 200 24">
<Widget type="AutoSizedButton" skin="SandTextButton" name="Attrib6">
<UserString key="ToolTipType" value="Layout"/>
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
<UserString key="Caption_AttributeName" value="#{sAttributeEndurance}"/>
<UserString key="Caption_AttributeDescription" value="#{sEndDesc}"/>
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_endurance.dds"/>
<Property key="Caption" value="#{sAttributeEndurance}"/>
</Widget>
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal6">
</Widget>
</Widget>
<Widget type="HBox" position="222 48 200 24">
<Widget type="AutoSizedButton" skin="SandTextButton" name="Attrib7">
<UserString key="ToolTipType" value="Layout"/>
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
<UserString key="Caption_AttributeName" value="#{sAttributePersonality}"/>
<UserString key="Caption_AttributeDescription" value="#{sPerDesc}"/>
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_personality.dds"/>
<Property key="Caption" value="#{sAttributePersonality}"/>
</Widget>
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal7">
</Widget>
</Widget>
<Widget type="HBox" position="222 72 200 24">
<Widget type="AutoSizedButton" skin="SandTextButton" name="Attrib8">
<UserString key="ToolTipType" value="Layout"/>
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
<UserString key="Caption_AttributeName" value="#{sAttributeLuck}"/>
<UserString key="Caption_AttributeDescription" value="#{sLucDesc}"/>
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_luck.dds"/>
<Property key="Caption" value="#{sAttributeLuck}"/>
</Widget>
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal8">
</Widget>
</Widget>
</Widget>
<Widget type="AutoSizedButton" skin="MW_Button" position="422 398 0 24" name="OkButton">
<Property key="ExpandDirection" value="Left"/>
<Property key="Caption" value="#{sOk}"/>
</Widget>
</Widget>
</MyGUI>

View File

@ -215,7 +215,7 @@ void OgreRenderer::createWindow(const std::string &title, const WindowSettings&
mWindow = mRoot->createRenderWindow(title, settings.window_x, settings.window_y, settings.fullscreen, &params); mWindow = mRoot->createRenderWindow(title, settings.window_x, settings.window_y, settings.fullscreen, &params);
// create the semi-transparent black background texture used by the GUI. // create the semi-transparent black background texture used by the GUI.
// has to be created in code with TU_DYNAMIC_WRITE_ONLY_DISCARDABLE param // has to be created in code with TU_DYNAMIC_WRITE_ONLY param
// so that it can be modified at runtime. // so that it can be modified at runtime.
Ogre::TextureManager::getSingleton().createManual( Ogre::TextureManager::getSingleton().createManual(
"transparent.png", "transparent.png",
@ -224,7 +224,7 @@ void OgreRenderer::createWindow(const std::string &title, const WindowSettings&
1, 1, 1, 1,
0, 0,
Ogre::PF_A8R8G8B8, Ogre::PF_A8R8G8B8,
Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE); Ogre::TU_DYNAMIC_WRITE_ONLY);
} }
void OgreRenderer::createScene(const std::string& camName, float fov, float nearClip) void OgreRenderer::createScene(const std::string& camName, float fov, float nearClip)

View File

@ -0,0 +1,123 @@
#include "selectionbuffer.hpp"
#include <OgreHardwarePixelBuffer.h>
#include <OgreRenderTexture.h>
#include <OgreSubEntity.h>
#include <OgreEntity.h>
#include <stdexcept>
#include <extern/shiny/Main/Factory.hpp>
namespace OEngine
{
namespace Render
{
SelectionBuffer::SelectionBuffer(Ogre::Camera *camera, int sizeX, int sizeY, int visibilityFlags)
{
mTexture = Ogre::TextureManager::getSingleton().createManual("SelectionBuffer",
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, sizeX, sizeY, 0, Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET);
mRenderTarget = mTexture->getBuffer()->getRenderTarget();
Ogre::Viewport* vp = mRenderTarget->addViewport(camera);
vp->setOverlaysEnabled(false);
vp->setBackgroundColour(Ogre::ColourValue(0, 0, 0, 0));
vp->setShadowsEnabled(false);
vp->setMaterialScheme("selectionbuffer");
vp->setVisibilityMask (visibilityFlags);
mRenderTarget->setActive(true);
mRenderTarget->setAutoUpdated (false);
mCurrentColour = Ogre::ColourValue(0.3, 0.3, 0.3);
}
SelectionBuffer::~SelectionBuffer()
{
Ogre::TextureManager::getSingleton ().remove("SelectionBuffer");
}
void SelectionBuffer::update ()
{
Ogre::MaterialManager::getSingleton ().addListener (this);
mRenderTarget->update();
Ogre::MaterialManager::getSingleton ().removeListener (this);
mTexture->convertToImage(mBuffer);
}
int SelectionBuffer::getSelected(int xPos, int yPos)
{
Ogre::ColourValue clr = mBuffer.getColourAt (xPos, yPos, 0);
clr.a = 1;
if (mColourMap.find(clr) != mColourMap.end())
return mColourMap[clr];
else
return -1; // nothing selected
}
Ogre::Technique* SelectionBuffer::handleSchemeNotFound (
unsigned short schemeIndex, const Ogre::String &schemeName, Ogre::Material *originalMaterial,
unsigned short lodIndex, const Ogre::Renderable *rend)
{
if (schemeName == "selectionbuffer")
{
sh::Factory::getInstance ()._ensureMaterial ("SelectionColour", "Default");
Ogre::MaterialPtr m = Ogre::MaterialManager::getSingleton ().getByName("SelectionColour");
if(typeid(*rend) == typeid(Ogre::SubEntity))
{
const Ogre::SubEntity *subEntity = static_cast<const Ogre::SubEntity *>(rend);
int id = Ogre::any_cast<int>(subEntity->getParent ()->getUserObjectBindings().getUserAny());
bool found = false;
Ogre::ColourValue colour;
for (std::map<Ogre::ColourValue, int, cmp_ColourValue>::iterator it = mColourMap.begin(); it != mColourMap.end(); ++it)
{
if (it->second == id)
{
found = true;
colour = it->first;
}
}
if (!found)
{
getNextColour();
const_cast<Ogre::SubEntity *>(subEntity)->setCustomParameter(1, Ogre::Vector4(mCurrentColour.r, mCurrentColour.g, mCurrentColour.b, 1.0));
mColourMap[mCurrentColour] = id;
}
else
{
const_cast<Ogre::SubEntity *>(subEntity)->setCustomParameter(1, Ogre::Vector4(colour.r, colour.g, colour.b, 1.0));
}
assert(m->getTechnique(1));
return m->getTechnique(1);
}
else
throw std::runtime_error("selectionbuffer only works with entities");
}
return NULL;
}
void SelectionBuffer::getNextColour ()
{
Ogre::ARGB color = (float(rand()) / float(RAND_MAX)) * std::numeric_limits<Ogre::uint32>::max();
if (mCurrentColour.getAsARGB () == color)
{
getNextColour();
return;
}
mCurrentColour.setAsARGB(color);
mCurrentColour.a = 1;
}
}
}

View File

@ -0,0 +1,54 @@
#ifndef OENGINE_SELECTIONBUFFER_H
#define OENGINE_SELECTIONBUFFER_H
#include <OgreTexture.h>
#include <OgreRenderTarget.h>
#include <OgreMaterialManager.h>
namespace OEngine
{
namespace Render
{
struct cmp_ColourValue
{
bool operator()(const Ogre::ColourValue &a, const Ogre::ColourValue &b) const
{
return a.getAsBGRA() < b.getAsBGRA();
}
};
class SelectionBuffer : public Ogre::MaterialManager::Listener
{
public:
SelectionBuffer(Ogre::Camera* camera, int sizeX, int sizeY, int visibilityFlags);
virtual ~SelectionBuffer();
int getSelected(int xPos, int yPos);
///< @return ID of the selected object
void update();
virtual Ogre::Technique* handleSchemeNotFound (
unsigned short schemeIndex, const Ogre::String &schemeName, Ogre::Material *originalMaterial,
unsigned short lodIndex, const Ogre::Renderable *rend);
private:
Ogre::TexturePtr mTexture;
Ogre::RenderTexture* mRenderTarget;
Ogre::Image mBuffer;
std::map<Ogre::ColourValue, int, cmp_ColourValue> mColourMap;
Ogre::ColourValue mCurrentColour;
void getNextColour();
};
}
}
#endif