mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-06 17:45:33 +00:00
Add OpenMW commits up to 29 Aug 2020
# Conflicts: # CMakeLists.txt # apps/openmw/mwmechanics/character.cpp
This commit is contained in:
commit
80af0ce6a7
59 changed files with 1102 additions and 776 deletions
|
@ -57,9 +57,10 @@ variables: &cs-targets
|
||||||
- windows
|
- windows
|
||||||
before_script:
|
before_script:
|
||||||
- Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1"
|
- Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1"
|
||||||
|
- choco source add -n=openmw-proxy -s="https://repo.openmw.org/repository/Chocolately/" --priority=1
|
||||||
- choco install git --force --params "/GitAndUnixToolsOnPath" -y
|
- choco install git --force --params "/GitAndUnixToolsOnPath" -y
|
||||||
- choco install 7zip -y
|
- choco install 7zip -y
|
||||||
- choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' -y
|
- choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' --version=3.18.0 -y
|
||||||
- choco install vswhere -y
|
- choco install vswhere -y
|
||||||
- choco install ninja -y
|
- choco install ninja -y
|
||||||
- choco install python -y
|
- choco install python -y
|
||||||
|
@ -146,6 +147,7 @@ Windows_Ninja_CS_RelWithDebInfo:
|
||||||
- windows
|
- windows
|
||||||
before_script:
|
before_script:
|
||||||
- Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1"
|
- Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1"
|
||||||
|
- choco source add -n=openmw-proxy -s="https://repo.openmw.org/repository/Chocolately/" --priority=1
|
||||||
- choco install git --force --params "/GitAndUnixToolsOnPath" -y
|
- choco install git --force --params "/GitAndUnixToolsOnPath" -y
|
||||||
- choco install 7zip -y
|
- choco install 7zip -y
|
||||||
- choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' -y
|
- choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' -y
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
Bug #5502: Dead zone for analogue stick movement is too small
|
Bug #5502: Dead zone for analogue stick movement is too small
|
||||||
Bug #5507: Sound volume is not clamped on ingame settings update
|
Bug #5507: Sound volume is not clamped on ingame settings update
|
||||||
Bug #5531: Actors flee using current rotation by axis x
|
Bug #5531: Actors flee using current rotation by axis x
|
||||||
|
Bug #5539: Window resize breaks when going from a lower resolution to full screen resolution
|
||||||
Bug #5548: Certain exhausted topics can be highlighted again even though there's no new dialogue
|
Bug #5548: Certain exhausted topics can be highlighted again even though there's no new dialogue
|
||||||
Feature #390: 3rd person look "over the shoulder"
|
Feature #390: 3rd person look "over the shoulder"
|
||||||
Feature #2386: Distant Statics in the form of Object Paging
|
Feature #2386: Distant Statics in the form of Object Paging
|
||||||
|
|
|
@ -1,6 +1,16 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
set -euo pipefail
|
oldSettings=$-
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
function restoreOldSettings {
|
||||||
|
if [[ $oldSettings != *e* ]]; then
|
||||||
|
set +e
|
||||||
|
fi
|
||||||
|
if [[ $oldSettings != *u* ]]; then
|
||||||
|
set +u
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||||
echo "Error: Script not sourced."
|
echo "Error: Script not sourced."
|
||||||
|
@ -8,6 +18,7 @@ if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||||
echo "source ./activate_msvc.sh"
|
echo "source ./activate_msvc.sh"
|
||||||
echo "or"
|
echo "or"
|
||||||
echo ". ./activate_msvc.sh"
|
echo ". ./activate_msvc.sh"
|
||||||
|
restoreOldSettings
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -78,7 +89,10 @@ command -v mt >/dev/null 2>&1 || { echo "Error: mt (MS Windows Manifest Tool) mi
|
||||||
|
|
||||||
if [ $MISSINGTOOLS -ne 0 ]; then
|
if [ $MISSINGTOOLS -ne 0 ]; then
|
||||||
echo "Some build tools were unavailable after activating MSVC in the shell. It's likely that your Visual Studio $MSVC_DISPLAY_YEAR installation needs repairing."
|
echo "Some build tools were unavailable after activating MSVC in the shell. It's likely that your Visual Studio $MSVC_DISPLAY_YEAR installation needs repairing."
|
||||||
|
restoreOldSettings
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
IFS="$originalIFS"
|
IFS="$originalIFS"
|
||||||
|
|
||||||
|
restoreOldSettings
|
|
@ -1,3 +1,6 @@
|
||||||
|
project(OpenMW)
|
||||||
|
cmake_minimum_required(VERSION 3.1.0)
|
||||||
|
|
||||||
# Apps and tools
|
# Apps and tools
|
||||||
option(BUILD_OPENMW "Build OpenMW" ON)
|
option(BUILD_OPENMW "Build OpenMW" ON)
|
||||||
option(BUILD_LAUNCHER "Build Launcher" ON)
|
option(BUILD_LAUNCHER "Build Launcher" ON)
|
||||||
|
@ -16,17 +19,14 @@ option(BUILD_OPENMW_MP "Build OpenMW-MP" ON)
|
||||||
option(BUILD_BROWSER "Build tes3mp Server Browser" ON)
|
option(BUILD_BROWSER "Build tes3mp Server Browser" ON)
|
||||||
option(BUILD_MASTER "Build tes3mp Master Server" OFF)
|
option(BUILD_MASTER "Build tes3mp Master Server" OFF)
|
||||||
|
|
||||||
|
set(OpenGL_GL_PREFERENCE LEGACY) # Use LEGACY as we use GL2; GLNVD is for GL3 and up.
|
||||||
|
|
||||||
if (NOT BUILD_LAUNCHER AND NOT BUILD_BROWSER AND NOT BUILD_OPENCS AND NOT BUILD_WIZARD)
|
if (NOT BUILD_LAUNCHER AND NOT BUILD_BROWSER AND NOT BUILD_OPENCS AND NOT BUILD_WIZARD)
|
||||||
set(USE_QT FALSE)
|
set(USE_QT FALSE)
|
||||||
else()
|
else()
|
||||||
set(USE_QT TRUE)
|
set(USE_QT TRUE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# set the minimum required version across the board
|
|
||||||
cmake_minimum_required(VERSION 3.1.0)
|
|
||||||
|
|
||||||
project(OpenMW)
|
|
||||||
|
|
||||||
# If the user doesn't supply a CMAKE_BUILD_TYPE via command line, choose one for them.
|
# If the user doesn't supply a CMAKE_BUILD_TYPE via command line, choose one for them.
|
||||||
IF(NOT CMAKE_BUILD_TYPE)
|
IF(NOT CMAKE_BUILD_TYPE)
|
||||||
SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING
|
SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING
|
||||||
|
@ -61,7 +61,7 @@ set(OPENMW_VERSION_COMMITDATE "")
|
||||||
|
|
||||||
set(OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")
|
set(OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")
|
||||||
|
|
||||||
set(OPENMW_DOC_BASEURL "https://openmw.readthedocs.io/en/master/")
|
set(OPENMW_DOC_BASEURL "https://openmw.readthedocs.io/en/stable/")
|
||||||
|
|
||||||
set(GIT_CHECKOUT FALSE)
|
set(GIT_CHECKOUT FALSE)
|
||||||
if(EXISTS ${PROJECT_SOURCE_DIR}/.git)
|
if(EXISTS ${PROJECT_SOURCE_DIR}/.git)
|
||||||
|
|
|
@ -10,37 +10,6 @@
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
|
||||||
class HorizontalTextWestTabStyle : public QProxyStyle
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QSize sizeFromContents(ContentsType type, const QStyleOption* option, const QSize& size, const QWidget* widget) const
|
|
||||||
{
|
|
||||||
QSize s = QProxyStyle::sizeFromContents(type, option, size, widget);
|
|
||||||
if (type == QStyle::CT_TabBarTab)
|
|
||||||
{
|
|
||||||
s.transpose();
|
|
||||||
s.setHeight(s.height() + 20);
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
|
|
||||||
{
|
|
||||||
if (element == CE_TabBarTabLabel)
|
|
||||||
{
|
|
||||||
if (const QStyleOptionTab* tab = qstyleoption_cast<const QStyleOptionTab*>(option))
|
|
||||||
{
|
|
||||||
QStyleOptionTab opt(*tab);
|
|
||||||
opt.shape = QTabBar::RoundedNorth;
|
|
||||||
QProxyStyle::drawControl(element, &opt, painter, widget);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
QProxyStyle::drawControl(element, option, painter, widget);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Launcher::AdvancedPage::AdvancedPage(Files::ConfigurationManager &cfg,
|
Launcher::AdvancedPage::AdvancedPage(Files::ConfigurationManager &cfg,
|
||||||
Config::GameSettings &gameSettings,
|
Config::GameSettings &gameSettings,
|
||||||
Settings::Manager &engineSettings, QWidget *parent)
|
Settings::Manager &engineSettings, QWidget *parent)
|
||||||
|
@ -53,7 +22,6 @@ Launcher::AdvancedPage::AdvancedPage(Files::ConfigurationManager &cfg,
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
|
|
||||||
loadSettings();
|
loadSettings();
|
||||||
AdvancedTabWidget->tabBar()->setStyle(new HorizontalTextWestTabStyle);
|
|
||||||
mCellNameCompleter.setModel(&mCellNameCompleterModel);
|
mCellNameCompleter.setModel(&mCellNameCompleterModel);
|
||||||
startDefaultCharacterAtField->setCompleter(&mCellNameCompleter);
|
startDefaultCharacterAtField->setCompleter(&mCellNameCompleter);
|
||||||
}
|
}
|
||||||
|
@ -119,15 +87,22 @@ bool Launcher::AdvancedPage::loadSettings()
|
||||||
loadSettingBool(requireAppropriateAmmunitionCheckBox, "only appropriate ammunition bypasses resistance", "Game");
|
loadSettingBool(requireAppropriateAmmunitionCheckBox, "only appropriate ammunition bypasses resistance", "Game");
|
||||||
loadSettingBool(uncappedDamageFatigueCheckBox, "uncapped damage fatigue", "Game");
|
loadSettingBool(uncappedDamageFatigueCheckBox, "uncapped damage fatigue", "Game");
|
||||||
loadSettingBool(normaliseRaceSpeedCheckBox, "normalise race speed", "Game");
|
loadSettingBool(normaliseRaceSpeedCheckBox, "normalise race speed", "Game");
|
||||||
|
loadSettingBool(swimUpwardCorrectionCheckBox, "swim upward correction", "Game");
|
||||||
int unarmedFactorsStrengthIndex = mEngineSettings.getInt("strength influences hand to hand", "Game");
|
int unarmedFactorsStrengthIndex = mEngineSettings.getInt("strength influences hand to hand", "Game");
|
||||||
if (unarmedFactorsStrengthIndex >= 0 && unarmedFactorsStrengthIndex <= 2)
|
if (unarmedFactorsStrengthIndex >= 0 && unarmedFactorsStrengthIndex <= 2)
|
||||||
unarmedFactorsStrengthComboBox->setCurrentIndex(unarmedFactorsStrengthIndex);
|
unarmedFactorsStrengthComboBox->setCurrentIndex(unarmedFactorsStrengthIndex);
|
||||||
loadSettingBool(stealingFromKnockedOutCheckBox, "always allow stealing from knocked out actors", "Game");
|
loadSettingBool(stealingFromKnockedOutCheckBox, "always allow stealing from knocked out actors", "Game");
|
||||||
|
loadSettingBool(enableNavigatorCheckBox, "enable", "Navigator");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Visuals
|
// Visuals
|
||||||
{
|
{
|
||||||
|
loadSettingBool(autoUseObjectNormalMapsCheckBox, "auto use object normal maps", "Shaders");
|
||||||
|
loadSettingBool(autoUseObjectSpecularMapsCheckBox, "auto use object specular maps", "Shaders");
|
||||||
|
loadSettingBool(autoUseTerrainNormalMapsCheckBox, "auto use terrain normal maps", "Shaders");
|
||||||
|
loadSettingBool(autoUseTerrainSpecularMapsCheckBox, "auto use terrain specular maps", "Shaders");
|
||||||
loadSettingBool(bumpMapLocalLightingCheckBox, "apply lighting to environment maps", "Shaders");
|
loadSettingBool(bumpMapLocalLightingCheckBox, "apply lighting to environment maps", "Shaders");
|
||||||
|
loadSettingBool(radialFogCheckBox, "radial fog", "Shaders");
|
||||||
loadSettingBool(magicItemAnimationsCheckBox, "use magic item animations", "Game");
|
loadSettingBool(magicItemAnimationsCheckBox, "use magic item animations", "Game");
|
||||||
connect(animSourcesCheckBox, SIGNAL(toggled(bool)), this, SLOT(slotAnimSourcesToggled(bool)));
|
connect(animSourcesCheckBox, SIGNAL(toggled(bool)), this, SLOT(slotAnimSourcesToggled(bool)));
|
||||||
loadSettingBool(animSourcesCheckBox, "use additional anim sources", "Game");
|
loadSettingBool(animSourcesCheckBox, "use additional anim sources", "Game");
|
||||||
|
@ -136,7 +111,6 @@ bool Launcher::AdvancedPage::loadSettings()
|
||||||
loadSettingBool(weaponSheathingCheckBox, "weapon sheathing", "Game");
|
loadSettingBool(weaponSheathingCheckBox, "weapon sheathing", "Game");
|
||||||
loadSettingBool(shieldSheathingCheckBox, "shield sheathing", "Game");
|
loadSettingBool(shieldSheathingCheckBox, "shield sheathing", "Game");
|
||||||
}
|
}
|
||||||
loadSettingBool(viewOverShoulderCheckBox, "view over shoulder", "Camera");
|
|
||||||
loadSettingBool(turnToMovementDirectionCheckBox, "turn to movement direction", "Game");
|
loadSettingBool(turnToMovementDirectionCheckBox, "turn to movement direction", "Game");
|
||||||
|
|
||||||
const bool distantTerrain = mEngineSettings.getBool("distant terrain", "Terrain");
|
const bool distantTerrain = mEngineSettings.getBool("distant terrain", "Terrain");
|
||||||
|
@ -149,6 +123,18 @@ bool Launcher::AdvancedPage::loadSettings()
|
||||||
viewingDistanceComboBox->setValue(convertToCells(mEngineSettings.getInt("viewing distance", "Camera")));
|
viewingDistanceComboBox->setValue(convertToCells(mEngineSettings.getInt("viewing distance", "Camera")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Camera
|
||||||
|
{
|
||||||
|
loadSettingBool(viewOverShoulderCheckBox, "view over shoulder", "Camera");
|
||||||
|
connect(viewOverShoulderCheckBox, SIGNAL(toggled(bool)), this, SLOT(slotViewOverShoulderToggled(bool)));
|
||||||
|
viewOverShoulderVerticalLayout->setEnabled(viewOverShoulderCheckBox->checkState());
|
||||||
|
loadSettingBool(autoSwitchShoulderCheckBox, "auto switch shoulder", "Camera");
|
||||||
|
loadSettingBool(previewIfStandStillCheckBox, "preview if stand still", "Camera");
|
||||||
|
loadSettingBool(deferredPreviewRotationCheckBox, "deferred preview rotation", "Camera");
|
||||||
|
defaultShoulderComboBox->setCurrentIndex(
|
||||||
|
mEngineSettings.getVector2("view over shoulder offset", "Camera").x() >= 0 ? 0 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
// Interface Changes
|
// Interface Changes
|
||||||
{
|
{
|
||||||
loadSettingBool(showEffectDurationCheckBox, "show effect duration", "Game");
|
loadSettingBool(showEffectDurationCheckBox, "show effect duration", "Game");
|
||||||
|
@ -213,20 +199,26 @@ void Launcher::AdvancedPage::saveSettings()
|
||||||
saveSettingBool(requireAppropriateAmmunitionCheckBox, "only appropriate ammunition bypasses resistance", "Game");
|
saveSettingBool(requireAppropriateAmmunitionCheckBox, "only appropriate ammunition bypasses resistance", "Game");
|
||||||
saveSettingBool(uncappedDamageFatigueCheckBox, "uncapped damage fatigue", "Game");
|
saveSettingBool(uncappedDamageFatigueCheckBox, "uncapped damage fatigue", "Game");
|
||||||
saveSettingBool(normaliseRaceSpeedCheckBox, "normalise race speed", "Game");
|
saveSettingBool(normaliseRaceSpeedCheckBox, "normalise race speed", "Game");
|
||||||
|
saveSettingBool(swimUpwardCorrectionCheckBox, "swim upward correction", "Game");
|
||||||
int unarmedFactorsStrengthIndex = unarmedFactorsStrengthComboBox->currentIndex();
|
int unarmedFactorsStrengthIndex = unarmedFactorsStrengthComboBox->currentIndex();
|
||||||
if (unarmedFactorsStrengthIndex != mEngineSettings.getInt("strength influences hand to hand", "Game"))
|
if (unarmedFactorsStrengthIndex != mEngineSettings.getInt("strength influences hand to hand", "Game"))
|
||||||
mEngineSettings.setInt("strength influences hand to hand", "Game", unarmedFactorsStrengthIndex);
|
mEngineSettings.setInt("strength influences hand to hand", "Game", unarmedFactorsStrengthIndex);
|
||||||
saveSettingBool(stealingFromKnockedOutCheckBox, "always allow stealing from knocked out actors", "Game");
|
saveSettingBool(stealingFromKnockedOutCheckBox, "always allow stealing from knocked out actors", "Game");
|
||||||
|
saveSettingBool(enableNavigatorCheckBox, "enable", "Navigator");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Visuals
|
// Visuals
|
||||||
{
|
{
|
||||||
|
saveSettingBool(autoUseObjectNormalMapsCheckBox, "auto use object normal maps", "Shaders");
|
||||||
|
saveSettingBool(autoUseObjectSpecularMapsCheckBox, "auto use object specular maps", "Shaders");
|
||||||
|
saveSettingBool(autoUseTerrainNormalMapsCheckBox, "auto use terrain normal maps", "Shaders");
|
||||||
|
saveSettingBool(autoUseTerrainSpecularMapsCheckBox, "auto use terrain specular maps", "Shaders");
|
||||||
saveSettingBool(bumpMapLocalLightingCheckBox, "apply lighting to environment maps", "Shaders");
|
saveSettingBool(bumpMapLocalLightingCheckBox, "apply lighting to environment maps", "Shaders");
|
||||||
|
saveSettingBool(radialFogCheckBox, "radial fog", "Shaders");
|
||||||
saveSettingBool(magicItemAnimationsCheckBox, "use magic item animations", "Game");
|
saveSettingBool(magicItemAnimationsCheckBox, "use magic item animations", "Game");
|
||||||
saveSettingBool(animSourcesCheckBox, "use additional anim sources", "Game");
|
saveSettingBool(animSourcesCheckBox, "use additional anim sources", "Game");
|
||||||
saveSettingBool(weaponSheathingCheckBox, "weapon sheathing", "Game");
|
saveSettingBool(weaponSheathingCheckBox, "weapon sheathing", "Game");
|
||||||
saveSettingBool(shieldSheathingCheckBox, "shield sheathing", "Game");
|
saveSettingBool(shieldSheathingCheckBox, "shield sheathing", "Game");
|
||||||
saveSettingBool(viewOverShoulderCheckBox, "view over shoulder", "Camera");
|
|
||||||
saveSettingBool(turnToMovementDirectionCheckBox, "turn to movement direction", "Game");
|
saveSettingBool(turnToMovementDirectionCheckBox, "turn to movement direction", "Game");
|
||||||
|
|
||||||
const bool distantTerrain = mEngineSettings.getBool("distant terrain", "Terrain");
|
const bool distantTerrain = mEngineSettings.getBool("distant terrain", "Terrain");
|
||||||
|
@ -245,6 +237,24 @@ void Launcher::AdvancedPage::saveSettings()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Camera
|
||||||
|
{
|
||||||
|
saveSettingBool(viewOverShoulderCheckBox, "view over shoulder", "Camera");
|
||||||
|
saveSettingBool(autoSwitchShoulderCheckBox, "auto switch shoulder", "Camera");
|
||||||
|
saveSettingBool(previewIfStandStillCheckBox, "preview if stand still", "Camera");
|
||||||
|
saveSettingBool(deferredPreviewRotationCheckBox, "deferred preview rotation", "Camera");
|
||||||
|
|
||||||
|
osg::Vec2f shoulderOffset = mEngineSettings.getVector2("view over shoulder offset", "Camera");
|
||||||
|
if (defaultShoulderComboBox->currentIndex() != (shoulderOffset.x() >= 0 ? 0 : 1))
|
||||||
|
{
|
||||||
|
if (defaultShoulderComboBox->currentIndex() == 0)
|
||||||
|
shoulderOffset.x() = std::abs(shoulderOffset.x());
|
||||||
|
else
|
||||||
|
shoulderOffset.x() = -std::abs(shoulderOffset.x());
|
||||||
|
mEngineSettings.setVector2("view over shoulder offset", "Camera", shoulderOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Interface Changes
|
// Interface Changes
|
||||||
{
|
{
|
||||||
saveSettingBool(showEffectDurationCheckBox, "show effect duration", "Game");
|
saveSettingBool(showEffectDurationCheckBox, "show effect duration", "Game");
|
||||||
|
@ -326,3 +336,8 @@ void Launcher::AdvancedPage::slotAnimSourcesToggled(bool checked)
|
||||||
shieldSheathingCheckBox->setCheckState(Qt::Unchecked);
|
shieldSheathingCheckBox->setCheckState(Qt::Unchecked);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Launcher::AdvancedPage::slotViewOverShoulderToggled(bool checked)
|
||||||
|
{
|
||||||
|
viewOverShoulderVerticalLayout->setEnabled(viewOverShoulderCheckBox->checkState());
|
||||||
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ namespace Launcher
|
||||||
void on_skipMenuCheckBox_stateChanged(int state);
|
void on_skipMenuCheckBox_stateChanged(int state);
|
||||||
void on_runScriptAfterStartupBrowseButton_clicked();
|
void on_runScriptAfterStartupBrowseButton_clicked();
|
||||||
void slotAnimSourcesToggled(bool checked);
|
void slotAnimSourcesToggled(bool checked);
|
||||||
|
void slotViewOverShoulderToggled(bool checked);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Files::ConfigurationManager &mCfgMgr;
|
Files::ConfigurationManager &mCfgMgr;
|
||||||
|
|
|
@ -65,16 +65,19 @@ bool Launcher::GraphicsPage::setupSDL()
|
||||||
msgBox.setWindowTitle(tr("Error receiving number of screens"));
|
msgBox.setWindowTitle(tr("Error receiving number of screens"));
|
||||||
msgBox.setIcon(QMessageBox::Critical);
|
msgBox.setIcon(QMessageBox::Critical);
|
||||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||||
msgBox.setText(tr("<br><b>SDL_GetNumDisplayModes failed:</b><br><br>") + QString::fromUtf8(SDL_GetError()) + "<br>");
|
msgBox.setText(tr("<br><b>SDL_GetNumVideoDisplays failed:</b><br><br>") + QString::fromUtf8(SDL_GetError()) + "<br>");
|
||||||
msgBox.exec();
|
msgBox.exec();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
screenComboBox->clear();
|
screenComboBox->clear();
|
||||||
|
mResolutionsPerScreen.clear();
|
||||||
for (int i = 0; i < displays; i++)
|
for (int i = 0; i < displays; i++)
|
||||||
{
|
{
|
||||||
|
mResolutionsPerScreen.append(getAvailableResolutions(i));
|
||||||
screenComboBox->addItem(QString(tr("Screen ")) + QString::number(i + 1));
|
screenComboBox->addItem(QString(tr("Screen ")) + QString::number(i + 1));
|
||||||
}
|
}
|
||||||
|
screenChanged(0);
|
||||||
|
|
||||||
// Disconnect from SDL processes
|
// Disconnect from SDL processes
|
||||||
quitSDL();
|
quitSDL();
|
||||||
|
@ -331,7 +334,7 @@ void Launcher::GraphicsPage::screenChanged(int screen)
|
||||||
{
|
{
|
||||||
if (screen >= 0) {
|
if (screen >= 0) {
|
||||||
resolutionComboBox->clear();
|
resolutionComboBox->clear();
|
||||||
resolutionComboBox->addItems(getAvailableResolutions(screen));
|
resolutionComboBox->addItems(mResolutionsPerScreen[screen]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,8 @@ namespace Launcher
|
||||||
Files::ConfigurationManager &mCfgMgr;
|
Files::ConfigurationManager &mCfgMgr;
|
||||||
Settings::Manager &mEngineSettings;
|
Settings::Manager &mEngineSettings;
|
||||||
|
|
||||||
|
QVector<QStringList> mResolutionsPerScreen;
|
||||||
|
|
||||||
static QStringList getAvailableResolutions(int screen);
|
static QStringList getAvailableResolutions(int screen);
|
||||||
static QRect getMaximumResolution();
|
static QRect getMaximumResolution();
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@ add_openmw_dir (mwworld
|
||||||
add_openmw_dir (mwphysics
|
add_openmw_dir (mwphysics
|
||||||
physicssystem trace collisiontype actor convert object heightfield closestnotmerayresultcallback
|
physicssystem trace collisiontype actor convert object heightfield closestnotmerayresultcallback
|
||||||
contacttestresultcallback deepestnotmecontacttestresultcallback stepper movementsolver
|
contacttestresultcallback deepestnotmecontacttestresultcallback stepper movementsolver
|
||||||
closestnotmeconvexresultcallback
|
closestnotmeconvexresultcallback raycasting
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwclass
|
add_openmw_dir (mwclass
|
||||||
|
|
|
@ -51,6 +51,11 @@ namespace ESM
|
||||||
struct TimeStamp;
|
struct TimeStamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace MWPhysics
|
||||||
|
{
|
||||||
|
class RayCastingInterface;
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
class Animation;
|
class Animation;
|
||||||
|
@ -420,6 +425,8 @@ namespace MWBase
|
||||||
|
|
||||||
virtual void updateAnimatedCollisionShape(const MWWorld::Ptr &ptr) = 0;
|
virtual void updateAnimatedCollisionShape(const MWWorld::Ptr &ptr) = 0;
|
||||||
|
|
||||||
|
virtual const MWPhysics::RayCastingInterface* getRayCasting() const = 0;
|
||||||
|
|
||||||
virtual bool castRay (float x1, float y1, float z1, float x2, float y2, float z2, int mask) = 0;
|
virtual bool castRay (float x1, float y1, float z1, float x2, float y2, float z2, int mask) = 0;
|
||||||
///< cast a Ray and return true if there is an object in the ray path.
|
///< cast a Ray and return true if there is an object in the ray path.
|
||||||
|
|
||||||
|
@ -541,9 +548,8 @@ namespace MWBase
|
||||||
virtual void togglePreviewMode(bool enable) = 0;
|
virtual void togglePreviewMode(bool enable) = 0;
|
||||||
virtual bool toggleVanityMode(bool enable) = 0;
|
virtual bool toggleVanityMode(bool enable) = 0;
|
||||||
virtual void allowVanityMode(bool allow) = 0;
|
virtual void allowVanityMode(bool allow) = 0;
|
||||||
virtual void changeVanityModeScale(float factor) = 0;
|
|
||||||
virtual bool vanityRotateCamera(float * rot) = 0;
|
virtual bool vanityRotateCamera(float * rot) = 0;
|
||||||
virtual void setCameraDistance(float dist, bool adjust = false, bool override = true)=0;
|
virtual void adjustCameraDistance(float dist) = 0;
|
||||||
virtual void applyDeferredPreviewRotationToPlayer(float dt) = 0;
|
virtual void applyDeferredPreviewRotationToPlayer(float dt) = 0;
|
||||||
virtual void disableDeferredPreviewRotation() = 0;
|
virtual void disableDeferredPreviewRotation() = 0;
|
||||||
|
|
||||||
|
|
|
@ -91,4 +91,13 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float Actor::getCurrentSpeed(const MWWorld::Ptr& ptr) const
|
||||||
|
{
|
||||||
|
const MWMechanics::Movement& movementSettings = ptr.getClass().getMovementSettings(ptr);
|
||||||
|
float moveSpeed = this->getMaxSpeed(ptr) * movementSettings.mSpeedFactor;
|
||||||
|
if (movementSettings.mIsStrafing)
|
||||||
|
moveSpeed *= 0.75f;
|
||||||
|
return moveSpeed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ namespace MWClass
|
||||||
virtual void block(const MWWorld::Ptr &ptr) const;
|
virtual void block(const MWWorld::Ptr &ptr) const;
|
||||||
|
|
||||||
virtual osg::Vec3f getRotationVector(const MWWorld::Ptr& ptr) const;
|
virtual osg::Vec3f getRotationVector(const MWWorld::Ptr& ptr) const;
|
||||||
///< Return desired rotations, as euler angles.
|
///< Return desired rotations, as euler angles. Sets getMovementSettings(ptr).mRotation to zero.
|
||||||
|
|
||||||
virtual float getEncumbrance(const MWWorld::Ptr& ptr) const;
|
virtual float getEncumbrance(const MWWorld::Ptr& ptr) const;
|
||||||
///< Returns total weight of objects inside this object (including modifications from magic
|
///< Returns total weight of objects inside this object (including modifications from magic
|
||||||
|
@ -42,6 +42,9 @@ namespace MWClass
|
||||||
|
|
||||||
virtual bool isActor() const;
|
virtual bool isActor() const;
|
||||||
|
|
||||||
|
/// Return current movement speed.
|
||||||
|
virtual float getCurrentSpeed(const MWWorld::Ptr& ptr) const;
|
||||||
|
|
||||||
// not implemented
|
// not implemented
|
||||||
Actor(const Actor&);
|
Actor(const Actor&);
|
||||||
Actor& operator= (const Actor&);
|
Actor& operator= (const Actor&);
|
||||||
|
|
|
@ -688,7 +688,7 @@ namespace MWClass
|
||||||
registerClass (typeid (ESM::Creature).name(), instance);
|
registerClass (typeid (ESM::Creature).name(), instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
float Creature::getSpeed(const MWWorld::Ptr &ptr) const
|
float Creature::getMaxSpeed(const MWWorld::Ptr &ptr) const
|
||||||
{
|
{
|
||||||
const MWMechanics::CreatureStats& stats = getCreatureStats(ptr);
|
const MWMechanics::CreatureStats& stats = getCreatureStats(ptr);
|
||||||
|
|
||||||
|
@ -720,11 +720,6 @@ namespace MWClass
|
||||||
else
|
else
|
||||||
moveSpeed = getWalkSpeed(ptr);
|
moveSpeed = getWalkSpeed(ptr);
|
||||||
|
|
||||||
const MWMechanics::Movement& movementSettings = ptr.getClass().getMovementSettings(ptr);
|
|
||||||
if (movementSettings.mIsStrafing)
|
|
||||||
moveSpeed *= 0.75f;
|
|
||||||
moveSpeed *= movementSettings.mSpeedFactor;
|
|
||||||
|
|
||||||
return moveSpeed;
|
return moveSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ namespace MWClass
|
||||||
virtual MWMechanics::Movement& getMovementSettings (const MWWorld::Ptr& ptr) const;
|
virtual MWMechanics::Movement& getMovementSettings (const MWWorld::Ptr& ptr) const;
|
||||||
///< Return desired movement.
|
///< Return desired movement.
|
||||||
|
|
||||||
float getSpeed (const MWWorld::Ptr& ptr) const;
|
float getMaxSpeed (const MWWorld::Ptr& ptr) const;
|
||||||
|
|
||||||
static void registerSelf();
|
static void registerSelf();
|
||||||
|
|
||||||
|
|
|
@ -1159,7 +1159,7 @@ namespace MWClass
|
||||||
return ref->mBase->mScript;
|
return ref->mBase->mScript;
|
||||||
}
|
}
|
||||||
|
|
||||||
float Npc::getSpeed(const MWWorld::Ptr& ptr) const
|
float Npc::getMaxSpeed(const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
const MWMechanics::CreatureStats& stats = getCreatureStats(ptr);
|
const MWMechanics::CreatureStats& stats = getCreatureStats(ptr);
|
||||||
if (stats.isParalyzed() || stats.getKnockedDown() || stats.isDead())
|
if (stats.isParalyzed() || stats.getKnockedDown() || stats.isDead())
|
||||||
|
@ -1202,11 +1202,6 @@ namespace MWClass
|
||||||
if(npcdata->mNpcStats.isWerewolf() && running && npcdata->mNpcStats.getDrawState() == MWMechanics::DrawState_Nothing)
|
if(npcdata->mNpcStats.isWerewolf() && running && npcdata->mNpcStats.getDrawState() == MWMechanics::DrawState_Nothing)
|
||||||
moveSpeed *= gmst.fWereWolfRunMult->mValue.getFloat();
|
moveSpeed *= gmst.fWereWolfRunMult->mValue.getFloat();
|
||||||
|
|
||||||
const MWMechanics::Movement& movementSettings = ptr.getClass().getMovementSettings(ptr);
|
|
||||||
if (movementSettings.mIsStrafing)
|
|
||||||
moveSpeed *= 0.75f;
|
|
||||||
moveSpeed *= movementSettings.mSpeedFactor;
|
|
||||||
|
|
||||||
return moveSpeed;
|
return moveSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,8 +94,8 @@ namespace MWClass
|
||||||
virtual std::string getScript (const MWWorld::ConstPtr& ptr) const;
|
virtual std::string getScript (const MWWorld::ConstPtr& ptr) const;
|
||||||
///< Return name of the script attached to ptr
|
///< Return name of the script attached to ptr
|
||||||
|
|
||||||
virtual float getSpeed (const MWWorld::Ptr& ptr) const;
|
virtual float getMaxSpeed (const MWWorld::Ptr& ptr) const;
|
||||||
///< Return movement speed.
|
///< Return maximal movement speed.
|
||||||
|
|
||||||
virtual float getJump(const MWWorld::Ptr &ptr) const;
|
virtual float getJump(const MWWorld::Ptr &ptr) const;
|
||||||
///< Return jump velocity (not accounting for movement)
|
///< Return jump velocity (not accounting for movement)
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
|
|
||||||
namespace MWInput
|
namespace MWInput
|
||||||
{
|
{
|
||||||
const float ZOOM_SCALE = 120.f; /// Used for scrolling camera in and out
|
const float ZOOM_SCALE = 10.f; /// Used for scrolling camera in and out
|
||||||
|
|
||||||
ActionManager::ActionManager(BindingsManager* bindingsManager,
|
ActionManager::ActionManager(BindingsManager* bindingsManager,
|
||||||
osgViewer::ScreenCaptureHandler::CaptureOperation* screenCaptureOperation,
|
osgViewer::ScreenCaptureHandler::CaptureOperation* screenCaptureOperation,
|
||||||
|
@ -206,6 +206,8 @@ namespace MWInput
|
||||||
|
|
||||||
void ActionManager::executeAction(int action)
|
void ActionManager::executeAction(int action)
|
||||||
{
|
{
|
||||||
|
auto* inputManager = MWBase::Environment::get().getInputManager();
|
||||||
|
auto* windowManager = MWBase::Environment::get().getWindowManager();
|
||||||
// trigger action activated
|
// trigger action activated
|
||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
|
@ -222,7 +224,7 @@ namespace MWInput
|
||||||
toggleConsole ();
|
toggleConsole ();
|
||||||
break;
|
break;
|
||||||
case A_Activate:
|
case A_Activate:
|
||||||
MWBase::Environment::get().getInputManager()->resetIdleTime();
|
inputManager->resetIdleTime();
|
||||||
activate();
|
activate();
|
||||||
break;
|
break;
|
||||||
case A_MoveLeft:
|
case A_MoveLeft:
|
||||||
|
@ -283,18 +285,18 @@ namespace MWInput
|
||||||
showQuickKeysMenu();
|
showQuickKeysMenu();
|
||||||
break;
|
break;
|
||||||
case A_ToggleHUD:
|
case A_ToggleHUD:
|
||||||
MWBase::Environment::get().getWindowManager()->toggleHud();
|
windowManager->toggleHud();
|
||||||
break;
|
break;
|
||||||
case A_ToggleDebug:
|
case A_ToggleDebug:
|
||||||
MWBase::Environment::get().getWindowManager()->toggleDebugWindow();
|
windowManager->toggleDebugWindow();
|
||||||
break;
|
break;
|
||||||
case A_ZoomIn:
|
case A_ZoomIn:
|
||||||
if (MWBase::Environment::get().getInputManager()->getControlSwitch("playerviewswitch") && MWBase::Environment::get().getInputManager()->getControlSwitch("playercontrols") && !MWBase::Environment::get().getWindowManager()->isGuiMode())
|
if (inputManager->getControlSwitch("playerviewswitch") && inputManager->getControlSwitch("playercontrols") && !windowManager->isGuiMode())
|
||||||
MWBase::Environment::get().getWorld()->setCameraDistance(ZOOM_SCALE, true, true);
|
MWBase::Environment::get().getWorld()->adjustCameraDistance(-ZOOM_SCALE);
|
||||||
break;
|
break;
|
||||||
case A_ZoomOut:
|
case A_ZoomOut:
|
||||||
if (MWBase::Environment::get().getInputManager()->getControlSwitch("playerviewswitch") && MWBase::Environment::get().getInputManager()->getControlSwitch("playercontrols") && !MWBase::Environment::get().getWindowManager()->isGuiMode())
|
if (inputManager->getControlSwitch("playerviewswitch") && inputManager->getControlSwitch("playercontrols") && !windowManager->isGuiMode())
|
||||||
MWBase::Environment::get().getWorld()->setCameraDistance(-ZOOM_SCALE, true, true);
|
MWBase::Environment::get().getWorld()->adjustCameraDistance(ZOOM_SCALE);
|
||||||
break;
|
break;
|
||||||
case A_QuickSave:
|
case A_QuickSave:
|
||||||
quickSave();
|
quickSave();
|
||||||
|
@ -303,19 +305,19 @@ namespace MWInput
|
||||||
quickLoad();
|
quickLoad();
|
||||||
break;
|
break;
|
||||||
case A_CycleSpellLeft:
|
case A_CycleSpellLeft:
|
||||||
if (checkAllowedToUseItems() && MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Magic))
|
if (checkAllowedToUseItems() && windowManager->isAllowed(MWGui::GW_Magic))
|
||||||
MWBase::Environment::get().getWindowManager()->cycleSpell(false);
|
MWBase::Environment::get().getWindowManager()->cycleSpell(false);
|
||||||
break;
|
break;
|
||||||
case A_CycleSpellRight:
|
case A_CycleSpellRight:
|
||||||
if (checkAllowedToUseItems() && MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Magic))
|
if (checkAllowedToUseItems() && windowManager->isAllowed(MWGui::GW_Magic))
|
||||||
MWBase::Environment::get().getWindowManager()->cycleSpell(true);
|
MWBase::Environment::get().getWindowManager()->cycleSpell(true);
|
||||||
break;
|
break;
|
||||||
case A_CycleWeaponLeft:
|
case A_CycleWeaponLeft:
|
||||||
if (checkAllowedToUseItems() && MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
|
if (checkAllowedToUseItems() && windowManager->isAllowed(MWGui::GW_Inventory))
|
||||||
MWBase::Environment::get().getWindowManager()->cycleWeapon(false);
|
MWBase::Environment::get().getWindowManager()->cycleWeapon(false);
|
||||||
break;
|
break;
|
||||||
case A_CycleWeaponRight:
|
case A_CycleWeaponRight:
|
||||||
if (checkAllowedToUseItems() && MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
|
if (checkAllowedToUseItems() && windowManager->isAllowed(MWGui::GW_Inventory))
|
||||||
MWBase::Environment::get().getWindowManager()->cycleWeapon(true);
|
MWBase::Environment::get().getWindowManager()->cycleWeapon(true);
|
||||||
break;
|
break;
|
||||||
case A_Sneak:
|
case A_Sneak:
|
||||||
|
|
|
@ -190,10 +190,7 @@ namespace MWInput
|
||||||
mGamepadZoom = 0;
|
mGamepadZoom = 0;
|
||||||
|
|
||||||
if (mGamepadZoom)
|
if (mGamepadZoom)
|
||||||
{
|
MWBase::Environment::get().getWorld()->adjustCameraDistance(-mGamepadZoom);
|
||||||
MWBase::Environment::get().getWorld()->changeVanityModeScale(mGamepadZoom);
|
|
||||||
MWBase::Environment::get().getWorld()->setCameraDistance(mGamepadZoom, true, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return triedToMove;
|
return triedToMove;
|
||||||
|
@ -291,12 +288,12 @@ namespace MWInput
|
||||||
{
|
{
|
||||||
if (arg.axis == SDL_CONTROLLER_AXIS_TRIGGERRIGHT)
|
if (arg.axis == SDL_CONTROLLER_AXIS_TRIGGERRIGHT)
|
||||||
{
|
{
|
||||||
mGamepadZoom = arg.value * 0.85f / 1000.f;
|
mGamepadZoom = arg.value * 0.85f / 1000.f / 12.f;
|
||||||
return; // Do not propagate event.
|
return; // Do not propagate event.
|
||||||
}
|
}
|
||||||
else if (arg.axis == SDL_CONTROLLER_AXIS_TRIGGERLEFT)
|
else if (arg.axis == SDL_CONTROLLER_AXIS_TRIGGERLEFT)
|
||||||
{
|
{
|
||||||
mGamepadZoom = -arg.value * 0.85f / 1000.f;
|
mGamepadZoom = -arg.value * 0.85f / 1000.f / 12.f;
|
||||||
return; // Do not propagate event.
|
return; // Do not propagate event.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,6 +93,8 @@ namespace MWInput
|
||||||
|
|
||||||
if (mMouseLookEnabled && !input->controlsDisabled())
|
if (mMouseLookEnabled && !input->controlsDisabled())
|
||||||
{
|
{
|
||||||
|
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||||
|
|
||||||
float x = arg.xrel * mCameraSensitivity * (mInvertX ? -1 : 1) / 256.f;
|
float x = arg.xrel * mCameraSensitivity * (mInvertX ? -1 : 1) / 256.f;
|
||||||
float y = arg.yrel * mCameraSensitivity * (mInvertY ? -1 : 1) * mCameraYMultiplier / 256.f;
|
float y = arg.yrel * mCameraSensitivity * (mInvertY ? -1 : 1) * mCameraYMultiplier / 256.f;
|
||||||
|
|
||||||
|
@ -102,19 +104,14 @@ namespace MWInput
|
||||||
rot[2] = -x;
|
rot[2] = -x;
|
||||||
|
|
||||||
// Only actually turn player when we're not in vanity mode
|
// Only actually turn player when we're not in vanity mode
|
||||||
if (!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot) && input->getControlSwitch("playerlooking"))
|
if (!world->vanityRotateCamera(rot) && input->getControlSwitch("playerlooking"))
|
||||||
{
|
{
|
||||||
MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer();
|
MWWorld::Player& player = world->getPlayer();
|
||||||
player.yaw(x);
|
player.yaw(x);
|
||||||
player.pitch(y);
|
player.pitch(y);
|
||||||
}
|
}
|
||||||
else if (!input->getControlSwitch("playerlooking"))
|
else if (!input->getControlSwitch("playerlooking"))
|
||||||
MWBase::Environment::get().getWorld()->disableDeferredPreviewRotation();
|
MWBase::Environment::get().getWorld()->disableDeferredPreviewRotation();
|
||||||
|
|
||||||
if (arg.zrel && input->getControlSwitch("playerviewswitch") && input->getControlSwitch("playercontrols")) //Check to make sure you are allowed to zoomout and there is a change
|
|
||||||
{
|
|
||||||
MWBase::Environment::get().getWorld()->changeVanityModeScale(static_cast<float>(arg.zrel));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -505,9 +505,6 @@ namespace MWMechanics
|
||||||
|
|
||||||
void Actors::updateMovementSpeed(const MWWorld::Ptr& actor)
|
void Actors::updateMovementSpeed(const MWWorld::Ptr& actor)
|
||||||
{
|
{
|
||||||
float previousSpeedFactor = actor.getClass().getMovementSettings(actor).mSpeedFactor;
|
|
||||||
float newSpeedFactor = 1.f;
|
|
||||||
|
|
||||||
CreatureStats &stats = actor.getClass().getCreatureStats(actor);
|
CreatureStats &stats = actor.getClass().getCreatureStats(actor);
|
||||||
MWMechanics::AiSequence& seq = stats.getAiSequence();
|
MWMechanics::AiSequence& seq = stats.getAiSequence();
|
||||||
|
|
||||||
|
@ -517,10 +514,13 @@ namespace MWMechanics
|
||||||
osg::Vec3f actorPos = actor.getRefData().getPosition().asVec3();
|
osg::Vec3f actorPos = actor.getRefData().getPosition().asVec3();
|
||||||
float distance = (targetPos - actorPos).length();
|
float distance = (targetPos - actorPos).length();
|
||||||
if (distance < DECELERATE_DISTANCE)
|
if (distance < DECELERATE_DISTANCE)
|
||||||
newSpeedFactor = std::max(0.7f, 0.1f * previousSpeedFactor * (distance/64.f + 2.f));
|
{
|
||||||
|
float speedCoef = std::max(0.7f, 0.1f * (distance/64.f + 2.f));
|
||||||
|
auto& movement = actor.getClass().getMovementSettings(actor);
|
||||||
|
movement.mPosition[0] *= speedCoef;
|
||||||
|
movement.mPosition[1] *= speedCoef;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actor.getClass().getMovementSettings(actor).mSpeedFactor = newSpeedFactor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Actors::updateGreetingState(const MWWorld::Ptr& actor, Actor& actorState, bool turnOnly)
|
void Actors::updateGreetingState(const MWWorld::Ptr& actor, Actor& actorState, bool turnOnly)
|
||||||
|
|
|
@ -60,14 +60,14 @@ bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor, CharacterCont
|
||||||
// Make all nearby actors also avoid the door
|
// Make all nearby actors also avoid the door
|
||||||
std::vector<MWWorld::Ptr> actors;
|
std::vector<MWWorld::Ptr> actors;
|
||||||
MWBase::Environment::get().getMechanicsManager()->getActorsInRange(pos.asVec3(),100,actors);
|
MWBase::Environment::get().getMechanicsManager()->getActorsInRange(pos.asVec3(),100,actors);
|
||||||
for(auto& actor : actors)
|
for(auto& neighbor : actors)
|
||||||
{
|
{
|
||||||
if (actor == getPlayer())
|
if (neighbor == getPlayer())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
MWMechanics::AiSequence& seq = actor.getClass().getCreatureStats(actor).getAiSequence();
|
MWMechanics::AiSequence& seq = neighbor.getClass().getCreatureStats(neighbor).getAiSequence();
|
||||||
if (seq.getTypeId() != MWMechanics::AiPackageTypeId::AvoidDoor)
|
if (seq.getTypeId() != MWMechanics::AiPackageTypeId::AvoidDoor)
|
||||||
seq.stack(MWMechanics::AiAvoidDoor(mDoorPtr), actor);
|
seq.stack(MWMechanics::AiAvoidDoor(mDoorPtr), neighbor);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -144,7 +144,7 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, const osg::Vec3f&
|
||||||
mTimer = 0;
|
mTimer = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const float actorTolerance = 2 * actor.getClass().getSpeed(actor) * duration
|
const float actorTolerance = 2 * actor.getClass().getMaxSpeed(actor) * duration
|
||||||
+ 1.2 * std::max(halfExtents.x(), halfExtents.y());
|
+ 1.2 * std::max(halfExtents.x(), halfExtents.y());
|
||||||
const float pointTolerance = std::max(MIN_TOLERANCE, actorTolerance);
|
const float pointTolerance = std::max(MIN_TOLERANCE, actorTolerance);
|
||||||
|
|
||||||
|
@ -300,7 +300,7 @@ bool MWMechanics::AiPackage::checkWayIsClearForActor(const osg::Vec3f& startPoin
|
||||||
if (canActorMoveByZAxis(actor))
|
if (canActorMoveByZAxis(actor))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
const float actorSpeed = actor.getClass().getSpeed(actor);
|
const float actorSpeed = actor.getClass().getMaxSpeed(actor);
|
||||||
const float maxAvoidDist = AI_REACTION_TIME * actorSpeed + actorSpeed / getAngularVelocity(actorSpeed) * 2; // *2 - for reliability
|
const float maxAvoidDist = AI_REACTION_TIME * actorSpeed + actorSpeed / getAngularVelocity(actorSpeed) * 2; // *2 - for reliability
|
||||||
const float distToTarget = osg::Vec2f(endPoint.x(), endPoint.y()).length();
|
const float distToTarget = osg::Vec2f(endPoint.x(), endPoint.y()).length();
|
||||||
|
|
||||||
|
@ -360,7 +360,7 @@ bool MWMechanics::AiPackage::isNearInactiveCell(osg::Vec3f position)
|
||||||
bool MWMechanics::AiPackage::isReachableRotatingOnTheRun(const MWWorld::Ptr& actor, const osg::Vec3f& dest)
|
bool MWMechanics::AiPackage::isReachableRotatingOnTheRun(const MWWorld::Ptr& actor, const osg::Vec3f& dest)
|
||||||
{
|
{
|
||||||
// get actor's shortest radius for moving in circle
|
// get actor's shortest radius for moving in circle
|
||||||
float speed = actor.getClass().getSpeed(actor);
|
float speed = actor.getClass().getMaxSpeed(actor);
|
||||||
speed += speed * 0.1f; // 10% real speed inaccuracy
|
speed += speed * 0.1f; // 10% real speed inaccuracy
|
||||||
float radius = speed / getAngularVelocity(speed);
|
float radius = speed / getAngularVelocity(speed);
|
||||||
|
|
||||||
|
|
|
@ -52,8 +52,7 @@ bool AiPursue::execute (const MWWorld::Ptr& actor, CharacterController& characte
|
||||||
if (target == MWWorld::Ptr() || !target.getRefData().getCount() || !target.getRefData().isEnabled())
|
if (target == MWWorld::Ptr() || !target.getRefData().getCount() || !target.getRefData().isEnabled())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!MWBase::Environment::get().getWorld()->getLOS(target, actor)
|
if (isTargetMagicallyHidden(target) && !MWBase::Environment::get().getMechanicsManager()->awarenessCheck(target, actor))
|
||||||
|| !MWBase::Environment::get().getMechanicsManager()->awarenessCheck(target, actor))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (target.getClass().getCreatureStats(target).isDead())
|
if (target.getClass().getCreatureStats(target).isDead())
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <components/misc/mathutil.hpp>
|
||||||
#include <components/misc/rng.hpp>
|
#include <components/misc/rng.hpp>
|
||||||
|
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
@ -68,15 +69,6 @@
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
// Wraps a value to (-PI, PI]
|
|
||||||
void wrap(float& rad)
|
|
||||||
{
|
|
||||||
if (rad>0)
|
|
||||||
rad = std::fmod(rad+osg::PI, 2.0f*osg::PI)-osg::PI;
|
|
||||||
else
|
|
||||||
rad = std::fmod(rad-osg::PI, 2.0f*osg::PI)+osg::PI;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getBestAttack (const ESM::Weapon* weapon)
|
std::string getBestAttack (const ESM::Weapon* weapon)
|
||||||
{
|
{
|
||||||
int slash = (weapon->mData.mSlash[0] + weapon->mData.mSlash[1])/2;
|
int slash = (weapon->mData.mSlash[0] + weapon->mData.mSlash[1])/2;
|
||||||
|
@ -2116,7 +2108,6 @@ void CharacterController::update(float duration, bool animationOnly)
|
||||||
|
|
||||||
osg::Vec3f rot = cls.getRotationVector(mPtr);
|
osg::Vec3f rot = cls.getRotationVector(mPtr);
|
||||||
osg::Vec3f vec(movementSettings.asVec3());
|
osg::Vec3f vec(movementSettings.asVec3());
|
||||||
vec.normalize();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Start of tes3mp addition
|
Start of tes3mp addition
|
||||||
|
@ -2150,21 +2141,18 @@ void CharacterController::update(float duration, bool animationOnly)
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
*/
|
*/
|
||||||
|
|
||||||
float analogueMult = 1.0f;
|
|
||||||
if (isPlayer)
|
if (isPlayer)
|
||||||
{
|
{
|
||||||
// TODO: Move this code to mwinput.
|
// TODO: Move this code to mwinput.
|
||||||
// Joystick analogue movement.
|
// Joystick analogue movement.
|
||||||
float xAxis = std::abs(movementSettings.mPosition[0]);
|
movementSettings.mSpeedFactor = std::max(std::abs(vec.x()), std::abs(vec.y()));
|
||||||
float yAxis = std::abs(movementSettings.mPosition[1]);
|
|
||||||
analogueMult = std::max(xAxis, yAxis);
|
|
||||||
|
|
||||||
// Due to the half way split between walking/running, we multiply speed by 2 while walking, unless a keyboard was used.
|
// Due to the half way split between walking/running, we multiply speed by 2 while walking, unless a keyboard was used.
|
||||||
if(!isrunning && !sneak && !flying && analogueMult <= 0.5f)
|
if(!isrunning && !sneak && !flying && movementSettings.mSpeedFactor <= 0.5f)
|
||||||
analogueMult *= 2.f;
|
movementSettings.mSpeedFactor *= 2.f;
|
||||||
|
} else
|
||||||
movementSettings.mSpeedFactor = analogueMult;
|
movementSettings.mSpeedFactor = std::min(vec.length(), 1.f);
|
||||||
}
|
vec.normalize();
|
||||||
|
|
||||||
float effectiveRotation = rot.z();
|
float effectiveRotation = rot.z();
|
||||||
static const bool turnToMovementDirection = Settings::Manager::getBool("turn to movement direction", "Game");
|
static const bool turnToMovementDirection = Settings::Manager::getBool("turn to movement direction", "Game");
|
||||||
|
@ -2197,7 +2185,7 @@ void CharacterController::update(float duration, bool animationOnly)
|
||||||
else
|
else
|
||||||
mAnimation->setUpperBodyYawRadians(stats.getSideMovementAngle() / 4);
|
mAnimation->setUpperBodyYawRadians(stats.getSideMovementAngle() / 4);
|
||||||
|
|
||||||
speed = cls.getSpeed(mPtr);
|
speed = cls.getCurrentSpeed(mPtr);
|
||||||
vec.x() *= speed;
|
vec.x() *= speed;
|
||||||
vec.y() *= speed;
|
vec.y() *= speed;
|
||||||
|
|
||||||
|
@ -2267,7 +2255,7 @@ void CharacterController::update(float duration, bool animationOnly)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fatigueLoss *= duration;
|
fatigueLoss *= duration;
|
||||||
fatigueLoss *= analogueMult;
|
fatigueLoss *= movementSettings.mSpeedFactor;
|
||||||
DynamicStat<float> fatigue = cls.getCreatureStats(mPtr).getFatigue();
|
DynamicStat<float> fatigue = cls.getCreatureStats(mPtr).getFatigue();
|
||||||
|
|
||||||
if (!godmode)
|
if (!godmode)
|
||||||
|
@ -2433,7 +2421,8 @@ void CharacterController::update(float duration, bool animationOnly)
|
||||||
swimmingPitch += osg::clampBetween(targetSwimmingPitch - swimmingPitch, -maxSwimPitchDelta, maxSwimPitchDelta);
|
swimmingPitch += osg::clampBetween(targetSwimmingPitch - swimmingPitch, -maxSwimPitchDelta, maxSwimPitchDelta);
|
||||||
mAnimation->setBodyPitchRadians(swimmingPitch);
|
mAnimation->setBodyPitchRadians(swimmingPitch);
|
||||||
}
|
}
|
||||||
if (inwater && isPlayer && !isFirstPersonPlayer)
|
static const bool swimUpwardCorrection = Settings::Manager::getBool("swim upward correction", "Game");
|
||||||
|
if (inwater && isPlayer && !isFirstPersonPlayer && swimUpwardCorrection)
|
||||||
{
|
{
|
||||||
static const float swimUpwardCoef = Settings::Manager::getFloat("swim upward coef", "Game");
|
static const float swimUpwardCoef = Settings::Manager::getFloat("swim upward coef", "Game");
|
||||||
static const float swimForwardCoef = sqrtf(1.0f - swimUpwardCoef * swimUpwardCoef);
|
static const float swimForwardCoef = sqrtf(1.0f - swimUpwardCoef * swimUpwardCoef);
|
||||||
|
@ -3140,13 +3129,10 @@ void CharacterController::updateHeadTracking(float duration)
|
||||||
zAngleRadians = std::atan2(direction.x(), direction.y()) - std::atan2(actorDirection.x(), actorDirection.y());
|
zAngleRadians = std::atan2(direction.x(), direction.y()) - std::atan2(actorDirection.x(), actorDirection.y());
|
||||||
xAngleRadians = -std::asin(direction.z());
|
xAngleRadians = -std::asin(direction.z());
|
||||||
|
|
||||||
wrap(zAngleRadians);
|
const double xLimit = osg::DegreesToRadians(40.0);
|
||||||
wrap(xAngleRadians);
|
const double zLimit = osg::DegreesToRadians(30.0);
|
||||||
|
zAngleRadians = osg::clampBetween(Misc::normalizeAngle(zAngleRadians), -xLimit, xLimit);
|
||||||
xAngleRadians = std::min(xAngleRadians, osg::DegreesToRadians(40.f));
|
xAngleRadians = osg::clampBetween(Misc::normalizeAngle(xAngleRadians), -zLimit, zLimit);
|
||||||
xAngleRadians = std::max(xAngleRadians, osg::DegreesToRadians(-40.f));
|
|
||||||
zAngleRadians = std::min(zAngleRadians, osg::DegreesToRadians(30.f));
|
|
||||||
zAngleRadians = std::max(zAngleRadians, osg::DegreesToRadians(-30.f));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float factor = duration*5;
|
float factor = duration*5;
|
||||||
|
|
|
@ -8,8 +8,14 @@ namespace MWMechanics
|
||||||
/// Desired movement for an actor
|
/// Desired movement for an actor
|
||||||
struct Movement
|
struct Movement
|
||||||
{
|
{
|
||||||
|
// Desired movement. Direction is relative to the current orientation.
|
||||||
|
// Length of the vector controls desired speed. 0 - stay, 0.5 - half-speed, 1.0 - max speed.
|
||||||
float mPosition[3];
|
float mPosition[3];
|
||||||
|
// Desired rotation delta (euler angles).
|
||||||
float mRotation[3];
|
float mRotation[3];
|
||||||
|
|
||||||
|
// Controlled by CharacterController, should not be changed from other places.
|
||||||
|
// These fields can not be private fields in CharacterController, because Actor::getCurrentSpeed uses it.
|
||||||
float mSpeedFactor;
|
float mSpeedFactor;
|
||||||
bool mIsStrafing;
|
bool mIsStrafing;
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
if (mWalkState != WalkState::Evade)
|
if (mWalkState != WalkState::Evade)
|
||||||
{
|
{
|
||||||
const float distSameSpot = DIST_SAME_SPOT * actor.getClass().getSpeed(actor) * duration;
|
const float distSameSpot = DIST_SAME_SPOT * actor.getClass().getCurrentSpeed(actor) * duration;
|
||||||
const float prevDistance = (destination - mPrev).length();
|
const float prevDistance = (destination - mPrev).length();
|
||||||
const float currentDistance = (destination - position).length();
|
const float currentDistance = (destination - position).length();
|
||||||
const float movedDistance = prevDistance - currentDistance;
|
const float movedDistance = prevDistance - currentDistance;
|
||||||
|
|
|
@ -26,6 +26,14 @@ namespace MWMechanics
|
||||||
|
|
||||||
class Spells;
|
class Spells;
|
||||||
|
|
||||||
|
/// Multiple instances of the same actor share the same spell list in Morrowind.
|
||||||
|
/// The most obvious result of this is that adding a spell or ability to one instance adds it to all instances.
|
||||||
|
/// @note The original game will only update visual effects associated with any added abilities for the originally targeted actor,
|
||||||
|
/// changing cells applies the update to all actors.
|
||||||
|
/// Aside from sharing the same active spell list, changes made to this list are also written to the actor's base record.
|
||||||
|
/// Interestingly, it is not just scripted changes that are persisted to the base record. Curing one instance's disease will cure all instances.
|
||||||
|
/// @note The original game is inconsistent in persisting this example;
|
||||||
|
/// saving and loading the game might reapply the cured disease depending on which instance was cured.
|
||||||
class SpellList
|
class SpellList
|
||||||
{
|
{
|
||||||
const std::string mId;
|
const std::string mId;
|
||||||
|
|
|
@ -455,8 +455,9 @@ namespace MWMechanics
|
||||||
const auto& baseSpells = mSpellList->getSpells();
|
const auto& baseSpells = mSpellList->getSpells();
|
||||||
for (const auto& it : mSpells)
|
for (const auto& it : mSpells)
|
||||||
{
|
{
|
||||||
//Don't save spells stored in the base record
|
// Don't save spells and powers stored in the base record
|
||||||
if(std::find(baseSpells.begin(), baseSpells.end(), it.first->mId) == baseSpells.end())
|
if((it.first->mData.mType != ESM::Spell::ST_Spell && it.first->mData.mType != ESM::Spell::ST_Power) ||
|
||||||
|
std::find(baseSpells.begin(), baseSpells.end(), it.first->mId) == baseSpells.end())
|
||||||
{
|
{
|
||||||
ESM::SpellState::SpellParams params;
|
ESM::SpellState::SpellParams params;
|
||||||
params.mEffectRands = it.second.mEffectRands;
|
params.mEffectRands = it.second.mEffectRands;
|
||||||
|
@ -476,8 +477,7 @@ namespace MWMechanics
|
||||||
bool result;
|
bool result;
|
||||||
std::tie(mSpellList, result) = MWBase::Environment::get().getWorld()->getStore().getSpellList(actorId);
|
std::tie(mSpellList, result) = MWBase::Environment::get().getWorld()->getStore().getSpellList(actorId);
|
||||||
mSpellList->addListener(this);
|
mSpellList->addListener(this);
|
||||||
for(const auto& id : mSpellList->getSpells())
|
addAllToInstance(mSpellList->getSpells());
|
||||||
addSpell(SpellList::getSpell(id));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ bool smoothTurn(const MWWorld::Ptr& actor, float targetAngleRadians, int axis, f
|
||||||
if (absDiff < epsilonRadians)
|
if (absDiff < epsilonRadians)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
float limit = getAngularVelocity(actor.getClass().getSpeed(actor)) * MWBase::Environment::get().getFrameDuration();
|
float limit = getAngularVelocity(actor.getClass().getMaxSpeed(actor)) * MWBase::Environment::get().getFrameDuration();
|
||||||
if (absDiff > limit)
|
if (absDiff > limit)
|
||||||
diff = osg::sign(diff) * limit;
|
diff = osg::sign(diff) * limit;
|
||||||
|
|
||||||
|
|
|
@ -201,7 +201,7 @@ namespace MWPhysics
|
||||||
{
|
{
|
||||||
// First of all, try to hit where you aim to
|
// First of all, try to hit where you aim to
|
||||||
int hitmask = CollisionType_World | CollisionType_Door | CollisionType_HeightMap | CollisionType_Actor;
|
int hitmask = CollisionType_World | CollisionType_Door | CollisionType_HeightMap | CollisionType_Actor;
|
||||||
RayResult result = castRay(origin, origin + (orient * osg::Vec3f(0.0f, queryDistance, 0.0f)), actor, targets, hitmask, CollisionType_Actor);
|
RayCastingResult result = castRay(origin, origin + (orient * osg::Vec3f(0.0f, queryDistance, 0.0f)), actor, targets, hitmask, CollisionType_Actor);
|
||||||
|
|
||||||
if (result.mHit)
|
if (result.mHit)
|
||||||
{
|
{
|
||||||
|
@ -284,7 +284,7 @@ namespace MWPhysics
|
||||||
return (point - Misc::Convert::toOsg(cb.m_hitPointWorld)).length();
|
return (point - Misc::Convert::toOsg(cb.m_hitPointWorld)).length();
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicsSystem::RayResult PhysicsSystem::castRay(const osg::Vec3f &from, const osg::Vec3f &to, const MWWorld::ConstPtr& ignore, std::vector<MWWorld::Ptr> targets, int mask, int group) const
|
RayCastingResult PhysicsSystem::castRay(const osg::Vec3f &from, const osg::Vec3f &to, const MWWorld::ConstPtr& ignore, std::vector<MWWorld::Ptr> targets, int mask, int group) const
|
||||||
{
|
{
|
||||||
btVector3 btFrom = Misc::Convert::toBullet(from);
|
btVector3 btFrom = Misc::Convert::toBullet(from);
|
||||||
btVector3 btTo = Misc::Convert::toBullet(to);
|
btVector3 btTo = Misc::Convert::toBullet(to);
|
||||||
|
@ -321,7 +321,7 @@ namespace MWPhysics
|
||||||
|
|
||||||
mCollisionWorld->rayTest(btFrom, btTo, resultCallback);
|
mCollisionWorld->rayTest(btFrom, btTo, resultCallback);
|
||||||
|
|
||||||
RayResult result;
|
RayCastingResult result;
|
||||||
result.mHit = resultCallback.hasHit();
|
result.mHit = resultCallback.hasHit();
|
||||||
if (resultCallback.hasHit())
|
if (resultCallback.hasHit())
|
||||||
{
|
{
|
||||||
|
@ -333,7 +333,7 @@ namespace MWPhysics
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicsSystem::RayResult PhysicsSystem::castSphere(const osg::Vec3f &from, const osg::Vec3f &to, float radius)
|
RayCastingResult PhysicsSystem::castSphere(const osg::Vec3f &from, const osg::Vec3f &to, float radius) const
|
||||||
{
|
{
|
||||||
btCollisionWorld::ClosestConvexResultCallback callback(Misc::Convert::toBullet(from), Misc::Convert::toBullet(to));
|
btCollisionWorld::ClosestConvexResultCallback callback(Misc::Convert::toBullet(from), Misc::Convert::toBullet(to));
|
||||||
callback.m_collisionFilterGroup = 0xff;
|
callback.m_collisionFilterGroup = 0xff;
|
||||||
|
@ -347,7 +347,7 @@ namespace MWPhysics
|
||||||
|
|
||||||
mCollisionWorld->convexSweepTest(&shape, from_, to_, callback);
|
mCollisionWorld->convexSweepTest(&shape, from_, to_, callback);
|
||||||
|
|
||||||
RayResult result;
|
RayCastingResult result;
|
||||||
result.mHit = callback.hasHit();
|
result.mHit = callback.hasHit();
|
||||||
if (result.mHit)
|
if (result.mHit)
|
||||||
{
|
{
|
||||||
|
@ -368,7 +368,7 @@ namespace MWPhysics
|
||||||
osg::Vec3f pos1 (physactor1->getCollisionObjectPosition() + osg::Vec3f(0,0,physactor1->getHalfExtents().z() * 0.9)); // eye level
|
osg::Vec3f pos1 (physactor1->getCollisionObjectPosition() + osg::Vec3f(0,0,physactor1->getHalfExtents().z() * 0.9)); // eye level
|
||||||
osg::Vec3f pos2 (physactor2->getCollisionObjectPosition() + osg::Vec3f(0,0,physactor2->getHalfExtents().z() * 0.9));
|
osg::Vec3f pos2 (physactor2->getCollisionObjectPosition() + osg::Vec3f(0,0,physactor2->getHalfExtents().z() * 0.9));
|
||||||
|
|
||||||
RayResult result = castRay(pos1, pos2, MWWorld::ConstPtr(), std::vector<MWWorld::Ptr>(), CollisionType_World|CollisionType_HeightMap|CollisionType_Door);
|
RayCastingResult result = castRay(pos1, pos2, MWWorld::ConstPtr(), std::vector<MWWorld::Ptr>(), CollisionType_World|CollisionType_HeightMap|CollisionType_Door);
|
||||||
|
|
||||||
return !result.mHit;
|
return !result.mHit;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
|
|
||||||
#include "collisiontype.hpp"
|
#include "collisiontype.hpp"
|
||||||
|
#include "raycasting.hpp"
|
||||||
|
|
||||||
namespace osg
|
namespace osg
|
||||||
{
|
{
|
||||||
|
@ -52,11 +53,11 @@ namespace MWPhysics
|
||||||
class Object;
|
class Object;
|
||||||
class Actor;
|
class Actor;
|
||||||
|
|
||||||
class PhysicsSystem
|
class PhysicsSystem : public RayCastingInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PhysicsSystem (Resource::ResourceSystem* resourceSystem, osg::ref_ptr<osg::Group> parentNode);
|
PhysicsSystem (Resource::ResourceSystem* resourceSystem, osg::ref_ptr<osg::Group> parentNode);
|
||||||
~PhysicsSystem ();
|
virtual ~PhysicsSystem ();
|
||||||
|
|
||||||
void setUnrefQueue(SceneUtil::UnrefQueue* unrefQueue);
|
void setUnrefQueue(SceneUtil::UnrefQueue* unrefQueue);
|
||||||
|
|
||||||
|
@ -108,25 +109,17 @@ namespace MWPhysics
|
||||||
/// target vector hits the collision shape and then calculates distance from the intersection point.
|
/// target vector hits the collision shape and then calculates distance from the intersection point.
|
||||||
/// This can be used to find out how much nearer we need to move to the target for a "getHitContact" to be successful.
|
/// This can be used to find out how much nearer we need to move to the target for a "getHitContact" to be successful.
|
||||||
/// \note Only Actor targets are supported at the moment.
|
/// \note Only Actor targets are supported at the moment.
|
||||||
float getHitDistance(const osg::Vec3f& point, const MWWorld::ConstPtr& target) const;
|
float getHitDistance(const osg::Vec3f& point, const MWWorld::ConstPtr& target) const override final;
|
||||||
|
|
||||||
struct RayResult
|
|
||||||
{
|
|
||||||
bool mHit;
|
|
||||||
osg::Vec3f mHitPos;
|
|
||||||
osg::Vec3f mHitNormal;
|
|
||||||
MWWorld::Ptr mHitObject;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// @param me Optional, a Ptr to ignore in the list of results. targets are actors to filter for, ignoring all other actors.
|
/// @param me Optional, a Ptr to ignore in the list of results. targets are actors to filter for, ignoring all other actors.
|
||||||
RayResult castRay(const osg::Vec3f &from, const osg::Vec3f &to, const MWWorld::ConstPtr& ignore = MWWorld::ConstPtr(),
|
RayCastingResult castRay(const osg::Vec3f &from, const osg::Vec3f &to, const MWWorld::ConstPtr& ignore = MWWorld::ConstPtr(),
|
||||||
std::vector<MWWorld::Ptr> targets = std::vector<MWWorld::Ptr>(),
|
std::vector<MWWorld::Ptr> targets = std::vector<MWWorld::Ptr>(),
|
||||||
int mask = CollisionType_World|CollisionType_HeightMap|CollisionType_Actor|CollisionType_Door, int group=0xff) const;
|
int mask = CollisionType_World|CollisionType_HeightMap|CollisionType_Actor|CollisionType_Door, int group=0xff) const override final;
|
||||||
|
|
||||||
RayResult castSphere(const osg::Vec3f& from, const osg::Vec3f& to, float radius);
|
RayCastingResult castSphere(const osg::Vec3f& from, const osg::Vec3f& to, float radius) const override final;
|
||||||
|
|
||||||
/// Return true if actor1 can see actor2.
|
/// Return true if actor1 can see actor2.
|
||||||
bool getLineOfSight(const MWWorld::ConstPtr& actor1, const MWWorld::ConstPtr& actor2) const;
|
bool getLineOfSight(const MWWorld::ConstPtr& actor1, const MWWorld::ConstPtr& actor2) const override final;
|
||||||
|
|
||||||
bool isOnGround (const MWWorld::Ptr& actor);
|
bool isOnGround (const MWWorld::Ptr& actor);
|
||||||
|
|
||||||
|
|
41
apps/openmw/mwphysics/raycasting.hpp
Normal file
41
apps/openmw/mwphysics/raycasting.hpp
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#ifndef OPENMW_MWPHYSICS_RAYCASTING_H
|
||||||
|
#define OPENMW_MWPHYSICS_RAYCASTING_H
|
||||||
|
|
||||||
|
#include <osg/Vec3f>
|
||||||
|
|
||||||
|
#include "../mwworld/ptr.hpp"
|
||||||
|
|
||||||
|
#include "collisiontype.hpp"
|
||||||
|
|
||||||
|
namespace MWPhysics
|
||||||
|
{
|
||||||
|
struct RayCastingResult
|
||||||
|
{
|
||||||
|
bool mHit;
|
||||||
|
osg::Vec3f mHitPos;
|
||||||
|
osg::Vec3f mHitNormal;
|
||||||
|
MWWorld::Ptr mHitObject;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RayCastingInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// Get distance from \a point to the collision shape of \a target. Uses a raycast to find where the
|
||||||
|
/// target vector hits the collision shape and then calculates distance from the intersection point.
|
||||||
|
/// This can be used to find out how much nearer we need to move to the target for a "getHitContact" to be successful.
|
||||||
|
/// \note Only Actor targets are supported at the moment.
|
||||||
|
virtual float getHitDistance(const osg::Vec3f& point, const MWWorld::ConstPtr& target) const = 0;
|
||||||
|
|
||||||
|
/// @param me Optional, a Ptr to ignore in the list of results. targets are actors to filter for, ignoring all other actors.
|
||||||
|
virtual RayCastingResult castRay(const osg::Vec3f &from, const osg::Vec3f &to, const MWWorld::ConstPtr& ignore = MWWorld::ConstPtr(),
|
||||||
|
std::vector<MWWorld::Ptr> targets = std::vector<MWWorld::Ptr>(),
|
||||||
|
int mask = CollisionType_World|CollisionType_HeightMap|CollisionType_Actor|CollisionType_Door, int group=0xff) const = 0;
|
||||||
|
|
||||||
|
virtual RayCastingResult castSphere(const osg::Vec3f& from, const osg::Vec3f& to, float radius) const = 0;
|
||||||
|
|
||||||
|
/// Return true if actor1 can see actor2.
|
||||||
|
virtual bool getLineOfSight(const MWWorld::ConstPtr& actor1, const MWWorld::ConstPtr& actor2) const = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -2,11 +2,13 @@
|
||||||
|
|
||||||
#include <osg/Camera>
|
#include <osg/Camera>
|
||||||
|
|
||||||
|
#include <components/misc/mathutil.hpp>
|
||||||
#include <components/sceneutil/positionattitudetransform.hpp>
|
#include <components/sceneutil/positionattitudetransform.hpp>
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
|
@ -16,6 +18,8 @@
|
||||||
#include "../mwmechanics/movement.hpp"
|
#include "../mwmechanics/movement.hpp"
|
||||||
#include "../mwmechanics/npcstats.hpp"
|
#include "../mwmechanics/npcstats.hpp"
|
||||||
|
|
||||||
|
#include "../mwphysics/raycasting.hpp"
|
||||||
|
|
||||||
#include "npcanimation.hpp"
|
#include "npcanimation.hpp"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
|
@ -195,8 +199,9 @@ namespace MWRender
|
||||||
rotateCamera(0.f, osg::DegreesToRadians(3.f * duration), true);
|
rotateCamera(0.f, osg::DegreesToRadians(3.f * duration), true);
|
||||||
|
|
||||||
updateFocalPointOffset(duration);
|
updateFocalPointOffset(duration);
|
||||||
|
updatePosition();
|
||||||
|
|
||||||
float speed = mTrackingPtr.getClass().getSpeed(mTrackingPtr);
|
float speed = mTrackingPtr.getClass().getCurrentSpeed(mTrackingPtr);
|
||||||
speed /= (1.f + speed / 500.f);
|
speed /= (1.f + speed / 500.f);
|
||||||
float maxDelta = 300.f * duration;
|
float maxDelta = 300.f * duration;
|
||||||
mSmoothedSpeed += osg::clampBetween(speed - mSmoothedSpeed, -maxDelta, maxDelta);
|
mSmoothedSpeed += osg::clampBetween(speed - mSmoothedSpeed, -maxDelta, maxDelta);
|
||||||
|
@ -205,11 +210,47 @@ namespace MWRender
|
||||||
updateStandingPreviewMode();
|
updateStandingPreviewMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Camera::updatePosition()
|
||||||
|
{
|
||||||
|
mFocalPointAdjustment = osg::Vec3d();
|
||||||
|
if (isFirstPerson())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const float cameraObstacleLimit = 5.0f;
|
||||||
|
const float focalObstacleLimit = 10.f;
|
||||||
|
|
||||||
|
const auto* rayCasting = MWBase::Environment::get().getWorld()->getRayCasting();
|
||||||
|
|
||||||
|
// Adjust focal point to prevent clipping.
|
||||||
|
osg::Vec3d focal = getFocalPoint();
|
||||||
|
osg::Vec3d focalOffset = getFocalPointOffset();
|
||||||
|
float offsetLen = focalOffset.length();
|
||||||
|
if (offsetLen > 0)
|
||||||
|
{
|
||||||
|
MWPhysics::RayCastingResult result = rayCasting->castSphere(focal - focalOffset, focal, focalObstacleLimit);
|
||||||
|
if (result.mHit)
|
||||||
|
{
|
||||||
|
double adjustmentCoef = -(result.mHitPos + result.mHitNormal * focalObstacleLimit - focal).length() / offsetLen;
|
||||||
|
mFocalPointAdjustment = focalOffset * std::max(-1.0, adjustmentCoef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate camera distance.
|
||||||
|
mCameraDistance = mBaseCameraDistance + getCameraDistanceCorrection();
|
||||||
|
if (mDynamicCameraDistanceEnabled)
|
||||||
|
mCameraDistance = std::min(mCameraDistance, mMaxNextCameraDistance);
|
||||||
|
osg::Vec3d cameraPos;
|
||||||
|
getPosition(focal, cameraPos);
|
||||||
|
MWPhysics::RayCastingResult result = rayCasting->castSphere(focal, cameraPos, cameraObstacleLimit);
|
||||||
|
if (result.mHit)
|
||||||
|
mCameraDistance = (result.mHitPos + result.mHitNormal * cameraObstacleLimit - focal).length();
|
||||||
|
}
|
||||||
|
|
||||||
void Camera::updateStandingPreviewMode()
|
void Camera::updateStandingPreviewMode()
|
||||||
{
|
{
|
||||||
if (!mStandingPreviewAllowed)
|
if (!mStandingPreviewAllowed)
|
||||||
return;
|
return;
|
||||||
float speed = mTrackingPtr.getClass().getSpeed(mTrackingPtr);
|
float speed = mTrackingPtr.getClass().getCurrentSpeed(mTrackingPtr);
|
||||||
bool combat = mTrackingPtr.getClass().isActor() &&
|
bool combat = mTrackingPtr.getClass().isActor() &&
|
||||||
mTrackingPtr.getClass().getCreatureStats(mTrackingPtr).getDrawState() != MWMechanics::DrawState_Nothing;
|
mTrackingPtr.getClass().getCreatureStats(mTrackingPtr).getDrawState() != MWMechanics::DrawState_Nothing;
|
||||||
bool standingStill = speed == 0 && !combat && !mFirstPersonView;
|
bool standingStill = speed == 0 && !combat && !mFirstPersonView;
|
||||||
|
@ -356,12 +397,7 @@ namespace MWRender
|
||||||
|
|
||||||
void Camera::setYaw(float angle)
|
void Camera::setYaw(float angle)
|
||||||
{
|
{
|
||||||
if (angle > osg::PI) {
|
mYaw = Misc::normalizeAngle(angle);
|
||||||
angle -= osg::PI*2;
|
|
||||||
} else if (angle < -osg::PI) {
|
|
||||||
angle += osg::PI*2;
|
|
||||||
}
|
|
||||||
mYaw = angle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Camera::setPitch(float angle)
|
void Camera::setPitch(float angle)
|
||||||
|
@ -378,27 +414,24 @@ namespace MWRender
|
||||||
return mCameraDistance;
|
return mCameraDistance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Camera::updateBaseCameraDistance(float dist, bool adjust)
|
void Camera::adjustCameraDistance(float delta)
|
||||||
{
|
{
|
||||||
if (isFirstPerson())
|
if (!isFirstPerson())
|
||||||
return;
|
{
|
||||||
|
if(isNearest() && delta < 0.f && getMode() != Mode::Preview && getMode() != Mode::Vanity)
|
||||||
|
toggleViewMode();
|
||||||
|
else
|
||||||
|
mBaseCameraDistance = std::min(mCameraDistance - getCameraDistanceCorrection(), mBaseCameraDistance) + delta;
|
||||||
|
}
|
||||||
|
else if (delta > 0.f)
|
||||||
|
{
|
||||||
|
toggleViewMode();
|
||||||
|
mBaseCameraDistance = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (adjust)
|
mIsNearest = mBaseCameraDistance <= mNearest;
|
||||||
dist += std::min(mCameraDistance - getCameraDistanceCorrection(), mBaseCameraDistance);
|
mBaseCameraDistance = osg::clampBetween(mBaseCameraDistance, mNearest, mFurthest);
|
||||||
|
|
||||||
mIsNearest = dist <= mNearest;
|
|
||||||
mBaseCameraDistance = osg::clampBetween(dist, mNearest, mFurthest);
|
|
||||||
Settings::Manager::setFloat("third person camera distance", "Camera", mBaseCameraDistance);
|
Settings::Manager::setFloat("third person camera distance", "Camera", mBaseCameraDistance);
|
||||||
setCameraDistance();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Camera::setCameraDistance(float dist, bool adjust)
|
|
||||||
{
|
|
||||||
if (isFirstPerson())
|
|
||||||
return;
|
|
||||||
if (adjust)
|
|
||||||
dist += mCameraDistance;
|
|
||||||
mCameraDistance = osg::clampBetween(dist, 10.f, mFurthest);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float Camera::getCameraDistanceCorrection() const
|
float Camera::getCameraDistanceCorrection() const
|
||||||
|
@ -414,16 +447,6 @@ namespace MWRender
|
||||||
return pitchCorrection + speedCorrection;
|
return pitchCorrection + speedCorrection;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Camera::setCameraDistance()
|
|
||||||
{
|
|
||||||
mFocalPointAdjustment = osg::Vec3d();
|
|
||||||
if (isFirstPerson())
|
|
||||||
return;
|
|
||||||
mCameraDistance = mBaseCameraDistance + getCameraDistanceCorrection();
|
|
||||||
if (mDynamicCameraDistanceEnabled)
|
|
||||||
mCameraDistance = std::min(mCameraDistance, mMaxNextCameraDistance);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Camera::setAnimation(NpcAnimation *anim)
|
void Camera::setAnimation(NpcAnimation *anim)
|
||||||
{
|
{
|
||||||
mAnimation = anim;
|
mAnimation = anim;
|
||||||
|
@ -511,16 +534,8 @@ namespace MWRender
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mDeferredRotation.x() = -ptr.getRefData().getPosition().rot[0] - mPitch;
|
mDeferredRotation.x() = Misc::normalizeAngle(-ptr.getRefData().getPosition().rot[0] - mPitch);
|
||||||
mDeferredRotation.z() = -ptr.getRefData().getPosition().rot[2] - mYaw;
|
mDeferredRotation.z() = Misc::normalizeAngle(-ptr.getRefData().getPosition().rot[2] - mYaw);
|
||||||
if (mDeferredRotation.x() > osg::PI)
|
|
||||||
mDeferredRotation.x() -= 2 * osg::PI;
|
|
||||||
if (mDeferredRotation.x() < -osg::PI)
|
|
||||||
mDeferredRotation.x() += 2 * osg::PI;
|
|
||||||
if (mDeferredRotation.z() > osg::PI)
|
|
||||||
mDeferredRotation.z() -= 2 * osg::PI;
|
|
||||||
if (mDeferredRotation.z() < -osg::PI)
|
|
||||||
mDeferredRotation.z() += 2 * osg::PI;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,7 @@ namespace MWRender
|
||||||
bool mShowCrosshairInThirdPersonMode;
|
bool mShowCrosshairInThirdPersonMode;
|
||||||
|
|
||||||
void updateFocalPointOffset(float duration);
|
void updateFocalPointOffset(float duration);
|
||||||
|
void updatePosition();
|
||||||
float getCameraDistanceCorrection() const;
|
float getCameraDistanceCorrection() const;
|
||||||
|
|
||||||
osg::ref_ptr<osg::NodeCallback> mUpdateCallback;
|
osg::ref_ptr<osg::NodeCallback> mUpdateCallback;
|
||||||
|
@ -135,17 +136,8 @@ namespace MWRender
|
||||||
|
|
||||||
void update(float duration, bool paused=false);
|
void update(float duration, bool paused=false);
|
||||||
|
|
||||||
/// Set base camera distance for current mode. Don't work on 1st person view.
|
/// Adds distDelta to the camera distance. Switches 3rd/1st person view if distance is less than limit.
|
||||||
/// \param adjust Indicates should distance be adjusted or set.
|
void adjustCameraDistance(float distDelta);
|
||||||
void updateBaseCameraDistance(float dist, bool adjust = false);
|
|
||||||
|
|
||||||
/// Set camera distance for current mode. Don't work on 1st person view.
|
|
||||||
/// \param adjust Indicates should distance be adjusted or set.
|
|
||||||
/// Default distance can be restored with setCameraDistance().
|
|
||||||
void setCameraDistance(float dist, bool adjust = false);
|
|
||||||
|
|
||||||
/// Restore default camera distance and offset for current mode.
|
|
||||||
void setCameraDistance();
|
|
||||||
|
|
||||||
float getCameraDistance() const;
|
float getCameraDistance() const;
|
||||||
|
|
||||||
|
@ -153,7 +145,6 @@ namespace MWRender
|
||||||
|
|
||||||
osg::Vec3d getFocalPoint() const;
|
osg::Vec3d getFocalPoint() const;
|
||||||
osg::Vec3d getFocalPointOffset() const;
|
osg::Vec3d getFocalPointOffset() const;
|
||||||
void adjustFocalPoint(osg::Vec3d adjustment) { mFocalPointAdjustment = adjustment; }
|
|
||||||
|
|
||||||
/// Stores focal and camera world positions in passed arguments
|
/// Stores focal and camera world positions in passed arguments
|
||||||
void getPosition(osg::Vec3d &focal, osg::Vec3d &camera) const;
|
void getPosition(osg::Vec3d &focal, osg::Vec3d &camera) const;
|
||||||
|
|
|
@ -1316,82 +1316,6 @@ namespace MWRender
|
||||||
return mTerrain->getHeightAt(pos);
|
return mTerrain->getHeightAt(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RenderingManager::vanityRotateCamera(const float *rot)
|
|
||||||
{
|
|
||||||
if(!mCamera->isVanityOrPreviewModeEnabled())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
mCamera->rotateCamera(rot[0], rot[2], true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderingManager::setCameraDistance(float dist, bool adjust, bool override)
|
|
||||||
{
|
|
||||||
if(!mCamera->isVanityOrPreviewModeEnabled() && !mCamera->isFirstPerson())
|
|
||||||
{
|
|
||||||
if(mCamera->isNearest() && dist > 0.f)
|
|
||||||
mCamera->toggleViewMode();
|
|
||||||
else if (override)
|
|
||||||
mCamera->updateBaseCameraDistance(-dist / 120.f * 10, adjust);
|
|
||||||
else
|
|
||||||
mCamera->setCameraDistance(-dist / 120.f * 10, adjust);
|
|
||||||
}
|
|
||||||
else if(mCamera->isFirstPerson() && dist < 0.f)
|
|
||||||
{
|
|
||||||
mCamera->toggleViewMode();
|
|
||||||
if (override)
|
|
||||||
mCamera->updateBaseCameraDistance(0.f, false);
|
|
||||||
else
|
|
||||||
mCamera->setCameraDistance(0.f, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderingManager::resetCamera()
|
|
||||||
{
|
|
||||||
mCamera->reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
float RenderingManager::getCameraDistance() const
|
|
||||||
{
|
|
||||||
return mCamera->getCameraDistance();
|
|
||||||
}
|
|
||||||
|
|
||||||
Camera* RenderingManager::getCamera()
|
|
||||||
{
|
|
||||||
return mCamera.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
const osg::Vec3f &RenderingManager::getCameraPosition() const
|
|
||||||
{
|
|
||||||
return mCurrentCameraPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderingManager::togglePOV(bool force)
|
|
||||||
{
|
|
||||||
mCamera->toggleViewMode(force);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderingManager::togglePreviewMode(bool enable)
|
|
||||||
{
|
|
||||||
mCamera->togglePreviewMode(enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RenderingManager::toggleVanityMode(bool enable)
|
|
||||||
{
|
|
||||||
return mCamera->toggleVanityMode(enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderingManager::allowVanityMode(bool allow)
|
|
||||||
{
|
|
||||||
mCamera->allowVanityMode(allow);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderingManager::changeVanityModeScale(float factor)
|
|
||||||
{
|
|
||||||
if(mCamera->isVanityOrPreviewModeEnabled())
|
|
||||||
mCamera->updateBaseCameraDistance(-factor/120.f*10, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderingManager::overrideFieldOfView(float val)
|
void RenderingManager::overrideFieldOfView(float val)
|
||||||
{
|
{
|
||||||
if (mFieldOfViewOverridden != true || mFieldOfViewOverride != val)
|
if (mFieldOfViewOverridden != true || mFieldOfViewOverride != val)
|
||||||
|
|
|
@ -209,17 +209,8 @@ namespace MWRender
|
||||||
float getTerrainHeightAt(const osg::Vec3f& pos);
|
float getTerrainHeightAt(const osg::Vec3f& pos);
|
||||||
|
|
||||||
// camera stuff
|
// camera stuff
|
||||||
bool vanityRotateCamera(const float *rot);
|
Camera* getCamera() { return mCamera.get(); }
|
||||||
void setCameraDistance(float dist, bool adjust, bool override);
|
const osg::Vec3f& getCameraPosition() const { return mCurrentCameraPos; }
|
||||||
void resetCamera();
|
|
||||||
float getCameraDistance() const;
|
|
||||||
Camera* getCamera();
|
|
||||||
const osg::Vec3f& getCameraPosition() const;
|
|
||||||
void togglePOV(bool force = false);
|
|
||||||
void togglePreviewMode(bool enable);
|
|
||||||
bool toggleVanityMode(bool enable);
|
|
||||||
void allowVanityMode(bool allow);
|
|
||||||
void changeVanityModeScale(float factor);
|
|
||||||
|
|
||||||
/// temporarily override the field of view with given value.
|
/// temporarily override the field of view with given value.
|
||||||
void overrideFieldOfView(float val);
|
void overrideFieldOfView(float val);
|
||||||
|
|
|
@ -89,17 +89,21 @@ namespace MWRender
|
||||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||||
osg::Vec3d sideOffset = orient * osg::Vec3d(world->getHalfExtents(mCamera->getTrackingPtr()).x() - 1, 0, 0);
|
osg::Vec3d sideOffset = orient * osg::Vec3d(world->getHalfExtents(mCamera->getTrackingPtr()).x() - 1, 0, 0);
|
||||||
float rayRight = world->getDistToNearestRayHit(
|
float rayRight = world->getDistToNearestRayHit(
|
||||||
playerPos + sideOffset, orient * osg::Vec3d(1, 1, 0), limitToSwitchBack + 1);
|
playerPos + sideOffset, orient * osg::Vec3d(1, 0, 0), limitToSwitchBack + 1);
|
||||||
float rayLeft = world->getDistToNearestRayHit(
|
float rayLeft = world->getDistToNearestRayHit(
|
||||||
playerPos - sideOffset, orient * osg::Vec3d(-1, 1, 0), limitToSwitchBack + 1);
|
playerPos - sideOffset, orient * osg::Vec3d(-1, 0, 0), limitToSwitchBack + 1);
|
||||||
float rayForward = world->getDistToNearestRayHit(
|
float rayRightForward = world->getDistToNearestRayHit(
|
||||||
playerPos, orient * osg::Vec3d(0, 1, 0), limitToSwitchBack + 1);
|
playerPos + sideOffset, orient * osg::Vec3d(1, 3, 0), limitToSwitchBack + 1);
|
||||||
|
float rayLeftForward = world->getDistToNearestRayHit(
|
||||||
|
playerPos - sideOffset, orient * osg::Vec3d(-1, 3, 0), limitToSwitchBack + 1);
|
||||||
|
float distRight = std::min(rayRight, rayRightForward);
|
||||||
|
float distLeft = std::min(rayLeft, rayLeftForward);
|
||||||
|
|
||||||
if (rayLeft < limitToSwitch && rayRight > limitToSwitchBack)
|
if (distLeft < limitToSwitch && distRight > limitToSwitchBack)
|
||||||
mMode = Mode::RightShoulder;
|
mMode = Mode::RightShoulder;
|
||||||
else if (rayRight < limitToSwitch && rayLeft > limitToSwitchBack)
|
else if (distRight < limitToSwitch && distLeft > limitToSwitchBack)
|
||||||
mMode = Mode::LeftShoulder;
|
mMode = Mode::LeftShoulder;
|
||||||
else if (rayLeft > limitToSwitchBack && rayRight > limitToSwitchBack && rayForward > limitToSwitchBack)
|
else if (distRight > limitToSwitchBack && distLeft > limitToSwitchBack)
|
||||||
mMode = mDefaultShoulderIsRight ? Mode::RightShoulder : Mode::LeftShoulder;
|
mMode = mDefaultShoulderIsRight ? Mode::RightShoulder : Mode::LeftShoulder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -735,9 +735,9 @@ namespace MWScript
|
||||||
effects += store.getMagicEffects();
|
effects += store.getMagicEffects();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& effect : effects)
|
for (const auto& activeEffect : effects)
|
||||||
{
|
{
|
||||||
if (effect.first.mId == key && effect.second.getModifier() > 0)
|
if (activeEffect.first.mId == key && activeEffect.second.getModifier() > 0)
|
||||||
{
|
{
|
||||||
runtime.push(1);
|
runtime.push(1);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -149,8 +149,6 @@ namespace MWScript
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int success = 0;
|
int success = 0;
|
||||||
|
|
||||||
const MWWorld::Store<ESM::Script>& scripts = mStore.get<ESM::Script>();
|
|
||||||
|
|
||||||
for (auto& script : mStore.get<ESM::Script>())
|
for (auto& script : mStore.get<ESM::Script>())
|
||||||
{
|
{
|
||||||
if (!std::binary_search (mScriptBlacklist.begin(), mScriptBlacklist.end(),
|
if (!std::binary_search (mScriptBlacklist.begin(), mScriptBlacklist.end(),
|
||||||
|
|
|
@ -194,7 +194,12 @@ namespace MWWorld
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
float Class::getSpeed (const Ptr& ptr) const
|
float Class::getMaxSpeed (const Ptr& ptr) const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Class::getCurrentSpeed (const Ptr& ptr) const
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -183,8 +183,15 @@ namespace MWWorld
|
||||||
///< Return name of the script attached to ptr (default implementation: return an empty
|
///< Return name of the script attached to ptr (default implementation: return an empty
|
||||||
/// string).
|
/// string).
|
||||||
|
|
||||||
virtual float getSpeed (const Ptr& ptr) const;
|
virtual float getWalkSpeed(const Ptr& ptr) const;
|
||||||
///< Return movement speed.
|
virtual float getRunSpeed(const Ptr& ptr) const;
|
||||||
|
virtual float getSwimSpeed(const Ptr& ptr) const;
|
||||||
|
|
||||||
|
/// Return maximal movement speed for the current state.
|
||||||
|
virtual float getMaxSpeed(const Ptr& ptr) const;
|
||||||
|
|
||||||
|
/// Return current movement speed.
|
||||||
|
virtual float getCurrentSpeed(const Ptr& ptr) const;
|
||||||
|
|
||||||
virtual float getJump(const MWWorld::Ptr &ptr) const;
|
virtual float getJump(const MWWorld::Ptr &ptr) const;
|
||||||
///< Return jump velocity (not accounting for movement)
|
///< Return jump velocity (not accounting for movement)
|
||||||
|
@ -193,7 +200,7 @@ namespace MWWorld
|
||||||
///< Return desired movement.
|
///< Return desired movement.
|
||||||
|
|
||||||
virtual osg::Vec3f getRotationVector (const Ptr& ptr) const;
|
virtual osg::Vec3f getRotationVector (const Ptr& ptr) const;
|
||||||
///< Return desired rotations, as euler angles.
|
///< Return desired rotations, as euler angles. Sets getMovementSettings(ptr).mRotation to zero.
|
||||||
|
|
||||||
virtual std::pair<std::vector<int>, bool> getEquipmentSlots (const ConstPtr& ptr) const;
|
virtual std::pair<std::vector<int>, bool> getEquipmentSlots (const ConstPtr& ptr) const;
|
||||||
///< \return first: Return IDs of the slot this object can be equipped in; second: can object
|
///< \return first: Return IDs of the slot this object can be equipped in; second: can object
|
||||||
|
@ -375,12 +382,6 @@ namespace MWWorld
|
||||||
virtual void setBaseAISetting(const std::string& id, MWMechanics::CreatureStats::AiSetting setting, int value) const;
|
virtual void setBaseAISetting(const std::string& id, MWMechanics::CreatureStats::AiSetting setting, int value) const;
|
||||||
|
|
||||||
virtual void modifyBaseInventory(const std::string& actorId, const std::string& itemId, int amount) const;
|
virtual void modifyBaseInventory(const std::string& actorId, const std::string& itemId, int amount) const;
|
||||||
|
|
||||||
virtual float getWalkSpeed(const Ptr& ptr) const;
|
|
||||||
|
|
||||||
virtual float getRunSpeed(const Ptr& ptr) const;
|
|
||||||
|
|
||||||
virtual float getSwimSpeed(const Ptr& ptr) const;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -264,8 +264,11 @@ namespace MWWorld
|
||||||
// To be called when we are done with dynamic record loading
|
// To be called when we are done with dynamic record loading
|
||||||
void checkPlayer();
|
void checkPlayer();
|
||||||
|
|
||||||
|
/// @return The number of instances defined in the base files. Excludes changes from the save file.
|
||||||
int getRefCount(const std::string& id) const;
|
int getRefCount(const std::string& id) const;
|
||||||
|
|
||||||
|
/// Actors with the same ID share spells, abilities, etc.
|
||||||
|
/// @return The shared spell list to use for this actor and whether or not it has already been initialized.
|
||||||
std::pair<std::shared_ptr<MWMechanics::SpellList>, bool> getSpellList(const std::string& id) const;
|
std::pair<std::shared_ptr<MWMechanics::SpellList>, bool> getSpellList(const std::string& id) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -424,7 +424,7 @@ namespace MWWorld
|
||||||
|
|
||||||
// Check for impact
|
// Check for impact
|
||||||
// TODO: use a proper btRigidBody / btGhostObject?
|
// TODO: use a proper btRigidBody / btGhostObject?
|
||||||
MWPhysics::PhysicsSystem::RayResult result = mPhysics->castRay(pos, newPos, caster, targetActors, 0xff, MWPhysics::CollisionType_Projectile);
|
MWPhysics::RayCastingResult result = mPhysics->castRay(pos, newPos, caster, targetActors, 0xff, MWPhysics::CollisionType_Projectile);
|
||||||
|
|
||||||
bool hit = false;
|
bool hit = false;
|
||||||
if (result.mHit)
|
if (result.mHit)
|
||||||
|
@ -500,7 +500,7 @@ namespace MWWorld
|
||||||
|
|
||||||
// Check for impact
|
// Check for impact
|
||||||
// TODO: use a proper btRigidBody / btGhostObject?
|
// TODO: use a proper btRigidBody / btGhostObject?
|
||||||
MWPhysics::PhysicsSystem::RayResult result = mPhysics->castRay(pos, newPos, caster, targetActors, 0xff, MWPhysics::CollisionType_Projectile);
|
MWPhysics::RayCastingResult result = mPhysics->castRay(pos, newPos, caster, targetActors, 0xff, MWPhysics::CollisionType_Projectile);
|
||||||
|
|
||||||
bool underwater = MWBase::Environment::get().getWorld()->isUnderwater(MWMechanics::getPlayer().getCell(), newPos);
|
bool underwater = MWBase::Environment::get().getWorld()->isUnderwater(MWMechanics::getPlayer().getCell(), newPos);
|
||||||
|
|
||||||
|
|
|
@ -248,7 +248,7 @@ namespace MWWorld
|
||||||
setupPlayer();
|
setupPlayer();
|
||||||
|
|
||||||
renderPlayer();
|
renderPlayer();
|
||||||
mRendering->resetCamera();
|
mRendering->getCamera()->reset();
|
||||||
|
|
||||||
// we don't want old weather to persist on a new game
|
// we don't want old weather to persist on a new game
|
||||||
// Note that if reset later, the initial ChangeWeather that the chargen script calls will be lost.
|
// Note that if reset later, the initial ChangeWeather that the chargen script calls will be lost.
|
||||||
|
@ -1736,6 +1736,11 @@ namespace MWWorld
|
||||||
return mNavigator->updateObject(DetourNavigator::ObjectId(object), shapes, object->getCollisionObject()->getWorldTransform());
|
return mNavigator->updateObject(DetourNavigator::ObjectId(object), shapes, object->getCollisionObject()->getWorldTransform());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MWPhysics::RayCastingInterface* World::getRayCasting() const
|
||||||
|
{
|
||||||
|
return mPhysics.get();
|
||||||
|
}
|
||||||
|
|
||||||
bool World::castRay (float x1, float y1, float z1, float x2, float y2, float z2)
|
bool World::castRay (float x1, float y1, float z1, float x2, float y2, float z2)
|
||||||
{
|
{
|
||||||
int mask = MWPhysics::CollisionType_World | MWPhysics::CollisionType_Door;
|
int mask = MWPhysics::CollisionType_World | MWPhysics::CollisionType_Door;
|
||||||
|
@ -1748,7 +1753,7 @@ namespace MWWorld
|
||||||
osg::Vec3f a(x1,y1,z1);
|
osg::Vec3f a(x1,y1,z1);
|
||||||
osg::Vec3f b(x2,y2,z2);
|
osg::Vec3f b(x2,y2,z2);
|
||||||
|
|
||||||
MWPhysics::PhysicsSystem::RayResult result = mPhysics->castRay(a, b, MWWorld::Ptr(), std::vector<MWWorld::Ptr>(), mask);
|
MWPhysics::RayCastingResult result = mPhysics->castRay(a, b, MWWorld::Ptr(), std::vector<MWWorld::Ptr>(), mask);
|
||||||
return result.mHit;
|
return result.mHit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2062,37 +2067,6 @@ namespace MWWorld
|
||||||
|
|
||||||
int nightEye = static_cast<int>(player.getClass().getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::NightEye).getMagnitude());
|
int nightEye = static_cast<int>(player.getClass().getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::NightEye).getMagnitude());
|
||||||
mRendering->setNightEyeFactor(std::min(1.f, (nightEye/100.f)));
|
mRendering->setNightEyeFactor(std::min(1.f, (nightEye/100.f)));
|
||||||
|
|
||||||
auto* camera = mRendering->getCamera();
|
|
||||||
camera->setCameraDistance();
|
|
||||||
if(!mRendering->getCamera()->isFirstPerson())
|
|
||||||
{
|
|
||||||
float cameraObstacleLimit = mRendering->getNearClipDistance() * 2.5f;
|
|
||||||
float focalObstacleLimit = std::max(cameraObstacleLimit, 10.0f);
|
|
||||||
|
|
||||||
// Adjust focal point.
|
|
||||||
osg::Vec3d focal = camera->getFocalPoint();
|
|
||||||
osg::Vec3d focalOffset = camera->getFocalPointOffset();
|
|
||||||
float offsetLen = focalOffset.length();
|
|
||||||
if (offsetLen > 0)
|
|
||||||
{
|
|
||||||
MWPhysics::PhysicsSystem::RayResult result = mPhysics->castSphere(focal - focalOffset, focal, focalObstacleLimit);
|
|
||||||
if (result.mHit)
|
|
||||||
{
|
|
||||||
double adjustmentCoef = -(result.mHitPos + result.mHitNormal * focalObstacleLimit - focal).length() / offsetLen;
|
|
||||||
if (adjustmentCoef < -1)
|
|
||||||
adjustmentCoef = -1;
|
|
||||||
camera->adjustFocalPoint(focalOffset * adjustmentCoef);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adjust camera position.
|
|
||||||
osg::Vec3d cameraPos;
|
|
||||||
camera->getPosition(focal, cameraPos);
|
|
||||||
MWPhysics::PhysicsSystem::RayResult result = mPhysics->castSphere(focal, cameraPos, cameraObstacleLimit);
|
|
||||||
if (result.mHit)
|
|
||||||
mRendering->getCamera()->setCameraDistance((result.mHitPos + result.mHitNormal * cameraObstacleLimit - focal).length(), false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::preloadSpells()
|
void World::preloadSpells()
|
||||||
|
@ -2183,7 +2157,7 @@ namespace MWWorld
|
||||||
|
|
||||||
MWWorld::Ptr World::getFacedObject(float maxDistance, bool ignorePlayer)
|
MWWorld::Ptr World::getFacedObject(float maxDistance, bool ignorePlayer)
|
||||||
{
|
{
|
||||||
const float camDist = mRendering->getCameraDistance();
|
const float camDist = mRendering->getCamera()->getCameraDistance();
|
||||||
maxDistance += camDist;
|
maxDistance += camDist;
|
||||||
MWWorld::Ptr facedObject;
|
MWWorld::Ptr facedObject;
|
||||||
MWRender::RenderingManager::RayResult rayToObject;
|
MWRender::RenderingManager::RayResult rayToObject;
|
||||||
|
@ -2643,7 +2617,7 @@ namespace MWWorld
|
||||||
|
|
||||||
void World::togglePOV(bool force)
|
void World::togglePOV(bool force)
|
||||||
{
|
{
|
||||||
mRendering->togglePOV(force);
|
mRendering->getCamera()->toggleViewMode(force);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool World::isFirstPerson() const
|
bool World::isFirstPerson() const
|
||||||
|
@ -2658,12 +2632,12 @@ namespace MWWorld
|
||||||
|
|
||||||
void World::togglePreviewMode(bool enable)
|
void World::togglePreviewMode(bool enable)
|
||||||
{
|
{
|
||||||
mRendering->togglePreviewMode(enable);
|
mRendering->getCamera()->togglePreviewMode(enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool World::toggleVanityMode(bool enable)
|
bool World::toggleVanityMode(bool enable)
|
||||||
{
|
{
|
||||||
return mRendering->toggleVanityMode(enable);
|
return mRendering->getCamera()->toggleVanityMode(enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::disableDeferredPreviewRotation()
|
void World::disableDeferredPreviewRotation()
|
||||||
|
@ -2678,22 +2652,21 @@ namespace MWWorld
|
||||||
|
|
||||||
void World::allowVanityMode(bool allow)
|
void World::allowVanityMode(bool allow)
|
||||||
{
|
{
|
||||||
mRendering->allowVanityMode(allow);
|
mRendering->getCamera()->allowVanityMode(allow);
|
||||||
}
|
|
||||||
|
|
||||||
void World::changeVanityModeScale(float factor)
|
|
||||||
{
|
|
||||||
mRendering->changeVanityModeScale(factor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool World::vanityRotateCamera(float * rot)
|
bool World::vanityRotateCamera(float * rot)
|
||||||
{
|
{
|
||||||
return mRendering->vanityRotateCamera(rot);
|
if(!mRendering->getCamera()->isVanityOrPreviewModeEnabled())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
mRendering->getCamera()->rotateCamera(rot[0], rot[2], true);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::setCameraDistance(float dist, bool adjust, bool override_)
|
void World::adjustCameraDistance(float dist)
|
||||||
{
|
{
|
||||||
mRendering->setCameraDistance(dist, adjust, override_);
|
mRendering->getCamera()->adjustCameraDistance(dist);
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::setupPlayer()
|
void World::setupPlayer()
|
||||||
|
@ -3166,7 +3139,7 @@ namespace MWWorld
|
||||||
if (includeWater) {
|
if (includeWater) {
|
||||||
collisionTypes |= MWPhysics::CollisionType_Water;
|
collisionTypes |= MWPhysics::CollisionType_Water;
|
||||||
}
|
}
|
||||||
MWPhysics::PhysicsSystem::RayResult result = mPhysics->castRay(from, to, MWWorld::Ptr(), std::vector<MWWorld::Ptr>(), collisionTypes);
|
MWPhysics::RayCastingResult result = mPhysics->castRay(from, to, MWWorld::Ptr(), std::vector<MWWorld::Ptr>(), collisionTypes);
|
||||||
|
|
||||||
if (!result.mHit)
|
if (!result.mHit)
|
||||||
return maxDist;
|
return maxDist;
|
||||||
|
@ -3577,7 +3550,7 @@ namespace MWWorld
|
||||||
actor.getClass().getCreatureStats(actor).getAiSequence().getCombatTargets(targetActors);
|
actor.getClass().getCreatureStats(actor).getAiSequence().getCombatTargets(targetActors);
|
||||||
|
|
||||||
// Check for impact, if yes, handle hit, if not, launch projectile
|
// Check for impact, if yes, handle hit, if not, launch projectile
|
||||||
MWPhysics::PhysicsSystem::RayResult result = mPhysics->castRay(sourcePos, worldPos, actor, targetActors, 0xff, MWPhysics::CollisionType_Projectile);
|
MWPhysics::RayCastingResult result = mPhysics->castRay(sourcePos, worldPos, actor, targetActors, 0xff, MWPhysics::CollisionType_Projectile);
|
||||||
if (result.mHit)
|
if (result.mHit)
|
||||||
MWMechanics::projectileHit(actor, result.mHitObject, bow, projectile, result.mHitPos, attackStrength);
|
MWMechanics::projectileHit(actor, result.mHitObject, bow, projectile, result.mHitPos, attackStrength);
|
||||||
else
|
else
|
||||||
|
@ -4087,8 +4060,11 @@ namespace MWWorld
|
||||||
std::string World::exportSceneGraph(const Ptr &ptr)
|
std::string World::exportSceneGraph(const Ptr &ptr)
|
||||||
{
|
{
|
||||||
std::string file = mUserDataPath + "/openmw.osgt";
|
std::string file = mUserDataPath + "/openmw.osgt";
|
||||||
mRendering->pagingBlacklistObject(mStore.find(ptr.getCellRef().getRefId()), ptr);
|
if (!ptr.isEmpty())
|
||||||
mWorldScene->removeFromPagedRefs(ptr);
|
{
|
||||||
|
mRendering->pagingBlacklistObject(mStore.find(ptr.getCellRef().getRefId()), ptr);
|
||||||
|
mWorldScene->removeFromPagedRefs(ptr);
|
||||||
|
}
|
||||||
mRendering->exportSceneGraph(ptr, file, "Ascii");
|
mRendering->exportSceneGraph(ptr, file, "Ascii");
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
|
@ -516,6 +516,8 @@ namespace MWWorld
|
||||||
|
|
||||||
void updateAnimatedCollisionShape(const Ptr &ptr) override;
|
void updateAnimatedCollisionShape(const Ptr &ptr) override;
|
||||||
|
|
||||||
|
const MWPhysics::RayCastingInterface* getRayCasting() const override;
|
||||||
|
|
||||||
bool castRay (float x1, float y1, float z1, float x2, float y2, float z2, int mask) override;
|
bool castRay (float x1, float y1, float z1, float x2, float y2, float z2, int mask) override;
|
||||||
///< cast a Ray and return true if there is an object in the ray path.
|
///< cast a Ray and return true if there is an object in the ray path.
|
||||||
|
|
||||||
|
@ -641,11 +643,8 @@ namespace MWWorld
|
||||||
bool toggleVanityMode(bool enable) override;
|
bool toggleVanityMode(bool enable) override;
|
||||||
|
|
||||||
void allowVanityMode(bool allow) override;
|
void allowVanityMode(bool allow) override;
|
||||||
|
|
||||||
void changeVanityModeScale(float factor) override;
|
|
||||||
|
|
||||||
bool vanityRotateCamera(float * rot) override;
|
bool vanityRotateCamera(float * rot) override;
|
||||||
void setCameraDistance(float dist, bool adjust = false, bool override = true) override;
|
void adjustCameraDistance(float dist) override;
|
||||||
|
|
||||||
void applyDeferredPreviewRotationToPlayer(float dt) override;
|
void applyDeferredPreviewRotationToPlayer(float dt) override;
|
||||||
void disableDeferredPreviewRotation() override;
|
void disableDeferredPreviewRotation() override;
|
||||||
|
|
27
components/misc/mathutil.hpp
Normal file
27
components/misc/mathutil.hpp
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef MISC_MATHUTIL_H
|
||||||
|
#define MISC_MATHUTIL_H
|
||||||
|
|
||||||
|
#include <osg/Math>
|
||||||
|
#include <osg/Vec2f>
|
||||||
|
|
||||||
|
namespace Misc
|
||||||
|
{
|
||||||
|
|
||||||
|
/// Normalizes given angle to the range [-PI, PI]. E.g. PI*3/2 -> -PI/2.
|
||||||
|
inline double normalizeAngle(double angle)
|
||||||
|
{
|
||||||
|
double fullTurns = angle / (2 * osg::PI) + 0.5;
|
||||||
|
return (fullTurns - floor(fullTurns) - 0.5) * (2 * osg::PI);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Rotates given 2d vector counterclockwise. Angle is in radians.
|
||||||
|
inline osg::Vec2f rotateVec2f(osg::Vec2f vec, float angle)
|
||||||
|
{
|
||||||
|
float s = std::sin(angle);
|
||||||
|
float c = std::cos(angle);
|
||||||
|
return osg::Vec2f(vec.x() * c + vec.y() * -s, vec.x() * s + vec.y() * c);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -26,11 +26,11 @@ enum InterpolationType
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct KeyT {
|
struct KeyT {
|
||||||
T mValue;
|
T mValue;
|
||||||
|
T mInTan; // Only for Quadratic interpolation, and never for QuaternionKeyList
|
||||||
|
T mOutTan; // Only for Quadratic interpolation, and never for QuaternionKeyList
|
||||||
|
|
||||||
// FIXME: Implement Quadratic and TBC interpolation
|
// FIXME: Implement TBC interpolation
|
||||||
/*
|
/*
|
||||||
T mForwardValue; // Only for Quadratic interpolation, and never for QuaternionKeyList
|
|
||||||
T mBackwardValue; // Only for Quadratic interpolation, and never for QuaternionKeyList
|
|
||||||
float mTension; // Only for TBC interpolation
|
float mTension; // Only for TBC interpolation
|
||||||
float mBias; // Only for TBC interpolation
|
float mBias; // Only for TBC interpolation
|
||||||
float mContinuity; // Only for TBC interpolation
|
float mContinuity; // Only for TBC interpolation
|
||||||
|
@ -136,8 +136,8 @@ private:
|
||||||
static void readQuadratic(NIFStream &nif, KeyT<U> &key)
|
static void readQuadratic(NIFStream &nif, KeyT<U> &key)
|
||||||
{
|
{
|
||||||
readValue(nif, key);
|
readValue(nif, key);
|
||||||
/*key.mForwardValue = */(nif.*getValue)();
|
key.mInTan = (nif.*getValue)();
|
||||||
/*key.mBackwardValue = */(nif.*getValue)();
|
key.mOutTan = (nif.*getValue)();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void readQuadratic(NIFStream &nif, KeyT<osg::Quat> &key)
|
static void readQuadratic(NIFStream &nif, KeyT<osg::Quat> &key)
|
||||||
|
|
|
@ -197,7 +197,6 @@ void GeomMorpherController::update(osg::NodeVisitor *nv, osg::Drawable *drawable
|
||||||
float val = 0;
|
float val = 0;
|
||||||
if (!(*it).empty())
|
if (!(*it).empty())
|
||||||
val = it->interpKey(input);
|
val = it->interpKey(input);
|
||||||
val = std::max(0.f, std::min(1.f, val));
|
|
||||||
|
|
||||||
SceneUtil::MorphGeometry::MorphTarget& target = morphGeom->getMorphTarget(i);
|
SceneUtil::MorphGeometry::MorphTarget& target = morphGeom->getMorphTarget(i);
|
||||||
if (target.getWeight() != val)
|
if (target.getWeight() != val)
|
||||||
|
|
|
@ -110,6 +110,24 @@ namespace NifOsg
|
||||||
{
|
{
|
||||||
case Nif::InterpolationType_Constant:
|
case Nif::InterpolationType_Constant:
|
||||||
return fraction > 0.5f ? b.mValue : a.mValue;
|
return fraction > 0.5f ? b.mValue : a.mValue;
|
||||||
|
case Nif::InterpolationType_Quadratic:
|
||||||
|
{
|
||||||
|
// Using a cubic Hermite spline.
|
||||||
|
// b1(t) = 2t^3 - 3t^2 + 1
|
||||||
|
// b2(t) = -2t^3 + 3t^2
|
||||||
|
// b3(t) = t^3 - 2t^2 + t
|
||||||
|
// b4(t) = t^3 - t^2
|
||||||
|
// f(t) = a.mValue * b1(t) + b.mValue * b2(t) + a.mOutTan * b3(t) + b.mInTan * b4(t)
|
||||||
|
const float t = fraction;
|
||||||
|
const float t2 = t * t;
|
||||||
|
const float t3 = t2 * t;
|
||||||
|
const float b1 = 2.f * t3 - 3.f * t2 + 1;
|
||||||
|
const float b2 = -2.f * t3 + 3.f * t2;
|
||||||
|
const float b3 = t3 - 2.f * t2 + t;
|
||||||
|
const float b4 = t3 - t2;
|
||||||
|
return a.mValue * b1 + b.mValue * b2 + a.mOutTan * b3 + b.mInTan * b4;
|
||||||
|
}
|
||||||
|
// TODO: Implement TBC interpolation
|
||||||
default:
|
default:
|
||||||
return a.mValue + ((b.mValue - a.mValue) * fraction);
|
return a.mValue + ((b.mValue - a.mValue) * fraction);
|
||||||
}
|
}
|
||||||
|
@ -120,6 +138,7 @@ namespace NifOsg
|
||||||
{
|
{
|
||||||
case Nif::InterpolationType_Constant:
|
case Nif::InterpolationType_Constant:
|
||||||
return fraction > 0.5f ? b.mValue : a.mValue;
|
return fraction > 0.5f ? b.mValue : a.mValue;
|
||||||
|
// TODO: Implement Quadratic and TBC interpolation
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
osg::Quat result;
|
osg::Quat result;
|
||||||
|
|
|
@ -625,8 +625,8 @@ namespace NifOsg
|
||||||
bool isAnimated = false;
|
bool isAnimated = false;
|
||||||
handleNodeControllers(nifNode, node, animflags, isAnimated);
|
handleNodeControllers(nifNode, node, animflags, isAnimated);
|
||||||
hasAnimatedParents |= isAnimated;
|
hasAnimatedParents |= isAnimated;
|
||||||
// Make sure empty nodes are not optimized away so the physics system can find them.
|
// Make sure empty nodes and animated shapes are not optimized away so the physics system can find them.
|
||||||
if (isAnimated || (hasAnimatedParents && (skipMeshes || hasMarkers)))
|
if (isAnimated || (hasAnimatedParents && ((skipMeshes || hasMarkers) || isGeometry)))
|
||||||
node->setDataVariance(osg::Object::DYNAMIC);
|
node->setDataVariance(osg::Object::DYNAMIC);
|
||||||
|
|
||||||
// LOD and Switch nodes must be wrapped by a transform (the current node) to support transformations properly
|
// LOD and Switch nodes must be wrapped by a transform (the current node) to support transformations properly
|
||||||
|
|
|
@ -749,7 +749,8 @@ MWShadowTechnique::ViewDependentData::ViewDependentData(MWShadowTechnique* vdsm)
|
||||||
_viewDependentShadowMap(vdsm)
|
_viewDependentShadowMap(vdsm)
|
||||||
{
|
{
|
||||||
OSG_INFO<<"ViewDependentData::ViewDependentData()"<<this<<std::endl;
|
OSG_INFO<<"ViewDependentData::ViewDependentData()"<<this<<std::endl;
|
||||||
_stateset = new osg::StateSet;
|
for (auto& perFrameStateset : _stateset)
|
||||||
|
perFrameStateset = new osg::StateSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MWShadowTechnique::ViewDependentData::releaseGLObjects(osg::State* state) const
|
void MWShadowTechnique::ViewDependentData::releaseGLObjects(osg::State* state) const
|
||||||
|
@ -1343,9 +1344,7 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv)
|
||||||
std::string validRegionUniformName = "validRegionMatrix" + std::to_string(sm_i);
|
std::string validRegionUniformName = "validRegionMatrix" + std::to_string(sm_i);
|
||||||
osg::ref_ptr<osg::Uniform> validRegionUniform;
|
osg::ref_ptr<osg::Uniform> validRegionUniform;
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(_accessUniformsAndProgramMutex);
|
for (auto uniform : _uniforms[cv.getTraversalNumber() % 2])
|
||||||
|
|
||||||
for (auto uniform : _uniforms)
|
|
||||||
{
|
{
|
||||||
if (uniform->getName() == validRegionUniformName)
|
if (uniform->getName() == validRegionUniformName)
|
||||||
validRegionUniform = uniform;
|
validRegionUniform = uniform;
|
||||||
|
@ -1354,7 +1353,7 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv)
|
||||||
if (!validRegionUniform)
|
if (!validRegionUniform)
|
||||||
{
|
{
|
||||||
validRegionUniform = new osg::Uniform(osg::Uniform::FLOAT_MAT4, validRegionUniformName);
|
validRegionUniform = new osg::Uniform(osg::Uniform::FLOAT_MAT4, validRegionUniformName);
|
||||||
_uniforms.push_back(validRegionUniform);
|
_uniforms[cv.getTraversalNumber() % 2].push_back(validRegionUniform);
|
||||||
}
|
}
|
||||||
|
|
||||||
validRegionUniform->set(validRegionMatrix);
|
validRegionUniform->set(validRegionMatrix);
|
||||||
|
@ -1400,7 +1399,7 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv)
|
||||||
|
|
||||||
if (numValidShadows>0)
|
if (numValidShadows>0)
|
||||||
{
|
{
|
||||||
decoratorStateGraph->setStateSet(selectStateSetForRenderingShadow(*vdd));
|
decoratorStateGraph->setStateSet(selectStateSetForRenderingShadow(*vdd, cv.getTraversalNumber()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// OSG_NOTICE<<"End of shadow setup Projection matrix "<<*cv.getProjectionMatrix()<<std::endl;
|
// OSG_NOTICE<<"End of shadow setup Projection matrix "<<*cv.getProjectionMatrix()<<std::endl;
|
||||||
|
@ -1467,8 +1466,6 @@ void MWShadowTechnique::createShaders()
|
||||||
|
|
||||||
unsigned int _baseTextureUnit = 0;
|
unsigned int _baseTextureUnit = 0;
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(_accessUniformsAndProgramMutex);
|
|
||||||
|
|
||||||
_shadowCastingStateSet = new osg::StateSet;
|
_shadowCastingStateSet = new osg::StateSet;
|
||||||
|
|
||||||
ShadowSettings* settings = getShadowedScene()->getShadowSettings();
|
ShadowSettings* settings = getShadowedScene()->getShadowSettings();
|
||||||
|
@ -1501,15 +1498,20 @@ void MWShadowTechnique::createShaders()
|
||||||
_shadowCastingStateSet->setMode(GL_POLYGON_OFFSET_FILL, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
_shadowCastingStateSet->setMode(GL_POLYGON_OFFSET_FILL, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||||
|
|
||||||
|
|
||||||
_uniforms.clear();
|
|
||||||
osg::ref_ptr<osg::Uniform> baseTextureSampler = new osg::Uniform("baseTexture",(int)_baseTextureUnit);
|
osg::ref_ptr<osg::Uniform> baseTextureSampler = new osg::Uniform("baseTexture",(int)_baseTextureUnit);
|
||||||
_uniforms.push_back(baseTextureSampler.get());
|
|
||||||
|
|
||||||
osg::ref_ptr<osg::Uniform> baseTextureUnit = new osg::Uniform("baseTextureUnit",(int)_baseTextureUnit);
|
osg::ref_ptr<osg::Uniform> baseTextureUnit = new osg::Uniform("baseTextureUnit",(int)_baseTextureUnit);
|
||||||
_uniforms.push_back(baseTextureUnit.get());
|
|
||||||
|
|
||||||
_uniforms.push_back(new osg::Uniform("maximumShadowMapDistance", (float)settings->getMaximumShadowMapDistance()));
|
osg::ref_ptr<osg::Uniform> maxDistance = new osg::Uniform("maximumShadowMapDistance", (float)settings->getMaximumShadowMapDistance());
|
||||||
_uniforms.push_back(new osg::Uniform("shadowFadeStart", (float)_shadowFadeStart));
|
osg::ref_ptr<osg::Uniform> fadeStart = new osg::Uniform("shadowFadeStart", (float)_shadowFadeStart);
|
||||||
|
|
||||||
|
for (auto& perFrameUniformList : _uniforms)
|
||||||
|
{
|
||||||
|
perFrameUniformList.clear();
|
||||||
|
perFrameUniformList.push_back(baseTextureSampler);
|
||||||
|
perFrameUniformList.push_back(baseTextureUnit.get());
|
||||||
|
perFrameUniformList.push_back(maxDistance);
|
||||||
|
perFrameUniformList.push_back(fadeStart);
|
||||||
|
}
|
||||||
|
|
||||||
for(unsigned int sm_i=0; sm_i<settings->getNumShadowMapsPerLight(); ++sm_i)
|
for(unsigned int sm_i=0; sm_i<settings->getNumShadowMapsPerLight(); ++sm_i)
|
||||||
{
|
{
|
||||||
|
@ -1517,14 +1519,16 @@ void MWShadowTechnique::createShaders()
|
||||||
std::stringstream sstr;
|
std::stringstream sstr;
|
||||||
sstr<<"shadowTexture"<<sm_i;
|
sstr<<"shadowTexture"<<sm_i;
|
||||||
osg::ref_ptr<osg::Uniform> shadowTextureSampler = new osg::Uniform(sstr.str().c_str(),(int)(settings->getBaseShadowTextureUnit()+sm_i));
|
osg::ref_ptr<osg::Uniform> shadowTextureSampler = new osg::Uniform(sstr.str().c_str(),(int)(settings->getBaseShadowTextureUnit()+sm_i));
|
||||||
_uniforms.push_back(shadowTextureSampler.get());
|
for (auto& perFrameUniformList : _uniforms)
|
||||||
|
perFrameUniformList.push_back(shadowTextureSampler.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
std::stringstream sstr;
|
std::stringstream sstr;
|
||||||
sstr<<"shadowTextureUnit"<<sm_i;
|
sstr<<"shadowTextureUnit"<<sm_i;
|
||||||
osg::ref_ptr<osg::Uniform> shadowTextureUnit = new osg::Uniform(sstr.str().c_str(),(int)(settings->getBaseShadowTextureUnit()+sm_i));
|
osg::ref_ptr<osg::Uniform> shadowTextureUnit = new osg::Uniform(sstr.str().c_str(),(int)(settings->getBaseShadowTextureUnit()+sm_i));
|
||||||
_uniforms.push_back(shadowTextureUnit.get());
|
for (auto& perFrameUniformList : _uniforms)
|
||||||
|
perFrameUniformList.push_back(shadowTextureUnit.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2974,24 +2978,20 @@ void MWShadowTechnique::cullShadowCastingScene(osgUtil::CullVisitor* cv, osg::Ca
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::StateSet* MWShadowTechnique::selectStateSetForRenderingShadow(ViewDependentData& vdd) const
|
osg::StateSet* MWShadowTechnique::selectStateSetForRenderingShadow(ViewDependentData& vdd, unsigned int traversalNumber) const
|
||||||
{
|
{
|
||||||
OSG_INFO<<" selectStateSetForRenderingShadow() "<<vdd.getStateSet()<<std::endl;
|
OSG_INFO<<" selectStateSetForRenderingShadow() "<<vdd.getStateSet(traversalNumber)<<std::endl;
|
||||||
|
|
||||||
osg::ref_ptr<osg::StateSet> stateset = vdd.getStateSet();
|
osg::ref_ptr<osg::StateSet> stateset = vdd.getStateSet(traversalNumber);
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(_accessUniformsAndProgramMutex);
|
stateset->clear();
|
||||||
|
|
||||||
vdd.getStateSet()->clear();
|
stateset->setTextureAttributeAndModes(0, _fallbackBaseTexture.get(), osg::StateAttribute::ON);
|
||||||
|
|
||||||
vdd.getStateSet()->setTextureAttributeAndModes(0, _fallbackBaseTexture.get(), osg::StateAttribute::ON);
|
for(const auto& uniform : _uniforms[traversalNumber % 2])
|
||||||
|
|
||||||
for(Uniforms::const_iterator itr=_uniforms.begin();
|
|
||||||
itr!=_uniforms.end();
|
|
||||||
++itr)
|
|
||||||
{
|
{
|
||||||
OSG_INFO<<"addUniform("<<(*itr)->getName()<<")"<<std::endl;
|
OSG_INFO<<"addUniform("<<uniform->getName()<<")"<<std::endl;
|
||||||
stateset->addUniform(itr->get());
|
stateset->addUniform(uniform);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_program.valid())
|
if (_program.valid())
|
||||||
|
@ -3047,7 +3047,7 @@ osg::StateSet* MWShadowTechnique::selectStateSetForRenderingShadow(ViewDependent
|
||||||
stateset->setTextureMode(sd._textureUnit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON);
|
stateset->setTextureMode(sd._textureUnit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON);
|
||||||
}
|
}
|
||||||
|
|
||||||
return vdd.getStateSet();
|
return stateset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MWShadowTechnique::resizeGLObjectBuffers(unsigned int /*maxSize*/)
|
void MWShadowTechnique::resizeGLObjectBuffers(unsigned int /*maxSize*/)
|
||||||
|
@ -3104,12 +3104,12 @@ SceneUtil::MWShadowTechnique::DebugHUD::DebugHUD(int numberOfShadowMapsPerLight)
|
||||||
fragmentShader = new osg::Shader(osg::Shader::FRAGMENT, debugFrustumFragmentShaderSource);
|
fragmentShader = new osg::Shader(osg::Shader::FRAGMENT, debugFrustumFragmentShaderSource);
|
||||||
frustumProgram->addShader(fragmentShader);
|
frustumProgram->addShader(fragmentShader);
|
||||||
|
|
||||||
for (int i = 0; i < 2; ++i)
|
for (auto& frustumGeometry : mFrustumGeometries)
|
||||||
{
|
{
|
||||||
mFrustumGeometries.emplace_back(new osg::Geometry());
|
frustumGeometry = new osg::Geometry();
|
||||||
mFrustumGeometries[i]->setCullingActive(false);
|
frustumGeometry->setCullingActive(false);
|
||||||
|
|
||||||
mFrustumGeometries[i]->getOrCreateStateSet()->setAttributeAndModes(frustumProgram, osg::StateAttribute::ON);
|
frustumGeometry->getOrCreateStateSet()->setAttributeAndModes(frustumProgram, osg::StateAttribute::ON);
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::ref_ptr<osg::DrawElementsUShort> frustumDrawElements = new osg::DrawElementsUShort(osg::PrimitiveSet::LINE_STRIP);
|
osg::ref_ptr<osg::DrawElementsUShort> frustumDrawElements = new osg::DrawElementsUShort(osg::PrimitiveSet::LINE_STRIP);
|
||||||
|
@ -3145,12 +3145,14 @@ void SceneUtil::MWShadowTechnique::DebugHUD::draw(osg::ref_ptr<osg::Texture2D> t
|
||||||
// It might be possible to change shadow settings at runtime
|
// It might be possible to change shadow settings at runtime
|
||||||
if (shadowMapNumber > mDebugCameras.size())
|
if (shadowMapNumber > mDebugCameras.size())
|
||||||
addAnotherShadowMap();
|
addAnotherShadowMap();
|
||||||
|
|
||||||
mFrustumUniforms[shadowMapNumber]->set(matrix);
|
|
||||||
|
|
||||||
osg::ref_ptr<osg::StateSet> stateSet = mDebugGeometry[shadowMapNumber]->getOrCreateStateSet();
|
osg::ref_ptr<osg::StateSet> stateSet = new osg::StateSet();
|
||||||
stateSet->setTextureAttributeAndModes(sDebugTextureUnit, texture, osg::StateAttribute::ON);
|
stateSet->setTextureAttributeAndModes(sDebugTextureUnit, texture, osg::StateAttribute::ON);
|
||||||
|
|
||||||
|
auto frustumUniform = mFrustumUniforms[cv.getTraversalNumber() % 2][shadowMapNumber];
|
||||||
|
frustumUniform->set(matrix);
|
||||||
|
stateSet->addUniform(frustumUniform);
|
||||||
|
|
||||||
// Some of these calls may be superfluous.
|
// Some of these calls may be superfluous.
|
||||||
unsigned int traversalMask = cv.getTraversalMask();
|
unsigned int traversalMask = cv.getTraversalMask();
|
||||||
cv.setTraversalMask(mDebugGeometry[shadowMapNumber]->getNodeMask());
|
cv.setTraversalMask(mDebugGeometry[shadowMapNumber]->getNodeMask());
|
||||||
|
@ -3205,6 +3207,6 @@ void SceneUtil::MWShadowTechnique::DebugHUD::addAnotherShadowMap()
|
||||||
mFrustumTransforms[shadowMapNumber]->setCullingActive(false);
|
mFrustumTransforms[shadowMapNumber]->setCullingActive(false);
|
||||||
mDebugCameras[shadowMapNumber]->addChild(mFrustumTransforms[shadowMapNumber]);
|
mDebugCameras[shadowMapNumber]->addChild(mFrustumTransforms[shadowMapNumber]);
|
||||||
|
|
||||||
mFrustumUniforms.push_back(new osg::Uniform(osg::Uniform::FLOAT_MAT4, "transform"));
|
for(auto& uniformVector : mFrustumUniforms)
|
||||||
mFrustumTransforms[shadowMapNumber]->getOrCreateStateSet()->addUniform(mFrustumUniforms[shadowMapNumber]);
|
uniformVector.push_back(new osg::Uniform(osg::Uniform::FLOAT_MAT4, "transform"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#ifndef COMPONENTS_SCENEUTIL_MWSHADOWTECHNIQUE_H
|
#ifndef COMPONENTS_SCENEUTIL_MWSHADOWTECHNIQUE_H
|
||||||
#define COMPONENTS_SCENEUTIL_MWSHADOWTECHNIQUE_H 1
|
#define COMPONENTS_SCENEUTIL_MWSHADOWTECHNIQUE_H 1
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include <osg/Camera>
|
#include <osg/Camera>
|
||||||
|
@ -191,7 +192,7 @@ namespace SceneUtil {
|
||||||
|
|
||||||
ShadowDataList& getShadowDataList() { return _shadowDataList; }
|
ShadowDataList& getShadowDataList() { return _shadowDataList; }
|
||||||
|
|
||||||
osg::StateSet* getStateSet() { return _stateset.get(); }
|
osg::StateSet* getStateSet(unsigned int traversalNumber) { return _stateset[traversalNumber % 2].get(); }
|
||||||
|
|
||||||
virtual void releaseGLObjects(osg::State* = 0) const;
|
virtual void releaseGLObjects(osg::State* = 0) const;
|
||||||
|
|
||||||
|
@ -200,7 +201,7 @@ namespace SceneUtil {
|
||||||
|
|
||||||
MWShadowTechnique* _viewDependentShadowMap;
|
MWShadowTechnique* _viewDependentShadowMap;
|
||||||
|
|
||||||
osg::ref_ptr<osg::StateSet> _stateset;
|
std::array<osg::ref_ptr<osg::StateSet>, 2> _stateset;
|
||||||
|
|
||||||
LightDataList _lightDataList;
|
LightDataList _lightDataList;
|
||||||
ShadowDataList _shadowDataList;
|
ShadowDataList _shadowDataList;
|
||||||
|
@ -230,7 +231,7 @@ namespace SceneUtil {
|
||||||
|
|
||||||
virtual void cullShadowCastingScene(osgUtil::CullVisitor* cv, osg::Camera* camera) const;
|
virtual void cullShadowCastingScene(osgUtil::CullVisitor* cv, osg::Camera* camera) const;
|
||||||
|
|
||||||
virtual osg::StateSet* selectStateSetForRenderingShadow(ViewDependentData& vdd) const;
|
virtual osg::StateSet* selectStateSetForRenderingShadow(ViewDependentData& vdd, unsigned int traversalNumber) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~MWShadowTechnique();
|
virtual ~MWShadowTechnique();
|
||||||
|
@ -247,8 +248,7 @@ namespace SceneUtil {
|
||||||
osg::ref_ptr<osg::Texture2D> _fallbackShadowMapTexture;
|
osg::ref_ptr<osg::Texture2D> _fallbackShadowMapTexture;
|
||||||
|
|
||||||
typedef std::vector< osg::ref_ptr<osg::Uniform> > Uniforms;
|
typedef std::vector< osg::ref_ptr<osg::Uniform> > Uniforms;
|
||||||
mutable std::mutex _accessUniformsAndProgramMutex;
|
std::array<Uniforms, 2> _uniforms;
|
||||||
Uniforms _uniforms;
|
|
||||||
osg::ref_ptr<osg::Program> _program;
|
osg::ref_ptr<osg::Program> _program;
|
||||||
|
|
||||||
bool _enableShadows;
|
bool _enableShadows;
|
||||||
|
@ -282,8 +282,8 @@ namespace SceneUtil {
|
||||||
osg::ref_ptr<osg::Program> mDebugProgram;
|
osg::ref_ptr<osg::Program> mDebugProgram;
|
||||||
std::vector<osg::ref_ptr<osg::Node>> mDebugGeometry;
|
std::vector<osg::ref_ptr<osg::Node>> mDebugGeometry;
|
||||||
std::vector<osg::ref_ptr<osg::Group>> mFrustumTransforms;
|
std::vector<osg::ref_ptr<osg::Group>> mFrustumTransforms;
|
||||||
std::vector<osg::ref_ptr<osg::Uniform>> mFrustumUniforms;
|
std::array<std::vector<osg::ref_ptr<osg::Uniform>>, 2> mFrustumUniforms;
|
||||||
std::vector<osg::ref_ptr<osg::Geometry>> mFrustumGeometries;
|
std::array<osg::ref_ptr<osg::Geometry>, 2> mFrustumGeometries;
|
||||||
};
|
};
|
||||||
|
|
||||||
osg::ref_ptr<DebugHUD> _debugHud;
|
osg::ref_ptr<DebugHUD> _debugHud;
|
||||||
|
|
|
@ -143,6 +143,7 @@ void registerSerializers()
|
||||||
"NifOsg::GeomMorpherController",
|
"NifOsg::GeomMorpherController",
|
||||||
"NifOsg::UpdateMorphGeometry",
|
"NifOsg::UpdateMorphGeometry",
|
||||||
"NifOsg::UVController",
|
"NifOsg::UVController",
|
||||||
|
"NifOsg::VisController",
|
||||||
"NifOsg::NodeIndexHolder",
|
"NifOsg::NodeIndexHolder",
|
||||||
"osgMyGUI::Drawable",
|
"osgMyGUI::Drawable",
|
||||||
"osg::DrawCallback",
|
"osg::DrawCallback",
|
||||||
|
|
|
@ -88,7 +88,37 @@ namespace SDLUtil
|
||||||
{
|
{
|
||||||
SDL_SetWindowSize(mWindow, width, height);
|
SDL_SetWindowSize(mWindow, width, height);
|
||||||
SDL_SetWindowBordered(mWindow, windowBorder ? SDL_TRUE : SDL_FALSE);
|
SDL_SetWindowBordered(mWindow, windowBorder ? SDL_TRUE : SDL_FALSE);
|
||||||
|
|
||||||
|
centerWindow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VideoWrapper::centerWindow()
|
||||||
|
{
|
||||||
|
// Resize breaks the sdl window in some cases; see issue: #5539
|
||||||
|
SDL_Rect rect{};
|
||||||
|
int x = 0;
|
||||||
|
int y = 0;
|
||||||
|
int w = 0;
|
||||||
|
int h = 0;
|
||||||
|
auto index = SDL_GetWindowDisplayIndex(mWindow);
|
||||||
|
SDL_GetDisplayBounds(index, &rect);
|
||||||
|
SDL_GetWindowSize(mWindow, &w, &h);
|
||||||
|
|
||||||
|
x = rect.x;
|
||||||
|
y = rect.y;
|
||||||
|
|
||||||
|
// Center dimensions that do not fill the screen
|
||||||
|
if (w < rect.w)
|
||||||
|
{
|
||||||
|
x = rect.x + rect.w / 2 - w / 2;
|
||||||
|
}
|
||||||
|
if (h < rect.h)
|
||||||
|
{
|
||||||
|
y = rect.y + rect.h / 2 - h / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_SetWindowPosition(mWindow, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,8 @@ namespace SDLUtil
|
||||||
|
|
||||||
void setVideoMode(int width, int height, bool fullscreen, bool windowBorder);
|
void setVideoMode(int width, int height, bool fullscreen, bool windowBorder);
|
||||||
|
|
||||||
|
void centerWindow();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SDL_Window* mWindow;
|
SDL_Window* mWindow;
|
||||||
osg::ref_ptr<osgViewer::Viewer> mViewer;
|
osg::ref_ptr<osgViewer::Viewer> mViewer;
|
||||||
|
|
|
@ -160,7 +160,7 @@ auto switch shoulder
|
||||||
This setting makes difference only in third person mode if 'view over shoulder' is enabled.
|
This setting makes difference only in third person mode if 'view over shoulder' is enabled.
|
||||||
When player is close to an obstacle, automatically switches camera to the shoulder that is farther away from the obstacle.
|
When player is close to an obstacle, automatically switches camera to the shoulder that is farther away from the obstacle.
|
||||||
|
|
||||||
This setting can only be configured by editing the settings configuration file.
|
This setting can be controlled in Advanced tab of the launcher.
|
||||||
|
|
||||||
zoom out when move coef
|
zoom out when move coef
|
||||||
-----------------------
|
-----------------------
|
||||||
|
@ -181,9 +181,10 @@ preview if stand still
|
||||||
:Range: True/False
|
:Range: True/False
|
||||||
:Default: False
|
:Default: False
|
||||||
|
|
||||||
|
Makes difference only in third person mode.
|
||||||
If enabled then the character rotation is not synchonized with the camera rotation while the character doesn't move and not in combat mode.
|
If enabled then the character rotation is not synchonized with the camera rotation while the character doesn't move and not in combat mode.
|
||||||
|
|
||||||
This setting can only be configured by editing the settings configuration file.
|
This setting can be controlled in Advanced tab of the launcher.
|
||||||
|
|
||||||
deferred preview rotation
|
deferred preview rotation
|
||||||
-------------------------
|
-------------------------
|
||||||
|
@ -196,5 +197,5 @@ Makes difference only in third person mode.
|
||||||
If enabled then the character smoothly rotates to the view direction after exiting preview or vanity mode.
|
If enabled then the character smoothly rotates to the view direction after exiting preview or vanity mode.
|
||||||
If disabled then the camera rotates rather than the character.
|
If disabled then the camera rotates rather than the character.
|
||||||
|
|
||||||
This setting can only be configured by editing the settings configuration file.
|
This setting can be controlled in Advanced tab of the launcher.
|
||||||
|
|
||||||
|
|
|
@ -327,7 +327,18 @@ Affects side and diagonal movement. Enabling this setting makes movement more re
|
||||||
|
|
||||||
If disabled then the whole character's body is pointed to the direction of view. Diagonal movement has no special animation and causes sliding.
|
If disabled then the whole character's body is pointed to the direction of view. Diagonal movement has no special animation and causes sliding.
|
||||||
|
|
||||||
If enabled then the character turns lower body to the direction of movement. Upper body is turned partially. Head is always pointed to the direction of view. In combat mode it works only for diagonal movement. In non-combat mode it also changes straight right and straight left movement.
|
If enabled then the character turns lower body to the direction of movement. Upper body is turned partially. Head is always pointed to the direction of view. In combat mode it works only for diagonal movement. In non-combat mode it changes straight right and straight left movement as well. Also turns the whole body up or down when swimming according to the movement direction.
|
||||||
|
|
||||||
|
This setting can be controlled in Advanced tab of the launcher.
|
||||||
|
|
||||||
|
swim upward correction
|
||||||
|
----------------
|
||||||
|
|
||||||
|
:Type: boolean
|
||||||
|
:Range: True/False
|
||||||
|
:Default: False
|
||||||
|
|
||||||
|
Makes player swim a bit upward from the line of sight. Applies only in third person mode. Intended to make simpler swimming without diving.
|
||||||
|
|
||||||
This setting can be controlled in Advanced tab of the launcher.
|
This setting can be controlled in Advanced tab of the launcher.
|
||||||
|
|
||||||
|
@ -336,9 +347,10 @@ swim upward coef
|
||||||
|
|
||||||
:Type: floating point
|
:Type: floating point
|
||||||
:Range: -1.0 to 1.0
|
:Range: -1.0 to 1.0
|
||||||
:Default: 0.0
|
:Default: 0.2
|
||||||
|
|
||||||
Makes player swim a bit upward (or downward in case of negative value) from the line of sight. Intended to make simpler swimming without diving. Recommened range of values is from 0.0 to 0.2.
|
Regulates strength of the "swim upward correction" effect (if enabled).
|
||||||
|
Makes player swim a bit upward (or downward in case of negative value) from the line of sight. Recommened range of values is from 0.0 to 0.25.
|
||||||
|
|
||||||
This setting can only be configured by editing the settings configuration file.
|
This setting can only be configured by editing the settings configuration file.
|
||||||
|
|
||||||
|
|
|
@ -325,8 +325,11 @@ uncapped damage fatigue = false
|
||||||
# Turn lower body to movement direction. 'true' makes diagonal movement more realistic.
|
# Turn lower body to movement direction. 'true' makes diagonal movement more realistic.
|
||||||
turn to movement direction = false
|
turn to movement direction = false
|
||||||
|
|
||||||
# Makes player swim a bit upward (or downward in case of negative value) from the line of sight.
|
# Makes player swim a bit upward from the line of sight.
|
||||||
swim upward coef = 0.0
|
swim upward correction = false
|
||||||
|
|
||||||
|
# Strength of the 'swim upward correction' effect (if enabled).
|
||||||
|
swim upward coef = 0.2
|
||||||
|
|
||||||
# Make the training skills proposed by a trainer based on its base attribute instead of its modified ones
|
# Make the training skills proposed by a trainer based on its base attribute instead of its modified ones
|
||||||
trainers training skills based on base skill = false
|
trainers training skills based on base skill = false
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue