mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-04-01 11:06:41 +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
.travis.ymlAUTHORS.mdCHANGELOG.mdCHANGELOG_PR.md
CI
apps
esmtool
launcher
opencs
CMakeLists.txt
model
prefs
world
view/render
cell.cppcellarrow.cppcellborder.cppcellmarker.cppcellwater.cppinstancemode.cppinstancemode.hppinstanceselectionmode.cppmask.hppobject.cppobject.hpppagedworldspacewidget.cpppathgrid.cpppathgridmode.cpppathgridselectionmode.cppscenewidget.cppselectionmode.hpptagbase.cpptagbase.hppterrainshapemode.cppterrainshapemode.hppterraintexturemode.cppunpagedworldspacewidget.cppworldspacewidget.cppworldspacewidget.hpp
openmw
CMakeLists.txtengine.cpp
mwbase
mwclass
mwgui
alchemywindow.cppalchemywindow.hppbackgroundimage.hppbookpage.cppcompanionwindow.cppcompanionwindow.hppcontrollers.hppcursor.hppinventorywindow.cppinventorywindow.hppitemchargeview.hppitemview.hppitemwidget.hppkeyboardnavigation.cpploadingscreen.cppmapwindow.cppresourceskin.hppsortfilteritemmodel.cppsortfilteritemmodel.hppspellview.hppspellwindow.cpptradewindow.cpptradewindow.hppwaitdialog.cppwidgets.hppwindowmanagerimp.cpp
mwmechanics
40
.travis.yml
40
.travis.yml
|
@ -9,19 +9,15 @@ env:
|
||||||
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
|
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
|
||||||
# via the "travis encrypt" command using the project repo's public key
|
# 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="
|
- secure: "jybGzAdUbqt9vWR/GEnRd96BgAi/7Zd1+2HK68j/i/8+/1YH2XxLOy4Jv/DUBhBlJIkxs/Xv8dRcUlFOclZDHX1d/9Qnsqd3oUVkD7k1y7cTOWy9TBQaE/v/kZo3LpzA3xPwwthrb0BvqIbOfIELi5fS5s8ba85WFRg3AX70wWE="
|
||||||
cache:
|
cache: ccache
|
||||||
ccache: true
|
|
||||||
directories:
|
|
||||||
- ${HOME}/.ccache
|
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
- sourceline: 'ppa:openmw/openmw'
|
- sourceline: 'ppa:openmw/openmw'
|
||||||
- ubuntu-toolchain-r-test
|
- ubuntu-toolchain-r-test
|
||||||
- llvm-toolchain-xenial-7
|
|
||||||
packages: [
|
packages: [
|
||||||
# Dev
|
# Dev
|
||||||
cmake, clang-7, clang-tools-7, gcc-8, g++-8, ccache,
|
cmake, clang-tools, gcc-9, g++-9, ccache,
|
||||||
# Boost
|
# Boost
|
||||||
libboost-filesystem-dev, libboost-iostreams-dev, libboost-program-options-dev, libboost-system-dev,
|
libboost-filesystem-dev, libboost-iostreams-dev, libboost-program-options-dev, libboost-system-dev,
|
||||||
# FFmpeg
|
# FFmpeg
|
||||||
|
@ -45,50 +41,51 @@ matrix:
|
||||||
os: osx
|
os: osx
|
||||||
osx_image: xcode10.2
|
osx_image: xcode10.2
|
||||||
if: branch != coverity_scan
|
if: branch != coverity_scan
|
||||||
- name: OpenMW (all) on Ubuntu Xenial GCC-5
|
- name: OpenMW (all) on Ubuntu Bionic GCC-7
|
||||||
os: linux
|
os: linux
|
||||||
dist: xenial
|
dist: bionic
|
||||||
sudo: required
|
sudo: required
|
||||||
if: branch != coverity_scan
|
if: branch != coverity_scan
|
||||||
- name: OpenMW (all) on Ubuntu Xenial GCC-8
|
- name: OpenMW (all) on Ubuntu Bionic GCC-9
|
||||||
os: linux
|
os: linux
|
||||||
dist: xenial
|
dist: bionic
|
||||||
sudo: required
|
sudo: required
|
||||||
env:
|
env:
|
||||||
- MATRIX_EVAL="CC=gcc-8 && CXX=g++-8"
|
- MATRIX_EVAL="CC=gcc-9 && CXX=g++-9"
|
||||||
if: branch != coverity_scan
|
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
|
os: linux
|
||||||
dist: xenial
|
dist: bionic
|
||||||
sudo: required
|
sudo: required
|
||||||
env:
|
env:
|
||||||
- MATRIX_EVAL="CC=clang-7 && CXX=clang++-7"
|
- MATRIX_EVAL="CC=clang && CXX=clang++"
|
||||||
- ANALYZE="scan-build-7 --force-analyze-debug-code --use-cc clang-7 --use-c++ clang++-7"
|
- ANALYZE="scan-build --force-analyze-debug-code --use-cc clang --use-c++ clang++"
|
||||||
- BUILD_OPENMW_CS="OFF"
|
- BUILD_OPENMW_CS="OFF"
|
||||||
if: branch != coverity_scan
|
if: branch != coverity_scan
|
||||||
compiler: clang
|
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
|
os: linux
|
||||||
dist: xenial
|
dist: bionic
|
||||||
sudo: required
|
sudo: required
|
||||||
env:
|
env:
|
||||||
- MATRIX_EVAL="CC=clang-7 && CXX=clang++-7"
|
- MATRIX_EVAL="CC=clang && CXX=clang++"
|
||||||
- ANALYZE="scan-build-7 --force-analyze-debug-code --use-cc clang-7 --use-c++ clang++-7"
|
- ANALYZE="scan-build --force-analyze-debug-code --use-cc clang --use-c++ clang++"
|
||||||
- BUILD_OPENMW="OFF"
|
- BUILD_OPENMW="OFF"
|
||||||
if: branch != coverity_scan
|
if: branch != coverity_scan
|
||||||
compiler: clang
|
compiler: clang
|
||||||
- name: OpenMW Components Coverity Scan
|
- name: OpenMW Components Coverity Scan
|
||||||
os: linux
|
os: linux
|
||||||
dist: xenial
|
dist: bionic
|
||||||
sudo: required
|
sudo: required
|
||||||
if: branch = coverity_scan
|
if: branch = coverity_scan
|
||||||
# allow_failures:
|
# 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:
|
before_install:
|
||||||
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then eval "${MATRIX_EVAL}"; fi
|
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then eval "${MATRIX_EVAL}"; fi
|
||||||
- if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then ./CI/before_install.${TRAVIS_OS_NAME}.sh; fi
|
- if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then ./CI/before_install.${TRAVIS_OS_NAME}.sh; fi
|
||||||
before_script:
|
before_script:
|
||||||
|
- ccache -z
|
||||||
- if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then ./CI/before_script.${TRAVIS_OS_NAME}.sh; fi
|
- if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then ./CI/before_script.${TRAVIS_OS_NAME}.sh; fi
|
||||||
script:
|
script:
|
||||||
- cd ./build
|
- 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 ./openmw_test_suite; fi
|
||||||
- if [ "${COVERITY_SCAN_BRANCH}" != 1 ] && [ "${TRAVIS_OS_NAME}" = "linux" ]; then cd .. && ./CI/check_tabs.sh; fi
|
- if [ "${COVERITY_SCAN_BRANCH}" != 1 ] && [ "${TRAVIS_OS_NAME}" = "linux" ]; then cd .. && ./CI/check_tabs.sh; fi
|
||||||
- cd "${TRAVIS_BUILD_DIR}"
|
- cd "${TRAVIS_BUILD_DIR}"
|
||||||
|
- ccache -s
|
||||||
deploy:
|
deploy:
|
||||||
provider: script
|
provider: script
|
||||||
script: ./CI/deploy.osx.sh
|
script: ./CI/deploy.osx.sh
|
||||||
|
|
|
@ -74,6 +74,7 @@ Programmers
|
||||||
Fil Krynicki (filkry)
|
Fil Krynicki (filkry)
|
||||||
Finbar Crago (finbar-crago)
|
Finbar Crago (finbar-crago)
|
||||||
Florian Weber (Florianjw)
|
Florian Weber (Florianjw)
|
||||||
|
Frédéric Chardon (fr3dz10)
|
||||||
Gaëtan Dezeiraud (Brouilles)
|
Gaëtan Dezeiraud (Brouilles)
|
||||||
Gašper Sedej
|
Gašper Sedej
|
||||||
Gijsbert ter Horst (Ghostbird)
|
Gijsbert ter Horst (Ghostbird)
|
||||||
|
@ -87,6 +88,7 @@ Programmers
|
||||||
Jacob Essex (Yacoby)
|
Jacob Essex (Yacoby)
|
||||||
Jake Westrip (16bitint)
|
Jake Westrip (16bitint)
|
||||||
James Carty (MrTopCat)
|
James Carty (MrTopCat)
|
||||||
|
James Moore (moore.work)
|
||||||
James Stephens (james-h-stephens)
|
James Stephens (james-h-stephens)
|
||||||
Jan-Peter Nilsson (peppe)
|
Jan-Peter Nilsson (peppe)
|
||||||
Jan Borsodi (am0s)
|
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 #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 #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 #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 #4202: Open .omwaddon files without needing toopen openmw-cs first
|
||||||
Bug #4240: Ash storm origin coordinates and hand shielding animation behavior are incorrect
|
Bug #4240: Ash storm origin coordinates and hand shielding animation behavior are incorrect
|
||||||
Bug #4262: Rain settings are hardcoded
|
Bug #4262: Rain settings are hardcoded
|
||||||
|
@ -36,10 +37,13 @@
|
||||||
Bug #4411: Reloading a saved game while falling prevents damage in some cases
|
Bug #4411: Reloading a saved game while falling prevents damage in some cases
|
||||||
Bug #4449: Value returned by GetWindSpeed is incorrect
|
Bug #4449: Value returned by GetWindSpeed is incorrect
|
||||||
Bug #4456: AiActivate should not be cancelled after target activation
|
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 #4540: Rain delay when exiting water
|
||||||
Bug #4594: Actors without AI packages don't use Hello dialogue
|
Bug #4594: Actors without AI packages don't use Hello dialogue
|
||||||
Bug #4598: Script parser does not support non-ASCII characters
|
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 #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 #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 #4650: Focus is lost after pressing ESC in confirmation dialog inside savegame dialog
|
||||||
Bug #4680: Heap corruption on faulty esp
|
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 #5239: OpenMW-CS does not support non-ASCII characters in path names
|
||||||
Bug #5241: On-self absorb spells cannot be detected
|
Bug #5241: On-self absorb spells cannot be detected
|
||||||
Bug #5242: ExplodeSpell behavior differs from Cast behavior
|
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 #5249: Wandering NPCs start walking too soon after they hello
|
||||||
Bug #5250: Creatures display shield ground mesh instead of shield body part
|
Bug #5250: Creatures display shield ground mesh instead of shield body part
|
||||||
Bug #5255: "GetTarget, player" doesn't return 1 during NPC hello
|
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 #1774: Handle AvoidNode
|
||||||
Feature #2229: Improve pathfinding AI
|
Feature #2229: Improve pathfinding AI
|
||||||
Feature #3025: Analogue gamepad movement controls
|
Feature #3025: Analogue gamepad movement controls
|
||||||
|
@ -215,9 +229,11 @@
|
||||||
Feature #4544: Actors movement deceleration
|
Feature #4544: Actors movement deceleration
|
||||||
Feature #4673: Weapon sheathing
|
Feature #4673: Weapon sheathing
|
||||||
Feature #4675: Support for NiRollController
|
Feature #4675: Support for NiRollController
|
||||||
|
Feature #4708: Radial fog support
|
||||||
Feature #4730: Native animated containers support
|
Feature #4730: Native animated containers support
|
||||||
Feature #4784: Launcher: Duplicate Content Lists
|
Feature #4784: Launcher: Duplicate Content Lists
|
||||||
Feature #4812: Support NiSwitchNode
|
Feature #4812: Support NiSwitchNode
|
||||||
|
Feature #4831: Item search in the player's inventory
|
||||||
Feature #4836: Daytime node switch
|
Feature #4836: Daytime node switch
|
||||||
Feature #4840: Editor: Transient terrain change support
|
Feature #4840: Editor: Transient terrain change support
|
||||||
Feature #4859: Make water reflections more configurable
|
Feature #4859: Make water reflections more configurable
|
||||||
|
@ -240,6 +256,7 @@
|
||||||
Feature #5091: Human-readable light source duration
|
Feature #5091: Human-readable light source duration
|
||||||
Feature #5094: Unix like console hotkeys
|
Feature #5094: Unix like console hotkeys
|
||||||
Feature #5098: Allow user controller bindings
|
Feature #5098: Allow user controller bindings
|
||||||
|
Feature #5114: Refresh launcher mod list
|
||||||
Feature #5121: Handle NiTriStrips and NiTriStripsData
|
Feature #5121: Handle NiTriStrips and NiTriStripsData
|
||||||
Feature #5122: Use magic glow for enchanted arrows
|
Feature #5122: Use magic glow for enchanted arrows
|
||||||
Feature #5131: Custom skeleton bones
|
Feature #5131: Custom skeleton bones
|
||||||
|
@ -247,9 +264,13 @@
|
||||||
Feature #5146: Safe Dispose corpse
|
Feature #5146: Safe Dispose corpse
|
||||||
Feature #5147: Show spell magicka cost in spell buying window
|
Feature #5147: Show spell magicka cost in spell buying window
|
||||||
Feature #5170: Editor: Land shape editing, land selection
|
Feature #5170: Editor: Land shape editing, land selection
|
||||||
|
Feature #5172: Editor: Delete instances/references with keypress in scene window
|
||||||
Feature #5193: Weapon sheathing
|
Feature #5193: Weapon sheathing
|
||||||
Feature #5219: Impelement TestCells console command
|
Feature #5219: Impelement TestCells console command
|
||||||
Feature #5224: Handle NiKeyframeController for NiTriShape
|
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 #4686: Upgrade media decoder to a more current FFmpeg API
|
||||||
Task #4695: Optimize Distant Terrain memory consumption
|
Task #4695: Optimize Distant Terrain memory consumption
|
||||||
Task #4789: Optimize cell transitions
|
Task #4789: Optimize cell transitions
|
||||||
|
|
|
@ -42,6 +42,8 @@ New Editor Features:
|
||||||
- "Faction Ranks" table for "Faction" records (#4209)
|
- "Faction Ranks" table for "Faction" records (#4209)
|
||||||
- Changes to height editing can be cancelled without changes to data (press esc to cancel) (#4840)
|
- Changes to height editing can be cancelled without changes to data (press esc to cancel) (#4840)
|
||||||
- Land heightmap/shape editing and vertex selection (#5170)
|
- Land heightmap/shape editing and vertex selection (#5170)
|
||||||
|
- Deleting instances with a keypress (#5172)
|
||||||
|
- Dropping objects with keyboard shortcuts (#5274)
|
||||||
|
|
||||||
Bug Fixes:
|
Bug Fixes:
|
||||||
- The Mouse Wheel can now be used for key bindings (#2679)
|
- The Mouse Wheel can now be used for key bindings (#2679)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/bin/bash -ex
|
#!/bin/bash -ex
|
||||||
|
|
||||||
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++-7 /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
|
mkdir build
|
||||||
cd 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}" ]]; then export BUILD_OPENMW=ON; fi
|
||||||
if [[ -z "${BUILD_OPENMW_CS}" ]]; then export BUILD_OPENMW_CS=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_WIZARD=${BUILD_OPENMW_CS} \
|
||||||
-DBUILD_NIFTEST=${BUILD_OPENMW_CS} \
|
-DBUILD_NIFTEST=${BUILD_OPENMW_CS} \
|
||||||
-DBUILD_MYGUI_PLUGIN=${BUILD_OPENMW_CS} \
|
-DBUILD_MYGUI_PLUGIN=${BUILD_OPENMW_CS} \
|
||||||
-DBUILD_WITH_CODE_COVERAGE=${CODE_COVERAGE} \
|
|
||||||
-DBUILD_UNITTESTS=1 \
|
-DBUILD_UNITTESTS=1 \
|
||||||
-DUSE_SYSTEM_TINYXML=1 \
|
-DUSE_SYSTEM_TINYXML=1 \
|
||||||
-DDESIRED_QT_VERSION=5 \
|
-DDESIRED_QT_VERSION=5 \
|
||||||
|
|
|
@ -421,16 +421,16 @@ if [ -z $SKIP_DOWNLOAD ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
download "Qt 5.7.0" \
|
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" \
|
"qt-5.7.0-msvc${MSVC_YEAR}-win${BITS}.exe" \
|
||||||
"https://www.lysator.liu.se/~ace/OpenMW/deps/qt-5-install.qs" \
|
"https://www.lysator.liu.se/~ace/OpenMW/deps/qt-5-install.qs" \
|
||||||
"qt-5-install.qs"
|
"qt-5-install.qs"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# SDL2
|
# SDL2
|
||||||
download "SDL 2.0.7" \
|
download "SDL 2.0.12" \
|
||||||
"https://www.libsdl.org/release/SDL2-devel-2.0.7-VC.zip" \
|
"https://www.libsdl.org/release/SDL2-devel-2.0.12-VC.zip" \
|
||||||
"SDL2-2.0.7.zip"
|
"SDL2-2.0.12.zip"
|
||||||
|
|
||||||
# Google test and mock
|
# Google test and mock
|
||||||
if [ ! -z $TEST_FRAMEWORK ]; then
|
if [ ! -z $TEST_FRAMEWORK ]; then
|
||||||
|
@ -697,16 +697,16 @@ fi
|
||||||
cd $DEPS
|
cd $DEPS
|
||||||
echo
|
echo
|
||||||
# SDL2
|
# 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. "
|
printf "Exists. "
|
||||||
elif [ -z $SKIP_EXTRACT ]; then
|
elif [ -z $SKIP_EXTRACT ]; then
|
||||||
rm -rf SDL2-2.0.7
|
rm -rf SDL2-2.0.12
|
||||||
eval 7z x -y SDL2-2.0.7.zip $STRIP
|
eval 7z x -y SDL2-2.0.12.zip $STRIP
|
||||||
fi
|
fi
|
||||||
export SDL2DIR="$(real_pwd)/SDL2-2.0.7"
|
export SDL2DIR="$(real_pwd)/SDL2-2.0.12"
|
||||||
add_runtime_dlls "$(pwd)/SDL2-2.0.7/lib/x${ARCHSUFFIX}/SDL2.dll"
|
add_runtime_dlls "$(pwd)/SDL2-2.0.12/lib/x${ARCHSUFFIX}/SDL2.dll"
|
||||||
echo Done.
|
echo Done.
|
||||||
}
|
}
|
||||||
cd $DEPS
|
cd $DEPS
|
||||||
|
|
|
@ -534,10 +534,18 @@ void Record<ESM::Cell>::print()
|
||||||
if (mData.mData.mFlags & ESM::Cell::Interior &&
|
if (mData.mData.mFlags & ESM::Cell::Interior &&
|
||||||
!(mData.mData.mFlags & ESM::Cell::QuasiEx))
|
!(mData.mData.mFlags & ESM::Cell::QuasiEx))
|
||||||
{
|
{
|
||||||
|
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 << " Ambient Light Color: " << mData.mAmbi.mAmbient << std::endl;
|
||||||
std::cout << " Sunlight Color: " << mData.mAmbi.mSunlight << std::endl;
|
std::cout << " Sunlight Color: " << mData.mAmbi.mSunlight << std::endl;
|
||||||
std::cout << " Fog Color: " << mData.mAmbi.mFog << std::endl;
|
std::cout << " Fog Color: " << mData.mAmbi.mFog << std::endl;
|
||||||
std::cout << " Fog Density: " << mData.mAmbi.mFogDensity << 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;
|
std::cout << " Water Level: " << mData.mWater << std::endl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -89,6 +89,7 @@ bool Launcher::AdvancedPage::loadSettings()
|
||||||
loadSettingBool(weaponSheathingCheckBox, "weapon sheathing", "Game");
|
loadSettingBool(weaponSheathingCheckBox, "weapon sheathing", "Game");
|
||||||
loadSettingBool(shieldSheathingCheckBox, "shield sheathing", "Game");
|
loadSettingBool(shieldSheathingCheckBox, "shield sheathing", "Game");
|
||||||
}
|
}
|
||||||
|
loadSettingBool(uncappedDamageFatigueCheckBox, "uncapped damage fatigue", "Game");
|
||||||
|
|
||||||
// Input Settings
|
// Input Settings
|
||||||
loadSettingBool(grabCursorCheckBox, "grab cursor", "Input");
|
loadSettingBool(grabCursorCheckBox, "grab cursor", "Input");
|
||||||
|
@ -152,6 +153,7 @@ void Launcher::AdvancedPage::saveSettings()
|
||||||
saveSettingBool(animSourcesCheckBox, "use additional anim sources", "Game");
|
saveSettingBool(animSourcesCheckBox, "use additional anim sources", "Game");
|
||||||
saveSettingBool(weaponSheathingCheckBox, "weapon sheathing", "Game");
|
saveSettingBool(weaponSheathingCheckBox, "weapon sheathing", "Game");
|
||||||
saveSettingBool(shieldSheathingCheckBox, "shield sheathing", "Game");
|
saveSettingBool(shieldSheathingCheckBox, "shield sheathing", "Game");
|
||||||
|
saveSettingBool(uncappedDamageFatigueCheckBox, "uncapped damage fatigue", "Game");
|
||||||
|
|
||||||
// Input Settings
|
// Input Settings
|
||||||
saveSettingBool(grabCursorCheckBox, "grab cursor", "Input");
|
saveSettingBool(grabCursorCheckBox, "grab cursor", "Input");
|
||||||
|
|
|
@ -62,10 +62,13 @@ void Launcher::DataFilesPage::buildView()
|
||||||
{
|
{
|
||||||
ui.verticalLayout->insertWidget (0, mSelector->uiWidget());
|
ui.verticalLayout->insertWidget (0, mSelector->uiWidget());
|
||||||
|
|
||||||
|
QToolButton * refreshButton = mSelector->refreshButton();
|
||||||
|
|
||||||
//tool buttons
|
//tool buttons
|
||||||
ui.newProfileButton->setToolTip ("Create a new Content List");
|
ui.newProfileButton->setToolTip ("Create a new Content List");
|
||||||
ui.cloneProfileButton->setToolTip ("Clone the current Content List");
|
ui.cloneProfileButton->setToolTip ("Clone the current Content List");
|
||||||
ui.deleteProfileButton->setToolTip ("Delete an existing Content List");
|
ui.deleteProfileButton->setToolTip ("Delete an existing Content List");
|
||||||
|
refreshButton->setToolTip("Refresh Data Files");
|
||||||
|
|
||||||
//combo box
|
//combo box
|
||||||
ui.profilesComboBox->addItem(mDefaultContentListName);
|
ui.profilesComboBox->addItem(mDefaultContentListName);
|
||||||
|
@ -76,6 +79,7 @@ void Launcher::DataFilesPage::buildView()
|
||||||
ui.newProfileButton->setDefaultAction (ui.newProfileAction);
|
ui.newProfileButton->setDefaultAction (ui.newProfileAction);
|
||||||
ui.cloneProfileButton->setDefaultAction (ui.cloneProfileAction);
|
ui.cloneProfileButton->setDefaultAction (ui.cloneProfileAction);
|
||||||
ui.deleteProfileButton->setDefaultAction (ui.deleteProfileAction);
|
ui.deleteProfileButton->setDefaultAction (ui.deleteProfileAction);
|
||||||
|
refreshButton->setDefaultAction(ui.refreshDataFilesAction);
|
||||||
|
|
||||||
//establish connections
|
//establish connections
|
||||||
connect (ui.profilesComboBox, SIGNAL (currentIndexChanged(int)),
|
connect (ui.profilesComboBox, SIGNAL (currentIndexChanged(int)),
|
||||||
|
@ -86,6 +90,8 @@ void Launcher::DataFilesPage::buildView()
|
||||||
|
|
||||||
connect (ui.profilesComboBox, SIGNAL (signalProfileChanged(QString, QString)),
|
connect (ui.profilesComboBox, SIGNAL (signalProfileChanged(QString, QString)),
|
||||||
this, SLOT (slotProfileChangedByUser(QString, QString)));
|
this, SLOT (slotProfileChangedByUser(QString, QString)));
|
||||||
|
|
||||||
|
connect(ui.refreshDataFilesAction, SIGNAL(triggered()),this, SLOT(slotRefreshButtonClicked()));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Launcher::DataFilesPage::loadSettings()
|
bool Launcher::DataFilesPage::loadSettings()
|
||||||
|
@ -114,6 +120,8 @@ void Launcher::DataFilesPage::populateFileViews(const QString& contentModelName)
|
||||||
if (!mDataLocal.isEmpty())
|
if (!mDataLocal.isEmpty())
|
||||||
paths.insert(0, mDataLocal);
|
paths.insert(0, mDataLocal);
|
||||||
|
|
||||||
|
mSelector->clearFiles();
|
||||||
|
|
||||||
for (const QString &path : paths)
|
for (const QString &path : paths)
|
||||||
mSelector->addFiles(path);
|
mSelector->addFiles(path);
|
||||||
|
|
||||||
|
@ -166,9 +174,18 @@ QStringList Launcher::DataFilesPage::selectedFilePaths()
|
||||||
ContentSelectorModel::ContentFileList items = mSelector->selectedFiles();
|
ContentSelectorModel::ContentFileList items = mSelector->selectedFiles();
|
||||||
QStringList filePaths;
|
QStringList filePaths;
|
||||||
for (const ContentSelectorModel::EsmFile *item : items)
|
for (const ContentSelectorModel::EsmFile *item : items)
|
||||||
|
{
|
||||||
|
QFile file(item->filePath());
|
||||||
|
|
||||||
|
if(file.exists())
|
||||||
{
|
{
|
||||||
filePaths.append(item->filePath());
|
filePaths.append(item->filePath());
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
slotRefreshButtonClicked();
|
||||||
|
}
|
||||||
|
}
|
||||||
return filePaths;
|
return filePaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,6 +238,18 @@ void Launcher::DataFilesPage::slotProfileDeleted (const QString &item)
|
||||||
removeProfile (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)
|
void Launcher::DataFilesPage::slotProfileChangedByUser(const QString &previous, const QString ¤t)
|
||||||
{
|
{
|
||||||
setProfile(previous, current, true);
|
setProfile(previous, current, true);
|
||||||
|
|
|
@ -61,6 +61,7 @@ namespace Launcher
|
||||||
void slotProfileRenamed(const QString &previous, const QString ¤t);
|
void slotProfileRenamed(const QString &previous, const QString ¤t);
|
||||||
void slotProfileDeleted(const QString &item);
|
void slotProfileDeleted(const QString &item);
|
||||||
void slotAddonDataChanged ();
|
void slotAddonDataChanged ();
|
||||||
|
void slotRefreshButtonClicked ();
|
||||||
|
|
||||||
void updateNewProfileOkButton(const QString &text);
|
void updateNewProfileOkButton(const QString &text);
|
||||||
void updateCloneProfileOkButton(const QString &text);
|
void updateCloneProfileOkButton(const QString &text);
|
||||||
|
@ -100,6 +101,7 @@ namespace Launcher
|
||||||
void checkForDefaultProfile();
|
void checkForDefaultProfile();
|
||||||
void populateFileViews(const QString& contentModelName);
|
void populateFileViews(const QString& contentModelName);
|
||||||
void reloadCells(QStringList selectedFiles);
|
void reloadCells(QStringList selectedFiles);
|
||||||
|
void refreshDataFilesView ();
|
||||||
|
|
||||||
class PathIterator
|
class PathIterator
|
||||||
{
|
{
|
||||||
|
|
|
@ -97,10 +97,6 @@ opencs_units_noqt (view/render
|
||||||
cellarrow cellmarker cellborder pathgrid
|
cellarrow cellmarker cellborder pathgrid
|
||||||
)
|
)
|
||||||
|
|
||||||
opencs_hdrs_noqt (view/render
|
|
||||||
mask
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
opencs_units (view/tools
|
opencs_units (view/tools
|
||||||
reportsubview reporttable searchsubview searchbox merge
|
reportsubview reporttable searchsubview searchbox merge
|
||||||
|
|
|
@ -355,6 +355,11 @@ void CSMPrefs::State::declare()
|
||||||
declareShortcut ("scene-select-secondary", "Secondary Select",
|
declareShortcut ("scene-select-secondary", "Secondary Select",
|
||||||
QKeySequence(Qt::ControlModifier | (int)Qt::MiddleButton));
|
QKeySequence(Qt::ControlModifier | (int)Qt::MiddleButton));
|
||||||
declareModifier ("scene-speed-modifier", "Speed Modifier", Qt::Key_Shift);
|
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-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-eastcell", "Load East Cell", QKeySequence(Qt::KeypadModifier | Qt::Key_6));
|
||||||
declareShortcut ("scene-load-cam-northcell", "Load North Cell", QKeySequence(Qt::KeypadModifier | Qt::Key_8));
|
declareShortcut ("scene-load-cam-northcell", "Load North Cell", QKeySequence(Qt::KeypadModifier | Qt::Key_8));
|
||||||
|
|
|
@ -76,53 +76,6 @@ namespace CSMWorld
|
||||||
return false;
|
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::LandNormalsColumn()
|
LandNormalsColumn::LandNormalsColumn()
|
||||||
: Column<Land>(Columns::ColumnId_LandNormalsIndex, ColumnBase::Display_String, 0)
|
: Column<Land>(Columns::ColumnId_LandNormalsIndex, ColumnBase::Display_String, 0)
|
||||||
|
|
|
@ -1770,7 +1770,7 @@ namespace CSMWorld
|
||||||
struct GenderNpcColumn : public Column<ESXRecordT>
|
struct GenderNpcColumn : public Column<ESXRecordT>
|
||||||
{
|
{
|
||||||
GenderNpcColumn()
|
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
|
virtual QVariant get(const Record<ESXRecordT>& record) const
|
||||||
|
@ -2461,17 +2461,6 @@ namespace CSMWorld
|
||||||
bool isEditable() const override;
|
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>
|
struct LandNormalsColumn : public Column<Land>
|
||||||
{
|
{
|
||||||
using DataType = QVector<signed char>;
|
using DataType = QVector<signed char>;
|
||||||
|
@ -2529,8 +2518,7 @@ namespace CSMWorld
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is required to access the type as a QVariant.
|
// This is required to access the type as a QVariant.
|
||||||
Q_DECLARE_METATYPE(CSMWorld::LandMapLodColumn::DataType)
|
Q_DECLARE_METATYPE(CSMWorld::LandNormalsColumn::DataType)
|
||||||
//Q_DECLARE_METATYPE(CSMWorld::LandNormalsColumn::DataType) // Same as LandMapLodColumn::DataType
|
|
||||||
Q_DECLARE_METATYPE(CSMWorld::LandHeightsColumn::DataType)
|
Q_DECLARE_METATYPE(CSMWorld::LandHeightsColumn::DataType)
|
||||||
Q_DECLARE_METATYPE(CSMWorld::LandColoursColumn::DataType)
|
Q_DECLARE_METATYPE(CSMWorld::LandColoursColumn::DataType)
|
||||||
Q_DECLARE_METATYPE(CSMWorld::LandTexturesColumn::DataType)
|
Q_DECLARE_METATYPE(CSMWorld::LandTexturesColumn::DataType)
|
||||||
|
|
|
@ -288,7 +288,6 @@ namespace CSMWorld
|
||||||
{ ColumnId_UChar, "Value [0..255]" },
|
{ ColumnId_UChar, "Value [0..255]" },
|
||||||
{ ColumnId_NpcMisc, "NPC Misc" },
|
{ ColumnId_NpcMisc, "NPC Misc" },
|
||||||
{ ColumnId_Level, "Level" },
|
{ ColumnId_Level, "Level" },
|
||||||
{ ColumnId_GenderNpc, "Gender"},
|
|
||||||
{ ColumnId_Mana, "Mana" },
|
{ ColumnId_Mana, "Mana" },
|
||||||
{ ColumnId_Fatigue, "Fatigue" },
|
{ ColumnId_Fatigue, "Fatigue" },
|
||||||
{ ColumnId_NpcDisposition, "NPC Disposition" },
|
{ ColumnId_NpcDisposition, "NPC Disposition" },
|
||||||
|
|
|
@ -273,7 +273,7 @@ namespace CSMWorld
|
||||||
ColumnId_UChar = 250,
|
ColumnId_UChar = 250,
|
||||||
ColumnId_NpcMisc = 251,
|
ColumnId_NpcMisc = 251,
|
||||||
ColumnId_Level = 252,
|
ColumnId_Level = 252,
|
||||||
ColumnId_GenderNpc = 254,
|
// unused
|
||||||
ColumnId_Mana = 255,
|
ColumnId_Mana = 255,
|
||||||
ColumnId_Fatigue = 256,
|
ColumnId_Fatigue = 256,
|
||||||
ColumnId_NpcDisposition = 257,
|
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 defines = mResourceSystem->getSceneManager()->getShaderManager().getGlobalDefines();
|
||||||
Shader::ShaderManager::DefineMap shadowDefines = SceneUtil::ShadowManager::getShadowsDisabledDefines();
|
Shader::ShaderManager::DefineMap shadowDefines = SceneUtil::ShadowManager::getShadowsDisabledDefines();
|
||||||
defines["forcePPL"] = "0";
|
defines["forcePPL"] = "0"; // Don't force per-pixel lighting
|
||||||
defines["clamp"] = "1";
|
defines["clamp"] = "1"; // Clamp lighting
|
||||||
|
defines["preLightEnv"] = "0"; // Apply environment maps after lighting like Morrowind
|
||||||
|
defines["radialFog"] = "0";
|
||||||
for (const auto& define : shadowDefines)
|
for (const auto& define : shadowDefines)
|
||||||
defines[define.first] = define.second;
|
defines[define.first] = define.second;
|
||||||
mResourceSystem->getSceneManager()->getShaderManager().setGlobalDefines(defines);
|
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 RecordStateColumn<Land>);
|
||||||
mLand.addColumn (new FixedRecordTypeColumn<Land>(UniversalId::Type_Land));
|
mLand.addColumn (new FixedRecordTypeColumn<Land>(UniversalId::Type_Land));
|
||||||
mLand.addColumn (new LandPluginIndexColumn);
|
mLand.addColumn (new LandPluginIndexColumn);
|
||||||
mLand.addColumn (new LandMapLodColumn);
|
|
||||||
mLand.addColumn (new LandNormalsColumn);
|
mLand.addColumn (new LandNormalsColumn);
|
||||||
mLand.addColumn (new LandHeightsColumn);
|
mLand.addColumn (new LandHeightsColumn);
|
||||||
mLand.addColumn (new LandColoursColumn);
|
mLand.addColumn (new LandColoursColumn);
|
||||||
|
|
|
@ -867,6 +867,8 @@ namespace CSMWorld
|
||||||
switch (subColIndex)
|
switch (subColIndex)
|
||||||
{
|
{
|
||||||
case 0: return isInterior;
|
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) ?
|
case 1: return (isInterior && !behaveLikeExterior) ?
|
||||||
cell.mAmbi.mAmbient : QVariant(QVariant::UserType);
|
cell.mAmbi.mAmbient : QVariant(QVariant::UserType);
|
||||||
case 2: return (isInterior && !behaveLikeExterior) ?
|
case 2: return (isInterior && !behaveLikeExterior) ?
|
||||||
|
@ -912,7 +914,10 @@ namespace CSMWorld
|
||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
if (isInterior && !behaveLikeExterior)
|
if (isInterior && !behaveLikeExterior)
|
||||||
|
{
|
||||||
cell.mAmbi.mAmbient = static_cast<int32_t>(value.toInt());
|
cell.mAmbi.mAmbient = static_cast<int32_t>(value.toInt());
|
||||||
|
cell.setHasAmbient(true);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return; // return without saving
|
return; // return without saving
|
||||||
break;
|
break;
|
||||||
|
@ -920,7 +925,10 @@ namespace CSMWorld
|
||||||
case 2:
|
case 2:
|
||||||
{
|
{
|
||||||
if (isInterior && !behaveLikeExterior)
|
if (isInterior && !behaveLikeExterior)
|
||||||
|
{
|
||||||
cell.mAmbi.mSunlight = static_cast<int32_t>(value.toInt());
|
cell.mAmbi.mSunlight = static_cast<int32_t>(value.toInt());
|
||||||
|
cell.setHasAmbient(true);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return; // return without saving
|
return; // return without saving
|
||||||
break;
|
break;
|
||||||
|
@ -928,7 +936,10 @@ namespace CSMWorld
|
||||||
case 3:
|
case 3:
|
||||||
{
|
{
|
||||||
if (isInterior && !behaveLikeExterior)
|
if (isInterior && !behaveLikeExterior)
|
||||||
|
{
|
||||||
cell.mAmbi.mFog = static_cast<int32_t>(value.toInt());
|
cell.mAmbi.mFog = static_cast<int32_t>(value.toInt());
|
||||||
|
cell.setHasAmbient(true);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return; // return without saving
|
return; // return without saving
|
||||||
break;
|
break;
|
||||||
|
@ -936,7 +947,10 @@ namespace CSMWorld
|
||||||
case 4:
|
case 4:
|
||||||
{
|
{
|
||||||
if (isInterior && !behaveLikeExterior)
|
if (isInterior && !behaveLikeExterior)
|
||||||
|
{
|
||||||
cell.mAmbi.mFogDensity = value.toFloat();
|
cell.mAmbi.mFogDensity = value.toFloat();
|
||||||
|
cell.setHasAmbient(true);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return; // return without saving
|
return; // return without saving
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -486,7 +486,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
|
||||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_Head, ColumnBase::Display_BodyPart));
|
mColumns.push_back (RefIdColumn (Columns::ColumnId_Head, ColumnBase::Display_BodyPart));
|
||||||
npcColumns.mHead = &mColumns.back();
|
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.mGender = &mColumns.back();
|
||||||
|
|
||||||
npcColumns.mFlags.insert (std::make_pair (essential, ESM::NPC::Essential));
|
npcColumns.mFlags.insert (std::make_pair (essential, ESM::NPC::Essential));
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <components/esm/loadcell.hpp>
|
#include <components/esm/loadcell.hpp>
|
||||||
#include <components/esm/loadland.hpp>
|
#include <components/esm/loadland.hpp>
|
||||||
#include <components/sceneutil/pathgridutil.hpp>
|
#include <components/sceneutil/pathgridutil.hpp>
|
||||||
|
#include <components/sceneutil/vismask.hpp>
|
||||||
#include <components/terrain/terraingrid.hpp>
|
#include <components/terrain/terraingrid.hpp>
|
||||||
|
|
||||||
#include "../../model/world/idtable.hpp"
|
#include "../../model/world/idtable.hpp"
|
||||||
|
@ -21,7 +22,6 @@
|
||||||
#include "cellborder.hpp"
|
#include "cellborder.hpp"
|
||||||
#include "cellarrow.hpp"
|
#include "cellarrow.hpp"
|
||||||
#include "cellmarker.hpp"
|
#include "cellmarker.hpp"
|
||||||
#include "mask.hpp"
|
|
||||||
#include "pathgrid.hpp"
|
#include "pathgrid.hpp"
|
||||||
#include "terrainstorage.hpp"
|
#include "terrainstorage.hpp"
|
||||||
#include "object.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));
|
std::unique_ptr<Object> object (new Object (mData, mCellNode, id, false));
|
||||||
|
|
||||||
if (mSubModeElementMask & Mask_Reference)
|
if (mSubModeElementMask & SceneUtil::Mask_EditorReference)
|
||||||
object->setSubMode (mSubMode);
|
object->setSubMode (mSubMode);
|
||||||
|
|
||||||
mObjects.insert (std::make_pair (id, object.release()));
|
mObjects.insert (std::make_pair (id, object.release()));
|
||||||
|
@ -134,7 +134,7 @@ void CSVRender::Cell::updateLand()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mTerrain.reset(new Terrain::TerrainGrid(mCellNode, mCellNode,
|
mTerrain.reset(new Terrain::TerrainGrid(mCellNode, mCellNode,
|
||||||
mData.getResourceSystem().get(), mTerrainStorage, Mask_Terrain));
|
mData.getResourceSystem().get(), mTerrainStorage));
|
||||||
}
|
}
|
||||||
|
|
||||||
mTerrain->loadCell(esmLand.mX, esmLand.mY);
|
mTerrain->loadCell(esmLand.mX, esmLand.mY);
|
||||||
|
@ -434,7 +434,7 @@ void CSVRender::Cell::reloadAssets()
|
||||||
|
|
||||||
void CSVRender::Cell::setSelection (int elementMask, Selection mode)
|
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());
|
for (std::map<std::string, Object *>::const_iterator iter (mObjects.begin());
|
||||||
iter!=mObjects.end(); ++iter)
|
iter!=mObjects.end(); ++iter)
|
||||||
|
@ -451,7 +451,7 @@ void CSVRender::Cell::setSelection (int elementMask, Selection mode)
|
||||||
iter->second->setSelected (selected);
|
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
|
// Only one pathgrid may be selected, so some operations will only have an effect
|
||||||
// if the pathgrid is already focused
|
// 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;
|
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());
|
for (std::map<std::string, Object *>::const_iterator iter (mObjects.begin());
|
||||||
iter!=mObjects.end(); ++iter)
|
iter!=mObjects.end(); ++iter)
|
||||||
if (iter->second->getSelected())
|
if (iter->second->getSelected())
|
||||||
result.push_back (iter->second->getTag());
|
result.push_back (iter->second->getTag());
|
||||||
if (mPathgrid && elementMask & Mask_Pathgrid)
|
if (mPathgrid && elementMask & SceneUtil::Mask_Pathgrid)
|
||||||
if (mPathgrid->isSelected())
|
if (mPathgrid->isSelected())
|
||||||
result.push_back(mPathgrid->getTag());
|
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;
|
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());
|
for (std::map<std::string, Object *>::const_iterator iter (mObjects.begin());
|
||||||
iter!=mObjects.end(); ++iter)
|
iter!=mObjects.end(); ++iter)
|
||||||
if (iter->second->isEdited())
|
if (iter->second->isEdited())
|
||||||
|
@ -576,7 +576,7 @@ void CSVRender::Cell::setSubMode (int subMode, unsigned int elementMask)
|
||||||
mSubMode = subMode;
|
mSubMode = subMode;
|
||||||
mSubModeElementMask = elementMask;
|
mSubModeElementMask = elementMask;
|
||||||
|
|
||||||
if (elementMask & Mask_Reference)
|
if (elementMask & SceneUtil::Mask_EditorReference)
|
||||||
for (std::map<std::string, Object *>::const_iterator iter (mObjects.begin());
|
for (std::map<std::string, Object *>::const_iterator iter (mObjects.begin());
|
||||||
iter!=mObjects.end(); ++iter)
|
iter!=mObjects.end(); ++iter)
|
||||||
iter->second->setSubMode (subMode);
|
iter->second->setSubMode (subMode);
|
||||||
|
@ -584,10 +584,10 @@ void CSVRender::Cell::setSubMode (int subMode, unsigned int elementMask)
|
||||||
|
|
||||||
void CSVRender::Cell::reset (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());
|
for (std::map<std::string, Object *>::const_iterator iter (mObjects.begin());
|
||||||
iter!=mObjects.end(); ++iter)
|
iter!=mObjects.end(); ++iter)
|
||||||
iter->second->reset();
|
iter->second->reset();
|
||||||
if (mPathgrid && elementMask & Mask_Pathgrid)
|
if (mPathgrid && elementMask & SceneUtil::Mask_Pathgrid)
|
||||||
mPathgrid->resetIndicators();
|
mPathgrid->resetIndicators();
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,11 +11,10 @@
|
||||||
#include "../../model/prefs/shortcutmanager.hpp"
|
#include "../../model/prefs/shortcutmanager.hpp"
|
||||||
|
|
||||||
#include <components/misc/constants.hpp>
|
#include <components/misc/constants.hpp>
|
||||||
|
#include <components/sceneutil/vismask.hpp>
|
||||||
#include "mask.hpp"
|
|
||||||
|
|
||||||
CSVRender::CellArrowTag::CellArrowTag (CellArrow *arrow)
|
CSVRender::CellArrowTag::CellArrowTag (CellArrow *arrow)
|
||||||
: TagBase (Mask_CellArrow), mArrow (arrow)
|
: TagBase (SceneUtil::Mask_EditorCellArrow), mArrow (arrow)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
CSVRender::CellArrow *CSVRender::CellArrowTag::getCellArrow() const
|
CSVRender::CellArrow *CSVRender::CellArrowTag::getCellArrow() const
|
||||||
|
@ -175,7 +174,7 @@ CSVRender::CellArrow::CellArrow (osg::Group *cellNode, Direction direction,
|
||||||
|
|
||||||
mParentNode->addChild (mBaseNode);
|
mParentNode->addChild (mBaseNode);
|
||||||
|
|
||||||
mBaseNode->setNodeMask (Mask_CellArrow);
|
mBaseNode->setNodeMask (SceneUtil::Mask_EditorCellArrow);
|
||||||
|
|
||||||
adjustTransform();
|
adjustTransform();
|
||||||
buildShape();
|
buildShape();
|
||||||
|
|
|
@ -7,8 +7,7 @@
|
||||||
#include <osg/PrimitiveSet>
|
#include <osg/PrimitiveSet>
|
||||||
|
|
||||||
#include <components/esm/loadland.hpp>
|
#include <components/esm/loadland.hpp>
|
||||||
|
#include <components/sceneutil/vismask.hpp>
|
||||||
#include "mask.hpp"
|
|
||||||
|
|
||||||
#include "../../model/world/cellcoordinates.hpp"
|
#include "../../model/world/cellcoordinates.hpp"
|
||||||
|
|
||||||
|
@ -20,7 +19,7 @@ CSVRender::CellBorder::CellBorder(osg::Group* cellNode, const CSMWorld::CellCoor
|
||||||
: mParentNode(cellNode)
|
: mParentNode(cellNode)
|
||||||
{
|
{
|
||||||
mBaseNode = new osg::PositionAttitudeTransform();
|
mBaseNode = new osg::PositionAttitudeTransform();
|
||||||
mBaseNode->setNodeMask(Mask_CellBorder);
|
mBaseNode->setNodeMask(SceneUtil::Mask_EditorCellBorder);
|
||||||
mBaseNode->setPosition(osg::Vec3f(coords.getX() * CellSize, coords.getY() * CellSize, 10));
|
mBaseNode->setPosition(osg::Vec3f(coords.getX() * CellSize, coords.getY() * CellSize, 10));
|
||||||
|
|
||||||
mParentNode->addChild(mBaseNode);
|
mParentNode->addChild(mBaseNode);
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#include <components/misc/constants.hpp>
|
#include <components/misc/constants.hpp>
|
||||||
|
|
||||||
CSVRender::CellMarkerTag::CellMarkerTag(CellMarker *marker)
|
CSVRender::CellMarkerTag::CellMarkerTag(CellMarker *marker)
|
||||||
: TagBase(Mask_CellMarker), mMarker(marker)
|
: TagBase(SceneUtil::Mask_EditorCellMarker), mMarker(marker)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
CSVRender::CellMarker *CSVRender::CellMarkerTag::getCellMarker() const
|
CSVRender::CellMarker *CSVRender::CellMarkerTag::getCellMarker() const
|
||||||
|
@ -79,7 +79,7 @@ CSVRender::CellMarker::CellMarker(
|
||||||
mMarkerNode->getOrCreateStateSet()->setAttribute(mat);
|
mMarkerNode->getOrCreateStateSet()->setAttribute(mat);
|
||||||
|
|
||||||
mMarkerNode->setUserData(new CellMarkerTag(this));
|
mMarkerNode->setUserData(new CellMarkerTag(this));
|
||||||
mMarkerNode->setNodeMask(Mask_CellMarker);
|
mMarkerNode->setNodeMask(SceneUtil::Mask_EditorCellMarker);
|
||||||
|
|
||||||
mCellNode->addChild(mMarkerNode);
|
mCellNode->addChild(mMarkerNode);
|
||||||
|
|
||||||
|
|
|
@ -11,12 +11,12 @@
|
||||||
#include <components/resource/imagemanager.hpp>
|
#include <components/resource/imagemanager.hpp>
|
||||||
#include <components/resource/resourcesystem.hpp>
|
#include <components/resource/resourcesystem.hpp>
|
||||||
#include <components/sceneutil/waterutil.hpp>
|
#include <components/sceneutil/waterutil.hpp>
|
||||||
|
#include <components/sceneutil/vismask.hpp>
|
||||||
|
|
||||||
#include "../../model/world/cell.hpp"
|
#include "../../model/world/cell.hpp"
|
||||||
#include "../../model/world/cellcoordinates.hpp"
|
#include "../../model/world/cellcoordinates.hpp"
|
||||||
#include "../../model/world/data.hpp"
|
#include "../../model/world/data.hpp"
|
||||||
|
|
||||||
#include "mask.hpp"
|
|
||||||
|
|
||||||
namespace CSVRender
|
namespace CSVRender
|
||||||
{
|
{
|
||||||
|
@ -38,7 +38,7 @@ namespace CSVRender
|
||||||
mWaterTransform->setPosition(osg::Vec3f(cellCoords.getX() * CellSize + CellSize / 2.f,
|
mWaterTransform->setPosition(osg::Vec3f(cellCoords.getX() * CellSize + CellSize / 2.f,
|
||||||
cellCoords.getY() * CellSize + CellSize / 2.f, 0));
|
cellCoords.getY() * CellSize + CellSize / 2.f, 0));
|
||||||
|
|
||||||
mWaterTransform->setNodeMask(Mask_Water);
|
mWaterTransform->setNodeMask(SceneUtil::Mask_Water);
|
||||||
mParentNode->addChild(mWaterTransform);
|
mParentNode->addChild(mWaterTransform);
|
||||||
|
|
||||||
mWaterNode = new osg::Geode();
|
mWaterNode = new osg::Geode();
|
||||||
|
|
|
@ -3,18 +3,25 @@
|
||||||
|
|
||||||
#include <QDragEnterEvent>
|
#include <QDragEnterEvent>
|
||||||
#include <QPoint>
|
#include <QPoint>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
#include "../../model/prefs/state.hpp"
|
#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/idtable.hpp"
|
||||||
#include "../../model/world/idtree.hpp"
|
#include "../../model/world/idtree.hpp"
|
||||||
#include "../../model/world/commands.hpp"
|
#include "../../model/world/commands.hpp"
|
||||||
#include "../../model/world/commandmacro.hpp"
|
#include "../../model/world/commandmacro.hpp"
|
||||||
|
#include "../../model/prefs/shortcut.hpp"
|
||||||
|
|
||||||
#include "../widget/scenetoolbar.hpp"
|
#include "../widget/scenetoolbar.hpp"
|
||||||
#include "../widget/scenetoolmode.hpp"
|
#include "../widget/scenetoolmode.hpp"
|
||||||
|
|
||||||
#include "mask.hpp"
|
#include <components/sceneutil/vismask.hpp>
|
||||||
|
|
||||||
#include "object.hpp"
|
#include "object.hpp"
|
||||||
#include "worldspacewidget.hpp"
|
#include "worldspacewidget.hpp"
|
||||||
|
@ -89,13 +96,26 @@ osg::Vec3f CSVRender::InstanceMode::getScreenCoords(const osg::Vec3f& pos)
|
||||||
return pos * combined;
|
return pos * combined;
|
||||||
}
|
}
|
||||||
|
|
||||||
CSVRender::InstanceMode::InstanceMode (WorldspaceWidget *worldspaceWidget, QWidget *parent)
|
CSVRender::InstanceMode::InstanceMode (WorldspaceWidget *worldspaceWidget, osg::ref_ptr<osg::Group> parentNode, QWidget *parent)
|
||||||
: EditMode (worldspaceWidget, QIcon (":scenetoolbar/editing-instance"), Mask_Reference | Mask_Terrain, "Instance editing",
|
: EditMode (worldspaceWidget, QIcon (":scenetoolbar/editing-instance"), SceneUtil::Mask_EditorReference | SceneUtil::Mask_Terrain, "Instance editing",
|
||||||
parent), mSubMode (0), mSubModeId ("move"), mSelectionMode (0), mDragMode (DragMode_None),
|
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&)),
|
connect(this, SIGNAL(requestFocus(const std::string&)),
|
||||||
worldspaceWidget, 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)
|
void CSVRender::InstanceMode::activate (CSVWidget::SceneToolbar *toolbar)
|
||||||
|
@ -137,13 +157,13 @@ void CSVRender::InstanceMode::activate (CSVWidget::SceneToolbar *toolbar)
|
||||||
|
|
||||||
std::string subMode = mSubMode->getCurrentId();
|
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)
|
void CSVRender::InstanceMode::deactivate (CSVWidget::SceneToolbar *toolbar)
|
||||||
{
|
{
|
||||||
mDragMode = DragMode_None;
|
mDragMode = DragMode_None;
|
||||||
getWorldspaceWidget().reset (Mask_Reference);
|
getWorldspaceWidget().reset (SceneUtil::Mask_EditorReference);
|
||||||
|
|
||||||
if (mSelectionMode)
|
if (mSelectionMode)
|
||||||
{
|
{
|
||||||
|
@ -196,7 +216,7 @@ void CSVRender::InstanceMode::secondaryEditPressed (const WorldspaceHitResult& h
|
||||||
|
|
||||||
void CSVRender::InstanceMode::primarySelectPressed (const WorldspaceHitResult& hit)
|
void CSVRender::InstanceMode::primarySelectPressed (const WorldspaceHitResult& hit)
|
||||||
{
|
{
|
||||||
getWorldspaceWidget().clearSelection (Mask_Reference);
|
getWorldspaceWidget().clearSelection (SceneUtil::Mask_EditorReference);
|
||||||
|
|
||||||
if (hit.tag)
|
if (hit.tag)
|
||||||
{
|
{
|
||||||
|
@ -231,13 +251,13 @@ bool CSVRender::InstanceMode::primaryEditStartDrag (const QPoint& pos)
|
||||||
|
|
||||||
WorldspaceHitResult hit = getWorldspaceWidget().mousePick (pos, getWorldspaceWidget().getInteractionMask());
|
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())
|
if (selection.empty())
|
||||||
{
|
{
|
||||||
// Only change selection at the start of drag if no object is already selected
|
// 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())
|
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()))
|
if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (hit.tag.get()))
|
||||||
{
|
{
|
||||||
CSVRender::Object* object = objectTag->mObject;
|
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())
|
if (selection.empty())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -271,7 +291,7 @@ bool CSVRender::InstanceMode::primaryEditStartDrag (const QPoint& pos)
|
||||||
mDragMode = DragMode_Scale;
|
mDragMode = DragMode_Scale;
|
||||||
|
|
||||||
// Calculate scale factor
|
// 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));
|
osg::Vec3f center = getScreenCoords(getSelectionCenter(editedSelection));
|
||||||
|
|
||||||
int widgetHeight = getWorldspaceWidget().height();
|
int widgetHeight = getWorldspaceWidget().height();
|
||||||
|
@ -307,7 +327,7 @@ void CSVRender::InstanceMode::drag (const QPoint& pos, int diffX, int diffY, dou
|
||||||
osg::Vec3f offset;
|
osg::Vec3f offset;
|
||||||
osg::Quat rotation;
|
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)
|
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)
|
void CSVRender::InstanceMode::dragCompleted(const QPoint& pos)
|
||||||
{
|
{
|
||||||
std::vector<osg::ref_ptr<TagBase> > selection =
|
std::vector<osg::ref_ptr<TagBase> > selection =
|
||||||
getWorldspaceWidget().getEdited (Mask_Reference);
|
getWorldspaceWidget().getEdited (SceneUtil::Mask_EditorReference);
|
||||||
|
|
||||||
QUndoStack& undoStack = getWorldspaceWidget().getDocument().getUndoStack();
|
QUndoStack& undoStack = getWorldspaceWidget().getDocument().getUndoStack();
|
||||||
|
|
||||||
|
@ -496,7 +516,7 @@ void CSVRender::InstanceMode::dragCompleted(const QPoint& pos)
|
||||||
|
|
||||||
void CSVRender::InstanceMode::dragAborted()
|
void CSVRender::InstanceMode::dragAborted()
|
||||||
{
|
{
|
||||||
getWorldspaceWidget().reset (Mask_Reference);
|
getWorldspaceWidget().reset (SceneUtil::Mask_EditorReference);
|
||||||
mDragMode = DragMode_None;
|
mDragMode = DragMode_None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -515,7 +535,7 @@ void CSVRender::InstanceMode::dragWheel (int diff, double speedFactor)
|
||||||
offset *= diff * speedFactor;
|
offset *= diff * speedFactor;
|
||||||
|
|
||||||
std::vector<osg::ref_ptr<TagBase> > selection =
|
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());
|
for (std::vector<osg::ref_ptr<TagBase> >::iterator iter (selection.begin());
|
||||||
iter!=selection.end(); ++iter)
|
iter!=selection.end(); ++iter)
|
||||||
|
@ -657,5 +677,207 @@ void CSVRender::InstanceMode::subModeChanged (const std::string& id)
|
||||||
{
|
{
|
||||||
mSubModeId = id;
|
mSubModeId = id;
|
||||||
getWorldspaceWidget().abortDrag();
|
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
|
#ifndef CSV_RENDER_INSTANCEMODE_H
|
||||||
#define CSV_RENDER_INSTANCEMODE_H
|
#define CSV_RENDER_INSTANCEMODE_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
#include <osg/ref_ptr>
|
#include <osg/ref_ptr>
|
||||||
|
#include <osg/Group>
|
||||||
#include <osg/Quat>
|
#include <osg/Quat>
|
||||||
#include <osg/Vec3f>
|
#include <osg/Vec3f>
|
||||||
|
|
||||||
|
@ -16,6 +19,7 @@ namespace CSVRender
|
||||||
{
|
{
|
||||||
class TagBase;
|
class TagBase;
|
||||||
class InstanceSelectionMode;
|
class InstanceSelectionMode;
|
||||||
|
class Object;
|
||||||
|
|
||||||
class InstanceMode : public EditMode
|
class InstanceMode : public EditMode
|
||||||
{
|
{
|
||||||
|
@ -29,6 +33,14 @@ namespace CSVRender
|
||||||
DragMode_Scale
|
DragMode_Scale
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum DropMode
|
||||||
|
{
|
||||||
|
Collision,
|
||||||
|
Terrain,
|
||||||
|
CollisionSep,
|
||||||
|
TerrainSep
|
||||||
|
};
|
||||||
|
|
||||||
CSVWidget::SceneToolMode *mSubMode;
|
CSVWidget::SceneToolMode *mSubMode;
|
||||||
std::string mSubModeId;
|
std::string mSubModeId;
|
||||||
InstanceSelectionMode *mSelectionMode;
|
InstanceSelectionMode *mSelectionMode;
|
||||||
|
@ -36,6 +48,7 @@ namespace CSVRender
|
||||||
int mDragAxis;
|
int mDragAxis;
|
||||||
bool mLocked;
|
bool mLocked;
|
||||||
float mUnitScaleDist;
|
float mUnitScaleDist;
|
||||||
|
osg::ref_ptr<osg::Group> mParentNode;
|
||||||
|
|
||||||
int getSubModeFromId (const std::string& id) const;
|
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 getSelectionCenter(const std::vector<osg::ref_ptr<TagBase> >& selection) const;
|
||||||
osg::Vec3f getScreenCoords(const osg::Vec3f& pos);
|
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:
|
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);
|
virtual void activate (CSVWidget::SceneToolbar *toolbar);
|
||||||
|
|
||||||
|
@ -92,6 +107,25 @@ namespace CSVRender
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void subModeChanged (const std::string& id);
|
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/idtable.hpp"
|
||||||
#include "../../model/world/commands.hpp"
|
#include "../../model/world/commands.hpp"
|
||||||
|
|
||||||
|
#include <components/sceneutil/vismask.hpp>
|
||||||
|
|
||||||
#include "worldspacewidget.hpp"
|
#include "worldspacewidget.hpp"
|
||||||
#include "object.hpp"
|
#include "object.hpp"
|
||||||
|
|
||||||
namespace CSVRender
|
namespace CSVRender
|
||||||
{
|
{
|
||||||
InstanceSelectionMode::InstanceSelectionMode(CSVWidget::SceneToolbar* parent, WorldspaceWidget& worldspaceWidget)
|
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);
|
mSelectSame = new QAction("Extend selection to instances with same object ID", this);
|
||||||
mDeleteSelection = new QAction("Delete selected instances", this);
|
mDeleteSelection = new QAction("Delete selected instances", this);
|
||||||
|
@ -36,12 +38,12 @@ namespace CSVRender
|
||||||
|
|
||||||
void InstanceSelectionMode::selectSame()
|
void InstanceSelectionMode::selectSame()
|
||||||
{
|
{
|
||||||
getWorldspaceWidget().selectAllWithSameParentId(Mask_Reference);
|
getWorldspaceWidget().selectAllWithSameParentId(SceneUtil::Mask_EditorReference);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceSelectionMode::deleteSelection()
|
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&>(
|
CSMWorld::IdTable& referencesTable = dynamic_cast<CSMWorld::IdTable&>(
|
||||||
*getWorldspaceWidget().getDocument().getData().getTableModel(CSMWorld::UniversalId::Type_References));
|
*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/resource/scenemanager.hpp>
|
||||||
#include <components/sceneutil/lightutil.hpp>
|
#include <components/sceneutil/lightutil.hpp>
|
||||||
#include <components/sceneutil/lightmanager.hpp>
|
#include <components/sceneutil/lightmanager.hpp>
|
||||||
|
#include <components/sceneutil/vismask.hpp>
|
||||||
|
|
||||||
#include "actor.hpp"
|
#include "actor.hpp"
|
||||||
#include "mask.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
const float CSVRender::Object::MarkerShaftWidth = 30;
|
const float CSVRender::Object::MarkerShaftWidth = 30;
|
||||||
|
@ -58,7 +58,7 @@ namespace
|
||||||
|
|
||||||
|
|
||||||
CSVRender::ObjectTag::ObjectTag (Object* object)
|
CSVRender::ObjectTag::ObjectTag (Object* object)
|
||||||
: TagBase (Mask_Reference), mObject (object)
|
: TagBase (SceneUtil::Mask_EditorReference), mObject (object)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
QString CSVRender::ObjectTag::getToolTip (bool hideBasics) const
|
QString CSVRender::ObjectTag::getToolTip (bool hideBasics) const
|
||||||
|
@ -140,7 +140,7 @@ void CSVRender::Object::update()
|
||||||
if (light)
|
if (light)
|
||||||
{
|
{
|
||||||
bool isExterior = false; // FIXME
|
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);
|
parentNode->addChild (mRootNode);
|
||||||
|
|
||||||
mRootNode->setNodeMask(Mask_Reference);
|
mRootNode->setNodeMask(SceneUtil::Mask_EditorReference);
|
||||||
|
|
||||||
if (referenceable)
|
if (referenceable)
|
||||||
{
|
{
|
||||||
|
@ -477,6 +477,16 @@ bool CSVRender::Object::getSelected() const
|
||||||
return mSelected;
|
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,
|
bool CSVRender::Object::referenceableDataChanged (const QModelIndex& topLeft,
|
||||||
const QModelIndex& bottomRight)
|
const QModelIndex& bottomRight)
|
||||||
{
|
{
|
||||||
|
@ -705,7 +715,7 @@ void CSVRender::Object::apply (CSMWorld::CommandMacro& commands)
|
||||||
CSMWorld::Columns::ColumnId_PositionXRot+i));
|
CSMWorld::Columns::ColumnId_PositionXRot+i));
|
||||||
|
|
||||||
commands.push (new CSMWorld::ModifyCommand (*model,
|
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;
|
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
|
/// \return Did this call result in a modification of the visual representation of
|
||||||
/// this object?
|
/// this object?
|
||||||
bool referenceableDataChanged (const QModelIndex& topLeft,
|
bool referenceableDataChanged (const QModelIndex& topLeft,
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
#include "../widget/scenetooltoggle2.hpp"
|
#include "../widget/scenetooltoggle2.hpp"
|
||||||
|
|
||||||
#include "editmode.hpp"
|
#include "editmode.hpp"
|
||||||
#include "mask.hpp"
|
|
||||||
#include "cameracontroller.hpp"
|
#include "cameracontroller.hpp"
|
||||||
#include "cellarrow.hpp"
|
#include "cellarrow.hpp"
|
||||||
#include "terraintexturemode.hpp"
|
#include "terraintexturemode.hpp"
|
||||||
|
@ -127,8 +126,8 @@ void CSVRender::PagedWorldspaceWidget::addVisibilitySelectorButtons (
|
||||||
CSVWidget::SceneToolToggle2 *tool)
|
CSVWidget::SceneToolToggle2 *tool)
|
||||||
{
|
{
|
||||||
WorldspaceWidget::addVisibilitySelectorButtons (tool);
|
WorldspaceWidget::addVisibilitySelectorButtons (tool);
|
||||||
tool->addButton (Button_Terrain, Mask_Terrain, "Terrain");
|
tool->addButton (Button_Terrain, SceneUtil::Mask_Terrain, "Terrain");
|
||||||
tool->addButton (Button_Fog, Mask_Fog, "Fog", "", true);
|
//tool->addButton (Button_Fog, Mask_Fog, "Fog", "", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVRender::PagedWorldspaceWidget::addEditModeSelectorButtons (
|
void CSVRender::PagedWorldspaceWidget::addEditModeSelectorButtons (
|
||||||
|
@ -142,16 +141,16 @@ void CSVRender::PagedWorldspaceWidget::addEditModeSelectorButtons (
|
||||||
tool->addButton (
|
tool->addButton (
|
||||||
new TerrainTextureMode (this, mRootNode, tool), "terrain-texture");
|
new TerrainTextureMode (this, mRootNode, tool), "terrain-texture");
|
||||||
tool->addButton (
|
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");
|
"terrain-vertex");
|
||||||
tool->addButton (
|
tool->addButton (
|
||||||
new EditMode (this, QIcon (":placeholder"), Mask_Reference, "Terrain movement"),
|
new EditMode (this, QIcon (":placeholder"), SceneUtil::Mask_EditorReference, "Terrain movement"),
|
||||||
"terrain-move");
|
"terrain-move");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVRender::PagedWorldspaceWidget::handleInteractionPress (const WorldspaceHitResult& hit, InteractionType type)
|
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()))
|
if (CellArrowTag *cellArrowTag = dynamic_cast<CSVRender::CellArrowTag *> (hit.tag.get()))
|
||||||
{
|
{
|
||||||
|
@ -874,9 +873,9 @@ CSVWidget::SceneToolToggle2 *CSVRender::PagedWorldspaceWidget::makeControlVisibi
|
||||||
mControlElements = new CSVWidget::SceneToolToggle2 (parent,
|
mControlElements = new CSVWidget::SceneToolToggle2 (parent,
|
||||||
"Controls & Guides Visibility", ":scenetoolbar/scene-view-marker-c", ":scenetoolbar/scene-view-marker-");
|
"Controls & Guides Visibility", ":scenetoolbar/scene-view-marker-c", ":scenetoolbar/scene-view-marker-");
|
||||||
|
|
||||||
mControlElements->addButton (1, Mask_CellMarker, "Cell Marker");
|
mControlElements->addButton (1, SceneUtil::Mask_EditorCellMarker, "Cell Marker");
|
||||||
mControlElements->addButton (2, Mask_CellArrow, "Cell Arrows");
|
mControlElements->addButton (2, SceneUtil::Mask_EditorCellArrow, "Cell Arrows");
|
||||||
mControlElements->addButton (4, Mask_CellBorder, "Cell Border");
|
mControlElements->addButton (4, SceneUtil::Mask_EditorCellBorder, "Cell Border");
|
||||||
|
|
||||||
mControlElements->setSelectionMask (0xffffffff);
|
mControlElements->setSelectionMask (0xffffffff);
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <osg/Vec3>
|
#include <osg/Vec3>
|
||||||
|
|
||||||
#include <components/sceneutil/pathgridutil.hpp>
|
#include <components/sceneutil/pathgridutil.hpp>
|
||||||
|
#include <components/sceneutil/vismask.hpp>
|
||||||
|
|
||||||
#include "../../model/world/cell.hpp"
|
#include "../../model/world/cell.hpp"
|
||||||
#include "../../model/world/commands.hpp"
|
#include "../../model/world/commands.hpp"
|
||||||
|
@ -31,7 +32,7 @@ namespace CSVRender
|
||||||
};
|
};
|
||||||
|
|
||||||
PathgridTag::PathgridTag(Pathgrid* pathgrid)
|
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->setPosition(osg::Vec3f(mCoords.getX() * CoordScalar, mCoords.getY() * CoordScalar, 0.f));
|
||||||
mBaseNode->setUserData(mTag);
|
mBaseNode->setUserData(mTag);
|
||||||
mBaseNode->setUpdateCallback(new PathgridNodeCallback());
|
mBaseNode->setUpdateCallback(new PathgridNodeCallback());
|
||||||
mBaseNode->setNodeMask(Mask_Pathgrid);
|
mBaseNode->setNodeMask(SceneUtil::Mask_Pathgrid);
|
||||||
mParent->addChild(mBaseNode);
|
mParent->addChild(mBaseNode);
|
||||||
|
|
||||||
mPathgridGeode = new osg::Geode();
|
mPathgridGeode = new osg::Geode();
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <QPoint>
|
#include <QPoint>
|
||||||
|
|
||||||
#include <components/sceneutil/pathgridutil.hpp>
|
#include <components/sceneutil/pathgridutil.hpp>
|
||||||
|
#include <components/sceneutil/vismask.hpp>
|
||||||
|
|
||||||
#include "../../model/prefs/state.hpp"
|
#include "../../model/prefs/state.hpp"
|
||||||
|
|
||||||
|
@ -15,7 +16,6 @@
|
||||||
#include "../widget/scenetoolbar.hpp"
|
#include "../widget/scenetoolbar.hpp"
|
||||||
|
|
||||||
#include "cell.hpp"
|
#include "cell.hpp"
|
||||||
#include "mask.hpp"
|
|
||||||
#include "pathgrid.hpp"
|
#include "pathgrid.hpp"
|
||||||
#include "pathgridselectionmode.hpp"
|
#include "pathgridselectionmode.hpp"
|
||||||
#include "worldspacewidget.hpp"
|
#include "worldspacewidget.hpp"
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
namespace CSVRender
|
namespace CSVRender
|
||||||
{
|
{
|
||||||
PathgridMode::PathgridMode(WorldspaceWidget* worldspaceWidget, QWidget* parent)
|
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)
|
getTooltip(), parent)
|
||||||
, mDragMode(DragMode_None)
|
, mDragMode(DragMode_None)
|
||||||
, mFromNode(0)
|
, mFromNode(0)
|
||||||
|
@ -110,7 +110,7 @@ namespace CSVRender
|
||||||
|
|
||||||
void PathgridMode::primarySelectPressed(const WorldspaceHitResult& hit)
|
void PathgridMode::primarySelectPressed(const WorldspaceHitResult& hit)
|
||||||
{
|
{
|
||||||
getWorldspaceWidget().clearSelection(Mask_Pathgrid);
|
getWorldspaceWidget().clearSelection(SceneUtil::Mask_Pathgrid);
|
||||||
|
|
||||||
if (hit.tag)
|
if (hit.tag)
|
||||||
{
|
{
|
||||||
|
@ -131,7 +131,7 @@ namespace CSVRender
|
||||||
{
|
{
|
||||||
if (tag->getPathgrid()->getId() != mLastId)
|
if (tag->getPathgrid()->getId() != mLastId)
|
||||||
{
|
{
|
||||||
getWorldspaceWidget().clearSelection(Mask_Pathgrid);
|
getWorldspaceWidget().clearSelection(SceneUtil::Mask_Pathgrid);
|
||||||
mLastId = tag->getPathgrid()->getId();
|
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)
|
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())
|
if (CSMPrefs::get()["3D Scene Input"]["context-select"].isTrue())
|
||||||
{
|
{
|
||||||
|
@ -156,7 +156,7 @@ namespace CSVRender
|
||||||
if (dynamic_cast<PathgridTag*>(hit.tag.get()))
|
if (dynamic_cast<PathgridTag*>(hit.tag.get()))
|
||||||
{
|
{
|
||||||
primarySelectPressed(hit);
|
primarySelectPressed(hit);
|
||||||
selection = getWorldspaceWidget().getSelection (Mask_Pathgrid);
|
selection = getWorldspaceWidget().getSelection (SceneUtil::Mask_Pathgrid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,7 +192,7 @@ namespace CSVRender
|
||||||
{
|
{
|
||||||
if (mDragMode == DragMode_Move)
|
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)
|
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)
|
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)
|
for (std::vector<osg::ref_ptr<TagBase> >::iterator it = selection.begin(); it != selection.end(); ++it)
|
||||||
{
|
{
|
||||||
if (PathgridTag* tag = dynamic_cast<PathgridTag*>(it->get()))
|
if (PathgridTag* tag = dynamic_cast<PathgridTag*>(it->get()))
|
||||||
|
@ -272,11 +272,11 @@ namespace CSVRender
|
||||||
}
|
}
|
||||||
|
|
||||||
mDragMode = DragMode_None;
|
mDragMode = DragMode_None;
|
||||||
getWorldspaceWidget().reset(Mask_Pathgrid);
|
getWorldspaceWidget().reset(SceneUtil::Mask_Pathgrid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PathgridMode::dragAborted()
|
void PathgridMode::dragAborted()
|
||||||
{
|
{
|
||||||
getWorldspaceWidget().reset(Mask_Pathgrid);
|
getWorldspaceWidget().reset(SceneUtil::Mask_Pathgrid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
namespace CSVRender
|
namespace CSVRender
|
||||||
{
|
{
|
||||||
PathgridSelectionMode::PathgridSelectionMode(CSVWidget::SceneToolbar* parent, WorldspaceWidget& worldspaceWidget)
|
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);
|
mRemoveSelectedNodes = new QAction("Remove selected nodes", this);
|
||||||
mRemoveSelectedEdges = new QAction("Remove edges between selected nodes", this);
|
mRemoveSelectedEdges = new QAction("Remove edges between selected nodes", this);
|
||||||
|
@ -37,7 +37,7 @@ namespace CSVRender
|
||||||
|
|
||||||
void PathgridSelectionMode::removeSelectedNodes()
|
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)
|
for (std::vector<osg::ref_ptr<TagBase> >::iterator it = selection.begin(); it != selection.end(); ++it)
|
||||||
{
|
{
|
||||||
|
@ -54,7 +54,7 @@ namespace CSVRender
|
||||||
|
|
||||||
void PathgridSelectionMode::removeSelectedEdges()
|
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)
|
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/scenemanager.hpp>
|
||||||
#include <components/resource/resourcesystem.hpp>
|
#include <components/resource/resourcesystem.hpp>
|
||||||
#include <components/sceneutil/lightmanager.hpp>
|
#include <components/sceneutil/lightmanager.hpp>
|
||||||
|
#include <components/sceneutil/vismask.hpp>
|
||||||
|
|
||||||
#include "../widget/scenetoolmode.hpp"
|
#include "../widget/scenetoolmode.hpp"
|
||||||
|
|
||||||
|
@ -25,7 +26,6 @@
|
||||||
#include "../../model/prefs/shortcuteventhandler.hpp"
|
#include "../../model/prefs/shortcuteventhandler.hpp"
|
||||||
|
|
||||||
#include "lighting.hpp"
|
#include "lighting.hpp"
|
||||||
#include "mask.hpp"
|
|
||||||
#include "cameracontroller.hpp"
|
#include "cameracontroller.hpp"
|
||||||
|
|
||||||
namespace CSVRender
|
namespace CSVRender
|
||||||
|
@ -71,7 +71,7 @@ RenderWidget::RenderWidget(QWidget *parent, Qt::WindowFlags f)
|
||||||
|
|
||||||
SceneUtil::LightManager* lightMgr = new SceneUtil::LightManager;
|
SceneUtil::LightManager* lightMgr = new SceneUtil::LightManager;
|
||||||
lightMgr->setStartLight(1);
|
lightMgr->setStartLight(1);
|
||||||
lightMgr->setLightingMask(Mask_Lighting);
|
lightMgr->setLightingMask(SceneUtil::Mask_Lighting);
|
||||||
mRootNode = lightMgr;
|
mRootNode = lightMgr;
|
||||||
|
|
||||||
mView->getCamera()->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
|
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
|
// Add ability to signal osg to show its statistics for debugging purposes
|
||||||
mView->addEventHandler(new osgViewer::StatsHandler);
|
mView->addEventHandler(new osgViewer::StatsHandler);
|
||||||
|
|
||||||
mView->getCamera()->setCullMask(~(Mask_UpdateVisitor));
|
mView->getCamera()->setCullMask(~(SceneUtil::Mask_UpdateVisitor));
|
||||||
|
|
||||||
viewer.addView(mView);
|
viewer.addView(mView);
|
||||||
viewer.setDone(false);
|
viewer.setDone(false);
|
||||||
|
@ -100,6 +100,14 @@ RenderWidget::~RenderWidget()
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
CompositeViewer::get().removeView(mView);
|
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)
|
catch(const std::exception& e)
|
||||||
{
|
{
|
||||||
|
@ -114,7 +122,7 @@ void RenderWidget::flagAsModified()
|
||||||
|
|
||||||
void RenderWidget::setVisibilityMask(int mask)
|
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()
|
osg::Camera *RenderWidget::getCamera()
|
||||||
|
@ -204,7 +212,7 @@ SceneWidget::SceneWidget(std::shared_ptr<Resource::ResourceSystem> resourceSyste
|
||||||
mOrbitCamControl = new OrbitCameraController(this);
|
mOrbitCamControl = new OrbitCameraController(this);
|
||||||
mCurrentCamControl = mFreeCamControl;
|
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() );
|
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);
|
setLighting(&mLightingDay);
|
||||||
|
|
||||||
mResourceSystem->getSceneManager()->setParticleSystemMask(Mask_ParticleSystem);
|
mResourceSystem->getSceneManager()->setParticleSystemMask(SceneUtil::Mask_ParticleSystem);
|
||||||
|
|
||||||
// Recieve mouse move event even if mouse button is not pressed
|
// Recieve mouse move event even if mouse button is not pressed
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
|
@ -342,7 +350,7 @@ void SceneWidget::update(double dt)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mCurrentCamControl->setup(mRootNode, Mask_Reference | Mask_Terrain, CameraController::WorldUp);
|
mCurrentCamControl->setup(mRootNode, SceneUtil::Mask_EditorReference | SceneUtil::Mask_Terrain, CameraController::WorldUp);
|
||||||
mCamPositionSet = true;
|
mCamPositionSet = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
|
|
||||||
#include "../widget/scenetoolmode.hpp"
|
#include "../widget/scenetoolmode.hpp"
|
||||||
|
|
||||||
#include "mask.hpp"
|
|
||||||
|
|
||||||
class QAction;
|
class QAction;
|
||||||
|
|
||||||
namespace CSVRender
|
namespace CSVRender
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
|
|
||||||
#include "tagbase.hpp"
|
#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;
|
return mMask;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,19 +5,19 @@
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
#include "mask.hpp"
|
#include <components/sceneutil/vismask.hpp>
|
||||||
|
|
||||||
namespace CSVRender
|
namespace CSVRender
|
||||||
{
|
{
|
||||||
class TagBase : public osg::Referenced
|
class TagBase : public osg::Referenced
|
||||||
{
|
{
|
||||||
Mask mMask;
|
SceneUtil::VisMask mMask;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
TagBase (Mask mask);
|
TagBase (SceneUtil::VisMask mask);
|
||||||
|
|
||||||
Mask getMask() const;
|
SceneUtil::VisMask getMask() const;
|
||||||
|
|
||||||
virtual QString getToolTip (bool hideBasics) const;
|
virtual QString getToolTip (bool hideBasics) const;
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include <components/esm/loadland.hpp>
|
#include <components/esm/loadland.hpp>
|
||||||
#include <components/debug/debuglog.hpp>
|
#include <components/debug/debuglog.hpp>
|
||||||
|
#include <components/sceneutil/vismask.hpp>
|
||||||
|
|
||||||
#include "../widget/brushshapes.hpp"
|
#include "../widget/brushshapes.hpp"
|
||||||
#include "../widget/modebutton.hpp"
|
#include "../widget/modebutton.hpp"
|
||||||
|
@ -38,13 +39,12 @@
|
||||||
|
|
||||||
#include "editmode.hpp"
|
#include "editmode.hpp"
|
||||||
#include "pagedworldspacewidget.hpp"
|
#include "pagedworldspacewidget.hpp"
|
||||||
#include "mask.hpp"
|
|
||||||
#include "tagbase.hpp"
|
#include "tagbase.hpp"
|
||||||
#include "terrainselection.hpp"
|
#include "terrainselection.hpp"
|
||||||
#include "worldspacewidget.hpp"
|
#include "worldspacewidget.hpp"
|
||||||
|
|
||||||
CSVRender::TerrainShapeMode::TerrainShapeMode (WorldspaceWidget *worldspaceWidget, osg::Group* parentNode, QWidget *parent)
|
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)
|
mParentNode(parentNode)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -273,7 +273,6 @@ void CSVRender::TerrainShapeMode::applyTerrainEditChanges()
|
||||||
*document.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures));
|
*document.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures));
|
||||||
|
|
||||||
int landshapeColumn = landTable.findColumnIndex(CSMWorld::Columns::ColumnId_LandHeightsIndex);
|
int landshapeColumn = landTable.findColumnIndex(CSMWorld::Columns::ColumnId_LandHeightsIndex);
|
||||||
int landMapLodColumn = landTable.findColumnIndex(CSMWorld::Columns::ColumnId_LandMapLodIndex);
|
|
||||||
int landnormalsColumn = landTable.findColumnIndex(CSMWorld::Columns::ColumnId_LandNormalsIndex);
|
int landnormalsColumn = landTable.findColumnIndex(CSMWorld::Columns::ColumnId_LandNormalsIndex);
|
||||||
|
|
||||||
QUndoStack& undoStack = document.getUndoStack();
|
QUndoStack& undoStack = document.getUndoStack();
|
||||||
|
@ -287,9 +286,7 @@ void CSVRender::TerrainShapeMode::applyTerrainEditChanges()
|
||||||
std::string cellId = CSMWorld::CellCoordinates::generateId(cellCoordinates.getX(), cellCoordinates.getY());
|
std::string cellId = CSMWorld::CellCoordinates::generateId(cellCoordinates.getX(), cellCoordinates.getY());
|
||||||
undoStack.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, cellId));
|
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::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::LandHeightsColumn::DataType landShapeNew(landShapePointer);
|
||||||
CSMWorld::LandMapLodColumn::DataType mapLodShapeNew(landMapLodPointer);
|
|
||||||
CSVRender::PagedWorldspaceWidget *paged = dynamic_cast<CSVRender::PagedWorldspaceWidget *> (&getWorldspaceWidget());
|
CSVRender::PagedWorldspaceWidget *paged = dynamic_cast<CSVRender::PagedWorldspaceWidget *> (&getWorldspaceWidget());
|
||||||
|
|
||||||
// Generate land height record
|
// 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);
|
pushEditToCommand(landShapeNew, document, landTable, cellId);
|
||||||
pushLodToCommand(mapLodShapeNew, document, landTable, cellId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(CSMWorld::CellCoordinates cellCoordinates: mAlteredCells)
|
for(CSMWorld::CellCoordinates cellCoordinates: mAlteredCells)
|
||||||
|
@ -1136,18 +1114,6 @@ void CSVRender::TerrainShapeMode::pushNormalsEditToCommand(const CSMWorld::LandN
|
||||||
undoStack.push (new CSMWorld::ModifyCommand(landTable, index, changedLand));
|
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)
|
bool CSVRender::TerrainShapeMode::noCell(const std::string& cellId)
|
||||||
{
|
{
|
||||||
CSMDoc::Document& document = getWorldspaceWidget().getDocument();
|
CSMDoc::Document& document = getWorldspaceWidget().getDocument();
|
||||||
|
|
|
@ -148,10 +148,6 @@ namespace CSVRender
|
||||||
void pushNormalsEditToCommand(const CSMWorld::LandNormalsColumn::DataType& newLandGrid, CSMDoc::Document& document,
|
void pushNormalsEditToCommand(const CSMWorld::LandNormalsColumn::DataType& newLandGrid, CSMDoc::Document& document,
|
||||||
CSMWorld::IdTable& landTable, const std::string& cellId);
|
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 noCell(const std::string& cellId);
|
||||||
|
|
||||||
bool noLand(const std::string& cellId);
|
bool noLand(const std::string& cellId);
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <osg/Group>
|
#include <osg/Group>
|
||||||
|
|
||||||
#include <components/esm/loadland.hpp>
|
#include <components/esm/loadland.hpp>
|
||||||
|
#include <components/sceneutil/vismask.hpp>
|
||||||
|
|
||||||
#include "../widget/modebutton.hpp"
|
#include "../widget/modebutton.hpp"
|
||||||
#include "../widget/scenetoolbar.hpp"
|
#include "../widget/scenetoolbar.hpp"
|
||||||
|
@ -34,12 +35,11 @@
|
||||||
|
|
||||||
#include "editmode.hpp"
|
#include "editmode.hpp"
|
||||||
#include "pagedworldspacewidget.hpp"
|
#include "pagedworldspacewidget.hpp"
|
||||||
#include "mask.hpp"
|
|
||||||
#include "object.hpp" // Something small needed regarding pointers from here ()
|
#include "object.hpp" // Something small needed regarding pointers from here ()
|
||||||
#include "worldspacewidget.hpp"
|
#include "worldspacewidget.hpp"
|
||||||
|
|
||||||
CSVRender::TerrainTextureMode::TerrainTextureMode (WorldspaceWidget *worldspaceWidget, osg::Group* parentNode, QWidget *parent)
|
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"),
|
mBrushTexture("L0#0"),
|
||||||
mBrushSize(1),
|
mBrushSize(1),
|
||||||
mBrushShape(0),
|
mBrushShape(0),
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
#include "../widget/scenetooltoggle2.hpp"
|
#include "../widget/scenetooltoggle2.hpp"
|
||||||
|
|
||||||
#include "cameracontroller.hpp"
|
#include "cameracontroller.hpp"
|
||||||
#include "mask.hpp"
|
|
||||||
#include "tagbase.hpp"
|
#include "tagbase.hpp"
|
||||||
|
|
||||||
void CSVRender::UnpagedWorldspaceWidget::update()
|
void CSVRender::UnpagedWorldspaceWidget::update()
|
||||||
|
@ -304,8 +303,8 @@ void CSVRender::UnpagedWorldspaceWidget::addVisibilitySelectorButtons (
|
||||||
CSVWidget::SceneToolToggle2 *tool)
|
CSVWidget::SceneToolToggle2 *tool)
|
||||||
{
|
{
|
||||||
WorldspaceWidget::addVisibilitySelectorButtons (tool);
|
WorldspaceWidget::addVisibilitySelectorButtons (tool);
|
||||||
tool->addButton (Button_Terrain, Mask_Terrain, "Terrain", "", true);
|
tool->addButton (Button_Terrain, SceneUtil::Mask_Terrain, "Terrain", "", true);
|
||||||
tool->addButton (Button_Fog, Mask_Fog, "Fog");
|
//tool->addButton (Button_Fog, Mask_Fog, "Fog");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CSVRender::UnpagedWorldspaceWidget::getStartupInstruction()
|
std::string CSVRender::UnpagedWorldspaceWidget::getStartupInstruction()
|
||||||
|
|
|
@ -26,8 +26,9 @@
|
||||||
#include "../widget/scenetooltoggle2.hpp"
|
#include "../widget/scenetooltoggle2.hpp"
|
||||||
#include "../widget/scenetoolrun.hpp"
|
#include "../widget/scenetoolrun.hpp"
|
||||||
|
|
||||||
|
#include <components/sceneutil/vismask.hpp>
|
||||||
|
|
||||||
#include "object.hpp"
|
#include "object.hpp"
|
||||||
#include "mask.hpp"
|
|
||||||
#include "instancemode.hpp"
|
#include "instancemode.hpp"
|
||||||
#include "pathgridmode.hpp"
|
#include "pathgridmode.hpp"
|
||||||
#include "cameracontroller.hpp"
|
#include "cameracontroller.hpp"
|
||||||
|
@ -138,7 +139,7 @@ void CSVRender::WorldspaceWidget::settingChanged (const CSMPrefs::Setting *setti
|
||||||
{
|
{
|
||||||
float alpha = setting->toDouble();
|
float alpha = setting->toDouble();
|
||||||
// getSelection is virtual, thus this can not be called from the constructor
|
// 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)
|
for (osg::ref_ptr<TagBase> tag : selection)
|
||||||
{
|
{
|
||||||
if (auto objTag = dynamic_cast<ObjectTag*>(tag.get()))
|
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)
|
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
|
unsigned int CSVRender::WorldspaceWidget::getInteractionMask() const
|
||||||
|
@ -361,15 +362,15 @@ void CSVRender::WorldspaceWidget::setEditLock (bool locked)
|
||||||
void CSVRender::WorldspaceWidget::addVisibilitySelectorButtons (
|
void CSVRender::WorldspaceWidget::addVisibilitySelectorButtons (
|
||||||
CSVWidget::SceneToolToggle2 *tool)
|
CSVWidget::SceneToolToggle2 *tool)
|
||||||
{
|
{
|
||||||
tool->addButton (Button_Reference, Mask_Reference, "Instances");
|
tool->addButton (Button_Reference, SceneUtil::Mask_EditorReference, "Instances");
|
||||||
tool->addButton (Button_Water, Mask_Water, "Water");
|
tool->addButton (Button_Water, SceneUtil::Mask_Water, "Water");
|
||||||
tool->addButton (Button_Pathgrid, Mask_Pathgrid, "Pathgrid");
|
tool->addButton (Button_Pathgrid, SceneUtil::Mask_Pathgrid, "Pathgrid");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVRender::WorldspaceWidget::addEditModeSelectorButtons (CSVWidget::SceneToolMode *tool)
|
void CSVRender::WorldspaceWidget::addEditModeSelectorButtons (CSVWidget::SceneToolMode *tool)
|
||||||
{
|
{
|
||||||
/// \todo replace EditMode with suitable subclasses
|
/// \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");
|
tool->addButton (new PathgridMode (this, tool), "pathgrid");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
#include "../../model/world/tablemimedata.hpp"
|
#include "../../model/world/tablemimedata.hpp"
|
||||||
|
|
||||||
#include "scenewidget.hpp"
|
#include "scenewidget.hpp"
|
||||||
#include "mask.hpp"
|
|
||||||
|
|
||||||
namespace CSMPrefs
|
namespace CSMPrefs
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,10 +18,10 @@ set(GAME_HEADER
|
||||||
source_group(game FILES ${GAME} ${GAME_HEADER})
|
source_group(game FILES ${GAME} ${GAME_HEADER})
|
||||||
|
|
||||||
add_openmw_dir (mwrender
|
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
|
creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation
|
||||||
bulletdebugdraw globalmap characterpreview camera localmap water terrainstorage ripplesimulation
|
bulletdebugdraw globalmap characterpreview camera localmap water terrainstorage ripplesimulation
|
||||||
renderbin actoranimation landmanager navmesh actorspaths
|
renderbin actoranimation landmanager navmesh actorspaths recastmesh
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwinput
|
add_openmw_dir (mwinput
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
#include <components/compiler/extensions0.hpp>
|
#include <components/compiler/extensions0.hpp>
|
||||||
|
|
||||||
|
#include <components/sceneutil/vismask.hpp>
|
||||||
#include <components/sceneutil/workqueue.hpp>
|
#include <components/sceneutil/workqueue.hpp>
|
||||||
|
|
||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/files/configurationmanager.hpp>
|
||||||
|
@ -47,8 +48,6 @@
|
||||||
#include "mwworld/player.hpp"
|
#include "mwworld/player.hpp"
|
||||||
#include "mwworld/worldimp.hpp"
|
#include "mwworld/worldimp.hpp"
|
||||||
|
|
||||||
#include "mwrender/vismask.hpp"
|
|
||||||
|
|
||||||
#include "mwclass/classes.hpp"
|
#include "mwclass/classes.hpp"
|
||||||
|
|
||||||
#include "mwdialogue/dialoguemanagerimp.hpp"
|
#include "mwdialogue/dialoguemanagerimp.hpp"
|
||||||
|
@ -558,7 +557,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
||||||
std::string myguiResources = (mResDir / "mygui").string();
|
std::string myguiResources = (mResDir / "mygui").string();
|
||||||
osg::ref_ptr<osg::Group> guiRoot = new osg::Group;
|
osg::ref_ptr<osg::Group> guiRoot = new osg::Group;
|
||||||
guiRoot->setName("GUI Root");
|
guiRoot->setName("GUI Root");
|
||||||
guiRoot->setNodeMask(MWRender::Mask_GUI);
|
guiRoot->setNodeMask(SceneUtil::Mask_GUI);
|
||||||
rootNode->addChild(guiRoot);
|
rootNode->addChild(guiRoot);
|
||||||
MWGui::WindowManager* window = new MWGui::WindowManager(mViewer, guiRoot, mResourceSystem.get(), mWorkQueue.get(),
|
MWGui::WindowManager* window = new MWGui::WindowManager(mViewer, guiRoot, mResourceSystem.get(), mWorkQueue.get(),
|
||||||
mCfgMgr.getLogPath().string() + std::string("/"), myguiResources,
|
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 (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 void setActorCollisionMode(const MWWorld::Ptr& ptr, bool internal, bool external) = 0;
|
||||||
virtual bool isActorCollisionEnabled(const MWWorld::Ptr& ptr) = 0;
|
virtual bool isActorCollisionEnabled(const MWWorld::Ptr& ptr) = 0;
|
||||||
|
|
||||||
|
@ -653,6 +655,8 @@ namespace MWBase
|
||||||
virtual MWPhysics::PhysicsSystem* getPhysicsSystem(void) = 0;
|
virtual MWPhysics::PhysicsSystem* getPhysicsSystem(void) = 0;
|
||||||
|
|
||||||
virtual void toggleWaterRTT(bool enable) = 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/esm/loadacti.hpp>
|
||||||
#include <components/misc/rng.hpp>
|
#include <components/misc/rng.hpp>
|
||||||
#include <components/sceneutil/positionattitudetransform.hpp>
|
#include <components/sceneutil/positionattitudetransform.hpp>
|
||||||
|
#include <components/sceneutil/vismask.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
@ -19,7 +20,6 @@
|
||||||
|
|
||||||
#include "../mwrender/objects.hpp"
|
#include "../mwrender/objects.hpp"
|
||||||
#include "../mwrender/renderinginterface.hpp"
|
#include "../mwrender/renderinginterface.hpp"
|
||||||
#include "../mwrender/vismask.hpp"
|
|
||||||
|
|
||||||
#include "../mwgui/tooltips.hpp"
|
#include "../mwgui/tooltips.hpp"
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ namespace MWClass
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
renderingInterface.getObjects().insertModel(ptr, model, true);
|
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)
|
if (!state.mHasCustomState)
|
||||||
return;
|
return;
|
||||||
const ESM::ContainerState& state2 = dynamic_cast<const ESM::ContainerState&> (state);
|
|
||||||
|
|
||||||
if (!ptr.getRefData().getCustomData())
|
if (!ptr.getRefData().getCustomData())
|
||||||
{
|
{
|
||||||
|
@ -326,21 +325,21 @@ namespace MWClass
|
||||||
ptr.getRefData().setCustomData (data.release());
|
ptr.getRefData().setCustomData (data.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamic_cast<ContainerCustomData&> (*ptr.getRefData().getCustomData()).mContainerStore.
|
ContainerCustomData& customData = ptr.getRefData().getCustomData()->asContainerCustomData();
|
||||||
readState (state2.mInventory);
|
const ESM::ContainerState& containerState = state.asContainerState();
|
||||||
|
customData.mContainerStore.readState (containerState.mInventory);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Container::writeAdditionalState (const MWWorld::ConstPtr& ptr, ESM::ObjectState& state) const
|
void Container::writeAdditionalState (const MWWorld::ConstPtr& ptr, ESM::ObjectState& state) const
|
||||||
{
|
{
|
||||||
ESM::ContainerState& state2 = dynamic_cast<ESM::ContainerState&> (state);
|
|
||||||
|
|
||||||
if (!ptr.getRefData().getCustomData())
|
if (!ptr.getRefData().getCustomData())
|
||||||
{
|
{
|
||||||
state.mHasCustomState = false;
|
state.mHasCustomState = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamic_cast<const ContainerCustomData&> (*ptr.getRefData().getCustomData()).mContainerStore.
|
const ContainerCustomData& customData = ptr.getRefData().getCustomData()->asContainerCustomData();
|
||||||
writeState (state2.mInventory);
|
ESM::ContainerState& containerState = state.asContainerState();
|
||||||
|
customData.mContainerStore.writeState (containerState.mInventory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -777,8 +777,6 @@ namespace MWClass
|
||||||
if (!state.mHasCustomState)
|
if (!state.mHasCustomState)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::CreatureState& state2 = dynamic_cast<const ESM::CreatureState&> (state);
|
|
||||||
|
|
||||||
if (state.mVersion > 0)
|
if (state.mVersion > 0)
|
||||||
{
|
{
|
||||||
if (!ptr.getRefData().getCustomData())
|
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.
|
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();
|
CreatureCustomData& customData = ptr.getRefData().getCustomData()->asCreatureCustomData();
|
||||||
|
const ESM::CreatureState& creatureState = state.asCreatureState();
|
||||||
customData.mContainerStore->readState (state2.mInventory);
|
customData.mContainerStore->readState (creatureState.mInventory);
|
||||||
customData.mCreatureStats.readState (state2.mCreatureStats);
|
customData.mCreatureStats.readState (creatureState.mCreatureStats);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Creature::writeAdditionalState (const MWWorld::ConstPtr& ptr, ESM::ObjectState& state)
|
void Creature::writeAdditionalState (const MWWorld::ConstPtr& ptr, ESM::ObjectState& state)
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
ESM::CreatureState& state2 = dynamic_cast<ESM::CreatureState&> (state);
|
|
||||||
|
|
||||||
if (!ptr.getRefData().getCustomData())
|
if (!ptr.getRefData().getCustomData())
|
||||||
{
|
{
|
||||||
state.mHasCustomState = false;
|
state.mHasCustomState = false;
|
||||||
|
@ -815,9 +811,9 @@ namespace MWClass
|
||||||
}
|
}
|
||||||
|
|
||||||
const CreatureCustomData& customData = ptr.getRefData().getCustomData()->asCreatureCustomData();
|
const CreatureCustomData& customData = ptr.getRefData().getCustomData()->asCreatureCustomData();
|
||||||
|
ESM::CreatureState& creatureState = state.asCreatureState();
|
||||||
customData.mContainerStore->writeState (state2.mInventory);
|
customData.mContainerStore->writeState (creatureState.mInventory);
|
||||||
customData.mCreatureStats.writeState (state2.mCreatureStats);
|
customData.mCreatureStats.writeState (creatureState.mCreatureStats);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Creature::getBaseGold(const MWWorld::ConstPtr& ptr) const
|
int Creature::getBaseGold(const MWWorld::ConstPtr& ptr) const
|
||||||
|
|
|
@ -151,19 +151,16 @@ namespace MWClass
|
||||||
if (!state.mHasCustomState)
|
if (!state.mHasCustomState)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::CreatureLevListState& state2 = dynamic_cast<const ESM::CreatureLevListState&> (state);
|
|
||||||
|
|
||||||
ensureCustomData(ptr);
|
ensureCustomData(ptr);
|
||||||
CreatureLevListCustomData& customData = ptr.getRefData().getCustomData()->asCreatureLevListCustomData();
|
CreatureLevListCustomData& customData = ptr.getRefData().getCustomData()->asCreatureLevListCustomData();
|
||||||
customData.mSpawnActorId = state2.mSpawnActorId;
|
const ESM::CreatureLevListState& levListState = state.asCreatureLevListState();
|
||||||
customData.mSpawn = state2.mSpawn;
|
customData.mSpawnActorId = levListState.mSpawnActorId;
|
||||||
|
customData.mSpawn = levListState.mSpawn;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreatureLevList::writeAdditionalState (const MWWorld::ConstPtr& ptr, ESM::ObjectState& state)
|
void CreatureLevList::writeAdditionalState (const MWWorld::ConstPtr& ptr, ESM::ObjectState& state)
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
ESM::CreatureLevListState& state2 = dynamic_cast<ESM::CreatureLevListState&> (state);
|
|
||||||
|
|
||||||
if (!ptr.getRefData().getCustomData())
|
if (!ptr.getRefData().getCustomData())
|
||||||
{
|
{
|
||||||
state.mHasCustomState = false;
|
state.mHasCustomState = false;
|
||||||
|
@ -171,7 +168,8 @@ namespace MWClass
|
||||||
}
|
}
|
||||||
|
|
||||||
const CreatureLevListCustomData& customData = ptr.getRefData().getCustomData()->asCreatureLevListCustomData();
|
const CreatureLevListCustomData& customData = ptr.getRefData().getCustomData()->asCreatureLevListCustomData();
|
||||||
state2.mSpawnActorId = customData.mSpawnActorId;
|
ESM::CreatureLevListState& levListState = state.asCreatureLevListState();
|
||||||
state2.mSpawn = customData.mSpawn;
|
levListState.mSpawnActorId = customData.mSpawnActorId;
|
||||||
|
levListState.mSpawn = customData.mSpawn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <components/esm/loaddoor.hpp>
|
#include <components/esm/loaddoor.hpp>
|
||||||
#include <components/esm/doorstate.hpp>
|
#include <components/esm/doorstate.hpp>
|
||||||
#include <components/sceneutil/positionattitudetransform.hpp>
|
#include <components/sceneutil/positionattitudetransform.hpp>
|
||||||
|
#include <components/sceneutil/vismask.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
@ -25,7 +26,6 @@
|
||||||
#include "../mwrender/objects.hpp"
|
#include "../mwrender/objects.hpp"
|
||||||
#include "../mwrender/renderinginterface.hpp"
|
#include "../mwrender/renderinginterface.hpp"
|
||||||
#include "../mwrender/animation.hpp"
|
#include "../mwrender/animation.hpp"
|
||||||
#include "../mwrender/vismask.hpp"
|
|
||||||
|
|
||||||
#include "../mwmechanics/actorutil.hpp"
|
#include "../mwmechanics/actorutil.hpp"
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ namespace MWClass
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
renderingInterface.getObjects().insertModel(ptr, model, true);
|
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)
|
if (!state.mHasCustomState)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ensureCustomData(ptr);
|
ensureCustomData(ptr);
|
||||||
DoorCustomData& customData = ptr.getRefData().getCustomData()->asDoorCustomData();
|
DoorCustomData& customData = ptr.getRefData().getCustomData()->asDoorCustomData();
|
||||||
|
const ESM::DoorState& doorState = state.asDoorState();
|
||||||
const ESM::DoorState& state2 = dynamic_cast<const ESM::DoorState&>(state);
|
customData.mDoorState = MWWorld::DoorState(doorState.mDoorState);
|
||||||
customData.mDoorState = static_cast<MWWorld::DoorState>(state2.mDoorState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Door::writeAdditionalState (const MWWorld::ConstPtr& ptr, ESM::ObjectState& state) const
|
void Door::writeAdditionalState (const MWWorld::ConstPtr& ptr, ESM::ObjectState& state) const
|
||||||
|
@ -384,10 +384,10 @@ namespace MWClass
|
||||||
state.mHasCustomState = false;
|
state.mHasCustomState = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DoorCustomData& customData = ptr.getRefData().getCustomData()->asDoorCustomData();
|
const DoorCustomData& customData = ptr.getRefData().getCustomData()->asDoorCustomData();
|
||||||
|
ESM::DoorState& doorState = state.asDoorState();
|
||||||
ESM::DoorState& state2 = dynamic_cast<ESM::DoorState&>(state);
|
doorState.mDoorState = int(customData.mDoorState);
|
||||||
state2.mDoorState = static_cast<int>(customData.mDoorState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1307,8 +1307,6 @@ namespace MWClass
|
||||||
if (!state.mHasCustomState)
|
if (!state.mHasCustomState)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::NpcState& state2 = dynamic_cast<const ESM::NpcState&> (state);
|
|
||||||
|
|
||||||
if (state.mVersion > 0)
|
if (state.mVersion > 0)
|
||||||
{
|
{
|
||||||
if (!ptr.getRefData().getCustomData())
|
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.
|
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();
|
NpcCustomData& customData = ptr.getRefData().getCustomData()->asNpcCustomData();
|
||||||
|
const ESM::NpcState& npcState = state.asNpcState();
|
||||||
customData.mInventoryStore.readState (state2.mInventory);
|
customData.mInventoryStore.readState (npcState.mInventory);
|
||||||
customData.mNpcStats.readState (state2.mNpcStats);
|
customData.mNpcStats.readState (npcState.mNpcStats);
|
||||||
static_cast<MWMechanics::CreatureStats&> (customData.mNpcStats).readState (state2.mCreatureStats);
|
customData.mNpcStats.readState (npcState.mCreatureStats);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Npc::writeAdditionalState (const MWWorld::ConstPtr& ptr, ESM::ObjectState& state)
|
void Npc::writeAdditionalState (const MWWorld::ConstPtr& ptr, ESM::ObjectState& state)
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
ESM::NpcState& state2 = dynamic_cast<ESM::NpcState&> (state);
|
|
||||||
|
|
||||||
if (!ptr.getRefData().getCustomData())
|
if (!ptr.getRefData().getCustomData())
|
||||||
{
|
{
|
||||||
state.mHasCustomState = false;
|
state.mHasCustomState = false;
|
||||||
|
@ -1340,10 +1336,10 @@ namespace MWClass
|
||||||
}
|
}
|
||||||
|
|
||||||
const NpcCustomData& customData = ptr.getRefData().getCustomData()->asNpcCustomData();
|
const NpcCustomData& customData = ptr.getRefData().getCustomData()->asNpcCustomData();
|
||||||
|
ESM::NpcState& npcState = state.asNpcState();
|
||||||
customData.mInventoryStore.writeState (state2.mInventory);
|
customData.mInventoryStore.writeState (npcState.mInventory);
|
||||||
customData.mNpcStats.writeState (state2.mNpcStats);
|
customData.mNpcStats.writeState (npcState.mNpcStats);
|
||||||
static_cast<const MWMechanics::CreatureStats&> (customData.mNpcStats).writeState (state2.mCreatureStats);
|
customData.mNpcStats.writeState (npcState.mCreatureStats);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Npc::getBaseGold(const MWWorld::ConstPtr& ptr) const
|
int Npc::getBaseGold(const MWWorld::ConstPtr& ptr) const
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <components/esm/loadstat.hpp>
|
#include <components/esm/loadstat.hpp>
|
||||||
#include <components/sceneutil/positionattitudetransform.hpp>
|
#include <components/sceneutil/positionattitudetransform.hpp>
|
||||||
|
#include <components/sceneutil/vismask.hpp>
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwphysics/physicssystem.hpp"
|
#include "../mwphysics/physicssystem.hpp"
|
||||||
|
@ -9,7 +10,6 @@
|
||||||
|
|
||||||
#include "../mwrender/objects.hpp"
|
#include "../mwrender/objects.hpp"
|
||||||
#include "../mwrender/renderinginterface.hpp"
|
#include "../mwrender/renderinginterface.hpp"
|
||||||
#include "../mwrender/vismask.hpp"
|
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
|
@ -19,7 +19,7 @@ namespace MWClass
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
renderingInterface.getObjects().insertModel(ptr, model);
|
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_Gui.h>
|
||||||
#include <MyGUI_Button.h>
|
#include <MyGUI_Button.h>
|
||||||
#include <MyGUI_EditBox.h>
|
#include <MyGUI_EditBox.h>
|
||||||
|
#include <MyGUI_ComboBox.h>
|
||||||
#include <MyGUI_ControllerManager.h>
|
#include <MyGUI_ControllerManager.h>
|
||||||
#include <MyGUI_ControllerRepeatClick.h>
|
#include <MyGUI_ControllerRepeatClick.h>
|
||||||
|
|
||||||
|
@ -17,6 +18,7 @@
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
|
#include <MyGUI_Macros.h>
|
||||||
#include <components/esm/records.hpp>
|
#include <components/esm/records.hpp>
|
||||||
|
|
||||||
#include "inventoryitemmodel.hpp"
|
#include "inventoryitemmodel.hpp"
|
||||||
|
@ -29,6 +31,7 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
AlchemyWindow::AlchemyWindow()
|
AlchemyWindow::AlchemyWindow()
|
||||||
: WindowBase("openmw_alchemy_window.layout")
|
: WindowBase("openmw_alchemy_window.layout")
|
||||||
|
, mModel(nullptr)
|
||||||
, mSortModel(nullptr)
|
, mSortModel(nullptr)
|
||||||
, mAlchemy(new MWMechanics::Alchemy())
|
, mAlchemy(new MWMechanics::Alchemy())
|
||||||
, mApparatus (4)
|
, mApparatus (4)
|
||||||
|
@ -50,6 +53,8 @@ namespace MWGui
|
||||||
getWidget(mDecreaseButton, "DecreaseButton");
|
getWidget(mDecreaseButton, "DecreaseButton");
|
||||||
getWidget(mNameEdit, "NameEdit");
|
getWidget(mNameEdit, "NameEdit");
|
||||||
getWidget(mItemView, "ItemView");
|
getWidget(mItemView, "ItemView");
|
||||||
|
getWidget(mFilterValue, "FilterValue");
|
||||||
|
getWidget(mFilterType, "FilterType");
|
||||||
|
|
||||||
mBrewCountEdit->eventValueChanged += MyGUI::newDelegate(this, &AlchemyWindow::onCountValueChanged);
|
mBrewCountEdit->eventValueChanged += MyGUI::newDelegate(this, &AlchemyWindow::onCountValueChanged);
|
||||||
mBrewCountEdit->eventEditSelectAccept += MyGUI::newDelegate(this, &AlchemyWindow::onAccept);
|
mBrewCountEdit->eventEditSelectAccept += MyGUI::newDelegate(this, &AlchemyWindow::onAccept);
|
||||||
|
@ -72,6 +77,9 @@ namespace MWGui
|
||||||
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onCancelButtonClicked);
|
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onCancelButtonClicked);
|
||||||
|
|
||||||
mNameEdit->eventEditSelectAccept += MyGUI::newDelegate(this, &AlchemyWindow::onAccept);
|
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();
|
center();
|
||||||
}
|
}
|
||||||
|
@ -136,16 +144,110 @@ namespace MWGui
|
||||||
removeIngredient(mIngredients[i]);
|
removeIngredient(mIngredients[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateFilters();
|
||||||
update();
|
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()
|
void AlchemyWindow::onOpen()
|
||||||
{
|
{
|
||||||
mAlchemy->clear();
|
mAlchemy->clear();
|
||||||
mAlchemy->setAlchemist (MWMechanics::getPlayer());
|
mAlchemy->setAlchemist (MWMechanics::getPlayer());
|
||||||
|
|
||||||
InventoryItemModel* model = new InventoryItemModel(MWMechanics::getPlayer());
|
mModel = new InventoryItemModel(MWMechanics::getPlayer());
|
||||||
mSortModel = new SortFilterItemModel(model);
|
mSortModel = new SortFilterItemModel(mModel);
|
||||||
mSortModel->setFilter(SortFilterItemModel::Filter_OnlyIngredients);
|
mSortModel->setFilter(SortFilterItemModel::Filter_OnlyIngredients);
|
||||||
mItemView->setModel (mSortModel);
|
mItemView->setModel (mSortModel);
|
||||||
mItemView->resetScrollBars();
|
mItemView->resetScrollBars();
|
||||||
|
@ -167,6 +269,7 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
|
|
||||||
update();
|
update();
|
||||||
|
initFilter();
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mNameEdit);
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mNameEdit);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,9 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <MyGUI_ControllerItem.h>
|
#include <MyGUI_ControllerItem.h>
|
||||||
|
#include <MyGUI_ComboBox.h>
|
||||||
|
|
||||||
|
#include <components/widgets/box.hpp>
|
||||||
#include <components/widgets/numericeditbox.hpp>
|
#include <components/widgets/numericeditbox.hpp>
|
||||||
|
|
||||||
#include "windowbase.hpp"
|
#include "windowbase.hpp"
|
||||||
|
@ -19,6 +21,7 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
class ItemView;
|
class ItemView;
|
||||||
class ItemWidget;
|
class ItemWidget;
|
||||||
|
class InventoryItemModel;
|
||||||
class SortFilterItemModel;
|
class SortFilterItemModel;
|
||||||
|
|
||||||
class AlchemyWindow : public WindowBase
|
class AlchemyWindow : public WindowBase
|
||||||
|
@ -36,8 +39,11 @@ namespace MWGui
|
||||||
static const float sCountChangeInterval; // in seconds
|
static const float sCountChangeInterval; // in seconds
|
||||||
|
|
||||||
std::string mSuggestedPotionName;
|
std::string mSuggestedPotionName;
|
||||||
|
enum class FilterType { ByName, ByEffect };
|
||||||
|
FilterType mCurrentFilter;
|
||||||
|
|
||||||
ItemView* mItemView;
|
ItemView* mItemView;
|
||||||
|
InventoryItemModel* mModel;
|
||||||
SortFilterItemModel* mSortModel;
|
SortFilterItemModel* mSortModel;
|
||||||
|
|
||||||
MyGUI::Button* mCreateButton;
|
MyGUI::Button* mCreateButton;
|
||||||
|
@ -47,6 +53,8 @@ namespace MWGui
|
||||||
|
|
||||||
MyGUI::Button* mIncreaseButton;
|
MyGUI::Button* mIncreaseButton;
|
||||||
MyGUI::Button* mDecreaseButton;
|
MyGUI::Button* mDecreaseButton;
|
||||||
|
Gui::AutoSizedButton* mFilterType;
|
||||||
|
MyGUI::ComboBox* mFilterValue;
|
||||||
MyGUI::EditBox* mNameEdit;
|
MyGUI::EditBox* mNameEdit;
|
||||||
Gui::NumericEditBox* mBrewCountEdit;
|
Gui::NumericEditBox* mBrewCountEdit;
|
||||||
|
|
||||||
|
@ -60,6 +68,13 @@ namespace MWGui
|
||||||
void onCountValueChanged(int value);
|
void onCountValueChanged(int value);
|
||||||
void onRepeatClick(MyGUI::Widget* widget, MyGUI::ControllerItem* controller);
|
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 addRepeatController(MyGUI::Widget* widget);
|
||||||
|
|
||||||
void onIncreaseButtonTriggered();
|
void onIncreaseButtonTriggered();
|
||||||
|
|
|
@ -9,7 +9,7 @@ namespace MWGui
|
||||||
/**
|
/**
|
||||||
* @brief A variant of MyGUI::ImageBox with aspect ratio correction using black bars
|
* @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)
|
MYGUI_RTTI_DERIVED(BackgroundImage)
|
||||||
|
|
||||||
|
@ -22,8 +22,8 @@ namespace MWGui
|
||||||
*/
|
*/
|
||||||
void setBackgroundImage (const std::string& image, bool fixedRatio=true, bool stretch=true);
|
void setBackgroundImage (const std::string& image, bool fixedRatio=true, bool stretch=true);
|
||||||
|
|
||||||
virtual void setSize (const MyGUI::IntSize &_value);
|
void setSize (const MyGUI::IntSize &_value) final;
|
||||||
virtual void setCoord (const MyGUI::IntCoord &_value);
|
void setCoord (const MyGUI::IntCoord &_value) final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MyGUI::ImageBox* mChild;
|
MyGUI::ImageBox* mChild;
|
||||||
|
|
|
@ -817,7 +817,7 @@ namespace
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
class PageDisplay : public MyGUI::ISubWidgetText
|
class PageDisplay final : public MyGUI::ISubWidgetText
|
||||||
{
|
{
|
||||||
MYGUI_RTTI_DERIVED(PageDisplay)
|
MYGUI_RTTI_DERIVED(PageDisplay)
|
||||||
protected:
|
protected:
|
||||||
|
@ -1140,7 +1140,7 @@ public:
|
||||||
i->second->createDrawItem (mNode);
|
i->second->createDrawItem (mNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setVisible (bool newVisible)
|
void setVisible (bool newVisible) final
|
||||||
{
|
{
|
||||||
if (mVisible == newVisible)
|
if (mVisible == newVisible)
|
||||||
return;
|
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;
|
mNode = node;
|
||||||
|
|
||||||
|
@ -1230,9 +1230,9 @@ public:
|
||||||
|
|
||||||
// ISubWidget should not necessarily be a drawitem
|
// ISubWidget should not necessarily be a drawitem
|
||||||
// in this case, it is not...
|
// in this case, it is not...
|
||||||
void doRender() { }
|
void doRender() final { }
|
||||||
|
|
||||||
void _updateView ()
|
void _updateView () final
|
||||||
{
|
{
|
||||||
_checkMargin();
|
_checkMargin();
|
||||||
|
|
||||||
|
@ -1241,7 +1241,7 @@ public:
|
||||||
mNode->outOfDate (i->second->mRenderItem);
|
mNode->outOfDate (i->second->mRenderItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _correctView()
|
void _correctView() final
|
||||||
{
|
{
|
||||||
_checkMargin ();
|
_checkMargin ();
|
||||||
|
|
||||||
|
@ -1251,7 +1251,7 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroyDrawItem()
|
void destroyDrawItem() final
|
||||||
{
|
{
|
||||||
for (ActiveTextFormats::iterator i = mActiveTextFormats.begin (); i != mActiveTextFormats.end (); ++i)
|
for (ActiveTextFormats::iterator i = mActiveTextFormats.begin (); i != mActiveTextFormats.end (); ++i)
|
||||||
i->second->destroyDrawItem (mNode);
|
i->second->destroyDrawItem (mNode);
|
||||||
|
@ -1261,7 +1261,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class BookPageImpl : public BookPage
|
class BookPageImpl final : public BookPage
|
||||||
{
|
{
|
||||||
MYGUI_RTTI_DERIVED(BookPage)
|
MYGUI_RTTI_DERIVED(BookPage)
|
||||||
public:
|
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);
|
mPageDisplay->showPage (book, page);
|
||||||
}
|
}
|
||||||
|
|
||||||
void adviseLinkClicked (std::function <void (InteractiveId)> linkClicked)
|
void adviseLinkClicked (std::function <void (InteractiveId)> linkClicked) final
|
||||||
{
|
{
|
||||||
mPageDisplay->mLinkClicked = linkClicked;
|
mPageDisplay->mLinkClicked = linkClicked;
|
||||||
}
|
}
|
||||||
|
|
||||||
void unadviseLinkClicked ()
|
void unadviseLinkClicked () final
|
||||||
{
|
{
|
||||||
mPageDisplay->mLinkClicked = std::function <void (InteractiveId)> ();
|
mPageDisplay->mLinkClicked = std::function <void (InteractiveId)> ();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual void initialiseOverride()
|
void initialiseOverride() final
|
||||||
{
|
{
|
||||||
Base::initialiseOverride();
|
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).
|
// 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.
|
// Child widgets may already be destroyed! So be careful.
|
||||||
mPageDisplay->onMouseLostFocus ();
|
mPageDisplay->onMouseLostFocus ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void onMouseMove(int left, int top)
|
void onMouseMove(int left, int top) final
|
||||||
{
|
{
|
||||||
mPageDisplay->onMouseMove (left, top);
|
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);
|
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);
|
mPageDisplay->onMouseButtonReleased (left, top, id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,9 +46,11 @@ CompanionWindow::CompanionWindow(DragAndDrop *dragAndDrop, MessageBoxManager* ma
|
||||||
getWidget(mCloseButton, "CloseButton");
|
getWidget(mCloseButton, "CloseButton");
|
||||||
getWidget(mProfitLabel, "ProfitLabel");
|
getWidget(mProfitLabel, "ProfitLabel");
|
||||||
getWidget(mEncumbranceBar, "EncumbranceBar");
|
getWidget(mEncumbranceBar, "EncumbranceBar");
|
||||||
|
getWidget(mFilterEdit, "FilterEdit");
|
||||||
getWidget(mItemView, "ItemView");
|
getWidget(mItemView, "ItemView");
|
||||||
mItemView->eventBackgroundClicked += MyGUI::newDelegate(this, &CompanionWindow::onBackgroundSelected);
|
mItemView->eventBackgroundClicked += MyGUI::newDelegate(this, &CompanionWindow::onBackgroundSelected);
|
||||||
mItemView->eventItemClicked += MyGUI::newDelegate(this, &CompanionWindow::onItemSelected);
|
mItemView->eventItemClicked += MyGUI::newDelegate(this, &CompanionWindow::onItemSelected);
|
||||||
|
mFilterEdit->eventEditTextChange += MyGUI::newDelegate(this, &CompanionWindow::onNameFilterChanged);
|
||||||
|
|
||||||
mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CompanionWindow::onCloseButtonClicked);
|
mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CompanionWindow::onCloseButtonClicked);
|
||||||
|
|
||||||
|
@ -92,6 +94,12 @@ void CompanionWindow::onItemSelected(int index)
|
||||||
dragItem (nullptr, count);
|
dragItem (nullptr, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CompanionWindow::onNameFilterChanged(MyGUI::EditBox* _sender)
|
||||||
|
{
|
||||||
|
mSortModel->setNameFilter(_sender->getCaption());
|
||||||
|
mItemView->update();
|
||||||
|
}
|
||||||
|
|
||||||
void CompanionWindow::dragItem(MyGUI::Widget* sender, int count)
|
void CompanionWindow::dragItem(MyGUI::Widget* sender, int count)
|
||||||
{
|
{
|
||||||
mDragAndDrop->startDrag(mSelectedItem, mSortModel, mModel, mItemView, count);
|
mDragAndDrop->startDrag(mSelectedItem, mSortModel, mModel, mItemView, count);
|
||||||
|
@ -113,6 +121,7 @@ void CompanionWindow::setPtr(const MWWorld::Ptr& npc)
|
||||||
|
|
||||||
mModel = new CompanionItemModel(npc);
|
mModel = new CompanionItemModel(npc);
|
||||||
mSortModel = new SortFilterItemModel(mModel);
|
mSortModel = new SortFilterItemModel(mModel);
|
||||||
|
mFilterEdit->setCaption(std::string());
|
||||||
mItemView->setModel(mSortModel);
|
mItemView->setModel(mSortModel);
|
||||||
mItemView->resetScrollBars();
|
mItemView->resetScrollBars();
|
||||||
|
|
||||||
|
|
|
@ -39,11 +39,13 @@ namespace MWGui
|
||||||
DragAndDrop* mDragAndDrop;
|
DragAndDrop* mDragAndDrop;
|
||||||
|
|
||||||
MyGUI::Button* mCloseButton;
|
MyGUI::Button* mCloseButton;
|
||||||
|
MyGUI::EditBox* mFilterEdit;
|
||||||
MyGUI::TextBox* mProfitLabel;
|
MyGUI::TextBox* mProfitLabel;
|
||||||
Widgets::MWDynamicStat* mEncumbranceBar;
|
Widgets::MWDynamicStat* mEncumbranceBar;
|
||||||
MessageBoxManager* mMessageBoxManager;
|
MessageBoxManager* mMessageBoxManager;
|
||||||
|
|
||||||
void onItemSelected(int index);
|
void onItemSelected(int index);
|
||||||
|
void onNameFilterChanged(MyGUI::EditBox* _sender);
|
||||||
void onBackgroundSelected();
|
void onBackgroundSelected();
|
||||||
void dragItem(MyGUI::Widget* sender, int count);
|
void dragItem(MyGUI::Widget* sender, int count);
|
||||||
|
|
||||||
|
|
|
@ -14,14 +14,14 @@ namespace MWGui
|
||||||
namespace Controllers
|
namespace Controllers
|
||||||
{
|
{
|
||||||
/// Automatically positions a widget below the mouse cursor.
|
/// Automatically positions a widget below the mouse cursor.
|
||||||
class ControllerFollowMouse :
|
class ControllerFollowMouse final :
|
||||||
public MyGUI::ControllerItem
|
public MyGUI::ControllerItem
|
||||||
{
|
{
|
||||||
MYGUI_RTTI_DERIVED( ControllerFollowMouse )
|
MYGUI_RTTI_DERIVED( ControllerFollowMouse )
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool addTime(MyGUI::Widget* _widget, float _time);
|
bool addTime(MyGUI::Widget* _widget, float _time) final;
|
||||||
void prepareItem(MyGUI::Widget* _widget);
|
void prepareItem(MyGUI::Widget* _widget) final;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace MWGui
|
||||||
/// ResourceImageSetPointer that we need.
|
/// ResourceImageSetPointer that we need.
|
||||||
/// \example MyGUI::FactoryManager::getInstance().registerFactory<ResourceImageSetPointerFix>("Resource", "ResourceImageSetPointer");
|
/// \example MyGUI::FactoryManager::getInstance().registerFactory<ResourceImageSetPointerFix>("Resource", "ResourceImageSetPointer");
|
||||||
/// MyGUI::ResourceManager::getInstance().load("core.xml");
|
/// MyGUI::ResourceManager::getInstance().load("core.xml");
|
||||||
class ResourceImageSetPointerFix :
|
class ResourceImageSetPointerFix final :
|
||||||
public MyGUI::IPointer
|
public MyGUI::IPointer
|
||||||
{
|
{
|
||||||
MYGUI_RTTI_DERIVED( ResourceImageSetPointerFix )
|
MYGUI_RTTI_DERIVED( ResourceImageSetPointerFix )
|
||||||
|
@ -20,17 +20,17 @@ namespace MWGui
|
||||||
ResourceImageSetPointerFix();
|
ResourceImageSetPointerFix();
|
||||||
virtual ~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);
|
void setImage(MyGUI::ImageBox* _image) final;
|
||||||
virtual void setPosition(MyGUI::ImageBox* _image, const MyGUI::IntPoint& _point);
|
void setPosition(MyGUI::ImageBox* _image, const MyGUI::IntPoint& _point) final;
|
||||||
|
|
||||||
//and now for the whole point of this class, allow us to get
|
//and now for the whole point of this class, allow us to get
|
||||||
//the hot spot, the image and the size of the cursor.
|
//the hot spot, the image and the size of the cursor.
|
||||||
virtual MyGUI::ResourceImageSetPtr getImageSet();
|
MyGUI::ResourceImageSetPtr getImageSet();
|
||||||
virtual MyGUI::IntPoint getHotSpot();
|
MyGUI::IntPoint getHotSpot();
|
||||||
virtual MyGUI::IntSize getSize();
|
MyGUI::IntSize getSize();
|
||||||
virtual int getRotation();
|
int getRotation();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MyGUI::IntPoint mPoint;
|
MyGUI::IntPoint mPoint;
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <MyGUI_RenderManager.h>
|
#include <MyGUI_RenderManager.h>
|
||||||
#include <MyGUI_InputManager.h>
|
#include <MyGUI_InputManager.h>
|
||||||
#include <MyGUI_Button.h>
|
#include <MyGUI_Button.h>
|
||||||
|
#include <MyGUI_EditBox.h>
|
||||||
|
|
||||||
#include <osg/Texture2D>
|
#include <osg/Texture2D>
|
||||||
|
|
||||||
|
@ -21,12 +22,10 @@
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
#include "../mwbase/mechanicsmanager.hpp"
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
#include "../mwbase/scriptmanager.hpp"
|
|
||||||
|
|
||||||
#include "../mwworld/inventorystore.hpp"
|
#include "../mwworld/inventorystore.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/actionequip.hpp"
|
#include "../mwworld/actionequip.hpp"
|
||||||
#include "../mwscript/interpretercontext.hpp"
|
|
||||||
|
|
||||||
#include "../mwmechanics/actorutil.hpp"
|
#include "../mwmechanics/actorutil.hpp"
|
||||||
#include "../mwmechanics/creaturestats.hpp"
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
|
@ -90,6 +89,7 @@ namespace MWGui
|
||||||
getWidget(mLeftPane, "LeftPane");
|
getWidget(mLeftPane, "LeftPane");
|
||||||
getWidget(mRightPane, "RightPane");
|
getWidget(mRightPane, "RightPane");
|
||||||
getWidget(mArmorRating, "ArmorRating");
|
getWidget(mArmorRating, "ArmorRating");
|
||||||
|
getWidget(mFilterEdit, "FilterEdit");
|
||||||
|
|
||||||
mAvatarImage->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onAvatarClicked);
|
mAvatarImage->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onAvatarClicked);
|
||||||
mAvatarImage->setRenderItemTexture(mPreviewTexture.get());
|
mAvatarImage->setRenderItemTexture(mPreviewTexture.get());
|
||||||
|
@ -104,6 +104,7 @@ namespace MWGui
|
||||||
mFilterApparel->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged);
|
mFilterApparel->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged);
|
||||||
mFilterMagic->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged);
|
mFilterMagic->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged);
|
||||||
mFilterMisc->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged);
|
mFilterMisc->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged);
|
||||||
|
mFilterEdit->eventEditTextChange += MyGUI::newDelegate(this, &InventoryWindow::onNameFilterChanged);
|
||||||
|
|
||||||
mFilterAll->setStateSelected(true);
|
mFilterAll->setStateSelected(true);
|
||||||
|
|
||||||
|
@ -133,6 +134,8 @@ namespace MWGui
|
||||||
else
|
else
|
||||||
mSortModel = new SortFilterItemModel(mTradeModel);
|
mSortModel = new SortFilterItemModel(mTradeModel);
|
||||||
|
|
||||||
|
mSortModel->setNameFilter(mFilterEdit->getCaption());
|
||||||
|
|
||||||
mItemView->setModel(mSortModel);
|
mItemView->setModel(mSortModel);
|
||||||
|
|
||||||
mFilterAll->setStateSelected(true);
|
mFilterAll->setStateSelected(true);
|
||||||
|
@ -388,6 +391,11 @@ namespace MWGui
|
||||||
|
|
||||||
void InventoryWindow::onOpen()
|
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())
|
if (!mPtr.isEmpty())
|
||||||
{
|
{
|
||||||
updateEncumbranceBar();
|
updateEncumbranceBar();
|
||||||
|
@ -465,6 +473,12 @@ namespace MWGui
|
||||||
width*mScaleFactor/float(mPreview->getTextureWidth()), height*mScaleFactor/float(mPreview->getTextureHeight())));
|
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)
|
void InventoryWindow::onFilterChanged(MyGUI::Widget* _sender)
|
||||||
{
|
{
|
||||||
if (_sender == mFilterAll)
|
if (_sender == mFilterAll)
|
||||||
|
@ -477,7 +491,6 @@ namespace MWGui
|
||||||
mSortModel->setCategory(SortFilterItemModel::Category_Magic);
|
mSortModel->setCategory(SortFilterItemModel::Category_Magic);
|
||||||
else if (_sender == mFilterMisc)
|
else if (_sender == mFilterMisc)
|
||||||
mSortModel->setCategory(SortFilterItemModel::Category_Misc);
|
mSortModel->setCategory(SortFilterItemModel::Category_Misc);
|
||||||
|
|
||||||
mFilterAll->setStateSelected(false);
|
mFilterAll->setStateSelected(false);
|
||||||
mFilterWeapon->setStateSelected(false);
|
mFilterWeapon->setStateSelected(false);
|
||||||
mFilterApparel->setStateSelected(false);
|
mFilterApparel->setStateSelected(false);
|
||||||
|
@ -507,6 +520,16 @@ namespace MWGui
|
||||||
void InventoryWindow::useItem(const MWWorld::Ptr &ptr, bool force)
|
void InventoryWindow::useItem(const MWWorld::Ptr &ptr, bool force)
|
||||||
{
|
{
|
||||||
const std::string& script = ptr.getClass().getScript(ptr);
|
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();
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||||
|
|
||||||
|
@ -526,10 +549,6 @@ namespace MWGui
|
||||||
|
|
||||||
if (canEquip.first == 0)
|
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();
|
updateItemView();
|
||||||
return;
|
return;
|
||||||
|
@ -537,32 +556,21 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the item has a script, set its OnPcEquip to 1
|
// If the item has a script, set OnPCEquip or PCSkipEquip to 1
|
||||||
if (!script.empty()
|
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())
|
|
||||||
{
|
{
|
||||||
MWScript::InterpreterContext interpreterContext (&ptr.getRefData().getLocals(), ptr);
|
// Ingredients, books and repair hammers must not have OnPCEquip set to 1 here
|
||||||
MWBase::Environment::get().getScriptManager()->run (script, interpreterContext);
|
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);
|
std::shared_ptr<MWWorld::Action> action = ptr.getClass().use(ptr, force);
|
||||||
action->execute(player);
|
action->execute(player);
|
||||||
}
|
|
||||||
else
|
|
||||||
mSkippedToEquip = ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isVisible())
|
if (isVisible())
|
||||||
{
|
{
|
||||||
|
|
|
@ -93,7 +93,7 @@ namespace MWGui
|
||||||
MyGUI::Button* mFilterMagic;
|
MyGUI::Button* mFilterMagic;
|
||||||
MyGUI::Button* mFilterMisc;
|
MyGUI::Button* mFilterMisc;
|
||||||
|
|
||||||
MWWorld::Ptr mSkippedToEquip;
|
MyGUI::EditBox* mFilterEdit;
|
||||||
|
|
||||||
GuiMode mGuiMode;
|
GuiMode mGuiMode;
|
||||||
|
|
||||||
|
@ -121,6 +121,7 @@ namespace MWGui
|
||||||
|
|
||||||
void onWindowResize(MyGUI::Window* _sender);
|
void onWindowResize(MyGUI::Window* _sender);
|
||||||
void onFilterChanged(MyGUI::Widget* _sender);
|
void onFilterChanged(MyGUI::Widget* _sender);
|
||||||
|
void onNameFilterChanged(MyGUI::EditBox* _sender);
|
||||||
void onAvatarClicked(MyGUI::Widget* _sender);
|
void onAvatarClicked(MyGUI::Widget* _sender);
|
||||||
void onPinToggled();
|
void onPinToggled();
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace MWGui
|
||||||
class ItemModel;
|
class ItemModel;
|
||||||
class ItemWidget;
|
class ItemWidget;
|
||||||
|
|
||||||
class ItemChargeView : public MyGUI::Widget
|
class ItemChargeView final : public MyGUI::Widget
|
||||||
{
|
{
|
||||||
MYGUI_RTTI_DERIVED(ItemChargeView)
|
MYGUI_RTTI_DERIVED(ItemChargeView)
|
||||||
public:
|
public:
|
||||||
|
@ -36,7 +36,7 @@ namespace MWGui
|
||||||
/// Register needed components with MyGUI's factory manager
|
/// Register needed components with MyGUI's factory manager
|
||||||
static void registerComponents();
|
static void registerComponents();
|
||||||
|
|
||||||
virtual void initialiseOverride();
|
void initialiseOverride() final;
|
||||||
|
|
||||||
/// Takes ownership of \a model
|
/// Takes ownership of \a model
|
||||||
void setModel(ItemModel* model);
|
void setModel(ItemModel* model);
|
||||||
|
@ -47,8 +47,8 @@ namespace MWGui
|
||||||
void layoutWidgets();
|
void layoutWidgets();
|
||||||
void resetScrollbars();
|
void resetScrollbars();
|
||||||
|
|
||||||
virtual void setSize(const MyGUI::IntSize& value);
|
void setSize(const MyGUI::IntSize& value) final;
|
||||||
virtual void setCoord(const MyGUI::IntCoord& value);
|
void setCoord(const MyGUI::IntCoord& value) final;
|
||||||
|
|
||||||
MyGUI::delegates::CMultiDelegate2<MyGUI::Widget*, const MWWorld::Ptr&> eventItemClicked;
|
MyGUI::delegates::CMultiDelegate2<MyGUI::Widget*, const MWWorld::Ptr&> eventItemClicked;
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
|
|
||||||
class ItemView : public MyGUI::Widget
|
class ItemView final : public MyGUI::Widget
|
||||||
{
|
{
|
||||||
MYGUI_RTTI_DERIVED(ItemView)
|
MYGUI_RTTI_DERIVED(ItemView)
|
||||||
public:
|
public:
|
||||||
|
@ -33,12 +33,12 @@ namespace MWGui
|
||||||
void resetScrollBars();
|
void resetScrollBars();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void initialiseOverride();
|
void initialiseOverride() final;
|
||||||
|
|
||||||
void layoutWidgets();
|
void layoutWidgets();
|
||||||
|
|
||||||
virtual void setSize(const MyGUI::IntSize& _value);
|
void setSize(const MyGUI::IntSize& _value) final;
|
||||||
virtual void setCoord(const MyGUI::IntCoord& _value);
|
void setCoord(const MyGUI::IntCoord& _value) final;
|
||||||
|
|
||||||
void onSelectedItem (MyGUI::Widget* sender);
|
void onSelectedItem (MyGUI::Widget* sender);
|
||||||
void onSelectedBackground (MyGUI::Widget* sender);
|
void onSelectedBackground (MyGUI::Widget* sender);
|
||||||
|
|
|
@ -41,7 +41,7 @@ namespace MWGui
|
||||||
void setFrame (const std::string& frame, const MyGUI::IntCoord& coord);
|
void setFrame (const std::string& frame, const MyGUI::IntCoord& coord);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void initialiseOverride();
|
void initialiseOverride() final;
|
||||||
|
|
||||||
MyGUI::ImageBox* mItem;
|
MyGUI::ImageBox* mItem;
|
||||||
MyGUI::ImageBox* mItemShadow;
|
MyGUI::ImageBox* mItemShadow;
|
||||||
|
|
|
@ -16,9 +16,6 @@ namespace MWGui
|
||||||
|
|
||||||
bool shouldAcceptKeyFocus(MyGUI::Widget* w)
|
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();
|
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/myguiplatform/myguitexture.hpp>
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
#include <components/vfs/manager.hpp>
|
#include <components/vfs/manager.hpp>
|
||||||
|
#include <components/sceneutil/vismask.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/statemanager.hpp"
|
#include "../mwbase/statemanager.hpp"
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
#include "../mwbase/inputmanager.hpp"
|
#include "../mwbase/inputmanager.hpp"
|
||||||
|
|
||||||
#include "../mwrender/vismask.hpp"
|
|
||||||
|
|
||||||
#include "backgroundimage.hpp"
|
#include "backgroundimage.hpp"
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
|
@ -335,8 +334,8 @@ namespace MWGui
|
||||||
// Turn off rendering except the GUI
|
// Turn off rendering except the GUI
|
||||||
int oldUpdateMask = mViewer->getUpdateVisitor()->getTraversalMask();
|
int oldUpdateMask = mViewer->getUpdateVisitor()->getTraversalMask();
|
||||||
int oldCullMask = mViewer->getCamera()->getCullMask();
|
int oldCullMask = mViewer->getCamera()->getCullMask();
|
||||||
mViewer->getUpdateVisitor()->setTraversalMask(MWRender::Mask_GUI|MWRender::Mask_PreCompile);
|
mViewer->getUpdateVisitor()->setTraversalMask(SceneUtil::Mask_GUI|SceneUtil::Mask_PreCompile);
|
||||||
mViewer->getCamera()->setCullMask(MWRender::Mask_GUI|MWRender::Mask_PreCompile);
|
mViewer->getCamera()->setCullMask(SceneUtil::Mask_GUI|SceneUtil::Mask_PreCompile);
|
||||||
|
|
||||||
MWBase::Environment::get().getInputManager()->update(0, true, true);
|
MWBase::Environment::get().getInputManager()->update(0, true, true);
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ namespace
|
||||||
|
|
||||||
|
|
||||||
/// @brief A widget that changes its color when hovered.
|
/// @brief A widget that changes its color when hovered.
|
||||||
class MarkerWidget: public MyGUI::Widget
|
class MarkerWidget final : public MyGUI::Widget
|
||||||
{
|
{
|
||||||
MYGUI_RTTI_DERIVED(MarkerWidget)
|
MYGUI_RTTI_DERIVED(MarkerWidget)
|
||||||
|
|
||||||
|
@ -74,12 +74,12 @@ namespace
|
||||||
MyGUI::Colour mNormalColour;
|
MyGUI::Colour mNormalColour;
|
||||||
MyGUI::Colour mHoverColour;
|
MyGUI::Colour mHoverColour;
|
||||||
|
|
||||||
void onMouseLostFocus(MyGUI::Widget* _new)
|
void onMouseLostFocus(MyGUI::Widget* _new) final
|
||||||
{
|
{
|
||||||
setColour(mNormalColour);
|
setColour(mNormalColour);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onMouseSetFocus(MyGUI::Widget* _old)
|
void onMouseSetFocus(MyGUI::Widget* _old) final
|
||||||
{
|
{
|
||||||
setColour(mHoverColour);
|
setColour(mHoverColour);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
class AutoSizedResourceSkin : public MyGUI::ResourceSkin
|
class AutoSizedResourceSkin final : public MyGUI::ResourceSkin
|
||||||
{
|
{
|
||||||
MYGUI_RTTI_DERIVED( AutoSizedResourceSkin )
|
MYGUI_RTTI_DERIVED( AutoSizedResourceSkin )
|
||||||
|
|
||||||
public:
|
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/nullaction.hpp"
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
|
#include "../mwmechanics/alchemy.hpp"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
bool compareType(const std::string& type1, const std::string& type2)
|
bool compareType(const std::string& type1, const std::string& type2)
|
||||||
|
@ -151,6 +153,8 @@ namespace MWGui
|
||||||
: mCategory(Category_All)
|
: mCategory(Category_All)
|
||||||
, mFilter(0)
|
, mFilter(0)
|
||||||
, mSortByType(true)
|
, mSortByType(true)
|
||||||
|
, mNameFilter("")
|
||||||
|
, mEffectFilter("")
|
||||||
{
|
{
|
||||||
mSourceModel = sourceModel;
|
mSourceModel = sourceModel;
|
||||||
}
|
}
|
||||||
|
@ -199,8 +203,39 @@ namespace MWGui
|
||||||
if (!(category & mCategory))
|
if (!(category & mCategory))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ((mFilter & Filter_OnlyIngredients) && base.getTypeName() != typeid(ESM::Ingredient).name())
|
if (mFilter & Filter_OnlyIngredients)
|
||||||
|
{
|
||||||
|
if (base.getTypeName() != typeid(ESM::Ingredient).name())
|
||||||
return false;
|
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))
|
if ((mFilter & Filter_OnlyEnchanted) && !(item.mFlags & ItemStack::Flag_Enchanted))
|
||||||
return false;
|
return false;
|
||||||
if ((mFilter & Filter_OnlyChargedSoulstones) && (base.getTypeName() != typeid(ESM::Miscellaneous).name()
|
if ((mFilter & Filter_OnlyChargedSoulstones) && (base.getTypeName() != typeid(ESM::Miscellaneous).name()
|
||||||
|
@ -250,6 +285,10 @@ namespace MWGui
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,6 +316,16 @@ namespace MWGui
|
||||||
mFilter = filter;
|
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()
|
void SortFilterItemModel::update()
|
||||||
{
|
{
|
||||||
mSourceModel->update();
|
mSourceModel->update();
|
||||||
|
|
|
@ -25,6 +25,8 @@ namespace MWGui
|
||||||
|
|
||||||
void setCategory (int category);
|
void setCategory (int category);
|
||||||
void setFilter (int filter);
|
void setFilter (int filter);
|
||||||
|
void setNameFilter (const std::string& filter);
|
||||||
|
void setEffectFilter (const std::string& filter);
|
||||||
|
|
||||||
/// Use ItemStack::Type for sorting?
|
/// Use ItemStack::Type for sorting?
|
||||||
void setSortByType(bool sort) { mSortByType = sort; }
|
void setSortByType(bool sort) { mSortByType = sort; }
|
||||||
|
@ -57,6 +59,9 @@ namespace MWGui
|
||||||
int mCategory;
|
int mCategory;
|
||||||
int mFilter;
|
int mFilter;
|
||||||
bool mSortByType;
|
bool mSortByType;
|
||||||
|
|
||||||
|
std::string mNameFilter; // filter by item name
|
||||||
|
std::string mEffectFilter; // filter by magic effect
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace MWGui
|
||||||
class SpellModel;
|
class SpellModel;
|
||||||
|
|
||||||
///@brief Displays a SpellModel in a list widget
|
///@brief Displays a SpellModel in a list widget
|
||||||
class SpellView : public MyGUI::Widget
|
class SpellView final : public MyGUI::Widget
|
||||||
{
|
{
|
||||||
MYGUI_RTTI_DERIVED(SpellView)
|
MYGUI_RTTI_DERIVED(SpellView)
|
||||||
public:
|
public:
|
||||||
|
@ -47,10 +47,10 @@ namespace MWGui
|
||||||
/// Fired when a spell was clicked
|
/// Fired when a spell was clicked
|
||||||
EventHandle_ModelIndex eventSpellClicked;
|
EventHandle_ModelIndex eventSpellClicked;
|
||||||
|
|
||||||
virtual void initialiseOverride();
|
void initialiseOverride() final;
|
||||||
|
|
||||||
virtual void setSize(const MyGUI::IntSize& _value);
|
void setSize(const MyGUI::IntSize& _value) final;
|
||||||
virtual void setCoord(const MyGUI::IntCoord& _value);
|
void setCoord(const MyGUI::IntCoord& _value) final;
|
||||||
|
|
||||||
void resetScrollbars();
|
void resetScrollbars();
|
||||||
|
|
||||||
|
|
|
@ -45,8 +45,6 @@ namespace MWGui
|
||||||
getWidget(mEffectBox, "EffectsBox");
|
getWidget(mEffectBox, "EffectsBox");
|
||||||
getWidget(mFilterEdit, "FilterEdit");
|
getWidget(mFilterEdit, "FilterEdit");
|
||||||
|
|
||||||
mFilterEdit->setUserString("IgnoreTabKey", "y");
|
|
||||||
|
|
||||||
mSpellView->eventSpellClicked += MyGUI::newDelegate(this, &SpellWindow::onModelIndexSelected);
|
mSpellView->eventSpellClicked += MyGUI::newDelegate(this, &SpellWindow::onModelIndexSelected);
|
||||||
mFilterEdit->eventEditTextChange += MyGUI::newDelegate(this, &SpellWindow::onFilterChanged);
|
mFilterEdit->eventEditTextChange += MyGUI::newDelegate(this, &SpellWindow::onFilterChanged);
|
||||||
deleteButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellWindow::onDeleteClicked);
|
deleteButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellWindow::onDeleteClicked);
|
||||||
|
|
|
@ -69,6 +69,7 @@ namespace MWGui
|
||||||
getWidget(mTotalBalance, "TotalBalance");
|
getWidget(mTotalBalance, "TotalBalance");
|
||||||
getWidget(mTotalBalanceLabel, "TotalBalanceLabel");
|
getWidget(mTotalBalanceLabel, "TotalBalanceLabel");
|
||||||
getWidget(mBottomPane, "BottomPane");
|
getWidget(mBottomPane, "BottomPane");
|
||||||
|
getWidget(mFilterEdit, "FilterEdit");
|
||||||
|
|
||||||
getWidget(mItemView, "ItemView");
|
getWidget(mItemView, "ItemView");
|
||||||
mItemView->eventItemClicked += MyGUI::newDelegate(this, &TradeWindow::onItemSelected);
|
mItemView->eventItemClicked += MyGUI::newDelegate(this, &TradeWindow::onItemSelected);
|
||||||
|
@ -80,6 +81,7 @@ namespace MWGui
|
||||||
mFilterApparel->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onFilterChanged);
|
mFilterApparel->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onFilterChanged);
|
||||||
mFilterMagic->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onFilterChanged);
|
mFilterMagic->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onFilterChanged);
|
||||||
mFilterMisc->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);
|
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onCancelButtonClicked);
|
||||||
mOfferButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onOfferButtonClicked);
|
mOfferButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onOfferButtonClicked);
|
||||||
|
@ -135,8 +137,7 @@ namespace MWGui
|
||||||
setTitle(actor.getClass().getName(actor));
|
setTitle(actor.getClass().getName(actor));
|
||||||
|
|
||||||
onFilterChanged(mFilterAll);
|
onFilterChanged(mFilterAll);
|
||||||
|
mFilterEdit->setCaption("");
|
||||||
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mTotalBalance);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TradeWindow::onFrame(float dt)
|
void TradeWindow::onFrame(float dt)
|
||||||
|
@ -144,6 +145,12 @@ namespace MWGui
|
||||||
checkReferenceAvailable();
|
checkReferenceAvailable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TradeWindow::onNameFilterChanged(MyGUI::EditBox* _sender)
|
||||||
|
{
|
||||||
|
mSortModel->setNameFilter(_sender->getCaption());
|
||||||
|
mItemView->update();
|
||||||
|
}
|
||||||
|
|
||||||
void TradeWindow::onFilterChanged(MyGUI::Widget* _sender)
|
void TradeWindow::onFilterChanged(MyGUI::Widget* _sender)
|
||||||
{
|
{
|
||||||
if (_sender == mFilterAll)
|
if (_sender == mFilterAll)
|
||||||
|
|
|
@ -59,6 +59,8 @@ namespace MWGui
|
||||||
MyGUI::Button* mFilterMagic;
|
MyGUI::Button* mFilterMagic;
|
||||||
MyGUI::Button* mFilterMisc;
|
MyGUI::Button* mFilterMisc;
|
||||||
|
|
||||||
|
MyGUI::EditBox* mFilterEdit;
|
||||||
|
|
||||||
MyGUI::Button* mIncreaseButton;
|
MyGUI::Button* mIncreaseButton;
|
||||||
MyGUI::Button* mDecreaseButton;
|
MyGUI::Button* mDecreaseButton;
|
||||||
MyGUI::TextBox* mTotalBalanceLabel;
|
MyGUI::TextBox* mTotalBalanceLabel;
|
||||||
|
@ -86,6 +88,7 @@ namespace MWGui
|
||||||
void sellItem (MyGUI::Widget* sender, int count);
|
void sellItem (MyGUI::Widget* sender, int count);
|
||||||
|
|
||||||
void onFilterChanged(MyGUI::Widget* _sender);
|
void onFilterChanged(MyGUI::Widget* _sender);
|
||||||
|
void onNameFilterChanged(MyGUI::EditBox* _sender);
|
||||||
void onOfferButtonClicked(MyGUI::Widget* _sender);
|
void onOfferButtonClicked(MyGUI::Widget* _sender);
|
||||||
void onAccept(MyGUI::EditBox* sender);
|
void onAccept(MyGUI::EditBox* sender);
|
||||||
void onCancelButtonClicked(MyGUI::Widget* _sender);
|
void onCancelButtonClicked(MyGUI::Widget* _sender);
|
||||||
|
|
|
@ -227,9 +227,9 @@ namespace MWGui
|
||||||
|
|
||||||
void WaitDialog::onKeyButtonPressed(MyGUI::Widget *sender, MyGUI::KeyCode key, MyGUI::Char character)
|
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));
|
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));
|
mHourSlider->setScrollPosition(std::max(static_cast<int>(mHourSlider->getScrollPosition())-1, 0));
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -90,7 +90,7 @@ namespace MWGui
|
||||||
|
|
||||||
typedef std::vector<SpellEffectParams> SpellEffectList;
|
typedef std::vector<SpellEffectParams> SpellEffectList;
|
||||||
|
|
||||||
class MWSkill : public MyGUI::Widget
|
class MWSkill final : public MyGUI::Widget
|
||||||
{
|
{
|
||||||
MYGUI_RTTI_DERIVED( MWSkill )
|
MYGUI_RTTI_DERIVED( MWSkill )
|
||||||
public:
|
public:
|
||||||
|
@ -116,7 +116,7 @@ namespace MWGui
|
||||||
protected:
|
protected:
|
||||||
virtual ~MWSkill();
|
virtual ~MWSkill();
|
||||||
|
|
||||||
virtual void initialiseOverride();
|
void initialiseOverride() final;
|
||||||
|
|
||||||
void onClicked(MyGUI::Widget* _sender);
|
void onClicked(MyGUI::Widget* _sender);
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ namespace MWGui
|
||||||
};
|
};
|
||||||
typedef MWSkill* MWSkillPtr;
|
typedef MWSkill* MWSkillPtr;
|
||||||
|
|
||||||
class MWAttribute : public MyGUI::Widget
|
class MWAttribute final : public MyGUI::Widget
|
||||||
{
|
{
|
||||||
MYGUI_RTTI_DERIVED( MWAttribute )
|
MYGUI_RTTI_DERIVED( MWAttribute )
|
||||||
public:
|
public:
|
||||||
|
@ -156,7 +156,7 @@ namespace MWGui
|
||||||
protected:
|
protected:
|
||||||
virtual ~MWAttribute();
|
virtual ~MWAttribute();
|
||||||
|
|
||||||
virtual void initialiseOverride();
|
void initialiseOverride() final;
|
||||||
|
|
||||||
void onClicked(MyGUI::Widget* _sender);
|
void onClicked(MyGUI::Widget* _sender);
|
||||||
|
|
||||||
|
@ -175,7 +175,7 @@ namespace MWGui
|
||||||
* @todo remove this class and use MWEffectList instead
|
* @todo remove this class and use MWEffectList instead
|
||||||
*/
|
*/
|
||||||
class MWSpellEffect;
|
class MWSpellEffect;
|
||||||
class MWSpell : public MyGUI::Widget
|
class MWSpell final : public MyGUI::Widget
|
||||||
{
|
{
|
||||||
MYGUI_RTTI_DERIVED( MWSpell )
|
MYGUI_RTTI_DERIVED( MWSpell )
|
||||||
public:
|
public:
|
||||||
|
@ -199,7 +199,7 @@ namespace MWGui
|
||||||
protected:
|
protected:
|
||||||
virtual ~MWSpell();
|
virtual ~MWSpell();
|
||||||
|
|
||||||
virtual void initialiseOverride();
|
void initialiseOverride() final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateWidgets();
|
void updateWidgets();
|
||||||
|
@ -209,7 +209,7 @@ namespace MWGui
|
||||||
};
|
};
|
||||||
typedef MWSpell* MWSpellPtr;
|
typedef MWSpell* MWSpellPtr;
|
||||||
|
|
||||||
class MWEffectList : public MyGUI::Widget
|
class MWEffectList final : public MyGUI::Widget
|
||||||
{
|
{
|
||||||
MYGUI_RTTI_DERIVED( MWEffectList )
|
MYGUI_RTTI_DERIVED( MWEffectList )
|
||||||
public:
|
public:
|
||||||
|
@ -241,7 +241,7 @@ namespace MWGui
|
||||||
protected:
|
protected:
|
||||||
virtual ~MWEffectList();
|
virtual ~MWEffectList();
|
||||||
|
|
||||||
virtual void initialiseOverride();
|
void initialiseOverride() final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateWidgets();
|
void updateWidgets();
|
||||||
|
@ -250,7 +250,7 @@ namespace MWGui
|
||||||
};
|
};
|
||||||
typedef MWEffectList* MWEffectListPtr;
|
typedef MWEffectList* MWEffectListPtr;
|
||||||
|
|
||||||
class MWSpellEffect : public MyGUI::Widget
|
class MWSpellEffect final : public MyGUI::Widget
|
||||||
{
|
{
|
||||||
MYGUI_RTTI_DERIVED( MWSpellEffect )
|
MYGUI_RTTI_DERIVED( MWSpellEffect )
|
||||||
public:
|
public:
|
||||||
|
@ -265,7 +265,7 @@ namespace MWGui
|
||||||
protected:
|
protected:
|
||||||
virtual ~MWSpellEffect();
|
virtual ~MWSpellEffect();
|
||||||
|
|
||||||
virtual void initialiseOverride();
|
void initialiseOverride() final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const int sIconOffset = 24;
|
static const int sIconOffset = 24;
|
||||||
|
@ -279,7 +279,7 @@ namespace MWGui
|
||||||
};
|
};
|
||||||
typedef MWSpellEffect* MWSpellEffectPtr;
|
typedef MWSpellEffect* MWSpellEffectPtr;
|
||||||
|
|
||||||
class MWDynamicStat : public MyGUI::Widget
|
class MWDynamicStat final : public MyGUI::Widget
|
||||||
{
|
{
|
||||||
MYGUI_RTTI_DERIVED( MWDynamicStat )
|
MYGUI_RTTI_DERIVED( MWDynamicStat )
|
||||||
public:
|
public:
|
||||||
|
@ -294,7 +294,7 @@ namespace MWGui
|
||||||
protected:
|
protected:
|
||||||
virtual ~MWDynamicStat();
|
virtual ~MWDynamicStat();
|
||||||
|
|
||||||
virtual void initialiseOverride();
|
void initialiseOverride() final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include <components/resource/resourcesystem.hpp>
|
#include <components/resource/resourcesystem.hpp>
|
||||||
#include <components/resource/imagemanager.hpp>
|
#include <components/resource/imagemanager.hpp>
|
||||||
|
|
||||||
|
#include <components/sceneutil/vismask.hpp>
|
||||||
#include <components/sceneutil/workqueue.hpp>
|
#include <components/sceneutil/workqueue.hpp>
|
||||||
|
|
||||||
#include <components/translation/translation.hpp>
|
#include <components/translation/translation.hpp>
|
||||||
|
@ -50,8 +51,6 @@
|
||||||
#include "../mwbase/soundmanager.hpp"
|
#include "../mwbase/soundmanager.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
#include "../mwrender/vismask.hpp"
|
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/player.hpp"
|
#include "../mwworld/player.hpp"
|
||||||
#include "../mwworld/cellstore.hpp"
|
#include "../mwworld/cellstore.hpp"
|
||||||
|
@ -1905,8 +1904,8 @@ namespace MWGui
|
||||||
// Turn off all rendering except for the GUI
|
// Turn off all rendering except for the GUI
|
||||||
int oldUpdateMask = mViewer->getUpdateVisitor()->getTraversalMask();
|
int oldUpdateMask = mViewer->getUpdateVisitor()->getTraversalMask();
|
||||||
int oldCullMask = mViewer->getCamera()->getCullMask();
|
int oldCullMask = mViewer->getCamera()->getCullMask();
|
||||||
mViewer->getUpdateVisitor()->setTraversalMask(MWRender::Mask_GUI);
|
mViewer->getUpdateVisitor()->setTraversalMask(SceneUtil::Mask_GUI);
|
||||||
mViewer->getCamera()->setCullMask(MWRender::Mask_GUI);
|
mViewer->getCamera()->setCullMask(SceneUtil::Mask_GUI);
|
||||||
|
|
||||||
MyGUI::IntSize screenSize = MyGUI::RenderManager::getInstance().getViewSize();
|
MyGUI::IntSize screenSize = MyGUI::RenderManager::getInstance().getViewSize();
|
||||||
sizeVideo(screenSize.width, screenSize.height);
|
sizeVideo(screenSize.width, screenSize.height);
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <components/esm/esmwriter.hpp>
|
#include <components/esm/esmwriter.hpp>
|
||||||
|
|
||||||
#include <components/sceneutil/positionattitudetransform.hpp>
|
#include <components/sceneutil/positionattitudetransform.hpp>
|
||||||
|
#include <components/sceneutil/vismask.hpp>
|
||||||
#include <components/debug/debuglog.hpp>
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/misc/rng.hpp>
|
#include <components/misc/rng.hpp>
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
@ -24,8 +25,6 @@
|
||||||
|
|
||||||
#include "../mwmechanics/aibreathe.hpp"
|
#include "../mwmechanics/aibreathe.hpp"
|
||||||
|
|
||||||
#include "../mwrender/vismask.hpp"
|
|
||||||
|
|
||||||
#include "spellcasting.hpp"
|
#include "spellcasting.hpp"
|
||||||
#include "steering.hpp"
|
#include "steering.hpp"
|
||||||
#include "npcstats.hpp"
|
#include "npcstats.hpp"
|
||||||
|
@ -452,22 +451,12 @@ namespace MWMechanics
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CreatureStats &stats = actor.getClass().getCreatureStats(actor);
|
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();
|
const MWMechanics::AiSequence& seq = stats.getAiSequence();
|
||||||
int packageId = seq.getTypeId();
|
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.setTurningToPlayer(false);
|
||||||
stats.setGreetingTimer(0);
|
stats.setGreetingTimer(0);
|
||||||
|
@ -475,6 +464,11 @@ namespace MWMechanics
|
||||||
return;
|
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())
|
if (stats.isTurningToPlayer())
|
||||||
{
|
{
|
||||||
// Reduce the turning animation glitch by using a *HUGE* value of
|
// Reduce the turning animation glitch by using a *HUGE* value of
|
||||||
|
@ -492,11 +486,10 @@ namespace MWMechanics
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Play a random voice greeting if the player gets too close
|
// 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()
|
static int iGreetDistanceMultiplier = MWBase::Environment::get().getWorld()->getStore()
|
||||||
.get<ESM::GameSetting>().find("iGreetDistanceMultiplier")->mValue.getInteger();
|
.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();
|
int greetingTimer = stats.getGreetingTimer();
|
||||||
GreetingState greetingState = stats.getGreetingState();
|
GreetingState greetingState = stats.getGreetingState();
|
||||||
|
@ -1241,6 +1234,11 @@ namespace MWMechanics
|
||||||
if (heldIter != inventoryStore.end() && heldIter->getTypeName() != typeid(ESM::Light).name())
|
if (heldIter != inventoryStore.end() && heldIter->getTypeName() != typeid(ESM::Light).name())
|
||||||
inventoryStore.unequipItem(*heldIter, ptr);
|
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);
|
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();
|
const float dist = (player.getRefData().getPosition().asVec3() - ptr.getRefData().getPosition().asVec3()).length();
|
||||||
if (dist > mActorsProcessingRange)
|
if (dist > mActorsProcessingRange)
|
||||||
{
|
{
|
||||||
ptr.getRefData().getBaseNode()->setNodeMask(0);
|
ptr.getRefData().getBaseNode()->setNodeMask(SceneUtil::Mask_Disabled);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
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)
|
// Fade away actors on large distance (>90% of actor's processing distance)
|
||||||
float visibilityRatio = 1.0;
|
float visibilityRatio = 1.0;
|
||||||
|
@ -1748,12 +1746,12 @@ namespace MWMechanics
|
||||||
|
|
||||||
if (!inRange)
|
if (!inRange)
|
||||||
{
|
{
|
||||||
iter->first.getRefData().getBaseNode()->setNodeMask(0);
|
iter->first.getRefData().getBaseNode()->setNodeMask(SceneUtil::Mask_Disabled);
|
||||||
world->setActorCollisionMode(iter->first, false, false);
|
world->setActorCollisionMode(iter->first, false, false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (!isPlayer)
|
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();
|
const bool isDead = iter->first.getClass().getCreatureStats(iter->first).isDead();
|
||||||
if (!isDead && iter->first.getClass().getCreatureStats(iter->first).isParalyzed())
|
if (!isDead && iter->first.getClass().getCreatureStats(iter->first).isParalyzed())
|
||||||
|
@ -1852,6 +1850,8 @@ namespace MWMechanics
|
||||||
stats.getActiveSpells().visitEffectSources(soulTrap);
|
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);
|
calculateCreatureStatModifiers(iter->first, 0);
|
||||||
|
|
||||||
if (cls.isEssential(iter->first))
|
if (cls.isEssential(iter->first))
|
||||||
|
@ -1869,7 +1869,10 @@ namespace MWMechanics
|
||||||
// Make sure spell effects are removed
|
// Make sure spell effects are removed
|
||||||
purgeSpellEffects(stats.getActorId());
|
purgeSpellEffects(stats.getActorId());
|
||||||
|
|
||||||
|
// Reset dynamic stats, attributes and skills
|
||||||
calculateCreatureStatModifiers(iter->first, 0);
|
calculateCreatureStatModifiers(iter->first, 0);
|
||||||
|
if (iter->first.getClass().isNpc())
|
||||||
|
calculateNpcStatModifiers(iter->first, 0);
|
||||||
|
|
||||||
if( iter->first == getPlayer())
|
if( iter->first == getPlayer())
|
||||||
{
|
{
|
||||||
|
|
|
@ -44,7 +44,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
void fastForward(const MWWorld::Ptr& actor, AiState& state);
|
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:
|
private:
|
||||||
std::string mCellId;
|
std::string mCellId;
|
||||||
|
|
|
@ -76,7 +76,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
void fastForward(const MWWorld::Ptr& actor, AiState& state);
|
void fastForward(const MWWorld::Ptr& actor, AiState& state);
|
||||||
|
|
||||||
virtual osg::Vec3f getDestination()
|
virtual osg::Vec3f getDestination() const
|
||||||
{
|
{
|
||||||
MWWorld::Ptr target = getTarget();
|
MWWorld::Ptr target = getTarget();
|
||||||
if (target.isEmpty())
|
if (target.isEmpty())
|
||||||
|
|
|
@ -102,7 +102,7 @@ namespace MWMechanics
|
||||||
/// Return true if this package should repeat. Currently only used for Wander packages.
|
/// Return true if this package should repeat. Currently only used for Wander packages.
|
||||||
virtual bool getRepeat() const;
|
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.
|
// Return true if any loaded actor with this AI package must be active.
|
||||||
virtual bool alwaysActive() const { return false; }
|
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());
|
for (std::list<AiPackage *>::const_iterator iter (sequence.mPackages.begin());
|
||||||
iter!=sequence.mPackages.end(); ++iter)
|
iter!=sequence.mPackages.end(); ++iter)
|
||||||
mPackages.push_back ((*iter)->clone());
|
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) {}
|
AiSequence::AiSequence() : mDone (false), mRepeat(false), mLastAiPackage(-1) {}
|
||||||
|
|
|
@ -39,6 +39,14 @@ namespace MWMechanics
|
||||||
return *result;
|
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 >
|
template< class Derived >
|
||||||
void store( const Derived& payload )
|
void store( const Derived& payload )
|
||||||
{
|
{
|
||||||
|
|
|
@ -54,8 +54,9 @@ namespace MWMechanics
|
||||||
stats.setMovementFlag(CreatureStats::Flag_Run, false);
|
stats.setMovementFlag(CreatureStats::Flag_Run, false);
|
||||||
stats.setDrawState(DrawState_Nothing);
|
stats.setDrawState(DrawState_Nothing);
|
||||||
|
|
||||||
|
// Note: we should cancel internal "return after combat" package, if original location is too far away
|
||||||
if (!isWithinMaxRange(targetPos, actorPos))
|
if (!isWithinMaxRange(targetPos, actorPos))
|
||||||
return false;
|
return mHidden;
|
||||||
|
|
||||||
// Unfortunately, with vanilla assets destination is sometimes blocked by other actor.
|
// 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.
|
// 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 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:
|
private:
|
||||||
float mX;
|
float mX;
|
||||||
|
|
|
@ -61,6 +61,34 @@ namespace MWMechanics
|
||||||
rotation.makeRotate(randomDirection, osg::Vec3f(0.0, 0.0, 1.0));
|
rotation.makeRotate(randomDirection, osg::Vec3f(0.0, 0.0, 1.0));
|
||||||
return position + osg::Vec3f(distance, 0.0, 0.0) * rotation;
|
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):
|
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
|
// get or create temporary storage
|
||||||
AiWanderStorage& storage = state.get<AiWanderStorage>();
|
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);
|
mRemainingDuration -= ((duration*MWBase::Environment::get().getWorld()->getTimeScaleFactor()) / 3600);
|
||||||
|
|
||||||
|
@ -200,14 +219,13 @@ namespace MWMechanics
|
||||||
if (AI_REACTION_TIME <= lastReaction)
|
if (AI_REACTION_TIME <= lastReaction)
|
||||||
{
|
{
|
||||||
lastReaction = 0;
|
lastReaction = 0;
|
||||||
return reactionTimeActions(actor, storage, currentCell, cellChange, pos);
|
return reactionTimeActions(actor, storage, pos);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AiWander::reactionTimeActions(const MWWorld::Ptr& actor, AiWanderStorage& storage,
|
bool AiWander::reactionTimeActions(const MWWorld::Ptr& actor, AiWanderStorage& storage, ESM::Position& pos)
|
||||||
const MWWorld::CellStore*& currentCell, bool cellChange, ESM::Position& pos)
|
|
||||||
{
|
{
|
||||||
if (mDistance <= 0)
|
if (mDistance <= 0)
|
||||||
storage.mCanWanderAlongPathGrid = false;
|
storage.mCanWanderAlongPathGrid = false;
|
||||||
|
@ -229,7 +247,7 @@ namespace MWMechanics
|
||||||
// Initialization to discover & store allowed node points for this actor.
|
// Initialization to discover & store allowed node points for this actor.
|
||||||
if (storage.mPopulateAvailableNodes)
|
if (storage.mPopulateAvailableNodes)
|
||||||
{
|
{
|
||||||
getAllowedNodes(actor, currentCell->getCell(), storage);
|
getAllowedNodes(actor, actor.getCell()->getCell(), storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canActorMoveByZAxis(actor) && mDistance > 0) {
|
if (canActorMoveByZAxis(actor) && mDistance > 0) {
|
||||||
|
@ -258,10 +276,6 @@ namespace MWMechanics
|
||||||
completeManualWalking(actor, storage);
|
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;
|
AiWanderStorage::WanderState& wanderState = storage.mState;
|
||||||
if ((wanderState == AiWanderStorage::Wander_MoveNow) && storage.mCanWanderAlongPathGrid)
|
if ((wanderState == AiWanderStorage::Wander_MoveNow) && storage.mCanWanderAlongPathGrid)
|
||||||
{
|
{
|
||||||
|
@ -279,6 +293,11 @@ namespace MWMechanics
|
||||||
completeManualWalking(actor, storage);
|
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
|
return false; // AiWander package not yet completed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,7 +349,7 @@ namespace MWMechanics
|
||||||
if (!isWaterCreature && !isFlyingCreature)
|
if (!isWaterCreature && !isFlyingCreature)
|
||||||
{
|
{
|
||||||
// findRandomPointAroundCircle uses wanderDistance as limit for random and not as exact distance
|
// 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;
|
mDestination = *destination;
|
||||||
else
|
else
|
||||||
mDestination = getRandomPointAround(mInitialActorPosition, wanderRadius);
|
mDestination = getRandomPointAround(mInitialActorPosition, wanderRadius);
|
||||||
|
@ -342,7 +361,10 @@ namespace MWMechanics
|
||||||
if (!isWaterCreature && destinationIsAtWater(actor, mDestination))
|
if (!isWaterCreature && destinationIsAtWater(actor, mDestination))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ((isWaterCreature || isFlyingCreature) && destinationThroughGround(currentPosition, mDestination))
|
if (isDestinationHidden(actor, mDestination))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (isAreaOccupiedByOtherActor(actor, mDestination))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (isWaterCreature || isFlyingCreature)
|
if (isWaterCreature || isFlyingCreature)
|
||||||
|
@ -371,16 +393,6 @@ namespace MWMechanics
|
||||||
return MWBase::Environment::get().getWorld()->isUnderwater(actor.getCell(), positionBelowSurface);
|
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) {
|
void AiWander::completeManualWalking(const MWWorld::Ptr &actor, AiWanderStorage &storage) {
|
||||||
stopWalking(actor, storage);
|
stopWalking(actor, storage);
|
||||||
mObstacleCheck.clear();
|
mObstacleCheck.clear();
|
||||||
|
@ -529,7 +541,7 @@ namespace MWMechanics
|
||||||
unsigned int randNode = Misc::Rng::rollDice(storage.mAllowedNodes.size());
|
unsigned int randNode = Misc::Rng::rollDice(storage.mAllowedNodes.size());
|
||||||
ESM::Pathgrid::Point dest(storage.mAllowedNodes[randNode]);
|
ESM::Pathgrid::Point dest(storage.mAllowedNodes[randNode]);
|
||||||
|
|
||||||
ToWorldCoordinates(dest, storage.mCell->getCell());
|
ToWorldCoordinates(dest, actor.getCell()->getCell());
|
||||||
|
|
||||||
// actor position is already in world coordinates
|
// actor position is already in world coordinates
|
||||||
const osg::Vec3f start = actorPos.asVec3();
|
const osg::Vec3f start = actorPos.asVec3();
|
||||||
|
|
|
@ -27,8 +27,6 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
float mReaction; // update some actions infrequently
|
float mReaction; // update some actions infrequently
|
||||||
|
|
||||||
const MWWorld::CellStore* mCell; // for detecting cell change
|
|
||||||
|
|
||||||
// AiWander states
|
// AiWander states
|
||||||
enum WanderState
|
enum WanderState
|
||||||
{
|
{
|
||||||
|
@ -60,7 +58,6 @@ namespace MWMechanics
|
||||||
|
|
||||||
AiWanderStorage():
|
AiWanderStorage():
|
||||||
mReaction(0),
|
mReaction(0),
|
||||||
mCell(nullptr),
|
|
||||||
mState(Wander_ChooseAction),
|
mState(Wander_ChooseAction),
|
||||||
mIsWanderingManually(false),
|
mIsWanderingManually(false),
|
||||||
mCanWanderAlongPathGrid(true),
|
mCanWanderAlongPathGrid(true),
|
||||||
|
@ -100,6 +97,8 @@ namespace MWMechanics
|
||||||
|
|
||||||
virtual int getTypeId() const;
|
virtual int getTypeId() const;
|
||||||
|
|
||||||
|
virtual bool useVariableSpeed() const { return true;}
|
||||||
|
|
||||||
virtual void writeState(ESM::AiSequence::AiSequence &sequence) const;
|
virtual void writeState(ESM::AiSequence::AiSequence &sequence) const;
|
||||||
|
|
||||||
virtual void fastForward(const MWWorld::Ptr& actor, AiState& state);
|
virtual void fastForward(const MWWorld::Ptr& actor, AiState& state);
|
||||||
|
@ -108,6 +107,14 @@ namespace MWMechanics
|
||||||
|
|
||||||
osg::Vec3f getDestination(const MWWorld::Ptr& actor) const;
|
osg::Vec3f getDestination(const MWWorld::Ptr& actor) const;
|
||||||
|
|
||||||
|
virtual osg::Vec3f getDestination() const
|
||||||
|
{
|
||||||
|
if (!mHasDestination)
|
||||||
|
return osg::Vec3f(0, 0, 0);
|
||||||
|
|
||||||
|
return mDestination;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// NOTE: mDistance and mDuration must be set already
|
// NOTE: mDistance and mDuration must be set already
|
||||||
void init();
|
void init();
|
||||||
|
@ -125,12 +132,10 @@ namespace MWMechanics
|
||||||
void onIdleStatePerFrameActions(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage);
|
void onIdleStatePerFrameActions(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage);
|
||||||
void onWalkingStatePerFrameActions(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);
|
void onChooseActionStatePerFrameActions(const MWWorld::Ptr& actor, AiWanderStorage& storage);
|
||||||
bool reactionTimeActions(const MWWorld::Ptr& actor, AiWanderStorage& storage,
|
bool reactionTimeActions(const MWWorld::Ptr& actor, AiWanderStorage& storage, ESM::Position& pos);
|
||||||
const MWWorld::CellStore*& currentCell, bool cellChange, ESM::Position& pos);
|
|
||||||
bool isPackageCompleted(const MWWorld::Ptr& actor, AiWanderStorage& storage);
|
bool isPackageCompleted(const MWWorld::Ptr& actor, AiWanderStorage& storage);
|
||||||
void wanderNearStart(const MWWorld::Ptr &actor, AiWanderStorage &storage, int wanderDistance);
|
void wanderNearStart(const MWWorld::Ptr &actor, AiWanderStorage &storage, int wanderDistance);
|
||||||
bool destinationIsAtWater(const MWWorld::Ptr &actor, const osg::Vec3f& destination);
|
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);
|
void completeManualWalking(const MWWorld::Ptr &actor, AiWanderStorage &storage);
|
||||||
|
|
||||||
int mDistance; // how far the actor can wander from the spawn point
|
int mDistance; // how far the actor can wander from the spawn point
|
||||||
|
@ -141,7 +146,7 @@ namespace MWMechanics
|
||||||
bool mRepeat;
|
bool mRepeat;
|
||||||
|
|
||||||
bool mStoredInitialActorPosition;
|
bool mStoredInitialActorPosition;
|
||||||
osg::Vec3f mInitialActorPosition;
|
osg::Vec3f mInitialActorPosition; // Note: an original engine does not reset coordinates even when actor changes a cell
|
||||||
|
|
||||||
bool mHasDestination;
|
bool mHasDestination;
|
||||||
osg::Vec3f mDestination;
|
osg::Vec3f mDestination;
|
||||||
|
|
|
@ -554,3 +554,37 @@ std::string MWMechanics::Alchemy::suggestPotionName()
|
||||||
return MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
|
return MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
|
||||||
ESM::MagicEffect::effectIdToString(effectId))->mValue.getString();
|
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
|
///< Try to create potions from the ingredients, place them in the inventory of the alchemist and
|
||||||
/// adjust the skills of the alchemist accordingly.
|
/// adjust the skills of the alchemist accordingly.
|
||||||
/// \param name must not be an empty string, or Result_NoName is returned
|
/// \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;
|
mTimeToStartDrowning=time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MWMechanics::NpcStats::writeState (ESM::CreatureStats& state) const
|
||||||
|
{
|
||||||
|
CreatureStats::writeState(state);
|
||||||
|
}
|
||||||
|
|
||||||
void MWMechanics::NpcStats::writeState (ESM::NpcStats& state) const
|
void MWMechanics::NpcStats::writeState (ESM::NpcStats& state) const
|
||||||
{
|
{
|
||||||
for (std::map<std::string, int>::const_iterator iter (mFactionRank.begin());
|
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;
|
state.mTimeToStartDrowning = mTimeToStartDrowning;
|
||||||
}
|
}
|
||||||
|
void MWMechanics::NpcStats::readState (const ESM::CreatureStats& state)
|
||||||
|
{
|
||||||
|
CreatureStats::readState(state);
|
||||||
|
}
|
||||||
|
|
||||||
void MWMechanics::NpcStats::readState (const ESM::NpcStats& state)
|
void MWMechanics::NpcStats::readState (const ESM::NpcStats& state)
|
||||||
{
|
{
|
||||||
|
|
|
@ -127,8 +127,10 @@ namespace MWMechanics
|
||||||
/// @param time value from [0,20]
|
/// @param time value from [0,20]
|
||||||
void setTimeToStartDrowning(float time);
|
void setTimeToStartDrowning(float time);
|
||||||
|
|
||||||
|
void writeState (ESM::CreatureStats& state) const;
|
||||||
void writeState (ESM::NpcStats& state) const;
|
void writeState (ESM::NpcStats& state) const;
|
||||||
|
|
||||||
|
void readState (const ESM::CreatureStats& state);
|
||||||
void readState (const ESM::NpcStats& state);
|
void readState (const ESM::NpcStats& state);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,6 +120,7 @@ namespace MWMechanics
|
||||||
mWalkState = WalkState::Norm;
|
mWalkState = WalkState::Norm;
|
||||||
mStateDuration = 0;
|
mStateDuration = 0;
|
||||||
mPrev = position;
|
mPrev = position;
|
||||||
|
mInitialDistance = (destination - position).length();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,10 +130,11 @@ namespace MWMechanics
|
||||||
const float prevDistance = (destination - mPrev).length();
|
const float prevDistance = (destination - mPrev).length();
|
||||||
const float currentDistance = (destination - position).length();
|
const float currentDistance = (destination - position).length();
|
||||||
const float movedDistance = prevDistance - currentDistance;
|
const float movedDistance = prevDistance - currentDistance;
|
||||||
|
const float movedFromInitialDistance = mInitialDistance - currentDistance;
|
||||||
|
|
||||||
mPrev = position;
|
mPrev = position;
|
||||||
|
|
||||||
if (movedDistance >= distSameSpot)
|
if (movedDistance >= distSameSpot && movedFromInitialDistance >= distSameSpot)
|
||||||
{
|
{
|
||||||
mWalkState = WalkState::Norm;
|
mWalkState = WalkState::Norm;
|
||||||
mStateDuration = 0;
|
mStateDuration = 0;
|
||||||
|
@ -143,6 +145,7 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
mWalkState = WalkState::CheckStuck;
|
mWalkState = WalkState::CheckStuck;
|
||||||
mStateDuration = duration;
|
mStateDuration = duration;
|
||||||
|
mInitialDistance = (destination - position).length();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
float mStateDuration;
|
float mStateDuration;
|
||||||
int mEvadeDirectionIndex;
|
int mEvadeDirectionIndex;
|
||||||
|
float mInitialDistance = 0;
|
||||||
|
|
||||||
void chooseEvasionDirection();
|
void chooseEvasionDirection();
|
||||||
};
|
};
|
||||||
|
|
|
@ -314,7 +314,9 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
mPath.clear();
|
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;
|
mConstructed = true;
|
||||||
}
|
}
|
||||||
|
@ -335,24 +337,27 @@ namespace MWMechanics
|
||||||
mConstructed = true;
|
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,
|
const osg::Vec3f& endPoint, const osg::Vec3f& halfExtents, const DetourNavigator::Flags flags,
|
||||||
std::back_insert_iterator<std::deque<osg::Vec3f>> out)
|
std::back_insert_iterator<std::deque<osg::Vec3f>> out)
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
const auto world = MWBase::Environment::get().getWorld();
|
const auto world = MWBase::Environment::get().getWorld();
|
||||||
const auto stepSize = getPathStepSize(actor);
|
const auto stepSize = getPathStepSize(actor);
|
||||||
const auto navigator = world->getNavigator();
|
const auto navigator = world->getNavigator();
|
||||||
navigator->findPath(halfExtents, stepSize, startPoint, endPoint, flags, out);
|
const auto status = navigator->findPath(halfExtents, stepSize, startPoint, endPoint, flags, out);
|
||||||
}
|
|
||||||
catch (const DetourNavigator::NavigatorException& exception)
|
if (status == DetourNavigator::Status::NavMeshNotFound)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (status != DetourNavigator::Status::Success)
|
||||||
{
|
{
|
||||||
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()
|
<< "\" for \"" << actor.getClass().getName(actor) << "\" (" << actor.getBase()
|
||||||
<< ") from " << startPoint << " to " << endPoint << " with flags ("
|
<< ") from " << startPoint << " to " << endPoint << " with flags ("
|
||||||
<< DetourNavigator::WriteFlags {flags} << ")";
|
<< DetourNavigator::WriteFlags {flags} << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PathFinder::buildPathByNavMeshToNextPoint(const MWWorld::ConstPtr& actor, const osg::Vec3f& halfExtents,
|
void PathFinder::buildPathByNavMeshToNextPoint(const MWWorld::ConstPtr& actor, const osg::Vec3f& halfExtents,
|
||||||
|
@ -367,11 +372,23 @@ namespace MWMechanics
|
||||||
if (sqrDistanceIgnoreZ(mPath.front(), startPoint) <= 4 * stepSize * stepSize)
|
if (sqrDistanceIgnoreZ(mPath.front(), startPoint) <= 4 * stepSize * stepSize)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
const auto navigator = MWBase::Environment::get().getWorld()->getNavigator();
|
const auto navigator = MWBase::Environment::get().getWorld()->getNavigator();
|
||||||
std::deque<osg::Vec3f> prePath;
|
std::deque<osg::Vec3f> prePath;
|
||||||
navigator->findPath(halfExtents, stepSize, startPoint, mPath.front(), flags, std::back_inserter(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)
|
||||||
|
{
|
||||||
|
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)
|
while (!prePath.empty() && sqrDistanceIgnoreZ(prePath.front(), startPoint) < stepSize * stepSize)
|
||||||
prePath.pop_front();
|
prePath.pop_front();
|
||||||
|
@ -381,12 +398,4 @@ namespace MWMechanics
|
||||||
|
|
||||||
std::copy(prePath.rbegin(), prePath.rend(), std::front_inserter(mPath));
|
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()
|
|
||||||
<< "\" for \"" << actor.getClass().getName(actor) << "\" (" << actor.getBase()
|
|
||||||
<< ") from " << startPoint << " to " << mPath.front() << " with flags ("
|
|
||||||
<< DetourNavigator::WriteFlags {flags} << ")";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,7 +201,7 @@ namespace MWMechanics
|
||||||
void buildPathByPathgridImpl(const osg::Vec3f& startPoint, const osg::Vec3f& endPoint,
|
void buildPathByPathgridImpl(const osg::Vec3f& startPoint, const osg::Vec3f& endPoint,
|
||||||
const PathgridGraph& pathgridGraph, std::back_insert_iterator<std::deque<osg::Vec3f>> out);
|
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,
|
const osg::Vec3f& endPoint, const osg::Vec3f& halfExtents, const DetourNavigator::Flags flags,
|
||||||
std::back_insert_iterator<std::deque<osg::Vec3f>> out);
|
std::back_insert_iterator<std::deque<osg::Vec3f>> out);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1199,10 +1199,10 @@ namespace MWMechanics
|
||||||
return false;
|
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);
|
DynamicStat<float> stat = creatureStats.getDynamic(index);
|
||||||
stat.setCurrent(stat.getCurrent() + magnitude, index == 2);
|
stat.setCurrent(stat.getCurrent() + magnitude, allowDecreaseBelowZero);
|
||||||
creatureStats.setDynamic(index, stat);
|
creatureStats.setDynamic(index, stat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1241,9 +1241,12 @@ namespace MWMechanics
|
||||||
|
|
||||||
case ESM::MagicEffect::DamageMagicka:
|
case ESM::MagicEffect::DamageMagicka:
|
||||||
case ESM::MagicEffect::DamageFatigue:
|
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;
|
break;
|
||||||
|
}
|
||||||
case ESM::MagicEffect::AbsorbHealth:
|
case ESM::MagicEffect::AbsorbHealth:
|
||||||
if (magnitude > 0.f)
|
if (magnitude > 0.f)
|
||||||
receivedMagicDamage = true;
|
receivedMagicDamage = true;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue