mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-20 07:23:51 +00:00
Merge branch 'master' of https://gitlab.com/madsbuvi/openmw.git into openxr_vr
# Conflicts: # apps/openmw/mwbase/world.hpp # apps/openmw/mwworld/worldimp.cpp # apps/openmw/mwworld/worldimp.hpp
This commit is contained in:
commit
14bb0f0208
244 changed files with 2757 additions and 1224 deletions
40
.travis.yml
40
.travis.yml
|
@ -9,19 +9,15 @@ env:
|
|||
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
|
||||
# via the "travis encrypt" command using the project repo's public key
|
||||
- secure: "jybGzAdUbqt9vWR/GEnRd96BgAi/7Zd1+2HK68j/i/8+/1YH2XxLOy4Jv/DUBhBlJIkxs/Xv8dRcUlFOclZDHX1d/9Qnsqd3oUVkD7k1y7cTOWy9TBQaE/v/kZo3LpzA3xPwwthrb0BvqIbOfIELi5fS5s8ba85WFRg3AX70wWE="
|
||||
cache:
|
||||
ccache: true
|
||||
directories:
|
||||
- ${HOME}/.ccache
|
||||
cache: ccache
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- sourceline: 'ppa:openmw/openmw'
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-xenial-7
|
||||
packages: [
|
||||
# Dev
|
||||
cmake, clang-7, clang-tools-7, gcc-8, g++-8, ccache,
|
||||
cmake, clang-tools, gcc-9, g++-9, ccache,
|
||||
# Boost
|
||||
libboost-filesystem-dev, libboost-iostreams-dev, libboost-program-options-dev, libboost-system-dev,
|
||||
# FFmpeg
|
||||
|
@ -45,50 +41,51 @@ matrix:
|
|||
os: osx
|
||||
osx_image: xcode10.2
|
||||
if: branch != coverity_scan
|
||||
- name: OpenMW (all) on Ubuntu Xenial GCC-5
|
||||
- name: OpenMW (all) on Ubuntu Bionic GCC-7
|
||||
os: linux
|
||||
dist: xenial
|
||||
dist: bionic
|
||||
sudo: required
|
||||
if: branch != coverity_scan
|
||||
- name: OpenMW (all) on Ubuntu Xenial GCC-8
|
||||
- name: OpenMW (all) on Ubuntu Bionic GCC-9
|
||||
os: linux
|
||||
dist: xenial
|
||||
dist: bionic
|
||||
sudo: required
|
||||
env:
|
||||
- MATRIX_EVAL="CC=gcc-8 && CXX=g++-8"
|
||||
- MATRIX_EVAL="CC=gcc-9 && CXX=g++-9"
|
||||
if: branch != coverity_scan
|
||||
- name: OpenMW (openmw) on Ubuntu Xenial Clang-7 with Static Analysis
|
||||
- name: OpenMW (openmw) on Ubuntu Bionic Clang-6 with Static Analysis
|
||||
os: linux
|
||||
dist: xenial
|
||||
dist: bionic
|
||||
sudo: required
|
||||
env:
|
||||
- MATRIX_EVAL="CC=clang-7 && CXX=clang++-7"
|
||||
- ANALYZE="scan-build-7 --force-analyze-debug-code --use-cc clang-7 --use-c++ clang++-7"
|
||||
- MATRIX_EVAL="CC=clang && CXX=clang++"
|
||||
- ANALYZE="scan-build --force-analyze-debug-code --use-cc clang --use-c++ clang++"
|
||||
- BUILD_OPENMW_CS="OFF"
|
||||
if: branch != coverity_scan
|
||||
compiler: clang
|
||||
- name: OpenMW (openmw-cs) on Ubuntu Xenial Clang-7 with Static Analysis
|
||||
- name: OpenMW (openmw-cs) on Ubuntu Bionic Clang-6 with Static Analysis
|
||||
os: linux
|
||||
dist: xenial
|
||||
dist: bionic
|
||||
sudo: required
|
||||
env:
|
||||
- MATRIX_EVAL="CC=clang-7 && CXX=clang++-7"
|
||||
- ANALYZE="scan-build-7 --force-analyze-debug-code --use-cc clang-7 --use-c++ clang++-7"
|
||||
- MATRIX_EVAL="CC=clang && CXX=clang++"
|
||||
- ANALYZE="scan-build --force-analyze-debug-code --use-cc clang --use-c++ clang++"
|
||||
- BUILD_OPENMW="OFF"
|
||||
if: branch != coverity_scan
|
||||
compiler: clang
|
||||
- name: OpenMW Components Coverity Scan
|
||||
os: linux
|
||||
dist: xenial
|
||||
dist: bionic
|
||||
sudo: required
|
||||
if: branch = coverity_scan
|
||||
# allow_failures:
|
||||
# - name: OpenMW (openmw) on Ubuntu Xenial Clang-7 with Static Analysis
|
||||
# - name: OpenMW (openmw) on Ubuntu Bionic Clang-6 with Static Analysis
|
||||
|
||||
before_install:
|
||||
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then eval "${MATRIX_EVAL}"; fi
|
||||
- if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then ./CI/before_install.${TRAVIS_OS_NAME}.sh; fi
|
||||
before_script:
|
||||
- ccache -z
|
||||
- if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then ./CI/before_script.${TRAVIS_OS_NAME}.sh; fi
|
||||
script:
|
||||
- cd ./build
|
||||
|
@ -98,6 +95,7 @@ script:
|
|||
- if [ "${COVERITY_SCAN_BRANCH}" != 1 ] && [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi
|
||||
- if [ "${COVERITY_SCAN_BRANCH}" != 1 ] && [ "${TRAVIS_OS_NAME}" = "linux" ]; then cd .. && ./CI/check_tabs.sh; fi
|
||||
- cd "${TRAVIS_BUILD_DIR}"
|
||||
- ccache -s
|
||||
deploy:
|
||||
provider: script
|
||||
script: ./CI/deploy.osx.sh
|
||||
|
|
|
@ -74,6 +74,7 @@ Programmers
|
|||
Fil Krynicki (filkry)
|
||||
Finbar Crago (finbar-crago)
|
||||
Florian Weber (Florianjw)
|
||||
Frédéric Chardon (fr3dz10)
|
||||
Gaëtan Dezeiraud (Brouilles)
|
||||
Gašper Sedej
|
||||
Gijsbert ter Horst (Ghostbird)
|
||||
|
@ -87,6 +88,7 @@ Programmers
|
|||
Jacob Essex (Yacoby)
|
||||
Jake Westrip (16bitint)
|
||||
James Carty (MrTopCat)
|
||||
James Moore (moore.work)
|
||||
James Stephens (james-h-stephens)
|
||||
Jan-Peter Nilsson (peppe)
|
||||
Jan Borsodi (am0s)
|
||||
|
|
21
CHANGELOG.md
21
CHANGELOG.md
|
@ -23,6 +23,7 @@
|
|||
Bug #3977: Non-ASCII characters in object ID's are not supported
|
||||
Bug #4009: Launcher does not show data files on the first run after installing
|
||||
Bug #4077: Enchanted items are not recharged if they are not in the player's inventory
|
||||
Bug #4141: PCSkipEquip isn't set to 1 when reading books/scrolls
|
||||
Bug #4202: Open .omwaddon files without needing toopen openmw-cs first
|
||||
Bug #4240: Ash storm origin coordinates and hand shielding animation behavior are incorrect
|
||||
Bug #4262: Rain settings are hardcoded
|
||||
|
@ -36,10 +37,13 @@
|
|||
Bug #4411: Reloading a saved game while falling prevents damage in some cases
|
||||
Bug #4449: Value returned by GetWindSpeed is incorrect
|
||||
Bug #4456: AiActivate should not be cancelled after target activation
|
||||
Bug #4493: If the setup doesn't find what it is expecting, it fails silently and displays the requester again instead of letting the user know what wasn't found.
|
||||
Bug #4523: "player->ModCurrentFatigue -0.001" in global script does not cause the running player to fall
|
||||
Bug #4540: Rain delay when exiting water
|
||||
Bug #4594: Actors without AI packages don't use Hello dialogue
|
||||
Bug #4598: Script parser does not support non-ASCII characters
|
||||
Bug #4600: Crash when no sound output is available or --no-sound is used.
|
||||
Bug #4601: Filtering referenceables by gender is broken
|
||||
Bug #4639: Black screen after completing first mages guild mission + training
|
||||
Bug #4650: Focus is lost after pressing ESC in confirmation dialog inside savegame dialog
|
||||
Bug #4680: Heap corruption on faulty esp
|
||||
|
@ -192,9 +196,19 @@
|
|||
Bug #5239: OpenMW-CS does not support non-ASCII characters in path names
|
||||
Bug #5241: On-self absorb spells cannot be detected
|
||||
Bug #5242: ExplodeSpell behavior differs from Cast behavior
|
||||
Bug #5246: Water ripples persist after cell change
|
||||
Bug #5249: Wandering NPCs start walking too soon after they hello
|
||||
Bug #5250: Creatures display shield ground mesh instead of shield body part
|
||||
Bug #5255: "GetTarget, player" doesn't return 1 during NPC hello
|
||||
Bug #5261: Creatures can sometimes become stuck playing idles and never wander again
|
||||
Bug #5264: "Damage Fatigue" Magic Effect Can Bring Fatigue below 0
|
||||
Bug #5269: Editor: Cell lighting in resaved cleaned content files is corrupted
|
||||
Bug #5278: Console command Show doesn't fall back to global variable after local var not found
|
||||
Bug #5300: NPCs don't switch from torch to shield when starting combat
|
||||
Bug #5308: World map copying makes save loading much slower
|
||||
Bug #5313: Node properties of identical type are not applied in the correct order
|
||||
Bug #5326: Formatting issues in the settings.cfg
|
||||
Bug #5328: Skills aren't properly reset for dead actors
|
||||
Feature #1774: Handle AvoidNode
|
||||
Feature #2229: Improve pathfinding AI
|
||||
Feature #3025: Analogue gamepad movement controls
|
||||
|
@ -215,9 +229,11 @@
|
|||
Feature #4544: Actors movement deceleration
|
||||
Feature #4673: Weapon sheathing
|
||||
Feature #4675: Support for NiRollController
|
||||
Feature #4708: Radial fog support
|
||||
Feature #4730: Native animated containers support
|
||||
Feature #4784: Launcher: Duplicate Content Lists
|
||||
Feature #4812: Support NiSwitchNode
|
||||
Feature #4831: Item search in the player's inventory
|
||||
Feature #4836: Daytime node switch
|
||||
Feature #4840: Editor: Transient terrain change support
|
||||
Feature #4859: Make water reflections more configurable
|
||||
|
@ -240,6 +256,7 @@
|
|||
Feature #5091: Human-readable light source duration
|
||||
Feature #5094: Unix like console hotkeys
|
||||
Feature #5098: Allow user controller bindings
|
||||
Feature #5114: Refresh launcher mod list
|
||||
Feature #5121: Handle NiTriStrips and NiTriStripsData
|
||||
Feature #5122: Use magic glow for enchanted arrows
|
||||
Feature #5131: Custom skeleton bones
|
||||
|
@ -247,9 +264,13 @@
|
|||
Feature #5146: Safe Dispose corpse
|
||||
Feature #5147: Show spell magicka cost in spell buying window
|
||||
Feature #5170: Editor: Land shape editing, land selection
|
||||
Feature #5172: Editor: Delete instances/references with keypress in scene window
|
||||
Feature #5193: Weapon sheathing
|
||||
Feature #5219: Impelement TestCells console command
|
||||
Feature #5224: Handle NiKeyframeController for NiTriShape
|
||||
Feature #5274: Editor: Keyboard shortcut to drop objects to ground/obstacle in scene view
|
||||
Feature #5304: Morrowind-style bump-mapping
|
||||
Feature #5314: Ingredient filter in the alchemy window
|
||||
Task #4686: Upgrade media decoder to a more current FFmpeg API
|
||||
Task #4695: Optimize Distant Terrain memory consumption
|
||||
Task #4789: Optimize cell transitions
|
||||
|
|
|
@ -42,6 +42,8 @@ New Editor Features:
|
|||
- "Faction Ranks" table for "Faction" records (#4209)
|
||||
- Changes to height editing can be cancelled without changes to data (press esc to cancel) (#4840)
|
||||
- Land heightmap/shape editing and vertex selection (#5170)
|
||||
- Deleting instances with a keypress (#5172)
|
||||
- Dropping objects with keyboard shortcuts (#5274)
|
||||
|
||||
Bug Fixes:
|
||||
- The Mouse Wheel can now be used for key bindings (#2679)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash -ex
|
||||
|
||||
sudo ln -sf /usr/bin/clang-7 /usr/local/bin/clang
|
||||
sudo ln -sf /usr/bin/clang++-7 /usr/local/bin/clang++
|
||||
#sudo ln -sf /usr/bin/clang-6 /usr/local/bin/clang
|
||||
#sudo ln -sf /usr/bin/clang++-6 /usr/local/bin/clang++
|
||||
|
|
|
@ -7,9 +7,7 @@ GOOGLETEST_DIR="$(pwd)/googletest/build"
|
|||
|
||||
mkdir build
|
||||
cd build
|
||||
export CODE_COVERAGE=1
|
||||
|
||||
if [[ "${CC}" =~ "clang" ]]; then export CODE_COVERAGE=0; fi
|
||||
if [[ -z "${BUILD_OPENMW}" ]]; then export BUILD_OPENMW=ON; fi
|
||||
if [[ -z "${BUILD_OPENMW_CS}" ]]; then export BUILD_OPENMW_CS=ON; fi
|
||||
|
||||
|
@ -28,7 +26,6 @@ ${ANALYZE} cmake \
|
|||
-DBUILD_WIZARD=${BUILD_OPENMW_CS} \
|
||||
-DBUILD_NIFTEST=${BUILD_OPENMW_CS} \
|
||||
-DBUILD_MYGUI_PLUGIN=${BUILD_OPENMW_CS} \
|
||||
-DBUILD_WITH_CODE_COVERAGE=${CODE_COVERAGE} \
|
||||
-DBUILD_UNITTESTS=1 \
|
||||
-DUSE_SYSTEM_TINYXML=1 \
|
||||
-DDESIRED_QT_VERSION=5 \
|
||||
|
|
|
@ -421,16 +421,16 @@ if [ -z $SKIP_DOWNLOAD ]; then
|
|||
fi
|
||||
|
||||
download "Qt 5.7.0" \
|
||||
"https://download.qt.io/archive/qt/5.7/5.7.0/qt-opensource-windows-x86-msvc${MSVC_YEAR}${QT_SUFFIX}-5.7.0.exe" \
|
||||
"https://download.qt.io/new_archive/qt/5.7/5.7.0/qt-opensource-windows-x86-msvc${MSVC_YEAR}${QT_SUFFIX}-5.7.0.exe" \
|
||||
"qt-5.7.0-msvc${MSVC_YEAR}-win${BITS}.exe" \
|
||||
"https://www.lysator.liu.se/~ace/OpenMW/deps/qt-5-install.qs" \
|
||||
"qt-5-install.qs"
|
||||
fi
|
||||
|
||||
# SDL2
|
||||
download "SDL 2.0.7" \
|
||||
"https://www.libsdl.org/release/SDL2-devel-2.0.7-VC.zip" \
|
||||
"SDL2-2.0.7.zip"
|
||||
download "SDL 2.0.12" \
|
||||
"https://www.libsdl.org/release/SDL2-devel-2.0.12-VC.zip" \
|
||||
"SDL2-2.0.12.zip"
|
||||
|
||||
# Google test and mock
|
||||
if [ ! -z $TEST_FRAMEWORK ]; then
|
||||
|
@ -697,16 +697,16 @@ fi
|
|||
cd $DEPS
|
||||
echo
|
||||
# SDL2
|
||||
printf "SDL 2.0.7... "
|
||||
printf "SDL 2.0.12... "
|
||||
{
|
||||
if [ -d SDL2-2.0.7 ]; then
|
||||
if [ -d SDL2-2.0.12 ]; then
|
||||
printf "Exists. "
|
||||
elif [ -z $SKIP_EXTRACT ]; then
|
||||
rm -rf SDL2-2.0.7
|
||||
eval 7z x -y SDL2-2.0.7.zip $STRIP
|
||||
rm -rf SDL2-2.0.12
|
||||
eval 7z x -y SDL2-2.0.12.zip $STRIP
|
||||
fi
|
||||
export SDL2DIR="$(real_pwd)/SDL2-2.0.7"
|
||||
add_runtime_dlls "$(pwd)/SDL2-2.0.7/lib/x${ARCHSUFFIX}/SDL2.dll"
|
||||
export SDL2DIR="$(real_pwd)/SDL2-2.0.12"
|
||||
add_runtime_dlls "$(pwd)/SDL2-2.0.12/lib/x${ARCHSUFFIX}/SDL2.dll"
|
||||
echo Done.
|
||||
}
|
||||
cd $DEPS
|
||||
|
|
|
@ -534,10 +534,18 @@ void Record<ESM::Cell>::print()
|
|||
if (mData.mData.mFlags & ESM::Cell::Interior &&
|
||||
!(mData.mData.mFlags & ESM::Cell::QuasiEx))
|
||||
{
|
||||
std::cout << " Ambient Light Color: " << mData.mAmbi.mAmbient << std::endl;
|
||||
std::cout << " Sunlight Color: " << mData.mAmbi.mSunlight << std::endl;
|
||||
std::cout << " Fog Color: " << mData.mAmbi.mFog << std::endl;
|
||||
std::cout << " Fog Density: " << mData.mAmbi.mFogDensity << std::endl;
|
||||
if (mData.hasAmbient())
|
||||
{
|
||||
// TODO: see if we can change the integer representation to something more sensible
|
||||
std::cout << " Ambient Light Color: " << mData.mAmbi.mAmbient << std::endl;
|
||||
std::cout << " Sunlight Color: " << mData.mAmbi.mSunlight << std::endl;
|
||||
std::cout << " Fog Color: " << mData.mAmbi.mFog << std::endl;
|
||||
std::cout << " Fog Density: " << mData.mAmbi.mFogDensity << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << " No Ambient Information" << std::endl;
|
||||
}
|
||||
std::cout << " Water Level: " << mData.mWater << std::endl;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -89,6 +89,7 @@ bool Launcher::AdvancedPage::loadSettings()
|
|||
loadSettingBool(weaponSheathingCheckBox, "weapon sheathing", "Game");
|
||||
loadSettingBool(shieldSheathingCheckBox, "shield sheathing", "Game");
|
||||
}
|
||||
loadSettingBool(uncappedDamageFatigueCheckBox, "uncapped damage fatigue", "Game");
|
||||
|
||||
// Input Settings
|
||||
loadSettingBool(grabCursorCheckBox, "grab cursor", "Input");
|
||||
|
@ -152,6 +153,7 @@ void Launcher::AdvancedPage::saveSettings()
|
|||
saveSettingBool(animSourcesCheckBox, "use additional anim sources", "Game");
|
||||
saveSettingBool(weaponSheathingCheckBox, "weapon sheathing", "Game");
|
||||
saveSettingBool(shieldSheathingCheckBox, "shield sheathing", "Game");
|
||||
saveSettingBool(uncappedDamageFatigueCheckBox, "uncapped damage fatigue", "Game");
|
||||
|
||||
// Input Settings
|
||||
saveSettingBool(grabCursorCheckBox, "grab cursor", "Input");
|
||||
|
|
|
@ -62,10 +62,13 @@ void Launcher::DataFilesPage::buildView()
|
|||
{
|
||||
ui.verticalLayout->insertWidget (0, mSelector->uiWidget());
|
||||
|
||||
QToolButton * refreshButton = mSelector->refreshButton();
|
||||
|
||||
//tool buttons
|
||||
ui.newProfileButton->setToolTip ("Create a new Content List");
|
||||
ui.cloneProfileButton->setToolTip ("Clone the current Content List");
|
||||
ui.deleteProfileButton->setToolTip ("Delete an existing Content List");
|
||||
refreshButton->setToolTip("Refresh Data Files");
|
||||
|
||||
//combo box
|
||||
ui.profilesComboBox->addItem(mDefaultContentListName);
|
||||
|
@ -76,6 +79,7 @@ void Launcher::DataFilesPage::buildView()
|
|||
ui.newProfileButton->setDefaultAction (ui.newProfileAction);
|
||||
ui.cloneProfileButton->setDefaultAction (ui.cloneProfileAction);
|
||||
ui.deleteProfileButton->setDefaultAction (ui.deleteProfileAction);
|
||||
refreshButton->setDefaultAction(ui.refreshDataFilesAction);
|
||||
|
||||
//establish connections
|
||||
connect (ui.profilesComboBox, SIGNAL (currentIndexChanged(int)),
|
||||
|
@ -86,6 +90,8 @@ void Launcher::DataFilesPage::buildView()
|
|||
|
||||
connect (ui.profilesComboBox, SIGNAL (signalProfileChanged(QString, QString)),
|
||||
this, SLOT (slotProfileChangedByUser(QString, QString)));
|
||||
|
||||
connect(ui.refreshDataFilesAction, SIGNAL(triggered()),this, SLOT(slotRefreshButtonClicked()));
|
||||
}
|
||||
|
||||
bool Launcher::DataFilesPage::loadSettings()
|
||||
|
@ -114,6 +120,8 @@ void Launcher::DataFilesPage::populateFileViews(const QString& contentModelName)
|
|||
if (!mDataLocal.isEmpty())
|
||||
paths.insert(0, mDataLocal);
|
||||
|
||||
mSelector->clearFiles();
|
||||
|
||||
for (const QString &path : paths)
|
||||
mSelector->addFiles(path);
|
||||
|
||||
|
@ -167,7 +175,16 @@ QStringList Launcher::DataFilesPage::selectedFilePaths()
|
|||
QStringList filePaths;
|
||||
for (const ContentSelectorModel::EsmFile *item : items)
|
||||
{
|
||||
filePaths.append(item->filePath());
|
||||
QFile file(item->filePath());
|
||||
|
||||
if(file.exists())
|
||||
{
|
||||
filePaths.append(item->filePath());
|
||||
}
|
||||
else
|
||||
{
|
||||
slotRefreshButtonClicked();
|
||||
}
|
||||
}
|
||||
return filePaths;
|
||||
}
|
||||
|
@ -221,6 +238,18 @@ void Launcher::DataFilesPage::slotProfileDeleted (const QString &item)
|
|||
removeProfile (item);
|
||||
}
|
||||
|
||||
void Launcher::DataFilesPage:: refreshDataFilesView ()
|
||||
{
|
||||
QString currentProfile = ui.profilesComboBox->currentText();
|
||||
saveSettings(currentProfile);
|
||||
populateFileViews(currentProfile);
|
||||
}
|
||||
|
||||
void Launcher::DataFilesPage::slotRefreshButtonClicked ()
|
||||
{
|
||||
refreshDataFilesView();
|
||||
}
|
||||
|
||||
void Launcher::DataFilesPage::slotProfileChangedByUser(const QString &previous, const QString ¤t)
|
||||
{
|
||||
setProfile(previous, current, true);
|
||||
|
|
|
@ -61,6 +61,7 @@ namespace Launcher
|
|||
void slotProfileRenamed(const QString &previous, const QString ¤t);
|
||||
void slotProfileDeleted(const QString &item);
|
||||
void slotAddonDataChanged ();
|
||||
void slotRefreshButtonClicked ();
|
||||
|
||||
void updateNewProfileOkButton(const QString &text);
|
||||
void updateCloneProfileOkButton(const QString &text);
|
||||
|
@ -100,6 +101,7 @@ namespace Launcher
|
|||
void checkForDefaultProfile();
|
||||
void populateFileViews(const QString& contentModelName);
|
||||
void reloadCells(QStringList selectedFiles);
|
||||
void refreshDataFilesView ();
|
||||
|
||||
class PathIterator
|
||||
{
|
||||
|
|
|
@ -97,10 +97,6 @@ opencs_units_noqt (view/render
|
|||
cellarrow cellmarker cellborder pathgrid
|
||||
)
|
||||
|
||||
opencs_hdrs_noqt (view/render
|
||||
mask
|
||||
)
|
||||
|
||||
|
||||
opencs_units (view/tools
|
||||
reportsubview reporttable searchsubview searchbox merge
|
||||
|
|
|
@ -355,6 +355,11 @@ void CSMPrefs::State::declare()
|
|||
declareShortcut ("scene-select-secondary", "Secondary Select",
|
||||
QKeySequence(Qt::ControlModifier | (int)Qt::MiddleButton));
|
||||
declareModifier ("scene-speed-modifier", "Speed Modifier", Qt::Key_Shift);
|
||||
declareShortcut ("scene-delete", "Delete Instance", QKeySequence(Qt::Key_Delete));
|
||||
declareShortcut ("scene-instance-drop-terrain", "Drop to terrain level", QKeySequence(Qt::Key_G));
|
||||
declareShortcut ("scene-instance-drop-collision", "Drop to collision", QKeySequence(Qt::Key_H));
|
||||
declareShortcut ("scene-instance-drop-terrain-separately", "Drop to terrain level separately", QKeySequence());
|
||||
declareShortcut ("scene-instance-drop-collision-separately", "Drop to collision separately", QKeySequence());
|
||||
declareShortcut ("scene-load-cam-cell", "Load Camera Cell", QKeySequence(Qt::KeypadModifier | Qt::Key_5));
|
||||
declareShortcut ("scene-load-cam-eastcell", "Load East Cell", QKeySequence(Qt::KeypadModifier | Qt::Key_6));
|
||||
declareShortcut ("scene-load-cam-northcell", "Load North Cell", QKeySequence(Qt::KeypadModifier | Qt::Key_8));
|
||||
|
|
|
@ -76,53 +76,6 @@ namespace CSMWorld
|
|||
return false;
|
||||
}
|
||||
|
||||
/* LandMapLodColumn */
|
||||
LandMapLodColumn::LandMapLodColumn()
|
||||
: Column<Land>(Columns::ColumnId_LandMapLodIndex, ColumnBase::Display_String, 0)
|
||||
{
|
||||
}
|
||||
|
||||
QVariant LandMapLodColumn::get(const Record<Land>& record) const
|
||||
{
|
||||
const int Size = Land::LAND_GLOBAL_MAP_LOD_SIZE;
|
||||
const Land& land = record.get();
|
||||
|
||||
DataType values(Size, 0);
|
||||
|
||||
if (land.mDataTypes & Land::DATA_WNAM)
|
||||
{
|
||||
for (int i = 0; i < Size; ++i)
|
||||
values[i] = land.mWnam[i];
|
||||
}
|
||||
|
||||
QVariant variant;
|
||||
variant.setValue(values);
|
||||
return variant;
|
||||
}
|
||||
|
||||
void LandMapLodColumn::set(Record<Land>& record, const QVariant& data)
|
||||
{
|
||||
DataType values = data.value<DataType>();
|
||||
|
||||
if (values.size() != Land::LAND_GLOBAL_MAP_LOD_SIZE)
|
||||
throw std::runtime_error("invalid land map LOD data");
|
||||
|
||||
Land copy = record.get();
|
||||
copy.add(Land::DATA_WNAM);
|
||||
|
||||
for (int i = 0; i < values.size(); ++i)
|
||||
{
|
||||
copy.mWnam[i] = values[i];
|
||||
}
|
||||
|
||||
record.setModified(copy);
|
||||
}
|
||||
|
||||
bool LandMapLodColumn::isEditable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/* LandNormalsColumn */
|
||||
LandNormalsColumn::LandNormalsColumn()
|
||||
: Column<Land>(Columns::ColumnId_LandNormalsIndex, ColumnBase::Display_String, 0)
|
||||
|
|
|
@ -1770,7 +1770,7 @@ namespace CSMWorld
|
|||
struct GenderNpcColumn : public Column<ESXRecordT>
|
||||
{
|
||||
GenderNpcColumn()
|
||||
: Column<ESXRecordT>(Columns::ColumnId_GenderNpc, ColumnBase::Display_GenderNpc)
|
||||
: Column<ESXRecordT>(Columns::ColumnId_Gender, ColumnBase::Display_GenderNpc)
|
||||
{}
|
||||
|
||||
virtual QVariant get(const Record<ESXRecordT>& record) const
|
||||
|
@ -2461,17 +2461,6 @@ namespace CSMWorld
|
|||
bool isEditable() const override;
|
||||
};
|
||||
|
||||
struct LandMapLodColumn : public Column<Land>
|
||||
{
|
||||
using DataType = QVector<signed char>;
|
||||
|
||||
LandMapLodColumn();
|
||||
|
||||
QVariant get(const Record<Land>& record) const override;
|
||||
void set(Record<Land>& record, const QVariant& data) override;
|
||||
bool isEditable() const override;
|
||||
};
|
||||
|
||||
struct LandNormalsColumn : public Column<Land>
|
||||
{
|
||||
using DataType = QVector<signed char>;
|
||||
|
@ -2529,8 +2518,7 @@ namespace CSMWorld
|
|||
}
|
||||
|
||||
// This is required to access the type as a QVariant.
|
||||
Q_DECLARE_METATYPE(CSMWorld::LandMapLodColumn::DataType)
|
||||
//Q_DECLARE_METATYPE(CSMWorld::LandNormalsColumn::DataType) // Same as LandMapLodColumn::DataType
|
||||
Q_DECLARE_METATYPE(CSMWorld::LandNormalsColumn::DataType)
|
||||
Q_DECLARE_METATYPE(CSMWorld::LandHeightsColumn::DataType)
|
||||
Q_DECLARE_METATYPE(CSMWorld::LandColoursColumn::DataType)
|
||||
Q_DECLARE_METATYPE(CSMWorld::LandTexturesColumn::DataType)
|
||||
|
|
|
@ -288,7 +288,6 @@ namespace CSMWorld
|
|||
{ ColumnId_UChar, "Value [0..255]" },
|
||||
{ ColumnId_NpcMisc, "NPC Misc" },
|
||||
{ ColumnId_Level, "Level" },
|
||||
{ ColumnId_GenderNpc, "Gender"},
|
||||
{ ColumnId_Mana, "Mana" },
|
||||
{ ColumnId_Fatigue, "Fatigue" },
|
||||
{ ColumnId_NpcDisposition, "NPC Disposition" },
|
||||
|
|
|
@ -273,7 +273,7 @@ namespace CSMWorld
|
|||
ColumnId_UChar = 250,
|
||||
ColumnId_NpcMisc = 251,
|
||||
ColumnId_Level = 252,
|
||||
ColumnId_GenderNpc = 254,
|
||||
// unused
|
||||
ColumnId_Mana = 255,
|
||||
ColumnId_Fatigue = 256,
|
||||
ColumnId_NpcDisposition = 257,
|
||||
|
|
|
@ -79,8 +79,10 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, bool fsStrict, const Files::Pat
|
|||
|
||||
Shader::ShaderManager::DefineMap defines = mResourceSystem->getSceneManager()->getShaderManager().getGlobalDefines();
|
||||
Shader::ShaderManager::DefineMap shadowDefines = SceneUtil::ShadowManager::getShadowsDisabledDefines();
|
||||
defines["forcePPL"] = "0";
|
||||
defines["clamp"] = "1";
|
||||
defines["forcePPL"] = "0"; // Don't force per-pixel lighting
|
||||
defines["clamp"] = "1"; // Clamp lighting
|
||||
defines["preLightEnv"] = "0"; // Apply environment maps after lighting like Morrowind
|
||||
defines["radialFog"] = "0";
|
||||
for (const auto& define : shadowDefines)
|
||||
defines[define.first] = define.second;
|
||||
mResourceSystem->getSceneManager()->getShaderManager().setGlobalDefines(defines);
|
||||
|
@ -443,7 +445,6 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, bool fsStrict, const Files::Pat
|
|||
mLand.addColumn (new RecordStateColumn<Land>);
|
||||
mLand.addColumn (new FixedRecordTypeColumn<Land>(UniversalId::Type_Land));
|
||||
mLand.addColumn (new LandPluginIndexColumn);
|
||||
mLand.addColumn (new LandMapLodColumn);
|
||||
mLand.addColumn (new LandNormalsColumn);
|
||||
mLand.addColumn (new LandHeightsColumn);
|
||||
mLand.addColumn (new LandColoursColumn);
|
||||
|
|
|
@ -867,6 +867,8 @@ namespace CSMWorld
|
|||
switch (subColIndex)
|
||||
{
|
||||
case 0: return isInterior;
|
||||
// While the ambient information is not necessarily valid if the subrecord wasn't loaded,
|
||||
// the user should still be allowed to edit it
|
||||
case 1: return (isInterior && !behaveLikeExterior) ?
|
||||
cell.mAmbi.mAmbient : QVariant(QVariant::UserType);
|
||||
case 2: return (isInterior && !behaveLikeExterior) ?
|
||||
|
@ -912,7 +914,10 @@ namespace CSMWorld
|
|||
case 1:
|
||||
{
|
||||
if (isInterior && !behaveLikeExterior)
|
||||
{
|
||||
cell.mAmbi.mAmbient = static_cast<int32_t>(value.toInt());
|
||||
cell.setHasAmbient(true);
|
||||
}
|
||||
else
|
||||
return; // return without saving
|
||||
break;
|
||||
|
@ -920,7 +925,10 @@ namespace CSMWorld
|
|||
case 2:
|
||||
{
|
||||
if (isInterior && !behaveLikeExterior)
|
||||
{
|
||||
cell.mAmbi.mSunlight = static_cast<int32_t>(value.toInt());
|
||||
cell.setHasAmbient(true);
|
||||
}
|
||||
else
|
||||
return; // return without saving
|
||||
break;
|
||||
|
@ -928,7 +936,10 @@ namespace CSMWorld
|
|||
case 3:
|
||||
{
|
||||
if (isInterior && !behaveLikeExterior)
|
||||
{
|
||||
cell.mAmbi.mFog = static_cast<int32_t>(value.toInt());
|
||||
cell.setHasAmbient(true);
|
||||
}
|
||||
else
|
||||
return; // return without saving
|
||||
break;
|
||||
|
@ -936,7 +947,10 @@ namespace CSMWorld
|
|||
case 4:
|
||||
{
|
||||
if (isInterior && !behaveLikeExterior)
|
||||
{
|
||||
cell.mAmbi.mFogDensity = value.toFloat();
|
||||
cell.setHasAmbient(true);
|
||||
}
|
||||
else
|
||||
return; // return without saving
|
||||
break;
|
||||
|
|
|
@ -486,7 +486,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
|
|||
mColumns.push_back (RefIdColumn (Columns::ColumnId_Head, ColumnBase::Display_BodyPart));
|
||||
npcColumns.mHead = &mColumns.back();
|
||||
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_GenderNpc, ColumnBase::Display_GenderNpc));
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_Gender, ColumnBase::Display_GenderNpc));
|
||||
npcColumns.mGender = &mColumns.back();
|
||||
|
||||
npcColumns.mFlags.insert (std::make_pair (essential, ESM::NPC::Essential));
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <components/esm/loadcell.hpp>
|
||||
#include <components/esm/loadland.hpp>
|
||||
#include <components/sceneutil/pathgridutil.hpp>
|
||||
#include <components/sceneutil/vismask.hpp>
|
||||
#include <components/terrain/terraingrid.hpp>
|
||||
|
||||
#include "../../model/world/idtable.hpp"
|
||||
|
@ -21,7 +22,6 @@
|
|||
#include "cellborder.hpp"
|
||||
#include "cellarrow.hpp"
|
||||
#include "cellmarker.hpp"
|
||||
#include "mask.hpp"
|
||||
#include "pathgrid.hpp"
|
||||
#include "terrainstorage.hpp"
|
||||
#include "object.hpp"
|
||||
|
@ -92,7 +92,7 @@ bool CSVRender::Cell::addObjects (int start, int end)
|
|||
|
||||
std::unique_ptr<Object> object (new Object (mData, mCellNode, id, false));
|
||||
|
||||
if (mSubModeElementMask & Mask_Reference)
|
||||
if (mSubModeElementMask & SceneUtil::Mask_EditorReference)
|
||||
object->setSubMode (mSubMode);
|
||||
|
||||
mObjects.insert (std::make_pair (id, object.release()));
|
||||
|
@ -134,7 +134,7 @@ void CSVRender::Cell::updateLand()
|
|||
else
|
||||
{
|
||||
mTerrain.reset(new Terrain::TerrainGrid(mCellNode, mCellNode,
|
||||
mData.getResourceSystem().get(), mTerrainStorage, Mask_Terrain));
|
||||
mData.getResourceSystem().get(), mTerrainStorage));
|
||||
}
|
||||
|
||||
mTerrain->loadCell(esmLand.mX, esmLand.mY);
|
||||
|
@ -434,7 +434,7 @@ void CSVRender::Cell::reloadAssets()
|
|||
|
||||
void CSVRender::Cell::setSelection (int elementMask, Selection mode)
|
||||
{
|
||||
if (elementMask & Mask_Reference)
|
||||
if (elementMask & SceneUtil::Mask_EditorReference)
|
||||
{
|
||||
for (std::map<std::string, Object *>::const_iterator iter (mObjects.begin());
|
||||
iter!=mObjects.end(); ++iter)
|
||||
|
@ -451,7 +451,7 @@ void CSVRender::Cell::setSelection (int elementMask, Selection mode)
|
|||
iter->second->setSelected (selected);
|
||||
}
|
||||
}
|
||||
if (mPathgrid && elementMask & Mask_Pathgrid)
|
||||
if (mPathgrid && elementMask & SceneUtil::Mask_Pathgrid)
|
||||
{
|
||||
// Only one pathgrid may be selected, so some operations will only have an effect
|
||||
// if the pathgrid is already focused
|
||||
|
@ -546,12 +546,12 @@ std::vector<osg::ref_ptr<CSVRender::TagBase> > CSVRender::Cell::getSelection (un
|
|||
{
|
||||
std::vector<osg::ref_ptr<TagBase> > result;
|
||||
|
||||
if (elementMask & Mask_Reference)
|
||||
if (elementMask & SceneUtil::Mask_EditorReference)
|
||||
for (std::map<std::string, Object *>::const_iterator iter (mObjects.begin());
|
||||
iter!=mObjects.end(); ++iter)
|
||||
if (iter->second->getSelected())
|
||||
result.push_back (iter->second->getTag());
|
||||
if (mPathgrid && elementMask & Mask_Pathgrid)
|
||||
if (mPathgrid && elementMask & SceneUtil::Mask_Pathgrid)
|
||||
if (mPathgrid->isSelected())
|
||||
result.push_back(mPathgrid->getTag());
|
||||
|
||||
|
@ -562,7 +562,7 @@ std::vector<osg::ref_ptr<CSVRender::TagBase> > CSVRender::Cell::getEdited (unsig
|
|||
{
|
||||
std::vector<osg::ref_ptr<TagBase> > result;
|
||||
|
||||
if (elementMask & Mask_Reference)
|
||||
if (elementMask & SceneUtil::Mask_EditorReference)
|
||||
for (std::map<std::string, Object *>::const_iterator iter (mObjects.begin());
|
||||
iter!=mObjects.end(); ++iter)
|
||||
if (iter->second->isEdited())
|
||||
|
@ -576,7 +576,7 @@ void CSVRender::Cell::setSubMode (int subMode, unsigned int elementMask)
|
|||
mSubMode = subMode;
|
||||
mSubModeElementMask = elementMask;
|
||||
|
||||
if (elementMask & Mask_Reference)
|
||||
if (elementMask & SceneUtil::Mask_EditorReference)
|
||||
for (std::map<std::string, Object *>::const_iterator iter (mObjects.begin());
|
||||
iter!=mObjects.end(); ++iter)
|
||||
iter->second->setSubMode (subMode);
|
||||
|
@ -584,10 +584,10 @@ void CSVRender::Cell::setSubMode (int subMode, unsigned int elementMask)
|
|||
|
||||
void CSVRender::Cell::reset (unsigned int elementMask)
|
||||
{
|
||||
if (elementMask & Mask_Reference)
|
||||
if (elementMask & SceneUtil::Mask_EditorReference)
|
||||
for (std::map<std::string, Object *>::const_iterator iter (mObjects.begin());
|
||||
iter!=mObjects.end(); ++iter)
|
||||
iter->second->reset();
|
||||
if (mPathgrid && elementMask & Mask_Pathgrid)
|
||||
if (mPathgrid && elementMask & SceneUtil::Mask_Pathgrid)
|
||||
mPathgrid->resetIndicators();
|
||||
}
|
||||
|
|
|
@ -11,11 +11,10 @@
|
|||
#include "../../model/prefs/shortcutmanager.hpp"
|
||||
|
||||
#include <components/misc/constants.hpp>
|
||||
|
||||
#include "mask.hpp"
|
||||
#include <components/sceneutil/vismask.hpp>
|
||||
|
||||
CSVRender::CellArrowTag::CellArrowTag (CellArrow *arrow)
|
||||
: TagBase (Mask_CellArrow), mArrow (arrow)
|
||||
: TagBase (SceneUtil::Mask_EditorCellArrow), mArrow (arrow)
|
||||
{}
|
||||
|
||||
CSVRender::CellArrow *CSVRender::CellArrowTag::getCellArrow() const
|
||||
|
@ -175,7 +174,7 @@ CSVRender::CellArrow::CellArrow (osg::Group *cellNode, Direction direction,
|
|||
|
||||
mParentNode->addChild (mBaseNode);
|
||||
|
||||
mBaseNode->setNodeMask (Mask_CellArrow);
|
||||
mBaseNode->setNodeMask (SceneUtil::Mask_EditorCellArrow);
|
||||
|
||||
adjustTransform();
|
||||
buildShape();
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
#include <osg/PrimitiveSet>
|
||||
|
||||
#include <components/esm/loadland.hpp>
|
||||
|
||||
#include "mask.hpp"
|
||||
#include <components/sceneutil/vismask.hpp>
|
||||
|
||||
#include "../../model/world/cellcoordinates.hpp"
|
||||
|
||||
|
@ -20,7 +19,7 @@ CSVRender::CellBorder::CellBorder(osg::Group* cellNode, const CSMWorld::CellCoor
|
|||
: mParentNode(cellNode)
|
||||
{
|
||||
mBaseNode = new osg::PositionAttitudeTransform();
|
||||
mBaseNode->setNodeMask(Mask_CellBorder);
|
||||
mBaseNode->setNodeMask(SceneUtil::Mask_EditorCellBorder);
|
||||
mBaseNode->setPosition(osg::Vec3f(coords.getX() * CellSize, coords.getY() * CellSize, 10));
|
||||
|
||||
mParentNode->addChild(mBaseNode);
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <components/misc/constants.hpp>
|
||||
|
||||
CSVRender::CellMarkerTag::CellMarkerTag(CellMarker *marker)
|
||||
: TagBase(Mask_CellMarker), mMarker(marker)
|
||||
: TagBase(SceneUtil::Mask_EditorCellMarker), mMarker(marker)
|
||||
{}
|
||||
|
||||
CSVRender::CellMarker *CSVRender::CellMarkerTag::getCellMarker() const
|
||||
|
@ -79,7 +79,7 @@ CSVRender::CellMarker::CellMarker(
|
|||
mMarkerNode->getOrCreateStateSet()->setAttribute(mat);
|
||||
|
||||
mMarkerNode->setUserData(new CellMarkerTag(this));
|
||||
mMarkerNode->setNodeMask(Mask_CellMarker);
|
||||
mMarkerNode->setNodeMask(SceneUtil::Mask_EditorCellMarker);
|
||||
|
||||
mCellNode->addChild(mMarkerNode);
|
||||
|
||||
|
|
|
@ -11,12 +11,12 @@
|
|||
#include <components/resource/imagemanager.hpp>
|
||||
#include <components/resource/resourcesystem.hpp>
|
||||
#include <components/sceneutil/waterutil.hpp>
|
||||
#include <components/sceneutil/vismask.hpp>
|
||||
|
||||
#include "../../model/world/cell.hpp"
|
||||
#include "../../model/world/cellcoordinates.hpp"
|
||||
#include "../../model/world/data.hpp"
|
||||
|
||||
#include "mask.hpp"
|
||||
|
||||
namespace CSVRender
|
||||
{
|
||||
|
@ -38,7 +38,7 @@ namespace CSVRender
|
|||
mWaterTransform->setPosition(osg::Vec3f(cellCoords.getX() * CellSize + CellSize / 2.f,
|
||||
cellCoords.getY() * CellSize + CellSize / 2.f, 0));
|
||||
|
||||
mWaterTransform->setNodeMask(Mask_Water);
|
||||
mWaterTransform->setNodeMask(SceneUtil::Mask_Water);
|
||||
mParentNode->addChild(mWaterTransform);
|
||||
|
||||
mWaterNode = new osg::Geode();
|
||||
|
|
|
@ -3,18 +3,25 @@
|
|||
|
||||
#include <QDragEnterEvent>
|
||||
#include <QPoint>
|
||||
#include <QString>
|
||||
|
||||
#include "../../model/prefs/state.hpp"
|
||||
|
||||
#include <osg/ComputeBoundsVisitor>
|
||||
#include <osg/Group>
|
||||
#include <osg/Vec3d>
|
||||
#include <osgUtil/LineSegmentIntersector>
|
||||
|
||||
#include "../../model/world/idtable.hpp"
|
||||
#include "../../model/world/idtree.hpp"
|
||||
#include "../../model/world/commands.hpp"
|
||||
#include "../../model/world/commandmacro.hpp"
|
||||
#include "../../model/prefs/shortcut.hpp"
|
||||
|
||||
#include "../widget/scenetoolbar.hpp"
|
||||
#include "../widget/scenetoolmode.hpp"
|
||||
|
||||
#include "mask.hpp"
|
||||
#include <components/sceneutil/vismask.hpp>
|
||||
|
||||
#include "object.hpp"
|
||||
#include "worldspacewidget.hpp"
|
||||
|
@ -89,13 +96,26 @@ osg::Vec3f CSVRender::InstanceMode::getScreenCoords(const osg::Vec3f& pos)
|
|||
return pos * combined;
|
||||
}
|
||||
|
||||
CSVRender::InstanceMode::InstanceMode (WorldspaceWidget *worldspaceWidget, QWidget *parent)
|
||||
: EditMode (worldspaceWidget, QIcon (":scenetoolbar/editing-instance"), Mask_Reference | Mask_Terrain, "Instance editing",
|
||||
CSVRender::InstanceMode::InstanceMode (WorldspaceWidget *worldspaceWidget, osg::ref_ptr<osg::Group> parentNode, QWidget *parent)
|
||||
: EditMode (worldspaceWidget, QIcon (":scenetoolbar/editing-instance"), SceneUtil::Mask_EditorReference | SceneUtil::Mask_Terrain, "Instance editing",
|
||||
parent), mSubMode (0), mSubModeId ("move"), mSelectionMode (0), mDragMode (DragMode_None),
|
||||
mDragAxis (-1), mLocked (false), mUnitScaleDist(1)
|
||||
mDragAxis (-1), mLocked (false), mUnitScaleDist(1), mParentNode (parentNode)
|
||||
{
|
||||
connect(this, SIGNAL(requestFocus(const std::string&)),
|
||||
worldspaceWidget, SIGNAL(requestFocus(const std::string&)));
|
||||
|
||||
CSMPrefs::Shortcut* deleteShortcut = new CSMPrefs::Shortcut("scene-delete", worldspaceWidget);
|
||||
connect(deleteShortcut, SIGNAL(activated(bool)), this, SLOT(deleteSelectedInstances(bool)));
|
||||
|
||||
// Following classes could be simplified by using QSignalMapper, which is obsolete in Qt5.10, but not in Qt4.8 and Qt5.14
|
||||
CSMPrefs::Shortcut* dropToCollisionShortcut = new CSMPrefs::Shortcut("scene-instance-drop-collision", worldspaceWidget);
|
||||
connect(dropToCollisionShortcut, SIGNAL(activated()), this, SLOT(dropSelectedInstancesToCollision()));
|
||||
CSMPrefs::Shortcut* dropToTerrainLevelShortcut = new CSMPrefs::Shortcut("scene-instance-drop-terrain", worldspaceWidget);
|
||||
connect(dropToTerrainLevelShortcut, SIGNAL(activated()), this, SLOT(dropSelectedInstancesToTerrain()));
|
||||
CSMPrefs::Shortcut* dropToCollisionShortcut2 = new CSMPrefs::Shortcut("scene-instance-drop-collision-separately", worldspaceWidget);
|
||||
connect(dropToCollisionShortcut2, SIGNAL(activated()), this, SLOT(dropSelectedInstancesToCollisionSeparately()));
|
||||
CSMPrefs::Shortcut* dropToTerrainLevelShortcut2 = new CSMPrefs::Shortcut("scene-instance-drop-terrain-separately", worldspaceWidget);
|
||||
connect(dropToTerrainLevelShortcut2, SIGNAL(activated()), this, SLOT(dropSelectedInstancesToTerrainSeparately()));
|
||||
}
|
||||
|
||||
void CSVRender::InstanceMode::activate (CSVWidget::SceneToolbar *toolbar)
|
||||
|
@ -137,13 +157,13 @@ void CSVRender::InstanceMode::activate (CSVWidget::SceneToolbar *toolbar)
|
|||
|
||||
std::string subMode = mSubMode->getCurrentId();
|
||||
|
||||
getWorldspaceWidget().setSubMode (getSubModeFromId (subMode), Mask_Reference);
|
||||
getWorldspaceWidget().setSubMode (getSubModeFromId (subMode), SceneUtil::Mask_EditorReference);
|
||||
}
|
||||
|
||||
void CSVRender::InstanceMode::deactivate (CSVWidget::SceneToolbar *toolbar)
|
||||
{
|
||||
mDragMode = DragMode_None;
|
||||
getWorldspaceWidget().reset (Mask_Reference);
|
||||
getWorldspaceWidget().reset (SceneUtil::Mask_EditorReference);
|
||||
|
||||
if (mSelectionMode)
|
||||
{
|
||||
|
@ -196,7 +216,7 @@ void CSVRender::InstanceMode::secondaryEditPressed (const WorldspaceHitResult& h
|
|||
|
||||
void CSVRender::InstanceMode::primarySelectPressed (const WorldspaceHitResult& hit)
|
||||
{
|
||||
getWorldspaceWidget().clearSelection (Mask_Reference);
|
||||
getWorldspaceWidget().clearSelection (SceneUtil::Mask_EditorReference);
|
||||
|
||||
if (hit.tag)
|
||||
{
|
||||
|
@ -231,13 +251,13 @@ bool CSVRender::InstanceMode::primaryEditStartDrag (const QPoint& pos)
|
|||
|
||||
WorldspaceHitResult hit = getWorldspaceWidget().mousePick (pos, getWorldspaceWidget().getInteractionMask());
|
||||
|
||||
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (Mask_Reference);
|
||||
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (SceneUtil::Mask_EditorReference);
|
||||
if (selection.empty())
|
||||
{
|
||||
// Only change selection at the start of drag if no object is already selected
|
||||
if (hit.tag && CSMPrefs::get()["3D Scene Input"]["context-select"].isTrue())
|
||||
{
|
||||
getWorldspaceWidget().clearSelection (Mask_Reference);
|
||||
getWorldspaceWidget().clearSelection (SceneUtil::Mask_EditorReference);
|
||||
if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (hit.tag.get()))
|
||||
{
|
||||
CSVRender::Object* object = objectTag->mObject;
|
||||
|
@ -245,7 +265,7 @@ bool CSVRender::InstanceMode::primaryEditStartDrag (const QPoint& pos)
|
|||
}
|
||||
}
|
||||
|
||||
selection = getWorldspaceWidget().getSelection (Mask_Reference);
|
||||
selection = getWorldspaceWidget().getSelection (SceneUtil::Mask_EditorReference);
|
||||
if (selection.empty())
|
||||
return false;
|
||||
}
|
||||
|
@ -271,7 +291,7 @@ bool CSVRender::InstanceMode::primaryEditStartDrag (const QPoint& pos)
|
|||
mDragMode = DragMode_Scale;
|
||||
|
||||
// Calculate scale factor
|
||||
std::vector<osg::ref_ptr<TagBase> > editedSelection = getWorldspaceWidget().getEdited (Mask_Reference);
|
||||
std::vector<osg::ref_ptr<TagBase> > editedSelection = getWorldspaceWidget().getEdited (SceneUtil::Mask_EditorReference);
|
||||
osg::Vec3f center = getScreenCoords(getSelectionCenter(editedSelection));
|
||||
|
||||
int widgetHeight = getWorldspaceWidget().height();
|
||||
|
@ -307,7 +327,7 @@ void CSVRender::InstanceMode::drag (const QPoint& pos, int diffX, int diffY, dou
|
|||
osg::Vec3f offset;
|
||||
osg::Quat rotation;
|
||||
|
||||
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getEdited (Mask_Reference);
|
||||
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getEdited (SceneUtil::Mask_EditorReference);
|
||||
|
||||
if (mDragMode == DragMode_Move)
|
||||
{
|
||||
|
@ -464,7 +484,7 @@ void CSVRender::InstanceMode::drag (const QPoint& pos, int diffX, int diffY, dou
|
|||
void CSVRender::InstanceMode::dragCompleted(const QPoint& pos)
|
||||
{
|
||||
std::vector<osg::ref_ptr<TagBase> > selection =
|
||||
getWorldspaceWidget().getEdited (Mask_Reference);
|
||||
getWorldspaceWidget().getEdited (SceneUtil::Mask_EditorReference);
|
||||
|
||||
QUndoStack& undoStack = getWorldspaceWidget().getDocument().getUndoStack();
|
||||
|
||||
|
@ -496,7 +516,7 @@ void CSVRender::InstanceMode::dragCompleted(const QPoint& pos)
|
|||
|
||||
void CSVRender::InstanceMode::dragAborted()
|
||||
{
|
||||
getWorldspaceWidget().reset (Mask_Reference);
|
||||
getWorldspaceWidget().reset (SceneUtil::Mask_EditorReference);
|
||||
mDragMode = DragMode_None;
|
||||
}
|
||||
|
||||
|
@ -515,7 +535,7 @@ void CSVRender::InstanceMode::dragWheel (int diff, double speedFactor)
|
|||
offset *= diff * speedFactor;
|
||||
|
||||
std::vector<osg::ref_ptr<TagBase> > selection =
|
||||
getWorldspaceWidget().getEdited (Mask_Reference);
|
||||
getWorldspaceWidget().getEdited (SceneUtil::Mask_EditorReference);
|
||||
|
||||
for (std::vector<osg::ref_ptr<TagBase> >::iterator iter (selection.begin());
|
||||
iter!=selection.end(); ++iter)
|
||||
|
@ -657,5 +677,207 @@ void CSVRender::InstanceMode::subModeChanged (const std::string& id)
|
|||
{
|
||||
mSubModeId = id;
|
||||
getWorldspaceWidget().abortDrag();
|
||||
getWorldspaceWidget().setSubMode (getSubModeFromId (id), Mask_Reference);
|
||||
getWorldspaceWidget().setSubMode (getSubModeFromId (id), SceneUtil::Mask_EditorReference);
|
||||
}
|
||||
|
||||
void CSVRender::InstanceMode::deleteSelectedInstances(bool active)
|
||||
{
|
||||
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (SceneUtil::Mask_EditorReference);
|
||||
if (selection.empty()) return;
|
||||
|
||||
CSMDoc::Document& document = getWorldspaceWidget().getDocument();
|
||||
CSMWorld::IdTable& referencesTable = dynamic_cast<CSMWorld::IdTable&> (
|
||||
*document.getData().getTableModel (CSMWorld::UniversalId::Type_References));
|
||||
QUndoStack& undoStack = document.getUndoStack();
|
||||
|
||||
CSMWorld::CommandMacro macro (undoStack, "Delete Instances");
|
||||
for(osg::ref_ptr<TagBase> tag: selection)
|
||||
if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (tag.get()))
|
||||
macro.push(new CSMWorld::DeleteCommand(referencesTable, objectTag->mObject->getReferenceId()));
|
||||
|
||||
getWorldspaceWidget().clearSelection (SceneUtil::Mask_EditorReference);
|
||||
}
|
||||
|
||||
void CSVRender::InstanceMode::dropInstance(DropMode dropMode, CSVRender::Object* object, float objectHeight)
|
||||
{
|
||||
osg::Vec3d point = object->getPosition().asVec3();
|
||||
|
||||
osg::Vec3d start = point;
|
||||
start.z() += objectHeight;
|
||||
osg::Vec3d end = point;
|
||||
end.z() = std::numeric_limits<float>::lowest();
|
||||
|
||||
osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector (new osgUtil::LineSegmentIntersector(
|
||||
osgUtil::Intersector::MODEL, start, end) );
|
||||
intersector->setIntersectionLimit(osgUtil::LineSegmentIntersector::NO_LIMIT);
|
||||
osgUtil::IntersectionVisitor visitor(intersector);
|
||||
|
||||
if (dropMode == TerrainSep)
|
||||
visitor.setTraversalMask(SceneUtil::Mask_Terrain);
|
||||
if (dropMode == CollisionSep)
|
||||
visitor.setTraversalMask(SceneUtil::Mask_Terrain | SceneUtil::Mask_EditorReference);
|
||||
|
||||
mParentNode->accept(visitor);
|
||||
|
||||
for (osgUtil::LineSegmentIntersector::Intersections::iterator it = intersector->getIntersections().begin();
|
||||
it != intersector->getIntersections().end(); ++it)
|
||||
{
|
||||
osgUtil::LineSegmentIntersector::Intersection intersection = *it;
|
||||
ESM::Position position = object->getPosition();
|
||||
object->setEdited (Object::Override_Position);
|
||||
position.pos[2] = intersection.getWorldIntersectPoint().z() + objectHeight;
|
||||
object->setPosition(position.pos);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
float CSVRender::InstanceMode::getDropHeight(DropMode dropMode, CSVRender::Object* object, float objectHeight)
|
||||
{
|
||||
osg::Vec3d point = object->getPosition().asVec3();
|
||||
|
||||
osg::Vec3d start = point;
|
||||
start.z() += objectHeight;
|
||||
osg::Vec3d end = point;
|
||||
end.z() = std::numeric_limits<float>::lowest();
|
||||
|
||||
osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector (new osgUtil::LineSegmentIntersector(
|
||||
osgUtil::Intersector::MODEL, start, end) );
|
||||
intersector->setIntersectionLimit(osgUtil::LineSegmentIntersector::NO_LIMIT);
|
||||
osgUtil::IntersectionVisitor visitor(intersector);
|
||||
|
||||
if (dropMode == Terrain)
|
||||
visitor.setTraversalMask(SceneUtil::Mask_Terrain);
|
||||
if (dropMode == Collision)
|
||||
visitor.setTraversalMask(SceneUtil::Mask_Terrain | SceneUtil::Mask_EditorReference);
|
||||
|
||||
mParentNode->accept(visitor);
|
||||
|
||||
for (osgUtil::LineSegmentIntersector::Intersections::iterator it = intersector->getIntersections().begin();
|
||||
it != intersector->getIntersections().end(); ++it)
|
||||
{
|
||||
osgUtil::LineSegmentIntersector::Intersection intersection = *it;
|
||||
float collisionLevel = intersection.getWorldIntersectPoint().z();
|
||||
return point.z() - collisionLevel + objectHeight;
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void CSVRender::InstanceMode::dropSelectedInstancesToCollision()
|
||||
{
|
||||
handleDropMethod(Collision, "Drop instances to next collision");
|
||||
}
|
||||
|
||||
void CSVRender::InstanceMode::dropSelectedInstancesToTerrain()
|
||||
{
|
||||
handleDropMethod(Terrain, "Drop instances to terrain level");
|
||||
}
|
||||
|
||||
void CSVRender::InstanceMode::dropSelectedInstancesToCollisionSeparately()
|
||||
{
|
||||
handleDropMethod(TerrainSep, "Drop instances to next collision level separately");
|
||||
}
|
||||
|
||||
void CSVRender::InstanceMode::dropSelectedInstancesToTerrainSeparately()
|
||||
{
|
||||
handleDropMethod(CollisionSep, "Drop instances to terrain level separately");
|
||||
}
|
||||
|
||||
void CSVRender::InstanceMode::handleDropMethod(DropMode dropMode, QString commandMsg)
|
||||
{
|
||||
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (SceneUtil::Mask_EditorReference);
|
||||
if (selection.empty())
|
||||
return;
|
||||
|
||||
CSMDoc::Document& document = getWorldspaceWidget().getDocument();
|
||||
QUndoStack& undoStack = document.getUndoStack();
|
||||
|
||||
CSMWorld::CommandMacro macro (undoStack, commandMsg);
|
||||
|
||||
DropObjectDataHandler dropObjectDataHandler(&getWorldspaceWidget());
|
||||
|
||||
switch (dropMode)
|
||||
{
|
||||
case Terrain:
|
||||
case Collision:
|
||||
{
|
||||
float smallestDropHeight = std::numeric_limits<float>::max();
|
||||
int counter = 0;
|
||||
for(osg::ref_ptr<TagBase> tag: selection)
|
||||
if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (tag.get()))
|
||||
{
|
||||
float thisDrop = getDropHeight(dropMode, objectTag->mObject, dropObjectDataHandler.mObjectHeights[counter]);
|
||||
if (thisDrop < smallestDropHeight)
|
||||
smallestDropHeight = thisDrop;
|
||||
counter++;
|
||||
}
|
||||
for(osg::ref_ptr<TagBase> tag: selection)
|
||||
if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (tag.get()))
|
||||
{
|
||||
objectTag->mObject->setEdited (Object::Override_Position);
|
||||
ESM::Position position = objectTag->mObject->getPosition();
|
||||
position.pos[2] -= smallestDropHeight;
|
||||
objectTag->mObject->setPosition(position.pos);
|
||||
objectTag->mObject->apply (macro);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TerrainSep:
|
||||
case CollisionSep:
|
||||
{
|
||||
int counter = 0;
|
||||
for(osg::ref_ptr<TagBase> tag: selection)
|
||||
if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (tag.get()))
|
||||
{
|
||||
dropInstance(dropMode, objectTag->mObject, dropObjectDataHandler.mObjectHeights[counter]);
|
||||
objectTag->mObject->apply (macro);
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CSVRender::DropObjectDataHandler::DropObjectDataHandler(WorldspaceWidget* worldspacewidget)
|
||||
: mWorldspaceWidget(worldspacewidget)
|
||||
{
|
||||
std::vector<osg::ref_ptr<TagBase> > selection = mWorldspaceWidget->getSelection (SceneUtil::Mask_EditorReference);
|
||||
for(osg::ref_ptr<TagBase> tag: selection)
|
||||
{
|
||||
if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (tag.get()))
|
||||
{
|
||||
osg::ref_ptr<osg::Group> objectNodeWithGUI = objectTag->mObject->getRootNode();
|
||||
osg::ref_ptr<osg::Group> objectNodeWithoutGUI = objectTag->mObject->getBaseNode();
|
||||
|
||||
osg::ComputeBoundsVisitor computeBounds;
|
||||
computeBounds.setTraversalMask(SceneUtil::Mask_EditorReference);
|
||||
objectNodeWithoutGUI->accept(computeBounds);
|
||||
osg::BoundingBox bounds = computeBounds.getBoundingBox();
|
||||
float boundingBoxOffset = 0.0f;
|
||||
if (bounds.valid())
|
||||
boundingBoxOffset = bounds.zMin();
|
||||
|
||||
mObjectHeights.emplace_back(boundingBoxOffset);
|
||||
mOldMasks.emplace_back(objectNodeWithGUI->getNodeMask());
|
||||
|
||||
objectNodeWithGUI->setNodeMask(SceneUtil::Mask_Disabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CSVRender::DropObjectDataHandler::~DropObjectDataHandler()
|
||||
{
|
||||
std::vector<osg::ref_ptr<TagBase> > selection = mWorldspaceWidget->getSelection (SceneUtil::Mask_EditorReference);
|
||||
int counter = 0;
|
||||
for(osg::ref_ptr<TagBase> tag: selection)
|
||||
{
|
||||
if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (tag.get()))
|
||||
{
|
||||
osg::ref_ptr<osg::Group> objectNodeWithGUI = objectTag->mObject->getRootNode();
|
||||
objectNodeWithGUI->setNodeMask(mOldMasks[counter]);
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
#ifndef CSV_RENDER_INSTANCEMODE_H
|
||||
#define CSV_RENDER_INSTANCEMODE_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
#include <osg/Group>
|
||||
#include <osg/Quat>
|
||||
#include <osg/Vec3f>
|
||||
|
||||
|
@ -16,6 +19,7 @@ namespace CSVRender
|
|||
{
|
||||
class TagBase;
|
||||
class InstanceSelectionMode;
|
||||
class Object;
|
||||
|
||||
class InstanceMode : public EditMode
|
||||
{
|
||||
|
@ -29,6 +33,14 @@ namespace CSVRender
|
|||
DragMode_Scale
|
||||
};
|
||||
|
||||
enum DropMode
|
||||
{
|
||||
Collision,
|
||||
Terrain,
|
||||
CollisionSep,
|
||||
TerrainSep
|
||||
};
|
||||
|
||||
CSVWidget::SceneToolMode *mSubMode;
|
||||
std::string mSubModeId;
|
||||
InstanceSelectionMode *mSelectionMode;
|
||||
|
@ -36,6 +48,7 @@ namespace CSVRender
|
|||
int mDragAxis;
|
||||
bool mLocked;
|
||||
float mUnitScaleDist;
|
||||
osg::ref_ptr<osg::Group> mParentNode;
|
||||
|
||||
int getSubModeFromId (const std::string& id) const;
|
||||
|
||||
|
@ -44,10 +57,12 @@ namespace CSVRender
|
|||
|
||||
osg::Vec3f getSelectionCenter(const std::vector<osg::ref_ptr<TagBase> >& selection) const;
|
||||
osg::Vec3f getScreenCoords(const osg::Vec3f& pos);
|
||||
void dropInstance(DropMode dropMode, CSVRender::Object* object, float objectHeight);
|
||||
float getDropHeight(DropMode dropMode, CSVRender::Object* object, float objectHeight);
|
||||
|
||||
public:
|
||||
|
||||
InstanceMode (WorldspaceWidget *worldspaceWidget, QWidget *parent = 0);
|
||||
InstanceMode (WorldspaceWidget *worldspaceWidget, osg::ref_ptr<osg::Group> parentNode, QWidget *parent = 0);
|
||||
|
||||
virtual void activate (CSVWidget::SceneToolbar *toolbar);
|
||||
|
||||
|
@ -92,6 +107,25 @@ namespace CSVRender
|
|||
private slots:
|
||||
|
||||
void subModeChanged (const std::string& id);
|
||||
void deleteSelectedInstances(bool active);
|
||||
void dropSelectedInstancesToCollision();
|
||||
void dropSelectedInstancesToTerrain();
|
||||
void dropSelectedInstancesToCollisionSeparately();
|
||||
void dropSelectedInstancesToTerrainSeparately();
|
||||
void handleDropMethod(DropMode dropMode, QString commandMsg);
|
||||
};
|
||||
|
||||
/// \brief Helper class to handle object mask data in safe way
|
||||
class DropObjectDataHandler
|
||||
{
|
||||
public:
|
||||
DropObjectDataHandler(WorldspaceWidget* worldspacewidget);
|
||||
~DropObjectDataHandler();
|
||||
std::vector<float> mObjectHeights;
|
||||
|
||||
private:
|
||||
WorldspaceWidget* mWorldspaceWidget;
|
||||
std::vector<osg::Node::NodeMask> mOldMasks;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -6,13 +6,15 @@
|
|||
#include "../../model/world/idtable.hpp"
|
||||
#include "../../model/world/commands.hpp"
|
||||
|
||||
#include <components/sceneutil/vismask.hpp>
|
||||
|
||||
#include "worldspacewidget.hpp"
|
||||
#include "object.hpp"
|
||||
|
||||
namespace CSVRender
|
||||
{
|
||||
InstanceSelectionMode::InstanceSelectionMode(CSVWidget::SceneToolbar* parent, WorldspaceWidget& worldspaceWidget)
|
||||
: SelectionMode(parent, worldspaceWidget, Mask_Reference)
|
||||
: SelectionMode(parent, worldspaceWidget, SceneUtil::Mask_EditorReference)
|
||||
{
|
||||
mSelectSame = new QAction("Extend selection to instances with same object ID", this);
|
||||
mDeleteSelection = new QAction("Delete selected instances", this);
|
||||
|
@ -36,12 +38,12 @@ namespace CSVRender
|
|||
|
||||
void InstanceSelectionMode::selectSame()
|
||||
{
|
||||
getWorldspaceWidget().selectAllWithSameParentId(Mask_Reference);
|
||||
getWorldspaceWidget().selectAllWithSameParentId(SceneUtil::Mask_EditorReference);
|
||||
}
|
||||
|
||||
void InstanceSelectionMode::deleteSelection()
|
||||
{
|
||||
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection(Mask_Reference);
|
||||
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection(SceneUtil::Mask_EditorReference);
|
||||
|
||||
CSMWorld::IdTable& referencesTable = dynamic_cast<CSMWorld::IdTable&>(
|
||||
*getWorldspaceWidget().getDocument().getData().getTableModel(CSMWorld::UniversalId::Type_References));
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
#ifndef CSV_RENDER_ELEMENTS_H
|
||||
#define CSV_RENDER_ELEMENTS_H
|
||||
|
||||
namespace CSVRender
|
||||
{
|
||||
|
||||
/// Node masks used on the OSG scene graph in OpenMW-CS.
|
||||
/// @note See the respective file in OpenMW (apps/openmw/mwrender/vismask.hpp)
|
||||
/// for general usage hints about node masks.
|
||||
/// @copydoc MWRender::VisMask
|
||||
enum Mask
|
||||
{
|
||||
// internal use within NifLoader, do not change
|
||||
Mask_UpdateVisitor = 0x1,
|
||||
|
||||
// elements that are part of the actual scene
|
||||
Mask_Reference = 0x2,
|
||||
Mask_Pathgrid = 0x4,
|
||||
Mask_Water = 0x8,
|
||||
Mask_Fog = 0x10,
|
||||
Mask_Terrain = 0x20,
|
||||
|
||||
// used within models
|
||||
Mask_ParticleSystem = 0x100,
|
||||
|
||||
Mask_Lighting = 0x200,
|
||||
|
||||
// control elements
|
||||
Mask_CellMarker = 0x10000,
|
||||
Mask_CellArrow = 0x20000,
|
||||
Mask_CellBorder = 0x40000
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -29,9 +29,9 @@
|
|||
#include <components/resource/scenemanager.hpp>
|
||||
#include <components/sceneutil/lightutil.hpp>
|
||||
#include <components/sceneutil/lightmanager.hpp>
|
||||
#include <components/sceneutil/vismask.hpp>
|
||||
|
||||
#include "actor.hpp"
|
||||
#include "mask.hpp"
|
||||
|
||||
|
||||
const float CSVRender::Object::MarkerShaftWidth = 30;
|
||||
|
@ -58,7 +58,7 @@ namespace
|
|||
|
||||
|
||||
CSVRender::ObjectTag::ObjectTag (Object* object)
|
||||
: TagBase (Mask_Reference), mObject (object)
|
||||
: TagBase (SceneUtil::Mask_EditorReference), mObject (object)
|
||||
{}
|
||||
|
||||
QString CSVRender::ObjectTag::getToolTip (bool hideBasics) const
|
||||
|
@ -140,7 +140,7 @@ void CSVRender::Object::update()
|
|||
if (light)
|
||||
{
|
||||
bool isExterior = false; // FIXME
|
||||
SceneUtil::addLight(mBaseNode, light, Mask_ParticleSystem, Mask_Lighting, isExterior);
|
||||
SceneUtil::addLight(mBaseNode, light, isExterior);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -429,7 +429,7 @@ CSVRender::Object::Object (CSMWorld::Data& data, osg::Group* parentNode,
|
|||
|
||||
parentNode->addChild (mRootNode);
|
||||
|
||||
mRootNode->setNodeMask(Mask_Reference);
|
||||
mRootNode->setNodeMask(SceneUtil::Mask_EditorReference);
|
||||
|
||||
if (referenceable)
|
||||
{
|
||||
|
@ -477,6 +477,16 @@ bool CSVRender::Object::getSelected() const
|
|||
return mSelected;
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Group> CSVRender::Object::getRootNode()
|
||||
{
|
||||
return mRootNode;
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Group> CSVRender::Object::getBaseNode()
|
||||
{
|
||||
return mBaseNode;
|
||||
}
|
||||
|
||||
bool CSVRender::Object::referenceableDataChanged (const QModelIndex& topLeft,
|
||||
const QModelIndex& bottomRight)
|
||||
{
|
||||
|
@ -705,7 +715,7 @@ void CSVRender::Object::apply (CSMWorld::CommandMacro& commands)
|
|||
CSMWorld::Columns::ColumnId_PositionXRot+i));
|
||||
|
||||
commands.push (new CSMWorld::ModifyCommand (*model,
|
||||
model->index (recordIndex, column), mPositionOverride.rot[i]));
|
||||
model->index (recordIndex, column), osg::RadiansToDegrees(mPositionOverride.rot[i])));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -146,6 +146,12 @@ namespace CSVRender
|
|||
|
||||
bool getSelected() const;
|
||||
|
||||
/// Get object node with GUI graphics
|
||||
osg::ref_ptr<osg::Group> getRootNode();
|
||||
|
||||
/// Get object node without GUI graphics
|
||||
osg::ref_ptr<osg::Group> getBaseNode();
|
||||
|
||||
/// \return Did this call result in a modification of the visual representation of
|
||||
/// this object?
|
||||
bool referenceableDataChanged (const QModelIndex& topLeft,
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include "../widget/scenetooltoggle2.hpp"
|
||||
|
||||
#include "editmode.hpp"
|
||||
#include "mask.hpp"
|
||||
#include "cameracontroller.hpp"
|
||||
#include "cellarrow.hpp"
|
||||
#include "terraintexturemode.hpp"
|
||||
|
@ -127,8 +126,8 @@ void CSVRender::PagedWorldspaceWidget::addVisibilitySelectorButtons (
|
|||
CSVWidget::SceneToolToggle2 *tool)
|
||||
{
|
||||
WorldspaceWidget::addVisibilitySelectorButtons (tool);
|
||||
tool->addButton (Button_Terrain, Mask_Terrain, "Terrain");
|
||||
tool->addButton (Button_Fog, Mask_Fog, "Fog", "", true);
|
||||
tool->addButton (Button_Terrain, SceneUtil::Mask_Terrain, "Terrain");
|
||||
//tool->addButton (Button_Fog, Mask_Fog, "Fog", "", true);
|
||||
}
|
||||
|
||||
void CSVRender::PagedWorldspaceWidget::addEditModeSelectorButtons (
|
||||
|
@ -142,16 +141,16 @@ void CSVRender::PagedWorldspaceWidget::addEditModeSelectorButtons (
|
|||
tool->addButton (
|
||||
new TerrainTextureMode (this, mRootNode, tool), "terrain-texture");
|
||||
tool->addButton (
|
||||
new EditMode (this, QIcon (":placeholder"), Mask_Reference, "Terrain vertex paint editing"),
|
||||
new EditMode (this, QIcon (":placeholder"), SceneUtil::Mask_EditorReference, "Terrain vertex paint editing"),
|
||||
"terrain-vertex");
|
||||
tool->addButton (
|
||||
new EditMode (this, QIcon (":placeholder"), Mask_Reference, "Terrain movement"),
|
||||
new EditMode (this, QIcon (":placeholder"), SceneUtil::Mask_EditorReference, "Terrain movement"),
|
||||
"terrain-move");
|
||||
}
|
||||
|
||||
void CSVRender::PagedWorldspaceWidget::handleInteractionPress (const WorldspaceHitResult& hit, InteractionType type)
|
||||
{
|
||||
if (hit.tag && hit.tag->getMask()==Mask_CellArrow)
|
||||
if (hit.tag && hit.tag->getMask()==SceneUtil::Mask_EditorCellArrow)
|
||||
{
|
||||
if (CellArrowTag *cellArrowTag = dynamic_cast<CSVRender::CellArrowTag *> (hit.tag.get()))
|
||||
{
|
||||
|
@ -874,9 +873,9 @@ CSVWidget::SceneToolToggle2 *CSVRender::PagedWorldspaceWidget::makeControlVisibi
|
|||
mControlElements = new CSVWidget::SceneToolToggle2 (parent,
|
||||
"Controls & Guides Visibility", ":scenetoolbar/scene-view-marker-c", ":scenetoolbar/scene-view-marker-");
|
||||
|
||||
mControlElements->addButton (1, Mask_CellMarker, "Cell Marker");
|
||||
mControlElements->addButton (2, Mask_CellArrow, "Cell Arrows");
|
||||
mControlElements->addButton (4, Mask_CellBorder, "Cell Border");
|
||||
mControlElements->addButton (1, SceneUtil::Mask_EditorCellMarker, "Cell Marker");
|
||||
mControlElements->addButton (2, SceneUtil::Mask_EditorCellArrow, "Cell Arrows");
|
||||
mControlElements->addButton (4, SceneUtil::Mask_EditorCellBorder, "Cell Border");
|
||||
|
||||
mControlElements->setSelectionMask (0xffffffff);
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <osg/Vec3>
|
||||
|
||||
#include <components/sceneutil/pathgridutil.hpp>
|
||||
#include <components/sceneutil/vismask.hpp>
|
||||
|
||||
#include "../../model/world/cell.hpp"
|
||||
#include "../../model/world/commands.hpp"
|
||||
|
@ -31,7 +32,7 @@ namespace CSVRender
|
|||
};
|
||||
|
||||
PathgridTag::PathgridTag(Pathgrid* pathgrid)
|
||||
: TagBase(Mask_Pathgrid), mPathgrid(pathgrid)
|
||||
: TagBase(SceneUtil::Mask_Pathgrid), mPathgrid(pathgrid)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -70,7 +71,7 @@ namespace CSVRender
|
|||
mBaseNode->setPosition(osg::Vec3f(mCoords.getX() * CoordScalar, mCoords.getY() * CoordScalar, 0.f));
|
||||
mBaseNode->setUserData(mTag);
|
||||
mBaseNode->setUpdateCallback(new PathgridNodeCallback());
|
||||
mBaseNode->setNodeMask(Mask_Pathgrid);
|
||||
mBaseNode->setNodeMask(SceneUtil::Mask_Pathgrid);
|
||||
mParent->addChild(mBaseNode);
|
||||
|
||||
mPathgridGeode = new osg::Geode();
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <QPoint>
|
||||
|
||||
#include <components/sceneutil/pathgridutil.hpp>
|
||||
#include <components/sceneutil/vismask.hpp>
|
||||
|
||||
#include "../../model/prefs/state.hpp"
|
||||
|
||||
|
@ -15,7 +16,6 @@
|
|||
#include "../widget/scenetoolbar.hpp"
|
||||
|
||||
#include "cell.hpp"
|
||||
#include "mask.hpp"
|
||||
#include "pathgrid.hpp"
|
||||
#include "pathgridselectionmode.hpp"
|
||||
#include "worldspacewidget.hpp"
|
||||
|
@ -23,7 +23,7 @@
|
|||
namespace CSVRender
|
||||
{
|
||||
PathgridMode::PathgridMode(WorldspaceWidget* worldspaceWidget, QWidget* parent)
|
||||
: EditMode(worldspaceWidget, QIcon(":placeholder"), Mask_Pathgrid | Mask_Terrain | Mask_Reference,
|
||||
: EditMode(worldspaceWidget, QIcon(":placeholder"), SceneUtil::Mask_Pathgrid | SceneUtil::Mask_Terrain | SceneUtil::Mask_EditorReference,
|
||||
getTooltip(), parent)
|
||||
, mDragMode(DragMode_None)
|
||||
, mFromNode(0)
|
||||
|
@ -110,7 +110,7 @@ namespace CSVRender
|
|||
|
||||
void PathgridMode::primarySelectPressed(const WorldspaceHitResult& hit)
|
||||
{
|
||||
getWorldspaceWidget().clearSelection(Mask_Pathgrid);
|
||||
getWorldspaceWidget().clearSelection(SceneUtil::Mask_Pathgrid);
|
||||
|
||||
if (hit.tag)
|
||||
{
|
||||
|
@ -131,7 +131,7 @@ namespace CSVRender
|
|||
{
|
||||
if (tag->getPathgrid()->getId() != mLastId)
|
||||
{
|
||||
getWorldspaceWidget().clearSelection(Mask_Pathgrid);
|
||||
getWorldspaceWidget().clearSelection(SceneUtil::Mask_Pathgrid);
|
||||
mLastId = tag->getPathgrid()->getId();
|
||||
}
|
||||
|
||||
|
@ -142,12 +142,12 @@ namespace CSVRender
|
|||
}
|
||||
}
|
||||
|
||||
getWorldspaceWidget().clearSelection(Mask_Pathgrid);
|
||||
getWorldspaceWidget().clearSelection(SceneUtil::Mask_Pathgrid);
|
||||
}
|
||||
|
||||
bool PathgridMode::primaryEditStartDrag(const QPoint& pos)
|
||||
{
|
||||
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (Mask_Pathgrid);
|
||||
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (SceneUtil::Mask_Pathgrid);
|
||||
|
||||
if (CSMPrefs::get()["3D Scene Input"]["context-select"].isTrue())
|
||||
{
|
||||
|
@ -156,7 +156,7 @@ namespace CSVRender
|
|||
if (dynamic_cast<PathgridTag*>(hit.tag.get()))
|
||||
{
|
||||
primarySelectPressed(hit);
|
||||
selection = getWorldspaceWidget().getSelection (Mask_Pathgrid);
|
||||
selection = getWorldspaceWidget().getSelection (SceneUtil::Mask_Pathgrid);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,7 +192,7 @@ namespace CSVRender
|
|||
{
|
||||
if (mDragMode == DragMode_Move)
|
||||
{
|
||||
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection(Mask_Pathgrid);
|
||||
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection(SceneUtil::Mask_Pathgrid);
|
||||
|
||||
for (std::vector<osg::ref_ptr<TagBase> >::iterator it = selection.begin(); it != selection.end(); ++it)
|
||||
{
|
||||
|
@ -233,7 +233,7 @@ namespace CSVRender
|
|||
{
|
||||
if (mDragMode == DragMode_Move)
|
||||
{
|
||||
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (Mask_Pathgrid);
|
||||
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (SceneUtil::Mask_Pathgrid);
|
||||
for (std::vector<osg::ref_ptr<TagBase> >::iterator it = selection.begin(); it != selection.end(); ++it)
|
||||
{
|
||||
if (PathgridTag* tag = dynamic_cast<PathgridTag*>(it->get()))
|
||||
|
@ -272,11 +272,11 @@ namespace CSVRender
|
|||
}
|
||||
|
||||
mDragMode = DragMode_None;
|
||||
getWorldspaceWidget().reset(Mask_Pathgrid);
|
||||
getWorldspaceWidget().reset(SceneUtil::Mask_Pathgrid);
|
||||
}
|
||||
|
||||
void PathgridMode::dragAborted()
|
||||
{
|
||||
getWorldspaceWidget().reset(Mask_Pathgrid);
|
||||
getWorldspaceWidget().reset(SceneUtil::Mask_Pathgrid);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
namespace CSVRender
|
||||
{
|
||||
PathgridSelectionMode::PathgridSelectionMode(CSVWidget::SceneToolbar* parent, WorldspaceWidget& worldspaceWidget)
|
||||
: SelectionMode(parent, worldspaceWidget, Mask_Pathgrid)
|
||||
: SelectionMode(parent, worldspaceWidget, SceneUtil::Mask_Pathgrid)
|
||||
{
|
||||
mRemoveSelectedNodes = new QAction("Remove selected nodes", this);
|
||||
mRemoveSelectedEdges = new QAction("Remove edges between selected nodes", this);
|
||||
|
@ -37,7 +37,7 @@ namespace CSVRender
|
|||
|
||||
void PathgridSelectionMode::removeSelectedNodes()
|
||||
{
|
||||
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (Mask_Pathgrid);
|
||||
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (SceneUtil::Mask_Pathgrid);
|
||||
|
||||
for (std::vector<osg::ref_ptr<TagBase> >::iterator it = selection.begin(); it != selection.end(); ++it)
|
||||
{
|
||||
|
@ -54,7 +54,7 @@ namespace CSVRender
|
|||
|
||||
void PathgridSelectionMode::removeSelectedEdges()
|
||||
{
|
||||
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (Mask_Pathgrid);
|
||||
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (SceneUtil::Mask_Pathgrid);
|
||||
|
||||
for (std::vector<osg::ref_ptr<TagBase> >::iterator it = selection.begin(); it != selection.end(); ++it)
|
||||
{
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <components/resource/scenemanager.hpp>
|
||||
#include <components/resource/resourcesystem.hpp>
|
||||
#include <components/sceneutil/lightmanager.hpp>
|
||||
#include <components/sceneutil/vismask.hpp>
|
||||
|
||||
#include "../widget/scenetoolmode.hpp"
|
||||
|
||||
|
@ -25,7 +26,6 @@
|
|||
#include "../../model/prefs/shortcuteventhandler.hpp"
|
||||
|
||||
#include "lighting.hpp"
|
||||
#include "mask.hpp"
|
||||
#include "cameracontroller.hpp"
|
||||
|
||||
namespace CSVRender
|
||||
|
@ -71,7 +71,7 @@ RenderWidget::RenderWidget(QWidget *parent, Qt::WindowFlags f)
|
|||
|
||||
SceneUtil::LightManager* lightMgr = new SceneUtil::LightManager;
|
||||
lightMgr->setStartLight(1);
|
||||
lightMgr->setLightingMask(Mask_Lighting);
|
||||
lightMgr->setLightingMask(SceneUtil::Mask_Lighting);
|
||||
mRootNode = lightMgr;
|
||||
|
||||
mView->getCamera()->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
|
||||
|
@ -88,7 +88,7 @@ RenderWidget::RenderWidget(QWidget *parent, Qt::WindowFlags f)
|
|||
// Add ability to signal osg to show its statistics for debugging purposes
|
||||
mView->addEventHandler(new osgViewer::StatsHandler);
|
||||
|
||||
mView->getCamera()->setCullMask(~(Mask_UpdateVisitor));
|
||||
mView->getCamera()->setCullMask(~(SceneUtil::Mask_UpdateVisitor));
|
||||
|
||||
viewer.addView(mView);
|
||||
viewer.setDone(false);
|
||||
|
@ -100,6 +100,14 @@ RenderWidget::~RenderWidget()
|
|||
try
|
||||
{
|
||||
CompositeViewer::get().removeView(mView);
|
||||
|
||||
#if OSG_VERSION_LESS_THAN(3,6,5)
|
||||
// before OSG 3.6.4, the default font was a static object, and if it wasn't attached to the scene when a graphics context was destroyed, it's program wouldn't be released.
|
||||
// 3.6.4 moved it into the object cache, which meant it usually got released, but not here.
|
||||
// 3.6.5 improved cleanup with osgViewer::CompositeViewer::removeView so it more reliably released associated state for objects in the object cache.
|
||||
osg::ref_ptr<osg::GraphicsContext> graphicsContext = mView->getCamera()->getGraphicsContext();
|
||||
osgText::Font::getDefaultFont()->releaseGLObjects(graphicsContext->getState());
|
||||
#endif
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
|
@ -114,7 +122,7 @@ void RenderWidget::flagAsModified()
|
|||
|
||||
void RenderWidget::setVisibilityMask(int mask)
|
||||
{
|
||||
mView->getCamera()->setCullMask(mask | Mask_ParticleSystem | Mask_Lighting);
|
||||
mView->getCamera()->setCullMask(mask | SceneUtil::Mask_ParticleSystem | SceneUtil::Mask_Lighting);
|
||||
}
|
||||
|
||||
osg::Camera *RenderWidget::getCamera()
|
||||
|
@ -204,7 +212,7 @@ SceneWidget::SceneWidget(std::shared_ptr<Resource::ResourceSystem> resourceSyste
|
|||
mOrbitCamControl = new OrbitCameraController(this);
|
||||
mCurrentCamControl = mFreeCamControl;
|
||||
|
||||
mOrbitCamControl->setPickingMask(Mask_Reference | Mask_Terrain);
|
||||
mOrbitCamControl->setPickingMask(SceneUtil::Mask_EditorReference | SceneUtil::Mask_Terrain);
|
||||
|
||||
mOrbitCamControl->setConstRoll( CSMPrefs::get()["3D Scene Input"]["navi-orbit-const-roll"].isTrue() );
|
||||
|
||||
|
@ -213,7 +221,7 @@ SceneWidget::SceneWidget(std::shared_ptr<Resource::ResourceSystem> resourceSyste
|
|||
|
||||
setLighting(&mLightingDay);
|
||||
|
||||
mResourceSystem->getSceneManager()->setParticleSystemMask(Mask_ParticleSystem);
|
||||
mResourceSystem->getSceneManager()->setParticleSystemMask(SceneUtil::Mask_ParticleSystem);
|
||||
|
||||
// Recieve mouse move event even if mouse button is not pressed
|
||||
setMouseTracking(true);
|
||||
|
@ -342,7 +350,7 @@ void SceneWidget::update(double dt)
|
|||
}
|
||||
else
|
||||
{
|
||||
mCurrentCamControl->setup(mRootNode, Mask_Reference | Mask_Terrain, CameraController::WorldUp);
|
||||
mCurrentCamControl->setup(mRootNode, SceneUtil::Mask_EditorReference | SceneUtil::Mask_Terrain, CameraController::WorldUp);
|
||||
mCamPositionSet = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
|
||||
#include "../widget/scenetoolmode.hpp"
|
||||
|
||||
#include "mask.hpp"
|
||||
|
||||
class QAction;
|
||||
|
||||
namespace CSVRender
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
|
||||
#include "tagbase.hpp"
|
||||
|
||||
CSVRender::TagBase::TagBase (Mask mask) : mMask (mask) {}
|
||||
CSVRender::TagBase::TagBase (SceneUtil::VisMask mask) : mMask (mask) {}
|
||||
|
||||
CSVRender::Mask CSVRender::TagBase::getMask() const
|
||||
SceneUtil::VisMask CSVRender::TagBase::getMask() const
|
||||
{
|
||||
return mMask;
|
||||
}
|
||||
|
|
|
@ -5,19 +5,19 @@
|
|||
|
||||
#include <QString>
|
||||
|
||||
#include "mask.hpp"
|
||||
#include <components/sceneutil/vismask.hpp>
|
||||
|
||||
namespace CSVRender
|
||||
{
|
||||
class TagBase : public osg::Referenced
|
||||
{
|
||||
Mask mMask;
|
||||
SceneUtil::VisMask mMask;
|
||||
|
||||
public:
|
||||
|
||||
TagBase (Mask mask);
|
||||
TagBase (SceneUtil::VisMask mask);
|
||||
|
||||
Mask getMask() const;
|
||||
SceneUtil::VisMask getMask() const;
|
||||
|
||||
virtual QString getToolTip (bool hideBasics) const;
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include <components/esm/loadland.hpp>
|
||||
#include <components/debug/debuglog.hpp>
|
||||
#include <components/sceneutil/vismask.hpp>
|
||||
|
||||
#include "../widget/brushshapes.hpp"
|
||||
#include "../widget/modebutton.hpp"
|
||||
|
@ -38,13 +39,12 @@
|
|||
|
||||
#include "editmode.hpp"
|
||||
#include "pagedworldspacewidget.hpp"
|
||||
#include "mask.hpp"
|
||||
#include "tagbase.hpp"
|
||||
#include "terrainselection.hpp"
|
||||
#include "worldspacewidget.hpp"
|
||||
|
||||
CSVRender::TerrainShapeMode::TerrainShapeMode (WorldspaceWidget *worldspaceWidget, osg::Group* parentNode, QWidget *parent)
|
||||
: EditMode (worldspaceWidget, QIcon {":scenetoolbar/editing-terrain-shape"}, Mask_Terrain | Mask_Reference, "Terrain land editing", parent),
|
||||
: EditMode (worldspaceWidget, QIcon {":scenetoolbar/editing-terrain-shape"}, SceneUtil::Mask_Terrain | SceneUtil::Mask_EditorReference, "Terrain land editing", parent),
|
||||
mParentNode(parentNode)
|
||||
{
|
||||
}
|
||||
|
@ -273,7 +273,6 @@ void CSVRender::TerrainShapeMode::applyTerrainEditChanges()
|
|||
*document.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures));
|
||||
|
||||
int landshapeColumn = landTable.findColumnIndex(CSMWorld::Columns::ColumnId_LandHeightsIndex);
|
||||
int landMapLodColumn = landTable.findColumnIndex(CSMWorld::Columns::ColumnId_LandMapLodIndex);
|
||||
int landnormalsColumn = landTable.findColumnIndex(CSMWorld::Columns::ColumnId_LandNormalsIndex);
|
||||
|
||||
QUndoStack& undoStack = document.getUndoStack();
|
||||
|
@ -287,9 +286,7 @@ void CSVRender::TerrainShapeMode::applyTerrainEditChanges()
|
|||
std::string cellId = CSMWorld::CellCoordinates::generateId(cellCoordinates.getX(), cellCoordinates.getY());
|
||||
undoStack.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, cellId));
|
||||
const CSMWorld::LandHeightsColumn::DataType landShapePointer = landTable.data(landTable.getModelIndex(cellId, landshapeColumn)).value<CSMWorld::LandHeightsColumn::DataType>();
|
||||
const CSMWorld::LandMapLodColumn::DataType landMapLodPointer = landTable.data(landTable.getModelIndex(cellId, landMapLodColumn)).value<CSMWorld::LandMapLodColumn::DataType>();
|
||||
CSMWorld::LandHeightsColumn::DataType landShapeNew(landShapePointer);
|
||||
CSMWorld::LandMapLodColumn::DataType mapLodShapeNew(landMapLodPointer);
|
||||
CSVRender::PagedWorldspaceWidget *paged = dynamic_cast<CSVRender::PagedWorldspaceWidget *> (&getWorldspaceWidget());
|
||||
|
||||
// Generate land height record
|
||||
|
@ -304,26 +301,7 @@ void CSVRender::TerrainShapeMode::applyTerrainEditChanges()
|
|||
}
|
||||
}
|
||||
|
||||
// Generate WNAM record
|
||||
int sqrtLandGlobalMapLodSize = sqrt(ESM::Land::LAND_GLOBAL_MAP_LOD_SIZE);
|
||||
for(int i = 0; i < sqrtLandGlobalMapLodSize; ++i)
|
||||
{
|
||||
for(int j = 0; j < sqrtLandGlobalMapLodSize; ++j)
|
||||
{
|
||||
int col = (static_cast<float>(j) / sqrtLandGlobalMapLodSize) * (ESM::Land::LAND_SIZE - 1);
|
||||
int row = (static_cast<float>(i) / sqrtLandGlobalMapLodSize) * (ESM::Land::LAND_SIZE - 1);
|
||||
signed char lodHeight = 0;
|
||||
float floatLodHeight = 0;
|
||||
if (landShapeNew[col * ESM::Land::LAND_SIZE + row] > 0) floatLodHeight = landShapeNew[col * ESM::Land::LAND_SIZE + row] / 128;
|
||||
if (landShapeNew[col * ESM::Land::LAND_SIZE + row] <= 0) floatLodHeight = landShapeNew[col * ESM::Land::LAND_SIZE + row] / 16;
|
||||
if (floatLodHeight > std::numeric_limits<signed char>::max()) lodHeight = std::numeric_limits<signed char>::max();
|
||||
else if (floatLodHeight < std::numeric_limits<signed char>::min()) lodHeight = std::numeric_limits<signed char>::min();
|
||||
else lodHeight = static_cast<signed char>(floatLodHeight);
|
||||
mapLodShapeNew[j * sqrtLandGlobalMapLodSize + i] = lodHeight;
|
||||
}
|
||||
}
|
||||
pushEditToCommand(landShapeNew, document, landTable, cellId);
|
||||
pushLodToCommand(mapLodShapeNew, document, landTable, cellId);
|
||||
}
|
||||
|
||||
for(CSMWorld::CellCoordinates cellCoordinates: mAlteredCells)
|
||||
|
@ -1136,18 +1114,6 @@ void CSVRender::TerrainShapeMode::pushNormalsEditToCommand(const CSMWorld::LandN
|
|||
undoStack.push (new CSMWorld::ModifyCommand(landTable, index, changedLand));
|
||||
}
|
||||
|
||||
void CSVRender::TerrainShapeMode::pushLodToCommand(const CSMWorld::LandMapLodColumn::DataType& newLandMapLod, CSMDoc::Document& document,
|
||||
CSMWorld::IdTable& landTable, const std::string& cellId)
|
||||
{
|
||||
QVariant changedLod;
|
||||
changedLod.setValue(newLandMapLod);
|
||||
|
||||
QModelIndex index(landTable.getModelIndex (cellId, landTable.findColumnIndex (CSMWorld::Columns::ColumnId_LandMapLodIndex)));
|
||||
|
||||
QUndoStack& undoStack = document.getUndoStack();
|
||||
undoStack.push (new CSMWorld::ModifyCommand(landTable, index, changedLod));
|
||||
}
|
||||
|
||||
bool CSVRender::TerrainShapeMode::noCell(const std::string& cellId)
|
||||
{
|
||||
CSMDoc::Document& document = getWorldspaceWidget().getDocument();
|
||||
|
|
|
@ -148,10 +148,6 @@ namespace CSVRender
|
|||
void pushNormalsEditToCommand(const CSMWorld::LandNormalsColumn::DataType& newLandGrid, CSMDoc::Document& document,
|
||||
CSMWorld::IdTable& landTable, const std::string& cellId);
|
||||
|
||||
/// Generate new land map LOD
|
||||
void pushLodToCommand(const CSMWorld::LandMapLodColumn::DataType& newLandMapLod, CSMDoc::Document& document,
|
||||
CSMWorld::IdTable& landTable, const std::string& cellId);
|
||||
|
||||
bool noCell(const std::string& cellId);
|
||||
|
||||
bool noLand(const std::string& cellId);
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <osg/Group>
|
||||
|
||||
#include <components/esm/loadland.hpp>
|
||||
#include <components/sceneutil/vismask.hpp>
|
||||
|
||||
#include "../widget/modebutton.hpp"
|
||||
#include "../widget/scenetoolbar.hpp"
|
||||
|
@ -34,12 +35,11 @@
|
|||
|
||||
#include "editmode.hpp"
|
||||
#include "pagedworldspacewidget.hpp"
|
||||
#include "mask.hpp"
|
||||
#include "object.hpp" // Something small needed regarding pointers from here ()
|
||||
#include "worldspacewidget.hpp"
|
||||
|
||||
CSVRender::TerrainTextureMode::TerrainTextureMode (WorldspaceWidget *worldspaceWidget, osg::Group* parentNode, QWidget *parent)
|
||||
: EditMode (worldspaceWidget, QIcon {":scenetoolbar/editing-terrain-texture"}, Mask_Terrain | Mask_Reference, "Terrain texture editing", parent),
|
||||
: EditMode (worldspaceWidget, QIcon {":scenetoolbar/editing-terrain-texture"}, SceneUtil::Mask_Terrain | SceneUtil::Mask_EditorReference, "Terrain texture editing", parent),
|
||||
mBrushTexture("L0#0"),
|
||||
mBrushSize(1),
|
||||
mBrushShape(0),
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include "../widget/scenetooltoggle2.hpp"
|
||||
|
||||
#include "cameracontroller.hpp"
|
||||
#include "mask.hpp"
|
||||
#include "tagbase.hpp"
|
||||
|
||||
void CSVRender::UnpagedWorldspaceWidget::update()
|
||||
|
@ -304,8 +303,8 @@ void CSVRender::UnpagedWorldspaceWidget::addVisibilitySelectorButtons (
|
|||
CSVWidget::SceneToolToggle2 *tool)
|
||||
{
|
||||
WorldspaceWidget::addVisibilitySelectorButtons (tool);
|
||||
tool->addButton (Button_Terrain, Mask_Terrain, "Terrain", "", true);
|
||||
tool->addButton (Button_Fog, Mask_Fog, "Fog");
|
||||
tool->addButton (Button_Terrain, SceneUtil::Mask_Terrain, "Terrain", "", true);
|
||||
//tool->addButton (Button_Fog, Mask_Fog, "Fog");
|
||||
}
|
||||
|
||||
std::string CSVRender::UnpagedWorldspaceWidget::getStartupInstruction()
|
||||
|
|
|
@ -26,8 +26,9 @@
|
|||
#include "../widget/scenetooltoggle2.hpp"
|
||||
#include "../widget/scenetoolrun.hpp"
|
||||
|
||||
#include <components/sceneutil/vismask.hpp>
|
||||
|
||||
#include "object.hpp"
|
||||
#include "mask.hpp"
|
||||
#include "instancemode.hpp"
|
||||
#include "pathgridmode.hpp"
|
||||
#include "cameracontroller.hpp"
|
||||
|
@ -138,7 +139,7 @@ void CSVRender::WorldspaceWidget::settingChanged (const CSMPrefs::Setting *setti
|
|||
{
|
||||
float alpha = setting->toDouble();
|
||||
// getSelection is virtual, thus this can not be called from the constructor
|
||||
auto selection = getSelection(Mask_Reference);
|
||||
auto selection = getSelection(SceneUtil::Mask_EditorReference);
|
||||
for (osg::ref_ptr<TagBase> tag : selection)
|
||||
{
|
||||
if (auto objTag = dynamic_cast<ObjectTag*>(tag.get()))
|
||||
|
@ -345,7 +346,7 @@ unsigned int CSVRender::WorldspaceWidget::getVisibilityMask() const
|
|||
|
||||
void CSVRender::WorldspaceWidget::setInteractionMask (unsigned int mask)
|
||||
{
|
||||
mInteractionMask = mask | Mask_CellMarker | Mask_CellArrow;
|
||||
mInteractionMask = mask | SceneUtil::Mask_EditorCellMarker | SceneUtil::Mask_EditorCellArrow;
|
||||
}
|
||||
|
||||
unsigned int CSVRender::WorldspaceWidget::getInteractionMask() const
|
||||
|
@ -361,15 +362,15 @@ void CSVRender::WorldspaceWidget::setEditLock (bool locked)
|
|||
void CSVRender::WorldspaceWidget::addVisibilitySelectorButtons (
|
||||
CSVWidget::SceneToolToggle2 *tool)
|
||||
{
|
||||
tool->addButton (Button_Reference, Mask_Reference, "Instances");
|
||||
tool->addButton (Button_Water, Mask_Water, "Water");
|
||||
tool->addButton (Button_Pathgrid, Mask_Pathgrid, "Pathgrid");
|
||||
tool->addButton (Button_Reference, SceneUtil::Mask_EditorReference, "Instances");
|
||||
tool->addButton (Button_Water, SceneUtil::Mask_Water, "Water");
|
||||
tool->addButton (Button_Pathgrid, SceneUtil::Mask_Pathgrid, "Pathgrid");
|
||||
}
|
||||
|
||||
void CSVRender::WorldspaceWidget::addEditModeSelectorButtons (CSVWidget::SceneToolMode *tool)
|
||||
{
|
||||
/// \todo replace EditMode with suitable subclasses
|
||||
tool->addButton (new InstanceMode (this, tool), "object");
|
||||
tool->addButton (new InstanceMode (this, mRootNode, tool), "object");
|
||||
tool->addButton (new PathgridMode (this, tool), "pathgrid");
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#include "../../model/world/tablemimedata.hpp"
|
||||
|
||||
#include "scenewidget.hpp"
|
||||
#include "mask.hpp"
|
||||
|
||||
namespace CSMPrefs
|
||||
{
|
||||
|
|
|
@ -18,10 +18,10 @@ set(GAME_HEADER
|
|||
source_group(game FILES ${GAME} ${GAME_HEADER})
|
||||
|
||||
add_openmw_dir (mwrender
|
||||
actors objects renderingmanager animation rotatecontroller sky npcanimation vismask
|
||||
actors objects renderingmanager animation rotatecontroller sky npcanimation
|
||||
creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation
|
||||
bulletdebugdraw globalmap characterpreview camera localmap water terrainstorage ripplesimulation
|
||||
renderbin actoranimation landmanager navmesh actorspaths
|
||||
renderbin actoranimation landmanager navmesh actorspaths recastmesh
|
||||
)
|
||||
|
||||
add_openmw_dir (mwinput
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <components/compiler/extensions0.hpp>
|
||||
|
||||
#include <components/sceneutil/vismask.hpp>
|
||||
#include <components/sceneutil/workqueue.hpp>
|
||||
|
||||
#include <components/files/configurationmanager.hpp>
|
||||
|
@ -47,8 +48,6 @@
|
|||
#include "mwworld/player.hpp"
|
||||
#include "mwworld/worldimp.hpp"
|
||||
|
||||
#include "mwrender/vismask.hpp"
|
||||
|
||||
#include "mwclass/classes.hpp"
|
||||
|
||||
#include "mwdialogue/dialoguemanagerimp.hpp"
|
||||
|
@ -558,7 +557,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
|||
std::string myguiResources = (mResDir / "mygui").string();
|
||||
osg::ref_ptr<osg::Group> guiRoot = new osg::Group;
|
||||
guiRoot->setName("GUI Root");
|
||||
guiRoot->setNodeMask(MWRender::Mask_GUI);
|
||||
guiRoot->setNodeMask(SceneUtil::Mask_GUI);
|
||||
rootNode->addChild(guiRoot);
|
||||
MWGui::WindowManager* window = new MWGui::WindowManager(mViewer, guiRoot, mResourceSystem.get(), mWorkQueue.get(),
|
||||
mCfgMgr.getLogPath().string() + std::string("/"), myguiResources,
|
||||
|
|
|
@ -325,6 +325,8 @@ namespace MWBase
|
|||
|
||||
virtual bool castRay (float x1, float y1, float z1, float x2, float y2, float z2) = 0;
|
||||
|
||||
virtual bool castRay(const osg::Vec3f& from, const osg::Vec3f& to, int mask, const MWWorld::ConstPtr& ignore) = 0;
|
||||
|
||||
virtual void setActorCollisionMode(const MWWorld::Ptr& ptr, bool internal, bool external) = 0;
|
||||
virtual bool isActorCollisionEnabled(const MWWorld::Ptr& ptr) = 0;
|
||||
|
||||
|
@ -653,6 +655,8 @@ namespace MWBase
|
|||
virtual MWPhysics::PhysicsSystem* getPhysicsSystem(void) = 0;
|
||||
|
||||
virtual void toggleWaterRTT(bool enable) = 0;
|
||||
|
||||
virtual bool isAreaOccupiedByOtherActor(const osg::Vec3f& position, const float radius, const MWWorld::ConstPtr& ignore) const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <components/esm/loadacti.hpp>
|
||||
#include <components/misc/rng.hpp>
|
||||
#include <components/sceneutil/positionattitudetransform.hpp>
|
||||
#include <components/sceneutil/vismask.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
|
@ -19,7 +20,6 @@
|
|||
|
||||
#include "../mwrender/objects.hpp"
|
||||
#include "../mwrender/renderinginterface.hpp"
|
||||
#include "../mwrender/vismask.hpp"
|
||||
|
||||
#include "../mwgui/tooltips.hpp"
|
||||
|
||||
|
@ -34,7 +34,7 @@ namespace MWClass
|
|||
if (!model.empty())
|
||||
{
|
||||
renderingInterface.getObjects().insertModel(ptr, model, true);
|
||||
ptr.getRefData().getBaseNode()->setNodeMask(MWRender::Mask_Static);
|
||||
ptr.getRefData().getBaseNode()->setNodeMask(SceneUtil::Mask_Static);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -317,7 +317,6 @@ namespace MWClass
|
|||
{
|
||||
if (!state.mHasCustomState)
|
||||
return;
|
||||
const ESM::ContainerState& state2 = dynamic_cast<const ESM::ContainerState&> (state);
|
||||
|
||||
if (!ptr.getRefData().getCustomData())
|
||||
{
|
||||
|
@ -326,21 +325,21 @@ namespace MWClass
|
|||
ptr.getRefData().setCustomData (data.release());
|
||||
}
|
||||
|
||||
dynamic_cast<ContainerCustomData&> (*ptr.getRefData().getCustomData()).mContainerStore.
|
||||
readState (state2.mInventory);
|
||||
ContainerCustomData& customData = ptr.getRefData().getCustomData()->asContainerCustomData();
|
||||
const ESM::ContainerState& containerState = state.asContainerState();
|
||||
customData.mContainerStore.readState (containerState.mInventory);
|
||||
}
|
||||
|
||||
void Container::writeAdditionalState (const MWWorld::ConstPtr& ptr, ESM::ObjectState& state) const
|
||||
{
|
||||
ESM::ContainerState& state2 = dynamic_cast<ESM::ContainerState&> (state);
|
||||
|
||||
if (!ptr.getRefData().getCustomData())
|
||||
{
|
||||
state.mHasCustomState = false;
|
||||
return;
|
||||
}
|
||||
|
||||
dynamic_cast<const ContainerCustomData&> (*ptr.getRefData().getCustomData()).mContainerStore.
|
||||
writeState (state2.mInventory);
|
||||
const ContainerCustomData& customData = ptr.getRefData().getCustomData()->asContainerCustomData();
|
||||
ESM::ContainerState& containerState = state.asContainerState();
|
||||
customData.mContainerStore.writeState (containerState.mInventory);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -777,8 +777,6 @@ namespace MWClass
|
|||
if (!state.mHasCustomState)
|
||||
return;
|
||||
|
||||
const ESM::CreatureState& state2 = dynamic_cast<const ESM::CreatureState&> (state);
|
||||
|
||||
if (state.mVersion > 0)
|
||||
{
|
||||
if (!ptr.getRefData().getCustomData())
|
||||
|
@ -798,16 +796,14 @@ namespace MWClass
|
|||
ensureCustomData(ptr); // in openmw 0.30 savegames not all state was saved yet, so need to load it regardless.
|
||||
|
||||
CreatureCustomData& customData = ptr.getRefData().getCustomData()->asCreatureCustomData();
|
||||
|
||||
customData.mContainerStore->readState (state2.mInventory);
|
||||
customData.mCreatureStats.readState (state2.mCreatureStats);
|
||||
const ESM::CreatureState& creatureState = state.asCreatureState();
|
||||
customData.mContainerStore->readState (creatureState.mInventory);
|
||||
customData.mCreatureStats.readState (creatureState.mCreatureStats);
|
||||
}
|
||||
|
||||
void Creature::writeAdditionalState (const MWWorld::ConstPtr& ptr, ESM::ObjectState& state)
|
||||
const
|
||||
{
|
||||
ESM::CreatureState& state2 = dynamic_cast<ESM::CreatureState&> (state);
|
||||
|
||||
if (!ptr.getRefData().getCustomData())
|
||||
{
|
||||
state.mHasCustomState = false;
|
||||
|
@ -815,9 +811,9 @@ namespace MWClass
|
|||
}
|
||||
|
||||
const CreatureCustomData& customData = ptr.getRefData().getCustomData()->asCreatureCustomData();
|
||||
|
||||
customData.mContainerStore->writeState (state2.mInventory);
|
||||
customData.mCreatureStats.writeState (state2.mCreatureStats);
|
||||
ESM::CreatureState& creatureState = state.asCreatureState();
|
||||
customData.mContainerStore->writeState (creatureState.mInventory);
|
||||
customData.mCreatureStats.writeState (creatureState.mCreatureStats);
|
||||
}
|
||||
|
||||
int Creature::getBaseGold(const MWWorld::ConstPtr& ptr) const
|
||||
|
|
|
@ -151,19 +151,16 @@ namespace MWClass
|
|||
if (!state.mHasCustomState)
|
||||
return;
|
||||
|
||||
const ESM::CreatureLevListState& state2 = dynamic_cast<const ESM::CreatureLevListState&> (state);
|
||||
|
||||
ensureCustomData(ptr);
|
||||
CreatureLevListCustomData& customData = ptr.getRefData().getCustomData()->asCreatureLevListCustomData();
|
||||
customData.mSpawnActorId = state2.mSpawnActorId;
|
||||
customData.mSpawn = state2.mSpawn;
|
||||
const ESM::CreatureLevListState& levListState = state.asCreatureLevListState();
|
||||
customData.mSpawnActorId = levListState.mSpawnActorId;
|
||||
customData.mSpawn = levListState.mSpawn;
|
||||
}
|
||||
|
||||
void CreatureLevList::writeAdditionalState (const MWWorld::ConstPtr& ptr, ESM::ObjectState& state)
|
||||
const
|
||||
{
|
||||
ESM::CreatureLevListState& state2 = dynamic_cast<ESM::CreatureLevListState&> (state);
|
||||
|
||||
if (!ptr.getRefData().getCustomData())
|
||||
{
|
||||
state.mHasCustomState = false;
|
||||
|
@ -171,7 +168,8 @@ namespace MWClass
|
|||
}
|
||||
|
||||
const CreatureLevListCustomData& customData = ptr.getRefData().getCustomData()->asCreatureLevListCustomData();
|
||||
state2.mSpawnActorId = customData.mSpawnActorId;
|
||||
state2.mSpawn = customData.mSpawn;
|
||||
ESM::CreatureLevListState& levListState = state.asCreatureLevListState();
|
||||
levListState.mSpawnActorId = customData.mSpawnActorId;
|
||||
levListState.mSpawn = customData.mSpawn;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <components/esm/loaddoor.hpp>
|
||||
#include <components/esm/doorstate.hpp>
|
||||
#include <components/sceneutil/positionattitudetransform.hpp>
|
||||
#include <components/sceneutil/vismask.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
|
@ -25,7 +26,6 @@
|
|||
#include "../mwrender/objects.hpp"
|
||||
#include "../mwrender/renderinginterface.hpp"
|
||||
#include "../mwrender/animation.hpp"
|
||||
#include "../mwrender/vismask.hpp"
|
||||
|
||||
#include "../mwmechanics/actorutil.hpp"
|
||||
|
||||
|
@ -58,7 +58,7 @@ namespace MWClass
|
|||
if (!model.empty())
|
||||
{
|
||||
renderingInterface.getObjects().insertModel(ptr, model, true);
|
||||
ptr.getRefData().getBaseNode()->setNodeMask(MWRender::Mask_Static);
|
||||
ptr.getRefData().getBaseNode()->setNodeMask(SceneUtil::Mask_Static);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -370,11 +370,11 @@ namespace MWClass
|
|||
{
|
||||
if (!state.mHasCustomState)
|
||||
return;
|
||||
|
||||
ensureCustomData(ptr);
|
||||
DoorCustomData& customData = ptr.getRefData().getCustomData()->asDoorCustomData();
|
||||
|
||||
const ESM::DoorState& state2 = dynamic_cast<const ESM::DoorState&>(state);
|
||||
customData.mDoorState = static_cast<MWWorld::DoorState>(state2.mDoorState);
|
||||
const ESM::DoorState& doorState = state.asDoorState();
|
||||
customData.mDoorState = MWWorld::DoorState(doorState.mDoorState);
|
||||
}
|
||||
|
||||
void Door::writeAdditionalState (const MWWorld::ConstPtr& ptr, ESM::ObjectState& state) const
|
||||
|
@ -384,10 +384,10 @@ namespace MWClass
|
|||
state.mHasCustomState = false;
|
||||
return;
|
||||
}
|
||||
const DoorCustomData& customData = ptr.getRefData().getCustomData()->asDoorCustomData();
|
||||
|
||||
ESM::DoorState& state2 = dynamic_cast<ESM::DoorState&>(state);
|
||||
state2.mDoorState = static_cast<int>(customData.mDoorState);
|
||||
const DoorCustomData& customData = ptr.getRefData().getCustomData()->asDoorCustomData();
|
||||
ESM::DoorState& doorState = state.asDoorState();
|
||||
doorState.mDoorState = int(customData.mDoorState);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1307,8 +1307,6 @@ namespace MWClass
|
|||
if (!state.mHasCustomState)
|
||||
return;
|
||||
|
||||
const ESM::NpcState& state2 = dynamic_cast<const ESM::NpcState&> (state);
|
||||
|
||||
if (state.mVersion > 0)
|
||||
{
|
||||
if (!ptr.getRefData().getCustomData())
|
||||
|
@ -1322,17 +1320,15 @@ namespace MWClass
|
|||
ensureCustomData(ptr); // in openmw 0.30 savegames not all state was saved yet, so need to load it regardless.
|
||||
|
||||
NpcCustomData& customData = ptr.getRefData().getCustomData()->asNpcCustomData();
|
||||
|
||||
customData.mInventoryStore.readState (state2.mInventory);
|
||||
customData.mNpcStats.readState (state2.mNpcStats);
|
||||
static_cast<MWMechanics::CreatureStats&> (customData.mNpcStats).readState (state2.mCreatureStats);
|
||||
const ESM::NpcState& npcState = state.asNpcState();
|
||||
customData.mInventoryStore.readState (npcState.mInventory);
|
||||
customData.mNpcStats.readState (npcState.mNpcStats);
|
||||
customData.mNpcStats.readState (npcState.mCreatureStats);
|
||||
}
|
||||
|
||||
void Npc::writeAdditionalState (const MWWorld::ConstPtr& ptr, ESM::ObjectState& state)
|
||||
const
|
||||
{
|
||||
ESM::NpcState& state2 = dynamic_cast<ESM::NpcState&> (state);
|
||||
|
||||
if (!ptr.getRefData().getCustomData())
|
||||
{
|
||||
state.mHasCustomState = false;
|
||||
|
@ -1340,10 +1336,10 @@ namespace MWClass
|
|||
}
|
||||
|
||||
const NpcCustomData& customData = ptr.getRefData().getCustomData()->asNpcCustomData();
|
||||
|
||||
customData.mInventoryStore.writeState (state2.mInventory);
|
||||
customData.mNpcStats.writeState (state2.mNpcStats);
|
||||
static_cast<const MWMechanics::CreatureStats&> (customData.mNpcStats).writeState (state2.mCreatureStats);
|
||||
ESM::NpcState& npcState = state.asNpcState();
|
||||
customData.mInventoryStore.writeState (npcState.mInventory);
|
||||
customData.mNpcStats.writeState (npcState.mNpcStats);
|
||||
customData.mNpcStats.writeState (npcState.mCreatureStats);
|
||||
}
|
||||
|
||||
int Npc::getBaseGold(const MWWorld::ConstPtr& ptr) const
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <components/esm/loadstat.hpp>
|
||||
#include <components/sceneutil/positionattitudetransform.hpp>
|
||||
#include <components/sceneutil/vismask.hpp>
|
||||
|
||||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwphysics/physicssystem.hpp"
|
||||
|
@ -9,7 +10,6 @@
|
|||
|
||||
#include "../mwrender/objects.hpp"
|
||||
#include "../mwrender/renderinginterface.hpp"
|
||||
#include "../mwrender/vismask.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
|
@ -19,7 +19,7 @@ namespace MWClass
|
|||
if (!model.empty())
|
||||
{
|
||||
renderingInterface.getObjects().insertModel(ptr, model);
|
||||
ptr.getRefData().getBaseNode()->setNodeMask(MWRender::Mask_Static);
|
||||
ptr.getRefData().getBaseNode()->setNodeMask(SceneUtil::Mask_Static);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <MyGUI_Gui.h>
|
||||
#include <MyGUI_Button.h>
|
||||
#include <MyGUI_EditBox.h>
|
||||
#include <MyGUI_ComboBox.h>
|
||||
#include <MyGUI_ControllerManager.h>
|
||||
#include <MyGUI_ControllerRepeatClick.h>
|
||||
|
||||
|
@ -17,6 +18,7 @@
|
|||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
|
||||
#include <MyGUI_Macros.h>
|
||||
#include <components/esm/records.hpp>
|
||||
|
||||
#include "inventoryitemmodel.hpp"
|
||||
|
@ -29,6 +31,7 @@ namespace MWGui
|
|||
{
|
||||
AlchemyWindow::AlchemyWindow()
|
||||
: WindowBase("openmw_alchemy_window.layout")
|
||||
, mModel(nullptr)
|
||||
, mSortModel(nullptr)
|
||||
, mAlchemy(new MWMechanics::Alchemy())
|
||||
, mApparatus (4)
|
||||
|
@ -50,6 +53,8 @@ namespace MWGui
|
|||
getWidget(mDecreaseButton, "DecreaseButton");
|
||||
getWidget(mNameEdit, "NameEdit");
|
||||
getWidget(mItemView, "ItemView");
|
||||
getWidget(mFilterValue, "FilterValue");
|
||||
getWidget(mFilterType, "FilterType");
|
||||
|
||||
mBrewCountEdit->eventValueChanged += MyGUI::newDelegate(this, &AlchemyWindow::onCountValueChanged);
|
||||
mBrewCountEdit->eventEditSelectAccept += MyGUI::newDelegate(this, &AlchemyWindow::onAccept);
|
||||
|
@ -72,6 +77,9 @@ namespace MWGui
|
|||
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onCancelButtonClicked);
|
||||
|
||||
mNameEdit->eventEditSelectAccept += MyGUI::newDelegate(this, &AlchemyWindow::onAccept);
|
||||
mFilterValue->eventComboChangePosition += MyGUI::newDelegate(this, &AlchemyWindow::onFilterChanged);
|
||||
mFilterValue->eventEditTextChange += MyGUI::newDelegate(this, &AlchemyWindow::onFilterEdited);
|
||||
mFilterType->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::switchFilterType);
|
||||
|
||||
center();
|
||||
}
|
||||
|
@ -136,16 +144,110 @@ namespace MWGui
|
|||
removeIngredient(mIngredients[i]);
|
||||
}
|
||||
|
||||
updateFilters();
|
||||
update();
|
||||
}
|
||||
|
||||
void AlchemyWindow::initFilter()
|
||||
{
|
||||
auto const& wm = MWBase::Environment::get().getWindowManager();
|
||||
auto const ingredient = wm->getGameSettingString("sIngredients", "Ingredients");
|
||||
auto const effect = wm->getGameSettingString("sMagicEffects", "Magic Effects");
|
||||
|
||||
if (mFilterType->getCaption() == ingredient)
|
||||
mCurrentFilter = FilterType::ByName;
|
||||
else
|
||||
mCurrentFilter = FilterType::ByEffect;
|
||||
updateFilters();
|
||||
mFilterValue->clearIndexSelected();
|
||||
updateFilters();
|
||||
}
|
||||
|
||||
void AlchemyWindow::switchFilterType(MyGUI::Widget* _sender)
|
||||
{
|
||||
auto const& wm = MWBase::Environment::get().getWindowManager();
|
||||
auto const ingredient = wm->getGameSettingString("sIngredients", "Ingredients");
|
||||
auto const effect = wm->getGameSettingString("sMagicEffects", "Magic Effects");
|
||||
auto *button = _sender->castType<MyGUI::Button>();
|
||||
|
||||
if (button->getCaption() == ingredient)
|
||||
{
|
||||
button->setCaption(effect);
|
||||
mCurrentFilter = FilterType::ByEffect;
|
||||
}
|
||||
else
|
||||
{
|
||||
button->setCaption(ingredient);
|
||||
mCurrentFilter = FilterType::ByName;
|
||||
}
|
||||
mSortModel->setNameFilter({});
|
||||
mSortModel->setEffectFilter({});
|
||||
mFilterValue->clearIndexSelected();
|
||||
updateFilters();
|
||||
mItemView->update();
|
||||
}
|
||||
|
||||
void AlchemyWindow::updateFilters()
|
||||
{
|
||||
std::set<std::string> itemNames, itemEffects;
|
||||
for (size_t i = 0; i < mModel->getItemCount(); ++i)
|
||||
{
|
||||
auto const& base = mModel->getItem(i).mBase;
|
||||
if (base.getTypeName() != typeid(ESM::Ingredient).name())
|
||||
continue;
|
||||
|
||||
itemNames.insert(base.getClass().getName(base));
|
||||
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
|
||||
auto const alchemySkill = player.getClass().getSkill(player, ESM::Skill::Alchemy);
|
||||
|
||||
auto const effects = MWMechanics::Alchemy::effectsDescription(base, alchemySkill);
|
||||
itemEffects.insert(effects.begin(), effects.end());
|
||||
}
|
||||
|
||||
mFilterValue->removeAllItems();
|
||||
auto const addItems = [&](auto const& container)
|
||||
{
|
||||
for (auto const& item : container)
|
||||
mFilterValue->addItem(item);
|
||||
};
|
||||
switch (mCurrentFilter)
|
||||
{
|
||||
case FilterType::ByName: addItems(itemNames); break;
|
||||
case FilterType::ByEffect: addItems(itemEffects); break;
|
||||
}
|
||||
}
|
||||
|
||||
void AlchemyWindow::applyFilter(const std::string& filter)
|
||||
{
|
||||
switch (mCurrentFilter)
|
||||
{
|
||||
case FilterType::ByName: mSortModel->setNameFilter(filter); break;
|
||||
case FilterType::ByEffect: mSortModel->setEffectFilter(filter); break;
|
||||
}
|
||||
mItemView->update();
|
||||
}
|
||||
|
||||
void AlchemyWindow::onFilterChanged(MyGUI::ComboBox* _sender, size_t _index)
|
||||
{
|
||||
// ignore spurious event fired when one edit the content after selection.
|
||||
// onFilterEdited will handle it.
|
||||
if (_index != MyGUI::ITEM_NONE)
|
||||
applyFilter(_sender->getItemNameAt(_index));
|
||||
}
|
||||
|
||||
void AlchemyWindow::onFilterEdited(MyGUI::EditBox* _sender)
|
||||
{
|
||||
applyFilter(_sender->getCaption());
|
||||
}
|
||||
|
||||
void AlchemyWindow::onOpen()
|
||||
{
|
||||
mAlchemy->clear();
|
||||
mAlchemy->setAlchemist (MWMechanics::getPlayer());
|
||||
|
||||
InventoryItemModel* model = new InventoryItemModel(MWMechanics::getPlayer());
|
||||
mSortModel = new SortFilterItemModel(model);
|
||||
mModel = new InventoryItemModel(MWMechanics::getPlayer());
|
||||
mSortModel = new SortFilterItemModel(mModel);
|
||||
mSortModel->setFilter(SortFilterItemModel::Filter_OnlyIngredients);
|
||||
mItemView->setModel (mSortModel);
|
||||
mItemView->resetScrollBars();
|
||||
|
@ -167,6 +269,7 @@ namespace MWGui
|
|||
}
|
||||
|
||||
update();
|
||||
initFilter();
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mNameEdit);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
#include <vector>
|
||||
|
||||
#include <MyGUI_ControllerItem.h>
|
||||
#include <MyGUI_ComboBox.h>
|
||||
|
||||
#include <components/widgets/box.hpp>
|
||||
#include <components/widgets/numericeditbox.hpp>
|
||||
|
||||
#include "windowbase.hpp"
|
||||
|
@ -19,6 +21,7 @@ namespace MWGui
|
|||
{
|
||||
class ItemView;
|
||||
class ItemWidget;
|
||||
class InventoryItemModel;
|
||||
class SortFilterItemModel;
|
||||
|
||||
class AlchemyWindow : public WindowBase
|
||||
|
@ -36,8 +39,11 @@ namespace MWGui
|
|||
static const float sCountChangeInterval; // in seconds
|
||||
|
||||
std::string mSuggestedPotionName;
|
||||
enum class FilterType { ByName, ByEffect };
|
||||
FilterType mCurrentFilter;
|
||||
|
||||
ItemView* mItemView;
|
||||
InventoryItemModel* mModel;
|
||||
SortFilterItemModel* mSortModel;
|
||||
|
||||
MyGUI::Button* mCreateButton;
|
||||
|
@ -47,6 +53,8 @@ namespace MWGui
|
|||
|
||||
MyGUI::Button* mIncreaseButton;
|
||||
MyGUI::Button* mDecreaseButton;
|
||||
Gui::AutoSizedButton* mFilterType;
|
||||
MyGUI::ComboBox* mFilterValue;
|
||||
MyGUI::EditBox* mNameEdit;
|
||||
Gui::NumericEditBox* mBrewCountEdit;
|
||||
|
||||
|
@ -60,6 +68,13 @@ namespace MWGui
|
|||
void onCountValueChanged(int value);
|
||||
void onRepeatClick(MyGUI::Widget* widget, MyGUI::ControllerItem* controller);
|
||||
|
||||
void applyFilter(const std::string& filter);
|
||||
void initFilter();
|
||||
void onFilterChanged(MyGUI::ComboBox* _sender, size_t _index);
|
||||
void onFilterEdited(MyGUI::EditBox* _sender);
|
||||
void switchFilterType(MyGUI::Widget* _sender);
|
||||
void updateFilters();
|
||||
|
||||
void addRepeatController(MyGUI::Widget* widget);
|
||||
|
||||
void onIncreaseButtonTriggered();
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace MWGui
|
|||
/**
|
||||
* @brief A variant of MyGUI::ImageBox with aspect ratio correction using black bars
|
||||
*/
|
||||
class BackgroundImage : public MyGUI::ImageBox
|
||||
class BackgroundImage final : public MyGUI::ImageBox
|
||||
{
|
||||
MYGUI_RTTI_DERIVED(BackgroundImage)
|
||||
|
||||
|
@ -22,8 +22,8 @@ namespace MWGui
|
|||
*/
|
||||
void setBackgroundImage (const std::string& image, bool fixedRatio=true, bool stretch=true);
|
||||
|
||||
virtual void setSize (const MyGUI::IntSize &_value);
|
||||
virtual void setCoord (const MyGUI::IntCoord &_value);
|
||||
void setSize (const MyGUI::IntSize &_value) final;
|
||||
void setCoord (const MyGUI::IntCoord &_value) final;
|
||||
|
||||
private:
|
||||
MyGUI::ImageBox* mChild;
|
||||
|
|
|
@ -817,7 +817,7 @@ namespace
|
|||
};
|
||||
}
|
||||
|
||||
class PageDisplay : public MyGUI::ISubWidgetText
|
||||
class PageDisplay final : public MyGUI::ISubWidgetText
|
||||
{
|
||||
MYGUI_RTTI_DERIVED(PageDisplay)
|
||||
protected:
|
||||
|
@ -1140,7 +1140,7 @@ public:
|
|||
i->second->createDrawItem (mNode);
|
||||
}
|
||||
|
||||
void setVisible (bool newVisible)
|
||||
void setVisible (bool newVisible) final
|
||||
{
|
||||
if (mVisible == newVisible)
|
||||
return;
|
||||
|
@ -1162,7 +1162,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void createDrawItem(MyGUI::ITexture* texture, MyGUI::ILayerNode* node)
|
||||
void createDrawItem(MyGUI::ITexture* texture, MyGUI::ILayerNode* node) final
|
||||
{
|
||||
mNode = node;
|
||||
|
||||
|
@ -1230,9 +1230,9 @@ public:
|
|||
|
||||
// ISubWidget should not necessarily be a drawitem
|
||||
// in this case, it is not...
|
||||
void doRender() { }
|
||||
void doRender() final { }
|
||||
|
||||
void _updateView ()
|
||||
void _updateView () final
|
||||
{
|
||||
_checkMargin();
|
||||
|
||||
|
@ -1241,7 +1241,7 @@ public:
|
|||
mNode->outOfDate (i->second->mRenderItem);
|
||||
}
|
||||
|
||||
void _correctView()
|
||||
void _correctView() final
|
||||
{
|
||||
_checkMargin ();
|
||||
|
||||
|
@ -1251,7 +1251,7 @@ public:
|
|||
|
||||
}
|
||||
|
||||
void destroyDrawItem()
|
||||
void destroyDrawItem() final
|
||||
{
|
||||
for (ActiveTextFormats::iterator i = mActiveTextFormats.begin (); i != mActiveTextFormats.end (); ++i)
|
||||
i->second->destroyDrawItem (mNode);
|
||||
|
@ -1261,7 +1261,7 @@ public:
|
|||
};
|
||||
|
||||
|
||||
class BookPageImpl : public BookPage
|
||||
class BookPageImpl final : public BookPage
|
||||
{
|
||||
MYGUI_RTTI_DERIVED(BookPage)
|
||||
public:
|
||||
|
@ -1271,24 +1271,24 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
void showPage (TypesetBook::Ptr book, size_t page)
|
||||
void showPage (TypesetBook::Ptr book, size_t page) final
|
||||
{
|
||||
mPageDisplay->showPage (book, page);
|
||||
}
|
||||
|
||||
void adviseLinkClicked (std::function <void (InteractiveId)> linkClicked)
|
||||
void adviseLinkClicked (std::function <void (InteractiveId)> linkClicked) final
|
||||
{
|
||||
mPageDisplay->mLinkClicked = linkClicked;
|
||||
}
|
||||
|
||||
void unadviseLinkClicked ()
|
||||
void unadviseLinkClicked () final
|
||||
{
|
||||
mPageDisplay->mLinkClicked = std::function <void (InteractiveId)> ();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual void initialiseOverride()
|
||||
void initialiseOverride() final
|
||||
{
|
||||
Base::initialiseOverride();
|
||||
|
||||
|
@ -1302,24 +1302,24 @@ protected:
|
|||
}
|
||||
}
|
||||
|
||||
void onMouseLostFocus(Widget* _new)
|
||||
void onMouseLostFocus(Widget* _new) final
|
||||
{
|
||||
// NOTE: MyGUI also fires eventMouseLostFocus for widgets that are about to be destroyed (if they had focus).
|
||||
// Child widgets may already be destroyed! So be careful.
|
||||
mPageDisplay->onMouseLostFocus ();
|
||||
}
|
||||
|
||||
void onMouseMove(int left, int top)
|
||||
void onMouseMove(int left, int top) final
|
||||
{
|
||||
mPageDisplay->onMouseMove (left, top);
|
||||
}
|
||||
|
||||
void onMouseButtonPressed (int left, int top, MyGUI::MouseButton id)
|
||||
void onMouseButtonPressed (int left, int top, MyGUI::MouseButton id) final
|
||||
{
|
||||
mPageDisplay->onMouseButtonPressed (left, top, id);
|
||||
}
|
||||
|
||||
void onMouseButtonReleased(int left, int top, MyGUI::MouseButton id)
|
||||
void onMouseButtonReleased(int left, int top, MyGUI::MouseButton id) final
|
||||
{
|
||||
mPageDisplay->onMouseButtonReleased (left, top, id);
|
||||
}
|
||||
|
|
|
@ -46,9 +46,11 @@ CompanionWindow::CompanionWindow(DragAndDrop *dragAndDrop, MessageBoxManager* ma
|
|||
getWidget(mCloseButton, "CloseButton");
|
||||
getWidget(mProfitLabel, "ProfitLabel");
|
||||
getWidget(mEncumbranceBar, "EncumbranceBar");
|
||||
getWidget(mFilterEdit, "FilterEdit");
|
||||
getWidget(mItemView, "ItemView");
|
||||
mItemView->eventBackgroundClicked += MyGUI::newDelegate(this, &CompanionWindow::onBackgroundSelected);
|
||||
mItemView->eventItemClicked += MyGUI::newDelegate(this, &CompanionWindow::onItemSelected);
|
||||
mFilterEdit->eventEditTextChange += MyGUI::newDelegate(this, &CompanionWindow::onNameFilterChanged);
|
||||
|
||||
mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CompanionWindow::onCloseButtonClicked);
|
||||
|
||||
|
@ -92,6 +94,12 @@ void CompanionWindow::onItemSelected(int index)
|
|||
dragItem (nullptr, count);
|
||||
}
|
||||
|
||||
void CompanionWindow::onNameFilterChanged(MyGUI::EditBox* _sender)
|
||||
{
|
||||
mSortModel->setNameFilter(_sender->getCaption());
|
||||
mItemView->update();
|
||||
}
|
||||
|
||||
void CompanionWindow::dragItem(MyGUI::Widget* sender, int count)
|
||||
{
|
||||
mDragAndDrop->startDrag(mSelectedItem, mSortModel, mModel, mItemView, count);
|
||||
|
@ -113,6 +121,7 @@ void CompanionWindow::setPtr(const MWWorld::Ptr& npc)
|
|||
|
||||
mModel = new CompanionItemModel(npc);
|
||||
mSortModel = new SortFilterItemModel(mModel);
|
||||
mFilterEdit->setCaption(std::string());
|
||||
mItemView->setModel(mSortModel);
|
||||
mItemView->resetScrollBars();
|
||||
|
||||
|
|
|
@ -39,11 +39,13 @@ namespace MWGui
|
|||
DragAndDrop* mDragAndDrop;
|
||||
|
||||
MyGUI::Button* mCloseButton;
|
||||
MyGUI::EditBox* mFilterEdit;
|
||||
MyGUI::TextBox* mProfitLabel;
|
||||
Widgets::MWDynamicStat* mEncumbranceBar;
|
||||
MessageBoxManager* mMessageBoxManager;
|
||||
|
||||
void onItemSelected(int index);
|
||||
void onNameFilterChanged(MyGUI::EditBox* _sender);
|
||||
void onBackgroundSelected();
|
||||
void dragItem(MyGUI::Widget* sender, int count);
|
||||
|
||||
|
|
|
@ -14,14 +14,14 @@ namespace MWGui
|
|||
namespace Controllers
|
||||
{
|
||||
/// Automatically positions a widget below the mouse cursor.
|
||||
class ControllerFollowMouse :
|
||||
class ControllerFollowMouse final :
|
||||
public MyGUI::ControllerItem
|
||||
{
|
||||
MYGUI_RTTI_DERIVED( ControllerFollowMouse )
|
||||
|
||||
private:
|
||||
bool addTime(MyGUI::Widget* _widget, float _time);
|
||||
void prepareItem(MyGUI::Widget* _widget);
|
||||
bool addTime(MyGUI::Widget* _widget, float _time) final;
|
||||
void prepareItem(MyGUI::Widget* _widget) final;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace MWGui
|
|||
/// ResourceImageSetPointer that we need.
|
||||
/// \example MyGUI::FactoryManager::getInstance().registerFactory<ResourceImageSetPointerFix>("Resource", "ResourceImageSetPointer");
|
||||
/// MyGUI::ResourceManager::getInstance().load("core.xml");
|
||||
class ResourceImageSetPointerFix :
|
||||
class ResourceImageSetPointerFix final :
|
||||
public MyGUI::IPointer
|
||||
{
|
||||
MYGUI_RTTI_DERIVED( ResourceImageSetPointerFix )
|
||||
|
@ -20,17 +20,17 @@ namespace MWGui
|
|||
ResourceImageSetPointerFix();
|
||||
virtual ~ResourceImageSetPointerFix();
|
||||
|
||||
virtual void deserialization(MyGUI::xml::ElementPtr _node, MyGUI::Version _version);
|
||||
void deserialization(MyGUI::xml::ElementPtr _node, MyGUI::Version _version) final;
|
||||
|
||||
virtual void setImage(MyGUI::ImageBox* _image);
|
||||
virtual void setPosition(MyGUI::ImageBox* _image, const MyGUI::IntPoint& _point);
|
||||
void setImage(MyGUI::ImageBox* _image) final;
|
||||
void setPosition(MyGUI::ImageBox* _image, const MyGUI::IntPoint& _point) final;
|
||||
|
||||
//and now for the whole point of this class, allow us to get
|
||||
//the hot spot, the image and the size of the cursor.
|
||||
virtual MyGUI::ResourceImageSetPtr getImageSet();
|
||||
virtual MyGUI::IntPoint getHotSpot();
|
||||
virtual MyGUI::IntSize getSize();
|
||||
virtual int getRotation();
|
||||
MyGUI::ResourceImageSetPtr getImageSet();
|
||||
MyGUI::IntPoint getHotSpot();
|
||||
MyGUI::IntSize getSize();
|
||||
int getRotation();
|
||||
|
||||
private:
|
||||
MyGUI::IntPoint mPoint;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <MyGUI_RenderManager.h>
|
||||
#include <MyGUI_InputManager.h>
|
||||
#include <MyGUI_Button.h>
|
||||
#include <MyGUI_EditBox.h>
|
||||
|
||||
#include <osg/Texture2D>
|
||||
|
||||
|
@ -21,12 +22,10 @@
|
|||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
#include "../mwbase/scriptmanager.hpp"
|
||||
|
||||
#include "../mwworld/inventorystore.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/actionequip.hpp"
|
||||
#include "../mwscript/interpretercontext.hpp"
|
||||
|
||||
#include "../mwmechanics/actorutil.hpp"
|
||||
#include "../mwmechanics/creaturestats.hpp"
|
||||
|
@ -90,6 +89,7 @@ namespace MWGui
|
|||
getWidget(mLeftPane, "LeftPane");
|
||||
getWidget(mRightPane, "RightPane");
|
||||
getWidget(mArmorRating, "ArmorRating");
|
||||
getWidget(mFilterEdit, "FilterEdit");
|
||||
|
||||
mAvatarImage->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onAvatarClicked);
|
||||
mAvatarImage->setRenderItemTexture(mPreviewTexture.get());
|
||||
|
@ -104,6 +104,7 @@ namespace MWGui
|
|||
mFilterApparel->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged);
|
||||
mFilterMagic->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged);
|
||||
mFilterMisc->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged);
|
||||
mFilterEdit->eventEditTextChange += MyGUI::newDelegate(this, &InventoryWindow::onNameFilterChanged);
|
||||
|
||||
mFilterAll->setStateSelected(true);
|
||||
|
||||
|
@ -133,6 +134,8 @@ namespace MWGui
|
|||
else
|
||||
mSortModel = new SortFilterItemModel(mTradeModel);
|
||||
|
||||
mSortModel->setNameFilter(mFilterEdit->getCaption());
|
||||
|
||||
mItemView->setModel(mSortModel);
|
||||
|
||||
mFilterAll->setStateSelected(true);
|
||||
|
@ -388,6 +391,11 @@ namespace MWGui
|
|||
|
||||
void InventoryWindow::onOpen()
|
||||
{
|
||||
// Reset the filter focus when opening the window
|
||||
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
|
||||
if (focus == mFilterEdit)
|
||||
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(nullptr);
|
||||
|
||||
if (!mPtr.isEmpty())
|
||||
{
|
||||
updateEncumbranceBar();
|
||||
|
@ -465,6 +473,12 @@ namespace MWGui
|
|||
width*mScaleFactor/float(mPreview->getTextureWidth()), height*mScaleFactor/float(mPreview->getTextureHeight())));
|
||||
}
|
||||
|
||||
void InventoryWindow::onNameFilterChanged(MyGUI::EditBox* _sender)
|
||||
{
|
||||
mSortModel->setNameFilter(_sender->getCaption());
|
||||
mItemView->update();
|
||||
}
|
||||
|
||||
void InventoryWindow::onFilterChanged(MyGUI::Widget* _sender)
|
||||
{
|
||||
if (_sender == mFilterAll)
|
||||
|
@ -477,7 +491,6 @@ namespace MWGui
|
|||
mSortModel->setCategory(SortFilterItemModel::Category_Magic);
|
||||
else if (_sender == mFilterMisc)
|
||||
mSortModel->setCategory(SortFilterItemModel::Category_Misc);
|
||||
|
||||
mFilterAll->setStateSelected(false);
|
||||
mFilterWeapon->setStateSelected(false);
|
||||
mFilterApparel->setStateSelected(false);
|
||||
|
@ -507,6 +520,16 @@ namespace MWGui
|
|||
void InventoryWindow::useItem(const MWWorld::Ptr &ptr, bool force)
|
||||
{
|
||||
const std::string& script = ptr.getClass().getScript(ptr);
|
||||
if (!script.empty())
|
||||
{
|
||||
// Don't try to equip the item if PCSkipEquip is set to 1
|
||||
if (ptr.getRefData().getLocals().getIntVar(script, "pcskipequip") == 1)
|
||||
{
|
||||
ptr.getRefData().getLocals().setVarByInt(script, "onpcequip", 1);
|
||||
return;
|
||||
}
|
||||
ptr.getRefData().getLocals().setVarByInt(script, "onpcequip", 0);
|
||||
}
|
||||
|
||||
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||
|
||||
|
@ -526,43 +549,28 @@ namespace MWGui
|
|||
|
||||
if (canEquip.first == 0)
|
||||
{
|
||||
/// If PCSkipEquip is set, set OnPCEquip to 1 and don't message anything
|
||||
if (!script.empty() && ptr.getRefData().getLocals().getIntVar(script, "pcskipequip") == 1)
|
||||
ptr.getRefData().getLocals().setVarByInt(script, "onpcequip", 1);
|
||||
else
|
||||
MWBase::Environment::get().getWindowManager()->messageBox(canEquip.second);
|
||||
MWBase::Environment::get().getWindowManager()->messageBox(canEquip.second);
|
||||
updateItemView();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the item has a script, set its OnPcEquip to 1
|
||||
if (!script.empty()
|
||||
// Another morrowind oddity: when an item has skipped equipping and pcskipequip is reset to 0 afterwards,
|
||||
// the next time it is equipped will work normally, but will not set onpcequip
|
||||
&& (ptr != mSkippedToEquip || ptr.getRefData().getLocals().getIntVar(script, "pcskipequip") == 1))
|
||||
ptr.getRefData().getLocals().setVarByInt(script, "onpcequip", 1);
|
||||
|
||||
// Give the script a chance to run once before we do anything else
|
||||
// this is important when setting pcskipequip as a reaction to onpcequip being set (bk_treasuryreport does this)
|
||||
if (!force && !script.empty() && MWBase::Environment::get().getWorld()->getScriptsEnabled())
|
||||
// If the item has a script, set OnPCEquip or PCSkipEquip to 1
|
||||
if (!script.empty())
|
||||
{
|
||||
MWScript::InterpreterContext interpreterContext (&ptr.getRefData().getLocals(), ptr);
|
||||
MWBase::Environment::get().getScriptManager()->run (script, interpreterContext);
|
||||
// Ingredients, books and repair hammers must not have OnPCEquip set to 1 here
|
||||
const std::string& type = ptr.getTypeName();
|
||||
bool isBook = type == typeid(ESM::Book).name();
|
||||
if (!isBook && type != typeid(ESM::Ingredient).name() && type != typeid(ESM::Repair).name())
|
||||
ptr.getRefData().getLocals().setVarByInt(script, "onpcequip", 1);
|
||||
// Books must have PCSkipEquip set to 1 instead
|
||||
else if (isBook)
|
||||
ptr.getRefData().getLocals().setVarByInt(script, "pcskipequip", 1);
|
||||
}
|
||||
|
||||
mSkippedToEquip = MWWorld::Ptr();
|
||||
if (ptr.getRefData().getCount()) // make sure the item is still there, the script might have removed it
|
||||
{
|
||||
if (script.empty() || ptr.getRefData().getLocals().getIntVar(script, "pcskipequip") == 0)
|
||||
{
|
||||
std::shared_ptr<MWWorld::Action> action = ptr.getClass().use(ptr, force);
|
||||
action->execute(player);
|
||||
}
|
||||
else
|
||||
mSkippedToEquip = ptr;
|
||||
}
|
||||
std::shared_ptr<MWWorld::Action> action = ptr.getClass().use(ptr, force);
|
||||
action->execute(player);
|
||||
|
||||
if (isVisible())
|
||||
{
|
||||
|
|
|
@ -93,7 +93,7 @@ namespace MWGui
|
|||
MyGUI::Button* mFilterMagic;
|
||||
MyGUI::Button* mFilterMisc;
|
||||
|
||||
MWWorld::Ptr mSkippedToEquip;
|
||||
MyGUI::EditBox* mFilterEdit;
|
||||
|
||||
GuiMode mGuiMode;
|
||||
|
||||
|
@ -121,6 +121,7 @@ namespace MWGui
|
|||
|
||||
void onWindowResize(MyGUI::Window* _sender);
|
||||
void onFilterChanged(MyGUI::Widget* _sender);
|
||||
void onNameFilterChanged(MyGUI::EditBox* _sender);
|
||||
void onAvatarClicked(MyGUI::Widget* _sender);
|
||||
void onPinToggled();
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace MWGui
|
|||
class ItemModel;
|
||||
class ItemWidget;
|
||||
|
||||
class ItemChargeView : public MyGUI::Widget
|
||||
class ItemChargeView final : public MyGUI::Widget
|
||||
{
|
||||
MYGUI_RTTI_DERIVED(ItemChargeView)
|
||||
public:
|
||||
|
@ -36,7 +36,7 @@ namespace MWGui
|
|||
/// Register needed components with MyGUI's factory manager
|
||||
static void registerComponents();
|
||||
|
||||
virtual void initialiseOverride();
|
||||
void initialiseOverride() final;
|
||||
|
||||
/// Takes ownership of \a model
|
||||
void setModel(ItemModel* model);
|
||||
|
@ -47,8 +47,8 @@ namespace MWGui
|
|||
void layoutWidgets();
|
||||
void resetScrollbars();
|
||||
|
||||
virtual void setSize(const MyGUI::IntSize& value);
|
||||
virtual void setCoord(const MyGUI::IntCoord& value);
|
||||
void setSize(const MyGUI::IntSize& value) final;
|
||||
void setCoord(const MyGUI::IntCoord& value) final;
|
||||
|
||||
MyGUI::delegates::CMultiDelegate2<MyGUI::Widget*, const MWWorld::Ptr&> eventItemClicked;
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
namespace MWGui
|
||||
{
|
||||
|
||||
class ItemView : public MyGUI::Widget
|
||||
class ItemView final : public MyGUI::Widget
|
||||
{
|
||||
MYGUI_RTTI_DERIVED(ItemView)
|
||||
public:
|
||||
|
@ -33,12 +33,12 @@ namespace MWGui
|
|||
void resetScrollBars();
|
||||
|
||||
private:
|
||||
virtual void initialiseOverride();
|
||||
void initialiseOverride() final;
|
||||
|
||||
void layoutWidgets();
|
||||
|
||||
virtual void setSize(const MyGUI::IntSize& _value);
|
||||
virtual void setCoord(const MyGUI::IntCoord& _value);
|
||||
void setSize(const MyGUI::IntSize& _value) final;
|
||||
void setCoord(const MyGUI::IntCoord& _value) final;
|
||||
|
||||
void onSelectedItem (MyGUI::Widget* sender);
|
||||
void onSelectedBackground (MyGUI::Widget* sender);
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace MWGui
|
|||
void setFrame (const std::string& frame, const MyGUI::IntCoord& coord);
|
||||
|
||||
protected:
|
||||
virtual void initialiseOverride();
|
||||
void initialiseOverride() final;
|
||||
|
||||
MyGUI::ImageBox* mItem;
|
||||
MyGUI::ImageBox* mItemShadow;
|
||||
|
|
|
@ -16,9 +16,6 @@ namespace MWGui
|
|||
|
||||
bool shouldAcceptKeyFocus(MyGUI::Widget* w)
|
||||
{
|
||||
if (w && w->getUserString("IgnoreTabKey") == "y")
|
||||
return false;
|
||||
|
||||
return w && !w->castType<MyGUI::Window>(false) && w->getInheritedEnabled() && w->getInheritedVisible() && w->getVisible() && w->getEnabled();
|
||||
}
|
||||
|
||||
|
|
|
@ -14,14 +14,13 @@
|
|||
#include <components/myguiplatform/myguitexture.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
#include <components/vfs/manager.hpp>
|
||||
#include <components/sceneutil/vismask.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/statemanager.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwbase/inputmanager.hpp"
|
||||
|
||||
#include "../mwrender/vismask.hpp"
|
||||
|
||||
#include "backgroundimage.hpp"
|
||||
|
||||
namespace MWGui
|
||||
|
@ -335,8 +334,8 @@ namespace MWGui
|
|||
// Turn off rendering except the GUI
|
||||
int oldUpdateMask = mViewer->getUpdateVisitor()->getTraversalMask();
|
||||
int oldCullMask = mViewer->getCamera()->getCullMask();
|
||||
mViewer->getUpdateVisitor()->setTraversalMask(MWRender::Mask_GUI|MWRender::Mask_PreCompile);
|
||||
mViewer->getCamera()->setCullMask(MWRender::Mask_GUI|MWRender::Mask_PreCompile);
|
||||
mViewer->getUpdateVisitor()->setTraversalMask(SceneUtil::Mask_GUI|SceneUtil::Mask_PreCompile);
|
||||
mViewer->getCamera()->setCullMask(SceneUtil::Mask_GUI|SceneUtil::Mask_PreCompile);
|
||||
|
||||
MWBase::Environment::get().getInputManager()->update(0, true, true);
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ namespace
|
|||
|
||||
|
||||
/// @brief A widget that changes its color when hovered.
|
||||
class MarkerWidget: public MyGUI::Widget
|
||||
class MarkerWidget final : public MyGUI::Widget
|
||||
{
|
||||
MYGUI_RTTI_DERIVED(MarkerWidget)
|
||||
|
||||
|
@ -74,12 +74,12 @@ namespace
|
|||
MyGUI::Colour mNormalColour;
|
||||
MyGUI::Colour mHoverColour;
|
||||
|
||||
void onMouseLostFocus(MyGUI::Widget* _new)
|
||||
void onMouseLostFocus(MyGUI::Widget* _new) final
|
||||
{
|
||||
setColour(mNormalColour);
|
||||
}
|
||||
|
||||
void onMouseSetFocus(MyGUI::Widget* _old)
|
||||
void onMouseSetFocus(MyGUI::Widget* _old) final
|
||||
{
|
||||
setColour(mHoverColour);
|
||||
}
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
|
||||
namespace MWGui
|
||||
{
|
||||
class AutoSizedResourceSkin : public MyGUI::ResourceSkin
|
||||
class AutoSizedResourceSkin final : public MyGUI::ResourceSkin
|
||||
{
|
||||
MYGUI_RTTI_DERIVED( AutoSizedResourceSkin )
|
||||
|
||||
public:
|
||||
virtual void deserialization(MyGUI::xml::ElementPtr _node, MyGUI::Version _version);
|
||||
void deserialization(MyGUI::xml::ElementPtr _node, MyGUI::Version _version) final;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include "../mwworld/nullaction.hpp"
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
|
||||
#include "../mwmechanics/alchemy.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
bool compareType(const std::string& type1, const std::string& type2)
|
||||
|
@ -151,6 +153,8 @@ namespace MWGui
|
|||
: mCategory(Category_All)
|
||||
, mFilter(0)
|
||||
, mSortByType(true)
|
||||
, mNameFilter("")
|
||||
, mEffectFilter("")
|
||||
{
|
||||
mSourceModel = sourceModel;
|
||||
}
|
||||
|
@ -199,8 +203,39 @@ namespace MWGui
|
|||
if (!(category & mCategory))
|
||||
return false;
|
||||
|
||||
if ((mFilter & Filter_OnlyIngredients) && base.getTypeName() != typeid(ESM::Ingredient).name())
|
||||
return false;
|
||||
if (mFilter & Filter_OnlyIngredients)
|
||||
{
|
||||
if (base.getTypeName() != typeid(ESM::Ingredient).name())
|
||||
return false;
|
||||
|
||||
if (!mNameFilter.empty() && !mEffectFilter.empty())
|
||||
throw std::logic_error("name and magic effect filter are mutually exclusive");
|
||||
|
||||
if (!mNameFilter.empty())
|
||||
{
|
||||
const auto itemName = Misc::StringUtils::lowerCase(base.getClass().getName(base));
|
||||
return itemName.find(mNameFilter) != std::string::npos;
|
||||
}
|
||||
|
||||
if (!mEffectFilter.empty())
|
||||
{
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
|
||||
const auto alchemySkill = player.getClass().getSkill(player, ESM::Skill::Alchemy);
|
||||
|
||||
const auto effects = MWMechanics::Alchemy::effectsDescription(base, alchemySkill);
|
||||
|
||||
for (const auto& effect : effects)
|
||||
{
|
||||
const auto ciEffect = Misc::StringUtils::lowerCase(effect);
|
||||
|
||||
if (ciEffect.find(mEffectFilter) != std::string::npos)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((mFilter & Filter_OnlyEnchanted) && !(item.mFlags & ItemStack::Flag_Enchanted))
|
||||
return false;
|
||||
if ((mFilter & Filter_OnlyChargedSoulstones) && (base.getTypeName() != typeid(ESM::Miscellaneous).name()
|
||||
|
@ -250,6 +285,10 @@ namespace MWGui
|
|||
return false;
|
||||
}
|
||||
|
||||
std::string compare = Misc::StringUtils::lowerCase(item.mBase.getClass().getName(item.mBase));
|
||||
if(compare.find(mNameFilter) == std::string::npos)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -277,6 +316,16 @@ namespace MWGui
|
|||
mFilter = filter;
|
||||
}
|
||||
|
||||
void SortFilterItemModel::setNameFilter (const std::string& filter)
|
||||
{
|
||||
mNameFilter = Misc::StringUtils::lowerCase(filter);
|
||||
}
|
||||
|
||||
void SortFilterItemModel::setEffectFilter (const std::string& filter)
|
||||
{
|
||||
mEffectFilter = Misc::StringUtils::lowerCase(filter);
|
||||
}
|
||||
|
||||
void SortFilterItemModel::update()
|
||||
{
|
||||
mSourceModel->update();
|
||||
|
|
|
@ -25,6 +25,8 @@ namespace MWGui
|
|||
|
||||
void setCategory (int category);
|
||||
void setFilter (int filter);
|
||||
void setNameFilter (const std::string& filter);
|
||||
void setEffectFilter (const std::string& filter);
|
||||
|
||||
/// Use ItemStack::Type for sorting?
|
||||
void setSortByType(bool sort) { mSortByType = sort; }
|
||||
|
@ -57,6 +59,9 @@ namespace MWGui
|
|||
int mCategory;
|
||||
int mFilter;
|
||||
bool mSortByType;
|
||||
|
||||
std::string mNameFilter; // filter by item name
|
||||
std::string mEffectFilter; // filter by magic effect
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace MWGui
|
|||
class SpellModel;
|
||||
|
||||
///@brief Displays a SpellModel in a list widget
|
||||
class SpellView : public MyGUI::Widget
|
||||
class SpellView final : public MyGUI::Widget
|
||||
{
|
||||
MYGUI_RTTI_DERIVED(SpellView)
|
||||
public:
|
||||
|
@ -47,10 +47,10 @@ namespace MWGui
|
|||
/// Fired when a spell was clicked
|
||||
EventHandle_ModelIndex eventSpellClicked;
|
||||
|
||||
virtual void initialiseOverride();
|
||||
void initialiseOverride() final;
|
||||
|
||||
virtual void setSize(const MyGUI::IntSize& _value);
|
||||
virtual void setCoord(const MyGUI::IntCoord& _value);
|
||||
void setSize(const MyGUI::IntSize& _value) final;
|
||||
void setCoord(const MyGUI::IntCoord& _value) final;
|
||||
|
||||
void resetScrollbars();
|
||||
|
||||
|
|
|
@ -45,8 +45,6 @@ namespace MWGui
|
|||
getWidget(mEffectBox, "EffectsBox");
|
||||
getWidget(mFilterEdit, "FilterEdit");
|
||||
|
||||
mFilterEdit->setUserString("IgnoreTabKey", "y");
|
||||
|
||||
mSpellView->eventSpellClicked += MyGUI::newDelegate(this, &SpellWindow::onModelIndexSelected);
|
||||
mFilterEdit->eventEditTextChange += MyGUI::newDelegate(this, &SpellWindow::onFilterChanged);
|
||||
deleteButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellWindow::onDeleteClicked);
|
||||
|
|
|
@ -69,6 +69,7 @@ namespace MWGui
|
|||
getWidget(mTotalBalance, "TotalBalance");
|
||||
getWidget(mTotalBalanceLabel, "TotalBalanceLabel");
|
||||
getWidget(mBottomPane, "BottomPane");
|
||||
getWidget(mFilterEdit, "FilterEdit");
|
||||
|
||||
getWidget(mItemView, "ItemView");
|
||||
mItemView->eventItemClicked += MyGUI::newDelegate(this, &TradeWindow::onItemSelected);
|
||||
|
@ -80,6 +81,7 @@ namespace MWGui
|
|||
mFilterApparel->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onFilterChanged);
|
||||
mFilterMagic->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onFilterChanged);
|
||||
mFilterMisc->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onFilterChanged);
|
||||
mFilterEdit->eventEditTextChange += MyGUI::newDelegate(this, &TradeWindow::onNameFilterChanged);
|
||||
|
||||
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onCancelButtonClicked);
|
||||
mOfferButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onOfferButtonClicked);
|
||||
|
@ -135,8 +137,7 @@ namespace MWGui
|
|||
setTitle(actor.getClass().getName(actor));
|
||||
|
||||
onFilterChanged(mFilterAll);
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mTotalBalance);
|
||||
mFilterEdit->setCaption("");
|
||||
}
|
||||
|
||||
void TradeWindow::onFrame(float dt)
|
||||
|
@ -144,6 +145,12 @@ namespace MWGui
|
|||
checkReferenceAvailable();
|
||||
}
|
||||
|
||||
void TradeWindow::onNameFilterChanged(MyGUI::EditBox* _sender)
|
||||
{
|
||||
mSortModel->setNameFilter(_sender->getCaption());
|
||||
mItemView->update();
|
||||
}
|
||||
|
||||
void TradeWindow::onFilterChanged(MyGUI::Widget* _sender)
|
||||
{
|
||||
if (_sender == mFilterAll)
|
||||
|
|
|
@ -59,6 +59,8 @@ namespace MWGui
|
|||
MyGUI::Button* mFilterMagic;
|
||||
MyGUI::Button* mFilterMisc;
|
||||
|
||||
MyGUI::EditBox* mFilterEdit;
|
||||
|
||||
MyGUI::Button* mIncreaseButton;
|
||||
MyGUI::Button* mDecreaseButton;
|
||||
MyGUI::TextBox* mTotalBalanceLabel;
|
||||
|
@ -86,6 +88,7 @@ namespace MWGui
|
|||
void sellItem (MyGUI::Widget* sender, int count);
|
||||
|
||||
void onFilterChanged(MyGUI::Widget* _sender);
|
||||
void onNameFilterChanged(MyGUI::EditBox* _sender);
|
||||
void onOfferButtonClicked(MyGUI::Widget* _sender);
|
||||
void onAccept(MyGUI::EditBox* sender);
|
||||
void onCancelButtonClicked(MyGUI::Widget* _sender);
|
||||
|
|
|
@ -227,9 +227,9 @@ namespace MWGui
|
|||
|
||||
void WaitDialog::onKeyButtonPressed(MyGUI::Widget *sender, MyGUI::KeyCode key, MyGUI::Char character)
|
||||
{
|
||||
if (key == MyGUI::KeyCode::ArrowDown)
|
||||
if (key == MyGUI::KeyCode::ArrowUp)
|
||||
mHourSlider->setScrollPosition(std::min(mHourSlider->getScrollPosition()+1, mHourSlider->getScrollRange()-1));
|
||||
else if (key == MyGUI::KeyCode::ArrowUp)
|
||||
else if (key == MyGUI::KeyCode::ArrowDown)
|
||||
mHourSlider->setScrollPosition(std::max(static_cast<int>(mHourSlider->getScrollPosition())-1, 0));
|
||||
else
|
||||
return;
|
||||
|
|
|
@ -90,7 +90,7 @@ namespace MWGui
|
|||
|
||||
typedef std::vector<SpellEffectParams> SpellEffectList;
|
||||
|
||||
class MWSkill : public MyGUI::Widget
|
||||
class MWSkill final : public MyGUI::Widget
|
||||
{
|
||||
MYGUI_RTTI_DERIVED( MWSkill )
|
||||
public:
|
||||
|
@ -116,7 +116,7 @@ namespace MWGui
|
|||
protected:
|
||||
virtual ~MWSkill();
|
||||
|
||||
virtual void initialiseOverride();
|
||||
void initialiseOverride() final;
|
||||
|
||||
void onClicked(MyGUI::Widget* _sender);
|
||||
|
||||
|
@ -131,7 +131,7 @@ namespace MWGui
|
|||
};
|
||||
typedef MWSkill* MWSkillPtr;
|
||||
|
||||
class MWAttribute : public MyGUI::Widget
|
||||
class MWAttribute final : public MyGUI::Widget
|
||||
{
|
||||
MYGUI_RTTI_DERIVED( MWAttribute )
|
||||
public:
|
||||
|
@ -156,7 +156,7 @@ namespace MWGui
|
|||
protected:
|
||||
virtual ~MWAttribute();
|
||||
|
||||
virtual void initialiseOverride();
|
||||
void initialiseOverride() final;
|
||||
|
||||
void onClicked(MyGUI::Widget* _sender);
|
||||
|
||||
|
@ -175,7 +175,7 @@ namespace MWGui
|
|||
* @todo remove this class and use MWEffectList instead
|
||||
*/
|
||||
class MWSpellEffect;
|
||||
class MWSpell : public MyGUI::Widget
|
||||
class MWSpell final : public MyGUI::Widget
|
||||
{
|
||||
MYGUI_RTTI_DERIVED( MWSpell )
|
||||
public:
|
||||
|
@ -199,7 +199,7 @@ namespace MWGui
|
|||
protected:
|
||||
virtual ~MWSpell();
|
||||
|
||||
virtual void initialiseOverride();
|
||||
void initialiseOverride() final;
|
||||
|
||||
private:
|
||||
void updateWidgets();
|
||||
|
@ -209,7 +209,7 @@ namespace MWGui
|
|||
};
|
||||
typedef MWSpell* MWSpellPtr;
|
||||
|
||||
class MWEffectList : public MyGUI::Widget
|
||||
class MWEffectList final : public MyGUI::Widget
|
||||
{
|
||||
MYGUI_RTTI_DERIVED( MWEffectList )
|
||||
public:
|
||||
|
@ -241,7 +241,7 @@ namespace MWGui
|
|||
protected:
|
||||
virtual ~MWEffectList();
|
||||
|
||||
virtual void initialiseOverride();
|
||||
void initialiseOverride() final;
|
||||
|
||||
private:
|
||||
void updateWidgets();
|
||||
|
@ -250,7 +250,7 @@ namespace MWGui
|
|||
};
|
||||
typedef MWEffectList* MWEffectListPtr;
|
||||
|
||||
class MWSpellEffect : public MyGUI::Widget
|
||||
class MWSpellEffect final : public MyGUI::Widget
|
||||
{
|
||||
MYGUI_RTTI_DERIVED( MWSpellEffect )
|
||||
public:
|
||||
|
@ -265,7 +265,7 @@ namespace MWGui
|
|||
protected:
|
||||
virtual ~MWSpellEffect();
|
||||
|
||||
virtual void initialiseOverride();
|
||||
void initialiseOverride() final;
|
||||
|
||||
private:
|
||||
static const int sIconOffset = 24;
|
||||
|
@ -279,7 +279,7 @@ namespace MWGui
|
|||
};
|
||||
typedef MWSpellEffect* MWSpellEffectPtr;
|
||||
|
||||
class MWDynamicStat : public MyGUI::Widget
|
||||
class MWDynamicStat final : public MyGUI::Widget
|
||||
{
|
||||
MYGUI_RTTI_DERIVED( MWDynamicStat )
|
||||
public:
|
||||
|
@ -294,7 +294,7 @@ namespace MWGui
|
|||
protected:
|
||||
virtual ~MWDynamicStat();
|
||||
|
||||
virtual void initialiseOverride();
|
||||
void initialiseOverride() final;
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <components/resource/resourcesystem.hpp>
|
||||
#include <components/resource/imagemanager.hpp>
|
||||
|
||||
#include <components/sceneutil/vismask.hpp>
|
||||
#include <components/sceneutil/workqueue.hpp>
|
||||
|
||||
#include <components/translation/translation.hpp>
|
||||
|
@ -50,8 +51,6 @@
|
|||
#include "../mwbase/soundmanager.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
|
||||
#include "../mwrender/vismask.hpp"
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/player.hpp"
|
||||
#include "../mwworld/cellstore.hpp"
|
||||
|
@ -1905,8 +1904,8 @@ namespace MWGui
|
|||
// Turn off all rendering except for the GUI
|
||||
int oldUpdateMask = mViewer->getUpdateVisitor()->getTraversalMask();
|
||||
int oldCullMask = mViewer->getCamera()->getCullMask();
|
||||
mViewer->getUpdateVisitor()->setTraversalMask(MWRender::Mask_GUI);
|
||||
mViewer->getCamera()->setCullMask(MWRender::Mask_GUI);
|
||||
mViewer->getUpdateVisitor()->setTraversalMask(SceneUtil::Mask_GUI);
|
||||
mViewer->getCamera()->setCullMask(SceneUtil::Mask_GUI);
|
||||
|
||||
MyGUI::IntSize screenSize = MyGUI::RenderManager::getInstance().getViewSize();
|
||||
sizeVideo(screenSize.width, screenSize.height);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <components/esm/esmwriter.hpp>
|
||||
|
||||
#include <components/sceneutil/positionattitudetransform.hpp>
|
||||
#include <components/sceneutil/vismask.hpp>
|
||||
#include <components/debug/debuglog.hpp>
|
||||
#include <components/misc/rng.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
|
@ -24,8 +25,6 @@
|
|||
|
||||
#include "../mwmechanics/aibreathe.hpp"
|
||||
|
||||
#include "../mwrender/vismask.hpp"
|
||||
|
||||
#include "spellcasting.hpp"
|
||||
#include "steering.hpp"
|
||||
#include "npcstats.hpp"
|
||||
|
@ -452,22 +451,12 @@ namespace MWMechanics
|
|||
return;
|
||||
|
||||
CreatureStats &stats = actor.getClass().getCreatureStats(actor);
|
||||
int hello = stats.getAiSetting(CreatureStats::AI_Hello).getModified();
|
||||
if (hello == 0)
|
||||
return;
|
||||
|
||||
if (MWBase::Environment::get().getWorld()->isSwimming(actor))
|
||||
return;
|
||||
|
||||
MWWorld::Ptr player = getPlayer();
|
||||
osg::Vec3f playerPos(player.getRefData().getPosition().asVec3());
|
||||
osg::Vec3f actorPos(actor.getRefData().getPosition().asVec3());
|
||||
osg::Vec3f dir = playerPos - actorPos;
|
||||
|
||||
const MWMechanics::AiSequence& seq = stats.getAiSequence();
|
||||
int packageId = seq.getTypeId();
|
||||
|
||||
if (seq.isInCombat() || (packageId != AiPackage::TypeIdWander && packageId != AiPackage::TypeIdTravel && packageId != -1))
|
||||
if (seq.isInCombat() ||
|
||||
MWBase::Environment::get().getWorld()->isSwimming(actor) ||
|
||||
(packageId != AiPackage::TypeIdWander && packageId != AiPackage::TypeIdTravel && packageId != -1))
|
||||
{
|
||||
stats.setTurningToPlayer(false);
|
||||
stats.setGreetingTimer(0);
|
||||
|
@ -475,6 +464,11 @@ namespace MWMechanics
|
|||
return;
|
||||
}
|
||||
|
||||
MWWorld::Ptr player = getPlayer();
|
||||
osg::Vec3f playerPos(player.getRefData().getPosition().asVec3());
|
||||
osg::Vec3f actorPos(actor.getRefData().getPosition().asVec3());
|
||||
osg::Vec3f dir = playerPos - actorPos;
|
||||
|
||||
if (stats.isTurningToPlayer())
|
||||
{
|
||||
// Reduce the turning animation glitch by using a *HUGE* value of
|
||||
|
@ -492,11 +486,10 @@ namespace MWMechanics
|
|||
return;
|
||||
|
||||
// Play a random voice greeting if the player gets too close
|
||||
float helloDistance = static_cast<float>(hello);
|
||||
static int iGreetDistanceMultiplier = MWBase::Environment::get().getWorld()->getStore()
|
||||
.get<ESM::GameSetting>().find("iGreetDistanceMultiplier")->mValue.getInteger();
|
||||
|
||||
helloDistance *= iGreetDistanceMultiplier;
|
||||
float helloDistance = static_cast<float>(stats.getAiSetting(CreatureStats::AI_Hello).getModified() * iGreetDistanceMultiplier);
|
||||
|
||||
int greetingTimer = stats.getGreetingTimer();
|
||||
GreetingState greetingState = stats.getGreetingState();
|
||||
|
@ -1241,6 +1234,11 @@ namespace MWMechanics
|
|||
if (heldIter != inventoryStore.end() && heldIter->getTypeName() != typeid(ESM::Light).name())
|
||||
inventoryStore.unequipItem(*heldIter, ptr);
|
||||
}
|
||||
else if (heldIter == inventoryStore.end() || heldIter->getTypeName() == typeid(ESM::Light).name())
|
||||
{
|
||||
// For hostile NPCs, see if they have anything better to equip first
|
||||
inventoryStore.autoEquip(ptr);
|
||||
}
|
||||
|
||||
heldIter = inventoryStore.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
|
||||
|
||||
|
@ -1420,11 +1418,11 @@ namespace MWMechanics
|
|||
const float dist = (player.getRefData().getPosition().asVec3() - ptr.getRefData().getPosition().asVec3()).length();
|
||||
if (dist > mActorsProcessingRange)
|
||||
{
|
||||
ptr.getRefData().getBaseNode()->setNodeMask(0);
|
||||
ptr.getRefData().getBaseNode()->setNodeMask(SceneUtil::Mask_Disabled);
|
||||
return;
|
||||
}
|
||||
else
|
||||
ptr.getRefData().getBaseNode()->setNodeMask(MWRender::Mask_Actor);
|
||||
ptr.getRefData().getBaseNode()->setNodeMask(SceneUtil::Mask_Actor);
|
||||
|
||||
// Fade away actors on large distance (>90% of actor's processing distance)
|
||||
float visibilityRatio = 1.0;
|
||||
|
@ -1748,12 +1746,12 @@ namespace MWMechanics
|
|||
|
||||
if (!inRange)
|
||||
{
|
||||
iter->first.getRefData().getBaseNode()->setNodeMask(0);
|
||||
iter->first.getRefData().getBaseNode()->setNodeMask(SceneUtil::Mask_Disabled);
|
||||
world->setActorCollisionMode(iter->first, false, false);
|
||||
continue;
|
||||
}
|
||||
else if (!isPlayer)
|
||||
iter->first.getRefData().getBaseNode()->setNodeMask(MWRender::Mask_Actor);
|
||||
iter->first.getRefData().getBaseNode()->setNodeMask(SceneUtil::Mask_Actor);
|
||||
|
||||
const bool isDead = iter->first.getClass().getCreatureStats(iter->first).isDead();
|
||||
if (!isDead && iter->first.getClass().getCreatureStats(iter->first).isParalyzed())
|
||||
|
@ -1852,6 +1850,8 @@ namespace MWMechanics
|
|||
stats.getActiveSpells().visitEffectSources(soulTrap);
|
||||
}
|
||||
|
||||
// Magic effects will be reset later, and the magic effect that could kill the actor
|
||||
// needs to be determined now
|
||||
calculateCreatureStatModifiers(iter->first, 0);
|
||||
|
||||
if (cls.isEssential(iter->first))
|
||||
|
@ -1869,7 +1869,10 @@ namespace MWMechanics
|
|||
// Make sure spell effects are removed
|
||||
purgeSpellEffects(stats.getActorId());
|
||||
|
||||
// Reset dynamic stats, attributes and skills
|
||||
calculateCreatureStatModifiers(iter->first, 0);
|
||||
if (iter->first.getClass().isNpc())
|
||||
calculateNpcStatModifiers(iter->first, 0);
|
||||
|
||||
if( iter->first == getPlayer())
|
||||
{
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace MWMechanics
|
|||
|
||||
void fastForward(const MWWorld::Ptr& actor, AiState& state);
|
||||
|
||||
virtual osg::Vec3f getDestination() { return osg::Vec3f(mX, mY, mZ); }
|
||||
virtual osg::Vec3f getDestination() const { return osg::Vec3f(mX, mY, mZ); }
|
||||
|
||||
private:
|
||||
std::string mCellId;
|
||||
|
|
|
@ -76,7 +76,7 @@ namespace MWMechanics
|
|||
|
||||
void fastForward(const MWWorld::Ptr& actor, AiState& state);
|
||||
|
||||
virtual osg::Vec3f getDestination()
|
||||
virtual osg::Vec3f getDestination() const
|
||||
{
|
||||
MWWorld::Ptr target = getTarget();
|
||||
if (target.isEmpty())
|
||||
|
|
|
@ -102,7 +102,7 @@ namespace MWMechanics
|
|||
/// Return true if this package should repeat. Currently only used for Wander packages.
|
||||
virtual bool getRepeat() const;
|
||||
|
||||
virtual osg::Vec3f getDestination() { return osg::Vec3f(0, 0, 0); }
|
||||
virtual osg::Vec3f getDestination() const { return osg::Vec3f(0, 0, 0); }
|
||||
|
||||
// Return true if any loaded actor with this AI package must be active.
|
||||
virtual bool alwaysActive() const { return false; }
|
||||
|
|
|
@ -28,6 +28,10 @@ void AiSequence::copy (const AiSequence& sequence)
|
|||
for (std::list<AiPackage *>::const_iterator iter (sequence.mPackages.begin());
|
||||
iter!=sequence.mPackages.end(); ++iter)
|
||||
mPackages.push_back ((*iter)->clone());
|
||||
|
||||
// We need to keep an AiWander storage, if present - it has a state machine.
|
||||
// Not sure about another temporary storages
|
||||
sequence.mAiState.copy<AiWanderStorage>(mAiState);
|
||||
}
|
||||
|
||||
AiSequence::AiSequence() : mDone (false), mRepeat(false), mLastAiPackage(-1) {}
|
||||
|
|
|
@ -39,6 +39,14 @@ namespace MWMechanics
|
|||
return *result;
|
||||
}
|
||||
|
||||
template< class Derived >
|
||||
void copy(DerivedClassStorage& destination) const
|
||||
{
|
||||
Derived* result = dynamic_cast<Derived*>(mStorage);
|
||||
if (result != nullptr)
|
||||
destination.store<Derived>(*result);
|
||||
}
|
||||
|
||||
template< class Derived >
|
||||
void store( const Derived& payload )
|
||||
{
|
||||
|
|
|
@ -54,8 +54,9 @@ namespace MWMechanics
|
|||
stats.setMovementFlag(CreatureStats::Flag_Run, false);
|
||||
stats.setDrawState(DrawState_Nothing);
|
||||
|
||||
// Note: we should cancel internal "return after combat" package, if original location is too far away
|
||||
if (!isWithinMaxRange(targetPos, actorPos))
|
||||
return false;
|
||||
return mHidden;
|
||||
|
||||
// Unfortunately, with vanilla assets destination is sometimes blocked by other actor.
|
||||
// If we got close to target, check for actors nearby. If they are, finish AI package.
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace MWMechanics
|
|||
|
||||
virtual bool alwaysActive() const { return true; }
|
||||
|
||||
virtual osg::Vec3f getDestination() { return osg::Vec3f(mX, mY, mZ); }
|
||||
virtual osg::Vec3f getDestination() const { return osg::Vec3f(mX, mY, mZ); }
|
||||
|
||||
private:
|
||||
float mX;
|
||||
|
|
|
@ -61,6 +61,34 @@ namespace MWMechanics
|
|||
rotation.makeRotate(randomDirection, osg::Vec3f(0.0, 0.0, 1.0));
|
||||
return position + osg::Vec3f(distance, 0.0, 0.0) * rotation;
|
||||
}
|
||||
|
||||
bool isDestinationHidden(const MWWorld::ConstPtr &actor, const osg::Vec3f& destination)
|
||||
{
|
||||
const auto position = actor.getRefData().getPosition().asVec3();
|
||||
const bool isWaterCreature = actor.getClass().isPureWaterCreature(actor);
|
||||
const bool isFlyingCreature = actor.getClass().isPureFlyingCreature(actor);
|
||||
const osg::Vec3f halfExtents = MWBase::Environment::get().getWorld()->getPathfindingHalfExtents(actor);
|
||||
osg::Vec3f direction = destination - position;
|
||||
direction.normalize();
|
||||
const auto visibleDestination = (
|
||||
isWaterCreature || isFlyingCreature
|
||||
? destination
|
||||
: destination + osg::Vec3f(0, 0, halfExtents.z())
|
||||
) + direction * std::max(halfExtents.x(), std::max(halfExtents.y(), halfExtents.z()));
|
||||
const int mask = MWPhysics::CollisionType_World
|
||||
| MWPhysics::CollisionType_HeightMap
|
||||
| MWPhysics::CollisionType_Door
|
||||
| MWPhysics::CollisionType_Actor;
|
||||
return MWBase::Environment::get().getWorld()->castRay(position, visibleDestination, mask, actor);
|
||||
}
|
||||
|
||||
bool isAreaOccupiedByOtherActor(const MWWorld::ConstPtr &actor, const osg::Vec3f& destination)
|
||||
{
|
||||
const auto world = MWBase::Environment::get().getWorld();
|
||||
const osg::Vec3f halfExtents = world->getPathfindingHalfExtents(actor);
|
||||
const auto maxHalfExtent = std::max(halfExtents.x(), std::max(halfExtents.y(), halfExtents.z()));
|
||||
return world->isAreaOccupiedByOtherActor(destination, 2 * maxHalfExtent, actor);
|
||||
}
|
||||
}
|
||||
|
||||
AiWander::AiWander(int distance, int duration, int timeOfDay, const std::vector<unsigned char>& idle, bool repeat):
|
||||
|
@ -145,15 +173,6 @@ namespace MWMechanics
|
|||
|
||||
// get or create temporary storage
|
||||
AiWanderStorage& storage = state.get<AiWanderStorage>();
|
||||
const MWWorld::CellStore*& currentCell = storage.mCell;
|
||||
bool cellChange = currentCell && (actor.getCell() != currentCell);
|
||||
if(!currentCell || cellChange)
|
||||
{
|
||||
stopWalking(actor, storage);
|
||||
currentCell = actor.getCell();
|
||||
storage.mPopulateAvailableNodes = true;
|
||||
mStoredInitialActorPosition = false;
|
||||
}
|
||||
|
||||
mRemainingDuration -= ((duration*MWBase::Environment::get().getWorld()->getTimeScaleFactor()) / 3600);
|
||||
|
||||
|
@ -200,14 +219,13 @@ namespace MWMechanics
|
|||
if (AI_REACTION_TIME <= lastReaction)
|
||||
{
|
||||
lastReaction = 0;
|
||||
return reactionTimeActions(actor, storage, currentCell, cellChange, pos);
|
||||
return reactionTimeActions(actor, storage, pos);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AiWander::reactionTimeActions(const MWWorld::Ptr& actor, AiWanderStorage& storage,
|
||||
const MWWorld::CellStore*& currentCell, bool cellChange, ESM::Position& pos)
|
||||
bool AiWander::reactionTimeActions(const MWWorld::Ptr& actor, AiWanderStorage& storage, ESM::Position& pos)
|
||||
{
|
||||
if (mDistance <= 0)
|
||||
storage.mCanWanderAlongPathGrid = false;
|
||||
|
@ -229,7 +247,7 @@ namespace MWMechanics
|
|||
// Initialization to discover & store allowed node points for this actor.
|
||||
if (storage.mPopulateAvailableNodes)
|
||||
{
|
||||
getAllowedNodes(actor, currentCell->getCell(), storage);
|
||||
getAllowedNodes(actor, actor.getCell()->getCell(), storage);
|
||||
}
|
||||
|
||||
if (canActorMoveByZAxis(actor) && mDistance > 0) {
|
||||
|
@ -258,10 +276,6 @@ namespace MWMechanics
|
|||
completeManualWalking(actor, storage);
|
||||
}
|
||||
|
||||
// Don't try to move if you are in a new cell (ie: positioncell command called) but still play idles.
|
||||
if(mDistance && cellChange)
|
||||
mDistance = 0;
|
||||
|
||||
AiWanderStorage::WanderState& wanderState = storage.mState;
|
||||
if ((wanderState == AiWanderStorage::Wander_MoveNow) && storage.mCanWanderAlongPathGrid)
|
||||
{
|
||||
|
@ -279,6 +293,11 @@ namespace MWMechanics
|
|||
completeManualWalking(actor, storage);
|
||||
}
|
||||
|
||||
if (wanderState == AiWanderStorage::Wander_Walking
|
||||
&& (isDestinationHidden(actor, mPathFinder.getPath().back())
|
||||
|| isAreaOccupiedByOtherActor(actor, mPathFinder.getPath().back())))
|
||||
completeManualWalking(actor, storage);
|
||||
|
||||
return false; // AiWander package not yet completed
|
||||
}
|
||||
|
||||
|
@ -330,7 +349,7 @@ namespace MWMechanics
|
|||
if (!isWaterCreature && !isFlyingCreature)
|
||||
{
|
||||
// findRandomPointAroundCircle uses wanderDistance as limit for random and not as exact distance
|
||||
if (const auto destination = navigator->findRandomPointAroundCircle(halfExtents, currentPosition, wanderDistance, navigatorFlags))
|
||||
if (const auto destination = navigator->findRandomPointAroundCircle(halfExtents, mInitialActorPosition, wanderDistance, navigatorFlags))
|
||||
mDestination = *destination;
|
||||
else
|
||||
mDestination = getRandomPointAround(mInitialActorPosition, wanderRadius);
|
||||
|
@ -342,7 +361,10 @@ namespace MWMechanics
|
|||
if (!isWaterCreature && destinationIsAtWater(actor, mDestination))
|
||||
continue;
|
||||
|
||||
if ((isWaterCreature || isFlyingCreature) && destinationThroughGround(currentPosition, mDestination))
|
||||
if (isDestinationHidden(actor, mDestination))
|
||||
continue;
|
||||
|
||||
if (isAreaOccupiedByOtherActor(actor, mDestination))
|
||||
continue;
|
||||
|
||||
if (isWaterCreature || isFlyingCreature)
|
||||
|
@ -371,16 +393,6 @@ namespace MWMechanics
|
|||
return MWBase::Environment::get().getWorld()->isUnderwater(actor.getCell(), positionBelowSurface);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if the start to end point travels through a collision point (land).
|
||||
*/
|
||||
bool AiWander::destinationThroughGround(const osg::Vec3f& startPoint, const osg::Vec3f& destination) {
|
||||
const int mask = MWPhysics::CollisionType_World | MWPhysics::CollisionType_HeightMap | MWPhysics::CollisionType_Door;
|
||||
return MWBase::Environment::get().getWorld()->castRay(startPoint.x(), startPoint.y(), startPoint.z(),
|
||||
destination.x(), destination.y(), destination.z(),
|
||||
mask);
|
||||
}
|
||||
|
||||
void AiWander::completeManualWalking(const MWWorld::Ptr &actor, AiWanderStorage &storage) {
|
||||
stopWalking(actor, storage);
|
||||
mObstacleCheck.clear();
|
||||
|
@ -529,7 +541,7 @@ namespace MWMechanics
|
|||
unsigned int randNode = Misc::Rng::rollDice(storage.mAllowedNodes.size());
|
||||
ESM::Pathgrid::Point dest(storage.mAllowedNodes[randNode]);
|
||||
|
||||
ToWorldCoordinates(dest, storage.mCell->getCell());
|
||||
ToWorldCoordinates(dest, actor.getCell()->getCell());
|
||||
|
||||
// actor position is already in world coordinates
|
||||
const osg::Vec3f start = actorPos.asVec3();
|
||||
|
|
|
@ -27,8 +27,6 @@ namespace MWMechanics
|
|||
{
|
||||
float mReaction; // update some actions infrequently
|
||||
|
||||
const MWWorld::CellStore* mCell; // for detecting cell change
|
||||
|
||||
// AiWander states
|
||||
enum WanderState
|
||||
{
|
||||
|
@ -60,7 +58,6 @@ namespace MWMechanics
|
|||
|
||||
AiWanderStorage():
|
||||
mReaction(0),
|
||||
mCell(nullptr),
|
||||
mState(Wander_ChooseAction),
|
||||
mIsWanderingManually(false),
|
||||
mCanWanderAlongPathGrid(true),
|
||||
|
@ -100,6 +97,8 @@ namespace MWMechanics
|
|||
|
||||
virtual int getTypeId() const;
|
||||
|
||||
virtual bool useVariableSpeed() const { return true;}
|
||||
|
||||
virtual void writeState(ESM::AiSequence::AiSequence &sequence) const;
|
||||
|
||||
virtual void fastForward(const MWWorld::Ptr& actor, AiState& state);
|
||||
|
@ -108,6 +107,14 @@ namespace MWMechanics
|
|||
|
||||
osg::Vec3f getDestination(const MWWorld::Ptr& actor) const;
|
||||
|
||||
virtual osg::Vec3f getDestination() const
|
||||
{
|
||||
if (!mHasDestination)
|
||||
return osg::Vec3f(0, 0, 0);
|
||||
|
||||
return mDestination;
|
||||
}
|
||||
|
||||
private:
|
||||
// NOTE: mDistance and mDuration must be set already
|
||||
void init();
|
||||
|
@ -125,12 +132,10 @@ namespace MWMechanics
|
|||
void onIdleStatePerFrameActions(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage);
|
||||
void onWalkingStatePerFrameActions(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage);
|
||||
void onChooseActionStatePerFrameActions(const MWWorld::Ptr& actor, AiWanderStorage& storage);
|
||||
bool reactionTimeActions(const MWWorld::Ptr& actor, AiWanderStorage& storage,
|
||||
const MWWorld::CellStore*& currentCell, bool cellChange, ESM::Position& pos);
|
||||
bool reactionTimeActions(const MWWorld::Ptr& actor, AiWanderStorage& storage, ESM::Position& pos);
|
||||
bool isPackageCompleted(const MWWorld::Ptr& actor, AiWanderStorage& storage);
|
||||
void wanderNearStart(const MWWorld::Ptr &actor, AiWanderStorage &storage, int wanderDistance);
|
||||
bool destinationIsAtWater(const MWWorld::Ptr &actor, const osg::Vec3f& destination);
|
||||
bool destinationThroughGround(const osg::Vec3f& startPoint, const osg::Vec3f& destination);
|
||||
void completeManualWalking(const MWWorld::Ptr &actor, AiWanderStorage &storage);
|
||||
|
||||
int mDistance; // how far the actor can wander from the spawn point
|
||||
|
@ -141,7 +146,7 @@ namespace MWMechanics
|
|||
bool mRepeat;
|
||||
|
||||
bool mStoredInitialActorPosition;
|
||||
osg::Vec3f mInitialActorPosition;
|
||||
osg::Vec3f mInitialActorPosition; // Note: an original engine does not reset coordinates even when actor changes a cell
|
||||
|
||||
bool mHasDestination;
|
||||
osg::Vec3f mDestination;
|
||||
|
|
|
@ -554,3 +554,37 @@ std::string MWMechanics::Alchemy::suggestPotionName()
|
|||
return MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
|
||||
ESM::MagicEffect::effectIdToString(effectId))->mValue.getString();
|
||||
}
|
||||
|
||||
std::vector<std::string> MWMechanics::Alchemy::effectsDescription (const MWWorld::ConstPtr &ptr, const int alchemySkill)
|
||||
{
|
||||
std::vector<std::string> effects;
|
||||
|
||||
const auto& item = ptr.get<ESM::Ingredient>()->mBase;
|
||||
const auto& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||
const static auto fWortChanceValue = gmst.find("fWortChanceValue")->mValue.getFloat();
|
||||
const auto& data = item->mData;
|
||||
|
||||
for (auto i = 0; i < 4; ++i)
|
||||
{
|
||||
const auto effectID = data.mEffectID[i];
|
||||
const auto skillID = data.mSkills[i];
|
||||
const auto attributeID = data.mAttributes[i];
|
||||
|
||||
if (alchemySkill < fWortChanceValue * (i + 1))
|
||||
break;
|
||||
|
||||
if (effectID != -1)
|
||||
{
|
||||
std::string effect = gmst.find(ESM::MagicEffect::effectIdToString(effectID))->mValue.getString();
|
||||
|
||||
if (skillID != -1)
|
||||
effect += " " + gmst.find(ESM::Skill::sSkillNameIds[skillID])->mValue.getString();
|
||||
else if (attributeID != -1)
|
||||
effect += " " + gmst.find(ESM::Attribute::sGmstAttributeIds[attributeID])->mValue.getString();
|
||||
|
||||
effects.push_back(effect);
|
||||
|
||||
}
|
||||
}
|
||||
return effects;
|
||||
}
|
||||
|
|
|
@ -131,6 +131,8 @@ namespace MWMechanics
|
|||
///< Try to create potions from the ingredients, place them in the inventory of the alchemist and
|
||||
/// adjust the skills of the alchemist accordingly.
|
||||
/// \param name must not be an empty string, or Result_NoName is returned
|
||||
|
||||
static std::vector<std::string> effectsDescription (const MWWorld::ConstPtr &ptr, const int alchemySKill);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -455,6 +455,11 @@ void MWMechanics::NpcStats::setTimeToStartDrowning(float time)
|
|||
mTimeToStartDrowning=time;
|
||||
}
|
||||
|
||||
void MWMechanics::NpcStats::writeState (ESM::CreatureStats& state) const
|
||||
{
|
||||
CreatureStats::writeState(state);
|
||||
}
|
||||
|
||||
void MWMechanics::NpcStats::writeState (ESM::NpcStats& state) const
|
||||
{
|
||||
for (std::map<std::string, int>::const_iterator iter (mFactionRank.begin());
|
||||
|
@ -494,6 +499,10 @@ void MWMechanics::NpcStats::writeState (ESM::NpcStats& state) const
|
|||
|
||||
state.mTimeToStartDrowning = mTimeToStartDrowning;
|
||||
}
|
||||
void MWMechanics::NpcStats::readState (const ESM::CreatureStats& state)
|
||||
{
|
||||
CreatureStats::readState(state);
|
||||
}
|
||||
|
||||
void MWMechanics::NpcStats::readState (const ESM::NpcStats& state)
|
||||
{
|
||||
|
|
|
@ -127,8 +127,10 @@ namespace MWMechanics
|
|||
/// @param time value from [0,20]
|
||||
void setTimeToStartDrowning(float time);
|
||||
|
||||
void writeState (ESM::CreatureStats& state) const;
|
||||
void writeState (ESM::NpcStats& state) const;
|
||||
|
||||
void readState (const ESM::CreatureStats& state);
|
||||
void readState (const ESM::NpcStats& state);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -120,6 +120,7 @@ namespace MWMechanics
|
|||
mWalkState = WalkState::Norm;
|
||||
mStateDuration = 0;
|
||||
mPrev = position;
|
||||
mInitialDistance = (destination - position).length();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -129,10 +130,11 @@ namespace MWMechanics
|
|||
const float prevDistance = (destination - mPrev).length();
|
||||
const float currentDistance = (destination - position).length();
|
||||
const float movedDistance = prevDistance - currentDistance;
|
||||
const float movedFromInitialDistance = mInitialDistance - currentDistance;
|
||||
|
||||
mPrev = position;
|
||||
|
||||
if (movedDistance >= distSameSpot)
|
||||
if (movedDistance >= distSameSpot && movedFromInitialDistance >= distSameSpot)
|
||||
{
|
||||
mWalkState = WalkState::Norm;
|
||||
mStateDuration = 0;
|
||||
|
@ -143,6 +145,7 @@ namespace MWMechanics
|
|||
{
|
||||
mWalkState = WalkState::CheckStuck;
|
||||
mStateDuration = duration;
|
||||
mInitialDistance = (destination - position).length();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ namespace MWMechanics
|
|||
|
||||
float mStateDuration;
|
||||
int mEvadeDirectionIndex;
|
||||
float mInitialDistance = 0;
|
||||
|
||||
void chooseEvasionDirection();
|
||||
};
|
||||
|
|
|
@ -314,7 +314,9 @@ namespace MWMechanics
|
|||
{
|
||||
mPath.clear();
|
||||
|
||||
buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents, flags, std::back_inserter(mPath));
|
||||
// If it's not possible to build path over navmesh due to disabled navmesh generation fallback to straight path
|
||||
if (!buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents, flags, std::back_inserter(mPath)))
|
||||
mPath.push_back(endPoint);
|
||||
|
||||
mConstructed = true;
|
||||
}
|
||||
|
@ -335,24 +337,27 @@ namespace MWMechanics
|
|||
mConstructed = true;
|
||||
}
|
||||
|
||||
void PathFinder::buildPathByNavigatorImpl(const MWWorld::ConstPtr& actor, const osg::Vec3f& startPoint,
|
||||
bool PathFinder::buildPathByNavigatorImpl(const MWWorld::ConstPtr& actor, const osg::Vec3f& startPoint,
|
||||
const osg::Vec3f& endPoint, const osg::Vec3f& halfExtents, const DetourNavigator::Flags flags,
|
||||
std::back_insert_iterator<std::deque<osg::Vec3f>> out)
|
||||
{
|
||||
try
|
||||
const auto world = MWBase::Environment::get().getWorld();
|
||||
const auto stepSize = getPathStepSize(actor);
|
||||
const auto navigator = world->getNavigator();
|
||||
const auto status = navigator->findPath(halfExtents, stepSize, startPoint, endPoint, flags, out);
|
||||
|
||||
if (status == DetourNavigator::Status::NavMeshNotFound)
|
||||
return false;
|
||||
|
||||
if (status != DetourNavigator::Status::Success)
|
||||
{
|
||||
const auto world = MWBase::Environment::get().getWorld();
|
||||
const auto stepSize = getPathStepSize(actor);
|
||||
const auto navigator = world->getNavigator();
|
||||
navigator->findPath(halfExtents, stepSize, startPoint, endPoint, flags, out);
|
||||
}
|
||||
catch (const DetourNavigator::NavigatorException& exception)
|
||||
{
|
||||
Log(Debug::Debug) << "Build path by navigator exception: \"" << exception.what()
|
||||
Log(Debug::Debug) << "Build path by navigator error: \"" << DetourNavigator::getMessage(status)
|
||||
<< "\" for \"" << actor.getClass().getName(actor) << "\" (" << actor.getBase()
|
||||
<< ") from " << startPoint << " to " << endPoint << " with flags ("
|
||||
<< DetourNavigator::WriteFlags {flags} << ")";
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PathFinder::buildPathByNavMeshToNextPoint(const MWWorld::ConstPtr& actor, const osg::Vec3f& halfExtents,
|
||||
|
@ -367,26 +372,30 @@ namespace MWMechanics
|
|||
if (sqrDistanceIgnoreZ(mPath.front(), startPoint) <= 4 * stepSize * stepSize)
|
||||
return;
|
||||
|
||||
try
|
||||
const auto navigator = MWBase::Environment::get().getWorld()->getNavigator();
|
||||
std::deque<osg::Vec3f> prePath;
|
||||
auto prePathInserter = std::back_inserter(prePath);
|
||||
const auto status = navigator->findPath(halfExtents, stepSize, startPoint, mPath.front(), flags,
|
||||
prePathInserter);
|
||||
|
||||
if (status == DetourNavigator::Status::NavMeshNotFound)
|
||||
return;
|
||||
|
||||
if (status != DetourNavigator::Status::Success)
|
||||
{
|
||||
const auto navigator = MWBase::Environment::get().getWorld()->getNavigator();
|
||||
std::deque<osg::Vec3f> prePath;
|
||||
navigator->findPath(halfExtents, stepSize, startPoint, mPath.front(), flags, std::back_inserter(prePath));
|
||||
|
||||
while (!prePath.empty() && sqrDistanceIgnoreZ(prePath.front(), startPoint) < stepSize * stepSize)
|
||||
prePath.pop_front();
|
||||
|
||||
while (!prePath.empty() && sqrDistanceIgnoreZ(prePath.back(), mPath.front()) < stepSize * stepSize)
|
||||
prePath.pop_back();
|
||||
|
||||
std::copy(prePath.rbegin(), prePath.rend(), std::front_inserter(mPath));
|
||||
}
|
||||
catch (const DetourNavigator::NavigatorException& exception)
|
||||
{
|
||||
Log(Debug::Debug) << "Build path by navigator exception: \"" << exception.what()
|
||||
Log(Debug::Debug) << "Build path by navigator error: \"" << DetourNavigator::getMessage(status)
|
||||
<< "\" for \"" << actor.getClass().getName(actor) << "\" (" << actor.getBase()
|
||||
<< ") from " << startPoint << " to " << mPath.front() << " with flags ("
|
||||
<< DetourNavigator::WriteFlags {flags} << ")";
|
||||
return;
|
||||
}
|
||||
|
||||
while (!prePath.empty() && sqrDistanceIgnoreZ(prePath.front(), startPoint) < stepSize * stepSize)
|
||||
prePath.pop_front();
|
||||
|
||||
while (!prePath.empty() && sqrDistanceIgnoreZ(prePath.back(), mPath.front()) < stepSize * stepSize)
|
||||
prePath.pop_back();
|
||||
|
||||
std::copy(prePath.rbegin(), prePath.rend(), std::front_inserter(mPath));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -201,7 +201,7 @@ namespace MWMechanics
|
|||
void buildPathByPathgridImpl(const osg::Vec3f& startPoint, const osg::Vec3f& endPoint,
|
||||
const PathgridGraph& pathgridGraph, std::back_insert_iterator<std::deque<osg::Vec3f>> out);
|
||||
|
||||
void buildPathByNavigatorImpl(const MWWorld::ConstPtr& actor, const osg::Vec3f& startPoint,
|
||||
bool buildPathByNavigatorImpl(const MWWorld::ConstPtr& actor, const osg::Vec3f& startPoint,
|
||||
const osg::Vec3f& endPoint, const osg::Vec3f& halfExtents, const DetourNavigator::Flags flags,
|
||||
std::back_insert_iterator<std::deque<osg::Vec3f>> out);
|
||||
};
|
||||
|
|
|
@ -1199,10 +1199,10 @@ namespace MWMechanics
|
|||
return false;
|
||||
}
|
||||
|
||||
void adjustDynamicStat(CreatureStats& creatureStats, int index, float magnitude)
|
||||
void adjustDynamicStat(CreatureStats& creatureStats, int index, float magnitude, bool allowDecreaseBelowZero = false)
|
||||
{
|
||||
DynamicStat<float> stat = creatureStats.getDynamic(index);
|
||||
stat.setCurrent(stat.getCurrent() + magnitude, index == 2);
|
||||
stat.setCurrent(stat.getCurrent() + magnitude, allowDecreaseBelowZero);
|
||||
creatureStats.setDynamic(index, stat);
|
||||
}
|
||||
|
||||
|
@ -1241,9 +1241,12 @@ namespace MWMechanics
|
|||
|
||||
case ESM::MagicEffect::DamageMagicka:
|
||||
case ESM::MagicEffect::DamageFatigue:
|
||||
adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::DamageHealth, -magnitude);
|
||||
{
|
||||
int index = effectKey.mId-ESM::MagicEffect::DamageHealth;
|
||||
static const bool uncappedDamageFatigue = Settings::Manager::getBool("uncapped damage fatigue", "Game");
|
||||
adjustDynamicStat(creatureStats, index, -magnitude, index == 2 && uncappedDamageFatigue);
|
||||
break;
|
||||
|
||||
}
|
||||
case ESM::MagicEffect::AbsorbHealth:
|
||||
if (magnitude > 0.f)
|
||||
receivedMagicDamage = true;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue