Merge remote-tracking branch 'remotes/upstream/master' into QtOgre

This reverts commit 0b133d5c2e0d258274ef5f272d7c1a185225673a, reversing
changes made to 3aea1bf5f9.
loadfix
cc9cii 10 years ago
commit c9e054cdd7

@ -259,20 +259,36 @@ int CS::Editor::run()
std::auto_ptr<sh::Factory> CS::Editor::setupGraphics()
{
// TODO: setting
Ogre::Root::getSingleton().setRenderSystem(Ogre::Root::getSingleton().getRenderSystemByName("OpenGL Rendering Subsystem"));
std::string renderer =
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
"Direct3D9 Rendering Subsystem";
#else
"OpenGL Rendering Subsystem";
#endif
std::string renderSystem = mUserSettings.setting("Video/render system", renderer.c_str()).toStdString();
Ogre::Root::getSingleton().setRenderSystem(Ogre::Root::getSingleton().getRenderSystemByName(renderSystem));
Ogre::Root::getSingleton().initialise(false);
// Create a hidden background window to keep resources
Ogre::NameValuePairList params;
params.insert(std::make_pair("title", ""));
params.insert(std::make_pair("FSAA", "0"));
std::string antialiasing = mUserSettings.settingValue("Video/antialiasing").toStdString();
if(antialiasing == "MSAA 16") antialiasing = "16";
else if(antialiasing == "MSAA 8") antialiasing = "8";
else if(antialiasing == "MSAA 4") antialiasing = "4";
else if(antialiasing == "MSAA 2") antialiasing = "2";
else antialiasing = "0";
params.insert(std::make_pair("FSAA", antialiasing));
params.insert(std::make_pair("vsync", "false"));
params.insert(std::make_pair("hidden", "true"));
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
params.insert(std::make_pair("macAPI", "cocoa"));
#endif
// NOTE: fullscreen mode not supported (doesn't really make sense for opencs)
Ogre::RenderWindow* hiddenWindow = Ogre::Root::getSingleton().createRenderWindow("InactiveHidden", 1, 1, false, &params);
hiddenWindow->setActive(false);
@ -286,7 +302,28 @@ std::auto_ptr<sh::Factory> CS::Editor::setupGraphics()
std::auto_ptr<sh::Factory> factory (new sh::Factory (platform));
factory->setCurrentLanguage (sh::Language_GLSL); /// \todo make this configurable
QString shLang = mUserSettings.settingValue("General/shader mode");
QString rend = renderSystem.c_str();
bool openGL = rend.contains(QRegExp("^OpenGL", Qt::CaseInsensitive));
bool glES = rend.contains(QRegExp("^OpenGL ES", Qt::CaseInsensitive));
// force shader language based on render system
if(shLang == ""
|| (openGL && shLang == "hlsl")
|| (!openGL && shLang == "glsl")
|| (glES && shLang != "glsles"))
{
shLang = openGL ? (glES ? "glsles" : "glsl") : "hlsl";
//no group means "General" group in the "ini" file standard
mUserSettings.setDefinitions("shader mode", (QStringList() << shLang));
}
enum sh::Language lang;
if(shLang == "glsl") lang = sh::Language_GLSL;
else if(shLang == "glsles") lang = sh::Language_GLSLES;
else if(shLang == "hlsl") lang = sh::Language_HLSL;
else lang = sh::Language_CG;
factory->setCurrentLanguage (lang);
factory->setWriteSourceCache (true);
factory->setReadSourceCache (true);
factory->setReadMicrocodeCache (true);
@ -294,16 +331,27 @@ std::auto_ptr<sh::Factory> CS::Editor::setupGraphics()
factory->loadAllFiles();
sh::Factory::getInstance().setGlobalSetting ("fog", "true");
bool shaders = mUserSettings.setting("Objects/shaders", QString("true")) == "true" ? true : false;
sh::Factory::getInstance ().setShadersEnabled (shaders);
std::string fog = mUserSettings.setting("Shader/fog", QString("true")).toStdString();
sh::Factory::getInstance().setGlobalSetting ("fog", fog);
std::string shadows = mUserSettings.setting("Shader/shadows", QString("false")).toStdString();
sh::Factory::getInstance().setGlobalSetting ("shadows", shadows);
sh::Factory::getInstance().setGlobalSetting ("shadows", "false");
sh::Factory::getInstance().setGlobalSetting ("shadows_pssm", "false");
std::string shadows_pssm = mUserSettings.setting("Shader/shadows_pssm", QString("false")).toStdString();
sh::Factory::getInstance().setGlobalSetting ("shadows_pssm", shadows_pssm);
sh::Factory::getInstance ().setGlobalSetting ("render_refraction", "false");
std::string render_refraction = mUserSettings.setting("Shader/render_refraction", QString("false")).toStdString();
sh::Factory::getInstance ().setGlobalSetting ("render_refraction", render_refraction);
// internal setting - may be switched on or off by the use of shader configurations
sh::Factory::getInstance ().setGlobalSetting ("viewproj_fix", "false");
sh::Factory::getInstance ().setGlobalSetting ("num_lights", "8");
std::string num_lights = mUserSettings.setting("Objects/num_lights", QString("8")).toStdString();
sh::Factory::getInstance ().setGlobalSetting ("num_lights", num_lights);
/// \todo add more configurable shiny settings

@ -194,6 +194,16 @@ QString CSMSettings::Setting::page() const
return property (Property_Page).at(0);
}
void CSMSettings::Setting::setStyleSheet (const QString &value)
{
setProperty (Property_StyleSheet, value);
}
QString CSMSettings::Setting::styleSheet() const
{
return property (Property_StyleSheet).at(0);
}
void CSMSettings::Setting::setPrefix (const QString &value)
{
setProperty (Property_Prefix, value);

@ -80,6 +80,9 @@ namespace CSMSettings
void setPage (const QString &value);
QString page() const;
void setStyleSheet (const QString &value);
QString styleSheet() const;
void setPrefix (const QString &value);
QString prefix() const;

@ -35,12 +35,13 @@ namespace CSMSettings
Property_TickInterval = 19,
Property_TicksAbove = 20,
Property_TicksBelow = 21,
Property_StyleSheet = 22,
//Stringlists should always be the last items
Property_DefaultValues = 22,
Property_DeclaredValues = 23,
Property_DefinedValues = 24,
Property_Proxies = 25
Property_DefaultValues = 23,
Property_DeclaredValues = 24,
Property_DefinedValues = 25,
Property_Proxies = 26
};
///Basic setting widget types.
@ -106,7 +107,7 @@ namespace CSMSettings
"is_multi_line", "widget_width", "view_row", "view_column", "delimiter",
"is_serializable","column_span", "row_span", "minimum", "maximum",
"special_value_text", "prefix", "suffix", "single_step", "wrapping",
"tick_interval", "ticks_above", "ticks_below",
"tick_interval", "ticks_above", "ticks_below", "stylesheet",
"defaults", "declarations", "definitions", "proxies"
};
@ -135,6 +136,7 @@ namespace CSMSettings
"1", //tick interval
"false", //ticks above
"true", //ticks below
"", //StyleSheet
"", //default values
"", //declared values
"", //defined values

@ -4,12 +4,16 @@
#include <QFile>
#include <components/files/configurationmanager.hpp>
#include <components/settings/settings.hpp>
#include <boost/version.hpp>
#include "setting.hpp"
#include "support.hpp"
#include <QTextCodec>
#include <QDebug>
#include <extern/shiny/Main/Factory.hpp>
/**
* Workaround for problems with whitespaces in paths in older versions of Boost library
*/
@ -28,20 +32,111 @@ namespace boost
CSMSettings::UserSettings *CSMSettings::UserSettings::mUserSettingsInstance = 0;
CSMSettings::UserSettings::UserSettings (const Files::ConfigurationManager& configurationManager)
: mCfgMgr (configurationManager)
CSMSettings::UserSettings::UserSettings (const Files::ConfigurationManager& configurationManager)
: mCfgMgr (configurationManager)
, mSettingDefinitions(NULL)
, mSettingCfgDefinitions(NULL)
{
assert(!mUserSettingsInstance);
mUserSettingsInstance = this;
mSettingDefinitions = 0;
buildSettingModelDefaults();
// for overriding opencs.ini settings with those from settings.cfg
mSettingCfgDefinitions = new QSettings(QSettings::IniFormat, QSettings::UserScope, "", QString(), this);
}
void CSMSettings::UserSettings::buildSettingModelDefaults()
{
QString section = "Window Size";
QString section;
section = "Objects";
{
Setting *numLights = createSetting (Type_SpinBox, section, "num_lights");
numLights->setDefaultValue(8);
numLights->setEditorSetting(true);
numLights->setColumnSpan (1);
numLights->setMinimum (0);
numLights->setMaximum (100); // FIXME: not sure what the max value should be
numLights->setWidgetWidth (10);
numLights->setViewLocation(1, 2);
Setting *shaders = createSetting (Type_CheckBox, section, "shaders");
shaders->setDeclaredValues(QStringList() << "true" << "false");
shaders->setDefaultValue("true");
shaders->setEditorSetting(true);
shaders->setSpecialValueText("Enable Shaders");
shaders->setWidgetWidth(25);
shaders->setColumnSpan (3);
shaders->setStyleSheet ("QGroupBox { border: 0px; }");
shaders->setViewLocation(2, 1);
}
section = "Scene";
{
Setting *fastFactor = createSetting (Type_SpinBox, section, "fast factor");
fastFactor->setDefaultValue(4);
fastFactor->setEditorSetting(true);
fastFactor->setColumnSpan (1);
fastFactor->setMinimum (1);
fastFactor->setSpecialValueText ("1"); // FIXME: workaround
fastFactor->setMaximum (100); // FIXME: not sure what the max value should be
fastFactor->setWidgetWidth (10);
fastFactor->setViewLocation(1, 2);
Setting *farClipDist = createSetting (Type_DoubleSpinBox, section, "far clip distance");
farClipDist->setDefaultValue(300000);
farClipDist->setEditorSetting(true);
farClipDist->setColumnSpan (1);
farClipDist->setMinimum (0);
farClipDist->setMaximum (1000000); // FIXME: not sure what the max value should be
farClipDist->setWidgetWidth (10);
farClipDist->setViewLocation(2, 2);
Setting *timerStart = createSetting (Type_SpinBox, section, "timer start");
timerStart->setDefaultValue(20);
timerStart->setEditorSetting(true);
timerStart->setColumnSpan (1);
timerStart->setMinimum (0);
timerStart->setMaximum (100); // FIXME: not sure what the max value should be
timerStart->setWidgetWidth (10);
timerStart->setViewLocation(3, 2);
}
section = "SubView";
{
Setting *maxSubView = createSetting (Type_SpinBox, section, "max subviews");
maxSubView->setDefaultValue(256);
maxSubView->setEditorSetting(true);
maxSubView->setColumnSpan (1);
maxSubView->setMinimum (1);
maxSubView->setSpecialValueText ("1");
maxSubView->setMaximum (256); // FIXME: not sure what the max value should be
maxSubView->setWidgetWidth (10);
maxSubView->setViewLocation(1, 2);
Setting *minWidth = createSetting (Type_SpinBox, section, "minimum width");
minWidth->setDefaultValue(325);
minWidth->setEditorSetting(true);
minWidth->setColumnSpan (1);
minWidth->setMinimum (50);
minWidth->setSpecialValueText ("50");
minWidth->setMaximum (10000); // FIXME: not sure what the max value should be
minWidth->setWidgetWidth (10);
minWidth->setViewLocation(2, 2);
Setting *reuse = createSetting (Type_CheckBox, section, "reuse");
reuse->setDeclaredValues(QStringList() << "true" << "false");
reuse->setDefaultValue("true");
reuse->setEditorSetting(true);
reuse->setSpecialValueText("Reuse SubView");
reuse->setWidgetWidth(25);
reuse->setColumnSpan (3);
reuse->setStyleSheet ("QGroupBox { border: 0px; }");
reuse->setViewLocation(3, 2);
}
section = "Window Size";
{
Setting *width = createSetting (Type_LineEdit, section, "Width");
Setting *height = createSetting (Type_LineEdit, section, "Height");
@ -100,6 +195,17 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
ritd->setEditorSetting (true);
}
section = "Video";
{
QString defaultValue = "None";
QStringList values = QStringList()
<< defaultValue << "MSAA 2" << "MSAA 4" << "MSAA 8" << "MSAA 16";
Setting *antialiasing = createSetting (Type_SpinBox, section, "antialiasing");
antialiasing->setDeclaredValues (values);
antialiasing->setEditorSetting (true);
antialiasing->setWidgetWidth(15);
}
section = "Proxy Selection Test";
{
/******************************************************************
@ -305,10 +411,27 @@ void CSMSettings::UserSettings::loadSettings (const QString &fileName)
mSettingDefinitions = new QSettings
(QSettings::IniFormat, QSettings::UserScope, "opencs", QString(), this);
// check if override entry exists (default: disabled)
if(!mSettingDefinitions->childGroups().contains("Video", Qt::CaseInsensitive))
mSettingDefinitions->setValue("Video/use settings.cfg", "false");
}
bool CSMSettings::UserSettings::hasSettingDefinitions
(const QString &viewKey) const
// if the key is not found create one with a defaut value
QString CSMSettings::UserSettings::setting(const QString &viewKey, const QString &value)
{
if(mSettingDefinitions->contains(viewKey))
return settingValue(viewKey);
else if(value != QString())
{
mSettingDefinitions->setValue (viewKey, QStringList() << value);
return value;
}
return QString();
}
bool CSMSettings::UserSettings::hasSettingDefinitions (const QString &viewKey) const
{
return (mSettingDefinitions->contains (viewKey));
}
@ -326,10 +449,25 @@ void CSMSettings::UserSettings::saveDefinitions() const
QString CSMSettings::UserSettings::settingValue (const QString &settingKey)
{
if (!mSettingDefinitions->contains (settingKey))
return QString();
QStringList defs;
// check if video settings are overriden
if(settingKey.contains(QRegExp("^Video\\b", Qt::CaseInsensitive)) &&
mSettingDefinitions->value("Video/use settings.cfg") == "true" &&
settingKey.contains(QRegExp("^Video/\\brender|antialiasing|vsync|fullscreen\\b", Qt::CaseInsensitive)))
{
if (!mSettingCfgDefinitions->contains (settingKey))
return QString();
else
defs = mSettingCfgDefinitions->value (settingKey).toStringList();
}
else
{
if (!mSettingDefinitions->contains (settingKey))
return QString();
QStringList defs = mSettingDefinitions->value (settingKey).toStringList();
defs = mSettingDefinitions->value (settingKey).toStringList();
}
if (defs.isEmpty())
return QString();
@ -348,6 +486,15 @@ void CSMSettings::UserSettings::updateUserSetting(const QString &settingKey,
{
mSettingDefinitions->setValue (settingKey ,list);
if(settingKey == "Objects/num_lights" && !list.empty())
{
sh::Factory::getInstance ().setGlobalSetting ("num_lights", list.at(0).toStdString());
}
else if(settingKey == "Objects/shaders" && !list.empty())
{
sh::Factory::getInstance ().setShadersEnabled (list.at(0).toStdString() == "true" ? true : false);
}
emit userSettingUpdated (settingKey, list);
}
@ -387,7 +534,6 @@ void CSMSettings::UserSettings::removeSetting
}
}
CSMSettings::SettingPageMap CSMSettings::UserSettings::settingPageMap() const
{
SettingPageMap pageMap;

@ -33,8 +33,10 @@ namespace CSMSettings {
const Files::ConfigurationManager& mCfgMgr;
QSettings *mSettingDefinitions;
QSettings *mSettingCfgDefinitions;
QList <Setting *> mSettings;
public:
/// Singleton implementation
@ -75,6 +77,8 @@ namespace CSMSettings {
///Save any unsaved changes in the QSettings object
void saveDefinitions() const;
QString setting(const QString &viewKey, const QString &value = QString());
private:
void buildSettingModelDefaults();

@ -71,6 +71,14 @@ namespace CSMWorld
record.load (reader);
if (index==-1)
{
std::string newId = IdAccessorT().getId(record);
int newIndex = this->searchId(newId);
if (newIndex != -1 && id != newId)
index = newIndex;
}
load (record, base, index);
}
}

@ -6,18 +6,20 @@
void CSMWorld::ResourcesManager::addResources (const Resources& resources)
{
mResources.insert (std::make_pair (resources.getType(), resources));
mResources.insert (std::make_pair (UniversalId::getParentType (resources.getType()),
resources));
}
void CSMWorld::ResourcesManager::listResources()
{
static const char * const sMeshTypes[] = { "nif", 0 };
addResources (Resources ("meshes", UniversalId::Type_Meshes, sMeshTypes));
addResources (Resources ("icons", UniversalId::Type_Icons));
addResources (Resources ("music", UniversalId::Type_Musics));
addResources (Resources ("sound", UniversalId::Type_SoundsRes));
addResources (Resources ("textures", UniversalId::Type_Textures));
addResources (Resources ("videos", UniversalId::Type_Videos));
addResources (Resources ("meshes", UniversalId::Type_Mesh, sMeshTypes));
addResources (Resources ("icons", UniversalId::Type_Icon));
addResources (Resources ("music", UniversalId::Type_Music));
addResources (Resources ("sound", UniversalId::Type_SoundRes));
addResources (Resources ("textures", UniversalId::Type_Texture));
addResources (Resources ("videos", UniversalId::Type_Video));
}
const CSMWorld::Resources& CSMWorld::ResourcesManager::get (UniversalId::Type type) const

@ -1,5 +1,7 @@
#include "subview.hpp"
#include "view.hpp"
CSVDoc::SubView::SubView (const CSMWorld::UniversalId& id) : mUniversalId (id)
{
/// \todo add a button to the title bar that clones this sub view
@ -25,3 +27,10 @@ void CSVDoc::SubView::setUniversalId (const CSMWorld::UniversalId& id)
mUniversalId = id;
setWindowTitle (mUniversalId.toString().c_str());
}
void CSVDoc::SubView::closeEvent (QCloseEvent *event)
{
// update title bars of view and subviews
if(mParent)
mParent->updateSubViewIndicies(this);
}

@ -18,11 +18,14 @@ namespace CSMWorld
namespace CSVDoc
{
class View;
class SubView : public QDockWidget
{
Q_OBJECT
CSMWorld::UniversalId mUniversalId;
View *mParent;
// not implemented
SubView (const SubView&);
@ -44,6 +47,12 @@ namespace CSVDoc
virtual void useHint (const std::string& hint);
///< Default implementation: ignored
void setParent(View *parent) { mParent = parent; }
private:
void closeEvent (QCloseEvent *event);
signals:
void focusId (const CSMWorld::UniversalId& universalId, const std::string& hint);

@ -8,6 +8,7 @@
#include <QMdiArea>
#include <QDockWidget>
#include <QtGui/QApplication>
#include <QDesktopWidget>
#include "../../model/doc/document.hpp"
#include "../../model/settings/usersettings.hpp"
@ -103,6 +104,10 @@ void CSVDoc::View::setupViewMenu()
mShowStatusBar = new QAction (tr ("Show Status Bar"), this);
mShowStatusBar->setCheckable (true);
connect (mShowStatusBar, SIGNAL (toggled (bool)), this, SLOT (toggleShowStatusBar (bool)));
std::string showStatusBar =
CSMSettings::UserSettings::instance().settingValue("Display/show statusbar").toStdString();
if(showStatusBar == "true")
mShowStatusBar->setChecked(true);
view->addAction (mShowStatusBar);
QAction *filters = new QAction (tr ("Filters"), this);
@ -283,7 +288,7 @@ void CSVDoc::View::setupUi()
setupDebugMenu();
}
void CSVDoc::View::updateTitle()
void CSVDoc::View::updateTitle(const std::string subview)
{
std::ostringstream stream;
@ -295,9 +300,40 @@ void CSVDoc::View::updateTitle()
if (mViewTotal>1)
stream << " [" << (mViewIndex+1) << "/" << mViewTotal << "]";
if (subview != "")
stream << " - " << subview;
setWindowTitle (stream.str().c_str());
}
void CSVDoc::View::updateSubViewIndicies(SubView *view)
{
if(view && mSubViews.contains(view))
mSubViews.removeOne(view);
if(mSubViews.size() == 1)
{
if(!mSubViews.at(0)->isFloating())
{
mSubViews.at(0)->setTitleBarWidget(new QWidget(this));
updateTitle(mSubViews.at(0)->getUniversalId().getTypeName().c_str());
}
}
else
{
updateTitle();
if(mSubViews.size() > 1)
{
foreach(SubView * sb, mSubViews)
{
QWidget * tb = sb->titleBarWidget();
if(tb) delete tb;
sb->setTitleBarWidget(0);
}
}
}
}
void CSVDoc::View::updateActions()
{
bool editing = !(mDocument->getState() & CSMDoc::State_Locked);
@ -326,7 +362,11 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to
QString height = CSMSettings::UserSettings::instance().settingValue
("Window Size/Height");
resize (width.toInt(), height.toInt());
// trick to get the window decorations and their sizes
show();
hide();
resize (width.toInt() - (frameGeometry().width() - geometry().width()),
height.toInt() - (frameGeometry().height() - geometry().height()));
mSubViewWindow.setDockOptions (QMainWindow::AllowNestedDocks);
@ -400,31 +440,64 @@ void CSVDoc::View::updateProgress (int current, int max, int type, int threads)
void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::string& hint)
{
/// \todo add an user setting for limiting the number of sub views per top level view. Automatically open a new top level view if this
/// number is exceeded
CSMSettings::UserSettings &userSettings = CSMSettings::UserSettings::instance();
/// \todo if the sub view limit setting is one, the sub view title bar should be hidden and the text in the main title bar adjusted
/// accordingly
const std::vector<CSMWorld::UniversalId::Type> referenceables(CSMWorld::UniversalId::listReferenceableTypes());
bool isReferenceable = std::find(referenceables.begin(), referenceables.end(), id.getType()) != referenceables.end();
/// \todo add an user setting to reuse sub views (on a per document basis or on a per top level view basis)
// User setting to reuse sub views (on a per top level view basis)
bool reuse =
userSettings.setting("SubView/reuse", QString("true")) == "true" ? true : false;
if(reuse)
{
foreach(SubView *sb, mSubViews)
{
if((isReferenceable && (CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Referenceable, id.getId()) == CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Referenceable, sb->getUniversalId().getId())))
|| (!isReferenceable && (id == sb->getUniversalId())))
{
sb->setFocus(Qt::OtherFocusReason); // FIXME: focus not quite working
return;
}
}
}
// User setting for limiting the number of sub views per top level view.
// Automatically open a new top level view if this number is exceeded
//
// If the sub view limit setting is one, the sub view title bar is hidden and the
// text in the main title bar is adjusted accordingly
int maxSubView = userSettings.setting("SubView/max subviews", QString("256")).toInt();
if(mSubViews.size() >= maxSubView) // create a new top level view
{
mViewManager.addView(mDocument, id, hint);
return;
}
const std::vector<CSMWorld::UniversalId::Type> referenceables(CSMWorld::UniversalId::listReferenceableTypes());
SubView *view = NULL;
if(std::find(referenceables.begin(), referenceables.end(), id.getType()) != referenceables.end())
{
view = mSubViewFactory.makeSubView (CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Referenceable, id.getId()), *mDocument);
} else
}
else
{
view = mSubViewFactory.makeSubView (id, *mDocument);
}
assert(view);
view->setParent(this);
mSubViews.append(view); // only after assert
if (!hint.empty())
view->useHint (hint);
int minWidth = userSettings.setting("SubView/minimum width", QString("325")).toInt();
view->setMinimumWidth(minWidth);
view->setStatusBar (mShowStatusBar->isChecked());
mSubViewWindow.addDockWidget (Qt::TopDockWidgetArea, view);
updateSubViewIndicies();
connect (view, SIGNAL (focusId (const CSMWorld::UniversalId&, const std::string&)), this,
SLOT (addSubView (const CSMWorld::UniversalId&, const std::string&)));
@ -642,6 +715,11 @@ void CSVDoc::View::toggleShowStatusBar (bool show)
}
}
void CSVDoc::View::toggleStatusBar(bool checked)
{
mShowStatusBar->setChecked(checked);
}
void CSVDoc::View::loadErrorLog()
{
addSubView (CSMWorld::UniversalId (CSMWorld::UniversalId::Type_LoadErrorLog, 0));

@ -35,6 +35,7 @@ namespace CSVDoc
CSMDoc::Document *mDocument;
int mViewIndex;
int mViewTotal;
QList<SubView *> mSubViews;
QAction *mUndo;
QAction *mRedo;
QAction *mSave;
@ -74,7 +75,7 @@ namespace CSVDoc
void setupUi();
void updateTitle();
void updateTitle(const std::string subview = "");
void updateActions();
@ -106,11 +107,16 @@ namespace CSVDoc
void updateProgress (int current, int max, int type, int threads);
void toggleStatusBar(bool checked);
Operations *getOperations() const;
/// Function called by view manager when user preferences are updated
void updateEditorSetting (const QString &, const QString &);
// called when subviews are added or removed
void updateSubViewIndicies(SubView *view = 0);
signals:
void newGameRequest();

@ -9,6 +9,7 @@
#include "../../model/doc/documentmanager.hpp"
#include "../../model/doc/document.hpp"
#include "../../model/world/columns.hpp"
#include "../../model/world/universalid.hpp"
#include "../world/util.hpp"
#include "../world/enumdelegate.hpp"
@ -140,6 +141,10 @@ CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document)
mViews.push_back (view);
std::string showStatusBar =
CSMSettings::UserSettings::instance().settingValue("Display/show statusbar").toStdString();
view->toggleStatusBar (showStatusBar == "true");
view->show();
connect (view, SIGNAL (newGameRequest ()), this, SIGNAL (newGameRequest()));
@ -157,6 +162,14 @@ CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document)
return view;
}
CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document, const CSMWorld::UniversalId& id, const std::string& hint)
{
View* view = addView(document);
view->addSubView(id, hint);
return view;
}
int CSVDoc::ViewManager::countViews (const CSMDoc::Document *document) const
{
int count = 0;

@ -18,6 +18,11 @@ namespace CSVWorld
class CommandDelegateFactoryCollection;
}
namespace CSMWorld
{
class UniversalId;
}
namespace CSVDoc
{
class View;
@ -52,6 +57,8 @@ namespace CSVDoc
View *addView (CSMDoc::Document *document);
///< The ownership of the returned view is not transferred.
View *addView (CSMDoc::Document *document, const CSMWorld::UniversalId& id, const std::string& hint);
int countViews (const CSMDoc::Document *document) const;
///< Return number of views for \a document.

@ -11,7 +11,7 @@ CSVFilter::RecordFilterBox::RecordFilterBox (CSMWorld::Data& data, QWidget *pare
{
QHBoxLayout *layout = new QHBoxLayout (this);
layout->setContentsMargins (0, 0, 0, 0);
layout->setContentsMargins (0, 6, 5, 0);
QLabel *label = new QLabel("Record Filter", this);
label->setIndent(2);

@ -13,6 +13,7 @@
#include <OgreViewport.h>
#include "../widget/scenetoolmode.hpp"
#include "../../model/settings/usersettings.hpp"
#include "navigation.hpp"
#include "lighting.hpp"
@ -27,7 +28,7 @@ namespace CSVRender
, mKeyForward (false), mKeyBackward (false), mKeyLeft (false), mKeyRight (false)
, mKeyRollLeft (false), mKeyRollRight (false)
, mFast (false), mDragging (false), mMod1 (false)
, mFastFactor (4) /// \todo make this configurable
, mFastFactor (4)
, mDefaultAmbient (0, 0, 0, 0), mHasDefaultAmbient (false)
{
setAttribute(Qt::WA_PaintOnScreen);
@ -44,7 +45,14 @@ namespace CSVRender
mCamera->setPosition (300, 0, 0);
mCamera->lookAt (0, 0, 0);
mCamera->setNearClipDistance (0.1);
mCamera->setFarClipDistance (300000); ///< \todo make this configurable
CSMSettings::UserSettings &userSettings = CSMSettings::UserSettings::instance();
float farClipDist = userSettings.setting("Scene/far clip distance", QString("300000")).toFloat();
mCamera->setFarClipDistance (farClipDist);
mFastFactor = userSettings.setting("Scene/fast factor", QString("4")).toInt();
mCamera->roll (Ogre::Degree (90));
setLighting (&mLightingDay);
@ -52,7 +60,9 @@ namespace CSVRender
QTimer *timer = new QTimer (this);
connect (timer, SIGNAL (timeout()), this, SLOT (update()));
timer->start (20); ///< \todo make this configurable
int timerStart = userSettings.setting("Scene/timer start", QString("20")).toInt();
timer->start (timerStart);
/// \todo make shortcut configurable
QShortcut *focusToolbar = new QShortcut (Qt::Key_T, this, 0, 0, Qt::WidgetWithChildrenShortcut);
@ -118,7 +128,16 @@ namespace CSVRender
params.insert(std::make_pair("externalWindowHandle", windowHandle.str()));
params.insert(std::make_pair("title", windowTitle.str()));
params.insert(std::make_pair("FSAA", "0")); // TODO setting
std::string antialiasing =
CSMSettings::UserSettings::instance().settingValue("Video/antialiasing").toStdString();
if(antialiasing == "MSAA 16") antialiasing = "16";
else if(antialiasing == "MSAA 8") antialiasing = "8";
else if(antialiasing == "MSAA 4") antialiasing = "4";
else if(antialiasing == "MSAA 2") antialiasing = "2";
else antialiasing = "0";
params.insert(std::make_pair("FSAA", antialiasing));
params.insert(std::make_pair("vsync", "false")); // TODO setting
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
params.insert(std::make_pair("macAPI", "cocoa"));
@ -382,4 +401,32 @@ namespace CSVRender
else if (mode=="bright")
setLighting (&mLightingBright);
}
void SceneWidget::updateUserSetting (const QString &key, const QStringList &list)
{
if(key.contains(QRegExp("^\\b(Objects|Shader|Scene)", Qt::CaseInsensitive)))
flagAsModified();
if(key == "Scene/far clip distance" && !list.empty())
{
if(mCamera->getFarClipDistance() != list.at(0).toFloat())
mCamera->setFarClipDistance(list.at(0).toFloat());
}
// minimise unnecessary ogre window creation by updating only when there is a change
if(key == "Video/antialiasing")
{
unsigned int aa = mWindow->getFSAA();
unsigned int antialiasing = 0;
if(!list.empty())
{
if(list.at(0) == "MSAA 16") antialiasing = 16;
else if(list.at(0) == "MSAA 8") antialiasing = 8;
else if(list.at(0) == "MSAA 4") antialiasing = 4;
else if(list.at(0) == "MSAA 2") antialiasing = 2;
}
if(aa != antialiasing)
updateOgreWindow();
}
}
}

@ -108,6 +108,10 @@ namespace CSVRender
LightingNight mLightingNight;
LightingBright mLightingBright;
public slots:
void updateUserSetting (const QString &key, const QStringList &list);
private slots:
void update();

@ -12,16 +12,27 @@
CSVSettings::BooleanView::BooleanView (CSMSettings::Setting *setting,
Page *parent)
: View (setting, parent)
: mType(setting->type()), View (setting, parent)
{
foreach (const QString &value, setting->declaredValues())
{
QAbstractButton *button = 0;
switch (setting->type())
switch (mType)
{
case CSMSettings::Type_CheckBox:
button = new QCheckBox (value, this);
case CSMSettings::Type_CheckBox: {
if(mButtons.empty()) // show only one for checkboxes
{
button = new QCheckBox (value, this);
button->setChecked (setting->defaultValues().at(0) == "true" ? true : false);
// special visual treatment option for checkboxes
if(setting->specialValueText() != "") {
Frame::setTitle("");
button->setText(setting->specialValueText());
}
}
}
break;
case CSMSettings::Type_RadioButton:
@ -32,14 +43,17 @@ CSVSettings::BooleanView::BooleanView (CSMSettings::Setting *setting,
break;
}
connect (button, SIGNAL (clicked (bool)),
this, SLOT (slotToggled (bool)));
if(button && (mType != CSMSettings::Type_CheckBox || mButtons.empty()))
{
connect (button, SIGNAL (clicked (bool)),
this, SLOT (slotToggled (bool)));
button->setObjectName (value);
button->setObjectName (value);
addWidget (button);
addWidget (button);
mButtons[value] = button;
mButtons[value] = button;
}
}
}
@ -53,8 +67,14 @@ void CSVSettings::BooleanView::slotToggled (bool state)
foreach (QString key, mButtons.keys())
{
if (mButtons.value(key)->isChecked())
values.append (key);
// checkbox values are true/false unlike radio buttons
if(mType == CSMSettings::Type_CheckBox)
values.append(mButtons.value(key)->isChecked() ? "true" : "false");
else
{
if (mButtons.value(key)->isChecked())
values.append (key);
}
}
setSelectedValues (values, false);

@ -16,6 +16,7 @@ namespace CSVSettings
Q_OBJECT
QMap <QString, QAbstractButton *> mButtons;
enum CSMSettings::SettingType mType;
public:
explicit BooleanView (CSMSettings::Setting *setting,

@ -3,7 +3,7 @@
#include <QWidget>
const QString CSVSettings::Frame::sInvisibleBoxStyle =
QString::fromUtf8("Frame { border:2px; padding 2px; margin: 2px;}");
QString::fromUtf8("Frame { border:2px; padding: 2px; margin: 2px;}");
CSVSettings::Frame::Frame (bool isVisible, const QString &title,
QWidget *parent)
@ -14,7 +14,11 @@ CSVSettings::Frame::Frame (bool isVisible, const QString &title,
mVisibleBoxStyle = styleSheet();
if (!isVisible)
{
// must be Page, not a View
setStyleSheet (sInvisibleBoxStyle);
mLayout->setContentsMargins(10, 15, 10, 15);
}
setLayout (mLayout);
}

@ -1,4 +1,7 @@
#include "page.hpp"
#include <QLabel>
#include "view.hpp"
#include "booleanview.hpp"
#include "textview.hpp"
@ -38,7 +41,18 @@ void CSVSettings::Page::setupViews
void CSVSettings::Page::addView (CSMSettings::Setting *setting)
{
if (setting->viewType() == ViewType_Undefined)
return;
{
if(setting->specialValueText() != "")
{
// hack to put a label
addWidget(new QLabel(setting->specialValueText()),
setting->viewRow(), setting->viewColumn(),
setting->rowSpan(), setting->columnSpan());
return;
}
else
return;
}
View *view = mViewFactories[setting->viewType()]->createView(setting, this);

@ -36,8 +36,11 @@ CSVSettings::RangeView::RangeView (CSMSettings::Setting *setting,
break;
}
mRangeWidget->setFixedWidth (widgetWidth (setting->widgetWidth()));
mRangeWidget->setObjectName (setting->name());
if(mRangeWidget)
{
mRangeWidget->setFixedWidth (widgetWidth (setting->widgetWidth()));
mRangeWidget->setObjectName (setting->name());
}
addWidget (mRangeWidget);
}
@ -75,13 +78,16 @@ void CSVSettings::RangeView::buildSlider (CSMSettings::Setting *setting)
break;
}
mRangeWidget->setProperty ("minimum", setting->minimum());
mRangeWidget->setProperty ("maximum", setting->maximum());
mRangeWidget->setProperty ("tracking", false);
mRangeWidget->setProperty ("singleStep", setting->singleStep());
if(mRangeWidget)
{
mRangeWidget->setProperty ("minimum", setting->minimum());
mRangeWidget->setProperty ("maximum", setting->maximum());
mRangeWidget->setProperty ("tracking", false);
mRangeWidget->setProperty ("singleStep", setting->singleStep());
connect (mRangeWidget, SIGNAL (valueChanged (int)),
this, SLOT (slotUpdateView (int)));
connect (mRangeWidget, SIGNAL (valueChanged (int)),
this, SLOT (slotUpdateView (int)));
}
}
void CSVSettings::RangeView::buildSpinBox (CSMSettings::Setting *setting)
@ -127,7 +133,10 @@ void CSVSettings::RangeView::buildSpinBox (CSMSettings::Setting *setting)
mRangeWidget->setProperty ("prefix", setting->prefix());
mRangeWidget->setProperty ("suffix", setting->suffix());
mRangeWidget->setProperty ("wrapping", setting->wrapping());
dynamic_cast<QAbstractSpinBox *> (mRangeWidget)->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
if(setting->type() == CSMSettings::Type_SpinBox && setting->declaredValues().isEmpty())
dynamic_cast<QSpinBox *> (mRangeWidget)->setValue (setting->defaultValues().at(0).toInt());
}
void CSVSettings::RangeView::slotUpdateView (int value)

@ -19,7 +19,7 @@ void CSVSettings::SettingWindow::createPages()
QList <CSMSettings::Setting *> connectedSettings;
foreach (const QString &pageName, pageMap.keys())
{
{
QList <CSMSettings::Setting *> pageSettings = pageMap.value (pageName);
mPages.append (new Page (pageName, pageSettings, this));
@ -129,7 +129,3 @@ void CSVSettings::SettingWindow::saveSettings()
mModel->saveDefinitions();
}
void CSVSettings::SettingWindow::closeEvent (QCloseEvent *event)
{
QApplication::focusWidget()->clearFocus();
}

@ -36,8 +36,6 @@ namespace CSVSettings {
protected:
virtual void closeEvent (QCloseEvent *event);
///construct the pages to be displayed in the dialog
void createPages();

@ -24,7 +24,7 @@ QString CSVSettings::SpinBox::textFromValue(int val) const
int CSVSettings::SpinBox::valueFromText(const QString &text) const
{
if (mValueList.isEmpty())
return -1;
return text.toInt(); // TODO: assumed integer, untested error handling for alpha types
if (mValueList.contains (text))
return mValueList.indexOf(text);

@ -22,6 +22,9 @@ CSVSettings::View::View(CSMSettings::Setting *setting,
setObjectName (setting->name());
buildView();
buildModel (setting);
// apply stylesheet to view's frame if exists
if(setting->styleSheet() != "")
Frame::setStyleSheet (setting->styleSheet());
}
void CSVSettings::View::buildModel (const CSMSettings::Setting *setting)

@ -392,7 +392,6 @@ void CSVWorld::EditWidget::remake(int row)
mWidgetMapper->setCurrentModelIndex(mTable->index(row, 0));
this->setMinimumWidth(325); /// \todo replace hardcoded value with a user setting
this->setWidget(mMainWidget);
this->setWidgetResizable(true);
}

@ -247,6 +247,8 @@ void CSVWorld::SceneSubView::replaceToolbarAndWorldspace (CSVRender::WorldspaceW
mToolbar = toolbar;
connect (mScene, SIGNAL (focusToolbarRequest()), mToolbar, SLOT (setFocus()));
connect (this, SIGNAL (updateSceneUserSetting(const QString &, const QStringList &)),
mScene, SLOT (updateUserSetting(const QString &, const QStringList &)));
connect (mToolbar, SIGNAL (focusSceneRequest()), mScene, SLOT (setFocus()));
mLayout->addWidget (mToolbar, 0);
@ -254,4 +256,9 @@ void CSVWorld::SceneSubView::replaceToolbarAndWorldspace (CSVRender::WorldspaceW
mScene->selectDefaultNavigationMode();
setFocusProxy (mScene);
}
}
void CSVWorld::SceneSubView::updateUserSetting (const QString &key, const QStringList &list)
{
emit updateSceneUserSetting(key, list);
}

@ -82,6 +82,14 @@ namespace CSVWorld
void cellSelectionChanged (const CSMWorld::UniversalId& id);
void handleDrop(const std::vector<CSMWorld::UniversalId>& data);
public slots:
void updateUserSetting (const QString &, const QStringList &);
signals:
void updateSceneUserSetting (const QString &, const QStringList &);
};
}

@ -40,7 +40,7 @@ add_openmw_dir (mwgui
merchantrepair repair soulgemdialog companionwindow bookpage journalviewmodel journalbooks
keywordsearch itemmodel containeritemmodel inventoryitemmodel sortfilteritemmodel itemview
tradeitemmodel companionitemmodel pickpocketitemmodel controllers savegamedialog
recharge mode videowidget backgroundimage itemwidget screenfader
recharge mode videowidget backgroundimage itemwidget screenfader debugwindow
)
add_openmw_dir (mwdialogue

@ -177,7 +177,7 @@ namespace MWBase
virtual void changeCell(MWWorld::CellStore* cell) = 0;
///< change the active cell
virtual void setPlayerPos(const float x, const float y) = 0;
virtual void setPlayerPos(int cellX, int cellY, const float x, const float y) = 0;
///< set player position in map space
virtual void setPlayerDir(const float x, const float y) = 0;
@ -337,6 +337,8 @@ namespace MWBase
virtual void fadeScreenTo(const int percent, const float time) = 0;
/// Darken the screen by \a factor (1.0 = no darkening). Works independently from screen fading.
virtual void setScreenFactor (float factor) = 0;
virtual void toggleDebugWindow() = 0;
};
}

@ -119,6 +119,7 @@ namespace MWBase
virtual void setWaterHeight(const float height) = 0;
virtual bool toggleWater() = 0;
virtual bool toggleWorld() = 0;
virtual void adjustSky() = 0;
@ -136,7 +137,7 @@ namespace MWBase
virtual MWWorld::LocalScripts& getLocalScripts() = 0;
virtual bool hasCellChanged() const = 0;
///< Has the player moved to a different cell, since the last frame?
///< Has the set of active cells changed, since the last frame?
virtual bool isCellExterior() const = 0;

@ -76,7 +76,7 @@ MWWorld::Ptr ContainerItemModel::copyItem (const ItemStack& item, size_t count,
const MWWorld::Ptr& source = mItemSources[mItemSources.size()-1];
if (item.mBase.getContainerStore() == &source.getClass().getContainerStore(source))
throw std::runtime_error("Item to copy needs to be from a different container!");
return *source.getClass().getContainerStore(source).add(item.mBase, count, source, setNewOwner);
return *source.getClass().getContainerStore(source).add(item.mBase, count, source);
}
void ContainerItemModel::removeItem (const ItemStack& item, size_t count)

@ -0,0 +1,116 @@
#include "debugwindow.hpp"
#include <LinearMath/btQuickprof.h>
namespace
{
void bulletDumpRecursive(CProfileIterator* pit, int spacing, std::stringstream& os)
{
pit->First();
if (pit->Is_Done())
return;
float accumulated_time=0,parent_time = pit->Is_Root() ? CProfileManager::Get_Time_Since_Reset() : pit->Get_Current_Parent_Total_Time();
int i,j;
int frames_since_reset = CProfileManager::Get_Frame_Count_Since_Reset();
for (i=0;i<spacing;i++) os << ".";
os << "----------------------------------\n";
for (i=0;i<spacing;i++) os << ".";
std::string s = "Profiling: "+
std::string(pit->Get_Current_Parent_Name())+" (total running time: "+MyGUI::utility::toString(parent_time,3)+" ms) ---\n";
os << s;
//float totalTime = 0.f;
int numChildren = 0;
for (i = 0; !pit->Is_Done(); i++,pit->Next())
{
numChildren++;
float current_total_time = pit->Get_Current_Total_Time();
accumulated_time += current_total_time;
float fraction = parent_time > SIMD_EPSILON ? (current_total_time / parent_time) * 100 : 0.f;
for (j=0;j<spacing;j++) os << ".";
double ms = (current_total_time / (double)frames_since_reset);
s = MyGUI::utility::toString(i)+" -- "+pit->Get_Current_Name()+" ("+MyGUI::utility::toString(fraction,2)+" %) :: "+MyGUI::utility::toString(ms,3)+" ms / frame ("+MyGUI::utility::toString(pit->Get_Current_Total_Calls())+" calls)\n";
os << s;
//totalTime += current_total_time;
//recurse into children
}
if (parent_time < accumulated_time)
{
os << "what's wrong\n";
}
for (i=0;i<spacing;i++) os << ".";
double unaccounted= parent_time > SIMD_EPSILON ? ((parent_time - accumulated_time) / parent_time) * 100 : 0.f;
s = "Unaccounted: ("+MyGUI::utility::toString(unaccounted,3)+" %) :: "+MyGUI::utility::toString(parent_time - accumulated_time,3)+" ms\n";
os << s;
for (i=0;i<numChildren;i++)
{
pit->Enter_Child(i);
bulletDumpRecursive(pit, spacing+3, os);
pit->Enter_Parent();
}
}
void bulletDumpAll(std::stringstream& os)
{
CProfileIterator* profileIterator = 0;
profileIterator = CProfileManager::Get_Iterator();
bulletDumpRecursive(profileIterator, 0, os);
CProfileManager::Release_Iterator(profileIterator);
}
}
namespace MWGui
{
DebugWindow::DebugWindow()
: WindowBase("openmw_debug_window.layout")
{
getWidget(mTabControl, "TabControl");
// Ideas for other tabs:
// - Texture / compositor texture viewer
// - Log viewer
// - Material editor
// - Shader editor
MyGUI::TabItem* item = mTabControl->addItem("Physics Profiler");
mBulletProfilerEdit = item->createWidgetReal<MyGUI::EditBox>
("LogEdit", MyGUI::FloatCoord(0,0,1,1), MyGUI::Align::Stretch);
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
mMainWidget->setSize(viewSize);
}
void DebugWindow::onFrame(float dt)
{
if (!isVisible())
return;
static float timer = 0;
timer -= dt;
if (timer > 0)
return;
timer = 1;
std::stringstream stream;
bulletDumpAll(stream);
if (mBulletProfilerEdit->isTextSelection()) // pause updating while user is trying to copy text
return;
size_t previousPos = mBulletProfilerEdit->getVScrollPosition();
mBulletProfilerEdit->setCaption(stream.str());
mBulletProfilerEdit->setVScrollPosition(std::min(previousPos, mBulletProfilerEdit->getVScrollRange()-1));
}
}

@ -0,0 +1,24 @@
#ifndef OPENMW_MWGUI_DEBUGWINDOW_H
#define OPENMW_MWGUI_DEBUGWINDOW_H
#include "windowbase.hpp"
namespace MWGui
{
class DebugWindow : public WindowBase
{
public:
DebugWindow();
void onFrame(float dt);
private:
MyGUI::TabControl* mTabControl;
MyGUI::EditBox* mBulletProfilerEdit;
};
}
#endif

@ -562,12 +562,11 @@ namespace MWGui
MyGUI::Button* byeButton;
getWidget(byeButton, "ByeButton");
if(MWBase::Environment::get().getDialogueManager()->isInChoice() && !mGoodbye) {
byeButton->setEnabled(false);
}
else {
byeButton->setEnabled(true);
}
bool goodbyeEnabled = !MWBase::Environment::get().getDialogueManager()->isInChoice() || mGoodbye;
byeButton->setEnabled(goodbyeEnabled);
bool topicsEnabled = !MWBase::Environment::get().getDialogueManager()->isInChoice() && !mGoodbye;
mTopicsList->setEnabled(topicsEnabled);
}
void DialogueWindow::notifyLinkClicked (TypesetBook::InteractiveId link)
@ -657,7 +656,6 @@ namespace MWGui
{
mLinks.push_back(new Goodbye());
mGoodbye = true;
mTopicsList->setEnabled(false);
mEnabled = false;
updateHistory();
}

@ -201,12 +201,23 @@ struct JournalViewModelImpl : JournalViewModel
std::set<std::string> visitedQuests;
// Note that for purposes of the journal GUI, quests are identified by the name, not the ID, so several
// different quest IDs can end up in the same quest log. A quest log should be considered finished
// when any quest ID in that log is finished.
for (MWBase::Journal::TQuestIter i = journal->questBegin (); i != journal->questEnd (); ++i)
{
if (active_only && i->second.isFinished ())
const MWDialogue::Quest& quest = i->second;
bool isFinished = false;
for (MWBase::Journal::TQuestIter j = journal->questBegin (); j != journal->questEnd (); ++j)
{
if (quest.getName() == j->second.getName() && j->second.isFinished())
isFinished = true;
}
if (active_only && isFinished)
continue;
const MWDialogue::Quest& quest = i->second;
// Unfortunately Morrowind.esm has no quest names, since the quest book was added with tribunal.
// Note that even with Tribunal, some quests still don't have quest names. I'm assuming those are not supposed
// to appear in the quest book.

@ -490,7 +490,7 @@ namespace
unsigned int & page = mStates.top ().mPage;
Book book = mStates.top ().mBook;
if (page < book->pageCount () - 2)
if (page+2 < book->pageCount())
{
page += 2;
updateShowingPages ();

@ -159,8 +159,6 @@ namespace MWGui
, mLocalMap(NULL)
, mPrefix()
, mChanged(true)
, mLastPositionX(0.0f)
, mLastPositionY(0.0f)
, mLastDirectionX(0.0f)
, mLastDirectionY(0.0f)
, mCompass(NULL)
@ -425,24 +423,22 @@ namespace MWGui
mLocalMap->getParent()->_updateChilds();
}
void LocalMapBase::setPlayerPos(const float x, const float y)
void LocalMapBase::setPlayerPos(int cellX, int cellY, const float nx, const float ny)
{
updateMagicMarkers();
if (x == mLastPositionX && y == mLastPositionY)
return;
MyGUI::IntPoint pos(widgetSize+nx*widgetSize-16, widgetSize+ny*widgetSize-16);
pos.left += (cellX - mCurX) * widgetSize;
pos.top -= (cellY - mCurY) * widgetSize;
notifyPlayerUpdate ();
MyGUI::IntSize size = mLocalMap->getCanvasSize();
MyGUI::IntPoint middle = MyGUI::IntPoint((1/3.f + x/3.f)*size.width,(1/3.f + y/3.f)*size.height);
MyGUI::IntCoord viewsize = mLocalMap->getCoord();
MyGUI::IntPoint pos(0.5*viewsize.width - middle.left, 0.5*viewsize.height - middle.top);
mLocalMap->setViewOffset(pos);
if (pos != mCompass->getPosition())
{
notifyPlayerUpdate ();
mCompass->setPosition(MyGUI::IntPoint(widgetSize+x*widgetSize-16, widgetSize+y*widgetSize-16));
mLastPositionX = x;
mLastPositionY = y;
mCompass->setPosition(pos);
MyGUI::IntPoint middle (pos.left+16, pos.top+16);
MyGUI::IntCoord viewsize = mLocalMap->getCoord();
MyGUI::IntPoint viewOffset(0.5*viewsize.width - middle.left, 0.5*viewsize.height - middle.top);
mLocalMap->setViewOffset(viewOffset);
}
}
void LocalMapBase::setPlayerDir(const float x, const float y)

@ -75,7 +75,7 @@ namespace MWGui
void setCellPrefix(const std::string& prefix);
void setActiveCell(const int x, const int y, bool interior=false);
void setPlayerDir(const float x, const float y);
void setPlayerPos(const float x, const float y);
void setPlayerPos(int cellX, int cellY, const float nx, const float ny);
void onFrame(float dt);
@ -129,8 +129,6 @@ namespace MWGui
float mMarkerUpdateTimer;
float mLastPositionX;
float mLastPositionY;
float mLastDirectionX;
float mLastDirectionY;
};

@ -157,12 +157,11 @@ namespace MWGui
, mMaxTime(0)
{
// defines
mBottomPadding = 20;
mNextBoxPadding = 20;
mBottomPadding = 48;
mNextBoxPadding = 4;
getWidget(mMessageWidget, "message");
mMessageWidget->setOverflowToTheLeft(true);
mMessageWidget->setCaptionWithReplacing(mMessage);
}
@ -178,7 +177,7 @@ namespace MWGui
int MessageBox::getHeight ()
{
return mMainWidget->getHeight()+mNextBoxPadding; // 20 is the padding between this and the next MessageBox
return mMainWidget->getHeight()+mNextBoxPadding;
}
@ -204,7 +203,6 @@ namespace MWGui
getWidget(mMessageWidget, "message");
getWidget(mButtonsWidget, "buttons");
mMessageWidget->setOverflowToTheLeft(true);
mMessageWidget->setSize(400, mMessageWidget->getHeight());
mMessageWidget->setCaptionWithReplacing(message);

@ -41,12 +41,11 @@ namespace MWGui
getWidget(mHeadRotate, "HeadRotate");
// Mouse wheel step is hardcoded to 50 in MyGUI 3.2 ("FIXME").
// Give other steps the same value to accomodate.
mHeadRotate->setScrollRange(1000);
mHeadRotate->setScrollPosition(500);
mHeadRotate->setScrollViewPage(50);
mHeadRotate->setScrollPage(50);
mHeadRotate->setScrollWheelPage(50);
mHeadRotate->eventScrollChangePosition += MyGUI::newDelegate(this, &RaceDialog::onHeadRotate);
// Set up next/previous buttons

@ -322,7 +322,8 @@ namespace MWGui
if (i == pos)
mCurrentSlot = &*it;
}
assert(mCurrentSlot && "Can't find selected slot");
if (!mCurrentSlot)
throw std::runtime_error("Can't find selected slot");
std::stringstream text;
time_t time = mCurrentSlot->mTimeStamp;

@ -100,6 +100,15 @@ namespace MWGui
if (spell->mData.mType!=ESM::Spell::ST_Spell)
continue; // don't try to sell diseases, curses or powers
if (actor.getClass().isNpc())
{
const ESM::Race* race =
MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(
actor.get<ESM::NPC>()->mBase->mRace);
if (race->mPowers.exists(spell->mId))
continue;
}
if (playerHasSpell(iter->first))
continue;

@ -422,12 +422,12 @@ namespace MWGui
y *= 1.5;
}
mSpell.mData.mCost = int(y);
ESM::EffectList effectList;
effectList.mList = mEffects;
mSpell.mEffects = effectList;
mSpell.mData.mCost = int(y);
mSpell.mData.mType = ESM::Spell::ST_Spell;
mSpell.mData.mFlags = 0;
mMagickaCost->setCaption(boost::lexical_cast<std::string>(int(y)));

@ -119,7 +119,7 @@ namespace MWGui
return mBorrowedToUs;
}
void TradeItemModel::transferItems(const MWWorld::Ptr& transferFrom)
void TradeItemModel::transferItems()
{
std::vector<ItemStack>::iterator it = mBorrowedToUs.begin();
for (; it != mBorrowedToUs.end(); ++it)
@ -135,11 +135,9 @@ namespace MWGui
if (i == sourceModel->getItemCount())
throw std::runtime_error("The borrowed item disappeared");
// reset owner while copying, but only for items bought by the player
bool setNewOwner = (mMerchant.isEmpty());
const ItemStack& item = sourceModel->getItem(i);
bool setNewOwner = Misc::StringUtils::ciEqual(item.mBase.getCellRef().getOwner(), transferFrom.getCellRef().getRefId())
|| item.mBase.getCellRef().getOwner().empty();
// copy the borrowed items to our model
copyItem(item, it->mCount, setNewOwner);
// then remove them from the source model

@ -30,8 +30,7 @@ namespace MWGui
void returnItemBorrowedFromUs (ModelIndex itemIndex, ItemModel* source, size_t count);
/// Permanently transfers items that were borrowed to us from another model to this model
/// @param transferFrom the actor that lent us the items
void transferItems (const MWWorld::Ptr& transferFrom);
void transferItems ();
/// Aborts trade
void abort();

@ -370,8 +370,8 @@ namespace MWGui
MWBase::Environment::get().getDialogueManager()->applyDispositionChange(iBarterSuccessDisposition);
// make the item transfer
mTradeModel->transferItems(player);
playerItemModel->transferItems(mPtr);
mTradeModel->transferItems();
playerItemModel->transferItems();
// transfer the gold
if (mCurrentBalance != 0)

@ -76,6 +76,8 @@ void WindowModal::close()
NoDrop::NoDrop(DragAndDrop *drag, MyGUI::Widget *widget)
: mDrag(drag), mWidget(widget), mTransparent(false)
{
if (!mWidget)
throw std::runtime_error("NoDrop needs a non-NULL widget!");
}
void NoDrop::onFrame(float dt)

@ -72,6 +72,7 @@
#include "backgroundimage.hpp"
#include "itemwidget.hpp"
#include "screenfader.hpp"
#include "debugwindow.hpp"
namespace MWGui
{
@ -120,6 +121,7 @@ namespace MWGui
, mVideoBackground(NULL)
, mVideoWidget(NULL)
, mScreenFader(NULL)
, mDebugWindow(NULL)
, mTranslationDataStorage (translationDataStorage)
, mCharGen(NULL)
, mInputBlocker(NULL)
@ -266,6 +268,7 @@ namespace MWGui
mCompanionWindow = new CompanionWindow(mDragAndDrop, mMessageBoxManager);
trackWindow(mCompanionWindow, "companion");
mScreenFader = new ScreenFader();
mDebugWindow = new DebugWindow();
mInputBlocker = MyGUI::Gui::getInstance().createWidget<MyGUI::Widget>("",0,0,w,h,MyGUI::Align::Stretch,"Overlay");
@ -357,6 +360,7 @@ namespace MWGui
delete mRecharge;
delete mCompanionWindow;
delete mScreenFader;
delete mDebugWindow;
cleanupGarbage();
@ -859,6 +863,8 @@ namespace MWGui
mCompanionWindow->onFrame();
mScreenFader->update(frameDuration);
mDebugWindow->onFrame(frameDuration);
}
void WindowManager::changeCell(MWWorld::CellStore* cell)
@ -874,9 +880,6 @@ namespace MWGui
mMap->addVisitedLocation ("#{sCell=" + name + "}", cell->getCell()->getGridX (), cell->getCell()->getGridY ());
mMap->cellExplored (cell->getCell()->getGridX(), cell->getCell()->getGridY());
mMap->setCellPrefix("Cell");
mHud->setCellPrefix("Cell");
}
else
{
@ -894,14 +897,20 @@ namespace MWGui
void WindowManager::setActiveMap(int x, int y, bool interior)
{
if (!interior)
{
mMap->setCellPrefix("Cell");
mHud->setCellPrefix("Cell");
}
mMap->setActiveCell(x,y, interior);
mHud->setActiveCell(x,y, interior);
}
void WindowManager::setPlayerPos(const float x, const float y)
void WindowManager::setPlayerPos(int cellX, int cellY, const float x, const float y)
{
mMap->setPlayerPos(x,y);
mHud->setPlayerPos(x,y);
mMap->setPlayerPos(cellX, cellY, x, y);
mHud->setPlayerPos(cellX, cellY, x, y);
}
void WindowManager::setPlayerDir(const float x, const float y)
@ -1749,4 +1758,9 @@ namespace MWGui
SDL_free(text);
}
void WindowManager::toggleDebugWindow()
{
mDebugWindow->setVisible(!mDebugWindow->isVisible());
}
}

@ -89,6 +89,7 @@ namespace MWGui
class VideoWidget;
class WindowModal;
class ScreenFader;
class DebugWindow;
class WindowManager : public MWBase::WindowManager
{
@ -182,7 +183,7 @@ namespace MWGui
virtual void updateSkillArea(); ///< update display of skills, factions, birth sign, reputation and bounty
virtual void changeCell(MWWorld::CellStore* cell); ///< change the active cell
virtual void setPlayerPos(const float x, const float y); ///< set player position in map space
virtual void setPlayerPos(int cellX, int cellY, const float x, const float y); ///< set player position in map space
virtual void setPlayerDir(const float x, const float y); ///< set player view direction in map space
virtual void setFocusObject(const MWWorld::Ptr& focus);
@ -333,6 +334,8 @@ namespace MWGui
/// Darken the screen by \a factor (1.0 = no darkening). Works independently from screen fading.
virtual void setScreenFactor (float factor);
virtual void toggleDebugWindow();
private:
bool mConsoleOnlyScripts;
@ -386,6 +389,7 @@ namespace MWGui
MyGUI::ImageBox* mVideoBackground;
VideoWidget* mVideoWidget;
ScreenFader* mScreenFader;
DebugWindow* mDebugWindow;
Translation::Storage& mTranslationDataStorage;
Cursor* mSoftwareCursor;

@ -279,6 +279,9 @@ namespace MWInput
case A_ToggleHUD:
MWBase::Environment::get().getWindowManager()->toggleGui();
break;
case A_ToggleDebug:
MWBase::Environment::get().getWindowManager()->toggleDebugWindow();
break;
case A_QuickSave:
quickSave();
break;
@ -902,6 +905,7 @@ namespace MWInput
defaultKeyBindings[A_QuickKey10] = SDL_SCANCODE_0;
defaultKeyBindings[A_Screenshot] = SDL_SCANCODE_F12;
defaultKeyBindings[A_ToggleHUD] = SDL_SCANCODE_F11;
defaultKeyBindings[A_ToggleDebug] = SDL_SCANCODE_F10;
defaultKeyBindings[A_AlwaysRun] = SDL_SCANCODE_CAPSLOCK;
defaultKeyBindings[A_QuickSave] = SDL_SCANCODE_F5;
defaultKeyBindings[A_QuickLoad] = SDL_SCANCODE_F9;
@ -932,9 +936,11 @@ namespace MWInput
{
clearAllBindings (control);
if (defaultKeyBindings.find(i) != defaultKeyBindings.end())
if (defaultKeyBindings.find(i) != defaultKeyBindings.end()
&& !mInputBinder->isKeyBound(defaultKeyBindings[i]))
mInputBinder->addKeyBinding(control, defaultKeyBindings[i], ICS::Control::INCREASE);
else if (defaultMouseButtonBindings.find(i) != defaultMouseButtonBindings.end())
else if (defaultMouseButtonBindings.find(i) != defaultMouseButtonBindings.end()
&& !mInputBinder->isMouseButtonBound(defaultMouseButtonBindings[i]))
mInputBinder->addMouseButtonBinding (control, defaultMouseButtonBindings[i], ICS::Control::INCREASE);
}
}

@ -259,6 +259,8 @@ namespace MWInput
A_ToggleHUD,
A_ToggleDebug,
A_Last // Marker for the last item
};
};

@ -470,13 +470,13 @@ namespace MWMechanics
return;
MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats (ptr);
const MWWorld::Store<ESM::GameSetting>& settings = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
int endurance = stats.getAttribute (ESM::Attribute::Endurance).getModified ();
// restore fatigue
float fFatigueReturnBase = settings.find("fFatigueReturnBase")->getFloat ();
float fFatigueReturnMult = settings.find("fFatigueReturnMult")->getFloat ();
const MWWorld::Store<ESM::GameSetting>& settings = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
static const float fFatigueReturnBase = settings.find("fFatigueReturnBase")->getFloat ();
static const float fFatigueReturnMult = settings.find("fFatigueReturnMult")->getFloat ();
float x = fFatigueReturnBase + fFatigueReturnMult * endurance;
@ -1122,20 +1122,21 @@ namespace MWMechanics
int hostilesCount = 0; // need to know this to play Battle music
// AI processing is only done within distance of 7168 units to the player. Note the "AI distance" slider doesn't affect this
// (it only does some throttling for targets beyond the "AI distance", so doesn't give any guarantees as to whether AI will be enabled or not)
// This distance could be made configurable later, but the setting must be marked with a big warning:
// using higher values will make a quest in Bloodmoon harder or impossible to complete (bug #1876)
const float sqrProcessingDistance = 7168*7168;
// AI and magic effects update
for(PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
{
if (!iter->first.getClass().getCreatureStats(iter->first).isDead())
{
updateActor(iter->first, duration);
// AI processing is only done within distance of 7168 units to the player. Note the "AI distance" slider doesn't affect this
// (it only does some throttling for targets beyond the "AI distance", so doesn't give any guarantees as to whether AI will be enabled or not)
// This distance could be made configurable later, but the setting must be marked with a big warning:
// using higher values will make a quest in Bloodmoon harder or impossible to complete (bug #1876)
if (MWBase::Environment::get().getMechanicsManager()->isAIActive() &&
Ogre::Vector3(player.getRefData().getPosition().pos).squaredDistance(Ogre::Vector3(iter->first.getRefData().getPosition().pos))
<= 7168*7168)
<= sqrProcessingDistance)
{
if (timerUpdateAITargets == 0)
{
@ -1182,6 +1183,11 @@ namespace MWMechanics
CharacterController* playerCharacter = NULL;
for(PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
{
if (iter->first != player &&
Ogre::Vector3(player.getRefData().getPosition().pos).squaredDistance(Ogre::Vector3(iter->first.getRefData().getPosition().pos))
> sqrProcessingDistance)
continue;
if (iter->first.getClass().getCreatureStats(iter->first).getMagicEffects().get(
ESM::MagicEffect::Paralyze).getMagnitude() > 0)
iter->second->skipAnim();

@ -92,7 +92,11 @@ namespace MWMechanics
if(distanceBetweenResult <= mMaxDist * mMaxDist)
{
if(pathTo(actor,ESM::Pathgrid::Point(mX,mY,mZ),duration)) //Returns true on path complete
ESM::Pathgrid::Point point(mX,mY,mZ);
point.mAutogenerated = 0;
point.mConnectionNum = 0;
point.mUnknown = 0;
if(pathTo(actor,point,duration)) //Returns true on path complete
return true;
mMaxDist = 450;
}

@ -260,15 +260,14 @@ void AiSequence::stack (const AiPackage& package, const MWWorld::Ptr& actor)
for(std::list<AiPackage *>::iterator it = mPackages.begin(); it != mPackages.end(); ++it)
{
if(mPackages.front()->getPriority() <= package.getPriority())
if((*it)->getPriority() <= package.getPriority())
{
mPackages.insert(it,package.clone());
return;
}
}
if(mPackages.empty())
mPackages.push_front (package.clone());
mPackages.push_front (package.clone());
}
AiPackage* MWMechanics::AiSequence::getActivePackage()

@ -133,7 +133,7 @@ void MWMechanics::Alchemy::updateEffects()
std::set<EffectKey> effects (listEffects());
// general alchemy factor
float x = getChance();
float x = getAlchemyFactor();
x *= mTools[ESM::Apparatus::MortarPestle].get<ESM::Apparatus>()->mBase->mData.mQuality;
x *= MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find ("fPotionStrengthMult")->getFloat();
@ -306,18 +306,15 @@ void MWMechanics::Alchemy::increaseSkill()
mAlchemist.getClass().skillUsageSucceeded (mAlchemist, ESM::Skill::Alchemy, 0);
}
float MWMechanics::Alchemy::getChance() const
float MWMechanics::Alchemy::getAlchemyFactor() const
{
const CreatureStats& creatureStats = mAlchemist.getClass().getCreatureStats (mAlchemist);
const NpcStats& npcStats = mAlchemist.getClass().getNpcStats (mAlchemist);
if (beginEffects() == endEffects())
return 0.f;
return
(npcStats.getSkill (ESM::Skill::Alchemy).getModified() +
0.1 * creatureStats.getAttribute (1).getModified()
+ 0.1 * creatureStats.getAttribute (7).getModified());
0.1 * creatureStats.getAttribute (ESM::Attribute::Intelligence).getModified()
+ 0.1 * creatureStats.getAttribute (ESM::Attribute::Luck).getModified());
}
int MWMechanics::Alchemy::countIngredients() const
@ -461,7 +458,14 @@ MWMechanics::Alchemy::Result MWMechanics::Alchemy::create (const std::string& na
if (listEffects().empty())
return Result_NoEffects;
if (getChance()<std::rand()/static_cast<double> (RAND_MAX)*100)
if (beginEffects() == endEffects())
{
// all effects were nullified due to insufficient skill
removeIngredients();
return Result_RandomFailure;
}
if (getAlchemyFactor()<std::rand()/static_cast<double> (RAND_MAX)*100)
{
removeIngredients();
return Result_RandomFailure;

@ -69,8 +69,7 @@ namespace MWMechanics
void increaseSkill();
///< Increase alchemist's skill.
float getChance() const;
///< Return chance of success.
float getAlchemyFactor() const;
int countIngredients() const;

@ -72,7 +72,7 @@ namespace MWMechanics
if (baseMagicka < iAutoSpellTimesCanCast * spell->mData.mCost)
continue;
if (race && std::find(race->mPowers.mList.begin(), race->mPowers.mList.end(), spell->mId) != race->mPowers.mList.end())
if (race && race->mPowers.exists(spell->mId))
continue;
if (!attrSkillCheck(spell, actorSkills, actorAttributes))
@ -220,7 +220,7 @@ namespace MWMechanics
if (spell->mData.mFlags & ESM::Spell::F_Always)
return 100.f;
float skillTerm;
float skillTerm = 0;
if (effectiveSchool != -1)
skillTerm = 2.f * actorSkills[mapSchoolToSkill(effectiveSchool)];
else

@ -1611,7 +1611,7 @@ void CharacterController::update(float duration)
if(mMovementAnimationControlled && mPtr.getClass().isActor())
world->queueMovement(mPtr, moved);
}
else if (mAnimation)
else
mAnimation->updateEffects(duration);
mSkipAnim = false;

@ -25,6 +25,8 @@ namespace MWMechanics
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
"fDiseaseXferChance")->getFloat();
MagicEffects& actorEffects = actor.getClass().getCreatureStats(actor).getMagicEffects();
Spells& spells = carrier.getClass().getCreatureStats(carrier).getSpells();
for (Spells::TIterator it = spells.begin(); it != spells.end(); ++it)
{
@ -33,26 +35,16 @@ namespace MWMechanics
if (actor.getClass().getCreatureStats(actor).getSpells().hasSpell(spell->mId))
continue;
bool hasCorprusEffect = false;
for (std::vector<ESM::ENAMstruct>::const_iterator effectIt = spell->mEffects.mList.begin(); effectIt != spell->mEffects.mList.end(); ++effectIt)
{
if (effectIt->mEffectID == ESM::MagicEffect::Corprus)
{
hasCorprusEffect = true;
break;
}
}
float resist = 0.f;
if (hasCorprusEffect)
resist = 1.f - 0.01 * (actor.getClass().getCreatureStats(actor).getMagicEffects().get(ESM::MagicEffect::ResistCorprusDisease).getMagnitude()
- actor.getClass().getCreatureStats(actor).getMagicEffects().get(ESM::MagicEffect::WeaknessToCorprusDisease).getMagnitude());
if (spells.hasCorprusEffect(spell))
resist = 1.f - 0.01 * (actorEffects.get(ESM::MagicEffect::ResistCorprusDisease).getMagnitude()
- actorEffects.get(ESM::MagicEffect::WeaknessToCorprusDisease).getMagnitude());
else if (spell->mData.mType == ESM::Spell::ST_Disease)
resist = 1.f - 0.01 * (actor.getClass().getCreatureStats(actor).getMagicEffects().get(ESM::MagicEffect::ResistCommonDisease).getMagnitude()
- actor.getClass().getCreatureStats(actor).getMagicEffects().get(ESM::MagicEffect::WeaknessToCommonDisease).getMagnitude());
resist = 1.f - 0.01 * (actorEffects.get(ESM::MagicEffect::ResistCommonDisease).getMagnitude()
- actorEffects.get(ESM::MagicEffect::WeaknessToCommonDisease).getMagnitude());
else if (spell->mData.mType == ESM::Spell::ST_Blight)
resist = 1.f - 0.01 * (actor.getClass().getCreatureStats(actor).getMagicEffects().get(ESM::MagicEffect::ResistBlightDisease).getMagnitude()
- actor.getClass().getCreatureStats(actor).getMagicEffects().get(ESM::MagicEffect::WeaknessToBlightDisease).getMagnitude());
resist = 1.f - 0.01 * (actorEffects.get(ESM::MagicEffect::ResistBlightDisease).getMagnitude()
- actorEffects.get(ESM::MagicEffect::WeaknessToBlightDisease).getMagnitude());
else
continue;

@ -53,6 +53,9 @@ namespace MWMechanics
MWWorld::ContainerStore& store = player.getClass().getContainerStore(player);
ESM::Enchantment enchantment;
enchantment.mData.mCharge = getGemCharge();
enchantment.mData.mAutocalc = 0;
enchantment.mData.mType = mCastStyle;
enchantment.mData.mCost = getEnchantPoints();
store.remove(mSoulGemPtr, 1, player);
@ -72,8 +75,6 @@ namespace MWMechanics
{
enchantment.mData.mCharge=0;
}
enchantment.mData.mType = mCastStyle;
enchantment.mData.mCost = getEnchantPoints();
enchantment.mEffects = mEffectList;
// Apply the enchantment

@ -566,11 +566,14 @@ namespace MWMechanics
MWWorld::LiveCellRef<ESM::NPC>* player = playerPtr.get<ESM::NPC>();
const MWMechanics::NpcStats &playerStats = playerPtr.getClass().getNpcStats(playerPtr);
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
static const float fDispRaceMod = gmst.find("fDispRaceMod")->getFloat();
if (Misc::StringUtils::ciEqual(npc->mBase->mRace, player->mBase->mRace))
x += MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispRaceMod")->getFloat();
x += fDispRaceMod;
x += MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispPersonalityMult")->getFloat()
* (playerStats.getAttribute(ESM::Attribute::Personality).getModified() - MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispPersonalityBase")->getFloat());
static const float fDispPersonalityMult = gmst.find("fDispPersonalityMult")->getFloat();
static const float fDispPersonalityBase = gmst.find("fDispPersonalityBase")->getFloat();
x += fDispPersonalityMult * (playerStats.getAttribute(ESM::Attribute::Personality).getModified() - fDispPersonalityBase);
float reaction = 0;
int rank = 0;
@ -606,16 +609,23 @@ namespace MWMechanics
reaction = 0;
rank = 0;
}
x += (MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispFactionRankMult")->getFloat() * rank
+ MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispFactionRankBase")->getFloat())
* MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispFactionMod")->getFloat() * reaction;
x -= MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispCrimeMod")->getFloat() * playerStats.getBounty();
static const float fDispFactionRankMult = gmst.find("fDispFactionRankMult")->getFloat();
static const float fDispFactionRankBase = gmst.find("fDispFactionRankBase")->getFloat();
static const float fDispFactionMod = gmst.find("fDispFactionMod")->getFloat();
x += (fDispFactionRankMult * rank
+ fDispFactionRankBase)
* fDispFactionMod * reaction;
static const float fDispCrimeMod = gmst.find("fDispCrimeMod")->getFloat();
static const float fDispDiseaseMod = gmst.find("fDispDiseaseMod")->getFloat();
x -= fDispCrimeMod * playerStats.getBounty();
if (playerStats.hasCommonDisease() || playerStats.hasBlightDisease())
x += MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispDiseaseMod")->getFloat();
x += fDispDiseaseMod;
static const float fDispWeaponDrawn = gmst.find("fDispWeaponDrawn")->getFloat();
if (playerStats.getDrawState() == MWMechanics::DrawState_Weapon)
x += MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispWeaponDrawn")->getFloat();
x += fDispWeaponDrawn;
x += ptr.getClass().getCreatureStats(ptr).getMagicEffects().get(ESM::MagicEffect::Charm).getMagnitude();

@ -74,7 +74,7 @@ namespace MWMechanics
TIterator end() const;
bool hasSpell(const std::string& spell) { return mSpells.find(Misc::StringUtils::lowerCase(spell)) != mSpells.end(); }
bool hasSpell(const std::string& spell) const { return mSpells.find(Misc::StringUtils::lowerCase(spell)) != mSpells.end(); }
void add (const std::string& spell);
///< Adding a spell that is already listed in *this is a no-op.

@ -19,6 +19,7 @@ namespace MWRender
Camera::Camera (Ogre::Camera *camera)
: mCamera(camera),
mCameraNode(NULL),
mCameraPosNode(NULL),
mAnimation(NULL),
mFirstPersonView(true),
mPreviewMode(false),
@ -26,8 +27,8 @@ namespace MWRender
mNearest(30.f),
mFurthest(800.f),
mIsNearest(false),
mHeight(128.f),
mCameraDistance(300.f),
mHeight(124.f),
mCameraDistance(192.f),
mDistanceAdjusted(false),
mVanityToggleQueued(false),
mViewModeToggleQueued(false)
@ -66,12 +67,16 @@ namespace MWRender
}
Ogre::Quaternion xr(Ogre::Radian(getPitch() + Ogre::Math::HALF_PI), Ogre::Vector3::UNIT_X);
if (!mVanity.enabled && !mPreviewMode) {
mCamera->getParentNode()->setOrientation(xr);
} else {
Ogre::Quaternion orient = xr;
if (mVanity.enabled || mPreviewMode) {
Ogre::Quaternion zr(Ogre::Radian(getYaw()), Ogre::Vector3::UNIT_Z);
mCamera->getParentNode()->setOrientation(zr * xr);
orient = zr * xr;
}
if (isFirstPerson())
mCamera->getParentNode()->setOrientation(orient);
else
mCameraNode->setOrientation(orient);
}
const std::string &Camera::getHandle() const
@ -79,20 +84,40 @@ namespace MWRender
return mTrackingPtr.getRefData().getHandle();
}
void Camera::attachTo(const MWWorld::Ptr &ptr)
Ogre::SceneNode* Camera::attachTo(const MWWorld::Ptr &ptr)
{
mTrackingPtr = ptr;
Ogre::SceneNode *node = mTrackingPtr.getRefData().getBaseNode()->createChildSceneNode(Ogre::Vector3(0.0f, 0.0f, mHeight));
node->setInheritScale(false);
Ogre::SceneNode *posNode = node->createChildSceneNode();
posNode->setInheritScale(false);
if(mCameraNode)
{
node->setOrientation(mCameraNode->getOrientation());
node->setPosition(mCameraNode->getPosition());
node->setScale(mCameraNode->getScale());
posNode->setPosition(mCameraPosNode->getPosition());
mCameraNode->getCreator()->destroySceneNode(mCameraNode);
mCameraNode->getCreator()->destroySceneNode(mCameraPosNode);
}
mCameraNode = node;
if(!mCamera->isAttached())
mCameraNode->attachObject(mCamera);
mCameraPosNode = posNode;
if (!isFirstPerson())
{
mCamera->detachFromParent();
mCameraPosNode->attachObject(mCamera);
}
return mCameraPosNode;
}
void Camera::setPosition(const Ogre::Vector3& position)
{
mCameraPosNode->setPosition(position);
}
void Camera::setPosition(float x, float y, float z)
{
setPosition(Ogre::Vector3(x,y,z));
}
void Camera::updateListener()
@ -155,9 +180,9 @@ namespace MWRender
processViewChange();
if (mFirstPersonView) {
mCamera->setPosition(0.f, 0.f, 0.f);
setPosition(0.f, 0.f, 0.f);
} else {
mCamera->setPosition(0.f, 0.f, mCameraDistance);
setPosition(0.f, 0.f, mCameraDistance);
}
}
@ -172,7 +197,7 @@ namespace MWRender
{
// Changing the view will stop all playing animations, so if we are playing
// anything important, queue the view change for later
if (!mPreviewMode)
if (isFirstPerson() && !mAnimation->upperBodyReady())
{
mVanityToggleQueued = true;
return false;
@ -191,14 +216,14 @@ namespace MWRender
Ogre::Vector3 rot(0.f, 0.f, 0.f);
if (mVanity.enabled) {
rot.x = Ogre::Degree(-30.f).valueRadians();
mMainCam.offset = mCamera->getPosition().z;
mMainCam.offset = mCameraPosNode->getPosition().z;
} else {
rot.x = getPitch();
offset = mMainCam.offset;
}
rot.z = getYaw();
mCamera->setPosition(0.f, 0.f, offset);
setPosition(0.f, 0.f, offset);
rotateCamera(rot, false);
return true;
@ -215,7 +240,7 @@ namespace MWRender
mPreviewMode = enable;
processViewChange();
float offset = mCamera->getPosition().z;
float offset = mCameraPosNode->getPosition().z;
if (mPreviewMode) {
mMainCam.offset = offset;
offset = mPreviewCam.offset;
@ -224,7 +249,7 @@ namespace MWRender
offset = mMainCam.offset;
}
mCamera->setPosition(0.f, 0.f, offset);
setPosition(0.f, 0.f, offset);
}
void Camera::setSneakOffset(float offset)
@ -283,7 +308,7 @@ namespace MWRender
float Camera::getCameraDistance() const
{
return mCamera->getPosition().z;
return mCameraPosNode->getPosition().z;
}
void Camera::setCameraDistance(float dist, bool adjust, bool override)
@ -295,7 +320,7 @@ namespace MWRender
Ogre::Vector3 v(0.f, 0.f, dist);
if (adjust) {
v += mCamera->getPosition();
v += mCameraPosNode->getPosition();
}
if (v.z >= mFurthest) {
v.z = mFurthest;
@ -305,7 +330,7 @@ namespace MWRender
v.z = mNearest;
mIsNearest = true;
}
mCamera->setPosition(v);
setPosition(v);
if (override) {
if (mVanity.enabled || mPreviewMode) {
@ -322,9 +347,9 @@ namespace MWRender
{
if (mDistanceAdjusted) {
if (mVanity.enabled || mPreviewMode) {
mCamera->setPosition(0, 0, mPreviewCam.offset);
setPosition(0, 0, mPreviewCam.offset);
} else if (!mFirstPersonView) {
mCamera->setPosition(0, 0, mCameraDistance);
setPosition(0, 0, mCameraDistance);
}
}
mDistanceAdjusted = false;
@ -355,10 +380,10 @@ namespace MWRender
Ogre::TagPoint *tag = mAnimation->attachObjectToBone("Head", mCamera);
tag->setInheritOrientation(false);
}
else
else
{
mAnimation->setViewMode(NpcAnimation::VM_Normal);
mCameraNode->attachObject(mCamera);
mCameraPosNode->attachObject(mCamera);
}
rotateCamera(Ogre::Vector3(getPitch(), 0.f, getYaw()), false);
}
@ -368,8 +393,7 @@ namespace MWRender
mCamera->getParentSceneNode()->needUpdate(true);
camera = mCamera->getRealPosition();
focal = Ogre::Vector3((mCamera->getParentNode()->_getFullTransform() *
Ogre::Vector4(0.0f, 0.0f, 0.0f, 1.0f)).ptr());
focal = mCameraNode->_getDerivedPosition();
}
void Camera::togglePlayerLooking(bool enable)

@ -27,6 +27,7 @@ namespace MWRender
Ogre::Camera *mCamera;
Ogre::SceneNode *mCameraNode;
Ogre::SceneNode *mCameraPosNode;
NpcAnimation *mAnimation;
@ -52,6 +53,9 @@ namespace MWRender
/// Updates sound manager listener data
void updateListener();
void setPosition(const Ogre::Vector3& position);
void setPosition(float x, float y, float z);
public:
Camera(Ogre::Camera *camera);
~Camera();
@ -72,7 +76,7 @@ namespace MWRender
const std::string &getHandle() const;
/// Attach camera to object
void attachTo(const MWWorld::Ptr &);
Ogre::SceneNode* attachTo(const MWWorld::Ptr &);
/// @param Force view mode switch, even if currently not allowed by the animation.
void toggleViewMode(bool force=false);

@ -25,7 +25,7 @@ using namespace MWRender;
using namespace Ogre;
LocalMap::LocalMap(OEngine::Render::OgreRenderer* rend, MWRender::RenderingManager* rendering) :
mInterior(false), mCellX(0), mCellY(0)
mInterior(false)
{
mRendering = rend;
mRenderingManager = rendering;
@ -522,10 +522,9 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni
{
x = std::ceil(pos.x / sSize)-1;
y = std::ceil(pos.y / sSize)-1;
mCellX = x;
mCellY = y;
}
MWBase::Environment::get().getWindowManager()->setActiveMap(x,y,mInterior);
else
MWBase::Environment::get().getWindowManager()->setActiveMap(x,y,mInterior);
// convert from world coordinates to texture UV coordinates
std::string texBaseName;
@ -540,7 +539,7 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni
texBaseName = mInteriorName + "_";
}
MWBase::Environment::get().getWindowManager()->setPlayerPos(u, v);
MWBase::Environment::get().getWindowManager()->setPlayerPos(x, y, u, v);
MWBase::Environment::get().getWindowManager()->setPlayerDir(playerdirection.x, playerdirection.y);
// explore radius (squared)

@ -134,7 +134,6 @@ namespace MWRender
Ogre::RenderTarget* mRenderTarget;
bool mInterior;
int mCellX, mCellY;
Ogre::AxisAlignedBox mBounds;
std::string mInteriorName;
};

@ -50,7 +50,8 @@ namespace MWRender
void Refraction::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt)
{
mParentCamera->getParentSceneNode ()->needUpdate ();
if (mParentCamera->isAttached())
mParentCamera->getParentSceneNode ()->needUpdate ();
mCamera->setOrientation(mParentCamera->getDerivedOrientation());
mCamera->setPosition(mParentCamera->getDerivedPosition());
mCamera->setNearClipDistance(mParentCamera->getNearClipDistance());

@ -63,6 +63,7 @@ RenderingManager::RenderingManager(OEngine::Render::OgreRenderer& _rend, const b
, mPhysicsEngine(engine)
, mTerrain(NULL)
, mEffectManager(NULL)
, mRenderWorld(true)
{
mActors = new MWRender::Actors(mRendering, this);
mObjects = new MWRender::Objects(mRendering);
@ -232,6 +233,15 @@ bool RenderingManager::toggleWater()
return mWater->toggle();
}
bool RenderingManager::toggleWorld()
{
mRenderWorld = !mRenderWorld;
int visibilityMask = mRenderWorld ? ~int(0) : 0;
mRendering.getViewport()->setVisibilityMask(visibilityMask);
return mRenderWorld;
}
void RenderingManager::cellAdded (MWWorld::CellStore *store)
{
if (store->isExterior())
@ -302,7 +312,7 @@ void RenderingManager::updatePlayerPtr(const MWWorld::Ptr &ptr)
if(mPlayerAnimation)
mPlayerAnimation->updatePtr(ptr);
if(mCamera->getHandle() == ptr.getRefData().getHandle())
mCamera->attachTo(ptr);
attachCameraTo(ptr);
}
void RenderingManager::rebuildPtr(const MWWorld::Ptr &ptr)
@ -317,7 +327,7 @@ void RenderingManager::rebuildPtr(const MWWorld::Ptr &ptr)
anim->rebuild();
if(mCamera->getHandle() == ptr.getRefData().getHandle())
{
mCamera->attachTo(ptr);
attachCameraTo(ptr);
mCamera->setAnimation(anim);
}
}
@ -489,7 +499,7 @@ bool RenderingManager::toggleRenderMode(int mode)
}
}
void RenderingManager::configureFog(MWWorld::CellStore &mCell)
void RenderingManager::configureFog(const MWWorld::CellStore &mCell)
{
Ogre::ColourValue color;
color.setAsABGR (mCell.getCell()->mAmbi.mFog);
@ -500,7 +510,7 @@ void RenderingManager::configureFog(MWWorld::CellStore &mCell)
void RenderingManager::configureFog(const float density, const Ogre::ColourValue& colour)
{
mFogColour = colour;
float max = Settings::Manager::getFloat("max viewing distance", "Viewing distance");
float max = Settings::Manager::getFloat("viewing distance", "Viewing distance");
if (density == 0)
{
@ -732,7 +742,7 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec
{
setMenuTransparency(Settings::Manager::getFloat("menu transparency", "GUI"));
}
else if (it->second == "max viewing distance" && it->first == "Viewing distance")
else if (it->second == "viewing distance" && it->first == "Viewing distance")
{
if (!MWBase::Environment::get().getWorld()->isCellExterior() && !MWBase::Environment::get().getWorld()->isCellQuasiExterior()
&& MWBase::Environment::get().getWorld()->getPlayerPtr().mCell)
@ -859,7 +869,13 @@ void RenderingManager::getTriangleBatchCount(unsigned int &triangles, unsigned i
void RenderingManager::setupPlayer(const MWWorld::Ptr &ptr)
{
ptr.getRefData().setBaseNode(mRendering.getScene()->getSceneNode("player"));
mCamera->attachTo(ptr);
attachCameraTo(ptr);
}
void RenderingManager::attachCameraTo(const MWWorld::Ptr &ptr)
{
Ogre::SceneNode* cameraNode = mCamera->attachTo(ptr);
mSkyManager->attachToNode(cameraNode);
}
void RenderingManager::renderPlayer(const MWWorld::Ptr &ptr)

@ -123,6 +123,7 @@ public:
void setWaterHeight(const float height);
bool toggleWater();
bool toggleWorld();
/// Updates object rendering after cell change
/// \param old Object reference in previous cell
@ -182,7 +183,7 @@ public:
///< request the local map for a cell
/// configure fog according to cell
void configureFog(MWWorld::CellStore &mCell);
void configureFog(const MWWorld::CellStore &mCell);
/// configure fog manually
void configureFog(const float density, const Ogre::ColourValue& colour);
@ -220,6 +221,8 @@ private:
void setAmbientMode();
void applyFog(bool underwater);
void attachCameraTo(const MWWorld::Ptr& ptr);
void setMenuTransparency(float val);
bool mSunEnabled;
@ -266,6 +269,8 @@ private:
MWRender::LocalMap* mLocalMap;
MWRender::Shadows* mShadows;
bool mRenderWorld;
};
}

@ -382,9 +382,7 @@ void SkyManager::clearRain()
for (std::map<Ogre::SceneNode*, NifOgre::ObjectScenePtr>::iterator it = mRainModels.begin(); it != mRainModels.end();)
{
it->second.setNull();
Ogre::SceneNode* parent = it->first->getParentSceneNode();
mSceneMgr->destroySceneNode(it->first);
mSceneMgr->destroySceneNode(parent);
mRainModels.erase(it++);
}
}
@ -402,9 +400,7 @@ void SkyManager::updateRain(float dt)
if (pos.z < -minHeight)
{
it->second.setNull();
Ogre::SceneNode* parent = it->first->getParentSceneNode();
mSceneMgr->destroySceneNode(it->first);
mSceneMgr->destroySceneNode(parent);
mRainModels.erase(it++);
}
else
@ -420,17 +416,20 @@ void SkyManager::updateRain(float dt)
{
mRainTimer = 0;
// TODO: handle rain settings from Morrowind.ini
const float rangeRandom = 100;
float xOffs = (std::rand()/(RAND_MAX+1.0)) * rangeRandom - (rangeRandom/2);
float yOffs = (std::rand()/(RAND_MAX+1.0)) * rangeRandom - (rangeRandom/2);
Ogre::SceneNode* sceneNode = mCamera->getParentSceneNode()->createChildSceneNode();
sceneNode->setInheritOrientation(false);
// Create a separate node to control the offset, since a node with setInheritOrientation(false) will still
// consider the orientation of the parent node for its position, just not for its orientation
float startHeight = 700;
Ogre::SceneNode* offsetNode = sceneNode->createChildSceneNode(Ogre::Vector3(xOffs,yOffs,startHeight));
Ogre::SceneNode* offsetNode = mParticleNode->createChildSceneNode(Ogre::Vector3(xOffs,yOffs,startHeight));
// Spawn a new rain object for each instance.
// TODO: this is inefficient. We could try to use an Ogre::ParticleSystem instead, but then we would need to make assumptions
// about the rain meshes being Quads and their dimensions.
// Or we could clone meshes into one vertex buffer manually.
NifOgre::ObjectScenePtr objects = NifOgre::Loader::createObjects(offsetNode, mRainEffect);
for (unsigned int i=0; i<objects->mEntities.size(); ++i)
{
@ -562,12 +561,6 @@ void SkyManager::setWeather(const MWWorld::WeatherResult& weather)
}
else
{
if (!mParticleNode)
{
mParticleNode = mCamera->getParentSceneNode()->createChildSceneNode();
mParticleNode->setInheritOrientation(false);
}
mParticle = NifOgre::Loader::createObjects(mParticleNode, mCurrentParticleEffect);
for(size_t i = 0; i < mParticle->mParticles.size(); ++i)
{
@ -783,3 +776,16 @@ void SkyManager::setGlareEnabled (bool enabled)
return;
mSunGlare->setVisible (mSunEnabled && enabled);
}
void SkyManager::attachToNode(SceneNode *sceneNode)
{
if (!mParticleNode)
{
mParticleNode = sceneNode->createChildSceneNode();
mParticleNode->setInheritOrientation(false);
}
else
{
sceneNode->addChild(mParticleNode);
}
}

@ -116,6 +116,9 @@ namespace MWRender
SkyManager(Ogre::SceneNode* root, Ogre::Camera* pCamera);
~SkyManager();
/// Attach weather particle effects to this scene node (should be the Camera's parent node)
void attachToNode(Ogre::SceneNode* sceneNode);
void update(float duration);
void enable();

@ -74,7 +74,8 @@ CubeReflection::~CubeReflection ()
void CubeReflection::update ()
{
mParentCamera->getParentSceneNode ()->needUpdate ();
if (mParentCamera->isAttached())
mParentCamera->getParentSceneNode ()->needUpdate ();
mCamera->setPosition(mParentCamera->getDerivedPosition());
}
@ -133,7 +134,8 @@ void PlaneReflection::renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::St
void PlaneReflection::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt)
{
mParentCamera->getParentSceneNode ()->needUpdate ();
if (mParentCamera->isAttached())
mParentCamera->getParentSceneNode ()->needUpdate ();
mCamera->setOrientation(mParentCamera->getDerivedOrientation());
mCamera->setPosition(mParentCamera->getDerivedPosition());
mCamera->setNearClipDistance(mParentCamera->getNearClipDistance());

@ -432,5 +432,6 @@ op 0x20002ac-0x20002c3: SetMagicEffect, explicit
op 0x20002c4-0x20002db: ModMagicEffect
op 0x20002dc-0x20002f3: ModMagicEffect, explicit
op 0x20002f4: ResetActors
op 0x20002f5: ToggleWorld
opcodes 0x20002f5-0x3ffffff unused
opcodes 0x20002f6-0x3ffffff unused

@ -290,6 +290,17 @@ namespace MWScript
}
};
class OpToggleWorld : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
runtime.getContext().report(MWBase::Environment::get().getWorld()->toggleWorld() ? "World -> On"
: "World -> Off");
}
};
class OpDontSaveObject : public Interpreter::Opcode0
{
public:
@ -979,6 +990,7 @@ namespace MWScript
interpreter.installSegment5 (Compiler::Misc::opcodeFadeTo, new OpFadeTo);
interpreter.installSegment5 (Compiler::Misc::opcodeTogglePathgrid, new OpTogglePathgrid);
interpreter.installSegment5 (Compiler::Misc::opcodeToggleWater, new OpToggleWater);
interpreter.installSegment5 (Compiler::Misc::opcodeToggleWorld, new OpToggleWorld);
interpreter.installSegment5 (Compiler::Misc::opcodeDontSaveObject, new OpDontSaveObject);
interpreter.installSegment5 (Compiler::Misc::opcodeToggleVanityMode, new OpToggleVanityMode);
interpreter.installSegment5 (Compiler::Misc::opcodeGetPcSleep, new OpGetPcSleep);

@ -40,7 +40,7 @@ using namespace Ogre;
namespace
{
void animateCollisionShapes (std::map<OEngine::Physic::RigidBody*, OEngine::Physic::AnimatedShapeInstance>& map)
void animateCollisionShapes (std::map<OEngine::Physic::RigidBody*, OEngine::Physic::AnimatedShapeInstance>& map, btDynamicsWorld* dynamicsWorld)
{
for (std::map<OEngine::Physic::RigidBody*, OEngine::Physic::AnimatedShapeInstance>::iterator it = map.begin();
it != map.end(); ++it)
@ -79,6 +79,9 @@ void animateCollisionShapes (std::map<OEngine::Physic::RigidBody*, OEngine::Phys
compound->getChildShape(shapeIt->second)->setLocalScaling(BtOgre::Convert::toBullet(bone->_getDerivedScale()));
compound->updateChildTransform(shapeIt->second, trans);
}
// needed because we used btDynamicsWorld::setForceUpdateAllAabbs(false)
dynamicsWorld->updateSingleAabb(it->first);
}
}
@ -283,8 +286,9 @@ namespace MWWorld
*/
OEngine::Physic::ActorTracer tracer;
bool wasOnGround = false;
bool isOnGround = false;
bool isOnGround = physicActor->getOnGround();
if (movement.z > 0.f)
isOnGround = false;
Ogre::Vector3 inertia(0.0f);
Ogre::Vector3 velocity;
@ -317,23 +321,6 @@ namespace MWWorld
velocity = newVelocity;
}
inertia = velocity; // NOTE: velocity is for z axis only in this code block
if(!(movement.z > 0.0f)) // falling or moving horizontally (or stationary?) check if we're on ground now
{
wasOnGround = physicActor->getOnGround(); // store current state
tracer.doTrace(colobj, position, position - Ogre::Vector3(0,0,2), engine); // check if down 2 possible
if(tracer.mFraction < 1.0f && getSlope(tracer.mPlaneNormal) <= sMaxSlope)
{
const btCollisionObject* standingOn = tracer.mHitObject;
if (const OEngine::Physic::RigidBody* body = dynamic_cast<const OEngine::Physic::RigidBody*>(standingOn))
{
standingCollisionTracker[ptr.getRefData().getHandle()] = body->mName;
}
isOnGround = true;
// if we're on the ground, don't try to fall any more
velocity.z = std::max(0.0f, velocity.z);
}
}
}
ptr.getClass().getMovementSettings(ptr).mPosition[2] = 0;
@ -385,7 +372,6 @@ namespace MWWorld
if(tracer.mFraction >= 1.0f)
{
newPosition = tracer.mEndPos; // ok to move, so set newPosition
remainingTime *= (1.0f-tracer.mFraction); // FIXME: remainingTime is no longer used so don't set it?
break;
}
else
@ -406,7 +392,6 @@ namespace MWWorld
// precision can be lost due to any math Bullet does internally). Since we
// aren't performing any collision detection, we want to reject the next
// position, so that we don't slowly move inside another object.
remainingTime *= (1.0f-tracer.mFraction); // FIXME: remainingTime is no longer used so don't set it?
break;
}
@ -438,12 +423,22 @@ namespace MWWorld
}
}
if(isOnGround || wasOnGround)
if (!(inertia.z > 0.f) && !(newPosition.z < waterlevel || isFlying))
{
tracer.doTrace(colobj, newPosition, newPosition - Ogre::Vector3(0,0,sStepSize+2.0f), engine);
Ogre::Vector3 from = newPosition;
Ogre::Vector3 to = newPosition - (isOnGround ?
Ogre::Vector3(0,0,sStepSize+2.f) : Ogre::Vector3(0,0,2.f));
tracer.doTrace(colobj, from, to, engine);
if(tracer.mFraction < 1.0f && getSlope(tracer.mPlaneNormal) <= sMaxSlope)
{
const btCollisionObject* standingOn = tracer.mHitObject;
if (const OEngine::Physic::RigidBody* body = dynamic_cast<const OEngine::Physic::RigidBody*>(standingOn))
{
standingCollisionTracker[ptr.getRefData().getHandle()] = body->mName;
}
newPosition.z = tracer.mEndPos.z + 1.0f;
isOnGround = true;
}
else
@ -672,11 +667,18 @@ namespace MWWorld
const Ogre::Vector3 &position = node->getPosition();
if(OEngine::Physic::RigidBody *body = mEngine->getRigidBody(handle))
{
body->getWorldTransform().setOrigin(btVector3(position.x,position.y,position.z));
mEngine->mDynamicsWorld->updateSingleAabb(body);
}
if(OEngine::Physic::RigidBody *body = mEngine->getRigidBody(handle, true))
{
body->getWorldTransform().setOrigin(btVector3(position.x,position.y,position.z));
mEngine->mDynamicsWorld->updateSingleAabb(body);
}
// Actors update their AABBs every frame (DISABLE_DEACTIVATION), so no need to do it manually
if(OEngine::Physic::PhysicActor *physact = mEngine->getCharacter(handle))
physact->setPosition(position);
}
@ -698,6 +700,7 @@ namespace MWWorld
body->getWorldTransform().setRotation(btQuaternion(rotation.x, rotation.y, rotation.z, rotation.w));
else
mEngine->boxAdjustExternal(handleToMesh[handle], body, node->getScale().x, node->getPosition(), rotation);
mEngine->mDynamicsWorld->updateSingleAabb(body);
}
if (OEngine::Physic::RigidBody* body = mEngine->getRigidBody(handle, true))
{
@ -705,6 +708,7 @@ namespace MWWorld
body->getWorldTransform().setRotation(btQuaternion(rotation.x, rotation.y, rotation.z, rotation.w));
else
mEngine->boxAdjustExternal(handleToMesh[handle], body, node->getScale().x, node->getPosition(), rotation);
mEngine->mDynamicsWorld->updateSingleAabb(body);
}
}
@ -866,8 +870,8 @@ namespace MWWorld
void PhysicsSystem::stepSimulation(float dt)
{
animateCollisionShapes(mEngine->mAnimatedShapes);
animateCollisionShapes(mEngine->mAnimatedRaycastingShapes);
animateCollisionShapes(mEngine->mAnimatedShapes, mEngine->mDynamicsWorld);
animateCollisionShapes(mEngine->mAnimatedRaycastingShapes, mEngine->mDynamicsWorld);
mEngine->stepSimulation(dt);
}

@ -5,7 +5,7 @@
#include <components/nif/niffile.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" /// FIXME
#include "../mwbase/world.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/windowmanager.hpp"
@ -117,6 +117,28 @@ namespace MWWorld
}
}
void Scene::getGridCenter(int &cellX, int &cellY)
{
int maxX = std::numeric_limits<int>().min();
int maxY = std::numeric_limits<int>().min();
int minX = std::numeric_limits<int>().max();
int minY = std::numeric_limits<int>().max();
CellStoreCollection::iterator iter = mActiveCells.begin();
while (iter!=mActiveCells.end())
{
assert ((*iter)->getCell()->isExterior());
int x = (*iter)->getCell()->getGridX();
int y = (*iter)->getCell()->getGridY();
maxX = std::max(x, maxX);
maxY = std::max(y, maxY);
minX = std::min(x, minX);
minY = std::min(y, minY);
++iter;
}
cellX = (minX + maxX) / 2;
cellY = (minY + maxY) / 2;
}
void Scene::update (float duration, bool paused)
{
if (mNeedMapUpdate)
@ -126,6 +148,13 @@ namespace MWWorld
for (CellStoreCollection::iterator active = mActiveCells.begin(); active!=mActiveCells.end(); ++active)
mRendering.requestMap(*active);
mNeedMapUpdate = false;
if (mCurrentCell->isExterior())
{
int cellX, cellY;
getGridCenter(cellX, cellY);
MWBase::Environment::get().getWindowManager()->setActiveMap(cellX,cellY,false);
}
}
mRendering.update (duration, paused);
@ -213,41 +242,6 @@ namespace MWWorld
MWBase::Environment::get().getWorld()->getLocalScripts().addCell (cell);
}
void Scene::playerCellChange(CellStore *cell, const ESM::Position& pos, bool adjustPlayerPos)
{
MWBase::World *world = MWBase::Environment::get().getWorld();
MWWorld::Ptr old = world->getPlayerPtr();
world->getPlayer().setCell(cell);
MWWorld::Ptr player = world->getPlayerPtr();
mRendering.updatePlayerPtr(player);
if (adjustPlayerPos) {
world->moveObject(player, pos.pos[0], pos.pos[1], pos.pos[2]);
float x = Ogre::Radian(pos.rot[0]).valueDegrees();
float y = Ogre::Radian(pos.rot[1]).valueDegrees();
float z = Ogre::Radian(pos.rot[2]).valueDegrees();
world->rotateObject(player, x, y, z);
player.getClass().adjustPosition(player, true);
}
MWBase::MechanicsManager *mechMgr =
MWBase::Environment::get().getMechanicsManager();
mechMgr->updateCell(old, player);
mechMgr->watchActor(player);
mRendering.updateTerrain();
// Delay the map update until scripts have been given a chance to run.
// If we don't do this, objects that should be disabled will still appear on the map.
mNeedMapUpdate = true;
MWBase::Environment::get().getWindowManager()->changeCell(mCurrentCell);
}
void Scene::changeToVoid()
{
CellStoreCollection::iterator active = mActiveCells.begin();
@ -257,7 +251,28 @@ namespace MWWorld
mCurrentCell = NULL;
}
void Scene::changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos)
void Scene::playerMoved(const Ogre::Vector3 &pos)
{
if (!mCurrentCell || !mCurrentCell->isExterior())
return;
// figure out the center of the current cell grid (*not* necessarily mCurrentCell, which is the cell the player is in)
int cellX, cellY;
getGridCenter(cellX, cellY);
float centerX, centerY;
MWBase::Environment::get().getWorld()->indexToPosition(cellX, cellY, centerX, centerY, true);
const float maxDistance = 8192/2 + 1024; // 1/2 cell size + threshold
float distance = std::max(std::abs(centerX-pos.x), std::abs(centerY-pos.y));
if (distance > maxDistance)
{
int newX, newY;
MWBase::Environment::get().getWorld()->positionToIndex(pos.x, pos.y, newX, newY);
changeCellGrid(newX, newY);
mRendering.updateTerrain();
}
}
void Scene::changeCellGrid (int X, int Y)
{
Loading::Listener* loadingListener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
Loading::ScopedLoad load(loadingListener);
@ -286,6 +301,7 @@ namespace MWWorld
int refsToLoad = 0;
// get the number of refs to load
for (int x=X-1; x<=X+1; ++x)
{
for (int y=Y-1; y<=Y+1; ++y)
{
CellStoreCollection::iterator iter = mActiveCells.begin();
@ -304,11 +320,13 @@ namespace MWWorld
if (iter==mActiveCells.end())
refsToLoad += MWBase::Environment::get().getWorld()->getExterior(x, y)->count();
}
}
loadingListener->setProgressRange(refsToLoad);
// Load cells
for (int x=X-1; x<=X+1; ++x)
{
for (int y=Y-1; y<=Y+1; ++y)
{
CellStoreCollection::iterator iter = mActiveCells.begin();
@ -331,32 +349,47 @@ namespace MWWorld
loadCell (cell, loadingListener);
}
}
}
// find current cell
CellStoreCollection::iterator iter = mActiveCells.begin();
CellStore* current = MWBase::Environment::get().getWorld()->getExterior(X,Y);
MWBase::Environment::get().getWindowManager()->changeCell(current);
while (iter!=mActiveCells.end())
{
assert ((*iter)->getCell()->isExterior());
mCellChanged = true;
if (X==(*iter)->getCell()->getGridX() &&
Y==(*iter)->getCell()->getGridY())
break;
// Delay the map update until scripts have been given a chance to run.
// If we don't do this, objects that should be disabled will still appear on the map.
mNeedMapUpdate = true;
}
++iter;
}
void Scene::changePlayerCell(CellStore *cell, const ESM::Position &pos, bool adjustPlayerPos)
{
mCurrentCell = cell;
assert (iter!=mActiveCells.end());
MWBase::World *world = MWBase::Environment::get().getWorld();
MWWorld::Ptr old = world->getPlayerPtr();
world->getPlayer().setCell(cell);
mCurrentCell = *iter;
MWWorld::Ptr player = world->getPlayerPtr();
mRendering.updatePlayerPtr(player);
// adjust player
playerCellChange (mCurrentCell, position, adjustPlayerPos);
if (adjustPlayerPos) {
world->moveObject(player, pos.pos[0], pos.pos[1], pos.pos[2]);
// Sky system
MWBase::Environment::get().getWorld()->adjustSky();
float x = Ogre::Radian(pos.rot[0]).valueDegrees();
float y = Ogre::Radian(pos.rot[1]).valueDegrees();
float z = Ogre::Radian(pos.rot[2]).valueDegrees();
world->rotateObject(player, x, y, z);
mCellChanged = true;
player.getClass().adjustPosition(player, true);
}
MWBase::MechanicsManager *mechMgr =
MWBase::Environment::get().getMechanicsManager();
mechMgr->updateCell(old, player);
mechMgr->watchActor(player);
MWBase::Environment::get().getWorld()->adjustSky();
}
//We need the ogre renderer and a scene node.
@ -427,33 +460,39 @@ namespace MWWorld
// Load cell.
std::cout << "cellName: " << cell->getCell()->mName << std::endl;
//Loading Interior loading text
loadCell (cell, loadingListener);
mCurrentCell = cell;
changePlayerCell(cell, position, true);
// adjust fog
mRendering.configureFog(*mCurrentCell);
// adjust player
playerCellChange (mCurrentCell, position);
// Sky system
MWBase::Environment::get().getWorld()->adjustSky();
mCellChanged = true;
MWBase::Environment::get().getWindowManager()->fadeScreenIn(0.5);
MWBase::Environment::get().getWindowManager()->changeCell(mCurrentCell);
// Delay the map update until scripts have been given a chance to run.
// If we don't do this, objects that should be disabled will still appear on the map.
mNeedMapUpdate = true;
}
void Scene::changeToExteriorCell (const ESM::Position& position)
void Scene::changeToExteriorCell (const ESM::Position& position, bool adjustPlayerPos)
{
int x = 0;
int y = 0;
MWBase::Environment::get().getWorld()->positionToIndex (position.pos[0], position.pos[1], x, y);
changeCell (x, y, position, true);
changeCellGrid(x, y);
CellStore* current = MWBase::Environment::get().getWorld()->getExterior(x, y);
changePlayerCell(current, position, adjustPlayerPos);
mRendering.updateTerrain();
}
CellStore* Scene::getCurrentCell ()

@ -60,11 +60,13 @@ namespace MWWorld
bool mNeedMapUpdate;
void playerCellChange (CellStore *cell, const ESM::Position& position,
bool adjustPlayerPos = true);
void insertCell (CellStore &cell, bool rescale, Loading::Listener* loadingListener);
// Load and unload cells as necessary to create a cell grid with "X" and "Y" in the center
void changeCellGrid (int X, int Y);
void getGridCenter(int& cellX, int& cellY);
public:
Scene (MWRender::RenderingManager& rendering, PhysicsSystem *physics);
@ -75,19 +77,21 @@ namespace MWWorld
void loadCell (CellStore *cell, Loading::Listener* loadingListener);
void changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos);
void playerMoved (const Ogre::Vector3& pos);
void changePlayerCell (CellStore* newCell, const ESM::Position& position, bool adjustPlayerPos);
CellStore* getCurrentCell ();
CellStore *getCurrentCell();
const CellStoreCollection& getActiveCells () const;
bool hasCellChanged() const;
///< Has the player moved to a different cell, since the last frame?
///< Has the set of active cells changed, since the last frame?
void changeToInteriorCell (const std::string& cellName, const ESM::Position& position);
///< Move to interior cell.
void changeToExteriorCell (const ESM::Position& position);
void changeToExteriorCell (const ESM::Position& position, bool adjustPlayerPos);
///< Move to exterior cell.
void changeToVoid();

@ -498,7 +498,8 @@ void WeatherManager::update(float duration)
else if (sound == 1) soundName = &mThunderSoundID1;
else if (sound == 2) soundName = &mThunderSoundID2;
else if (sound == 3) soundName = &mThunderSoundID3;
MWBase::Environment::get().getSoundManager()->playSound(*soundName, 1.0, 1.0);
if (soundName)
MWBase::Environment::get().getSoundManager()->playSound(*soundName, 1.0, 1.0);
mThunderSoundDelay = 1000;
}

@ -241,7 +241,7 @@ namespace MWWorld
pos.rot[0] = 0;
pos.rot[1] = 0;
pos.rot[2] = 0;
mWorldScene->changeToExteriorCell(pos);
mWorldScene->changeToExteriorCell(pos, true);
}
}
@ -920,7 +920,7 @@ namespace MWWorld
mRendering->notifyWorldSpaceChanged();
}
removeContainerScripts(getPlayerPtr());
mWorldScene->changeToExteriorCell(position);
mWorldScene->changeToExteriorCell(position, true);
addContainerScripts(getPlayerPtr(), getPlayerPtr().getCell());
}
@ -1045,7 +1045,7 @@ namespace MWWorld
CellStore *currCell = ptr.isInCell() ? ptr.getCell() : NULL; // currCell == NULL should only happen for player, during initial startup
bool isPlayer = ptr == mPlayer->getPlayer();
bool haveToMove = isPlayer || mWorldScene->isCellActive(*currCell);
bool haveToMove = isPlayer || (currCell && mWorldScene->isCellActive(*currCell));
if (currCell != newCell)
{
@ -1057,9 +1057,10 @@ namespace MWWorld
changeToInteriorCell(Misc::StringUtils::lowerCase(newCell->getCell()->mName), pos);
else
{
int cellX = newCell->getCell()->getGridX();
int cellY = newCell->getCell()->getGridY();
mWorldScene->changeCell(cellX, cellY, pos, false);
if (mWorldScene->isCellActive(*newCell))
mWorldScene->changePlayerCell(newCell, pos, false);
else
mWorldScene->changeToExteriorCell(pos, false);
}
addContainerScripts (getPlayerPtr(), newCell);
}
@ -1120,6 +1121,10 @@ namespace MWWorld
mRendering->moveObject(ptr, vec);
mPhysics->moveObject (ptr);
}
if (isPlayer)
{
mWorldScene->playerMoved (vec);
}
}
bool World::moveObjectImp(const Ptr& ptr, float x, float y, float z)
@ -1309,6 +1314,8 @@ namespace MWWorld
void World::doPhysics(float duration)
{
mPhysics->stepSimulation(duration);
processDoors(duration);
mProjectileManager->update(duration);
@ -1327,8 +1334,6 @@ namespace MWWorld
}
if(player != results.end())
moveObjectImp(player->first, player->second.x, player->second.y, player->second.z);
mPhysics->stepSimulation(duration);
}
bool World::castRay (float x1, float y1, float z1, float x2, float y2, float z2)
@ -1565,7 +1570,7 @@ namespace MWWorld
bool World::isCellExterior() const
{
CellStore *currentCell = mWorldScene->getCurrentCell();
const CellStore *currentCell = mWorldScene->getCurrentCell();
if (currentCell)
{
return currentCell->getCell()->isExterior();
@ -1575,7 +1580,7 @@ namespace MWWorld
bool World::isCellQuasiExterior() const
{
CellStore *currentCell = mWorldScene->getCurrentCell();
const CellStore *currentCell = mWorldScene->getCurrentCell();
if (currentCell)
{
if (!(currentCell->getCell()->mData.mFlags & ESM::Cell::QuasiEx))
@ -1663,6 +1668,11 @@ namespace MWWorld
return mRendering->toggleWater();
}
bool World::toggleWorld()
{
return mRendering->toggleWorld();
}
void World::PCDropped (const Ptr& item)
{
std::string script = item.getClass().getScript(item);

@ -180,6 +180,7 @@ namespace MWWorld
virtual void setWaterHeight(const float height);
virtual bool toggleWater();
virtual bool toggleWorld();
virtual void adjustSky();
@ -197,7 +198,7 @@ namespace MWWorld
virtual LocalScripts& getLocalScripts();
virtual bool hasCellChanged() const;
///< Has the player moved to a different cell, since the last frame?
///< Has the set of active cells changed, since the last frame?
virtual bool isCellExterior() const;

@ -256,6 +256,8 @@ namespace Compiler
extensions.registerInstruction ("fadeto", "ff", opcodeFadeTo);
extensions.registerInstruction ("togglewater", "", opcodeToggleWater);
extensions.registerInstruction ("twa", "", opcodeToggleWater);
extensions.registerInstruction ("toggleworld", "", opcodeToggleWorld);
extensions.registerInstruction ("tw", "", opcodeToggleWorld);
extensions.registerInstruction ("togglepathgrid", "", opcodeTogglePathgrid);
extensions.registerInstruction ("tpg", "", opcodeTogglePathgrid);
extensions.registerInstruction ("dontsaveobject", "", opcodeDontSaveObject);

@ -212,6 +212,7 @@ namespace Compiler
const int opcodeFadeOut = 0x200013d;
const int opcodeFadeTo = 0x200013e;
const int opcodeToggleWater = 0x2000144;
const int opcodeToggleWorld = 0x20002f5;
const int opcodeTogglePathgrid = 0x2000146;
const int opcodeDontSaveObject = 0x2000153;
const int opcodeToggleVanityMode = 0x2000174;

@ -20,4 +20,12 @@ void SpellList::save(ESMWriter &esm) const
}
}
bool SpellList::exists(const std::string &spell) const
{
for (std::vector<std::string>::const_iterator it = mList.begin(); it != mList.end(); ++it)
if (Misc::StringUtils::ciEqual(*it, spell))
return true;
return false;
}
}

@ -16,6 +16,9 @@ namespace ESM
{
std::vector<std::string> mList;
/// Is this spell ID in mList?
bool exists(const std::string& spell) const;
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
};

@ -147,8 +147,8 @@ namespace ESMTerrain
Ogre::Vector3 normal;
Ogre::ColourValue color;
float vertY;
float vertX;
float vertY = 0;
float vertX = 0;
float vertY_ = 0; // of current cell corner
for (int cellY = startY; cellY < startY + std::ceil(size); ++cellY)

@ -73,38 +73,6 @@ namespace
return NULL;
}
// Ogre::AxisAlignedBox::distance is broken in 1.8.
Ogre::Real distance(const Ogre::AxisAlignedBox& box, const Ogre::Vector3& v)
{
if (box.contains(v))
return 0;
else
{
Ogre::Vector3 maxDist(0,0,0);
const Ogre::Vector3& minimum = box.getMinimum();
const Ogre::Vector3& maximum = box.getMaximum();
if (v.x < minimum.x)
maxDist.x = minimum.x - v.x;
else if (v.x > maximum.x)
maxDist.x = v.x - maximum.x;
if (v.y < minimum.y)
maxDist.y = minimum.y - v.y;
else if (v.y > maximum.y)
maxDist.y = v.y - maximum.y;
if (v.z < minimum.z)
maxDist.z = minimum.z - v.z;
else if (v.z > maximum.z)
maxDist.z = v.z - maximum.z;
return maxDist.length();
}
}
// Create a 2D quad
void makeQuad(Ogre::SceneManager* sceneMgr, float left, float top, float right, float bottom, Ogre::MaterialPtr material)
{
@ -270,7 +238,7 @@ bool QuadTreeNode::update(const Ogre::Vector3 &cameraPos)
if (mBounds.isNull())
return true;
float dist = distance(mWorldBounds, cameraPos);
float dist = mWorldBounds.distance(cameraPos);
// Make sure our scene node is attached
if (!mSceneNode->isInSceneGraph())

@ -197,8 +197,17 @@ namespace Gui
MyGUI::IntCoord widgetCoord;
widgetCoord.left = curX;
widgetCoord.top = mPadding + (getSize().height-mPadding*2 - height) / 2;
int width = sizes[i].second ? sizes[i].first.width + (getSize().width-mPadding*2 - total_width)/h_stretched_count
: sizes[i].first.width;
int width = 0;
if (sizes[i].second)
{
if (h_stretched_count == 0)
throw std::logic_error("unexpected");
width = sizes[i].first.width + (getSize().width-mPadding*2 - total_width)/h_stretched_count;
}
else
width = sizes[i].first.width;
widgetCoord.width = width;
widgetCoord.height = height;
w->setCoord(widgetCoord);
@ -334,8 +343,17 @@ namespace Gui
MyGUI::IntCoord widgetCoord;
widgetCoord.top = curY;
widgetCoord.left = mPadding + (getSize().width-mPadding*2 - width) / 2;
int height = sizes[i].second ? sizes[i].first.height + (getSize().height-mPadding*2 - total_height)/v_stretched_count
: sizes[i].first.height;
int height = 0;
if (sizes[i].second)
{
if (v_stretched_count == 0)
throw std::logic_error("unexpected");
height = sizes[i].first.height + (getSize().height-mPadding*2 - total_height)/v_stretched_count;
}
else
height = sizes[i].first.height;
widgetCoord.height = height;
widgetCoord.width = width;
w->setCoord(widgetCoord);

@ -119,9 +119,11 @@ namespace ICS
//bool sliderMoved(const OIS::JoyStickEvent &evt, int index);
void addKeyBinding(Control* control, SDL_Scancode key, Control::ControlChangingDirection direction);
bool isKeyBound(SDL_Scancode key) const;
void addMouseAxisBinding(Control* control, NamedAxis axis, Control::ControlChangingDirection direction);
void addMouseButtonBinding(Control* control, unsigned int button, Control::ControlChangingDirection direction);
void addJoystickAxisBinding(Control* control, int deviceId, int axis, Control::ControlChangingDirection direction);
bool isMouseButtonBound(unsigned int button) const;
void addJoystickAxisBinding(Control* control, int deviceId, int axis, Control::ControlChangingDirection direction);
void addJoystickButtonBinding(Control* control, int deviceId, unsigned int button, Control::ControlChangingDirection direction);
void addJoystickPOVBinding(Control* control, int deviceId, int index, POVAxis axis, Control::ControlChangingDirection direction);
void addJoystickSliderBinding(Control* control, int deviceId, int index, Control::ControlChangingDirection direction);

@ -61,6 +61,11 @@ namespace ICS
mControlsKeyBinderMap[ key ] = controlKeyBinderItem;
}
bool InputControlSystem::isKeyBound(SDL_Scancode key) const
{
return mControlsKeyBinderMap.find(key) != mControlsKeyBinderMap.end();
}
void InputControlSystem::removeKeyBinding(SDL_Scancode key)
{
ControlsKeyBinderMapType::iterator it = mControlsKeyBinderMap.find(key);

@ -139,6 +139,11 @@ namespace ICS
mControlsMouseButtonBinderMap[ button ] = controlMouseButtonBinderItem;
}
bool InputControlSystem::isMouseButtonBound(unsigned int button) const
{
return mControlsMouseButtonBinderMap.find(button) != mControlsMouseButtonBinderMap.end();
}
// get bindings
InputControlSystem::NamedAxis InputControlSystem::getMouseAxisBinding(Control* control, ICS::Control::ControlChangingDirection direction)
{

@ -12,13 +12,13 @@
{
float4x4 viewFixed = view;
#if !SH_GLSL
viewFixed[0][3] = 0;
viewFixed[1][3] = 0;
viewFixed[2][3] = 0;
viewFixed[0][3] = 0.0;
viewFixed[1][3] = 0.0;
viewFixed[2][3] = 0.0;
#else
viewFixed[3][0] = 0;
viewFixed[3][1] = 0;
viewFixed[3][2] = 0;
viewFixed[3][0] = 0.0;
viewFixed[3][1] = 0.0;
viewFixed[3][2] = 0.0;
#endif
shOutputPosition = shMatrixMult(projection, shMatrixMult(viewFixed, shInputPosition));
alphaFade = shInputPosition.z < 150.0 ? 0.0 : 1.0;

@ -14,13 +14,13 @@
float4x4 worldviewFixed = worldview;
#if !SH_GLSL
worldviewFixed[0][3] = 0;
worldviewFixed[1][3] = 0;
worldviewFixed[2][3] = 0;
worldviewFixed[0][3] = 0.0;
worldviewFixed[1][3] = 0.0;
worldviewFixed[2][3] = 0.0;
#else
worldviewFixed[3][0] = 0;
worldviewFixed[3][1] = 0;
worldviewFixed[3][2] = 0;
worldviewFixed[3][0] = 0.0;
worldviewFixed[3][1] = 0.0;
worldviewFixed[3][2] = 0.0;
#endif
shOutputPosition = shMatrixMult(proj, shMatrixMult(worldviewFixed, shInputPosition));

@ -13,13 +13,13 @@ shUniform(float4x4, projection) @shAutoConstant(projection, projection_matrix)
{
float4x4 viewFixed = view;
#if !SH_GLSL
viewFixed[0][3] = 0;
viewFixed[1][3] = 0;
viewFixed[2][3] = 0;
viewFixed[0][3] = 0.0;
viewFixed[1][3] = 0.0;
viewFixed[2][3] = 0.0;
#else
viewFixed[3][0] = 0;
viewFixed[3][1] = 0;
viewFixed[3][2] = 0;
viewFixed[3][0] = 0.0;
viewFixed[3][1] = 0.0;
viewFixed[3][2] = 0.0;
#endif
shOutputPosition = shMatrixMult(projection, shMatrixMult(viewFixed, shMatrixMult(world, shInputPosition)));
UV = uv0;

@ -13,13 +13,13 @@ shUniform(float4x4, projection) @shAutoConstant(projection, projection_matrix)
{
float4x4 viewFixed = view;
#if !SH_GLSL
viewFixed[0][3] = 0;
viewFixed[1][3] = 0;
viewFixed[2][3] = 0;
viewFixed[0][3] = 0.0;
viewFixed[1][3] = 0.0;
viewFixed[2][3] = 0.0;
#else
viewFixed[3][0] = 0;
viewFixed[3][1] = 0;
viewFixed[3][2] = 0;
viewFixed[3][0] = 0.0;
viewFixed[3][1] = 0.0;
viewFixed[3][2] = 0.0;
#endif
shOutputPosition = shMatrixMult(projection, shMatrixMult(viewFixed, shMatrixMult(world, shInputPosition)));
UV = uv0;

@ -40,7 +40,7 @@
SH_START_PROGRAM
{
shOutputColour(0).xyz = shSample(animatedTexture, UV * 15).xyz * float3(1.0, 1.0, 1.0);
shOutputColour(0).xyz = shSample(animatedTexture, UV * float2(15.0, 15.0)).xyz * float3(1.0, 1.0, 1.0);
shOutputColour(0).w = 0.7;
#if FOG

@ -28,7 +28,7 @@ set(MYGUI_FILES
openmw_container_window.layout
openmw_count_window.layout
openmw_dialogue_window.layout
openmw_dialogue_window_skin.xml
openmw_dialogue_window.skin.xml
openmw_edit.skin.xml
openmw_font.xml
openmw_hud_box.skin.xml
@ -38,19 +38,19 @@ set(MYGUI_FILES
openmw_interactive_messagebox.layout
openmw_inventory_window.layout
openmw_journal.layout
openmw_journal_skin.xml
openmw_journal.skin.xml
openmw_layers.xml
openmw_list.skin.xml
openmw_mainmenu.layout
openmw_mainmenu_skin.xml
openmw_mainmenu.skin.xml
openmw_map_window.layout
openmw_map_window_skin.xml
openmw_map_window.skin.xml
openmw_messagebox.layout
openmw_pointer.xml
openmw_progress.skin.xml
openmw_resources.xml
openmw_scroll.layout
openmw_scroll_skin.xml
openmw_scroll.skin.xml
openmw_settings_window.layout
openmw_settings.xml
openmw_spell_window.layout
@ -83,6 +83,8 @@ set(MYGUI_FILES
openmw_recharge_dialog.layout
openmw_screen_fader.layout
openmw_edit_note.layout
openmw_debug_window.layout
openmw_debug_window.skin.xml
DejaVuLGCSansMono.ttf
../launcher/images/openmw.png
OpenMWResourcePlugin.xml

@ -15,13 +15,14 @@
<List file="openmw_progress.skin.xml" />
<List file="openmw_hud_energybar.skin.xml" />
<List file="openmw_hud_box.skin.xml" />
<List file="openmw_mainmenu_skin.xml" />
<List file="openmw_mainmenu.skin.xml" />
<List file="openmw_console.skin.xml" />
<List file="openmw_journal_skin.xml" />
<List file="openmw_map_window_skin.xml" />
<List file="openmw_dialogue_window_skin.xml" />
<List file="openmw_scroll_skin.xml" />
<List file="openmw_journal.skin.xml" />
<List file="openmw_map_window.skin.xml" />
<List file="openmw_dialogue_window.skin.xml" />
<List file="openmw_scroll.skin.xml" />
<List file="openmw_settings.xml" />
<List file="openmw_debug_window.skin.xml" />
</MyGUI>
</MyGUI>

@ -73,6 +73,36 @@
<Child type="Widget" skin="BTN_BottomLeft" offset="0 20 4 4" align="Bottom Left"/>
<Child type="Widget" skin="BTN_BottomRight" offset="132 20 4 4" align="Bottom Right"/>
<BasisSkin type="SimpleText" offset="4 4 128 16" align="Stretch">
<State name="disabled" colour="#{fontcolour=disabled}" shift="0"/>
<State name="normal" colour="#{fontcolour=normal}" shift="0"/>
<State name="highlighted" colour="#{fontcolour=normal_over}" shift="0"/>
<State name="pushed" colour="#{fontcolour=normal_pressed}" shift="0"/>
<State name="disabled_checked" colour="#{fontcolour=disabled}" shift="0"/>
<State name="normal_checked" colour="#{fontcolour=active}" shift="0"/>
<State name="highlighted_checked" colour="#{fontcolour=active_over}" shift="0"/>
<State name="pushed_checked" colour="#{fontcolour=active_pressed}" shift="0"/>
</BasisSkin>
</Resource>
<!-- Button widget, 4 px padding on the right -->
<Resource type="ResourceSkin" name="MW_Button_RightPadding" size="140 24" version="3.2.1">
<Property key="FontName" value="Default"/>
<Property key="TextAlign" value="Center"/>
<!-- padding -->
<Child type="Widget" skin="" offset="136 0 4 24" align="Right VStretch"/>
<Child type="Widget" skin="BTN_Left" offset="0 4 4 16" align="VStretch Left"/>
<Child type="Widget" skin="BTN_Right" offset="132 4 4 16" align="VStretch Right"/>
<Child type="Widget" skin="BTN_Top" offset="4 0 128 4" align="HStretch Top"/>
<Child type="Widget" skin="BTN_Bottom" offset="4 20 128 4" align="HStretch Bottom"/>
<Child type="Widget" skin="BTN_TopLeft" offset="0 0 4 4" align="Top Left"/>
<Child type="Widget" skin="BTN_TopRight" offset="132 0 4 4" align="Top Right"/>
<Child type="Widget" skin="BTN_BottomLeft" offset="0 20 4 4" align="Bottom Left"/>
<Child type="Widget" skin="BTN_BottomRight" offset="132 20 4 4" align="Bottom Right"/>
<Child type="Widget" skin="BTN_BottomRight" offset="132 20 4 4" align="Bottom Right"/>
<BasisSkin type="SimpleText" offset="4 4 128 16" align="Stretch">
<State name="disabled" colour="#{fontcolour=disabled}" shift="0"/>
<State name="normal" colour="#{fontcolour=normal}" shift="0"/>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save