1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-19 23:53:52 +00:00

Merge branch 'master' of https://gitlab.com/madsbuvi/openmw.git into openxr_vr

# Conflicts:
#	CMakeLists.txt
#	apps/openmw/engine.cpp
#	apps/openmw/mwgui/windowmanagerimp.cpp
#	apps/openmw/mwinput/inputmanagerimp.cpp
#	apps/openmw/mwinput/inputmanagerimp.hpp
#	apps/openmw/mwphysics/physicssystem.cpp
#	apps/openmw/mwrender/water.cpp
#	apps/openmw/mwrender/water.hpp
#	apps/openmw/mwworld/worldimp.cpp
This commit is contained in:
Mads Buvik Sandvei 2020-05-17 23:47:28 +02:00
commit cbbc82f053
356 changed files with 10085 additions and 6656 deletions

1
.gitignore vendored
View file

@ -30,6 +30,7 @@ cmake-build-*
files/windows/*.aps files/windows/*.aps
## qt-creator ## qt-creator
CMakeLists.txt.user* CMakeLists.txt.user*
.vs
## resources ## resources
data data

View file

@ -23,6 +23,7 @@ Debian:
artifacts: artifacts:
paths: paths:
- build/artifacts/ - build/artifacts/
MacOS: MacOS:
tags: tags:
- macos - macos
@ -42,18 +43,21 @@ MacOS:
Windows: Windows:
tags: tags:
- win10 - windows
- msvc2017
except:
- branches # because our CI VMs are not public, MRs can't use them and timeout
stage: build stage: build
allow_failure: true allow_failure: true
script: script:
# - env # turn on for debugging - Set-Variable -Name "time" -Value (date -Format "%H:%m")
- sh %CI_PROJECT_DIR%/CI/before_script.msvc.sh -c Release -p x64 -v 2017 -V - echo ${time}
- SET msBuildLocation="C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\msbuild.exe" - echo "started by ${GITLAB_USER_NAME}"
- call %msBuildLocation% MSVC2017_64\OpenMW.sln /t:Build /p:Configuration=Release /m:%NUMBER_OF_PROCESSORS% # TODO: to anyone wanting to do further work here, we need to figure out how to get the below working
- 7z a OpenMW_MSVC2017_64_%CI_BUILD_REF_NAME%_%CI_BUILD_ID%.zip %CI_PROJECT_DIR%\MSVC2017_64\Release\ # TODO: on gitlab's new shared windows runners. They currently don't have bash or anything else installed
# TODO: it is currently just a bare windows 10 with powershell.
# - env # turn on for debugging
# - sh %CI_PROJECT_DIR%/CI/before_script.msvc.sh -c Release -p x64 -v 2017 -V
# - SET msBuildLocation="C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\msbuild.exe"
# - call %msBuildLocation% MSVC2017_64\OpenMW.sln /t:Build /p:Configuration=Release /m:%NUMBER_OF_PROCESSORS%
# - 7z a OpenMW_MSVC2017_64_%CI_BUILD_REF_NAME%_%CI_BUILD_ID%.zip %CI_PROJECT_DIR%\MSVC2017_64\Release\
cache: cache:
paths: paths:
- deps - deps

View file

@ -25,7 +25,7 @@ addons:
# Audio, Video and Misc. deps # Audio, Video and Misc. deps
libsdl2-dev, libqt5opengl5-dev, libopenal-dev, libunshield-dev, libtinyxml-dev, libsdl2-dev, libqt5opengl5-dev, libopenal-dev, libunshield-dev, libtinyxml-dev,
# The other ones from OpenMW ppa # The other ones from OpenMW ppa
libbullet-dev, libopenscenegraph-3.4-dev, libmygui-dev libbullet-dev, libopenscenegraph-dev, libmygui-dev
] ]
coverity_scan: # TODO: currently takes too long, disabled openmw/openmw-cs for now. coverity_scan: # TODO: currently takes too long, disabled openmw/openmw-cs for now.
project: project:

View file

@ -1,3 +1,22 @@
0.47.0
------
Bug #1952: Incorrect particle lighting
Bug #2311: Targeted scripts are not properly supported on non-unique RefIDs
Bug #3676: NiParticleColorModifier isn't applied properly
Bug #4774: Guards are ignorant of an invisible player that tries to attack them
Bug #5108: Savegame bloating due to inefficient fog textures format
Bug #5358: ForceGreeting always resets the dialogue window completely
Bug #5363: Enchantment autocalc not always 0/1
Bug #5364: Script fails/stops if trying to startscript an unknown script
Bug #5367: Selecting a spell on an enchanted item per hotkey always plays the equip sound
Bug #5369: Spawnpoint in the Grazelands doesn't produce oversized creatures
Bug #5370: Opening an unlocked but trapped door uses the key
Bug #5400: Editor: Verifier checks race of non-skin bodyparts
Bug #5415: Environment maps in ebony cuirass and HiRez Armors Indoril cuirass don't work
Bug #5416: Junk non-node records before the root node are not handled gracefully
Feature #5362: Show the soul gems' trapped soul in count dialog
0.46.0 0.46.0
------ ------
@ -153,7 +172,6 @@
Bug #5099: Non-swimming enemies will enter water if player is water walking Bug #5099: Non-swimming enemies will enter water if player is water walking
Bug #5103: Sneaking state behavior is still inconsistent Bug #5103: Sneaking state behavior is still inconsistent
Bug #5104: Black Dart's enchantment doesn't trigger at low Enchant levels Bug #5104: Black Dart's enchantment doesn't trigger at low Enchant levels
Bug #5105: NPCs start combat with werewolves from any distance
Bug #5106: Still can jump even when encumbered Bug #5106: Still can jump even when encumbered
Bug #5110: ModRegion with a redundant numerical argument breaks script execution Bug #5110: ModRegion with a redundant numerical argument breaks script execution
Bug #5112: Insufficient magicka for current spell not reflected on HUD icon Bug #5112: Insufficient magicka for current spell not reflected on HUD icon
@ -171,6 +189,7 @@
Bug #5159: NiMaterialColorController can only control the diffuse color Bug #5159: NiMaterialColorController can only control the diffuse color
Bug #5161: Creature companions can't be activated when they are knocked down Bug #5161: Creature companions can't be activated when they are knocked down
Bug #5164: Faction owned items handling is incorrect Bug #5164: Faction owned items handling is incorrect
Bug #5163: UserData is not copied during node cloning
Bug #5166: Scripts still should be executed after player's death Bug #5166: Scripts still should be executed after player's death
Bug #5167: Player can select and cast spells before magic menu is enabled Bug #5167: Player can select and cast spells before magic menu is enabled
Bug #5168: Force1stPerson and Force3rdPerson commands are not really force view change Bug #5168: Force1stPerson and Force3rdPerson commands are not really force view change
@ -204,12 +223,14 @@
Bug #5264: "Damage Fatigue" Magic Effect Can Bring Fatigue below 0 Bug #5264: "Damage Fatigue" Magic Effect Can Bring Fatigue below 0
Bug #5269: Editor: Cell lighting in resaved cleaned content files is corrupted 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 #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 #5308: World map copying makes save loading much slower
Bug #5313: Node properties of identical type are not applied in the correct order Bug #5313: Node properties of identical type are not applied in the correct order
Bug #5326: Formatting issues in the settings.cfg Bug #5326: Formatting issues in the settings.cfg
Bug #5328: Skills aren't properly reset for dead actors Bug #5328: Skills aren't properly reset for dead actors
Feature #1774: Handle AvoidNode Bug #5345: Dopey Necromancy does not work due to a missing quote
Bug #5350: An attempt to launch magic bolt causes "AL error invalid value" error
Bug #5352: Light source items' duration is decremented while they aren't visible
Feature #1724: Handle AvoidNode
Feature #2229: Improve pathfinding AI Feature #2229: Improve pathfinding AI
Feature #3025: Analogue gamepad movement controls Feature #3025: Analogue gamepad movement controls
Feature #3442: Default values for fallbacks from ini file Feature #3442: Default values for fallbacks from ini file
@ -240,6 +261,7 @@
Feature #4882: Support for NiPalette node Feature #4882: Support for NiPalette node
Feature #4887: Add openmw command option to set initial random seed Feature #4887: Add openmw command option to set initial random seed
Feature #4890: Make Distant Terrain configurable Feature #4890: Make Distant Terrain configurable
Feature #4944: Pause audio when OpenMW is minimized
Feature #4958: Support eight blood types Feature #4958: Support eight blood types
Feature #4962: Add casting animations for magic items Feature #4962: Add casting animations for magic items
Feature #4968: Scalable UI widget skins Feature #4968: Scalable UI widget skins
@ -266,10 +288,12 @@
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 #5172: Editor: Delete instances/references with keypress in scene window
Feature #5193: Weapon sheathing Feature #5193: Weapon sheathing
Feature #5201: Editor: Show tool outline in scene view, when using editmodes
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 #5274: Editor: Keyboard shortcut to drop objects to ground/obstacle in scene view
Feature #5304: Morrowind-style bump-mapping Feature #5304: Morrowind-style bump-mapping
Feature #5311: Support for gyroscopic input (e.g. Android)
Feature #5314: Ingredient filter in the alchemy window 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

View file

@ -5,112 +5,36 @@
*** ***
0.46.0 0.47.0
------ ------
The OpenMW team is proud to announce the release of version 0.46.0! Grab it from our Downloads Page for all operating systems. ***short summary: shadows, recastnavigation, etc.*** The OpenMW team is proud to announce the release of version 0.47.0! Grab it from our Downloads Page for all operating systems. ***short summary: XXX ***
Check out the release video (***add link***) and the OpenMW-CS release video (***add link***) by the ***add flattering adjective*** Atahualpa, and see below for the full list of changes. Check out the release video (***add link***) and the OpenMW-CS release video (***add link***) by the ***add flattering adjective*** Atahualpa, and see below for the full list of changes.
Known Issues: Known Issues:
- There's currently no way to redirect the logging output to the command prompt on Windows Release builds -- this will be resolved in version 0.46.0
- To use generic Linux binaries, Qt4 and libpng12 must be installed on your system - To use generic Linux binaries, Qt4 and libpng12 must be installed on your system
- On macOS, launching OpenMW from OpenMW-CS requires OpenMW.app and OpenMW-CS.app to be siblings - On macOS, launching OpenMW from OpenMW-CS requires OpenMW.app and OpenMW-CS.app to be siblings
New Features: New Features:
- NIF files which contain an "AvoidNode" are ignored by the pathfinding algorithm (#1724) - Dialogue to split item stacks now displays the name of the trapped soul for stacks of soul gems (#5362)
- Navmeshes are used for AI pathfinding which should resolve most related issues (#2229)
- Movement input from gamepad joysticks is transformed into analogue values (#3025)
- Sane default values for openmw.cfg file to overcome the original morrowind.ini file (#3442)
- Option to invert x-axis for controllers (#3610)
- Local variables of objects selected in the console can now be directly read and set without explicitly stating the object (#3893)
- In-game option to enable or disable controllers (#3980)
- Sneak mode can be toggled using a controller (#4001)
- Controllers use original engine's default key bindings (#4360)
- Support for sheathing animations, including weapon holstering, scabbards (except for throwing weapons), and quivers for projectiles (#4673)
- Support for "NiRollController" in NIF files to ensure correct rotation of models in "Weapon Sheathing" mod (#4675)
- Support for native animated containers (#4730)
- Support for VAO ("Vertex Array Objects") from OSG 3.5.6 or later (#4756)
- Support for "NiSwitchNode" in NIF files to allow future implementation of native support for extended features like harvestable plants or glowing - windows (#4812)
- Native support for glowing windows (and other daytime-dependent meshes) by adding internal day-night-mode switch (#4836)
- Shadows (#4851)
- More configuration options for in-game water reflections (#4859)
- Command line option to specify a random seed to be used by the game's random-number generator ("RNG") for debugging purposes (#4887)
- Configuration options for distant terrain to adjust quality and performance impact (#4890)
New Editor Features: New Editor Features:
- "Faction Ranks" table for "Faction" records (#4209) - ?
- Changes to height editing can be cancelled without changes to data (press esc to cancel) (#4840)
- Land heightmap/shape editing and vertex selection (#5170)
- Deleting instances with a keypress (#5172)
- Dropping objects with keyboard shortcuts (#5274)
Bug Fixes: Bug Fixes:
- The Mouse Wheel can now be used for key bindings (#2679) - NiParticleColorModifier in NIF files is now properly handled which solves issues regarding particle effects, e.g., smoke and fire (#1952, #3676)
- Scripted Items cannot be stacked anymore to avoid multiple script execution (#2969) - Targetting non-unique actors in scripts is now supported (#2311)
- Stray text after an "else" statement is now ignored, like in the original engine, to handle mods which erroneously use "else if" statements (#3006) - Guards no longer ignore attacks of invisible players but rather initiate dialogue and flee if the player resists being arrested (#4774)
- "SetPos" and "SetPosition" commands now more closely replicate the original engine's behaviour (#3109) - Changing the dialogue window without closing it no longer clears the dialogue history in order to allow, e.g., emulation of three-way dialogue via ForceGreeting (#5358)
- "Reserved keys [F3], [F4], [F10], and [F11] cannot be assigned to in-game controls anymore (#3282) - Scripts which try to start a non-existent global script now skip that step and continue execution instead of breaking (#5364)
- Windows: Reserved [Windows] key cannot be assigned to in-game controls anymore (#3282)" - Selecting already equipped spells or magic items via hotkey no longer triggers the equip sound to play (#5367)
- Windows: Windows-internal display scaling no longer breaks main menu (#3623) - 'Scale' argument in levelled creature lists is now taken into account when spawning creatures from such lists (#5369)
- Normal maps on mirrored UVs are no longer inverted (#3733) - Morrowind legacy madness: Using a key on a trapped door/container now only disarms the trap if the door/container is locked (#5370)
- Teleporting attempts are now also detected if teleporting is disabled to ensure compatibility with certain mods (#3765)
- Throwing weapons are now correctly rotated during throwing animation when using the "Improved Thrown Weapon Projectiles" mod (#3778)
- Birthsign abilities are no longer restored upon loading to ensure mod compatibility (#4329)
- Player character's model is no longer scaled in first-person mode to prevent issues with arrows obscuring the crosshair (#4383)
- Optional: Ranged attacks now bypass normal weapon resistance or weakness if ammunition and/or bow are appropriate (#4384)
- Fall damage is now also applied when first reloading a savegame and when your character is near the ground in the loaded game (#4411)
- Rain drops are no longer delayed when your character emerges from water (#4540)
- ESM record for prison markers is now hardcoded like, e.g., door markers or temple markers (#4701)
- Loading a savegame which includes active messages no longer crashes the game (#4714)
- An empty pointer actor no longer throws an exception upon exiting the dialogue menu (#4715)
- Inventory paper doll no longer simultaneously displays shield and two-handed weapon during drawing and holstering animations (#4720)
- "Reset actors" command ("ra") no longer tries to reset actors originating from inactive cells, e.g., followers (#4723)
- "Reset actors" command ("ra") now traces reset actors to the ground and also resets fall damage (#4723)"
- Land texture records can now be overwritten by content files to create mods like "Winter in Morrowind" (#4736)
- Disabling collision no longer forces your character to walking speed, but also allows them to run or sneak (#4746)
- NPCs now also use the skeleton associated with their specified model, not only the animations (#4747)
- Sneaking und swimming idle animations are no longer interrupted if your character is in attack-ready state in first-person view (#4750)
- Numerical fallback values with invalid values (e.g., stray text) in the openmw.cfg file no longer crash or break the game (#4768)
- Character's "jumping" flag is no longer unnecessarily reset to ensure compatibility with certain mods, e.g., "Sotha Sil Expanded" (#4775)
- Calling "GetSpellEffects", "GetEffect", or "GetSpell" function on non-actor objects now returns 0, fixing issues with "Sotha Sil Expanded" - (#4778)
- AI values for actors without AIDT ("AI Data") subrecord are now set to zero upon loading instead of filling in "random" values (#4778)
- Running and sneaking are now also considered in in-game checks when your character is in midair, fixing an issue with the "Reign of Fire" mod - (#4797)
- Collision checks are now immediately updated when an object is moved to ensure compatibility with "Sotha Sil Expanded" (#4800)
- Stray special characters before the "begin" statement of a script are now ignored to ensure, once again, compatibility with "Sotha Sil Expanded" - (#4803)
- Particle nodes with an empty "sizes" array are now correctly loaded and no longer cause an exception (#4804)
- Handling of "root bone" and "bip01" nodes in NIF files now matches the original engine's behaviour to ensure compatibility with "Skyrim: Home of - the Nords" (#4810)
- Creatures without specified sound files now fallback to the sounds of the first creature sharing the same model (#4813)
- "Journal" command now also closes a quest when the specified "finish quest" entry has a lower value than the current one for that quest (#4815)
- Spell effects are no longer applied when a spell is successfully absorbed (#4820)
- World state is no longer updated for every in-game hour your character is in jail but only once, which should significantly reduce loading times - (#4823)
- "NiUVController" in NIF files now only affects textures which use the specified "UV Set" index, usually 0; ensures compatibility with "Glow in the Dahrk" (#4827)
- Visual effects ("VFX") for magic effects are now played immediately after the effect is triggered to not accidentally skip the VFX, e.g., when actors drink potions in battle (#4828)
- Meshes with "NiLODNode" or "NiSwitchNode" no longer cause crashes when they contain particles (#4837)
- Localisations can now make use of implicit keywords to create hyperlinks in dialogue text (#4841)
- Actors outside of the processing range no longer appear for one frame when they are spawned (#4860)
- Stray text after a local-variable declaration is now ignored to ensure mod compatibility (#4867)
- Range and default values of AI data fields now match the original engine's ones (#4876)
- "Startup" scripts are now always run once upon starting OpenMW (#4877)
- Stray explicit reference calls for global variables are now ignored to ensure mod compatibility, e.g., with "Sotha Sil Expanded" (#4888)
- Title screen music now loops (#4896)
- "Specular power" is no longer hardcoded but uses the specified value in the shader code (#4916)
- Werewolves can now also attack if their transformation happened during an attack move (#4922)
- Plug-ins with valid empty subrecords are now correctly loaded, which fixes issues with the "DC - Return of Great House Dagoth" mod (#4938)
- Hand-to-hand attacks are now movement-based when the "always use best attack" option is turned off, like in the original engine (#4942)
Editor Bug Fixes: Editor Bug Fixes:
- Certain numerical fields now only accept unsigned 8-bit integers to avoid overflows (#2987) - Verifier no longer checks for alleged 'race' entries in clothing body parts (#5400)
- Preview option is now disabled for levelled lists (#4703)
- Opening the "Scene" view from the "Instances" table now also works for exterior cells (#4705)
- Colour fields in interior-cell records now also use the colour picker widget (#4745)
- Cloned, added, or moved instances no longer disappear at load-time (#4748)
- "Clear" function in the content selector no longer tries to execute a "Remove" action on an empty file list (#4757)
- Terrain texture editing for plugins now correctly handles drags from base file (#4904)
- Engine no longer tries to swap buffers of windows which weren't exposed to Qt's window management system (#4911)
- Minimap doesn't get corrupted, when editing new omwgame (#5177)
Miscellaneous: Miscellaneous:
- Upgraded to FFMPEG3 for media decoding (#4686) - Prevent save-game bloating by using an appropriate fog texture format (#5108)
- Optimised terrain code to drastically increase performance with distant terrain enabled (#4695) - Ensure that 'Enchantment autocalc" flag is treated as flag in OpenMW-CS and in our esm tools (#5363)
- Windows: Added support for NMake to the prebuild script (#4721)

26
CI/ActivateMSVC.ps1 Normal file
View file

@ -0,0 +1,26 @@
& "${env:COMSPEC}" /c ActivateMSVC.bat "&&" set | ForEach-Object {
$name, $value = $_ -split '=', 2
Set-Content env:\"$name" $value
}
$MissingTools = $false
$tools = "cl", "link", "rc", "mt", "awooga"
$descriptions = "MSVC Compiler", "MSVC Linker", "MS Windows Resource Compiler", "MS Windows Manifest Tool", "A made up command"
for ($i = 0; $i -lt $tools.Length; $i++) {
$present = $true
try {
Get-Command $tools[$i] *>&1 | Out-Null
$present = $present -and $?
} catch {
$present = $false
}
if (!$present) {
Write-Warning "$($tools[$i]) ($($descriptions[$i])) missing."
$MissingTools = $true
}
}
if ($MissingTools) {
Write-Error "Some build tools were unavailable after activating MSVC in the shell. It's likely that your Visual Studio $MSVC_DISPLAY_YEAR installation needs repairing."
exit 1
}

76
CI/activate_msvc.sh Normal file
View file

@ -0,0 +1,76 @@
#!/bin/bash
set -euo pipefail
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
echo "Error: Script not sourced."
echo "You must source this script for it to work, i.e. "
echo "source ./activate_msvc.sh"
echo "or"
echo ". ./activate_msvc.sh"
exit 1
fi
command -v unixPathAsWindows >/dev/null 2>&1 || function unixPathAsWindows {
if command -v cygpath >/dev/null 2>&1; then
cygpath -w $1
else
echo "$1" | sed "s,^/\([^/]\)/,\\1:/," | sed "s,/,\\\\,g"
fi
}
function windowsSystemPathAsUnix {
if command -v cygpath >/dev/null 2>&1; then
cygpath -u -p $1
else
IFS=';' read -r -a paths <<< "$1"
declare -a convertedPaths
for entry in paths; do
convertedPaths+=(windowsPathAsUnix $entry)
done
convertedPath=printf ":%s" ${convertedPaths[@]}
echo ${convertedPath:1}
fi
}
# capture CMD environment so we know what's been changed
declare -A originalCmdEnv
originalIFS="$IFS"
IFS=$'\n\r'
for pair in $(cmd //c "set"); do
IFS='=' read -r -a separatedPair <<< "${pair}"
originalCmdEnv["${separatedPair[0]}"]="${separatedPair[1]}"
done
# capture CMD environment in a shell with MSVC activated
cmdEnv="$(cmd //c "$(unixPathAsWindows "$(dirname "${BASH_SOURCE[0]}")")\ActivateMSVC.bat" "&&" set)"
declare -A cmdEnvChanges
for pair in $cmdEnv; do
if [ -n "$pair" ]; then
IFS='=' read -r -a separatedPair <<< "${pair}"
key="${separatedPair[0]}"
value="${separatedPair[1]}"
if ! [ ${originalCmdEnv[$key]+_} ] || [ "${originalCmdEnv[$key]}" != "$value" ]; then
if [ $key != 'PATH' ] && [ $key != 'path' ] && [ $key != 'Path' ]; then
export "$key=$value"
else
export PATH=$(windowsSystemPathAsUnix $value)
fi
fi
fi
done
MISSINGTOOLS=0
command -v cl >/dev/null 2>&1 || { echo "Error: cl (MSVC Compiler) missing."; MISSINGTOOLS=1; }
command -v link >/dev/null 2>&1 || { echo "Error: link (MSVC Linker) missing."; MISSINGTOOLS=1; }
command -v rc >/dev/null 2>&1 || { echo "Error: rc (MS Windows Resource Compiler) missing."; MISSINGTOOLS=1; }
command -v mt >/dev/null 2>&1 || { echo "Error: mt (MS Windows Manifest Tool) missing."; MISSINGTOOLS=1; }
if [ $MISSINGTOOLS -ne 0 ]; then
echo "Some build tools were unavailable after activating MSVC in the shell. It's likely that your Visual Studio $MSVC_DISPLAY_YEAR installation needs repairing."
return 1
fi
IFS="$originalIFS"

View file

@ -5,5 +5,5 @@ brew outdated pkgconfig || brew upgrade pkgconfig
brew install qt brew install qt
brew install ccache brew install ccache
curl -fSL -R -J https://downloads.openmw.org/osx/dependencies/openmw-deps-110f3d3.zip -o ~/openmw-deps.zip curl -fSL -R -J https://downloads.openmw.org/osx/dependencies/openmw-deps-ef2462c.zip -o ~/openmw-deps.zip
unzip -o ~/openmw-deps.zip -d /private/tmp/openmw-deps > /dev/null unzip -o ~/openmw-deps.zip -d /private/tmp/openmw-deps > /dev/null

View file

@ -25,7 +25,6 @@ ${ANALYZE} cmake \
-DBUILD_ESSIMPORTER=${BUILD_OPENMW_CS} \ -DBUILD_ESSIMPORTER=${BUILD_OPENMW_CS} \
-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_UNITTESTS=1 \ -DBUILD_UNITTESTS=1 \
-DUSE_SYSTEM_TINYXML=1 \ -DUSE_SYSTEM_TINYXML=1 \
-DDESIRED_QT_VERSION=5 \ -DDESIRED_QT_VERSION=5 \

View file

@ -1,25 +1,50 @@
#!/bin/bash #!/bin/bash
# set -x # turn-on for debugging # set -x # turn-on for debugging
function wrappedExit {
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
exit $1
else
return $1
fi
}
MISSINGTOOLS=0 MISSINGTOOLS=0
command -v 7z >/dev/null 2>&1 || { echo "Error: 7z (7zip) is not on the path."; MISSINGTOOLS=1; } command -v 7z >/dev/null 2>&1 || { echo "Error: 7z (7zip) is not on the path."; MISSINGTOOLS=1; }
command -v cmake >/dev/null 2>&1 || { echo "Error: cmake (CMake) is not on the path."; MISSINGTOOLS=1; } command -v cmake >/dev/null 2>&1 || { echo "Error: cmake (CMake) is not on the path."; MISSINGTOOLS=1; }
command -v python >/dev/null 2>&1 || { echo "Warning: Python is not on the path, automatic Qt installation impossible."; }
if [ $MISSINGTOOLS -ne 0 ]; then if [ $MISSINGTOOLS -ne 0 ]; then
exit 1 wrappedExit 1
fi fi
WORKINGDIR="$(pwd)" WORKINGDIR="$(pwd)"
case "$WORKINGDIR" in case "$WORKINGDIR" in
*[[:space:]]*) *[[:space:]]*)
echo "Error: Working directory contains spaces." echo "Error: Working directory contains spaces."
exit 1 wrappedExit 1
;; ;;
esac esac
set -euo pipefail set -euo pipefail
function windowsPathAsUnix {
if command -v cygpath >/dev/null 2>&1; then
cygpath -u $1
else
echo "$1" | sed "s,\\\\,/,g" | sed "s,\(.\):,/\\1,"
fi
}
function unixPathAsWindows {
if command -v cygpath >/dev/null 2>&1; then
cygpath -w $1
else
echo "$1" | sed "s,^/\([^/]\)/,\\1:/," | sed "s,/,\\\\,g"
fi
}
APPVEYOR=${APPVEYOR:-} APPVEYOR=${APPVEYOR:-}
CI=${CI:-} CI=${CI:-}
STEP=${STEP:-} STEP=${STEP:-}
@ -32,10 +57,19 @@ KEEP=""
UNITY_BUILD="" UNITY_BUILD=""
VS_VERSION="" VS_VERSION=""
NMAKE="" NMAKE=""
NINJA=""
PDBS=""
PLATFORM="" PLATFORM=""
CONFIGURATION="" CONFIGURATION=""
TEST_FRAMEWORK="" TEST_FRAMEWORK=""
GOOGLE_INSTALL_ROOT="" GOOGLE_INSTALL_ROOT=""
INSTALL_PREFIX="."
BULLET_DOUBLE=""
BULLET_DBL=""
BULLET_DBL_DISPLAY="Single precision"
ACTIVATE_MSVC=""
SINGLE_CONFIG=""
while [ $# -gt 0 ]; do while [ $# -gt 0 ]; do
ARGSTR=$1 ARGSTR=$1
@ -44,7 +78,7 @@ while [ $# -gt 0 ]; do
if [ ${ARGSTR:0:1} != "-" ]; then if [ ${ARGSTR:0:1} != "-" ]; then
echo "Unknown argument $ARGSTR" echo "Unknown argument $ARGSTR"
echo "Try '$0 -h'" echo "Try '$0 -h'"
exit 1 wrappedExit 1
fi fi
for (( i=1; i<${#ARGSTR}; i++ )); do for (( i=1; i<${#ARGSTR}; i++ )); do
@ -56,6 +90,9 @@ while [ $# -gt 0 ]; do
d ) d )
SKIP_DOWNLOAD=true ;; SKIP_DOWNLOAD=true ;;
D )
BULLET_DOUBLE=true ;;
e ) e )
SKIP_EXTRACT=true ;; SKIP_EXTRACT=true ;;
@ -71,11 +108,17 @@ while [ $# -gt 0 ]; do
n ) n )
NMAKE=true ;; NMAKE=true ;;
N )
NINJA=true ;;
p ) p )
PLATFORM=$1 PLATFORM=$1
shift ;; shift ;;
P )
PDBS=true ;;
c ) c )
CONFIGURATION=$1 CONFIGURATION=$1
shift ;; shift ;;
@ -83,14 +126,20 @@ while [ $# -gt 0 ]; do
t ) t )
TEST_FRAMEWORK=true ;; TEST_FRAMEWORK=true ;;
i )
INSTALL_PREFIX=$(echo "$1" | sed 's;\\;/;g' | sed -E 's;/+;/;g')
shift ;;
h ) h )
cat <<EOF cat <<EOF
Usage: $0 [-cdehkpuvV] Usage: $0 [-cdehkpuvVi]
Options: Options:
-c <Release/Debug> -c <Release/Debug>
Set the configuration, can also be set with environment variable CONFIGURATION. Set the configuration, can also be set with environment variable CONFIGURATION.
-d -d
Skip checking the downloads. Skip checking the downloads.
-D
Use double-precision Bullet
-e -e
Skip extracting dependencies. Skip extracting dependencies.
-h -h
@ -106,23 +155,33 @@ Options:
-v <2013/2015/2017/2019> -v <2013/2015/2017/2019>
Choose the Visual Studio version to use. Choose the Visual Studio version to use.
-n -n
Produce NMake makefiles instead of a Visual Studio solution. Produce NMake makefiles instead of a Visual Studio solution. Cannout be used with -N.
-N
Produce Ninja (multi-config if CMake is new enough to support it) files instead of a Visual Studio solution. Cannot be used with -n..
-P
Download debug symbols where available
-V -V
Run verbosely Run verbosely
-i
CMake install prefix
EOF EOF
exit 0 wrappedExit 0
;; ;;
* ) * )
echo "Unknown argument $ARG." echo "Unknown argument $ARG."
echo "Try '$0 -h'" echo "Try '$0 -h'"
exit 1 ;; wrappedExit 1 ;;
esac esac
done done
done done
if [ -n "$NMAKE" ]; then if [ -n "$NMAKE" ] || [ -n "$NINJA" ]; then
command -v nmake -? >/dev/null 2>&1 || { echo "Error: nmake (NMake) is not on the path. Make sure you have the necessary environment variables set for command-line C++ development (for example, by starting from a Developer Command Prompt)."; exit 1; } if [ -n "$NMAKE" ] && [ -n "$NINJA" ]; then
echo "Cannout run in NMake and Ninja mode at the same time."
wrappedExit 1
fi
ACTIVATE_MSVC=true
fi fi
if [ -z $VERBOSE ]; then if [ -z $VERBOSE ]; then
@ -132,7 +191,7 @@ fi
if [ -z $APPVEYOR ]; then if [ -z $APPVEYOR ]; then
echo "Running prebuild outside of Appveyor." echo "Running prebuild outside of Appveyor."
DIR=$(echo "$0" | sed "s,\\\\,/,g" | sed "s,\(.\):,/\\1,") DIR=$(windowsPathAsUnix "${BASH_SOURCE[0]}")
cd $(dirname "$DIR")/.. cd $(dirname "$DIR")/..
else else
echo "Running prebuild in Appveyor." echo "Running prebuild in Appveyor."
@ -257,6 +316,7 @@ case $VS_VERSION in
MSVC_REAL_VER="16" MSVC_REAL_VER="16"
MSVC_VER="14.2" MSVC_VER="14.2"
MSVC_YEAR="2015" MSVC_YEAR="2015"
MSVC_REAL_YEAR="2019"
MSVC_DISPLAY_YEAR="2019" MSVC_DISPLAY_YEAR="2019"
BOOST_VER="1.71.0" BOOST_VER="1.71.0"
BOOST_VER_URL="1_71_0" BOOST_VER_URL="1_71_0"
@ -269,6 +329,7 @@ case $VS_VERSION in
MSVC_REAL_VER="15" MSVC_REAL_VER="15"
MSVC_VER="14.1" MSVC_VER="14.1"
MSVC_YEAR="2015" MSVC_YEAR="2015"
MSVC_REAL_YEAR="2017"
MSVC_DISPLAY_YEAR="2017" MSVC_DISPLAY_YEAR="2017"
BOOST_VER="1.67.0" BOOST_VER="1.67.0"
BOOST_VER_URL="1_67_0" BOOST_VER_URL="1_67_0"
@ -281,6 +342,7 @@ case $VS_VERSION in
MSVC_REAL_VER="14" MSVC_REAL_VER="14"
MSVC_VER="14.0" MSVC_VER="14.0"
MSVC_YEAR="2015" MSVC_YEAR="2015"
MSVC_REAL_YEAR="2015"
MSVC_DISPLAY_YEAR="2015" MSVC_DISPLAY_YEAR="2015"
BOOST_VER="1.67.0" BOOST_VER="1.67.0"
BOOST_VER_URL="1_67_0" BOOST_VER_URL="1_67_0"
@ -288,15 +350,8 @@ case $VS_VERSION in
;; ;;
12|12.0|2013 ) 12|12.0|2013 )
GENERATOR="Visual Studio 12 2013" echo "Visual Studio 2013 is no longer supported"
TOOLSET="vc120" exit 1
MSVC_REAL_VER="12"
MSVC_VER="12.0"
MSVC_YEAR="2013"
MSVC_DISPLAY_YEAR="2013"
BOOST_VER="1.58.0"
BOOST_VER_URL="1_58_0"
BOOST_VER_SDK="105800"
;; ;;
esac esac
@ -315,7 +370,7 @@ case $PLATFORM in
* ) * )
echo "Unknown platform $PLATFORM." echo "Unknown platform $PLATFORM."
exit 1 wrappedExit 1
;; ;;
esac esac
@ -342,9 +397,18 @@ fi
if [ -n "$NMAKE" ]; then if [ -n "$NMAKE" ]; then
GENERATOR="NMake Makefiles" GENERATOR="NMake Makefiles"
SINGLE_CONFIG=true
fi fi
if [ $MSVC_REAL_VER -ge 16 ]; then if [ -n "$NINJA" ]; then
GENERATOR="Ninja Multi-Config"
if ! cmake -E capabilities | grep -F "$GENERATOR" > /dev/null; then
SINGLE_CONFIG=true
GENERATOR="Ninja"
fi
fi
if [ $MSVC_REAL_VER -ge 16 ] && [ -z "$NMAKE" ] && [ -z "$NINJA" ]; then
if [ $BITS -eq 64 ]; then if [ $BITS -eq 64 ]; then
add_cmake_opts "-G\"$GENERATOR\" -A x64" add_cmake_opts "-G\"$GENERATOR\" -A x64"
else else
@ -354,7 +418,7 @@ else
add_cmake_opts "-G\"$GENERATOR\"" add_cmake_opts "-G\"$GENERATOR\""
fi fi
if [ -n "$NMAKE" ]; then if [ -n "$SINGLE_CONFIG" ]; then
add_cmake_opts "-DCMAKE_BUILD_TYPE=${BUILD_CONFIG}" add_cmake_opts "-DCMAKE_BUILD_TYPE=${BUILD_CONFIG}"
fi fi
@ -362,6 +426,12 @@ if ! [ -z $UNITY_BUILD ]; then
add_cmake_opts "-DOPENMW_UNITY_BUILD=True" add_cmake_opts "-DOPENMW_UNITY_BUILD=True"
fi fi
if [ -n "$BULLET_DOUBLE" ]; then
BULLET_DBL="-double"
BULLET_DBL_DISPLAY="Double precision"
add_cmake_opts "-DBULLET_USE_DOUBLES=True"
fi
echo echo
echo "===================================" echo "==================================="
echo "Starting prebuild on MSVC${MSVC_DISPLAY_YEAR} WIN${BITS}" echo "Starting prebuild on MSVC${MSVC_DISPLAY_YEAR} WIN${BITS}"
@ -386,45 +456,54 @@ if [ -z $SKIP_DOWNLOAD ]; then
fi fi
# Bullet # Bullet
download "Bullet 2.86" \ download "Bullet 2.89 (${BULLET_DBL_DISPLAY})" \
"https://www.lysator.liu.se/~ace/OpenMW/deps/Bullet-2.86-msvc${MSVC_YEAR}-win${BITS}.7z" \ "https://rgw.ctrl-c.liu.se/openmw/Deps/Bullet-2.89-msvc${MSVC_YEAR}-win${BITS}${BULLET_DBL}.7z" \
"Bullet-2.86-msvc${MSVC_YEAR}-win${BITS}.7z" "Bullet-2.89-msvc${MSVC_YEAR}-win${BITS}${BULLET_DBL}.7z"
# FFmpeg # FFmpeg
download "FFmpeg 3.2.4" \ download "FFmpeg 4.2.2" \
"https://ffmpeg.zeranoe.com/builds/win${BITS}/shared/ffmpeg-3.2.4-win${BITS}-shared.zip" \ "https://ffmpeg.zeranoe.com/builds/win${BITS}/shared/ffmpeg-4.2.2-win${BITS}-shared.zip" \
"ffmpeg-3.2.4-win${BITS}.zip" \ "ffmpeg-4.2.2-win${BITS}.zip" \
"https://ffmpeg.zeranoe.com/builds/win${BITS}/dev/ffmpeg-3.2.4-win${BITS}-dev.zip" \ "https://ffmpeg.zeranoe.com/builds/win${BITS}/dev/ffmpeg-4.2.2-win${BITS}-dev.zip" \
"ffmpeg-3.2.4-dev-win${BITS}.zip" "ffmpeg-4.2.2-dev-win${BITS}.zip"
# MyGUI # MyGUI
download "MyGUI 3.2.2" \ download "MyGUI 3.4.0" \
"https://www.lysator.liu.se/~ace/OpenMW/deps/MyGUI-3.2.2-msvc${MSVC_YEAR}-win${BITS}.7z" \ "https://rgw.ctrl-c.liu.se/openmw/Deps/MyGUI-3.4.0-msvc${MSVC_REAL_YEAR}-win${BITS}.7z" \
"MyGUI-3.2.2-msvc${MSVC_YEAR}-win${BITS}.7z" "MyGUI-3.4.0-msvc${MSVC_REAL_YEAR}-win${BITS}.7z"
if [ -n "$PDBS" ]; then
download "MyGUI symbols" \
"https://rgw.ctrl-c.liu.se/openmw/Deps/MyGUI-3.4.0-msvc${MSVC_REAL_YEAR}-win${BITS}-sym.7z" \
"MyGUI-3.4.0-msvc${MSVC_REAL_YEAR}-win${BITS}-sym.7z"
fi
# OpenAL # OpenAL
download "OpenAL-Soft 1.19.1" \ download "OpenAL-Soft 1.20.1" \
"http://openal-soft.org/openal-binaries/openal-soft-1.19.1-bin.zip" \ "http://openal-soft.org/openal-binaries/openal-soft-1.20.1-bin.zip" \
"OpenAL-Soft-1.19.1.zip" "OpenAL-Soft-1.20.1.zip"
# OSG # OSG
download "OpenSceneGraph 3.4.1-scrawl" \ download "OpenSceneGraph 3.6.5" \
"https://www.lysator.liu.se/~ace/OpenMW/deps/OSG-3.4.1-scrawl-msvc${MSVC_YEAR}-win${BITS}.7z" \ "https://rgw.ctrl-c.liu.se/openmw/Deps/OSG-3.6.5-msvc${MSVC_REAL_YEAR}-win${BITS}.7z" \
"OSG-3.4.1-scrawl-msvc${MSVC_YEAR}-win${BITS}.7z" "OSG-3.6.5-msvc${MSVC_REAL_YEAR}-win${BITS}.7z"
if [ -n "$PDBS" ]; then
download "OpenSceneGraph symbols" \
"https://rgw.ctrl-c.liu.se/openmw/Deps/OSG-3.6.5-msvc${MSVC_REAL_YEAR}-win${BITS}-sym.7z" \
"OSG-3.6.5-msvc${MSVC_REAL_YEAR}-win${BITS}-sym.7z"
fi
# Qt # Qt
if [ -z $APPVEYOR ]; then if [ -z $APPVEYOR ]; then
if [ $BITS == "64" ]; then if [ "${MSVC_REAL_YEAR}" = "2015" ] && [ "${BITS}" = "32" ]; then
QT_SUFFIX="_64" echo "Qt no longer provides MSVC2015 Win32 packages, switch to 64-bit or a newer Visual Studio. Sorry."
else exit 1
QT_SUFFIX=""
fi fi
download "Qt 5.7.0" \ download "AQt installer" \
"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" \ "https://files.pythonhosted.org/packages/f3/bb/aee972f08deecca31bfc46b5aedfad1ce6c7f3aaf1288d685e4a914b53ac/aqtinstall-0.8-py2.py3-none-any.whl" \
"qt-5.7.0-msvc${MSVC_YEAR}-win${BITS}.exe" \ "aqtinstall-0.8-py2.py3-none-any.whl"
"https://www.lysator.liu.se/~ace/OpenMW/deps/qt-5-install.qs" \
"qt-5-install.qs"
fi fi
# SDL2 # SDL2
@ -449,7 +528,13 @@ cd .. #/..
BUILD_DIR="MSVC${MSVC_DISPLAY_YEAR}_${BITS}" BUILD_DIR="MSVC${MSVC_DISPLAY_YEAR}_${BITS}"
if [ -n "$NMAKE" ]; then if [ -n "$NMAKE" ]; then
BUILD_DIR="${BUILD_DIR}_NMake_${BUILD_CONFIG}" BUILD_DIR="${BUILD_DIR}_NMake"
elif [ -n "$NINJA" ]; then
BUILD_DIR="${BUILD_DIR}_Ninja"
fi
if [ -n "$SINGLE_CONFIG" ]; then
BUILD_DIR="${BUILD_DIR}_${BUILD_CONFIG}"
fi fi
if [ -z $KEEP ]; then if [ -z $KEEP ]; then
@ -487,10 +572,10 @@ fi
# We work around this by installing to root of the current working drive and then move it to our deps # We work around this by installing to root of the current working drive and then move it to our deps
# get the current working drive's root, we'll install to that temporarily # get the current working drive's root, we'll install to that temporarily
CWD_DRIVE_ROOT="$(powershell -command '(get-location).Drive.Root')Boost_temp" CWD_DRIVE_ROOT="$(powershell -command '(get-location).Drive.Root')Boost_temp"
CWD_DRIVE_ROOT_BASH=$(echo "$CWD_DRIVE_ROOT" | sed "s,\\\\,/,g" | sed "s,\(.\):,/\\1,") CWD_DRIVE_ROOT_BASH=$(windowsPathAsUnix "$CWD_DRIVE_ROOT")
if [ -d CWD_DRIVE_ROOT_BASH ]; then if [ -d CWD_DRIVE_ROOT_BASH ]; then
printf "Cannot continue, ${CWD_DRIVE_ROOT_BASH} aka ${CWD_DRIVE_ROOT} already exists. Please remove before re-running. "; printf "Cannot continue, ${CWD_DRIVE_ROOT_BASH} aka ${CWD_DRIVE_ROOT} already exists. Please remove before re-running. ";
exit 1; wrappedExit 1;
fi fi
if [ -d ${BOOST_SDK} ] && grep "BOOST_VERSION ${BOOST_VER_SDK}" Boost/boost/version.hpp > /dev/null; then if [ -d ${BOOST_SDK} ] && grep "BOOST_VERSION ${BOOST_VER_SDK}" Boost/boost/version.hpp > /dev/null; then
@ -526,15 +611,15 @@ fi
cd $DEPS cd $DEPS
echo echo
# Bullet # Bullet
printf "Bullet 2.86... " printf "Bullet 2.89 (${BULLET_DBL_DISPLAY})... "
{ {
cd $DEPS_INSTALL cd $DEPS_INSTALL
if [ -d Bullet ]; then if [ -d Bullet ]; then
printf -- "Exists. (No version checking) " printf -- "Exists. (No version checking) "
elif [ -z $SKIP_EXTRACT ]; then elif [ -z $SKIP_EXTRACT ]; then
rm -rf Bullet rm -rf Bullet
eval 7z x -y "${DEPS}/Bullet-2.86-msvc${MSVC_YEAR}-win${BITS}.7z" $STRIP eval 7z x -y "${DEPS}/Bullet-2.89-msvc${MSVC_YEAR}-win${BITS}${BULLET_DBL}.7z" $STRIP
mv "Bullet-2.86-msvc${MSVC_YEAR}-win${BITS}" Bullet mv "Bullet-2.89-msvc${MSVC_YEAR}-win${BITS}${BULLET_DBL}" Bullet
fi fi
export BULLET_ROOT="$(real_pwd)/Bullet" export BULLET_ROOT="$(real_pwd)/Bullet"
echo Done. echo Done.
@ -542,21 +627,21 @@ printf "Bullet 2.86... "
cd $DEPS cd $DEPS
echo echo
# FFmpeg # FFmpeg
printf "FFmpeg 3.2.4... " printf "FFmpeg 4.2.2... "
{ {
cd $DEPS_INSTALL cd $DEPS_INSTALL
if [ -d FFmpeg ] && grep "FFmpeg version: 3.2.4" FFmpeg/README.txt > /dev/null; then if [ -d FFmpeg ] && grep "4.2.2" FFmpeg/README.txt > /dev/null; then
printf "Exists. " printf "Exists. "
elif [ -z $SKIP_EXTRACT ]; then elif [ -z $SKIP_EXTRACT ]; then
rm -rf FFmpeg rm -rf FFmpeg
eval 7z x -y "${DEPS}/ffmpeg-3.2.4-win${BITS}.zip" $STRIP eval 7z x -y "${DEPS}/ffmpeg-4.2.2-win${BITS}.zip" $STRIP
eval 7z x -y "${DEPS}/ffmpeg-3.2.4-dev-win${BITS}.zip" $STRIP eval 7z x -y "${DEPS}/ffmpeg-4.2.2-dev-win${BITS}.zip" $STRIP
mv "ffmpeg-3.2.4-win${BITS}-shared" FFmpeg mv "ffmpeg-4.2.2-win${BITS}-shared" FFmpeg
cp -r "ffmpeg-3.2.4-win${BITS}-dev/"* FFmpeg/ cp -r "ffmpeg-4.2.2-win${BITS}-dev/"* FFmpeg/
rm -rf "ffmpeg-3.2.4-win${BITS}-dev" rm -rf "ffmpeg-4.2.2-win${BITS}-dev"
fi fi
export FFMPEG_HOME="$(real_pwd)/FFmpeg" export FFMPEG_HOME="$(real_pwd)/FFmpeg"
add_runtime_dlls "$(pwd)/FFmpeg/bin/"{avcodec-57,avformat-57,avutil-55,swresample-2,swscale-4}.dll add_runtime_dlls "$(pwd)/FFmpeg/bin/"{avcodec-58,avformat-58,avutil-56,swresample-3,swscale-5}.dll
if [ $BITS -eq 32 ]; then if [ $BITS -eq 32 ]; then
add_cmake_opts "-DCMAKE_EXE_LINKER_FLAGS=\"/machine:X86 /safeseh:no\"" add_cmake_opts "-DCMAKE_EXE_LINKER_FLAGS=\"/machine:X86 /safeseh:no\""
fi fi
@ -565,62 +650,66 @@ printf "FFmpeg 3.2.4... "
cd $DEPS cd $DEPS
echo echo
# MyGUI # MyGUI
printf "MyGUI 3.2.2... " printf "MyGUI 3.4.0... "
{ {
cd $DEPS_INSTALL cd $DEPS_INSTALL
if [ -d MyGUI ] && \ if [ -d MyGUI ] && \
grep "MYGUI_VERSION_MAJOR 3" MyGUI/include/MYGUI/MyGUI_Prerequest.h > /dev/null && \ grep "MYGUI_VERSION_MAJOR 3" MyGUI/include/MYGUI/MyGUI_Prerequest.h > /dev/null && \
grep "MYGUI_VERSION_MINOR 2" MyGUI/include/MYGUI/MyGUI_Prerequest.h > /dev/null && \ grep "MYGUI_VERSION_MINOR 4" MyGUI/include/MYGUI/MyGUI_Prerequest.h > /dev/null && \
grep "MYGUI_VERSION_PATCH 2" MyGUI/include/MYGUI/MyGUI_Prerequest.h > /dev/null grep "MYGUI_VERSION_PATCH 0" MyGUI/include/MYGUI/MyGUI_Prerequest.h > /dev/null
then then
printf "Exists. " printf "Exists. "
elif [ -z $SKIP_EXTRACT ]; then elif [ -z $SKIP_EXTRACT ]; then
rm -rf MyGUI rm -rf MyGUI
eval 7z x -y "${DEPS}/MyGUI-3.2.2-msvc${MSVC_YEAR}-win${BITS}.7z" $STRIP eval 7z x -y "${DEPS}/MyGUI-3.4.0-msvc${MSVC_REAL_YEAR}-win${BITS}.7z" $STRIP
mv "MyGUI-3.2.2-msvc${MSVC_YEAR}-win${BITS}" MyGUI [ -n "$PDBS" ] && eval 7z x -y "${DEPS}/MyGUI-3.4.0-msvc${MSVC_REAL_YEAR}-win${BITS}-sym.7z" $STRIP
mv "MyGUI-3.4.0-msvc${MSVC_REAL_YEAR}-win${BITS}" MyGUI
fi fi
export MYGUI_HOME="$(real_pwd)/MyGUI" export MYGUI_HOME="$(real_pwd)/MyGUI"
if [ $CONFIGURATION == "Debug" ]; then if [ $CONFIGURATION == "Debug" ]; then
SUFFIX="_d" SUFFIX="_d"
MYGUI_CONFIGURATION="Debug"
else else
SUFFIX="" SUFFIX=""
MYGUI_CONFIGURATION="RelWithDebInfo"
fi fi
add_runtime_dlls "$(pwd)/MyGUI/bin/${CONFIGURATION}/MyGUIEngine${SUFFIX}.dll" add_runtime_dlls "$(pwd)/MyGUI/bin/${MYGUI_CONFIGURATION}/MyGUIEngine${SUFFIX}.dll"
echo Done. echo Done.
} }
cd $DEPS cd $DEPS
echo echo
# OpenAL # OpenAL
printf "OpenAL-Soft 1.19.1... " printf "OpenAL-Soft 1.20.1... "
{ {
if [ -d openal-soft-1.19.1-bin ]; then if [ -d openal-soft-1.20.1-bin ]; then
printf "Exists. " printf "Exists. "
elif [ -z $SKIP_EXTRACT ]; then elif [ -z $SKIP_EXTRACT ]; then
rm -rf openal-soft-1.19.1-bin rm -rf openal-soft-1.20.1-bin
eval 7z x -y OpenAL-Soft-1.19.1.zip $STRIP eval 7z x -y OpenAL-Soft-1.20.1.zip $STRIP
fi fi
OPENAL_SDK="$(real_pwd)/openal-soft-1.19.1-bin" OPENAL_SDK="$(real_pwd)/openal-soft-1.20.1-bin"
add_cmake_opts -DOPENAL_INCLUDE_DIR="${OPENAL_SDK}/include/AL" \ add_cmake_opts -DOPENAL_INCLUDE_DIR="${OPENAL_SDK}/include/AL" \
-DOPENAL_LIBRARY="${OPENAL_SDK}/libs/Win${BITS}/OpenAL32.lib" -DOPENAL_LIBRARY="${OPENAL_SDK}/libs/Win${BITS}/OpenAL32.lib"
add_runtime_dlls "$(pwd)/openal-soft-1.19.1-bin/bin/WIN${BITS}/soft_oal.dll:OpenAL32.dll" add_runtime_dlls "$(pwd)/openal-soft-1.20.1-bin/bin/WIN${BITS}/soft_oal.dll:OpenAL32.dll"
echo Done. echo Done.
} }
cd $DEPS cd $DEPS
echo echo
# OSG # OSG
printf "OSG 3.4.1-scrawl... " printf "OSG 3.6.5... "
{ {
cd $DEPS_INSTALL cd $DEPS_INSTALL
if [ -d OSG ] && \ if [ -d OSG ] && \
grep "OPENSCENEGRAPH_MAJOR_VERSION 3" OSG/include/osg/Version > /dev/null && \ grep "OPENSCENEGRAPH_MAJOR_VERSION 3" OSG/include/osg/Version > /dev/null && \
grep "OPENSCENEGRAPH_MINOR_VERSION 4" OSG/include/osg/Version > /dev/null && \ grep "OPENSCENEGRAPH_MINOR_VERSION 6" OSG/include/osg/Version > /dev/null && \
grep "OPENSCENEGRAPH_PATCH_VERSION 1" OSG/include/osg/Version > /dev/null grep "OPENSCENEGRAPH_PATCH_VERSION 5" OSG/include/osg/Version > /dev/null
then then
printf "Exists. " printf "Exists. "
elif [ -z $SKIP_EXTRACT ]; then elif [ -z $SKIP_EXTRACT ]; then
rm -rf OSG rm -rf OSG
eval 7z x -y "${DEPS}/OSG-3.4.1-scrawl-msvc${MSVC_YEAR}-win${BITS}.7z" $STRIP eval 7z x -y "${DEPS}/OSG-3.6.5-msvc${MSVC_REAL_YEAR}-win${BITS}.7z" $STRIP
mv "OSG-3.4.1-scrawl-msvc${MSVC_YEAR}-win${BITS}" OSG [ -n "$PDBS" ] && eval 7z x -y "${DEPS}/OSG-3.6.5-msvc${MSVC_REAL_YEAR}-win${BITS}-sym.7z" $STRIP
mv "OSG-3.6.5-msvc${MSVC_REAL_YEAR}-win${BITS}" OSG
fi fi
OSG_SDK="$(real_pwd)/OSG" OSG_SDK="$(real_pwd)/OSG"
add_cmake_opts -DOSG_DIR="$OSG_SDK" add_cmake_opts -DOSG_DIR="$OSG_SDK"
@ -629,17 +718,17 @@ printf "OSG 3.4.1-scrawl... "
else else
SUFFIX="" SUFFIX=""
fi fi
add_runtime_dlls "$(pwd)/OSG/bin/"{OpenThreads,zlib,libpng*}${SUFFIX}.dll \ add_runtime_dlls "$(pwd)/OSG/bin/"{OpenThreads,zlib,libpng}${SUFFIX}.dll \
"$(pwd)/OSG/bin/osg"{,Animation,DB,FX,GA,Particle,Text,Util,Viewer,Shadow}${SUFFIX}.dll "$(pwd)/OSG/bin/osg"{,Animation,DB,FX,GA,Particle,Text,Util,Viewer,Shadow}${SUFFIX}.dll
add_osg_dlls "$(pwd)/OSG/bin/osgPlugins-3.4.1/osgdb_"{bmp,dds,freetype,jpeg,osg,png,tga}${SUFFIX}.dll add_osg_dlls "$(pwd)/OSG/bin/osgPlugins-3.6.5/osgdb_"{bmp,dds,freetype,jpeg,osg,png,tga}${SUFFIX}.dll
add_osg_dlls "$(pwd)/OSG/bin/osgPlugins-3.4.1/osgdb_serializers_osg"{,animation,fx,ga,particle,text,util,viewer,shadow}${SUFFIX}.dll add_osg_dlls "$(pwd)/OSG/bin/osgPlugins-3.6.5/osgdb_serializers_osg"{,animation,fx,ga,particle,text,util,viewer,shadow}${SUFFIX}.dll
echo Done. echo Done.
} }
cd $DEPS cd $DEPS
echo echo
# Qt # Qt
if [ -z $APPVEYOR ]; then if [ -z $APPVEYOR ]; then
printf "Qt 5.7.0... " printf "Qt 5.15.0... "
else else
printf "Qt 5.13 AppVeyor... " printf "Qt 5.13 AppVeyor... "
fi fi
@ -651,21 +740,44 @@ fi
fi fi
if [ -z $APPVEYOR ]; then if [ -z $APPVEYOR ]; then
cd $DEPS_INSTALL cd $DEPS_INSTALL
QT_SDK="$(real_pwd)/Qt/5.7/msvc${MSVC_YEAR}${SUFFIX}" QT_SDK="$(real_pwd)/Qt/5.15.0/msvc${MSVC_REAL_YEAR}${SUFFIX}"
if [ -d Qt ] && head -n2 Qt/InstallationLog.txt | grep "5.7.0" > /dev/null; then
if [ -d 'Qt/5.15.0' ]; then
printf "Exists. " printf "Exists. "
elif [ -z $SKIP_EXTRACT ]; then elif [ -z $SKIP_EXTRACT ]; then
pushd "$DEPS" > /dev/null
if ! [ -d 'aqt-venv' ]; then
echo " Creating Virtualenv for aqt..."
eval python -m venv aqt-venv $STRIP
fi
if [ -d 'aqt-venv/bin' ]; then
VENV_BIN_DIR='bin'
elif [ -d 'aqt-venv/Scripts' ]; then
VENV_BIN_DIR='Scripts'
else
echo "Error: Failed to create virtualenv."
exit 1
fi
if ! [ -e "aqt-venv/${VENV_BIN_DIR}/aqt" ]; then
echo " Installing aqt wheel into virtualenv..."
eval "aqt-venv/${VENV_BIN_DIR}/pip" install aqtinstall-0.8-py2.py3-none-any.whl $STRIP
fi
popd > /dev/null
rm -rf Qt rm -rf Qt
cp "${DEPS}/qt-5-install.qs" qt-install.qs
sed -i "s|INSTALL_DIR|$(real_pwd)/Qt|" qt-install.qs mkdir Qt
sed -i "s/qt.VERSION.winBITS_msvcYEAR/qt.57.win${BITS}_msvc${MSVC_YEAR}${SUFFIX}/" qt-install.qs cd Qt
printf -- "(Installation might take a while) "
"${DEPS}/qt-5.7.0-msvc${MSVC_YEAR}-win${BITS}.exe" --script qt-install.qs --silent eval "${DEPS}/aqt-venv/${VENV_BIN_DIR}/aqt" install 5.15.0 windows desktop "win${BITS}_msvc${MSVC_REAL_YEAR}${SUFFIX}" $STRIP
mv qt-install.qs Qt/
echo Done.
printf " Cleaning up extraneous data... " printf " Cleaning up extraneous data... "
rm -r "$(real_pwd)/Qt/"{dist,Docs,Examples,Tools,vcredist,components.xml,MaintenanceTool.dat,MaintenanceTool.exe,MaintenanceTool.ini,network.xml,qt-install.qs} rm -rf Qt/{aqtinstall.log,Tools}
echo Done.
fi fi
cd $QT_SDK cd $QT_SDK
add_cmake_opts -DDESIRED_QT_VERSION=5 \ add_cmake_opts -DDESIRED_QT_VERSION=5 \
-DQT_QMAKE_EXECUTABLE="${QT_SDK}/bin/qmake.exe" \ -DQT_QMAKE_EXECUTABLE="${QT_SDK}/bin/qmake.exe" \
@ -688,7 +800,7 @@ fi
else else
SUFFIX="" SUFFIX=""
fi fi
DIR=$(echo "${QT_SDK}" | sed "s,\\\\,/,g" | sed "s,\(.\):,/\\1,") DIR=$(windowsPathAsUnix "${QT_SDK}")
add_runtime_dlls "${DIR}/bin/Qt5"{Core,Gui,Network,OpenGL,Widgets}${SUFFIX}.dll add_runtime_dlls "${DIR}/bin/Qt5"{Core,Gui,Network,OpenGL,Widgets}${SUFFIX}.dll
add_qt_platform_dlls "${DIR}/plugins/platforms/qwindows${SUFFIX}.dll" add_qt_platform_dlls "${DIR}/plugins/platforms/qwindows${SUFFIX}.dll"
echo Done. echo Done.
@ -759,10 +871,8 @@ echo
cd $DEPS_INSTALL/.. cd $DEPS_INSTALL/..
echo echo
echo "Setting up OpenMW build..." echo "Setting up OpenMW build..."
add_cmake_opts -DBUILD_BSATOOL=no \ add_cmake_opts -DOPENMW_MP_BUILD=on
-DBUILD_ESMTOOL=no \ add_cmake_opts -DCMAKE_INSTALL_PREFIX="${INSTALL_PREFIX}"
-DBUILD_MYGUI_PLUGIN=no \
-DOPENMW_MP_BUILD=on
if [ ! -z $CI ]; then if [ ! -z $CI ]; then
case $STEP in case $STEP in
components ) components )
@ -801,14 +911,15 @@ fi
#if [ -z $CI ]; then #if [ -z $CI ]; then
echo "- Copying Runtime DLLs..." echo "- Copying Runtime DLLs..."
DLL_PREFIX="" DLL_PREFIX=""
if [ -z $NMAKE ]; then if [ -z $SINGLE_CONFIG ]; then
mkdir -p $BUILD_CONFIG mkdir -p $BUILD_CONFIG
DLL_PREFIX="$BUILD_CONFIG/" DLL_PREFIX="$BUILD_CONFIG/"
fi fi
for DLL in $RUNTIME_DLLS; do for DLL in $RUNTIME_DLLS; do
TARGET="$(basename "$DLL")" TARGET="$(basename "$DLL")"
if [[ "$DLL" == *":"* ]]; then if [[ "$DLL" == *":"* ]]; then
IFS=':'; SPLIT=( ${DLL} ); unset IFS originalIFS="$IFS"
IFS=':'; SPLIT=( ${DLL} ); IFS=$originalIFS
DLL=${SPLIT[0]} DLL=${SPLIT[0]}
TARGET=${SPLIT[1]} TARGET=${SPLIT[1]}
fi fi
@ -817,10 +928,10 @@ fi
done done
echo echo
echo "- OSG Plugin DLLs..." echo "- OSG Plugin DLLs..."
mkdir -p ${DLL_PREFIX}osgPlugins-3.4.1 mkdir -p ${DLL_PREFIX}osgPlugins-3.6.5
for DLL in $OSG_PLUGINS; do for DLL in $OSG_PLUGINS; do
echo " $(basename $DLL)." echo " $(basename $DLL)."
cp "$DLL" ${DLL_PREFIX}osgPlugins-3.4.1 cp "$DLL" ${DLL_PREFIX}osgPlugins-3.6.5
done done
echo echo
echo "- Qt Platform DLLs..." echo "- Qt Platform DLLs..."
@ -831,6 +942,42 @@ fi
done done
echo echo
#fi #fi
if ! [ -z $ACTIVATE_MSVC ]; then
echo -n "- Activating MSVC in the current shell... "
command -v vswhere >/dev/null 2>&1 || { echo "Error: vswhere is not on the path."; wrappedExit 1; }
MSVC_INSTALLATION_PATH=$(vswhere -legacy -version "[$MSVC_VER,$(awk "BEGIN { print $MSVC_REAL_VER + 1; exit }"))" -property installationPath)
if [ $MSVC_REAL_VER -ge 15 ]; then
echo "@\"${MSVC_INSTALLATION_PATH}\Common7\Tools\VsDevCmd.bat\" -no_logo -arch=$([ $BITS -eq 64 ] && echo "amd64" || echo "x86") -host_arch=$([ $(uname -m) == 'x86_64' ] && echo "amd64" || echo "x86")" > ActivateMSVC.bat
else
if [ $(uname -m) == 'x86_64' ]; then
if [ $BITS -eq 64 ]; then
compiler=amd64
else
compiler=amd64_x86
fi
else
if [ $BITS -eq 64 ]; then
compiler=x86_amd64
else
compiler=x86
fi
fi
echo "@\"${MSVC_INSTALLATION_PATH}\VC\vcvarsall.bat\" $compiler" > ActivateMSVC.bat
fi
cp "../CI/activate_msvc.sh" .
sed -i "s/\$MSVC_DISPLAY_YEAR/$MSVC_DISPLAY_YEAR/g" activate_msvc.sh
source ./activate_msvc.sh
cp "../CI/ActivateMSVC.ps1" .
sed -i "s/\$MSVC_DISPLAY_YEAR/$MSVC_DISPLAY_YEAR/g" ActivateMSVC.ps1
echo "done."
echo
fi
if [ -z $VERBOSE ]; then if [ -z $VERBOSE ]; then
printf -- "- Configuring... " printf -- "- Configuring... "
else else
@ -841,8 +988,34 @@ RET=$?
if [ -z $VERBOSE ]; then if [ -z $VERBOSE ]; then
if [ $RET -eq 0 ]; then if [ $RET -eq 0 ]; then
echo Done. echo Done.
if [ -n $ACTIVATE_MSVC ]; then
echo
echo "Note: you must manually activate MSVC for the shell in which you want to do the build."
echo
echo "Some scripts have been created in the build directory to do so in an existing shell."
echo "Bash: source activate_msvc.sh"
echo "CMD: ActivateMSVC.bat"
echo "PowerShell: ActivateMSVC.ps1"
echo
echo "You may find options to launch a Development/Native Tools/Cross Tools shell in your start menu or Visual Studio."
echo
if [ $(uname -m) == 'x86_64' ]; then
if [ $BITS -eq 64 ]; then
inheritEnvironments=msvc_x64_x64
else
inheritEnvironments=msvc_x64
fi
else
if [ $BITS -eq 64 ]; then
inheritEnvironments=msvc_x86_x64
else
inheritEnvironments=msvc_x86
fi
fi
echo "In Visual Studio 15.3 (2017 Update 3) or later, try setting '\"inheritEnvironments\": [ \"$inheritEnvironments\" ]' in CMakeSettings.json to build in the IDE."
fi
else else
echo Failed. echo Failed.
fi fi
fi fi
exit $RET wrappedExit $RET

View file

@ -19,6 +19,5 @@ cmake \
-D OPENMW_OSX_DEPLOYMENT=TRUE \ -D OPENMW_OSX_DEPLOYMENT=TRUE \
-D DESIRED_QT_VERSION=5 \ -D DESIRED_QT_VERSION=5 \
-D BUILD_ESMTOOL=FALSE \ -D BUILD_ESMTOOL=FALSE \
-D BUILD_MYGUI_PLUGIN=FALSE \
-G"Unix Makefiles" \ -G"Unix Makefiles" \
.. ..

View file

@ -1,6 +1,6 @@
#!/bin/sh -e #!/bin/sh -e
git clone -b release-1.8.1 https://github.com/google/googletest.git git clone -b release-1.10.0 https://github.com/google/googletest.git
cd googletest cd googletest
mkdir build mkdir build
cd build cd build

View file

@ -8,11 +8,11 @@ option(BUILD_ESSIMPORTER "Build ESS (Morrowind save game) importer" ON)
option(BUILD_BSATOOL "Build BSA extractor" ON) option(BUILD_BSATOOL "Build BSA extractor" ON)
option(BUILD_ESMTOOL "Build ESM inspector" ON) option(BUILD_ESMTOOL "Build ESM inspector" ON)
option(BUILD_NIFTEST "Build nif file tester" ON) option(BUILD_NIFTEST "Build nif file tester" ON)
option(BUILD_MYGUI_PLUGIN "Build MyGUI plugin for OpenMW resources, to use with MyGUI tools" ON)
option(BUILD_DOCS "Build documentation." OFF) option(BUILD_DOCS "Build documentation." OFF)
option(BUILD_VR_OPENXR "Build VR support using OpenXR" on) option(BUILD_VR_OPENXR "Build VR support using OpenXR" on)
option(BUILD_WITH_CODE_COVERAGE "Enable code coverage with gconv" OFF) option(BUILD_WITH_CODE_COVERAGE "Enable code coverage with gconv" OFF)
option(BUILD_UNITTESTS "Enable Unittests with Google C++ Unittest" OFF) option(BUILD_UNITTESTS "Enable Unittests with Google C++ Unittest" OFF)
option(BULLET_USE_DOUBLES "Use double precision for Bullet" OFF)
if (NOT BUILD_LAUNCHER AND NOT BUILD_OPENCS AND NOT BUILD_WIZARD) if (NOT BUILD_LAUNCHER AND NOT BUILD_OPENCS AND NOT BUILD_WIZARD)
set(USE_QT FALSE) set(USE_QT FALSE)
@ -55,7 +55,7 @@ endif()
message(STATUS "Configuring OpenMW...") message(STATUS "Configuring OpenMW...")
set(OPENMW_VERSION_MAJOR 0) set(OPENMW_VERSION_MAJOR 0)
set(OPENMW_VERSION_MINOR 46) set(OPENMW_VERSION_MINOR 47)
set(OPENMW_VERSION_RELEASE 0) set(OPENMW_VERSION_RELEASE 0)
set(OPENMW_VERSION_COMMITHASH "") set(OPENMW_VERSION_COMMITHASH "")
@ -64,6 +64,8 @@ set(OPENMW_VERSION_COMMITDATE "")
set(OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}") set(OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")
set(OPENMW_DOC_BASEURL "https://openmw.readthedocs.io/en/master/")
set(GIT_CHECKOUT FALSE) set(GIT_CHECKOUT FALSE)
if(EXISTS ${PROJECT_SOURCE_DIR}/.git) if(EXISTS ${PROJECT_SOURCE_DIR}/.git)
find_package(Git) find_package(Git)
@ -322,7 +324,7 @@ set(Boost_NO_BOOST_CMAKE ON)
find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS}) find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS})
find_package(MyGUI 3.2.2 REQUIRED) find_package(MyGUI 3.2.2 REQUIRED)
find_package(SDL2 REQUIRED) find_package(SDL2 2.0.9 REQUIRED)
find_package(OpenAL REQUIRED) find_package(OpenAL REQUIRED)
find_package(Bullet ${REQUIRED_BULLET_VERSION} REQUIRED COMPONENTS BulletCollision LinearMath) find_package(Bullet ${REQUIRED_BULLET_VERSION} REQUIRED COMPONENTS BulletCollision LinearMath)
@ -404,19 +406,13 @@ copy_resource_file(${OpenMW_SOURCE_DIR}/files/opencs/defaultfilters
configure_resource_file(${OpenMW_SOURCE_DIR}/files/gamecontrollerdb.txt configure_resource_file(${OpenMW_SOURCE_DIR}/files/gamecontrollerdb.txt
"${OpenMW_BINARY_DIR}" "gamecontrollerdb.txt") "${OpenMW_BINARY_DIR}" "gamecontrollerdb.txt")
configure_resource_file(${OpenMW_SOURCE_DIR}/files/gamecontrollerdb_204.txt
"${OpenMW_BINARY_DIR}" "gamecontrollerdb_204.txt")
configure_resource_file(${OpenMW_SOURCE_DIR}/files/gamecontrollerdb_205.txt
"${OpenMW_BINARY_DIR}" "gamecontrollerdb_205.txt")
if (NOT WIN32 AND NOT APPLE) if (NOT WIN32 AND NOT APPLE)
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.desktop configure_file(${OpenMW_SOURCE_DIR}/files/org.openmw.launcher.desktop
"${OpenMW_BINARY_DIR}/openmw.desktop") "${OpenMW_BINARY_DIR}/org.openmw.launcher.desktop")
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.appdata.xml configure_file(${OpenMW_SOURCE_DIR}/files/openmw.appdata.xml
"${OpenMW_BINARY_DIR}/openmw.appdata.xml") "${OpenMW_BINARY_DIR}/openmw.appdata.xml")
configure_file(${OpenMW_SOURCE_DIR}/files/openmw-cs.desktop configure_file(${OpenMW_SOURCE_DIR}/files/org.openmw.cs.desktop
"${OpenMW_BINARY_DIR}/openmw-cs.desktop") "${OpenMW_BINARY_DIR}/org.openmw.cs.desktop")
endif() endif()
# CXX Compiler settings # CXX Compiler settings
@ -482,19 +478,16 @@ IF(NOT WIN32 AND NOT APPLE)
IF(BUILD_WIZARD) IF(BUILD_WIZARD)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw-wizard" DESTINATION "${BINDIR}" ) INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw-wizard" DESTINATION "${BINDIR}" )
ENDIF(BUILD_WIZARD) ENDIF(BUILD_WIZARD)
#if(BUILD_MYGUI_PLUGIN)
# INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Plugin_MyGUI_OpenMW_Resources.so" DESTINATION "${LIBDIR}" )
#ENDIF(BUILD_MYGUI_PLUGIN)
# Install licenses # Install licenses
INSTALL(FILES "files/mygui/DejaVu Font License.txt" DESTINATION "${LICDIR}" ) INSTALL(FILES "files/mygui/DejaVu Font License.txt" DESTINATION "${LICDIR}" )
# Install icon and desktop file # Install icon and desktop file
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.desktop" DESTINATION "${DATAROOTDIR}/applications" COMPONENT "openmw") INSTALL(FILES "${OpenMW_BINARY_DIR}/org.openmw.launcher.desktop" DESTINATION "${DATAROOTDIR}/applications" COMPONENT "openmw")
INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.png" DESTINATION "${ICONDIR}" COMPONENT "openmw") INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.png" DESTINATION "${ICONDIR}" COMPONENT "openmw")
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.appdata.xml" DESTINATION "${DATAROOTDIR}/metainfo" COMPONENT "openmw") INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.appdata.xml" DESTINATION "${DATAROOTDIR}/metainfo" COMPONENT "openmw")
IF(BUILD_OPENCS) IF(BUILD_OPENCS)
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw-cs.desktop" DESTINATION "${DATAROOTDIR}/applications" COMPONENT "opencs") INSTALL(FILES "${OpenMW_BINARY_DIR}/org.openmw.cs.desktop" DESTINATION "${DATAROOTDIR}/applications" COMPONENT "opencs")
INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/opencs/openmw-cs.png" DESTINATION "${ICONDIR}" COMPONENT "opencs") INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/opencs/openmw-cs.png" DESTINATION "${ICONDIR}" COMPONENT "opencs")
ENDIF(BUILD_OPENCS) ENDIF(BUILD_OPENCS)
@ -503,8 +496,6 @@ IF(NOT WIN32 AND NOT APPLE)
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "${SYSCONFDIR}" RENAME "openmw.cfg" COMPONENT "openmw") INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "${SYSCONFDIR}" RENAME "openmw.cfg" COMPONENT "openmw")
INSTALL(FILES "${OpenMW_BINARY_DIR}/resources/version" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw") INSTALL(FILES "${OpenMW_BINARY_DIR}/resources/version" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")
INSTALL(FILES "${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw") INSTALL(FILES "${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")
INSTALL(FILES "${OpenMW_BINARY_DIR}/gamecontrollerdb_204.txt" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")
INSTALL(FILES "${OpenMW_BINARY_DIR}/gamecontrollerdb_205.txt" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")
IF(BUILD_OPENCS) IF(BUILD_OPENCS)
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw-cs.cfg" DESTINATION "${SYSCONFDIR}" COMPONENT "opencs") INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw-cs.cfg" DESTINATION "${SYSCONFDIR}" COMPONENT "opencs")
@ -532,15 +523,6 @@ if(WIN32)
INSTALL(FILES "${OpenMW_BINARY_DIR}/Release/settings-default.cfg" DESTINATION "." CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel) INSTALL(FILES "${OpenMW_BINARY_DIR}/Release/settings-default.cfg" DESTINATION "." CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel)
INSTALL(FILES "${OpenMW_BINARY_DIR}/Debug/gamecontrollerdb.txt" DESTINATION "." CONFIGURATIONS Debug) INSTALL(FILES "${OpenMW_BINARY_DIR}/Debug/gamecontrollerdb.txt" DESTINATION "." CONFIGURATIONS Debug)
INSTALL(FILES "${OpenMW_BINARY_DIR}/Release/gamecontrollerdb.txt" DESTINATION "." CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel) INSTALL(FILES "${OpenMW_BINARY_DIR}/Release/gamecontrollerdb.txt" DESTINATION "." CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel)
INSTALL(FILES "${OpenMW_BINARY_DIR}/Debug/gamecontrollerdb_204.txt" DESTINATION "." CONFIGURATIONS Debug)
INSTALL(FILES "${OpenMW_BINARY_DIR}/Release/gamecontrollerdb_204.txt" DESTINATION "." CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel)
INSTALL(FILES "${OpenMW_BINARY_DIR}/Debug/gamecontrollerdb_205.txt" DESTINATION "." CONFIGURATIONS Debug)
INSTALL(FILES "${OpenMW_BINARY_DIR}/Release/gamecontrollerdb_205.txt" DESTINATION "." CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel)
if(BUILD_MYGUI_PLUGIN)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Debug/Plugin_MyGUI_OpenMW_Resources.dll" DESTINATION "." CONFIGURATIONS Debug)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Release/Plugin_MyGUI_OpenMW_Resources.dll" DESTINATION "." CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel)
ENDIF(BUILD_MYGUI_PLUGIN)
IF(DESIRED_QT_VERSION MATCHES 5) IF(DESIRED_QT_VERSION MATCHES 5)
INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/Debug/platforms" DESTINATION "." CONFIGURATIONS Debug) INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/Debug/platforms" DESTINATION "." CONFIGURATIONS Debug)
@ -627,6 +609,7 @@ endif()
# Components # Components
add_subdirectory (components) add_subdirectory (components)
target_compile_definitions(components PRIVATE OPENMW_DOC_BASEURL="${OPENMW_DOC_BASEURL}")
# Apps and tools # Apps and tools
if (BUILD_OPENMW) if (BUILD_OPENMW)
@ -743,6 +726,7 @@ if (WIN32)
# caused by boost # caused by boost
4191 # 'type cast' : unsafe conversion (1.56, thread_primitives.hpp, normally off) 4191 # 'type cast' : unsafe conversion (1.56, thread_primitives.hpp, normally off)
4643 # Forward declaring 'X' in namespace std is not permitted by the C++ Standard. (in *_std_fwd.h files) 4643 # Forward declaring 'X' in namespace std is not permitted by the C++ Standard. (in *_std_fwd.h files)
5204 # Class has virtual functions, but its trivial destructor is not virtual
# caused by MyGUI # caused by MyGUI
4275 # non dll-interface class 'std::exception' used as base for dll-interface class 'MyGUI::Exception' 4275 # non dll-interface class 'std::exception' used as base for dll-interface class 'MyGUI::Exception'
@ -956,4 +940,3 @@ if (DOXYGEN_FOUND)
WORKING_DIRECTORY ${OpenMW_BINARY_DIR} WORKING_DIRECTORY ${OpenMW_BINARY_DIR}
COMMENT "Generating documentation for the github-pages at ${DOXYGEN_PAGES_OUTPUT_DIR}" VERBATIM) COMMENT "Generating documentation for the github-pages at ${DOXYGEN_PAGES_OUTPUT_DIR}" VERBATIM)
endif () endif ()

View file

@ -21,7 +21,7 @@ Pull Request Guidelines
To facilitate the review process, your pull request description should include the following, if applicable: To facilitate the review process, your pull request description should include the following, if applicable:
* A link back to the bug report or forum discussion that prompted the change. Note: when linking bugs, use the syntax ```[Bug #xyz](https://bugs.openmw.org/issues/#xyz)``` to create a clickable link. Writing only 'Bug #xyz' will unfortunately create a link to the Github pull request with that number instead. * A link back to the bug report or forum discussion that prompted the change. Note: when linking bugs, use the syntax ```[Bug #xyz](https://gitlab.com/OpenMW/openmw/issues/#xyz)``` to create a clickable link. Writing only 'Bug #xyz' will unfortunately create a link to the Github pull request with that number instead.
* Summary of the changes made * Summary of the changes made
* Reasoning / motivation behind the change * Reasoning / motivation behind the change
* What testing you have carried out to verify the change * What testing you have carried out to verify the change

View file

@ -7,7 +7,7 @@ OpenMW is an open-source game engine that supports playing Morrowind by Bethesda
OpenMW also comes with OpenMW-CS, a replacement for Bethesda's Construction Set. OpenMW also comes with OpenMW-CS, a replacement for Bethesda's Construction Set.
* Version: 0.46.0 * Version: 0.47.0
* License: GPLv3 (see [LICENSE](https://github.com/OpenMW/openmw/blob/master/LICENSE) for more information) * License: GPLv3 (see [LICENSE](https://github.com/OpenMW/openmw/blob/master/LICENSE) for more information)
* Website: https://www.openmw.org * Website: https://www.openmw.org
* IRC: #openmw on irc.freenode.net * IRC: #openmw on irc.freenode.net

View file

@ -258,18 +258,37 @@ void loadCell(ESM::Cell &cell, ESM::ESMReader &esm, Arguments& info)
if(quiet) continue; if(quiet) continue;
std::cout << " Refnum: " << ref.mRefNum.mIndex << std::endl; std::cout << " Refnum: " << ref.mRefNum.mIndex << std::endl;
std::cout << " ID: '" << ref.mRefID << "'\n"; std::cout << " ID: " << ref.mRefID << std::endl;
std::cout << " Owner: '" << ref.mOwner << "'\n"; std::cout << " Position: (" << ref.mPos.pos[0] << ", " << ref.mPos.pos[1] << ", " << ref.mPos.pos[2] << ")" << std::endl;
std::cout << " Global: '" << ref.mGlobalVariable << "'" << std::endl; if (ref.mScale != 1.f)
std::cout << " Faction: '" << ref.mFaction << "'" << std::endl; std::cout << " Scale: " << ref.mScale << std::endl;
std::cout << " Faction rank: '" << ref.mFactionRank << "'" << std::endl; if (!ref.mOwner.empty())
std::cout << " Enchantment charge: '" << ref.mEnchantmentCharge << "'\n"; std::cout << " Owner: " << ref.mOwner << std::endl;
std::cout << " Uses/health: '" << ref.mChargeInt << "'\n"; if (!ref.mGlobalVariable.empty())
std::cout << " Gold value: '" << ref.mGoldValue << "'\n"; std::cout << " Global: " << ref.mGlobalVariable << std::endl;
std::cout << " Blocked: '" << static_cast<int>(ref.mReferenceBlocked) << "'" << std::endl; if (!ref.mFaction.empty())
std::cout << " Faction: " << ref.mFaction << std::endl;
if (!ref.mFaction.empty() || ref.mFactionRank != -2)
std::cout << " Faction rank: " << ref.mFactionRank << std::endl;
std::cout << " Enchantment charge: " << ref.mEnchantmentCharge << std::endl;
std::cout << " Uses/health: " << ref.mChargeInt << std::endl;
std::cout << " Gold value: " << ref.mGoldValue << std::endl;
std::cout << " Blocked: " << static_cast<int>(ref.mReferenceBlocked) << std::endl;
std::cout << " Deleted: " << deleted << std::endl; std::cout << " Deleted: " << deleted << std::endl;
if (!ref.mKey.empty()) if (!ref.mKey.empty())
std::cout << " Key: '" << ref.mKey << "'" << std::endl; std::cout << " Key: " << ref.mKey << std::endl;
std::cout << " Lock level: " << ref.mLockLevel << std::endl;
if (!ref.mTrap.empty())
std::cout << " Trap: " << ref.mTrap << std::endl;
if (!ref.mSoul.empty())
std::cout << " Soul: " << ref.mSoul << std::endl;
if (ref.mTeleport)
{
std::cout << " Destination position: (" << ref.mDoorDest.pos[0] << ", "
<< ref.mDoorDest.pos[1] << ", " << ref.mDoorDest.pos[2] << ")" << std::endl;
if (!ref.mDestCell.empty())
std::cout << " Destination cell: " << ref.mDestCell << std::endl;
}
} }
} }

View file

@ -4,6 +4,7 @@
#include <components/esm/loadcell.hpp> #include <components/esm/loadcell.hpp>
#include <components/esm/loadcont.hpp> #include <components/esm/loadcont.hpp>
#include <components/esm/loadcrea.hpp> #include <components/esm/loadcrea.hpp>
#include <components/esm/loadench.hpp>
#include <components/esm/loadlevlist.hpp> #include <components/esm/loadlevlist.hpp>
#include <components/esm/loadligh.hpp> #include <components/esm/loadligh.hpp>
#include <components/esm/loadmgef.hpp> #include <components/esm/loadmgef.hpp>
@ -726,6 +727,16 @@ std::string creatureFlags(int flags)
return properties; return properties;
} }
std::string enchantmentFlags(int flags)
{
std::string properties;
if (flags == 0) properties += "[None] ";
if (flags & ESM::Enchantment::Autocalc) properties += "Autocalc ";
if (flags & (0xFFFFFFFF ^ ESM::Enchantment::Autocalc)) properties += "Invalid ";
properties += Misc::StringUtils::format("(0x%08X)", flags);
return properties;
}
std::string landFlags(int flags) std::string landFlags(int flags)
{ {
std::string properties; std::string properties;

View file

@ -49,6 +49,7 @@ std::string bodyPartFlags(int flags);
std::string cellFlags(int flags); std::string cellFlags(int flags);
std::string containerFlags(int flags); std::string containerFlags(int flags);
std::string creatureFlags(int flags); std::string creatureFlags(int flags);
std::string enchantmentFlags(int flags);
std::string landFlags(int flags); std::string landFlags(int flags);
std::string creatureListFlags(int flags); std::string creatureListFlags(int flags);
std::string itemListFlags(int flags); std::string itemListFlags(int flags);

View file

@ -714,7 +714,7 @@ void Record<ESM::Enchantment>::print()
<< " (" << mData.mData.mType << ")" << std::endl; << " (" << mData.mData.mType << ")" << std::endl;
std::cout << " Cost: " << mData.mData.mCost << std::endl; std::cout << " Cost: " << mData.mData.mCost << std::endl;
std::cout << " Charge: " << mData.mData.mCharge << std::endl; std::cout << " Charge: " << mData.mData.mCharge << std::endl;
std::cout << " AutoCalc: " << mData.mData.mAutocalc << std::endl; std::cout << " Flags: " << enchantmentFlags(mData.mData.mFlags) << std::endl;
printEffectList(mData.mEffects); printEffectList(mData.mEffects);
std::cout << " Deleted: " << mIsDeleted << std::endl; std::cout << " Deleted: " << mIsDeleted << std::endl;
} }

View file

@ -1,6 +1,7 @@
#include "maindialog.hpp" #include "maindialog.hpp"
#include <components/version/version.hpp> #include <components/version/version.hpp>
#include <components/misc/helpviewer.hpp>
#include <QDate> #include <QDate>
#include <QMessageBox> #include <QMessageBox>
@ -54,12 +55,15 @@ Launcher::MainDialog::MainDialog(QWidget *parent)
iconWidget->setCurrentRow(0); iconWidget->setCurrentRow(0);
iconWidget->setFlow(QListView::LeftToRight); iconWidget->setFlow(QListView::LeftToRight);
QPushButton *helpButton = new QPushButton(tr("Help"));
QPushButton *playButton = new QPushButton(tr("Play")); QPushButton *playButton = new QPushButton(tr("Play"));
buttonBox->button(QDialogButtonBox::Close)->setText(tr("Close")); buttonBox->button(QDialogButtonBox::Close)->setText(tr("Close"));
buttonBox->addButton(helpButton, QDialogButtonBox::HelpRole);
buttonBox->addButton(playButton, QDialogButtonBox::AcceptRole); buttonBox->addButton(playButton, QDialogButtonBox::AcceptRole);
connect(buttonBox, SIGNAL(rejected()), this, SLOT(close())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(close()));
connect(buttonBox, SIGNAL(accepted()), this, SLOT(play())); connect(buttonBox, SIGNAL(accepted()), this, SLOT(play()));
connect(buttonBox, SIGNAL(helpRequested()), this, SLOT(help()));
// Remove what's this? button // Remove what's this? button
setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint); setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
@ -614,3 +618,8 @@ void Launcher::MainDialog::play()
if (mGameInvoker->startProcess(QLatin1String("openmw"), true)) if (mGameInvoker->startProcess(QLatin1String("openmw"), true))
return qApp->quit(); return qApp->quit();
} }
void Launcher::MainDialog::help()
{
Misc::HelpViewer::openHelp("reference/index.html");
}

View file

@ -59,6 +59,7 @@ namespace Launcher
public slots: public slots:
void changePage(QListWidgetItem *current, QListWidgetItem *previous); void changePage(QListWidgetItem *current, QListWidgetItem *previous);
void play(); void play();
void help();
private slots: private slots:
void wizardStarted(); void wizardStarted();

View file

@ -89,7 +89,7 @@ opencs_units (view/render
scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget
previewwidget editmode instancemode instanceselectionmode instancemovemode previewwidget editmode instancemode instanceselectionmode instancemovemode
orbitcameramode pathgridmode selectionmode pathgridselectionmode cameracontroller orbitcameramode pathgridmode selectionmode pathgridselectionmode cameracontroller
cellwater terraintexturemode actor terrainselection terrainshapemode cellwater terraintexturemode actor terrainselection terrainshapemode brushdraw
) )
opencs_units_noqt (view/render opencs_units_noqt (view/render
@ -97,6 +97,10 @@ 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

View file

@ -356,7 +356,7 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages)
istream >> ignore >> moved.mTarget[0] >> moved.mTarget[1]; istream >> ignore >> moved.mTarget[0] >> moved.mTarget[1];
refRecord.mRefNum.save (writer, false, "MVRF"); refRecord.mRefNum.save (writer, false, "MVRF");
writer.writeHNT ("CNDT", moved.mTarget, 8); writer.writeHNT ("CNDT", moved.mTarget);
} }
refRecord.save (writer, false, false, ref.mState == CSMWorld::RecordBase::State_Deleted); refRecord.save (writer, false, false, ref.mState == CSMWorld::RecordBase::State_Deleted);

View file

@ -271,6 +271,8 @@ void CSMPrefs::State::declare()
declareShortcut ("document-file-newaddon", "New Addon", QKeySequence()); declareShortcut ("document-file-newaddon", "New Addon", QKeySequence());
declareShortcut ("document-file-open", "Open", QKeySequence(Qt::ControlModifier | Qt::Key_O)); declareShortcut ("document-file-open", "Open", QKeySequence(Qt::ControlModifier | Qt::Key_O));
declareShortcut ("document-file-save", "Save", QKeySequence(Qt::ControlModifier | Qt::Key_S)); declareShortcut ("document-file-save", "Save", QKeySequence(Qt::ControlModifier | Qt::Key_S));
declareShortcut ("document-help-help", "Help", QKeySequence(Qt::Key_F1));
declareShortcut ("document-help-tutorial", "Tutorial", QKeySequence());
declareShortcut ("document-file-verify", "Verify", QKeySequence()); declareShortcut ("document-file-verify", "Verify", QKeySequence());
declareShortcut ("document-file-merge", "Merge", QKeySequence()); declareShortcut ("document-file-merge", "Merge", QKeySequence());
declareShortcut ("document-file-errorlog", "Open Load Error Log", QKeySequence()); declareShortcut ("document-file-errorlog", "Open Load Error Log", QKeySequence());

View file

@ -33,13 +33,10 @@ void CSMTools::BodyPartCheckStage::perform (int stage, CSMDoc::Messages &message
CSMWorld::UniversalId id( CSMWorld::UniversalId::Type_BodyPart, bodyPart.mId ); CSMWorld::UniversalId id( CSMWorld::UniversalId::Type_BodyPart, bodyPart.mId );
// Check BYDT // Check BYDT
if (bodyPart.mData.mPart > 14 ) if (bodyPart.mData.mPart >= ESM::BodyPart::MP_Count )
messages.add(id, "Invalid part", "", CSMDoc::Message::Severity_Error); messages.add(id, "Invalid part", "", CSMDoc::Message::Severity_Error);
if (bodyPart.mData.mFlags > 3 ) if (bodyPart.mData.mType > ESM::BodyPart::MT_Armor )
messages.add(id, "Invalid flags", "", CSMDoc::Message::Severity_Error);
if (bodyPart.mData.mType > 2 )
messages.add(id, "Invalid type", "", CSMDoc::Message::Severity_Error); messages.add(id, "Invalid type", "", CSMDoc::Message::Severity_Error);
// Check MODL // Check MODL
@ -48,9 +45,12 @@ void CSMTools::BodyPartCheckStage::perform (int stage, CSMDoc::Messages &message
else if ( mMeshes.searchId( bodyPart.mModel ) == -1 ) else if ( mMeshes.searchId( bodyPart.mModel ) == -1 )
messages.add(id, "Model '" + bodyPart.mModel + "' does not exist", "", CSMDoc::Message::Severity_Error); messages.add(id, "Model '" + bodyPart.mModel + "' does not exist", "", CSMDoc::Message::Severity_Error);
// Check FNAM // Check FNAM for skin body parts (for non-skin body parts it's meaningless)
if ( bodyPart.mRace.empty() ) if ( bodyPart.mData.mType == ESM::BodyPart::MT_Skin )
messages.add(id, "Race is missing", "", CSMDoc::Message::Severity_Error); {
else if ( mRaces.searchId( bodyPart.mRace ) == -1 ) if ( bodyPart.mRace.empty() )
messages.add(id, "Race '" + bodyPart.mRace + "' does not exist", "", CSMDoc::Message::Severity_Error); messages.add(id, "Race is missing", "", CSMDoc::Message::Severity_Error);
else if ( mRaces.searchId( bodyPart.mRace ) == -1 )
messages.add(id, "Race '" + bodyPart.mRace + "' does not exist", "", CSMDoc::Message::Severity_Error);
}
} }

View file

@ -91,9 +91,14 @@ std::pair<int, int> CSMWorld::CellCoordinates::toVertexCoords(const osg::Vec3d&
return std::make_pair(x, y); return std::make_pair(x, y);
} }
float CSMWorld::CellCoordinates::textureGlobalToWorldCoords(int textureGlobal) float CSMWorld::CellCoordinates::textureGlobalXToWorldCoords(int textureGlobal)
{ {
return ESM::Land::REAL_SIZE * static_cast<float>(textureGlobal) / ESM::Land::LAND_TEXTURE_SIZE; return ESM::Land::REAL_SIZE * (static_cast<float>(textureGlobal) + 0.25f) / ESM::Land::LAND_TEXTURE_SIZE;
}
float CSMWorld::CellCoordinates::textureGlobalYToWorldCoords(int textureGlobal)
{
return ESM::Land::REAL_SIZE * (static_cast<float>(textureGlobal) - 0.25f) / ESM::Land::LAND_TEXTURE_SIZE;
} }
float CSMWorld::CellCoordinates::vertexGlobalToWorldCoords(int vertexGlobal) float CSMWorld::CellCoordinates::vertexGlobalToWorldCoords(int vertexGlobal)

View file

@ -54,8 +54,11 @@ namespace CSMWorld
///Converts worldspace coordinates to global vertex selection. ///Converts worldspace coordinates to global vertex selection.
static std::pair<int, int> toVertexCoords(const osg::Vec3d& worldPos); static std::pair<int, int> toVertexCoords(const osg::Vec3d& worldPos);
///Converts global texture coordinate to worldspace coordinate that is at the upper left corner of the selected texture. ///Converts global texture coordinate X to worldspace coordinate, offset by 0.25f.
static float textureGlobalToWorldCoords(int textureGlobal); static float textureGlobalXToWorldCoords(int textureGlobal);
///Converts global texture coordinate Y to worldspace coordinate, offset by 0.25f.
static float textureGlobalYToWorldCoords(int textureGlobal);
///Converts global vertex coordinate to worldspace coordinate ///Converts global vertex coordinate to worldspace coordinate
static float vertexGlobalToWorldCoords(int vertexGlobal); static float vertexGlobalToWorldCoords(int vertexGlobal);

View file

@ -373,7 +373,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, bool fsStrict, const Files::Pat
mEnchantments.addColumn (new EnchantmentTypeColumn<ESM::Enchantment>); mEnchantments.addColumn (new EnchantmentTypeColumn<ESM::Enchantment>);
mEnchantments.addColumn (new CostColumn<ESM::Enchantment>); mEnchantments.addColumn (new CostColumn<ESM::Enchantment>);
mEnchantments.addColumn (new ChargesColumn2<ESM::Enchantment>); mEnchantments.addColumn (new ChargesColumn2<ESM::Enchantment>);
mEnchantments.addColumn (new AutoCalcColumn<ESM::Enchantment>); mEnchantments.addColumn (new FlagColumn<ESM::Enchantment> (Columns::ColumnId_AutoCalc, ESM::Enchantment::Autocalc));
// Enchantment effects // Enchantment effects
mEnchantments.addColumn (new NestedParentColumn<ESM::Enchantment> (Columns::ColumnId_EffectList)); mEnchantments.addColumn (new NestedParentColumn<ESM::Enchantment> (Columns::ColumnId_EffectList));
index = mEnchantments.getColumns()-1; index = mEnchantments.getColumns()-1;

View file

@ -18,10 +18,10 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool
CellRef ref; CellRef ref;
ref.mNew = false; ref.mNew = false;
ESM::MovedCellRef mref; ESM::MovedCellRef mref;
mref.mRefNum.mIndex = 0;
bool isDeleted = false; bool isDeleted = false;
// hack to initialise mindex while (ESM::Cell::getNextRef(reader, ref, isDeleted, true, &mref))
while (!(mref.mRefNum.mIndex = 0) && ESM::Cell::getNextRef(reader, ref, isDeleted, true, &mref))
{ {
// Keep mOriginalCell empty when in modified (as an indicator that the // Keep mOriginalCell empty when in modified (as an indicator that the
// original cell will always be equal the current cell). // original cell will always be equal the current cell).
@ -60,6 +60,8 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool
else else
ref.mCell = cell2.mId; ref.mCell = cell2.mId;
mref.mRefNum.mIndex = 0;
// ignore content file number // ignore content file number
std::map<ESM::RefNum, std::string>::iterator iter = cache.begin(); std::map<ESM::RefNum, std::string>::iterator iter = cache.begin();
for (; iter != cache.end(); ++iter) for (; iter != cache.end(); ++iter)

View file

@ -31,6 +31,7 @@
#include "../tools/subviews.hpp" #include "../tools/subviews.hpp"
#include <components/misc/helpviewer.hpp>
#include <components/version/version.hpp> #include <components/version/version.hpp>
#include "viewmanager.hpp" #include "viewmanager.hpp"
@ -315,6 +316,12 @@ void CSVDoc::View::setupHelpMenu()
{ {
QMenu *help = menuBar()->addMenu (tr ("Help")); QMenu *help = menuBar()->addMenu (tr ("Help"));
QAction* helpInfo = createMenuEntry("Help", ":/info.png", help, "document-help-help");
connect (helpInfo, SIGNAL (triggered()), this, SLOT (openHelp()));
QAction* tutorial = createMenuEntry("Tutorial", ":/info.png", help, "document-help-tutorial");
connect (tutorial, SIGNAL (triggered()), this, SLOT (tutorial()));
QAction* about = createMenuEntry("About OpenMW-CS", ":./info.png", help, "document-help-about"); QAction* about = createMenuEntry("About OpenMW-CS", ":./info.png", help, "document-help-about");
connect (about, SIGNAL (triggered()), this, SLOT (infoAbout())); connect (about, SIGNAL (triggered()), this, SLOT (infoAbout()));
@ -708,6 +715,16 @@ void CSVDoc::View::save()
mDocument->save(); mDocument->save();
} }
void CSVDoc::View::openHelp()
{
Misc::HelpViewer::openHelp("manuals/openmw-cs/index.html");
}
void CSVDoc::View::tutorial()
{
Misc::HelpViewer::openHelp("manuals/openmw-cs/tour.html");
}
void CSVDoc::View::infoAbout() void CSVDoc::View::infoAbout()
{ {
// Get current OpenMW version // Get current OpenMW version

View file

@ -169,6 +169,10 @@ namespace CSVDoc
void exit(); void exit();
static void openHelp();
static void tutorial();
void infoAbout(); void infoAbout();
void infoAboutQt(); void infoAboutQt();

View file

@ -1,12 +1,18 @@
#include "editwidget.hpp" #include "editwidget.hpp"
#include <QAbstractItemModel> #include <QAbstractItemModel>
#include <QAction>
#include <QContextMenuEvent>
#include <QMenu>
#include <QString> #include <QString>
#include <QApplication> #include <QApplication>
#include <components/misc/helpviewer.hpp>
#include "../../model/world/data.hpp" #include "../../model/world/data.hpp"
#include "../../model/world/idtablebase.hpp" #include "../../model/world/idtablebase.hpp"
#include "../../model/world/columns.hpp" #include "../../model/world/columns.hpp"
#include "../../model/prefs/shortcut.hpp"
CSVFilter::EditWidget::EditWidget (CSMWorld::Data& data, QWidget *parent) CSVFilter::EditWidget::EditWidget (CSMWorld::Data& data, QWidget *parent)
: QLineEdit (parent), mParser (data), mIsEmpty(true) : QLineEdit (parent), mParser (data), mIsEmpty(true)
@ -29,6 +35,13 @@ CSVFilter::EditWidget::EditWidget (CSMWorld::Data& data, QWidget *parent)
mStateColumnIndex = model->findColumnIndex(CSMWorld::Columns::ColumnId_Modification); mStateColumnIndex = model->findColumnIndex(CSMWorld::Columns::ColumnId_Modification);
mDescColumnIndex = model->findColumnIndex(CSMWorld::Columns::ColumnId_Description); mDescColumnIndex = model->findColumnIndex(CSMWorld::Columns::ColumnId_Description);
mHelpAction = new QAction (tr ("Help"), this);
connect (mHelpAction, SIGNAL (triggered()), this, SLOT (openHelp()));
mHelpAction->setIcon(QIcon(":/info.png"));
addAction (mHelpAction);
auto* openHelpShortcut = new CSMPrefs::Shortcut("help", this);
openHelpShortcut->associateAction(mHelpAction);
} }
void CSVFilter::EditWidget::textChanged (const QString& text) void CSVFilter::EditWidget::textChanged (const QString& text)
@ -211,3 +224,17 @@ std::string CSVFilter::EditWidget::generateFilter (std::pair< std::string, std::
return ss.str(); return ss.str();
} }
void CSVFilter::EditWidget::contextMenuEvent(QContextMenuEvent *event)
{
QMenu *menu = createStandardContextMenu();
menu->addAction(mHelpAction);
menu->exec(event->globalPos());
delete menu;
}
void CSVFilter::EditWidget::openHelp()
{
Misc::HelpViewer::openHelp("manuals/openmw-cs/record-filters.html");
}

View file

@ -26,6 +26,7 @@ namespace CSVFilter
bool mIsEmpty; bool mIsEmpty;
int mStateColumnIndex; int mStateColumnIndex;
int mDescColumnIndex; int mDescColumnIndex;
QAction *mHelpAction;
public: public:
@ -40,6 +41,7 @@ namespace CSVFilter
private: private:
std::string generateFilter(std::pair<std::string, std::vector<std::string> >& seekedString) const; std::string generateFilter(std::pair<std::string, std::vector<std::string> >& seekedString) const;
void contextMenuEvent (QContextMenuEvent *event) override;
private slots: private slots:
@ -51,6 +53,8 @@ namespace CSVFilter
void filterRowsInserted (const QModelIndex& parent, int start, int end); void filterRowsInserted (const QModelIndex& parent, int start, int end);
static void openHelp();
}; };
} }

View file

@ -0,0 +1,307 @@
#include "brushdraw.hpp"
#include <limits>
#include <osg/Group>
#include <osg/Geometry>
#include <osg/Array>
#include <osgUtil/LineSegmentIntersector>
#include "../../model/world/cellcoordinates.hpp"
#include "../widget/brushshapes.hpp"
#include "mask.hpp"
CSVRender::BrushDraw::BrushDraw(osg::ref_ptr<osg::Group> parentNode, bool textureMode) :
mParentNode(parentNode), mTextureMode(textureMode)
{
mBrushDrawNode = new osg::Group();
mGeometry = new osg::Geometry();
mBrushDrawNode->addChild(mGeometry);
mParentNode->addChild(mBrushDrawNode);
if (mTextureMode)
mLandSizeFactor = static_cast<float>(ESM::Land::REAL_SIZE) / static_cast<float>(ESM::Land::LAND_TEXTURE_SIZE);
else
mLandSizeFactor = static_cast<float>(ESM::Land::REAL_SIZE) / static_cast<float>(ESM::Land::LAND_SIZE - 1);
}
CSVRender::BrushDraw::~BrushDraw()
{
mBrushDrawNode->removeChild(mGeometry);
mParentNode->removeChild(mBrushDrawNode);
}
float CSVRender::BrushDraw::getIntersectionHeight (const osg::Vec3d& point)
{
osg::Vec3d start = point;
osg::Vec3d end = point;
start.z() = std::numeric_limits<int>::max();
end.z() = std::numeric_limits<int>::lowest();
osg::Vec3d direction = end - start;
// Get intersection
osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector (new osgUtil::LineSegmentIntersector(
osgUtil::Intersector::MODEL, start, end) );
intersector->setIntersectionLimit(osgUtil::LineSegmentIntersector::NO_LIMIT);
osgUtil::IntersectionVisitor visitor(intersector);
visitor.setTraversalMask(Mask_Terrain);
mParentNode->accept(visitor);
for (osgUtil::LineSegmentIntersector::Intersections::iterator it = intersector->getIntersections().begin();
it != intersector->getIntersections().end(); ++it)
{
osgUtil::LineSegmentIntersector::Intersection intersection = *it;
// reject back-facing polygons
if (direction * intersection.getWorldIntersectNormal() > 0)
{
continue;
}
return intersection.getWorldIntersectPoint().z();
}
return 0.0f;
}
void CSVRender::BrushDraw::buildPointGeometry(const osg::Vec3d& point)
{
osg::ref_ptr<osg::Geometry> geom (new osg::Geometry());
osg::ref_ptr<osg::Vec3Array> vertices (new osg::Vec3Array());
osg::ref_ptr<osg::Vec4Array> colors (new osg::Vec4Array());
const float brushOutlineHeight (1.0f);
const float crossHeadSize (8.0f);
osg::Vec4f lineColor(1.0f, 1.0f, 1.0f, 0.6f);
vertices->push_back(osg::Vec3d(
point.x() - crossHeadSize,
point.y() - crossHeadSize,
getIntersectionHeight(osg::Vec3d(
point.x() - crossHeadSize,
point.y() - crossHeadSize,
point.z()) ) + brushOutlineHeight));
colors->push_back(lineColor);
vertices->push_back(osg::Vec3d(
point.x() + crossHeadSize,
point.y() + crossHeadSize,
getIntersectionHeight(osg::Vec3d(
point.x() + crossHeadSize,
point.y() + crossHeadSize,
point.z()) ) + brushOutlineHeight));
colors->push_back(lineColor);
vertices->push_back(osg::Vec3d(
point.x() + crossHeadSize,
point.y() - crossHeadSize,
getIntersectionHeight(osg::Vec3d(
point.x() + crossHeadSize,
point.y() - crossHeadSize,
point.z()) ) + brushOutlineHeight));
colors->push_back(lineColor);
vertices->push_back(osg::Vec3d(
point.x() - crossHeadSize,
point.y() + crossHeadSize,
getIntersectionHeight(osg::Vec3d(
point.x() - crossHeadSize,
point.y() + crossHeadSize,
point.z()) ) + brushOutlineHeight));
colors->push_back(lineColor);
geom->setVertexArray(vertices);
geom->setColorArray(colors, osg::Array::BIND_PER_VERTEX);
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, 4));
mGeometry = geom;
}
void CSVRender::BrushDraw::buildSquareGeometry(const float& radius, const osg::Vec3d& point)
{
osg::ref_ptr<osg::Geometry> geom (new osg::Geometry());
osg::ref_ptr<osg::Vec3Array> vertices (new osg::Vec3Array());
osg::ref_ptr<osg::Vec4Array> colors (new osg::Vec4Array());
const float brushOutlineHeight (1.0f);
float diameter = radius * 2;
int resolution = static_cast<int>(2.f * diameter / mLandSizeFactor); //half a vertex resolution
float resAdjustedLandSizeFactor = mLandSizeFactor / 2;
osg::Vec4f lineColor(1.0f, 1.0f, 1.0f, 0.6f);
for (int i = 0; i < resolution; i++)
{
int step = i * resAdjustedLandSizeFactor;
int step2 = (i + 1) * resAdjustedLandSizeFactor;
osg::Vec3d upHorizontalLinePoint1(
point.x() - radius + step,
point.y() - radius,
getIntersectionHeight(osg::Vec3d(
point.x() - radius + step,
point.y() - radius,
point.z())) + brushOutlineHeight);
osg::Vec3d upHorizontalLinePoint2(
point.x() - radius + step2,
point.y() - radius,
getIntersectionHeight(osg::Vec3d(
point.x() - radius + step2,
point.y() - radius,
point.z())) + brushOutlineHeight);
osg::Vec3d upVerticalLinePoint1(
point.x() - radius,
point.y() - radius + step,
getIntersectionHeight(osg::Vec3d(
point.x() - radius,
point.y() - radius + step,
point.z())) + brushOutlineHeight);
osg::Vec3d upVerticalLinePoint2(
point.x() - radius,
point.y() - radius + step2,
getIntersectionHeight(osg::Vec3d(
point.x() - radius,
point.y() - radius + step2,
point.z())) + brushOutlineHeight);
osg::Vec3d downHorizontalLinePoint1(
point.x() + radius - step,
point.y() + radius,
getIntersectionHeight(osg::Vec3d(
point.x() + radius - step,
point.y() + radius,
point.z())) + brushOutlineHeight);
osg::Vec3d downHorizontalLinePoint2(
point.x() + radius - step2,
point.y() + radius,
getIntersectionHeight(osg::Vec3d(
point.x() + radius - step2,
point.y() + radius,
point.z())) + brushOutlineHeight);
osg::Vec3d downVerticalLinePoint1(
point.x() + radius,
point.y() + radius - step,
getIntersectionHeight(osg::Vec3d(
point.x() + radius,
point.y() + radius - step,
point.z())) + brushOutlineHeight);
osg::Vec3d downVerticalLinePoint2(
point.x() + radius,
point.y() + radius - step2,
getIntersectionHeight(osg::Vec3d(
point.x() + radius,
point.y() + radius - step2,
point.z())) + brushOutlineHeight);
vertices->push_back(upHorizontalLinePoint1);
colors->push_back(lineColor);
vertices->push_back(upHorizontalLinePoint2);
colors->push_back(lineColor);
vertices->push_back(upVerticalLinePoint1);
colors->push_back(lineColor);
vertices->push_back(upVerticalLinePoint2);
colors->push_back(lineColor);
vertices->push_back(downHorizontalLinePoint1);
colors->push_back(lineColor);
vertices->push_back(downHorizontalLinePoint2);
colors->push_back(lineColor);
vertices->push_back(downVerticalLinePoint1);
colors->push_back(lineColor);
vertices->push_back(downVerticalLinePoint2);
colors->push_back(lineColor);
}
geom->setVertexArray(vertices);
geom->setColorArray(colors, osg::Array::BIND_PER_VERTEX);
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, resolution * 8));
mGeometry = geom;
}
void CSVRender::BrushDraw::buildCircleGeometry(const float& radius, const osg::Vec3d& point)
{
osg::ref_ptr<osg::Geometry> geom (new osg::Geometry());
osg::ref_ptr<osg::Vec3Array> vertices (new osg::Vec3Array());
osg::ref_ptr<osg::Vec4Array> colors (new osg::Vec4Array());
const int amountOfPoints = (osg::PI * 2.0f) * radius / 20;
const float step ((osg::PI * 2.0f) / static_cast<float>(amountOfPoints));
const float brushOutlineHeight (1.0f);
osg::Vec4f lineColor(1.0f, 1.0f, 1.0f, 0.6f);
for (int i = 0; i < amountOfPoints + 2; i++)
{
float angle (i * step);
vertices->push_back(osg::Vec3d(
point.x() + radius * cosf(angle),
point.y() + radius * sinf(angle),
getIntersectionHeight(osg::Vec3d(
point.x() + radius * cosf(angle),
point.y() + radius * sinf(angle),
point.z()) ) + brushOutlineHeight));
colors->push_back(lineColor);
angle = static_cast<float>(i + 1) * step;
vertices->push_back(osg::Vec3d(
point.x() + radius * cosf(angle),
point.y() + radius * sinf(angle),
getIntersectionHeight(osg::Vec3d(
point.x() + radius * cosf(angle),
point.y() + radius * sinf(angle),
point.z()) ) + brushOutlineHeight));
colors->push_back(lineColor);
}
geom->setVertexArray(vertices);
geom->setColorArray(colors, osg::Array::BIND_PER_VERTEX);
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP, 0, amountOfPoints * 2));
mGeometry = geom;
}
void CSVRender::BrushDraw::buildCustomGeometry(const float& radius, const osg::Vec3d& point)
{
// Not implemented
}
void CSVRender::BrushDraw::update(osg::Vec3d point, int brushSize, CSVWidget::BrushShape toolShape)
{
if (mBrushDrawNode->containsNode(mGeometry))
mBrushDrawNode->removeChild(mGeometry);
float radius = (mLandSizeFactor * brushSize) / 2;
osg::Vec3d snapToGridPoint = point;
if (mTextureMode)
{
std::pair<int, int> snapToGridXY = CSMWorld::CellCoordinates::toTextureCoords(point);
float offsetToMiddle = mLandSizeFactor * 0.5f;
snapToGridPoint = osg::Vec3d(
CSMWorld::CellCoordinates::textureGlobalXToWorldCoords(snapToGridXY.first) + offsetToMiddle,
CSMWorld::CellCoordinates::textureGlobalYToWorldCoords(snapToGridXY.second) + offsetToMiddle,
point.z());
}
else
{
std::pair<int, int> snapToGridXY = CSMWorld::CellCoordinates::toVertexCoords(point);
snapToGridPoint = osg::Vec3d(
CSMWorld::CellCoordinates::vertexGlobalToWorldCoords(snapToGridXY.first),
CSMWorld::CellCoordinates::vertexGlobalToWorldCoords(snapToGridXY.second),
point.z());
}
switch (toolShape)
{
case (CSVWidget::BrushShape_Point) :
buildPointGeometry(snapToGridPoint);
break;
case (CSVWidget::BrushShape_Square) :
buildSquareGeometry(radius, snapToGridPoint);
break;
case (CSVWidget::BrushShape_Circle) :
buildCircleGeometry(radius, snapToGridPoint);
break;
case (CSVWidget::BrushShape_Custom) :
buildSquareGeometry(1, snapToGridPoint);
//buildCustomGeometry
break;
}
mGeometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
mBrushDrawNode->addChild(mGeometry);
}
void CSVRender::BrushDraw::hide()
{
if (mBrushDrawNode->containsNode(mGeometry))
mBrushDrawNode->removeChild(mGeometry);
}

View file

@ -0,0 +1,36 @@
#ifndef CSV_RENDER_BRUSHDRAW_H
#define CSV_RENDER_BRUSHDRAW_H
#include <osg/Group>
#include <osg/Geometry>
#include <components/esm/loadland.hpp>
#include "../widget/brushshapes.hpp"
namespace CSVRender
{
class BrushDraw
{
public:
BrushDraw(osg::ref_ptr<osg::Group> parentNode, bool textureMode = false);
~BrushDraw();
void update(osg::Vec3d point, int brushSize, CSVWidget::BrushShape toolShape);
void hide();
private:
void buildPointGeometry(const osg::Vec3d& point);
void buildSquareGeometry(const float& radius, const osg::Vec3d& point);
void buildCircleGeometry(const float& radius, const osg::Vec3d& point);
void buildCustomGeometry(const float& radius, const osg::Vec3d& point);
float getIntersectionHeight (const osg::Vec3d& point);
osg::ref_ptr<osg::Group> mParentNode;
osg::ref_ptr<osg::Group> mBrushDrawNode;
osg::ref_ptr<osg::Geometry> mGeometry;
bool mTextureMode;
float mLandSizeFactor;
};
}
#endif

View file

@ -9,7 +9,6 @@
#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"
@ -22,6 +21,7 @@
#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 & SceneUtil::Mask_EditorReference) if (mSubModeElementMask & Mask_Reference)
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)); mData.getResourceSystem().get(), mTerrainStorage, Mask_Terrain));
} }
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 & SceneUtil::Mask_EditorReference) if (elementMask & Mask_Reference)
{ {
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 & SceneUtil::Mask_Pathgrid) if (mPathgrid && elementMask & 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 & SceneUtil::Mask_EditorReference) if (elementMask & Mask_Reference)
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 & SceneUtil::Mask_Pathgrid) if (mPathgrid && elementMask & 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 & SceneUtil::Mask_EditorReference) if (elementMask & Mask_Reference)
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 & SceneUtil::Mask_EditorReference) if (elementMask & Mask_Reference)
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 & SceneUtil::Mask_EditorReference) if (elementMask & Mask_Reference)
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 & SceneUtil::Mask_Pathgrid) if (mPathgrid && elementMask & Mask_Pathgrid)
mPathgrid->resetIndicators(); mPathgrid->resetIndicators();
} }

View file

@ -11,10 +11,11 @@
#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 (SceneUtil::Mask_EditorCellArrow), mArrow (arrow) : TagBase (Mask_CellArrow), mArrow (arrow)
{} {}
CSVRender::CellArrow *CSVRender::CellArrowTag::getCellArrow() const CSVRender::CellArrow *CSVRender::CellArrowTag::getCellArrow() const
@ -174,7 +175,7 @@ CSVRender::CellArrow::CellArrow (osg::Group *cellNode, Direction direction,
mParentNode->addChild (mBaseNode); mParentNode->addChild (mBaseNode);
mBaseNode->setNodeMask (SceneUtil::Mask_EditorCellArrow); mBaseNode->setNodeMask (Mask_CellArrow);
adjustTransform(); adjustTransform();
buildShape(); buildShape();

View file

@ -7,7 +7,8 @@
#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"
@ -19,7 +20,7 @@ CSVRender::CellBorder::CellBorder(osg::Group* cellNode, const CSMWorld::CellCoor
: mParentNode(cellNode) : mParentNode(cellNode)
{ {
mBaseNode = new osg::PositionAttitudeTransform(); mBaseNode = new osg::PositionAttitudeTransform();
mBaseNode->setNodeMask(SceneUtil::Mask_EditorCellBorder); mBaseNode->setNodeMask(Mask_CellBorder);
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);

View file

@ -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(SceneUtil::Mask_EditorCellMarker), mMarker(marker) : TagBase(Mask_CellMarker), 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(SceneUtil::Mask_EditorCellMarker); mMarkerNode->setNodeMask(Mask_CellMarker);
mCellNode->addChild(mMarkerNode); mCellNode->addChild(mMarkerNode);

View file

@ -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(SceneUtil::Mask_Water); mWaterTransform->setNodeMask(Mask_Water);
mParentNode->addChild(mWaterTransform); mParentNode->addChild(mWaterTransform);
mWaterNode = new osg::Geode(); mWaterNode = new osg::Geode();

View file

@ -73,6 +73,8 @@ void CSVRender::EditMode::dropEvent (QDropEvent *event) {}
void CSVRender::EditMode::dragMoveEvent (QDragMoveEvent *event) {} void CSVRender::EditMode::dragMoveEvent (QDragMoveEvent *event) {}
void CSVRender::EditMode::mouseMoveEvent (QMouseEvent *event) {}
int CSVRender::EditMode::getSubMode() const int CSVRender::EditMode::getSubMode() const
{ {
return -1; return -1;

View file

@ -98,6 +98,8 @@ namespace CSVRender
/// Default-implementation: ignored /// Default-implementation: ignored
virtual void dragMoveEvent (QDragMoveEvent *event); virtual void dragMoveEvent (QDragMoveEvent *event);
virtual void mouseMoveEvent (QMouseEvent *event);
/// Default: return -1 /// Default: return -1
virtual int getSubMode() const; virtual int getSubMode() const;
}; };

View file

@ -21,7 +21,7 @@
#include "../widget/scenetoolbar.hpp" #include "../widget/scenetoolbar.hpp"
#include "../widget/scenetoolmode.hpp" #include "../widget/scenetoolmode.hpp"
#include <components/sceneutil/vismask.hpp> #include "mask.hpp"
#include "object.hpp" #include "object.hpp"
#include "worldspacewidget.hpp" #include "worldspacewidget.hpp"
@ -97,7 +97,7 @@ osg::Vec3f CSVRender::InstanceMode::getScreenCoords(const osg::Vec3f& pos)
} }
CSVRender::InstanceMode::InstanceMode (WorldspaceWidget *worldspaceWidget, osg::ref_ptr<osg::Group> parentNode, QWidget *parent) CSVRender::InstanceMode::InstanceMode (WorldspaceWidget *worldspaceWidget, osg::ref_ptr<osg::Group> parentNode, QWidget *parent)
: EditMode (worldspaceWidget, QIcon (":scenetoolbar/editing-instance"), SceneUtil::Mask_EditorReference | SceneUtil::Mask_Terrain, "Instance editing", : EditMode (worldspaceWidget, QIcon (":scenetoolbar/editing-instance"), Mask_Reference | 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), mParentNode (parentNode) mDragAxis (-1), mLocked (false), mUnitScaleDist(1), mParentNode (parentNode)
{ {
@ -157,13 +157,13 @@ void CSVRender::InstanceMode::activate (CSVWidget::SceneToolbar *toolbar)
std::string subMode = mSubMode->getCurrentId(); std::string subMode = mSubMode->getCurrentId();
getWorldspaceWidget().setSubMode (getSubModeFromId (subMode), SceneUtil::Mask_EditorReference); getWorldspaceWidget().setSubMode (getSubModeFromId (subMode), Mask_Reference);
} }
void CSVRender::InstanceMode::deactivate (CSVWidget::SceneToolbar *toolbar) void CSVRender::InstanceMode::deactivate (CSVWidget::SceneToolbar *toolbar)
{ {
mDragMode = DragMode_None; mDragMode = DragMode_None;
getWorldspaceWidget().reset (SceneUtil::Mask_EditorReference); getWorldspaceWidget().reset (Mask_Reference);
if (mSelectionMode) if (mSelectionMode)
{ {
@ -216,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 (SceneUtil::Mask_EditorReference); getWorldspaceWidget().clearSelection (Mask_Reference);
if (hit.tag) if (hit.tag)
{ {
@ -251,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 (SceneUtil::Mask_EditorReference); std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (Mask_Reference);
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 (SceneUtil::Mask_EditorReference); getWorldspaceWidget().clearSelection (Mask_Reference);
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;
@ -265,7 +265,7 @@ bool CSVRender::InstanceMode::primaryEditStartDrag (const QPoint& pos)
} }
} }
selection = getWorldspaceWidget().getSelection (SceneUtil::Mask_EditorReference); selection = getWorldspaceWidget().getSelection (Mask_Reference);
if (selection.empty()) if (selection.empty())
return false; return false;
} }
@ -291,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 (SceneUtil::Mask_EditorReference); std::vector<osg::ref_ptr<TagBase> > editedSelection = getWorldspaceWidget().getEdited (Mask_Reference);
osg::Vec3f center = getScreenCoords(getSelectionCenter(editedSelection)); osg::Vec3f center = getScreenCoords(getSelectionCenter(editedSelection));
int widgetHeight = getWorldspaceWidget().height(); int widgetHeight = getWorldspaceWidget().height();
@ -327,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 (SceneUtil::Mask_EditorReference); std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getEdited (Mask_Reference);
if (mDragMode == DragMode_Move) if (mDragMode == DragMode_Move)
{ {
@ -484,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 (SceneUtil::Mask_EditorReference); getWorldspaceWidget().getEdited (Mask_Reference);
QUndoStack& undoStack = getWorldspaceWidget().getDocument().getUndoStack(); QUndoStack& undoStack = getWorldspaceWidget().getDocument().getUndoStack();
@ -516,7 +516,7 @@ void CSVRender::InstanceMode::dragCompleted(const QPoint& pos)
void CSVRender::InstanceMode::dragAborted() void CSVRender::InstanceMode::dragAborted()
{ {
getWorldspaceWidget().reset (SceneUtil::Mask_EditorReference); getWorldspaceWidget().reset (Mask_Reference);
mDragMode = DragMode_None; mDragMode = DragMode_None;
} }
@ -535,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 (SceneUtil::Mask_EditorReference); getWorldspaceWidget().getEdited (Mask_Reference);
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)
@ -677,12 +677,12 @@ void CSVRender::InstanceMode::subModeChanged (const std::string& id)
{ {
mSubModeId = id; mSubModeId = id;
getWorldspaceWidget().abortDrag(); getWorldspaceWidget().abortDrag();
getWorldspaceWidget().setSubMode (getSubModeFromId (id), SceneUtil::Mask_EditorReference); getWorldspaceWidget().setSubMode (getSubModeFromId (id), Mask_Reference);
} }
void CSVRender::InstanceMode::deleteSelectedInstances(bool active) void CSVRender::InstanceMode::deleteSelectedInstances(bool active)
{ {
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (SceneUtil::Mask_EditorReference); std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (Mask_Reference);
if (selection.empty()) return; if (selection.empty()) return;
CSMDoc::Document& document = getWorldspaceWidget().getDocument(); CSMDoc::Document& document = getWorldspaceWidget().getDocument();
@ -695,7 +695,7 @@ void CSVRender::InstanceMode::deleteSelectedInstances(bool active)
if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (tag.get())) if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (tag.get()))
macro.push(new CSMWorld::DeleteCommand(referencesTable, objectTag->mObject->getReferenceId())); macro.push(new CSMWorld::DeleteCommand(referencesTable, objectTag->mObject->getReferenceId()));
getWorldspaceWidget().clearSelection (SceneUtil::Mask_EditorReference); getWorldspaceWidget().clearSelection (Mask_Reference);
} }
void CSVRender::InstanceMode::dropInstance(DropMode dropMode, CSVRender::Object* object, float objectHeight) void CSVRender::InstanceMode::dropInstance(DropMode dropMode, CSVRender::Object* object, float objectHeight)
@ -713,22 +713,20 @@ void CSVRender::InstanceMode::dropInstance(DropMode dropMode, CSVRender::Object*
osgUtil::IntersectionVisitor visitor(intersector); osgUtil::IntersectionVisitor visitor(intersector);
if (dropMode == TerrainSep) if (dropMode == TerrainSep)
visitor.setTraversalMask(SceneUtil::Mask_Terrain); visitor.setTraversalMask(Mask_Terrain);
if (dropMode == CollisionSep) if (dropMode == CollisionSep)
visitor.setTraversalMask(SceneUtil::Mask_Terrain | SceneUtil::Mask_EditorReference); visitor.setTraversalMask(Mask_Terrain | Mask_Reference);
mParentNode->accept(visitor); mParentNode->accept(visitor);
for (osgUtil::LineSegmentIntersector::Intersections::iterator it = intersector->getIntersections().begin(); osgUtil::LineSegmentIntersector::Intersections::iterator it = intersector->getIntersections().begin();
it != intersector->getIntersections().end(); ++it) if (it != intersector->getIntersections().end())
{ {
osgUtil::LineSegmentIntersector::Intersection intersection = *it; osgUtil::LineSegmentIntersector::Intersection intersection = *it;
ESM::Position position = object->getPosition(); ESM::Position position = object->getPosition();
object->setEdited (Object::Override_Position); object->setEdited (Object::Override_Position);
position.pos[2] = intersection.getWorldIntersectPoint().z() + objectHeight; position.pos[2] = intersection.getWorldIntersectPoint().z() + objectHeight;
object->setPosition(position.pos); object->setPosition(position.pos);
return;
} }
} }
@ -747,14 +745,14 @@ float CSVRender::InstanceMode::getDropHeight(DropMode dropMode, CSVRender::Objec
osgUtil::IntersectionVisitor visitor(intersector); osgUtil::IntersectionVisitor visitor(intersector);
if (dropMode == Terrain) if (dropMode == Terrain)
visitor.setTraversalMask(SceneUtil::Mask_Terrain); visitor.setTraversalMask(Mask_Terrain);
if (dropMode == Collision) if (dropMode == Collision)
visitor.setTraversalMask(SceneUtil::Mask_Terrain | SceneUtil::Mask_EditorReference); visitor.setTraversalMask(Mask_Terrain | Mask_Reference);
mParentNode->accept(visitor); mParentNode->accept(visitor);
for (osgUtil::LineSegmentIntersector::Intersections::iterator it = intersector->getIntersections().begin(); osgUtil::LineSegmentIntersector::Intersections::iterator it = intersector->getIntersections().begin();
it != intersector->getIntersections().end(); ++it) if (it != intersector->getIntersections().end())
{ {
osgUtil::LineSegmentIntersector::Intersection intersection = *it; osgUtil::LineSegmentIntersector::Intersection intersection = *it;
float collisionLevel = intersection.getWorldIntersectPoint().z(); float collisionLevel = intersection.getWorldIntersectPoint().z();
@ -786,7 +784,7 @@ void CSVRender::InstanceMode::dropSelectedInstancesToTerrainSeparately()
void CSVRender::InstanceMode::handleDropMethod(DropMode dropMode, QString commandMsg) void CSVRender::InstanceMode::handleDropMethod(DropMode dropMode, QString commandMsg)
{ {
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (SceneUtil::Mask_EditorReference); std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (Mask_Reference);
if (selection.empty()) if (selection.empty())
return; return;
@ -843,7 +841,7 @@ void CSVRender::InstanceMode::handleDropMethod(DropMode dropMode, QString comman
CSVRender::DropObjectDataHandler::DropObjectDataHandler(WorldspaceWidget* worldspacewidget) CSVRender::DropObjectDataHandler::DropObjectDataHandler(WorldspaceWidget* worldspacewidget)
: mWorldspaceWidget(worldspacewidget) : mWorldspaceWidget(worldspacewidget)
{ {
std::vector<osg::ref_ptr<TagBase> > selection = mWorldspaceWidget->getSelection (SceneUtil::Mask_EditorReference); std::vector<osg::ref_ptr<TagBase> > selection = mWorldspaceWidget->getSelection (Mask_Reference);
for(osg::ref_ptr<TagBase> tag: selection) for(osg::ref_ptr<TagBase> tag: selection)
{ {
if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (tag.get())) if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (tag.get()))
@ -852,7 +850,7 @@ CSVRender::DropObjectDataHandler::DropObjectDataHandler(WorldspaceWidget* worlds
osg::ref_ptr<osg::Group> objectNodeWithoutGUI = objectTag->mObject->getBaseNode(); osg::ref_ptr<osg::Group> objectNodeWithoutGUI = objectTag->mObject->getBaseNode();
osg::ComputeBoundsVisitor computeBounds; osg::ComputeBoundsVisitor computeBounds;
computeBounds.setTraversalMask(SceneUtil::Mask_EditorReference); computeBounds.setTraversalMask(Mask_Reference);
objectNodeWithoutGUI->accept(computeBounds); objectNodeWithoutGUI->accept(computeBounds);
osg::BoundingBox bounds = computeBounds.getBoundingBox(); osg::BoundingBox bounds = computeBounds.getBoundingBox();
float boundingBoxOffset = 0.0f; float boundingBoxOffset = 0.0f;
@ -862,14 +860,14 @@ CSVRender::DropObjectDataHandler::DropObjectDataHandler(WorldspaceWidget* worlds
mObjectHeights.emplace_back(boundingBoxOffset); mObjectHeights.emplace_back(boundingBoxOffset);
mOldMasks.emplace_back(objectNodeWithGUI->getNodeMask()); mOldMasks.emplace_back(objectNodeWithGUI->getNodeMask());
objectNodeWithGUI->setNodeMask(SceneUtil::Mask_Disabled); objectNodeWithGUI->setNodeMask(0);
} }
} }
} }
CSVRender::DropObjectDataHandler::~DropObjectDataHandler() CSVRender::DropObjectDataHandler::~DropObjectDataHandler()
{ {
std::vector<osg::ref_ptr<TagBase> > selection = mWorldspaceWidget->getSelection (SceneUtil::Mask_EditorReference); std::vector<osg::ref_ptr<TagBase> > selection = mWorldspaceWidget->getSelection (Mask_Reference);
int counter = 0; int counter = 0;
for(osg::ref_ptr<TagBase> tag: selection) for(osg::ref_ptr<TagBase> tag: selection)
{ {

View file

@ -6,15 +6,13 @@
#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, SceneUtil::Mask_EditorReference) : SelectionMode(parent, worldspaceWidget, Mask_Reference)
{ {
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);
@ -38,12 +36,12 @@ namespace CSVRender
void InstanceSelectionMode::selectSame() void InstanceSelectionMode::selectSame()
{ {
getWorldspaceWidget().selectAllWithSameParentId(SceneUtil::Mask_EditorReference); getWorldspaceWidget().selectAllWithSameParentId(Mask_Reference);
} }
void InstanceSelectionMode::deleteSelection() void InstanceSelectionMode::deleteSelection()
{ {
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection(SceneUtil::Mask_EditorReference); std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection(Mask_Reference);
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));

View file

@ -0,0 +1,32 @@
#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
{
// 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

View file

@ -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 (SceneUtil::Mask_EditorReference), mObject (object) : TagBase (Mask_Reference), 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, isExterior); SceneUtil::addLight(mBaseNode, light, Mask_ParticleSystem, Mask_Lighting, isExterior);
} }
} }
@ -429,7 +429,7 @@ CSVRender::Object::Object (CSMWorld::Data& data, osg::Group* parentNode,
parentNode->addChild (mRootNode); parentNode->addChild (mRootNode);
mRootNode->setNodeMask(SceneUtil::Mask_EditorReference); mRootNode->setNodeMask(Mask_Reference);
if (referenceable) if (referenceable)
{ {

View file

@ -21,6 +21,7 @@
#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"
@ -126,8 +127,8 @@ void CSVRender::PagedWorldspaceWidget::addVisibilitySelectorButtons (
CSVWidget::SceneToolToggle2 *tool) CSVWidget::SceneToolToggle2 *tool)
{ {
WorldspaceWidget::addVisibilitySelectorButtons (tool); WorldspaceWidget::addVisibilitySelectorButtons (tool);
tool->addButton (Button_Terrain, SceneUtil::Mask_Terrain, "Terrain"); tool->addButton (Button_Terrain, 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 (
@ -141,16 +142,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"), SceneUtil::Mask_EditorReference, "Terrain vertex paint editing"), new EditMode (this, QIcon (":placeholder"), Mask_Reference, "Terrain vertex paint editing"),
"terrain-vertex"); "terrain-vertex");
tool->addButton ( tool->addButton (
new EditMode (this, QIcon (":placeholder"), SceneUtil::Mask_EditorReference, "Terrain movement"), new EditMode (this, QIcon (":placeholder"), Mask_Reference, "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()==SceneUtil::Mask_EditorCellArrow) if (hit.tag && hit.tag->getMask()==Mask_CellArrow)
{ {
if (CellArrowTag *cellArrowTag = dynamic_cast<CSVRender::CellArrowTag *> (hit.tag.get())) if (CellArrowTag *cellArrowTag = dynamic_cast<CSVRender::CellArrowTag *> (hit.tag.get()))
{ {
@ -873,9 +874,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, SceneUtil::Mask_EditorCellMarker, "Cell Marker"); mControlElements->addButton (1, Mask_CellMarker, "Cell Marker");
mControlElements->addButton (2, SceneUtil::Mask_EditorCellArrow, "Cell Arrows"); mControlElements->addButton (2, Mask_CellArrow, "Cell Arrows");
mControlElements->addButton (4, SceneUtil::Mask_EditorCellBorder, "Cell Border"); mControlElements->addButton (4, Mask_CellBorder, "Cell Border");
mControlElements->setSelectionMask (0xffffffff); mControlElements->setSelectionMask (0xffffffff);

View file

@ -10,7 +10,6 @@
#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"
@ -32,7 +31,7 @@ namespace CSVRender
}; };
PathgridTag::PathgridTag(Pathgrid* pathgrid) PathgridTag::PathgridTag(Pathgrid* pathgrid)
: TagBase(SceneUtil::Mask_Pathgrid), mPathgrid(pathgrid) : TagBase(Mask_Pathgrid), mPathgrid(pathgrid)
{ {
} }
@ -71,7 +70,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(SceneUtil::Mask_Pathgrid); mBaseNode->setNodeMask(Mask_Pathgrid);
mParent->addChild(mBaseNode); mParent->addChild(mBaseNode);
mPathgridGeode = new osg::Geode(); mPathgridGeode = new osg::Geode();

View file

@ -4,7 +4,6 @@
#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"
@ -16,6 +15,7 @@
#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"), SceneUtil::Mask_Pathgrid | SceneUtil::Mask_Terrain | SceneUtil::Mask_EditorReference, : EditMode(worldspaceWidget, QIcon(":placeholder"), Mask_Pathgrid | Mask_Terrain | Mask_Reference,
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(SceneUtil::Mask_Pathgrid); getWorldspaceWidget().clearSelection(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(SceneUtil::Mask_Pathgrid); getWorldspaceWidget().clearSelection(Mask_Pathgrid);
mLastId = tag->getPathgrid()->getId(); mLastId = tag->getPathgrid()->getId();
} }
@ -142,12 +142,12 @@ namespace CSVRender
} }
} }
getWorldspaceWidget().clearSelection(SceneUtil::Mask_Pathgrid); getWorldspaceWidget().clearSelection(Mask_Pathgrid);
} }
bool PathgridMode::primaryEditStartDrag(const QPoint& pos) bool PathgridMode::primaryEditStartDrag(const QPoint& pos)
{ {
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (SceneUtil::Mask_Pathgrid); std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (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 (SceneUtil::Mask_Pathgrid); selection = getWorldspaceWidget().getSelection (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(SceneUtil::Mask_Pathgrid); std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection(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 (SceneUtil::Mask_Pathgrid); std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (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(SceneUtil::Mask_Pathgrid); getWorldspaceWidget().reset(Mask_Pathgrid);
} }
void PathgridMode::dragAborted() void PathgridMode::dragAborted()
{ {
getWorldspaceWidget().reset(SceneUtil::Mask_Pathgrid); getWorldspaceWidget().reset(Mask_Pathgrid);
} }
} }

View file

@ -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, SceneUtil::Mask_Pathgrid) : SelectionMode(parent, worldspaceWidget, 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 (SceneUtil::Mask_Pathgrid); std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (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 (SceneUtil::Mask_Pathgrid); std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (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)
{ {

View file

@ -17,7 +17,6 @@
#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"
@ -26,6 +25,7 @@
#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(SceneUtil::Mask_Lighting); lightMgr->setLightingMask(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,8 +88,6 @@ 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(~(SceneUtil::Mask_UpdateVisitor));
viewer.addView(mView); viewer.addView(mView);
viewer.setDone(false); viewer.setDone(false);
viewer.realize(); viewer.realize();
@ -122,7 +120,7 @@ void RenderWidget::flagAsModified()
void RenderWidget::setVisibilityMask(int mask) void RenderWidget::setVisibilityMask(int mask)
{ {
mView->getCamera()->setCullMask(mask | SceneUtil::Mask_ParticleSystem | SceneUtil::Mask_Lighting); mView->getCamera()->setCullMask(mask | Mask_ParticleSystem | Mask_Lighting);
} }
osg::Camera *RenderWidget::getCamera() osg::Camera *RenderWidget::getCamera()
@ -212,7 +210,7 @@ SceneWidget::SceneWidget(std::shared_ptr<Resource::ResourceSystem> resourceSyste
mOrbitCamControl = new OrbitCameraController(this); mOrbitCamControl = new OrbitCameraController(this);
mCurrentCamControl = mFreeCamControl; mCurrentCamControl = mFreeCamControl;
mOrbitCamControl->setPickingMask(SceneUtil::Mask_EditorReference | SceneUtil::Mask_Terrain); mOrbitCamControl->setPickingMask(Mask_Reference | 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() );
@ -221,7 +219,7 @@ SceneWidget::SceneWidget(std::shared_ptr<Resource::ResourceSystem> resourceSyste
setLighting(&mLightingDay); setLighting(&mLightingDay);
mResourceSystem->getSceneManager()->setParticleSystemMask(SceneUtil::Mask_ParticleSystem); mResourceSystem->getSceneManager()->setParticleSystemMask(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);
@ -350,7 +348,7 @@ void SceneWidget::update(double dt)
} }
else else
{ {
mCurrentCamControl->setup(mRootNode, SceneUtil::Mask_EditorReference | SceneUtil::Mask_Terrain, CameraController::WorldUp); mCurrentCamControl->setup(mRootNode, Mask_Reference | Mask_Terrain, CameraController::WorldUp);
mCamPositionSet = true; mCamPositionSet = true;
} }
} }

View file

@ -3,6 +3,8 @@
#include "../widget/scenetoolmode.hpp" #include "../widget/scenetoolmode.hpp"
#include "mask.hpp"
class QAction; class QAction;
namespace CSVRender namespace CSVRender

View file

@ -1,9 +1,9 @@
#include "tagbase.hpp" #include "tagbase.hpp"
CSVRender::TagBase::TagBase (SceneUtil::VisMask mask) : mMask (mask) {} CSVRender::TagBase::TagBase (Mask mask) : mMask (mask) {}
SceneUtil::VisMask CSVRender::TagBase::getMask() const CSVRender::Mask CSVRender::TagBase::getMask() const
{ {
return mMask; return mMask;
} }

View file

@ -5,19 +5,19 @@
#include <QString> #include <QString>
#include <components/sceneutil/vismask.hpp> #include "mask.hpp"
namespace CSVRender namespace CSVRender
{ {
class TagBase : public osg::Referenced class TagBase : public osg::Referenced
{ {
SceneUtil::VisMask mMask; Mask mMask;
public: public:
TagBase (SceneUtil::VisMask mask); TagBase (Mask mask);
SceneUtil::VisMask getMask() const; Mask getMask() const;
virtual QString getToolTip (bool hideBasics) const; virtual QString getToolTip (bool hideBasics) const;

View file

@ -171,9 +171,6 @@ void CSVRender::TerrainSelection::drawTextureSelection(const osg::ref_ptr<osg::V
{ {
if (!mSelection.empty()) if (!mSelection.empty())
{ {
// Nudge selection by 1/4th of a texture size, similar how blendmaps are nudged
const float nudgePercentage = 0.25f;
const int nudgeOffset = (ESM::Land::REAL_SIZE / ESM::Land::LAND_TEXTURE_SIZE) * nudgePercentage;
const int landHeightsNudge = (ESM::Land::REAL_SIZE / ESM::Land::LAND_SIZE) / (ESM::Land::LAND_SIZE - 1); // Does this work with all land size configurations? const int landHeightsNudge = (ESM::Land::REAL_SIZE / ESM::Land::LAND_SIZE) / (ESM::Land::LAND_SIZE - 1); // Does this work with all land size configurations?
const int textureSizeToLandSizeModifier = (ESM::Land::LAND_SIZE - 1) / ESM::Land::LAND_TEXTURE_SIZE; const int textureSizeToLandSizeModifier = (ESM::Land::LAND_SIZE - 1) / ESM::Land::LAND_TEXTURE_SIZE;
@ -196,10 +193,10 @@ void CSVRender::TerrainSelection::drawTextureSelection(const osg::ref_ptr<osg::V
{ {
for(int i = 1; i < (textureSizeToLandSizeModifier + 1); i++) for(int i = 1; i < (textureSizeToLandSizeModifier + 1); i++)
{ {
float drawPreviousX = CSMWorld::CellCoordinates::textureGlobalToWorldCoords(x) + (i - 1) * (ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1)); float drawPreviousX = CSMWorld::CellCoordinates::textureGlobalXToWorldCoords(x) + (i - 1) * (ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1));
float drawCurrentX = CSMWorld::CellCoordinates::textureGlobalToWorldCoords(x) + i * (ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1)); float drawCurrentX = CSMWorld::CellCoordinates::textureGlobalXToWorldCoords(x) + i * (ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1));
vertices->push_back(osg::Vec3f(drawPreviousX + nudgeOffset, CSMWorld::CellCoordinates::textureGlobalToWorldCoords(y + 1) - nudgeOffset, calculateLandHeight(x1+(i-1), y2)+2)); vertices->push_back(osg::Vec3f(drawPreviousX, CSMWorld::CellCoordinates::textureGlobalYToWorldCoords(y + 1), calculateLandHeight(x1+(i-1), y2)+2));
vertices->push_back(osg::Vec3f(drawCurrentX + nudgeOffset, CSMWorld::CellCoordinates::textureGlobalToWorldCoords(y + 1) - nudgeOffset, calculateLandHeight(x1+i, y2)+2)); vertices->push_back(osg::Vec3f(drawCurrentX, CSMWorld::CellCoordinates::textureGlobalYToWorldCoords(y + 1), calculateLandHeight(x1+i, y2)+2));
} }
} }
@ -208,10 +205,10 @@ void CSVRender::TerrainSelection::drawTextureSelection(const osg::ref_ptr<osg::V
{ {
for(int i = 1; i < (textureSizeToLandSizeModifier + 1); i++) for(int i = 1; i < (textureSizeToLandSizeModifier + 1); i++)
{ {
float drawPreviousX = CSMWorld::CellCoordinates::textureGlobalToWorldCoords(x) + (i - 1) *(ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1)); float drawPreviousX = CSMWorld::CellCoordinates::textureGlobalXToWorldCoords(x) + (i - 1) *(ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1));
float drawCurrentX = CSMWorld::CellCoordinates::textureGlobalToWorldCoords(x) + i * (ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1)); float drawCurrentX = CSMWorld::CellCoordinates::textureGlobalXToWorldCoords(x) + i * (ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1));
vertices->push_back(osg::Vec3f(drawPreviousX + nudgeOffset, CSMWorld::CellCoordinates::textureGlobalToWorldCoords(y) - nudgeOffset, calculateLandHeight(x1+(i-1), y1)+2)); vertices->push_back(osg::Vec3f(drawPreviousX, CSMWorld::CellCoordinates::textureGlobalYToWorldCoords(y), calculateLandHeight(x1+(i-1), y1)+2));
vertices->push_back(osg::Vec3f(drawCurrentX + nudgeOffset, CSMWorld::CellCoordinates::textureGlobalToWorldCoords(y) - nudgeOffset, calculateLandHeight(x1+i, y1)+2)); vertices->push_back(osg::Vec3f(drawCurrentX, CSMWorld::CellCoordinates::textureGlobalYToWorldCoords(y), calculateLandHeight(x1+i, y1)+2));
} }
} }
@ -220,10 +217,10 @@ void CSVRender::TerrainSelection::drawTextureSelection(const osg::ref_ptr<osg::V
{ {
for(int i = 1; i < (textureSizeToLandSizeModifier + 1); i++) for(int i = 1; i < (textureSizeToLandSizeModifier + 1); i++)
{ {
float drawPreviousY = CSMWorld::CellCoordinates::textureGlobalToWorldCoords(y) + (i - 1) * (ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1)); float drawPreviousY = CSMWorld::CellCoordinates::textureGlobalYToWorldCoords(y) + (i - 1) * (ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1));
float drawCurrentY = CSMWorld::CellCoordinates::textureGlobalToWorldCoords(y) + i * (ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1)); float drawCurrentY = CSMWorld::CellCoordinates::textureGlobalYToWorldCoords(y) + i * (ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1));
vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::textureGlobalToWorldCoords(x + 1) + nudgeOffset, drawPreviousY - nudgeOffset, calculateLandHeight(x2, y1+(i-1))+2)); vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::textureGlobalXToWorldCoords(x + 1), drawPreviousY, calculateLandHeight(x2, y1+(i-1))+2));
vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::textureGlobalToWorldCoords(x + 1) + nudgeOffset, drawCurrentY - nudgeOffset, calculateLandHeight(x2, y1+i)+2)); vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::textureGlobalXToWorldCoords(x + 1), drawCurrentY, calculateLandHeight(x2, y1+i)+2));
} }
} }
@ -232,10 +229,10 @@ void CSVRender::TerrainSelection::drawTextureSelection(const osg::ref_ptr<osg::V
{ {
for(int i = 1; i < (textureSizeToLandSizeModifier + 1); i++) for(int i = 1; i < (textureSizeToLandSizeModifier + 1); i++)
{ {
float drawPreviousY = CSMWorld::CellCoordinates::textureGlobalToWorldCoords(y) + (i - 1) * (ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1)); float drawPreviousY = CSMWorld::CellCoordinates::textureGlobalYToWorldCoords(y) + (i - 1) * (ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1));
float drawCurrentY = CSMWorld::CellCoordinates::textureGlobalToWorldCoords(y) + i * (ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1)); float drawCurrentY = CSMWorld::CellCoordinates::textureGlobalYToWorldCoords(y) + i * (ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1));
vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::textureGlobalToWorldCoords(x) + nudgeOffset, drawPreviousY - nudgeOffset, calculateLandHeight(x1, y1+(i-1))+2)); vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::textureGlobalXToWorldCoords(x), drawPreviousY, calculateLandHeight(x1, y1+(i-1))+2));
vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::textureGlobalToWorldCoords(x) + nudgeOffset, drawCurrentY - nudgeOffset, calculateLandHeight(x1, y1+i)+2)); vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::textureGlobalXToWorldCoords(x), drawCurrentY, calculateLandHeight(x1, y1+i)+2));
} }
} }
} }

View file

@ -17,7 +17,6 @@
#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"
@ -37,14 +36,16 @@
#include "../../model/world/tablemimedata.hpp" #include "../../model/world/tablemimedata.hpp"
#include "../../model/world/universalid.hpp" #include "../../model/world/universalid.hpp"
#include "brushdraw.hpp"
#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"}, SceneUtil::Mask_Terrain | SceneUtil::Mask_EditorReference, "Terrain land editing", parent), : EditMode (worldspaceWidget, QIcon {":scenetoolbar/editing-terrain-shape"}, Mask_Terrain | Mask_Reference, "Terrain land editing", parent),
mParentNode(parentNode) mParentNode(parentNode)
{ {
} }
@ -67,6 +68,9 @@ void CSVRender::TerrainShapeMode::activate(CSVWidget::SceneToolbar* toolbar)
connect(mShapeBrushScenetool->mShapeBrushWindow->mToolStrengthSlider, SIGNAL(valueChanged(int)), this, SLOT(setShapeEditToolStrength(int))); connect(mShapeBrushScenetool->mShapeBrushWindow->mToolStrengthSlider, SIGNAL(valueChanged(int)), this, SLOT(setShapeEditToolStrength(int)));
} }
if (!mBrushDraw)
mBrushDraw.reset(new BrushDraw(mParentNode));
EditMode::activate(toolbar); EditMode::activate(toolbar);
toolbar->addTool (mShapeBrushScenetool); toolbar->addTool (mShapeBrushScenetool);
} }
@ -83,6 +87,9 @@ void CSVRender::TerrainShapeMode::deactivate(CSVWidget::SceneToolbar* toolbar)
mTerrainShapeSelection.reset(); mTerrainShapeSelection.reset();
} }
if (mBrushDraw)
mBrushDraw.reset();
EditMode::deactivate(toolbar); EditMode::deactivate(toolbar);
} }
@ -1382,6 +1389,15 @@ void CSVRender::TerrainShapeMode::dragMoveEvent (QDragMoveEvent *event)
{ {
} }
void CSVRender::TerrainShapeMode::mouseMoveEvent (QMouseEvent *event)
{
WorldspaceHitResult hit = getWorldspaceWidget().mousePick(event->pos(), getInteractionMask());
if (hit.hit && mBrushDraw && !(mShapeEditTool == ShapeEditTool_Drag && mIsEditing))
mBrushDraw->update(hit.worldPos, mBrushSize, mBrushShape);
if (!hit.hit && mBrushDraw && !(mShapeEditTool == ShapeEditTool_Drag && mIsEditing))
mBrushDraw->hide();
}
void CSVRender::TerrainShapeMode::setBrushSize(int brushSize) void CSVRender::TerrainShapeMode::setBrushSize(int brushSize)
{ {
mBrushSize = brushSize; mBrushSize = brushSize;

View file

@ -19,6 +19,7 @@
#include "../widget/brushshapes.hpp" #include "../widget/brushshapes.hpp"
#endif #endif
#include "brushdraw.hpp"
#include "terrainselection.hpp" #include "terrainselection.hpp"
namespace CSVWidget namespace CSVWidget
@ -89,6 +90,7 @@ namespace CSVRender
void dragWheel (int diff, double speedFactor) final; void dragWheel (int diff, double speedFactor) final;
void dragMoveEvent (QDragMoveEvent *event) final; void dragMoveEvent (QDragMoveEvent *event) final;
void mouseMoveEvent (QMouseEvent *event) final;
private: private:
@ -168,6 +170,7 @@ namespace CSVRender
std::string mBrushTexture; std::string mBrushTexture;
int mBrushSize = 1; int mBrushSize = 1;
CSVWidget::BrushShape mBrushShape = CSVWidget::BrushShape_Point; CSVWidget::BrushShape mBrushShape = CSVWidget::BrushShape_Point;
std::unique_ptr<BrushDraw> mBrushDraw;
std::vector<std::pair<int, int>> mCustomBrushShape; std::vector<std::pair<int, int>> mCustomBrushShape;
CSVWidget::SceneToolShapeBrush *mShapeBrushScenetool = nullptr; CSVWidget::SceneToolShapeBrush *mShapeBrushScenetool = nullptr;
int mDragMode = InteractionType_None; int mDragMode = InteractionType_None;

View file

@ -13,7 +13,6 @@
#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"
@ -32,17 +31,20 @@
#include "../../model/world/resourcetable.hpp" #include "../../model/world/resourcetable.hpp"
#include "../../model/world/tablemimedata.hpp" #include "../../model/world/tablemimedata.hpp"
#include "../../model/world/universalid.hpp" #include "../../model/world/universalid.hpp"
#include "../widget/brushshapes.hpp"
#include "brushdraw.hpp"
#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"}, SceneUtil::Mask_Terrain | SceneUtil::Mask_EditorReference, "Terrain texture editing", parent), : EditMode (worldspaceWidget, QIcon {":scenetoolbar/editing-terrain-texture"}, Mask_Terrain | Mask_Reference, "Terrain texture editing", parent),
mBrushTexture("L0#0"), mBrushTexture("L0#0"),
mBrushSize(1), mBrushSize(1),
mBrushShape(0), mBrushShape(CSVWidget::BrushShape_Point),
mTextureBrushScenetool(nullptr), mTextureBrushScenetool(nullptr),
mDragMode(InteractionType_None), mDragMode(InteractionType_None),
mParentNode(parentNode), mParentNode(parentNode),
@ -57,7 +59,7 @@ void CSVRender::TerrainTextureMode::activate(CSVWidget::SceneToolbar* toolbar)
mTextureBrushScenetool = new CSVWidget::SceneToolTextureBrush (toolbar, "scenetooltexturebrush", getWorldspaceWidget().getDocument()); mTextureBrushScenetool = new CSVWidget::SceneToolTextureBrush (toolbar, "scenetooltexturebrush", getWorldspaceWidget().getDocument());
connect(mTextureBrushScenetool, SIGNAL (clicked()), mTextureBrushScenetool, SLOT (activate())); connect(mTextureBrushScenetool, SIGNAL (clicked()), mTextureBrushScenetool, SLOT (activate()));
connect(mTextureBrushScenetool->mTextureBrushWindow, SIGNAL(passBrushSize(int)), this, SLOT(setBrushSize(int))); connect(mTextureBrushScenetool->mTextureBrushWindow, SIGNAL(passBrushSize(int)), this, SLOT(setBrushSize(int)));
connect(mTextureBrushScenetool->mTextureBrushWindow, SIGNAL(passBrushShape(int)), this, SLOT(setBrushShape(int))); connect(mTextureBrushScenetool->mTextureBrushWindow, SIGNAL(passBrushShape(CSVWidget::BrushShape)), this, SLOT(setBrushShape(CSVWidget::BrushShape)));
connect(mTextureBrushScenetool->mTextureBrushWindow->mSizeSliders->mBrushSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(setBrushSize(int))); connect(mTextureBrushScenetool->mTextureBrushWindow->mSizeSliders->mBrushSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(setBrushSize(int)));
connect(mTextureBrushScenetool, SIGNAL(passTextureId(std::string)), this, SLOT(setBrushTexture(std::string))); connect(mTextureBrushScenetool, SIGNAL(passTextureId(std::string)), this, SLOT(setBrushTexture(std::string)));
connect(mTextureBrushScenetool->mTextureBrushWindow, SIGNAL(passTextureId(std::string)), this, SLOT(setBrushTexture(std::string))); connect(mTextureBrushScenetool->mTextureBrushWindow, SIGNAL(passTextureId(std::string)), this, SLOT(setBrushTexture(std::string)));
@ -72,6 +74,9 @@ void CSVRender::TerrainTextureMode::activate(CSVWidget::SceneToolbar* toolbar)
mTerrainTextureSelection.reset(new TerrainSelection(mParentNode, &getWorldspaceWidget(), TerrainSelectionType::Texture)); mTerrainTextureSelection.reset(new TerrainSelection(mParentNode, &getWorldspaceWidget(), TerrainSelectionType::Texture));
} }
if (!mBrushDraw)
mBrushDraw.reset(new BrushDraw(mParentNode, true));
EditMode::activate(toolbar); EditMode::activate(toolbar);
toolbar->addTool (mTextureBrushScenetool); toolbar->addTool (mTextureBrushScenetool);
} }
@ -90,6 +95,9 @@ void CSVRender::TerrainTextureMode::deactivate(CSVWidget::SceneToolbar* toolbar)
mTerrainTextureSelection.reset(); mTerrainTextureSelection.reset();
} }
if (mBrushDraw)
mBrushDraw.reset();
EditMode::deactivate(toolbar); EditMode::deactivate(toolbar);
} }
@ -328,11 +336,9 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe
std::string mBrushTextureInt = mBrushTexture.substr (hashlocation+1); std::string mBrushTextureInt = mBrushTexture.substr (hashlocation+1);
int brushInt = stoi(mBrushTexture.substr (hashlocation+1))+1; // All indices are offset by +1 int brushInt = stoi(mBrushTexture.substr (hashlocation+1))+1; // All indices are offset by +1
int rf = mBrushSize / 2; int r = static_cast<float>(mBrushSize) / 2;
int r = mBrushSize / 2 + 1;
int distance = 0;
if (mBrushShape == 0) if (mBrushShape == CSVWidget::BrushShape_Point)
{ {
CSMWorld::LandTexturesColumn::DataType newTerrainPointer = landTable.data(landTable.getModelIndex(mCellId, textureColumn)).value<CSMWorld::LandTexturesColumn::DataType>(); CSMWorld::LandTexturesColumn::DataType newTerrainPointer = landTable.data(landTable.getModelIndex(mCellId, textureColumn)).value<CSMWorld::LandTexturesColumn::DataType>();
CSMWorld::LandTexturesColumn::DataType newTerrain(newTerrainPointer); CSMWorld::LandTexturesColumn::DataType newTerrain(newTerrainPointer);
@ -344,7 +350,7 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe
} }
} }
if (mBrushShape == 1) if (mBrushShape == CSVWidget::BrushShape_Square)
{ {
int upperLeftCellX = cellX - std::floor(r / landTextureSize); int upperLeftCellX = cellX - std::floor(r / landTextureSize);
int upperLeftCellY = cellY - std::floor(r / landTextureSize); int upperLeftCellY = cellY - std::floor(r / landTextureSize);
@ -394,7 +400,7 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe
} }
} }
if (mBrushShape == 2) if (mBrushShape == CSVWidget::BrushShape_Circle)
{ {
int upperLeftCellX = cellX - std::floor(r / landTextureSize); int upperLeftCellX = cellX - std::floor(r / landTextureSize);
int upperLeftCellY = cellY - std::floor(r / landTextureSize); int upperLeftCellY = cellY - std::floor(r / landTextureSize);
@ -419,7 +425,6 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe
{ {
for(int j = 0; j < landTextureSize; j++) for(int j = 0; j < landTextureSize; j++)
{ {
if (i_cell == cellX && j_cell == cellY && abs(i-xHitInCell) < r && abs(j-yHitInCell) < r) if (i_cell == cellX && j_cell == cellY && abs(i-xHitInCell) < r && abs(j-yHitInCell) < r)
{ {
int distanceX(0); int distanceX(0);
@ -430,7 +435,8 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe
if (j_cell > cellY) distanceY = -yHitInCell + landTextureSize * abs(j_cell-cellY) + j; if (j_cell > cellY) distanceY = -yHitInCell + landTextureSize * abs(j_cell-cellY) + j;
if (i_cell == cellX) distanceX = abs(i-xHitInCell); if (i_cell == cellX) distanceX = abs(i-xHitInCell);
if (j_cell == cellY) distanceY = abs(j-yHitInCell); if (j_cell == cellY) distanceY = abs(j-yHitInCell);
distance = std::round(sqrt(pow(distanceX, 2)+pow(distanceY, 2))); float distance = std::round(sqrt(pow(distanceX, 2)+pow(distanceY, 2)));
float rf = static_cast<float>(mBrushSize) / 2;
if (distance < rf) newTerrain[j*landTextureSize+i] = brushInt; if (distance < rf) newTerrain[j*landTextureSize+i] = brushInt;
} }
else else
@ -443,7 +449,8 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe
if (j_cell > cellY) distanceY = -yHitInCell + landTextureSize * abs(j_cell-cellY) + j; if (j_cell > cellY) distanceY = -yHitInCell + landTextureSize * abs(j_cell-cellY) + j;
if (i_cell == cellX) distanceX = abs(i-xHitInCell); if (i_cell == cellX) distanceX = abs(i-xHitInCell);
if (j_cell == cellY) distanceY = abs(j-yHitInCell); if (j_cell == cellY) distanceY = abs(j-yHitInCell);
distance = std::round(sqrt(pow(distanceX, 2)+pow(distanceY, 2))); float distance = std::round(sqrt(pow(distanceX, 2)+pow(distanceY, 2)));
float rf = static_cast<float>(mBrushSize) / 2;
if (distance < rf) newTerrain[j*landTextureSize+i] = brushInt; if (distance < rf) newTerrain[j*landTextureSize+i] = brushInt;
} }
} }
@ -454,7 +461,7 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe
} }
} }
if (mBrushShape == 3) if (mBrushShape == CSVWidget::BrushShape_Custom)
{ {
CSMWorld::LandTexturesColumn::DataType newTerrainPointer = landTable.data(landTable.getModelIndex(mCellId, textureColumn)).value<CSMWorld::LandTexturesColumn::DataType>(); CSMWorld::LandTexturesColumn::DataType newTerrainPointer = landTable.data(landTable.getModelIndex(mCellId, textureColumn)).value<CSMWorld::LandTexturesColumn::DataType>();
CSMWorld::LandTexturesColumn::DataType newTerrain(newTerrainPointer); CSMWorld::LandTexturesColumn::DataType newTerrain(newTerrainPointer);
@ -506,12 +513,12 @@ void CSVRender::TerrainTextureMode::selectTerrainTextures(const std::pair<int, i
int r = mBrushSize / 2; int r = mBrushSize / 2;
std::vector<std::pair<int, int>> selections; std::vector<std::pair<int, int>> selections;
if (mBrushShape == 0) if (mBrushShape == CSVWidget::BrushShape_Point)
{ {
if (isInCellSelection(texCoords.first, texCoords.second)) selections.emplace_back(texCoords); if (isInCellSelection(texCoords.first, texCoords.second)) selections.emplace_back(texCoords);
} }
if (mBrushShape == 1) if (mBrushShape == CSVWidget::BrushShape_Square)
{ {
for (int i = -r; i <= r; i++) for (int i = -r; i <= r; i++)
{ {
@ -527,14 +534,15 @@ void CSVRender::TerrainTextureMode::selectTerrainTextures(const std::pair<int, i
} }
} }
if (mBrushShape == 2) if (mBrushShape == CSVWidget::BrushShape_Circle)
{ {
for (int i = -r; i <= r; i++) for (int i = -r; i <= r; i++)
{ {
for (int j = -r; j <= r; j++) for (int j = -r; j <= r; j++)
{ {
osg::Vec2f coords(i,j); osg::Vec2f coords(i,j);
if (std::round(coords.length()) < r) float rf = static_cast<float>(mBrushSize) / 2;
if (std::round(coords.length()) < rf)
{ {
int x = i + texCoords.first; int x = i + texCoords.first;
int y = j + texCoords.second; int y = j + texCoords.second;
@ -547,7 +555,7 @@ void CSVRender::TerrainTextureMode::selectTerrainTextures(const std::pair<int, i
} }
} }
if (mBrushShape == 3) if (mBrushShape == CSVWidget::BrushShape_Custom)
{ {
if(!mCustomBrushShape.empty()) if(!mCustomBrushShape.empty())
{ {
@ -707,17 +715,27 @@ void CSVRender::TerrainTextureMode::dragMoveEvent (QDragMoveEvent *event)
{ {
} }
void CSVRender::TerrainTextureMode::mouseMoveEvent (QMouseEvent *event)
{
WorldspaceHitResult hit = getWorldspaceWidget().mousePick(event->pos(), getInteractionMask());
if (hit.hit && mBrushDraw)
mBrushDraw->update(hit.worldPos, mBrushSize, mBrushShape);
if (!hit.hit && mBrushDraw)
mBrushDraw->hide();
}
void CSVRender::TerrainTextureMode::setBrushSize(int brushSize) void CSVRender::TerrainTextureMode::setBrushSize(int brushSize)
{ {
mBrushSize = brushSize; mBrushSize = brushSize;
} }
void CSVRender::TerrainTextureMode::setBrushShape(int brushShape) void CSVRender::TerrainTextureMode::setBrushShape(CSVWidget::BrushShape brushShape)
{ {
mBrushShape = brushShape; mBrushShape = brushShape;
//Set custom brush shape //Set custom brush shape
if (mBrushShape == 3 && !mTerrainTextureSelection->getTerrainSelection().empty()) if (mBrushShape == CSVWidget::BrushShape_Custom && !mTerrainTextureSelection->getTerrainSelection().empty())
{ {
auto terrainSelection = mTerrainTextureSelection->getTerrainSelection(); auto terrainSelection = mTerrainTextureSelection->getTerrainSelection();
int selectionCenterX = 0; int selectionCenterX = 0;

View file

@ -17,6 +17,8 @@
#include "../../model/world/commands.hpp" #include "../../model/world/commands.hpp"
#include "../../model/world/idtable.hpp" #include "../../model/world/idtable.hpp"
#include "../../model/world/landtexture.hpp" #include "../../model/world/landtexture.hpp"
#include "../widget/brushshapes.hpp"
#include "brushdraw.hpp"
#endif #endif
#include "terrainselection.hpp" #include "terrainselection.hpp"
@ -81,6 +83,8 @@ namespace CSVRender
void dragWheel (int diff, double speedFactor) final; void dragWheel (int diff, double speedFactor) final;
void dragMoveEvent (QDragMoveEvent *event) final; void dragMoveEvent (QDragMoveEvent *event) final;
void mouseMoveEvent (QMouseEvent *event) final;
private: private:
/// \brief Handle brush mechanics, maths regarding worldspace hit etc. /// \brief Handle brush mechanics, maths regarding worldspace hit etc.
void editTerrainTextureGrid (const WorldspaceHitResult& hit); void editTerrainTextureGrid (const WorldspaceHitResult& hit);
@ -104,7 +108,8 @@ namespace CSVRender
std::string mCellId; std::string mCellId;
std::string mBrushTexture; std::string mBrushTexture;
int mBrushSize; int mBrushSize;
int mBrushShape; CSVWidget::BrushShape mBrushShape;
std::unique_ptr<BrushDraw> mBrushDraw;
std::vector<std::pair<int, int>> mCustomBrushShape; std::vector<std::pair<int, int>> mCustomBrushShape;
CSVWidget::SceneToolTextureBrush *mTextureBrushScenetool; CSVWidget::SceneToolTextureBrush *mTextureBrushScenetool;
int mDragMode; int mDragMode;
@ -121,7 +126,7 @@ namespace CSVRender
public slots: public slots:
void handleDropEvent(QDropEvent *event); void handleDropEvent(QDropEvent *event);
void setBrushSize(int brushSize); void setBrushSize(int brushSize);
void setBrushShape(int brushShape); void setBrushShape(CSVWidget::BrushShape brushShape);
void setBrushTexture(std::string brushShape); void setBrushTexture(std::string brushShape);
}; };
} }

View file

@ -16,6 +16,7 @@
#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()
@ -303,8 +304,8 @@ void CSVRender::UnpagedWorldspaceWidget::addVisibilitySelectorButtons (
CSVWidget::SceneToolToggle2 *tool) CSVWidget::SceneToolToggle2 *tool)
{ {
WorldspaceWidget::addVisibilitySelectorButtons (tool); WorldspaceWidget::addVisibilitySelectorButtons (tool);
tool->addButton (Button_Terrain, SceneUtil::Mask_Terrain, "Terrain", "", true); tool->addButton (Button_Terrain, 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()

View file

@ -26,9 +26,8 @@
#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"
@ -139,7 +138,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(SceneUtil::Mask_EditorReference); auto selection = getSelection(Mask_Reference);
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()))
@ -346,7 +345,7 @@ unsigned int CSVRender::WorldspaceWidget::getVisibilityMask() const
void CSVRender::WorldspaceWidget::setInteractionMask (unsigned int mask) void CSVRender::WorldspaceWidget::setInteractionMask (unsigned int mask)
{ {
mInteractionMask = mask | SceneUtil::Mask_EditorCellMarker | SceneUtil::Mask_EditorCellArrow; mInteractionMask = mask | Mask_CellMarker | Mask_CellArrow;
} }
unsigned int CSVRender::WorldspaceWidget::getInteractionMask() const unsigned int CSVRender::WorldspaceWidget::getInteractionMask() const
@ -362,9 +361,9 @@ void CSVRender::WorldspaceWidget::setEditLock (bool locked)
void CSVRender::WorldspaceWidget::addVisibilitySelectorButtons ( void CSVRender::WorldspaceWidget::addVisibilitySelectorButtons (
CSVWidget::SceneToolToggle2 *tool) CSVWidget::SceneToolToggle2 *tool)
{ {
tool->addButton (Button_Reference, SceneUtil::Mask_EditorReference, "Instances"); tool->addButton (Button_Reference, Mask_Reference, "Instances");
tool->addButton (Button_Water, SceneUtil::Mask_Water, "Water"); tool->addButton (Button_Water, Mask_Water, "Water");
tool->addButton (Button_Pathgrid, SceneUtil::Mask_Pathgrid, "Pathgrid"); tool->addButton (Button_Pathgrid, Mask_Pathgrid, "Pathgrid");
} }
void CSVRender::WorldspaceWidget::addEditModeSelectorButtons (CSVWidget::SceneToolMode *tool) void CSVRender::WorldspaceWidget::addEditModeSelectorButtons (CSVWidget::SceneToolMode *tool)
@ -613,6 +612,8 @@ void CSVRender::WorldspaceWidget::updateOverlay()
void CSVRender::WorldspaceWidget::mouseMoveEvent (QMouseEvent *event) void CSVRender::WorldspaceWidget::mouseMoveEvent (QMouseEvent *event)
{ {
dynamic_cast<CSVRender::EditMode&> (*mEditMode->getCurrent()).mouseMoveEvent (event);
if (mDragging) if (mDragging)
{ {
int diffX = event->x() - mDragX; int diffX = event->x() - mDragX;

View file

@ -8,6 +8,7 @@
#include "../../model/world/tablemimedata.hpp" #include "../../model/world/tablemimedata.hpp"
#include "scenewidget.hpp" #include "scenewidget.hpp"
#include "mask.hpp"
namespace CSMPrefs namespace CSMPrefs
{ {

View file

@ -57,9 +57,6 @@ CSVWidget::BrushSizeControls::BrushSizeControls(const QString &title, QWidget *p
CSVWidget::TextureBrushWindow::TextureBrushWindow(CSMDoc::Document& document, QWidget *parent) CSVWidget::TextureBrushWindow::TextureBrushWindow(CSMDoc::Document& document, QWidget *parent)
: QFrame(parent, Qt::Popup), : QFrame(parent, Qt::Popup),
mBrushShape(0),
mBrushSize(1),
mBrushTexture("L0#0"),
mDocument(document) mDocument(document)
{ {
mBrushTextureLabel = "Selected texture: " + mBrushTexture + " "; mBrushTextureLabel = "Selected texture: " + mBrushTexture + " ";
@ -207,10 +204,14 @@ void CSVWidget::TextureBrushWindow::setBrushSize(int brushSize)
void CSVWidget::TextureBrushWindow::setBrushShape() void CSVWidget::TextureBrushWindow::setBrushShape()
{ {
if(mButtonPoint->isChecked()) mBrushShape = 0; if (mButtonPoint->isChecked())
if(mButtonSquare->isChecked()) mBrushShape = 1; mBrushShape = CSVWidget::BrushShape_Point;
if(mButtonCircle->isChecked()) mBrushShape = 2; if (mButtonSquare->isChecked())
if(mButtonCustom->isChecked()) mBrushShape = 3; mBrushShape = CSVWidget::BrushShape_Square;
if (mButtonCircle->isChecked())
mBrushShape = CSVWidget::BrushShape_Circle;
if (mButtonCustom->isChecked())
mBrushShape = CSVWidget::BrushShape_Custom;
emit passBrushShape(mBrushShape); emit passBrushShape(mBrushShape);
} }
@ -228,7 +229,7 @@ CSVWidget::SceneToolTextureBrush::SceneToolTextureBrush (SceneToolbar *parent, c
mBrushHistory[0] = "L0#0"; mBrushHistory[0] = "L0#0";
setAcceptDrops(true); setAcceptDrops(true);
connect(mTextureBrushWindow, SIGNAL(passBrushShape(int)), this, SLOT(setButtonIcon(int))); connect(mTextureBrushWindow, SIGNAL(passBrushShape(CSVWidget::BrushShape)), this, SLOT(setButtonIcon(CSVWidget::BrushShape)));
setButtonIcon(mTextureBrushWindow->mBrushShape); setButtonIcon(mTextureBrushWindow->mBrushShape);
mPanel = new QFrame (this, Qt::Popup); mPanel = new QFrame (this, Qt::Popup);
@ -258,31 +259,31 @@ CSVWidget::SceneToolTextureBrush::SceneToolTextureBrush (SceneToolbar *parent, c
} }
void CSVWidget::SceneToolTextureBrush::setButtonIcon (int brushShape) void CSVWidget::SceneToolTextureBrush::setButtonIcon (CSVWidget::BrushShape brushShape)
{ {
QString tooltip = "Change brush settings <p>Currently selected: "; QString tooltip = "Change brush settings <p>Currently selected: ";
switch (brushShape) switch (brushShape)
{ {
case 0: case BrushShape_Point:
setIcon (QIcon (QPixmap (":scenetoolbar/brush-point"))); setIcon (QIcon (QPixmap (":scenetoolbar/brush-point")));
tooltip += mTextureBrushWindow->toolTipPoint; tooltip += mTextureBrushWindow->toolTipPoint;
break; break;
case 1: case BrushShape_Square:
setIcon (QIcon (QPixmap (":scenetoolbar/brush-square"))); setIcon (QIcon (QPixmap (":scenetoolbar/brush-square")));
tooltip += mTextureBrushWindow->toolTipSquare; tooltip += mTextureBrushWindow->toolTipSquare;
break; break;
case 2: case BrushShape_Circle:
setIcon (QIcon (QPixmap (":scenetoolbar/brush-circle"))); setIcon (QIcon (QPixmap (":scenetoolbar/brush-circle")));
tooltip += mTextureBrushWindow->toolTipCircle; tooltip += mTextureBrushWindow->toolTipCircle;
break; break;
case 3: case BrushShape_Custom:
setIcon (QIcon (QPixmap (":scenetoolbar/brush-custom"))); setIcon (QIcon (QPixmap (":scenetoolbar/brush-custom")));
tooltip += mTextureBrushWindow->toolTipCustom; tooltip += mTextureBrushWindow->toolTipCustom;

View file

@ -15,6 +15,7 @@
#include <QPushButton> #include <QPushButton>
#ifndef Q_MOC_RUN #ifndef Q_MOC_RUN
#include "brushshapes.hpp"
#include "scenetool.hpp" #include "scenetool.hpp"
#include "../../model/doc/document.hpp" #include "../../model/doc/document.hpp"
@ -65,9 +66,9 @@ namespace CSVWidget
const QString toolTipCustom = "Paint custom selection (not implemented yet)"; const QString toolTipCustom = "Paint custom selection (not implemented yet)";
private: private:
int mBrushShape; CSVWidget::BrushShape mBrushShape = CSVWidget::BrushShape_Point;
int mBrushSize; int mBrushSize = 1;
std::string mBrushTexture; std::string mBrushTexture = "L0#0";
CSMDoc::Document& mDocument; CSMDoc::Document& mDocument;
QLabel *mSelectedBrush; QLabel *mSelectedBrush;
QGroupBox *mHorizontalGroupBox; QGroupBox *mHorizontalGroupBox;
@ -88,7 +89,7 @@ namespace CSVWidget
signals: signals:
void passBrushSize (int brushSize); void passBrushSize (int brushSize);
void passBrushShape(int brushShape); void passBrushShape(CSVWidget::BrushShape brushShape);
void passTextureId(std::string brushTexture); void passTextureId(std::string brushTexture);
}; };
@ -120,7 +121,7 @@ namespace CSVWidget
friend class CSVRender::TerrainTextureMode; friend class CSVRender::TerrainTextureMode;
public slots: public slots:
void setButtonIcon(int brushShape); void setButtonIcon(CSVWidget::BrushShape brushShape);
void updateBrushHistory (const std::string& mBrushTexture); void updateBrushHistory (const std::string& mBrushTexture);
void clicked (const QModelIndex& index); void clicked (const QModelIndex& index);
virtual void activate(); virtual void activate();

View file

@ -7,6 +7,7 @@
#include <QString> #include <QString>
#include <QtCore/qnamespace.h> #include <QtCore/qnamespace.h>
#include <components/misc/helpviewer.hpp>
#include <components/misc/stringops.hpp> #include <components/misc/stringops.hpp>
#include "../../model/doc/document.hpp" #include "../../model/doc/document.hpp"
@ -155,6 +156,9 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
} }
} }
if (mHelpAction)
menu.addAction (mHelpAction);
menu.exec (event->globalPos()); menu.exec (event->globalPos());
} }
@ -387,6 +391,13 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id,
connect (mEditIdAction, SIGNAL (triggered()), this, SLOT (editCell())); connect (mEditIdAction, SIGNAL (triggered()), this, SLOT (editCell()));
addAction (mEditIdAction); addAction (mEditIdAction);
mHelpAction = new QAction (tr ("Help"), this);
connect (mHelpAction, SIGNAL (triggered()), this, SLOT (openHelp()));
mHelpAction->setIcon(QIcon(":/info.png"));
addAction (mHelpAction);
CSMPrefs::Shortcut* openHelpShortcut = new CSMPrefs::Shortcut("help", this);
openHelpShortcut->associateAction(mHelpAction);
connect (mProxyModel, SIGNAL (rowsRemoved (const QModelIndex&, int, int)), connect (mProxyModel, SIGNAL (rowsRemoved (const QModelIndex&, int, int)),
this, SLOT (tableSizeUpdate())); this, SLOT (tableSizeUpdate()));
@ -561,6 +572,11 @@ void CSVWorld::Table::editCell()
emit editRequest(mEditIdAction->getCurrentId(), ""); emit editRequest(mEditIdAction->getCurrentId(), "");
} }
void CSVWorld::Table::openHelp()
{
Misc::HelpViewer::openHelp("manuals/openmw-cs/tables.html");
}
void CSVWorld::Table::viewRecord() void CSVWorld::Table::viewRecord()
{ {
if (!(mModel->getFeatures() & CSMWorld::IdTableBase::Feature_View)) if (!(mModel->getFeatures() & CSMWorld::IdTableBase::Feature_View))

View file

@ -65,6 +65,7 @@ namespace CSVWorld
QAction *mPreviewAction; QAction *mPreviewAction;
QAction *mExtendedDeleteAction; QAction *mExtendedDeleteAction;
QAction *mExtendedRevertAction; QAction *mExtendedRevertAction;
QAction *mHelpAction;
TableEditIdAction *mEditIdAction; TableEditIdAction *mEditIdAction;
CSMWorld::IdTableProxyModel *mProxyModel; CSMWorld::IdTableProxyModel *mProxyModel;
CSMWorld::IdTableBase *mModel; CSMWorld::IdTableBase *mModel;
@ -128,6 +129,8 @@ namespace CSVWorld
void editCell(); void editCell();
static void openHelp();
void editRecord(); void editRecord();
void cloneRecord(); void cloneRecord();

View file

@ -15,17 +15,22 @@ set(GAME_HEADER
engine.hpp engine.hpp
) )
if (BULLET_USE_DOUBLES)
add_definitions(-DBT_USE_DOUBLE_PRECISION)
endif()
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 actors objects renderingmanager animation rotatecontroller sky npcanimation vismask
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 recastmesh renderbin actoranimation landmanager navmesh actorspaths recastmesh
) )
add_openmw_dir (mwinput add_openmw_dir (mwinput
inputmanagerimp actions actionmanager bindingsmanager controllermanager controlswitch
inputmanagerimp mousemanager keyboardmanager sdlmappings sensormanager
) )
add_openmw_dir (mwgui add_openmw_dir (mwgui
@ -70,7 +75,9 @@ add_openmw_dir (mwworld
) )
add_openmw_dir (mwphysics add_openmw_dir (mwphysics
physicssystem trace collisiontype actor convert object heightfield physicssystem trace collisiontype actor convert object heightfield closestnotmerayresultcallback
contacttestresultcallback deepestnotmecontacttestresultcallback stepper movementsolver
closestnotmeconvexresultcallback
) )
add_openmw_dir (mwclass add_openmw_dir (mwclass
@ -81,9 +88,10 @@ add_openmw_dir (mwclass
add_openmw_dir (mwmechanics add_openmw_dir (mwmechanics
mechanicsmanagerimp stat creaturestats magiceffects movement actorutil mechanicsmanagerimp stat creaturestats magiceffects movement actorutil
drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow aiavoiddoor aibreathe drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow aiavoiddoor aibreathe
aicast aiescort aiface aiactivate aicombat recharge repair enchanting pathfinding pathgrid security spellsuccess spellcasting aicast aiescort aiface aiactivate aicombat recharge repair enchanting pathfinding pathgrid security spellcasting spellresistance
disease pickpocket levelledlist combat steering obstacle autocalcspell difficultyscaling aicombataction actor summoning disease pickpocket levelledlist combat steering obstacle autocalcspell difficultyscaling aicombataction actor summoning
character actors objects aistate coordinateconverter trading weaponpriority spellpriority weapontype character actors objects aistate coordinateconverter trading weaponpriority spellpriority weapontype spellutil tickableeffects
spellabsorption linkedeffects
) )
add_openmw_dir (mwstate add_openmw_dir (mwstate
@ -246,8 +254,6 @@ if(APPLE)
configure_file("${OpenMW_BINARY_DIR}/settings-default.cfg" ${BUNDLE_RESOURCES_DIR} COPYONLY) configure_file("${OpenMW_BINARY_DIR}/settings-default.cfg" ${BUNDLE_RESOURCES_DIR} COPYONLY)
configure_file("${OpenMW_BINARY_DIR}/openmw.cfg" ${BUNDLE_RESOURCES_DIR} COPYONLY) configure_file("${OpenMW_BINARY_DIR}/openmw.cfg" ${BUNDLE_RESOURCES_DIR} COPYONLY)
configure_file("${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" ${BUNDLE_RESOURCES_DIR} COPYONLY) configure_file("${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" ${BUNDLE_RESOURCES_DIR} COPYONLY)
configure_file("${OpenMW_BINARY_DIR}/gamecontrollerdb_204.txt" ${BUNDLE_RESOURCES_DIR} COPYONLY)
configure_file("${OpenMW_BINARY_DIR}/gamecontrollerdb_205.txt" ${BUNDLE_RESOURCES_DIR} COPYONLY)
add_custom_command(TARGET openmw add_custom_command(TARGET openmw
POST_BUILD POST_BUILD

View file

@ -26,7 +26,6 @@
#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>
@ -48,6 +47,8 @@
#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"
@ -100,8 +101,13 @@ bool OMW::Engine::frame(float frametime)
// When the window is minimized, pause the game. Currently this *has* to be here to work around a MyGUI bug. // When the window is minimized, pause the game. Currently this *has* to be here to work around a MyGUI bug.
// If we are not currently rendering, then RenderItems will not be reused resulting in a memory leak upon changing widget textures (fixed in MyGUI 3.3.2), // If we are not currently rendering, then RenderItems will not be reused resulting in a memory leak upon changing widget textures (fixed in MyGUI 3.3.2),
// and destroyed widgets will not be deleted (not fixed yet, https://github.com/MyGUI/mygui/issues/21) // and destroyed widgets will not be deleted (not fixed yet, https://github.com/MyGUI/mygui/issues/21)
if (!mEnvironment.getInputManager()->isWindowVisible()) if (!mEnvironment.getWindowManager()->isWindowVisible())
{
mEnvironment.getSoundManager()->pausePlayback();
return false; return false;
}
else
mEnvironment.getSoundManager()->resumePlayback();
// sound // sound
if (mUseSound) if (mUseSound)
@ -240,7 +246,9 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
{ {
MWClass::registerClasses(); MWClass::registerClasses();
Uint32 flags = SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE|SDL_INIT_GAMECONTROLLER|SDL_INIT_JOYSTICK; SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0"); // We use only gamepads
Uint32 flags = SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE|SDL_INIT_GAMECONTROLLER|SDL_INIT_JOYSTICK|SDL_INIT_SENSOR;
if(SDL_WasInit(flags) == 0) if(SDL_WasInit(flags) == 0)
{ {
SDL_SetMainReady(); SDL_SetMainReady();
@ -515,22 +523,9 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
else else
Log(Debug::Info) << "Loading keybindings file: " << keybinderUser; Log(Debug::Info) << "Loading keybindings file: " << keybinderUser;
// find correct path to the game controller bindings const std::string userdefault = mCfgMgr.getUserConfigPath().string() + "/gamecontrollerdb.txt";
// File format for controller mappings is different for SDL <= 2.0.4, 2.0.5, and >= 2.0.6 const std::string localdefault = mCfgMgr.getLocalPath().string() + "/gamecontrollerdb.txt";
SDL_version linkedSdlVersion; const std::string globaldefault = mCfgMgr.getGlobalPath().string() + "/gamecontrollerdb.txt";
SDL_GetVersion(&linkedSdlVersion);
std::string controllerFileName;
if (linkedSdlVersion.major == 2 && linkedSdlVersion.minor == 0 && linkedSdlVersion.patch <= 4) {
controllerFileName = "gamecontrollerdb_204.txt";
} else if (linkedSdlVersion.major == 2 && linkedSdlVersion.minor == 0 && linkedSdlVersion.patch == 5) {
controllerFileName = "gamecontrollerdb_205.txt";
} else {
controllerFileName = "gamecontrollerdb.txt";
}
const std::string userdefault = mCfgMgr.getUserConfigPath().string() + "/" + controllerFileName;
const std::string localdefault = mCfgMgr.getLocalPath().string() + "/" + controllerFileName;
const std::string globaldefault = mCfgMgr.getGlobalPath().string() + "/" + controllerFileName;
std::string userGameControllerdb; std::string userGameControllerdb;
if (boost::filesystem::exists(userdefault)){ if (boost::filesystem::exists(userdefault)){
@ -546,6 +541,17 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
gameControllerdb = globaldefault; gameControllerdb = globaldefault;
else else
gameControllerdb = ""; //if it doesn't exist, pass in an empty string gameControllerdb = ""; //if it doesn't exist, pass in an empty string
std::string myguiResources = (mResDir / "mygui").string();
osg::ref_ptr<osg::Group> guiRoot = new osg::Group;
guiRoot->setName("GUI Root");
guiRoot->setNodeMask(MWRender::Mask_GUI);
rootNode->addChild(guiRoot);
MWGui::WindowManager* window = new MWGui::WindowManager(mWindow, mViewer, guiRoot, mResourceSystem.get(), mWorkQueue.get(),
mCfgMgr.getLogPath().string() + std::string("/"), myguiResources,
mScriptConsoleMode, mTranslationDataStorage, mEncoding, mExportFonts,
Version::getOpenmwVersionDescription(mResDir.string()), mCfgMgr.getUserConfigPath().string());
mEnvironment.setWindowManager (window);
MWInput::InputManager* input = MWInput::InputManager* input =
#ifdef USE_OPENXR #ifdef USE_OPENXR
new MWVR::OpenXRInputManager(mWindow, mViewer, mScreenCaptureHandler, mScreenCaptureOperation, keybinderUser, keybinderUserExists, userGameControllerdb, gameControllerdb, mGrab); new MWVR::OpenXRInputManager(mWindow, mViewer, mScreenCaptureHandler, mScreenCaptureOperation, keybinderUser, keybinderUserExists, userGameControllerdb, gameControllerdb, mGrab);
@ -554,17 +560,6 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
#endif #endif
mEnvironment.setInputManager (input); mEnvironment.setInputManager (input);
std::string myguiResources = (mResDir / "mygui").string();
osg::ref_ptr<osg::Group> guiRoot = new osg::Group;
guiRoot->setName("GUI Root");
guiRoot->setNodeMask(SceneUtil::Mask_GUI);
rootNode->addChild(guiRoot);
MWGui::WindowManager* window = new MWGui::WindowManager(mViewer, guiRoot, mResourceSystem.get(), mWorkQueue.get(),
mCfgMgr.getLogPath().string() + std::string("/"), myguiResources,
mScriptConsoleMode, mTranslationDataStorage, mEncoding, mExportFonts,
Version::getOpenmwVersionDescription(mResDir.string()), mCfgMgr.getUserConfigPath().string());
mEnvironment.setWindowManager (window);
// Create sound system // Create sound system
mEnvironment.setSoundManager (new MWSound::SoundManager(mVFS.get(), mUseSound)); mEnvironment.setSoundManager (new MWSound::SoundManager(mVFS.get(), mUseSound));
@ -584,7 +579,6 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
mFileCollections, mContentFiles, mEncoder, mActivationDistanceOverride, mCellName, mFileCollections, mContentFiles, mEncoder, mActivationDistanceOverride, mCellName,
mStartupScript, mResDir.string(), mCfgMgr.getUserDataPath().string())); mStartupScript, mResDir.string(), mCfgMgr.getUserDataPath().string()));
mEnvironment.getWorld()->setupPlayer(); mEnvironment.getWorld()->setupPlayer();
input->setPlayer(&mEnvironment.getWorld()->getPlayer());
window->setStore(mEnvironment.getWorld()->getStore()); window->setStore(mEnvironment.getWorld()->getStore());
window->initUI(); window->initUI();
@ -681,7 +675,6 @@ private:
}; };
// Initialise and enter main loop. // Initialise and enter main loop.
void OMW::Engine::go() void OMW::Engine::go()
{ {
assert (!mContentFiles.empty()); assert (!mContentFiles.empty());
@ -710,7 +703,8 @@ void OMW::Engine::go()
mViewer->setUseConfigureAffinity(false); mViewer->setUseConfigureAffinity(false);
#endif #endif
mScreenCaptureOperation = new WriteScreenshotToFileOperation(mCfgMgr.getUserDataPath().string(), mScreenCaptureOperation = new WriteScreenshotToFileOperation(
mCfgMgr.getScreenshotPath().string(),
Settings::Manager::getString("screenshot format", "General")); Settings::Manager::getString("screenshot format", "General"));
mScreenCaptureHandler = new osgViewer::ScreenCaptureHandler(mScreenCaptureOperation); mScreenCaptureHandler = new osgViewer::ScreenCaptureHandler(mScreenCaptureOperation);

View file

@ -38,8 +38,6 @@ namespace MWBase
virtual ~InputManager() {} virtual ~InputManager() {}
virtual bool isWindowVisible() = 0;
virtual void update(float dt, bool disableControls, bool disableEvents=false) = 0; virtual void update(float dt, bool disableControls, bool disableEvents=false) = 0;
virtual void changeInputMode(bool guiMode) = 0; virtual void changeInputMode(bool guiMode) = 0;
@ -47,6 +45,8 @@ namespace MWBase
virtual void processChangedSettings(const std::set< std::pair<std::string, std::string> >& changed) = 0; virtual void processChangedSettings(const std::set< std::pair<std::string, std::string> >& changed) = 0;
virtual void setDragDrop(bool dragDrop) = 0; virtual void setDragDrop(bool dragDrop) = 0;
virtual void setGamepadGuiCursorEnabled(bool enabled) = 0;
virtual void setAttemptJump(bool jumping) = 0;
virtual void toggleControlSwitch (const std::string& sw, bool value) = 0; virtual void toggleControlSwitch (const std::string& sw, bool value) = 0;
virtual bool getControlSwitch (const std::string& sw) = 0; virtual bool getControlSwitch (const std::string& sw) = 0;
@ -54,8 +54,6 @@ namespace MWBase
virtual std::string getActionDescription (int action) = 0; virtual std::string getActionDescription (int action) = 0;
virtual std::string getActionKeyBindingName (int action) = 0; virtual std::string getActionKeyBindingName (int action) = 0;
virtual std::string getActionControllerBindingName (int action) = 0; virtual std::string getActionControllerBindingName (int action) = 0;
virtual std::string sdlControllerAxisToString(int axis) = 0;
virtual std::string sdlControllerButtonToString(int button) = 0;
///Actions available for binding to keyboard buttons ///Actions available for binding to keyboard buttons
virtual std::vector<int> getActionKeySorting() = 0; virtual std::vector<int> getActionKeySorting() = 0;
///Actions available for binding to controller buttons ///Actions available for binding to controller buttons
@ -71,10 +69,15 @@ namespace MWBase
/// Returns if the last used input device was a joystick or a keyboard /// Returns if the last used input device was a joystick or a keyboard
/// @return true if joystick, false otherwise /// @return true if joystick, false otherwise
virtual bool joystickLastUsed() = 0; virtual bool joystickLastUsed() = 0;
virtual void setJoystickLastUsed(bool enabled) = 0;
virtual int countSavedGameRecords() const = 0; virtual int countSavedGameRecords() const = 0;
virtual void write(ESM::ESMWriter& writer, Loading::Listener& progress) = 0; virtual void write(ESM::ESMWriter& writer, Loading::Listener& progress) = 0;
virtual void readRecord(ESM::ESMReader& reader, uint32_t type) = 0; virtual void readRecord(ESM::ESMReader& reader, uint32_t type) = 0;
virtual void resetIdleTime() = 0;
virtual void executeAction(int action) = 0;
}; };
} }

View file

@ -35,7 +35,7 @@ namespace MWBase
virtual ~ScriptManager() {} virtual ~ScriptManager() {}
virtual void run (const std::string& name, Interpreter::Context& interpreterContext) = 0; virtual bool run (const std::string& name, Interpreter::Context& interpreterContext) = 0;
///< Run the script with the given name (compile first, if not compiled yet) ///< Run the script with the given name (compile first, if not compiled yet)
virtual bool compile (const std::string& name) = 0; virtual bool compile (const std::string& name) = 0;

View file

@ -14,6 +14,14 @@ namespace MWWorld
namespace MWSound namespace MWSound
{ {
// Each entry excepts of MaxCount should be used only in one place
enum BlockerType
{
VideoPlayback,
MaxCount
};
class Sound; class Sound;
class Stream; class Stream;
struct Sound_Decoder; struct Sound_Decoder;
@ -168,12 +176,15 @@ namespace MWBase
///< Is the given sound currently playing on the given object? ///< Is the given sound currently playing on the given object?
/// If you want to check if sound played with playSound is playing, use empty Ptr /// If you want to check if sound played with playSound is playing, use empty Ptr
virtual void pauseSounds(int types=static_cast<int>(Type::Mask)) = 0; virtual void pauseSounds(MWSound::BlockerType blocker, int types=int(Type::Mask)) = 0;
///< Pauses all currently playing sounds, including music. ///< Pauses all currently playing sounds, including music.
virtual void resumeSounds(int types=static_cast<int>(Type::Mask)) = 0; virtual void resumeSounds(MWSound::BlockerType blocker) = 0;
///< Resumes all previously paused sounds. ///< Resumes all previously paused sounds.
virtual void pausePlayback() = 0;
virtual void resumePlayback() = 0;
virtual void update(float duration) = 0; virtual void update(float duration) = 0;
virtual void setListenerPosDir(const osg::Vec3f &pos, const osg::Vec3f &dir, const osg::Vec3f &up, bool underwater) = 0; virtual void setListenerPosDir(const osg::Vec3f &pos, const osg::Vec3f &dir, const osg::Vec3f &up, bool underwater) = 0;

View file

@ -11,6 +11,8 @@
#include "../mwgui/mode.hpp" #include "../mwgui/mode.hpp"
#include <components/sdlutil/events.hpp>
namespace Loading namespace Loading
{ {
class Listener; class Listener;
@ -86,7 +88,7 @@ namespace SFO
namespace MWBase namespace MWBase
{ {
/// \brief Interface for widnow manager (implemented in MWGui) /// \brief Interface for widnow manager (implemented in MWGui)
class WindowManager class WindowManager : public SDLUtil::WindowListener
{ {
WindowManager (const WindowManager&); WindowManager (const WindowManager&);
///< not implemented ///< not implemented
@ -269,8 +271,6 @@ namespace MWBase
virtual void processChangedSettings(const std::set< std::pair<std::string, std::string> >& changed) = 0; virtual void processChangedSettings(const std::set< std::pair<std::string, std::string> >& changed) = 0;
virtual void windowResized(int x, int y) = 0;
virtual void executeInConsole (const std::string& path) = 0; virtual void executeInConsole (const std::string& path) = 0;
virtual void enableRest() = 0; virtual void enableRest() = 0;
@ -361,6 +361,11 @@ namespace MWBase
virtual bool injectKeyPress(MyGUI::KeyCode key, unsigned int text, bool repeat) = 0; virtual bool injectKeyPress(MyGUI::KeyCode key, unsigned int text, bool repeat) = 0;
virtual bool injectKeyRelease(MyGUI::KeyCode key) = 0; virtual bool injectKeyRelease(MyGUI::KeyCode key) = 0;
virtual void windowVisibilityChange(bool visible) = 0;
virtual void windowResized(int x, int y) = 0;
virtual void windowClosed() = 0;
virtual bool isWindowVisible() = 0;
}; };
} }

View file

@ -201,6 +201,8 @@ namespace MWBase
virtual MWWorld::Ptr searchPtrViaActorId (int actorId) = 0; virtual MWWorld::Ptr searchPtrViaActorId (int actorId) = 0;
///< Search is limited to the active cells. ///< Search is limited to the active cells.
virtual MWWorld::Ptr searchPtrViaRefNum (const std::string& id, const ESM::RefNum& refNum) = 0;
virtual MWWorld::Ptr findContainer (const MWWorld::ConstPtr& ptr) = 0; virtual MWWorld::Ptr findContainer (const MWWorld::ConstPtr& ptr) = 0;
///< Return a pointer to a liveCellRef which contains \a ptr. ///< Return a pointer to a liveCellRef which contains \a ptr.
/// \note Search is limited to the active cells. /// \note Search is limited to the active cells.

View file

@ -3,7 +3,6 @@
#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"
@ -20,6 +19,7 @@
#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(SceneUtil::Mask_Static); ptr.getRefData().getBaseNode()->setNodeMask(MWRender::Mask_Static);
} }
} }

View file

@ -177,11 +177,10 @@ namespace MWClass
} }
} }
if ((isLocked || isTrapped) && hasKey) if (isLocked && hasKey)
{ {
MWBase::Environment::get().getWindowManager ()->messageBox (keyName + " #{sKeyUsed}"); MWBase::Environment::get().getWindowManager ()->messageBox (keyName + " #{sKeyUsed}");
if(isLocked) ptr.getCellRef().unlock();
ptr.getCellRef().unlock();
// using a key disarms the trap // using a key disarms the trap
if(isTrapped) if(isTrapped)
{ {

View file

@ -125,6 +125,7 @@ namespace MWClass
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
MWWorld::ManualRef manualRef(store, id); MWWorld::ManualRef manualRef(store, id);
manualRef.getPtr().getCellRef().setPosition(ptr.getCellRef().getPosition()); manualRef.getPtr().getCellRef().setPosition(ptr.getCellRef().getPosition());
manualRef.getPtr().getCellRef().setScale(ptr.getCellRef().getScale());
MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->placeObject(manualRef.getPtr(), ptr.getCell() , ptr.getCellRef().getPosition()); MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->placeObject(manualRef.getPtr(), ptr.getCell() , ptr.getCellRef().getPosition());
customData.mSpawnActorId = placed.getClass().getCreatureStats(placed).getActorId(); customData.mSpawnActorId = placed.getClass().getCreatureStats(placed).getActorId();
customData.mSpawn = false; customData.mSpawn = false;

View file

@ -3,7 +3,6 @@
#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"
@ -26,6 +25,7 @@
#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(SceneUtil::Mask_Static); ptr.getRefData().getBaseNode()->setNodeMask(MWRender::Mask_Static);
} }
} }
@ -158,12 +158,11 @@ namespace MWClass
} }
} }
if ((isLocked || isTrapped) && hasKey) if (isLocked && hasKey)
{ {
if(actor == MWMechanics::getPlayer()) if(actor == MWMechanics::getPlayer())
MWBase::Environment::get().getWindowManager()->messageBox(keyName + " #{sKeyUsed}"); MWBase::Environment::get().getWindowManager()->messageBox(keyName + " #{sKeyUsed}");
if(isLocked) ptr.getCellRef().unlock(); //Call the function here. because that makes sense.
ptr.getCellRef().unlock(); //Call the function here. because that makes sense.
// using a key disarms the trap // using a key disarms the trap
if(isTrapped) if(isTrapped)
{ {

View file

@ -141,8 +141,6 @@ namespace MWClass
MWGui::ToolTipInfo info; MWGui::ToolTipInfo info;
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
bool gold = isGold(ptr); bool gold = isGold(ptr);
if (gold) if (gold)
count *= getValue(ptr); count *= getValue(ptr);
@ -153,18 +151,9 @@ namespace MWClass
else // gold displays its count also if it's 1. else // gold displays its count also if it's 1.
countString = " (" + std::to_string(count) + ")"; countString = " (" + std::to_string(count) + ")";
info.caption = MyGUI::TextIterator::toTagsString(getName(ptr)) + countString; info.caption = MyGUI::TextIterator::toTagsString(getName(ptr)) + countString + MWGui::ToolTips::getSoulString(ptr.getCellRef());
info.icon = ref->mBase->mIcon; info.icon = ref->mBase->mIcon;
if (ref->mRef.getSoul() != "")
{
const ESM::Creature *creature = store.get<ESM::Creature>().search(ref->mRef.getSoul());
if (creature && !creature->mName.empty())
info.caption += " (" + creature->mName + ")";
else if (creature)
info.caption += " (" + creature->mId + ")";
}
std::string text; std::string text;
text += MWGui::ToolTips::getWeightString(ref->mBase->mData.mWeight, "#{sWeight}"); text += MWGui::ToolTips::getWeightString(ref->mBase->mData.mWeight, "#{sWeight}");

View file

@ -2,7 +2,6 @@
#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"
@ -10,6 +9,7 @@
#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(SceneUtil::Mask_Static); ptr.getRefData().getBaseNode()->setNodeMask(MWRender::Mask_Static);
} }
} }

View file

@ -31,6 +31,7 @@ namespace MWGui
{ {
AlchemyWindow::AlchemyWindow() AlchemyWindow::AlchemyWindow()
: WindowBase("openmw_alchemy_window.layout") : WindowBase("openmw_alchemy_window.layout")
, mCurrentFilter(FilterType::ByName)
, mModel(nullptr) , mModel(nullptr)
, mSortModel(nullptr) , mSortModel(nullptr)
, mAlchemy(new MWMechanics::Alchemy()) , mAlchemy(new MWMechanics::Alchemy())
@ -192,16 +193,16 @@ namespace MWGui
std::set<std::string> itemNames, itemEffects; std::set<std::string> itemNames, itemEffects;
for (size_t i = 0; i < mModel->getItemCount(); ++i) for (size_t i = 0; i < mModel->getItemCount(); ++i)
{ {
auto const& base = mModel->getItem(i).mBase; MWWorld::Ptr item = mModel->getItem(i).mBase;
if (base.getTypeName() != typeid(ESM::Ingredient).name()) if (item.getTypeName() != typeid(ESM::Ingredient).name())
continue; continue;
itemNames.insert(base.getClass().getName(base)); itemNames.insert(item.getClass().getName(item));
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr(); MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
auto const alchemySkill = player.getClass().getSkill(player, ESM::Skill::Alchemy); auto const alchemySkill = player.getClass().getSkill(player, ESM::Skill::Alchemy);
auto const effects = MWMechanics::Alchemy::effectsDescription(base, alchemySkill); auto const effects = MWMechanics::Alchemy::effectsDescription(item, alchemySkill);
itemEffects.insert(effects.begin(), effects.end()); itemEffects.insert(effects.begin(), effects.end());
} }

View file

@ -34,6 +34,8 @@ namespace MWGui
/// right edge. The second integer is the height of all /// right edge. The second integer is the height of all
/// text combined prior to pagination. /// text combined prior to pagination.
virtual std::pair <unsigned int, unsigned int> getSize () const = 0; virtual std::pair <unsigned int, unsigned int> getSize () const = 0;
virtual ~TypesetBook() = default;
}; };
struct GlyphInfo struct GlyphInfo
@ -87,8 +89,7 @@ namespace MWGui
typedef uint8_t const * Utf8Point; typedef uint8_t const * Utf8Point;
typedef std::pair <Utf8Point, Utf8Point> Utf8Span; typedef std::pair <Utf8Point, Utf8Point> Utf8Span;
virtual ~BookTypesetter() = default;
enum Alignment { enum Alignment {
AlignLeft = -1, AlignLeft = -1,

View file

@ -16,6 +16,7 @@
#include "draganddrop.hpp" #include "draganddrop.hpp"
#include "countdialog.hpp" #include "countdialog.hpp"
#include "widgets.hpp" #include "widgets.hpp"
#include "tooltips.hpp"
namespace namespace
{ {
@ -86,7 +87,8 @@ void CompanionWindow::onItemSelected(int index)
if (count > 1 && !shift) if (count > 1 && !shift)
{ {
CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog(); CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog();
dialog->openCountDialog(object.getClass().getName(object), "#{sTake}", count); std::string name = object.getClass().getName(object) + MWGui::ToolTips::getSoulString(object.getCellRef());
dialog->openCountDialog(name, "#{sTake}", count);
dialog->eventOkClicked.clear(); dialog->eventOkClicked.clear();
dialog->eventOkClicked += MyGUI::newDelegate(this, &CompanionWindow::dragItem); dialog->eventOkClicked += MyGUI::newDelegate(this, &CompanionWindow::dragItem);
} }

View file

@ -25,6 +25,7 @@
#include "sortfilteritemmodel.hpp" #include "sortfilteritemmodel.hpp"
#include "pickpocketitemmodel.hpp" #include "pickpocketitemmodel.hpp"
#include "draganddrop.hpp" #include "draganddrop.hpp"
#include "tooltips.hpp"
namespace MWGui namespace MWGui
{ {
@ -83,7 +84,8 @@ namespace MWGui
if (count > 1 && !shift) if (count > 1 && !shift)
{ {
CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog(); CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog();
dialog->openCountDialog(object.getClass().getName(object), "#{sTake}", count); std::string name = object.getClass().getName(object) + MWGui::ToolTips::getSoulString(object.getCellRef());
dialog->openCountDialog(name, "#{sTake}", count);
dialog->eventOkClicked.clear(); dialog->eventOkClicked.clear();
dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerWindow::dragItem); dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerWindow::dragItem);
} }

View file

@ -358,7 +358,9 @@ namespace MWGui
void DialogueWindow::onByeClicked(MyGUI::Widget* _sender) void DialogueWindow::onByeClicked(MyGUI::Widget* _sender)
{ {
if (exit()) if (exit())
{
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Dialogue); MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Dialogue);
}
} }
void DialogueWindow::onSelectListItem(const std::string& topic, int id) void DialogueWindow::onSelectListItem(const std::string& topic, int id)
@ -422,9 +424,7 @@ namespace MWGui
bool sameActor = (mPtr == actor); bool sameActor = (mPtr == actor);
if (!sameActor) if (!sameActor)
{ {
for (DialogueText* text : mHistoryContents) // The history is not reset here
delete text;
mHistoryContents.clear();
mKeywords.clear(); mKeywords.clear();
mTopicsList->clear(); mTopicsList->clear();
for (Link* link : mLinks) for (Link* link : mLinks)
@ -479,6 +479,16 @@ namespace MWGui
mDeleteLater.clear(); mDeleteLater.clear();
} }
void DialogueWindow::onClose()
{
if (MWBase::Environment::get().getWindowManager()->containsMode(GM_Dialogue))
return;
// Reset history
for (DialogueText* text : mHistoryContents)
delete text;
mHistoryContents.clear();
}
void DialogueWindow::setKeywords(std::list<std::string> keyWords) void DialogueWindow::setKeywords(std::list<std::string> keyWords)
{ {
if (mKeywords == keyWords && isCompanion() == mIsCompanion) if (mKeywords == keyWords && isCompanion() == mIsCompanion)

View file

@ -133,6 +133,8 @@ namespace MWGui
void updateTopics(); void updateTopics();
void onClose();
protected: protected:
void updateTopicsPane(); void updateTopicsPane();
bool isCompanion(const MWWorld::Ptr& actor); bool isCompanion(const MWWorld::Ptr& actor);

View file

@ -38,6 +38,7 @@
#include "tradewindow.hpp" #include "tradewindow.hpp"
#include "draganddrop.hpp" #include "draganddrop.hpp"
#include "widgets.hpp" #include "widgets.hpp"
#include "tooltips.hpp"
namespace namespace
{ {
@ -302,7 +303,8 @@ namespace MWGui
{ {
CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog(); CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog();
std::string message = mTrading ? "#{sQuanityMenuMessage01}" : "#{sTake}"; std::string message = mTrading ? "#{sQuanityMenuMessage01}" : "#{sTake}";
dialog->openCountDialog(object.getClass().getName(object), message, count); std::string name = object.getClass().getName(object) + MWGui::ToolTips::getSoulString(object.getCellRef());
dialog->openCountDialog(name, message, count);
dialog->eventOkClicked.clear(); dialog->eventOkClicked.clear();
if (mTrading) if (mTrading)
dialog->eventOkClicked += MyGUI::newDelegate(this, &InventoryWindow::sellItem); dialog->eventOkClicked += MyGUI::newDelegate(this, &InventoryWindow::sellItem);
@ -734,7 +736,8 @@ namespace MWGui
&& (type != typeid(ESM::Potion).name())) && (type != typeid(ESM::Potion).name()))
return; return;
if (object.getClass().getName(object) == "") // objects without name presented to user can never be picked up // An object that can be picked up must have a tooltip.
if (!object.getClass().hasToolTip(object))
return; return;
int count = object.getRefData().getCount(); int count = object.getRefData().getCount();

View file

@ -32,26 +32,6 @@ namespace MWGui
{ {
} }
bool ItemStack::stacks(const ItemStack &other)
{
if(mBase == other.mBase)
return true;
// If one of the items is in an inventory and currently equipped, we need to check stacking both ways to be sure
if (mBase.getContainerStore() && other.mBase.getContainerStore())
return mBase.getContainerStore()->stacks(mBase, other.mBase)
&& other.mBase.getContainerStore()->stacks(mBase, other.mBase);
if (mBase.getContainerStore())
return mBase.getContainerStore()->stacks(mBase, other.mBase);
if (other.mBase.getContainerStore())
return other.mBase.getContainerStore()->stacks(mBase, other.mBase);
MWWorld::ContainerStore store;
return store.stacks(mBase, other.mBase);
}
bool operator == (const ItemStack& left, const ItemStack& right) bool operator == (const ItemStack& left, const ItemStack& right)
{ {
if (left.mType != right.mType) if (left.mType != right.mType)

View file

@ -13,7 +13,6 @@ namespace MWGui
{ {
ItemStack (const MWWorld::Ptr& base, ItemModel* creator, size_t count); ItemStack (const MWWorld::Ptr& base, ItemModel* creator, size_t count);
ItemStack(); ItemStack();
bool stacks (const ItemStack& other);
///< like operator==, only without checking mType ///< like operator==, only without checking mType
enum Type enum Type

View file

@ -39,6 +39,8 @@ namespace MWGui
/// and end of the span relative to the body, and a valid topic ID if /// and end of the span relative to the body, and a valid topic ID if
/// the span represents a keyword, or zero if not. /// the span represents a keyword, or zero if not.
virtual void visitSpans (std::function <void (TopicId, size_t, size_t)> visitor) const = 0; virtual void visitSpans (std::function <void (TopicId, size_t, size_t)> visitor) const = 0;
virtual ~Entry() = default;
}; };
/// An interface to topic data. /// An interface to topic data.
@ -47,6 +49,8 @@ namespace MWGui
/// Returns a pre-formatted span of UTF8 encoded text representing /// Returns a pre-formatted span of UTF8 encoded text representing
/// the name of the NPC this portion of dialog was heard from. /// the name of the NPC this portion of dialog was heard from.
virtual Utf8Span source () const = 0; virtual Utf8Span source () const = 0;
virtual ~TopicEntry() = default;
}; };
/// An interface to journal data. /// An interface to journal data.
@ -55,8 +59,9 @@ namespace MWGui
/// Returns a pre-formatted span of UTF8 encoded text representing /// Returns a pre-formatted span of UTF8 encoded text representing
/// the in-game date this entry was added to the journal. /// the in-game date this entry was added to the journal.
virtual Utf8Span timestamp () const = 0; virtual Utf8Span timestamp () const = 0;
};
virtual ~JournalEntry() = default;
};
/// called prior to journal opening /// called prior to journal opening
virtual void load () = 0; virtual void load () = 0;
@ -85,6 +90,8 @@ namespace MWGui
// create an instance of the default journal view model implementation // create an instance of the default journal view model implementation
static Ptr create (); static Ptr create ();
virtual ~JournalViewModel() = default;
}; };
} }

View file

@ -116,6 +116,12 @@ void KeyboardNavigation::onFrame()
if (!mEnabled) if (!mEnabled)
return; return;
if (!MWBase::Environment::get().getWindowManager()->isGuiMode())
{
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(nullptr);
return;
}
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget(); MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
if (focus == mCurrentFocus) if (focus == mCurrentFocus)
@ -215,6 +221,9 @@ bool KeyboardNavigation::injectKeyPress(MyGUI::KeyCode key, unsigned int text, b
bool KeyboardNavigation::switchFocus(int direction, bool wrap) bool KeyboardNavigation::switchFocus(int direction, bool wrap)
{ {
if (!MWBase::Environment::get().getWindowManager()->isGuiMode())
return false;
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget(); MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
bool isCycle = (direction == D_Prev || direction == D_Next); bool isCycle = (direction == D_Prev || direction == D_Next);

View file

@ -1,5 +1,7 @@
#include "loadingscreen.hpp" #include "loadingscreen.hpp"
#include <array>
#include <osgViewer/Viewer> #include <osgViewer/Viewer>
#include <osg/Texture2D> #include <osg/Texture2D>
@ -14,13 +16,14 @@
#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
@ -66,7 +69,7 @@ namespace MWGui
mVFS->normalizeFilename(pattern); mVFS->normalizeFilename(pattern);
/* priority given to the left */ /* priority given to the left */
std::list<std::string> supported_extensions = {".tga", ".dds", ".ktx", ".png", ".bmp", ".jpeg", ".jpg"}; const std::array<std::string, 7> supported_extensions {{".tga", ".dds", ".ktx", ".png", ".bmp", ".jpeg", ".jpg"}};
auto found = index.lower_bound(pattern); auto found = index.lower_bound(pattern);
while (found != index.end()) while (found != index.end())
@ -77,7 +80,7 @@ namespace MWGui
size_t pos = name.find_last_of('.'); size_t pos = name.find_last_of('.');
if (pos != std::string::npos) if (pos != std::string::npos)
{ {
for(auto const extension: supported_extensions) for(auto const& extension: supported_extensions)
{ {
if (name.compare(pos, name.size() - pos, extension) == 0) if (name.compare(pos, name.size() - pos, extension) == 0)
{ {
@ -331,12 +334,6 @@ namespace MWGui
setupCopyFramebufferToTextureCallback(); setupCopyFramebufferToTextureCallback();
} }
// Turn off rendering except the GUI
int oldUpdateMask = mViewer->getUpdateVisitor()->getTraversalMask();
int oldCullMask = mViewer->getCamera()->getCullMask();
mViewer->getUpdateVisitor()->setTraversalMask(SceneUtil::Mask_GUI|SceneUtil::Mask_PreCompile);
mViewer->getCamera()->setCullMask(SceneUtil::Mask_GUI|SceneUtil::Mask_PreCompile);
MWBase::Environment::get().getInputManager()->update(0, true, true); MWBase::Environment::get().getInputManager()->update(0, true, true);
//osg::Timer timer; //osg::Timer timer;
@ -352,10 +349,6 @@ namespace MWGui
//if (mViewer->getIncrementalCompileOperation()) //if (mViewer->getIncrementalCompileOperation())
//std::cout << "num to compile " << mViewer->getIncrementalCompileOperation()->getToCompile().size() << std::endl; //std::cout << "num to compile " << mViewer->getIncrementalCompileOperation()->getToCompile().size() << std::endl;
// resume 3d rendering
mViewer->getUpdateVisitor()->setTraversalMask(oldUpdateMask);
mViewer->getCamera()->setCullMask(oldCullMask);
mLastRenderTime = mTimer.time_m(); mLastRenderTime = mTimer.time_m();
} }

View file

@ -209,6 +209,7 @@ namespace MWGui
MyGUI::IntCoord(mx*mMapWidgetSize, my*mMapWidgetSize, mMapWidgetSize, mMapWidgetSize), MyGUI::IntCoord(mx*mMapWidgetSize, my*mMapWidgetSize, mMapWidgetSize, mMapWidgetSize),
MyGUI::Align::Top | MyGUI::Align::Left); MyGUI::Align::Top | MyGUI::Align::Left);
fog->setDepth(Local_FogLayer); fog->setDepth(Local_FogLayer);
fog->setColour(MyGUI::Colour(0, 0, 0));
map->setNeedMouseFocus(false); map->setNeedMouseFocus(false);
fog->setNeedMouseFocus(false); fog->setNeedMouseFocus(false);

View file

@ -19,7 +19,7 @@
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwmechanics/spellcasting.hpp" #include "../mwmechanics/spellutil.hpp"
#include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/actorutil.hpp" #include "../mwmechanics/actorutil.hpp"
@ -401,7 +401,8 @@ namespace MWGui
return; return;
} }
MWBase::Environment::get().getWindowManager()->useItem(item); if (!store.isEquipped(item))
MWBase::Environment::get().getWindowManager()->useItem(item);
MWWorld::ConstContainerStoreIterator rightHand = store.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); MWWorld::ConstContainerStoreIterator rightHand = store.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
// change draw state only if the item is in player's right hand // change draw state only if the item is in player's right hand
if (rightHand != store.end() && item == *rightHand) if (rightHand != store.end() && item == *rightHand)
@ -411,8 +412,8 @@ namespace MWGui
} }
else if (key->type == Type_MagicItem) else if (key->type == Type_MagicItem)
{ {
// equip, if it can be equipped // equip, if it can be equipped and isn't yet equipped
if (!item.getClass().getEquipmentSlots(item).first.empty()) if (!item.getClass().getEquipmentSlots(item).first.empty() && !store.isEquipped(item))
{ {
MWBase::Environment::get().getWindowManager()->useItem(item); MWBase::Environment::get().getWindowManager()->useItem(item);

View file

@ -15,10 +15,10 @@
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwworld/esmstore.hpp" #include "../mwworld/esmstore.hpp"
#include "../mwmechanics/spellcasting.hpp"
#include "../mwmechanics/spells.hpp" #include "../mwmechanics/spells.hpp"
#include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/actorutil.hpp" #include "../mwmechanics/actorutil.hpp"
#include "../mwmechanics/spellutil.hpp"
#include "tooltips.hpp" #include "tooltips.hpp"
#include "class.hpp" #include "class.hpp"

View file

@ -7,7 +7,7 @@
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/spellcasting.hpp" #include "../mwmechanics/spellutil.hpp"
#include "../mwworld/esmstore.hpp" #include "../mwworld/esmstore.hpp"
#include "../mwworld/inventorystore.hpp" #include "../mwworld/inventorystore.hpp"

View file

@ -18,7 +18,7 @@
#include "../mwworld/esmstore.hpp" #include "../mwworld/esmstore.hpp"
#include "../mwworld/player.hpp" #include "../mwworld/player.hpp"
#include "../mwmechanics/spellcasting.hpp" #include "../mwmechanics/spellutil.hpp"
#include "../mwmechanics/spells.hpp" #include "../mwmechanics/spells.hpp"
#include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/actorutil.hpp" #include "../mwmechanics/actorutil.hpp"

View file

@ -17,7 +17,7 @@
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwworld/esmstore.hpp" #include "../mwworld/esmstore.hpp"
#include "../mwmechanics/spellcasting.hpp" #include "../mwmechanics/spellutil.hpp"
#include "../mwmechanics/actorutil.hpp" #include "../mwmechanics/actorutil.hpp"
#include "mapwindow.hpp" #include "mapwindow.hpp"
@ -651,6 +651,20 @@ namespace MWGui
return " (" + MyGUI::utility::toString(value) + ")"; return " (" + MyGUI::utility::toString(value) + ")";
} }
std::string ToolTips::getSoulString(const MWWorld::CellRef& cellref)
{
std::string soul = cellref.getSoul();
if (soul.empty())
return std::string();
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
const ESM::Creature *creature = store.get<ESM::Creature>().search(soul);
if (!creature)
return std::string();
if (creature->mName.empty())
return " (" + creature->mId + ")";
return " (" + creature->mName + ")";
}
std::string ToolTips::getCellRefString(const MWWorld::CellRef& cellref) std::string ToolTips::getCellRefString(const MWWorld::CellRef& cellref)
{ {
std::string ret; std::string ret;

View file

@ -81,6 +81,9 @@ namespace MWGui
static std::string getCountString(const int value); static std::string getCountString(const int value);
///< @return blank string if count is 1, or else " (value)" ///< @return blank string if count is 1, or else " (value)"
static std::string getSoulString(const MWWorld::CellRef& cellref);
///< Returns a string containing the name of the creature that the ID in the cellref's soul field belongs to.
static std::string getCellRefString(const MWWorld::CellRef& cellref); static std::string getCellRefString(const MWWorld::CellRef& cellref);
///< Returns a string containing debug tooltip information about the given cellref. ///< Returns a string containing debug tooltip information about the given cellref.

View file

@ -27,6 +27,7 @@
#include "tradeitemmodel.hpp" #include "tradeitemmodel.hpp"
#include "countdialog.hpp" #include "countdialog.hpp"
#include "controllers.hpp" #include "controllers.hpp"
#include "tooltips.hpp"
namespace namespace
{ {
@ -205,7 +206,8 @@ namespace MWGui
{ {
CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog(); CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog();
std::string message = "#{sQuanityMenuMessage02}"; std::string message = "#{sQuanityMenuMessage02}";
dialog->openCountDialog(object.getClass().getName(object), message, count); std::string name = object.getClass().getName(object) + MWGui::ToolTips::getSoulString(object.getCellRef());
dialog->openCountDialog(name, message, count);
dialog->eventOkClicked.clear(); dialog->eventOkClicked.clear();
dialog->eventOkClicked += MyGUI::newDelegate(this, &TradeWindow::sellItem); dialog->eventOkClicked += MyGUI::newDelegate(this, &TradeWindow::sellItem);
mItemToSell = mSortModel->mapToSource(index); mItemToSell = mSortModel->mapToSource(index);

View file

@ -76,6 +76,21 @@ void VideoWidget::stop()
mPlayer->close(); mPlayer->close();
} }
void VideoWidget::pause()
{
mPlayer->pause();
}
void VideoWidget::resume()
{
mPlayer->play();
}
bool VideoWidget::isPaused() const
{
return mPlayer->isPaused();
}
bool VideoWidget::hasAudioStream() bool VideoWidget::hasAudioStream()
{ {
return mPlayer->hasAudioStream(); return mPlayer->hasAudioStream();

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