forked from teamnwah/openmw-tes3coop
Merge branch 'master' into appveyor
This commit is contained in:
commit
93e100f210
671 changed files with 20928 additions and 17441 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -5,7 +5,7 @@ CMakeCache.txt
|
|||
cmake_install.cmake
|
||||
Makefile
|
||||
makefile
|
||||
build
|
||||
build*
|
||||
prebuilt
|
||||
|
||||
## doxygen
|
||||
|
|
|
@ -40,8 +40,8 @@ script:
|
|||
- cd ./build
|
||||
- if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then ${ANALYZE}make -j2; fi
|
||||
- if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi
|
||||
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi
|
||||
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then cd .. && ./CI/check_tabs.sh; fi
|
||||
- if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi
|
||||
- if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "linux" ]; then cd .. && ./CI/check_tabs.sh; fi
|
||||
notifications:
|
||||
recipients:
|
||||
- corrmage+travis-ci@gmail.com
|
||||
|
|
|
@ -13,6 +13,7 @@ Programmers
|
|||
Marc Zinnschlag (Zini) - Lead Programmer/Project Manager
|
||||
|
||||
Adam Hogan (aurix)
|
||||
Aesylwinn
|
||||
Aleksandar Jovanov
|
||||
Alex Haddad (rainChu)
|
||||
Alex McKibben (WeirdSexy)
|
||||
|
@ -47,6 +48,7 @@ Programmers
|
|||
Gašper Sedej
|
||||
gugus/gus
|
||||
Hallfaer Tuilinn
|
||||
hristoast
|
||||
Internecine
|
||||
Jacob Essex (Yacoby)
|
||||
Jannik Heller (scrawl)
|
||||
|
@ -55,6 +57,7 @@ Programmers
|
|||
Jeffrey Haines (Jyby)
|
||||
Jengerer
|
||||
Jiří Kuneš (kunesj)
|
||||
Joe Wilkerson (neuralroberts)
|
||||
Joel Graff (graffy)
|
||||
John Blomberg (fstp)
|
||||
Jordan Ayers
|
||||
|
@ -74,6 +77,7 @@ Programmers
|
|||
Marco Melletti (mellotanica)
|
||||
Marco Schulze
|
||||
Mateusz Kołaczek (PL_kolek)
|
||||
Mateusz Malisz (malice)
|
||||
megaton
|
||||
Michael Hogan (Xethik)
|
||||
Michael Mc Donnell
|
||||
|
@ -88,10 +92,12 @@ Programmers
|
|||
Nikolay Kasyanov (corristo)
|
||||
nobrakal
|
||||
Nolan Poe (nopoe)
|
||||
Paul Cercueil (pcercuei)
|
||||
Paul McElroy (Greendogo)
|
||||
Pieter van der Kloet (pvdk)
|
||||
pkubik
|
||||
Radu-Marius Popovici (rpopovici)
|
||||
rcutmore
|
||||
rdimesio
|
||||
riothamus
|
||||
Robert MacGregor (Ragora)
|
||||
|
|
229
CHANGELOG.md
229
CHANGELOG.md
|
@ -1,3 +1,232 @@
|
|||
0.37.0
|
||||
------
|
||||
|
||||
Bug #385: Light emitting objects have a too short distance of activation
|
||||
Bug #455: Animation doesn't resize creature's bounding box
|
||||
Bug #602: Only collision model is updated when modifying objects trough console
|
||||
Bug #639: Sky horizon at nighttime
|
||||
Bug #672: incorrect trajectory of the moons
|
||||
Bug #814: incorrect NPC width
|
||||
Bug #827: Inaccurate raycasting for dead actors
|
||||
Bug #996: Can see underwater clearly when at right height/angle
|
||||
Bug #1317: Erene Llenim in Seyda Neen does not walk around
|
||||
Bug #1330: Cliff racers fail to hit the player
|
||||
Bug #1366: Combat AI can't aim down (in order to hit small creatures)
|
||||
Bug #1511: View distance while under water is much too short
|
||||
Bug #1563: Terrain positioned incorrectly and appears to vibrate in far-out cells
|
||||
Bug #1612: First person models clip through walls
|
||||
Bug #1647: Crash switching from full screen to windows mode - D3D9
|
||||
Bug #1650: No textures with directx on windows
|
||||
Bug #1730: Scripts names starting with digit(s) fail to compile
|
||||
Bug #1738: Socucius Ergalla's greetings are doubled during the tutorial
|
||||
Bug #1784: First person weapons always in the same position
|
||||
Bug #1813: Underwater flora lighting up entire area.
|
||||
Bug #1871: Handle controller extrapolation flags
|
||||
Bug #1921: Footstep frequency and velocity do not immediately update when speed attribute changes
|
||||
Bug #2001: OpenMW crashes on start with OpenGL 1.4 drivers
|
||||
Bug #2014: Antialiasing setting does nothing on Linux
|
||||
Bug #2037: Some enemies attack the air when spotting the player
|
||||
Bug #2052: NIF rotation matrices including scales are not supported
|
||||
Bug #2062: Crank in Old Mournhold: Forgotten Sewer turns about the wrong axis
|
||||
Bug #2111: Raindrops in front of fire look wrong
|
||||
Bug #2140: [OpenGL] Water effects, flames and parts of creatures solid black when observed through brazier flame
|
||||
Bug #2147: Trueflame and Hopesfire flame effects not properly aligned with blade
|
||||
Bug #2148: Verminous fabricants have little coloured box beneath their feet
|
||||
Bug #2149: Sparks in Clockwork City should bounce off the floor
|
||||
Bug #2151: Clockwork City dicer trap doesn't activate when you're too close
|
||||
Bug #2186: Mini map contains scrambled pixels that cause the mini map to flicker
|
||||
Bug #2187: NIF file with more than 255 NiBillboardNodes does not load
|
||||
Bug #2191: Editor: Crash when trying to view cell in render view in OpenCS
|
||||
Bug #2270: Objects flicker transparently
|
||||
Bug #2280: Latest 32bit windows build of openmw runns out of vram
|
||||
Bug #2281: NPCs don't scream when they die
|
||||
Bug #2286: Jumping animation restarts when equipping mid-air
|
||||
Bug #2287: Weapon idle animation stops when turning
|
||||
Bug #2355: Light spell doesn't work in 1st person view
|
||||
Bug #2362: Lantern glas opaque to flame effect from certain viewing angles
|
||||
Bug #2364: Light spells are not as bright as in Morrowind
|
||||
Bug #2383: Remove the alpha testing override list
|
||||
Bug #2436: Crash on entering cell "Tower of Tel Fyr, Hall of Fyr"
|
||||
Bug #2457: Player followers should not report crimes
|
||||
Bug #2458: crash in some fighting situations
|
||||
Bug #2464: Hiding an emitter node should make that emitter stop firing particles
|
||||
Bug #2466: Can't load a save created with OpenMW-0.35.0-win64
|
||||
Bug #2468: music from title screen continues after loading savegame
|
||||
Bug #2494: Map not consistent between saves
|
||||
Bug #2504: Dialog scroll should always start at the top
|
||||
Bug #2506: Editor: Undo/Redo shortcuts do not work in script editor
|
||||
Bug #2513: Mannequins in mods appear as dead bodies
|
||||
Bug #2524: Editor: TopicInfo "custom" condition section is missing
|
||||
Bug #2540: Editor: search and verification result table can not be sorted by clicking on the column names
|
||||
Bug #2543: Editor: there is a problem with spell effects
|
||||
Bug #2544: Editor fails to save NPC information correctly.
|
||||
Bug #2545: Editor: delete record in Objects (referenceables) table messes up data
|
||||
Bug #2546: Editor: race base attributes and skill boni are not displayed, thus not editable
|
||||
Bug #2547: Editor: some NPC data is not displayed, thus not editable
|
||||
Bug #2551: Editor: missing data in cell definition
|
||||
Bug #2553: Editor: value filter does not work for float values
|
||||
Bug #2555: Editor: undo leaves the record status as Modified
|
||||
Bug #2559: Make Detect Enchantment marks appear on top of the player arrow
|
||||
Bug #2563: position consoling npc doesn't work without cell reload
|
||||
Bug #2564: Editor: Closing a subview from code does not clean up properly and will lead to crash on opening the next subview
|
||||
Bug #2568: Editor: Setting default window size is ignored
|
||||
Bug #2569: Editor: saving from an esp to omwaddon file results in data loss for TopicInfo
|
||||
Bug #2575: Editor: Deleted record (with Added (ModifiedOnly) status) remains in the Dialog SubView
|
||||
Bug #2576: Editor: Editor doesn't scroll to a newly opened subview, when ScrollBar Only mode is active
|
||||
Bug #2578: Editor: changing Level or Reputation of an NPC crashes the editor
|
||||
Bug #2579: Editor: filters not updated when adding or cloning records
|
||||
Bug #2580: Editor: omwaddon makes OpenMW crash
|
||||
Bug #2581: Editor: focus problems in edit subviews single- and multiline input fields
|
||||
Bug #2582: Editor: object verifier should check for non-existing scripts being referenced
|
||||
Bug #2583: Editor: applying filter to TopicInfo on mods that have added dialouge makes the Editor crash
|
||||
Bug #2586: Editor: some dialogue only editable items do not refresh after undo
|
||||
Bug #2588: Editor: Cancel button exits program
|
||||
Bug #2589: Editor: Regions table - mapcolor does not change correctly
|
||||
Bug #2591: Placeatme - spurious 5th parameter raises error
|
||||
Bug #2593: COC command prints multiple times when GUI is hidden
|
||||
Bug #2598: Editor: scene view of instances has to be zoomed out to displaying something - center camera instance please
|
||||
Bug #2607: water behind an invisible NPC becomes invisible as well
|
||||
Bug #2611: Editor: Sort problem in Objects table when few nested rows are added
|
||||
Bug #2621: crash when a creature has no model
|
||||
Bug #2624: Editor: missing columns in tables
|
||||
Bug #2627: Character sheet doesn't properly update when backing out of CharGen
|
||||
Bug #2642: Editor: endif without if - is not reported as error when "verify" was executed
|
||||
Bug #2644: Editor: rebuild the list of available content files when opening the open/new dialogues
|
||||
Bug #2656: OpenMW & OpenMW-CS: setting "Flies" flag for ghosts has no effect
|
||||
Bug #2659: OpenMW & OpenMW-CS: savegame load fail due to script attached to NPCs
|
||||
Bug #2668: Editor: reputation value in the input field is not stored
|
||||
Bug #2696: Horkers use land idle animations under water
|
||||
Bug #2705: Editor: Sort by Record Type (Objects table) is incorrect
|
||||
Bug #2711: Map notes on an exterior cell that shows up with a map marker on the world map do not show up in the tooltip for that cell's marker on the world map
|
||||
Bug #2714: Editor: Can't reorder rows with the same topic in different letter case
|
||||
Bug #2720: Head tracking for creatures not implemented
|
||||
Bug #2722: Alchemy should only include effects shared by at least 2 ingredients
|
||||
Bug #2723: "ori" console command is not working
|
||||
Bug #2726: Ashlanders in front of Ghostgate start wandering around
|
||||
Bug #2727: ESM writer does not handle encoding when saving the TES3 header
|
||||
Bug #2728: Editor: Incorrect position of an added row in Info tables
|
||||
Bug #2731: Editor: Deleting a record triggers a Qt warning
|
||||
Bug #2733: Editor: Undo doesn't restore the Modified status of a record when a nested data is changed
|
||||
Bug #2734: Editor: The Search doesn't work
|
||||
Bug #2738: Additive moon blending
|
||||
Bug #2746: NIF node names should be case insensitive
|
||||
Bug #2752: Fog depth/density not handled correctly
|
||||
Bug #2753: Editor: line edit in dialogue subview tables shows after a single click
|
||||
Bug #2755: Combat AI changes target too frequently
|
||||
Bug #2761: Can't attack during block animations
|
||||
Bug #2764: Player doesn't raise arm in 3rd person for weathertype 9
|
||||
Bug #2768: Current screen resolution not selected in options when starting OpenMW
|
||||
Bug #2773: Editor: Deleted scripts are editable
|
||||
Bug #2776: ordinators still think I'm wearing their helm even though Khajiit and argonians can't
|
||||
Bug #2779: Slider bars continue to move if you don't release mouse button
|
||||
Bug #2781: sleep interruption is a little off (is this an added feature?)
|
||||
Bug #2782: erroneously able to ready weapon/magic (+sheathe weapon/magic) while paralyzed
|
||||
Bug #2785: Editor: Incorrect GMSTs for newly created omwgame files
|
||||
Bug #2786: Kwama Queen head is inverted under OpenMW
|
||||
Bug #2788: additem and removeitem incorrect gold behavior
|
||||
Bug #2790: --start doesn't trace down
|
||||
Bug #2791: Editor: Listed attributes and skill should not be based on number of NPC objects.
|
||||
Bug #2792: glitched merchantile/infinite free items
|
||||
Bug #2794: Need to ignore quotes in names of script function
|
||||
Bug #2797: Editor: Crash when removing the first row in a nested table
|
||||
Bug #2800: Show an error message when S3TC support is missing
|
||||
Bug #2811: Targetted Open spell effect persists.
|
||||
Bug #2819: Editor: bodypart's race filter not displayed correctly
|
||||
Bug #2820: Editor: table sorting is inverted
|
||||
Bug #2821: Editor: undo/redo command labels are incorrect
|
||||
Bug #2826: locking beds that have been locked via magic psuedo-freezes the game
|
||||
Bug #2830: Script compiler does not accept IDs as instruction/functions arguments if the ID is also a keyword
|
||||
Bug #2832: Cell names are not localized on the world map
|
||||
Bug #2833: [cosmetic] Players swimming at water's surface are slightly too low.
|
||||
Bug #2840: Save/load menu is not entirely localized
|
||||
Bug #2853: [exploit/bug] disintegrate weapon incorrectly applying to lockpicks, probes. creates unbreakable lockpicks
|
||||
Bug #2855: Mouse wheel in journal is not disabled by "Options" panel.
|
||||
Bug #2856: Heart of Lorkhan doesn't visually respond to attacks
|
||||
Bug #2863: Inventory highlights wrong category after load
|
||||
Bug #2864: Illuminated Order 1.0c Bug – The teleport amulet is not placed in the PC inventory.
|
||||
Bug #2866: Editor: use checkbox instead of combobox for boolean values
|
||||
Bug #2875: special cases of fSleepRandMod not behaving properly.
|
||||
Bug #2878: Editor: Verify reports "creature has non-positive level" but there is no level setting
|
||||
Bug #2879: Editor: entered value of field "Buys *" is not saved for a creature
|
||||
Bug #2880: OpenMW & OpenMW-CS: having a scale value of 0.000 makes the game laggy
|
||||
Bug #2882: Freeze when entering cell "Guild of Fighters (Ald'ruhn)" after dropping some items inside
|
||||
Bug #2883: game not playable if mod providing a spell is removed but the list of known spells still contains it
|
||||
Bug #2884: NPC chats about wrong player race
|
||||
Bug #2886: Adding custom races breaks existing numbering of PcRace
|
||||
Bug #2888: Editor: value entered in "AI Wander Idle" is not kept
|
||||
Bug #2889: Editor: creatures made with the CS (not cloned) are always dead
|
||||
Bug #2890: Editor: can't make NPC say a specific "Hello" voice-dialouge
|
||||
Bug #2893: Editor: making a creature use textual dialogue doesn't work.
|
||||
Bug #2901: Editor: gold for trading can not be set for creatures
|
||||
Bug #2907: looking from uderwater part of the PC that is below the surface looks like it would be above the water
|
||||
Bug #2914: Magicka not recalculated on character generation
|
||||
Bug #2915: When paralyzed, you can still enter and exit sneak
|
||||
Bug #2917: chameleon does not work for creatures
|
||||
Bug #2927: Editor: in the automatic script checker local variable caches are not invalidated/updated on modifications of other scripts
|
||||
Bug #2930: Editor: AIWander Idle can not be set for a creature
|
||||
Bug #2932: Editor: you can add rows to "Creature Attack" but you can not enter values
|
||||
Bug #2938: Editor: Can't add a start script.
|
||||
Bug #2944: Spell chance for power to show as 0 on hud when used
|
||||
Bug #2953: Editor: rightclick in an empty place in the menu bar shows an unnamed checkbox
|
||||
Bug #2956: Editor: freezes while editing Filter
|
||||
Bug #2959: space character in field enchantment (of an amulet) prevents rendering of surroundings
|
||||
Bug #2962: OpenMW: Assertion `it != invStore.end()' failed
|
||||
Bug #2964: Recursive script execution can corrupt script runtime data
|
||||
Bug #2973: Editor: placing a chest in the game world and activating it heavily blurrs the character portrait
|
||||
Bug #2978: Editor: Cannot edit alchemy ingredient properties
|
||||
Bug #2980: Editor: Attribute and Skill can be selected for spells that do not require these parameters, leading to non-functional spells
|
||||
Bug #2990: Compiling a script with warning mode 2 and enabled error downgrading leads to infinite recursion
|
||||
Bug #2992: [Mod: Great House Dagoth] Killing Dagoth Gares freezes the game
|
||||
Bug #3007: PlaceItem takes radians instead of degrees + angle reliability
|
||||
Feature #706: Editor: Script Editor enhancements
|
||||
Feature #872: Editor: Colour values in tables
|
||||
Feature #880: Editor: ID auto-complete
|
||||
Feature #928: Editor: Partial sorting in info tables
|
||||
Feature #942: Editor: Dialogue for editing/viewing content file meta information
|
||||
Feature #1057: NiStencilProperty
|
||||
Feature #1278: Editor: Mouse picking in worldspace widget
|
||||
Feature #1280: Editor: Cell border arrows
|
||||
Feature #1401: Editor: Cloning enhancements
|
||||
Feature #1463: Editor: Fine grained configuration of extended revert/delete commands
|
||||
Feature #1591: Editor: Make fields in creation bar drop targets where applicable
|
||||
Feature #1998: Editor: Magic effect record verifier
|
||||
Feature #1999: Editor Sound Gen record verifier
|
||||
Feature #2000: Editor: Pathgrid record verifier
|
||||
Feature #2528: Game Time Tracker
|
||||
Feature #2534: Editor: global search does not auomatically focus the search input field
|
||||
Feature #2535: OpenMW: allow comments in openmw.cfg
|
||||
Feature #2541: Editor: provide a go to the very bottom button for TopicInfo and JournalInfo
|
||||
Feature #2549: Editor: add a horizontal slider to scroll between opened tables
|
||||
Feature #2558: Editor: provide a shortcut for closing the subview that has the focus
|
||||
Feature #2565: Editor: add context menu for dialogue sub view fields with an item matching "Edit 'x'" from the table subview context menu
|
||||
Feature #2585: Editor: Ignore mouse wheel input for numeric values unless the respective widget has the focus
|
||||
Feature #2620: Editor: make the verify-view refreshable
|
||||
Feature #2622: Editor: Make double click behaviour in result tables configurable (see ID tables)
|
||||
Feature #2717: Editor: Add severity column to report tables
|
||||
Feature #2729: Editor: Various dialogue button bar improvements
|
||||
Feature #2739: Profiling overlay
|
||||
Feature #2740: Resource manager optimizations
|
||||
Feature #2741: Make NIF files into proper resources
|
||||
Feature #2742: Use the skinning data in NIF files as-is
|
||||
Feature #2743: Small feature culling
|
||||
Feature #2744: Configurable near clip distance
|
||||
Feature #2745: GUI scaling option
|
||||
Feature #2747: Support anonymous textures
|
||||
Feature #2749: Loading screen optimizations
|
||||
Feature #2751: Character preview optimization
|
||||
Feature #2804: Editor: Merge Tool
|
||||
Feature #2818: Editor: allow copying a record ID to the clipboard
|
||||
Feature #2946: Editor: add script line number in results of search
|
||||
Feature #2963: Editor: Mouse button bindings in 3D scene
|
||||
Feature #2983: Sun Glare fader
|
||||
Feature #2999: Scaling of journal and books
|
||||
Task #2665: Support building with Qt5
|
||||
Task #2725: Editor: Remove Display_YesNo
|
||||
Task #2730: Replace hardcoded column numbers in SimpleDialogueSubView/DialogueSubView
|
||||
Task #2750: Bullet shape instancing optimization
|
||||
Task #2793: Replace grid size setting with half grid size setting
|
||||
Task #3003: Support FFMPEG 2.9 (Debian request)
|
||||
|
||||
0.36.1
|
||||
------
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ echo "yes" | sudo apt-add-repository ppa:boost-latest/ppa
|
|||
sudo apt-get update -qq
|
||||
sudo apt-get install -qq libgtest-dev google-mock
|
||||
sudo apt-get install -qq libboost-filesystem1.55-dev libboost-program-options1.55-dev libboost-system1.55-dev libboost-thread1.55-dev
|
||||
sudo apt-get install -qq libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libavresample-dev
|
||||
sudo apt-get install -qq ffmpeg libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libswresample-dev
|
||||
sudo apt-get install -qq libbullet-dev libopenscenegraph-dev libmygui-dev libsdl2-dev libunshield-dev libtinyxml-dev libopenal-dev libqt4-dev
|
||||
sudo apt-get install -qq cmake-data #workaround for broken osgqt cmake script in ubuntu 12.04
|
||||
if [ "${ANALYZE}" ]; then sudo apt-get install -qq clang-3.6; fi
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
OUTPUT=$(grep -nRP '\t' --include=\*.{cpp,hpp,c,h} apps components)
|
||||
OUTPUT=$(grep -nRP '\t' --include=\*.{cpp,hpp,c,h} --exclude=ui_\* apps components)
|
||||
|
||||
if [[ $OUTPUT ]] ; then
|
||||
echo "Error: Tab characters found!"
|
||||
|
|
167
CMakeLists.txt
167
CMakeLists.txt
|
@ -3,8 +3,9 @@ project(OpenMW)
|
|||
# If the user doesn't supply a CMAKE_BUILD_TYPE via command line, choose one for them.
|
||||
IF(NOT CMAKE_BUILD_TYPE)
|
||||
SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING
|
||||
"Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel."
|
||||
"Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel."
|
||||
FORCE)
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS None Debug Release RelWithDebInfo MinSizeRel)
|
||||
ENDIF()
|
||||
|
||||
if (APPLE)
|
||||
|
@ -15,12 +16,17 @@ endif (APPLE)
|
|||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/)
|
||||
|
||||
if (ANDROID)
|
||||
set(CMAKE_FIND_ROOT_PATH ${OPENMW_DEPENDENCIES_DIR} "${CMAKE_FIND_ROOT_PATH}")
|
||||
set (OSG_PLUGINS_DIR CACHE STRING "")
|
||||
endif()
|
||||
|
||||
# Version
|
||||
message(STATUS "Configuring OpenMW...")
|
||||
|
||||
set(OPENMW_VERSION_MAJOR 0)
|
||||
set(OPENMW_VERSION_MINOR 36)
|
||||
set(OPENMW_VERSION_RELEASE 1)
|
||||
set(OPENMW_VERSION_MINOR 37)
|
||||
set(OPENMW_VERSION_RELEASE 0)
|
||||
|
||||
set(OPENMW_VERSION_COMMITHASH "")
|
||||
set(OPENMW_VERSION_TAGHASH "")
|
||||
|
@ -45,10 +51,6 @@ endif(EXISTS ${PROJECT_SOURCE_DIR}/.git)
|
|||
# Macros
|
||||
include(OpenMWMacros)
|
||||
|
||||
if (ANDROID)
|
||||
set(CMAKE_FIND_ROOT_PATH ${OPENMW_DEPENDENCIES_DIR} "${CMAKE_FIND_ROOT_PATH}")
|
||||
endif (ANDROID)
|
||||
|
||||
# doxygen main page
|
||||
|
||||
configure_file ("${OpenMW_SOURCE_DIR}/docs/mainpage.hpp.cmake" "${OpenMW_BINARY_DIR}/docs/mainpage.hpp")
|
||||
|
@ -83,13 +85,28 @@ if (MSVC)
|
|||
option(OPENMW_LTO_BUILD "Build OpenMW with Link-Time Optimization (Needs ~2GB of RAM)" OFF)
|
||||
endif()
|
||||
|
||||
# Location of morrowind data files
|
||||
# Set up common paths
|
||||
if (APPLE)
|
||||
set(MORROWIND_DATA_FILES "./data" CACHE PATH "location of Morrowind data files")
|
||||
set(OPENMW_RESOURCE_FILES "./resources" CACHE PATH "location of OpenMW resources files")
|
||||
elseif(UNIX)
|
||||
set(MORROWIND_DATA_FILES "${CMAKE_INSTALL_PREFIX}/share/games/openmw/data/" CACHE PATH "location of Morrowind data files")
|
||||
set(OPENMW_RESOURCE_FILES "${CMAKE_INSTALL_PREFIX}/share/games/openmw/resources/" CACHE PATH "location of OpenMW resources files")
|
||||
# Paths
|
||||
SET(BINDIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Where to install binaries")
|
||||
SET(LIBDIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE PATH "Where to install libraries")
|
||||
SET(DATAROOTDIR "${CMAKE_INSTALL_PREFIX}/share" CACHE PATH "Sets the root of data directories to a non-default location")
|
||||
SET(GLOBAL_DATA_PATH "${DATAROOTDIR}/games/" CACHE PATH "Set data path prefix")
|
||||
SET(DATADIR "${GLOBAL_DATA_PATH}/openmw" CACHE PATH "Sets the openmw data directories to a non-default location")
|
||||
SET(ICONDIR "${DATAROOTDIR}/pixmaps" CACHE PATH "Set icon dir")
|
||||
SET(LICDIR "${DATAROOTDIR}/licenses/openmw" CACHE PATH "Sets the openmw license directory to a non-default location.")
|
||||
IF("${CMAKE_INSTALL_PREFIX}" STREQUAL "/usr")
|
||||
SET(GLOBAL_CONFIG_PATH "/etc/" CACHE PATH "Set config dir prefix")
|
||||
ELSE()
|
||||
SET(GLOBAL_CONFIG_PATH "${CMAKE_INSTALL_PREFIX}/etc/" CACHE PATH "Set config dir prefix")
|
||||
ENDIF()
|
||||
SET(SYSCONFDIR "${GLOBAL_CONFIG_PATH}/openmw" CACHE PATH "Set config dir")
|
||||
|
||||
set(MORROWIND_DATA_FILES "${DATADIR}/data" CACHE PATH "location of Morrowind data files")
|
||||
set(OPENMW_RESOURCE_FILES "${DATADIR}/resources" CACHE PATH "location of OpenMW resources files")
|
||||
else()
|
||||
set(MORROWIND_DATA_FILES "data" CACHE PATH "location of Morrowind data files")
|
||||
set(OPENMW_RESOURCE_FILES "resources" CACHE PATH "location of OpenMW resources files")
|
||||
|
@ -107,27 +124,14 @@ unset(FFMPEG_LIBRARIES CACHE)
|
|||
|
||||
find_package(FFmpeg REQUIRED)
|
||||
|
||||
set (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${SWSCALE_LIBRARY})
|
||||
set (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${SWSCALE_LIBRARY} ${SWRESAMPLE_LIBRARIES})
|
||||
|
||||
if ( NOT AVCODEC_FOUND OR NOT AVFORMAT_FOUND OR NOT AVUTIL_FOUND OR NOT SWSCALE_FOUND )
|
||||
if ( NOT AVCODEC_FOUND OR NOT AVFORMAT_FOUND OR NOT AVUTIL_FOUND OR NOT SWSCALE_FOUND OR NOT SWRESAMPLE_FOUND)
|
||||
message(FATAL_ERROR "FFmpeg component required, but not found!")
|
||||
endif()
|
||||
set(SOUND_INPUT_INCLUDES ${FFMPEG_INCLUDE_DIRS})
|
||||
if( SWRESAMPLE_FOUND )
|
||||
add_definitions(-DHAVE_LIBSWRESAMPLE)
|
||||
set (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${SWRESAMPLE_LIBRARIES})
|
||||
else()
|
||||
if( AVRESAMPLE_FOUND )
|
||||
set (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${AVRESAMPLE_LIBRARIES})
|
||||
else()
|
||||
message(FATAL_ERROR "Install either libswresample (FFmpeg) or libavresample (Libav).")
|
||||
endif()
|
||||
endif()
|
||||
# Required for building the FFmpeg headers
|
||||
add_definitions(-D__STDC_CONSTANT_MACROS)
|
||||
|
||||
set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES})
|
||||
|
||||
# TinyXML
|
||||
option(USE_SYSTEM_TINYXML "Use system TinyXML library instead of internal." OFF)
|
||||
if(USE_SYSTEM_TINYXML)
|
||||
|
@ -157,20 +161,38 @@ if (WIN32)
|
|||
add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN)
|
||||
endif()
|
||||
|
||||
# Dependencies
|
||||
if (ANDROID)
|
||||
set(OPENGL_ES TRUE CACHE BOOL "enable opengl es support for android" FORCE)
|
||||
endif (ANDROID)
|
||||
|
||||
set(DESIRED_QT_VERSION 4 CACHE STRING "The QT version OpenMW should use (4 or 5)")
|
||||
message(STATUS "Using Qt${DESIRED_QT_VERSION}")
|
||||
option(OPENGL_ES "enable opengl es support" FALSE )
|
||||
|
||||
if (DESIRED_QT_VERSION MATCHES 4)
|
||||
find_package(Qt4 REQUIRED COMPONENTS QtCore QtGui QtNetwork QtOpenGL)
|
||||
if (OPENGL_ES)
|
||||
add_definitions(-DOPENGL_ES)
|
||||
endif(OPENGL_ES)
|
||||
|
||||
if (NOT BUILD_LAUNCHER AND NOT BUILD_OPENCS AND NOT BUILD_WIZARD)
|
||||
set(USE_QT FALSE)
|
||||
else()
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
find_package(Qt5Core REQUIRED)
|
||||
find_package(Qt5Network REQUIRED)
|
||||
find_package(Qt5OpenGL REQUIRED)
|
||||
set(USE_QT TRUE)
|
||||
endif()
|
||||
|
||||
# Dependencies
|
||||
if (USE_QT)
|
||||
set(DESIRED_QT_VERSION 4 CACHE STRING "The QT version OpenMW should use (4 or 5)")
|
||||
set_property(CACHE DESIRED_QT_VERSION PROPERTY STRINGS 4 5)
|
||||
message(STATUS "Using Qt${DESIRED_QT_VERSION}")
|
||||
|
||||
if (DESIRED_QT_VERSION MATCHES 4)
|
||||
find_package(Qt4 REQUIRED COMPONENTS QtCore QtGui QtNetwork QtOpenGL)
|
||||
else()
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
find_package(Qt5Core REQUIRED)
|
||||
find_package(Qt5Network REQUIRED)
|
||||
find_package(Qt5OpenGL REQUIRED)
|
||||
# Instruct CMake to run moc automatically when needed.
|
||||
#set(CMAKE_AUTOMOC ON)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Fix for not visible pthreads functions for linker with glibc 2.15
|
||||
|
@ -202,7 +224,12 @@ IF(BOOST_STATIC)
|
|||
set(Boost_USE_STATIC_LIBS ON)
|
||||
endif()
|
||||
|
||||
find_package(OpenSceneGraph 3.2.0 REQUIRED osgDB osgViewer osgText osgGA osgAnimation osgParticle osgQt osgUtil osgFX)
|
||||
if (USE_QT)
|
||||
set (OSG_QT osgQt)
|
||||
endif()
|
||||
|
||||
find_package(OpenSceneGraph 3.2.0 REQUIRED osgDB osgViewer osgText osgGA osgAnimation osgParticle ${OSG_QT} osgUtil osgFX)
|
||||
|
||||
include_directories(${OPENSCENEGRAPH_INCLUDE_DIRS})
|
||||
|
||||
if(OSG_STATIC)
|
||||
|
@ -308,8 +335,7 @@ if (APPLE)
|
|||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${APP_BUNDLE_DIR}/Contents/MacOS")
|
||||
|
||||
if (OPENMW_OSX_DEPLOYMENT)
|
||||
SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
|
||||
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)
|
||||
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
endif()
|
||||
else (APPLE)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${OpenMW_BINARY_DIR}")
|
||||
|
@ -327,8 +353,8 @@ configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg.local
|
|||
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg
|
||||
"${OpenMW_BINARY_DIR}/openmw.cfg.install")
|
||||
|
||||
configure_file(${OpenMW_SOURCE_DIR}/files/opencs.ini
|
||||
"${OpenMW_BINARY_DIR}/opencs.ini")
|
||||
configure_file(${OpenMW_SOURCE_DIR}/files/openmw-cs.cfg
|
||||
"${OpenMW_BINARY_DIR}/openmw-cs.cfg")
|
||||
|
||||
configure_file(${OpenMW_SOURCE_DIR}/files/opencs/defaultfilters
|
||||
"${OpenMW_BINARY_DIR}/resources/defaultfilters" COPYONLY)
|
||||
|
@ -375,21 +401,7 @@ elseif (MSVC)
|
|||
endif (CMAKE_CXX_COMPILER_ID STREQUAL GNU OR CMAKE_CXX_COMPILER_ID STREQUAL Clang)
|
||||
|
||||
IF(NOT WIN32 AND NOT APPLE)
|
||||
# Linux building
|
||||
# Paths
|
||||
SET(BINDIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Where to install binaries")
|
||||
SET(LIBDIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE PATH "Where to install libraries")
|
||||
SET(DATAROOTDIR "${CMAKE_INSTALL_PREFIX}/share" CACHE PATH "Sets the root of data directories to a non-default location")
|
||||
SET(GLOBAL_DATA_PATH "${DATAROOTDIR}/games/" CACHE PATH "Set data path prefix")
|
||||
SET(DATADIR "${GLOBAL_DATA_PATH}/openmw" CACHE PATH "Sets the openmw data directories to a non-default location")
|
||||
SET(ICONDIR "${DATAROOTDIR}/pixmaps" CACHE PATH "Set icon dir")
|
||||
SET(LICDIR "${DATAROOTDIR}/licenses/openmw" CACHE PATH "Sets the openmw license directory to a non-default location.")
|
||||
IF("${CMAKE_INSTALL_PREFIX}" STREQUAL "/usr")
|
||||
SET(GLOBAL_CONFIG_PATH "/etc/" CACHE PATH "Set config dir prefix")
|
||||
ELSE()
|
||||
SET(GLOBAL_CONFIG_PATH "${CMAKE_INSTALL_PREFIX}/etc/" CACHE PATH "Set config dir prefix")
|
||||
ENDIF()
|
||||
SET(SYSCONFDIR "${GLOBAL_CONFIG_PATH}/openmw" CACHE PATH "Set config dir")
|
||||
# Linux installation
|
||||
|
||||
# Install binaries
|
||||
IF(BUILD_OPENMW)
|
||||
|
@ -442,7 +454,7 @@ IF(NOT WIN32 AND NOT APPLE)
|
|||
INSTALL(FILES "${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")
|
||||
|
||||
IF(BUILD_OPENCS)
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION "${SYSCONFDIR}" COMPONENT "opencs")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw-cs.cfg" DESTINATION "${SYSCONFDIR}" COMPONENT "opencs")
|
||||
ENDIF(BUILD_OPENCS)
|
||||
|
||||
# Install resources
|
||||
|
@ -475,7 +487,7 @@ if(WIN32)
|
|||
ENDIF(BUILD_ESSIMPORTER)
|
||||
IF(BUILD_OPENCS)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Release/openmw-cs.exe" DESTINATION ".")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION ".")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw-cs.cfg" DESTINATION ".")
|
||||
ENDIF(BUILD_OPENCS)
|
||||
IF(BUILD_WIZARD)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Release/openmw-wizard.exe" DESTINATION ".")
|
||||
|
@ -721,6 +733,18 @@ endif()
|
|||
|
||||
# Apple bundling
|
||||
if (APPLE)
|
||||
get_property(QT_COCOA_PLUGIN_PATH TARGET Qt5::QCocoaIntegrationPlugin PROPERTY LOCATION_RELEASE)
|
||||
get_filename_component(QT_COCOA_PLUGIN_DIR "${QT_COCOA_PLUGIN_PATH}" DIRECTORY)
|
||||
get_filename_component(QT_COCOA_PLUGIN_GROUP "${QT_COCOA_PLUGIN_DIR}" NAME)
|
||||
get_filename_component(QT_COCOA_PLUGIN_NAME "${QT_COCOA_PLUGIN_PATH}" NAME)
|
||||
configure_file("${QT_COCOA_PLUGIN_PATH}" "${APP_BUNDLE_DIR}/Contents/MacOS/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}" COPYONLY)
|
||||
|
||||
if (BUILD_OPENCS)
|
||||
get_property(OPENCS_BUNDLE_NAME_TMP TARGET openmw-cs PROPERTY OUTPUT_NAME)
|
||||
set(OPENCS_BUNDLE_NAME "${OPENCS_BUNDLE_NAME_TMP}.app")
|
||||
configure_file("${QT_COCOA_PLUGIN_PATH}" "${OPENCS_BUNDLE_NAME}/Contents/MacOS/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}" COPYONLY)
|
||||
endif ()
|
||||
|
||||
set(INSTALL_SUBDIR OpenMW)
|
||||
|
||||
install(DIRECTORY "${APP_BUNDLE_DIR}" USE_SOURCE_PERMISSIONS DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
|
||||
|
@ -728,7 +752,7 @@ if (APPLE)
|
|||
install(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" RENAME "openmw.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
|
||||
install(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
|
||||
install(FILES "${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
|
||||
install(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
|
||||
install(FILES "${OpenMW_BINARY_DIR}/openmw-cs.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
|
||||
|
||||
set(CPACK_GENERATOR "DragNDrop")
|
||||
set(CPACK_PACKAGE_VERSION ${OPENMW_VERSION})
|
||||
|
@ -736,22 +760,22 @@ if (APPLE)
|
|||
set(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINOR})
|
||||
set(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE})
|
||||
|
||||
set(OPENMW_APP "\${CMAKE_INSTALL_PREFIX}/${INSTALL_SUBDIR}/${APP_BUNDLE_NAME}")
|
||||
|
||||
set(OPENCS_BUNDLE_NAME "OpenMW-CS.app")
|
||||
set(OPENCS_APP "\${CMAKE_INSTALL_PREFIX}/${INSTALL_SUBDIR}/${OPENCS_BUNDLE_NAME}")
|
||||
set(INSTALLED_OPENMW_APP "\${CMAKE_INSTALL_PREFIX}/${INSTALL_SUBDIR}/${APP_BUNDLE_NAME}")
|
||||
set(INSTALLED_OPENCS_APP "\${CMAKE_INSTALL_PREFIX}/${INSTALL_SUBDIR}/${OPENCS_BUNDLE_NAME}")
|
||||
|
||||
install(CODE "
|
||||
set(BU_CHMOD_BUNDLE_ITEMS ON)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH})
|
||||
include(BundleUtilitiesWithRPath)
|
||||
include(BundleUtilities)
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
" COMPONENT Runtime)
|
||||
|
||||
set(ABSOLUTE_PLUGINS "")
|
||||
set(USED_OSG_PLUGINS
|
||||
osgdb_tga
|
||||
osgdb_dds
|
||||
osgdb_imageio
|
||||
osgdb_jpeg
|
||||
osgdb_png
|
||||
osgdb_tga
|
||||
)
|
||||
|
||||
foreach (PLUGIN_NAME ${USED_OSG_PLUGINS})
|
||||
|
@ -759,12 +783,12 @@ if (APPLE)
|
|||
set(ABSOLUTE_PLUGINS ${PLUGIN_ABS} ${ABSOLUTE_PLUGINS})
|
||||
endforeach ()
|
||||
|
||||
get_filename_component(PLUGIN_PREFIX_DIR "${OSG_PLUGIN_LIB_SEARCH_PATH}" NAME)
|
||||
get_filename_component(OSG_PLUGIN_PREFIX_DIR "${OSG_PLUGIN_LIB_SEARCH_PATH}" NAME)
|
||||
|
||||
# installs used plugins in bundle at given path (bundle_path must be relative to ${CMAKE_INSTALL_PREFIX})
|
||||
# and returns list of install paths for all installed plugins
|
||||
function (install_plugins_for_bundle bundle_path plugins_var)
|
||||
set(RELATIVE_PLUGIN_INSTALL_BASE "${bundle_path}/Contents/PlugIns/${PLUGIN_PREFIX_DIR}")
|
||||
set(RELATIVE_PLUGIN_INSTALL_BASE "${bundle_path}/Contents/PlugIns/${OSG_PLUGIN_PREFIX_DIR}")
|
||||
|
||||
set(PLUGINS "")
|
||||
set(PLUGIN_INSTALL_BASE "\${CMAKE_INSTALL_PREFIX}/${RELATIVE_PLUGIN_INSTALL_BASE}")
|
||||
|
@ -787,19 +811,20 @@ if (APPLE)
|
|||
install_plugins_for_bundle("${INSTALL_SUBDIR}/${APP_BUNDLE_NAME}" PLUGINS)
|
||||
install_plugins_for_bundle("${INSTALL_SUBDIR}/${OPENCS_BUNDLE_NAME}" OPENCS_PLUGINS)
|
||||
|
||||
set(DIRS "${CMAKE_PREFIX_PATH}/lib")
|
||||
set(PLUGINS ${PLUGINS} "${INSTALLED_OPENMW_APP}/Contents/MacOS/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}")
|
||||
set(OPENCS_PLUGINS ${OPENCS_PLUGINS} "${INSTALLED_OPENCS_APP}/Contents/MacOS/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}")
|
||||
|
||||
install(CODE "
|
||||
function(gp_item_default_embedded_path_override item default_embedded_path_var)
|
||||
if (\${item} MATCHES ${PLUGIN_PREFIX_DIR})
|
||||
set(path \"@executable_path/../PlugIns/${PLUGIN_PREFIX_DIR}\")
|
||||
if (\${item} MATCHES ${OSG_PLUGIN_PREFIX_DIR})
|
||||
set(path \"@executable_path/../PlugIns/${OSG_PLUGIN_PREFIX_DIR}\")
|
||||
set(\${default_embedded_path_var} \"\${path}\" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
cmake_policy(SET CMP0009 OLD)
|
||||
fixup_bundle(\"${OPENMW_APP}\" \"${PLUGINS}\" \"${DIRS}\")
|
||||
fixup_bundle(\"${OPENCS_APP}\" \"${OPENCS_PLUGINS}\" \"${DIRS}\")
|
||||
fixup_bundle(\"${INSTALLED_OPENMW_APP}\" \"${PLUGINS}\" \"\")
|
||||
fixup_bundle(\"${INSTALLED_OPENCS_APP}\" \"${OPENCS_PLUGINS}\" \"\")
|
||||
" COMPONENT Runtime)
|
||||
include(CPack)
|
||||
endif (APPLE)
|
||||
|
|
|
@ -7,7 +7,7 @@ OpenMW is a recreation of the engine for the popular role-playing game Morrowind
|
|||
|
||||
OpenMW also comes with OpenMW-CS, a replacement for Morrowind's TES Construction Set.
|
||||
|
||||
* Version: 0.36.1
|
||||
* Version: 0.37.0
|
||||
* License: GPL (see docs/license/GPL3.txt for more information)
|
||||
* Website: http://www.openmw.org
|
||||
* IRC: #openmw on irc.freenode.net
|
||||
|
|
|
@ -27,7 +27,8 @@ struct ESMData
|
|||
std::vector<ESM::Header::MasterData> masters;
|
||||
|
||||
std::deque<EsmTool::RecordBase *> mRecords;
|
||||
std::map<ESM::Cell *, std::deque<ESM::CellRef> > mCellRefs;
|
||||
// Value: (Reference, Deleted flag)
|
||||
std::map<ESM::Cell *, std::deque<std::pair<ESM::CellRef, bool> > > mCellRefs;
|
||||
std::map<int, int> mRecordStats;
|
||||
|
||||
static const std::set<int> sLabeledRec;
|
||||
|
@ -255,7 +256,7 @@ void loadCell(ESM::Cell &cell, ESM::ESMReader &esm, Arguments& info)
|
|||
while(cell.getNextRef(esm, ref, deleted))
|
||||
{
|
||||
if (save) {
|
||||
info.data.mCellRefs[&cell].push_back(ref);
|
||||
info.data.mCellRefs[&cell].push_back(std::make_pair(ref, deleted));
|
||||
}
|
||||
|
||||
if(quiet) continue;
|
||||
|
@ -352,30 +353,9 @@ int load(Arguments& info)
|
|||
uint32_t flags;
|
||||
esm.getRecHeader(flags);
|
||||
|
||||
// Is the user interested in this record type?
|
||||
bool interested = true;
|
||||
if (!info.types.empty())
|
||||
{
|
||||
std::vector<std::string>::iterator match;
|
||||
match = std::find(info.types.begin(), info.types.end(),
|
||||
n.toString());
|
||||
if (match == info.types.end()) interested = false;
|
||||
}
|
||||
|
||||
std::string id = esm.getHNOString("NAME");
|
||||
if (id.empty())
|
||||
id = esm.getHNOString("INAM");
|
||||
|
||||
if (!info.name.empty() && !Misc::StringUtils::ciEqual(info.name, id))
|
||||
interested = false;
|
||||
|
||||
if(!quiet && interested)
|
||||
std::cout << "\nRecord: " << n.toString()
|
||||
<< " '" << id << "'\n";
|
||||
|
||||
EsmTool::RecordBase *record = EsmTool::RecordBase::create(n);
|
||||
|
||||
if (record == 0) {
|
||||
if (record == 0)
|
||||
{
|
||||
if (std::find(skipped.begin(), skipped.end(), n.val) == skipped.end())
|
||||
{
|
||||
std::cout << "Skipping " << n.toString() << " records." << std::endl;
|
||||
|
@ -385,28 +365,46 @@ int load(Arguments& info)
|
|||
esm.skipRecord();
|
||||
if (quiet) break;
|
||||
std::cout << " Skipping\n";
|
||||
} else {
|
||||
if (record->getType().val == ESM::REC_GMST) {
|
||||
// preset id for GameSetting record
|
||||
record->cast<ESM::GameSetting>()->get().mId = id;
|
||||
}
|
||||
record->setId(id);
|
||||
record->setFlags((int) flags);
|
||||
record->setPrintPlain(info.plain_given);
|
||||
record->load(esm);
|
||||
if (!quiet && interested) record->print();
|
||||
|
||||
if (record->getType().val == ESM::REC_CELL && loadCells && interested) {
|
||||
loadCell(record->cast<ESM::Cell>()->get(), esm, info);
|
||||
}
|
||||
|
||||
if (save) {
|
||||
info.data.mRecords.push_back(record);
|
||||
} else {
|
||||
delete record;
|
||||
}
|
||||
++info.data.mRecordStats[n.val];
|
||||
continue;
|
||||
}
|
||||
|
||||
record->setFlags(static_cast<int>(flags));
|
||||
record->setPrintPlain(info.plain_given);
|
||||
record->load(esm);
|
||||
|
||||
// Is the user interested in this record type?
|
||||
bool interested = true;
|
||||
if (!info.types.empty())
|
||||
{
|
||||
std::vector<std::string>::iterator match;
|
||||
match = std::find(info.types.begin(), info.types.end(), n.toString());
|
||||
if (match == info.types.end()) interested = false;
|
||||
}
|
||||
|
||||
if (!info.name.empty() && !Misc::StringUtils::ciEqual(info.name, record->getId()))
|
||||
interested = false;
|
||||
|
||||
if(!quiet && interested)
|
||||
{
|
||||
std::cout << "\nRecord: " << n.toString() << " '" << record->getId() << "'\n";
|
||||
record->print();
|
||||
}
|
||||
|
||||
if (record->getType().val == ESM::REC_CELL && loadCells && interested)
|
||||
{
|
||||
loadCell(record->cast<ESM::Cell>()->get(), esm, info);
|
||||
}
|
||||
|
||||
if (save)
|
||||
{
|
||||
info.data.mRecords.push_back(record);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete record;
|
||||
}
|
||||
++info.data.mRecordStats[n.val];
|
||||
}
|
||||
|
||||
} catch(std::exception &e) {
|
||||
|
@ -493,28 +491,19 @@ int clone(Arguments& info)
|
|||
for (Records::iterator it = records.begin(); it != records.end() && i > 0; ++it)
|
||||
{
|
||||
EsmTool::RecordBase *record = *it;
|
||||
|
||||
name.val = record->getType().val;
|
||||
|
||||
esm.startRecord(name.toString(), record->getFlags());
|
||||
|
||||
// TODO wrap this with std::set
|
||||
if (ESMData::sLabeledRec.count(name.val) > 0) {
|
||||
esm.writeHNCString("NAME", record->getId());
|
||||
} else {
|
||||
esm.writeHNOString("NAME", record->getId());
|
||||
}
|
||||
|
||||
record->save(esm);
|
||||
|
||||
if (name.val == ESM::REC_CELL) {
|
||||
ESM::Cell *ptr = &record->cast<ESM::Cell>()->get();
|
||||
if (!info.data.mCellRefs[ptr].empty()) {
|
||||
typedef std::deque<ESM::CellRef> RefList;
|
||||
typedef std::deque<std::pair<ESM::CellRef, bool> > RefList;
|
||||
RefList &refs = info.data.mCellRefs[ptr];
|
||||
for (RefList::iterator refIt = refs.begin(); refIt != refs.end(); ++refIt)
|
||||
{
|
||||
refIt->save(esm);
|
||||
refIt->first.save(esm, refIt->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -405,6 +405,7 @@ void Record<ESM::Activator>::print()
|
|||
std::cout << " Name: " << mData.mName << std::endl;
|
||||
std::cout << " Model: " << mData.mModel << std::endl;
|
||||
std::cout << " Script: " << mData.mScript << std::endl;
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -419,6 +420,7 @@ void Record<ESM::Potion>::print()
|
|||
std::cout << " Value: " << mData.mData.mValue << std::endl;
|
||||
std::cout << " AutoCalc: " << mData.mData.mAutoCalc << std::endl;
|
||||
printEffectList(mData.mEffects);
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -447,6 +449,7 @@ void Record<ESM::Armor>::print()
|
|||
if (pit->mFemale != "")
|
||||
std::cout << " Female Name: " << pit->mFemale << std::endl;
|
||||
}
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -461,6 +464,7 @@ void Record<ESM::Apparatus>::print()
|
|||
std::cout << " Weight: " << mData.mData.mWeight << std::endl;
|
||||
std::cout << " Value: " << mData.mData.mValue << std::endl;
|
||||
std::cout << " Quality: " << mData.mData.mQuality << std::endl;
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -474,6 +478,7 @@ void Record<ESM::BodyPart>::print()
|
|||
std::cout << " Part: " << meshPartLabel(mData.mData.mPart)
|
||||
<< " (" << (int)mData.mData.mPart << ")" << std::endl;
|
||||
std::cout << " Vampire: " << (int)mData.mData.mVampire << std::endl;
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -502,6 +507,7 @@ void Record<ESM::Book>::print()
|
|||
{
|
||||
std::cout << " Text: [skipped]" << std::endl;
|
||||
}
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -513,6 +519,7 @@ void Record<ESM::BirthSign>::print()
|
|||
std::vector<std::string>::iterator pit;
|
||||
for (pit = mData.mPowers.mList.begin(); pit != mData.mPowers.mList.end(); ++pit)
|
||||
std::cout << " Power: " << *pit << std::endl;
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -541,6 +548,7 @@ void Record<ESM::Cell>::print()
|
|||
std::cout << " Map Color: " << boost::format("0x%08X") % mData.mMapColor << std::endl;
|
||||
std::cout << " Water Level Int: " << mData.mWaterInt << std::endl;
|
||||
std::cout << " RefId counter: " << mData.mRefNumCounter << std::endl;
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
|
||||
}
|
||||
|
||||
|
@ -563,6 +571,7 @@ void Record<ESM::Class>::print()
|
|||
for (int i = 0; i != 5; i++)
|
||||
std::cout << " Major Skill: " << skillLabel(mData.mData.mSkills[i][1])
|
||||
<< " (" << mData.mData.mSkills[i][1] << ")" << std::endl;
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -589,6 +598,7 @@ void Record<ESM::Clothing>::print()
|
|||
if (pit->mFemale != "")
|
||||
std::cout << " Female Name: " << pit->mFemale << std::endl;
|
||||
}
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -604,6 +614,7 @@ void Record<ESM::Container>::print()
|
|||
for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); ++cit)
|
||||
std::cout << " Inventory: Count: " << boost::format("%4d") % cit->mCount
|
||||
<< " Item: " << cit->mItem.toString() << std::endl;
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -670,6 +681,7 @@ void Record<ESM::Creature>::print()
|
|||
std::vector<ESM::AIPackage>::iterator pit;
|
||||
for (pit = mData.mAiPackage.mList.begin(); pit != mData.mAiPackage.mList.end(); ++pit)
|
||||
printAIPackage(*pit);
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -677,6 +689,7 @@ void Record<ESM::Dialogue>::print()
|
|||
{
|
||||
std::cout << " Type: " << dialogTypeLabel(mData.mType)
|
||||
<< " (" << (int)mData.mType << ")" << std::endl;
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
// Sadly, there are no DialInfos, because the loader dumps as it
|
||||
// loads, rather than loading and then dumping. :-( Anyone mind if
|
||||
// I change this?
|
||||
|
@ -693,6 +706,7 @@ void Record<ESM::Door>::print()
|
|||
std::cout << " Script: " << mData.mScript << std::endl;
|
||||
std::cout << " OpenSound: " << mData.mOpenSound << std::endl;
|
||||
std::cout << " CloseSound: " << mData.mCloseSound << std::endl;
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -704,6 +718,7 @@ void Record<ESM::Enchantment>::print()
|
|||
std::cout << " Charge: " << mData.mData.mCharge << std::endl;
|
||||
std::cout << " AutoCalc: " << mData.mData.mAutocalc << std::endl;
|
||||
printEffectList(mData.mEffects);
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -737,12 +752,14 @@ void Record<ESM::Faction>::print()
|
|||
std::map<std::string, int>::iterator rit;
|
||||
for (rit = mData.mReactions.begin(); rit != mData.mReactions.end(); ++rit)
|
||||
std::cout << " Reaction: " << rit->second << " = " << rit->first << std::endl;
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
void Record<ESM::Global>::print()
|
||||
{
|
||||
std::cout << " " << mData.mValue << std::endl;
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -809,6 +826,7 @@ void Record<ESM::DialInfo>::print()
|
|||
std::cout << " Result Script: [skipped]" << std::endl;
|
||||
}
|
||||
}
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -832,6 +850,7 @@ void Record<ESM::Ingredient>::print()
|
|||
std::cout << " Attribute: " << attributeLabel(mData.mData.mAttributes[i])
|
||||
<< " (" << mData.mData.mAttributes[i] << ")" << std::endl;
|
||||
}
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -848,6 +867,8 @@ void Record<ESM::Land>::print()
|
|||
std::cout << " Unknown1: " << data->mUnk1 << std::endl;
|
||||
std::cout << " Unknown2: " << data->mUnk2 << std::endl;
|
||||
}
|
||||
mData.unloadData();
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -860,6 +881,7 @@ void Record<ESM::CreatureLevList>::print()
|
|||
for (iit = mData.mList.begin(); iit != mData.mList.end(); ++iit)
|
||||
std::cout << " Creature: Level: " << iit->mLevel
|
||||
<< " Creature: " << iit->mId << std::endl;
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -872,6 +894,7 @@ void Record<ESM::ItemLevList>::print()
|
|||
for (iit = mData.mList.begin(); iit != mData.mList.end(); ++iit)
|
||||
std::cout << " Inventory: Level: " << iit->mLevel
|
||||
<< " Item: " << iit->mId << std::endl;
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -892,6 +915,7 @@ void Record<ESM::Light>::print()
|
|||
std::cout << " Duration: " << mData.mData.mTime << std::endl;
|
||||
std::cout << " Radius: " << mData.mData.mRadius << std::endl;
|
||||
std::cout << " Color: " << mData.mData.mColor << std::endl;
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -906,6 +930,7 @@ void Record<ESM::Lockpick>::print()
|
|||
std::cout << " Value: " << mData.mData.mValue << std::endl;
|
||||
std::cout << " Quality: " << mData.mData.mQuality << std::endl;
|
||||
std::cout << " Uses: " << mData.mData.mUses << std::endl;
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -920,6 +945,7 @@ void Record<ESM::Probe>::print()
|
|||
std::cout << " Value: " << mData.mData.mValue << std::endl;
|
||||
std::cout << " Quality: " << mData.mData.mQuality << std::endl;
|
||||
std::cout << " Uses: " << mData.mData.mUses << std::endl;
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -934,6 +960,7 @@ void Record<ESM::Repair>::print()
|
|||
std::cout << " Value: " << mData.mData.mValue << std::endl;
|
||||
std::cout << " Quality: " << mData.mData.mQuality << std::endl;
|
||||
std::cout << " Uses: " << mData.mData.mUses << std::endl;
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -942,6 +969,7 @@ void Record<ESM::LandTexture>::print()
|
|||
std::cout << " Id: " << mData.mId << std::endl;
|
||||
std::cout << " Index: " << mData.mIndex << std::endl;
|
||||
std::cout << " Texture: " << mData.mTexture << std::endl;
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -992,6 +1020,7 @@ void Record<ESM::Miscellaneous>::print()
|
|||
std::cout << " Weight: " << mData.mData.mWeight << std::endl;
|
||||
std::cout << " Value: " << mData.mData.mValue << std::endl;
|
||||
std::cout << " Is Key: " << mData.mData.mIsKey << std::endl;
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -1077,6 +1106,8 @@ void Record<ESM::NPC>::print()
|
|||
std::vector<ESM::AIPackage>::iterator pit;
|
||||
for (pit = mData.mAiPackage.mList.begin(); pit != mData.mAiPackage.mList.end(); ++pit)
|
||||
printAIPackage(*pit);
|
||||
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -1111,6 +1142,8 @@ void Record<ESM::Pathgrid>::print()
|
|||
std::cout << " BAD POINT IN EDGE!" << std::endl;
|
||||
i++;
|
||||
}
|
||||
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -1151,6 +1184,8 @@ void Record<ESM::Race>::print()
|
|||
std::vector<std::string>::iterator sit;
|
||||
for (sit = mData.mPowers.mList.begin(); sit != mData.mPowers.mList.end(); ++sit)
|
||||
std::cout << " Power: " << *sit << std::endl;
|
||||
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -1210,6 +1245,8 @@ void Record<ESM::Script>::print()
|
|||
{
|
||||
std::cout << " Script: [skipped]" << std::endl;
|
||||
}
|
||||
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -1233,6 +1270,7 @@ void Record<ESM::SoundGenerator>::print()
|
|||
std::cout << " Sound: " << mData.mSound << std::endl;
|
||||
std::cout << " Type: " << soundTypeLabel(mData.mType)
|
||||
<< " (" << mData.mType << ")" << std::endl;
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -1243,6 +1281,7 @@ void Record<ESM::Sound>::print()
|
|||
if (mData.mData.mMinRange != 0 && mData.mData.mMaxRange != 0)
|
||||
std::cout << " Range: " << (int)mData.mData.mMinRange << " - "
|
||||
<< (int)mData.mData.mMaxRange << std::endl;
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -1254,13 +1293,15 @@ void Record<ESM::Spell>::print()
|
|||
std::cout << " Flags: " << spellFlags(mData.mData.mFlags) << std::endl;
|
||||
std::cout << " Cost: " << mData.mData.mCost << std::endl;
|
||||
printEffectList(mData.mEffects);
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
void Record<ESM::StartScript>::print()
|
||||
{
|
||||
std::cout << "Start Script: " << mData.mId << std::endl;
|
||||
std::cout << "Start Data: " << mData.mData << std::endl;
|
||||
std::cout << " Start Script: " << mData.mId << std::endl;
|
||||
std::cout << " Start Data: " << mData.mData << std::endl;
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -1301,6 +1342,37 @@ void Record<ESM::Weapon>::print()
|
|||
if (mData.mData.mThrust[0] != 0 && mData.mData.mThrust[1] != 0)
|
||||
std::cout << " Thrust: " << (int)mData.mData.mThrust[0] << "-"
|
||||
<< (int)mData.mData.mThrust[1] << std::endl;
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
}
|
||||
|
||||
template<>
|
||||
std::string Record<ESM::Cell>::getId() const
|
||||
{
|
||||
return mData.mName;
|
||||
}
|
||||
|
||||
template<>
|
||||
std::string Record<ESM::Land>::getId() const
|
||||
{
|
||||
return ""; // No ID for Land record
|
||||
}
|
||||
|
||||
template<>
|
||||
std::string Record<ESM::MagicEffect>::getId() const
|
||||
{
|
||||
return ""; // No ID for MagicEffect record
|
||||
}
|
||||
|
||||
template<>
|
||||
std::string Record<ESM::Pathgrid>::getId() const
|
||||
{
|
||||
return ""; // No ID for Pathgrid record
|
||||
}
|
||||
|
||||
template<>
|
||||
std::string Record<ESM::Skill>::getId() const
|
||||
{
|
||||
return ""; // No ID for Skill record
|
||||
}
|
||||
|
||||
} // end namespace
|
||||
|
|
|
@ -32,13 +32,7 @@ namespace EsmTool
|
|||
|
||||
virtual ~RecordBase() {}
|
||||
|
||||
const std::string &getId() const {
|
||||
return mId;
|
||||
}
|
||||
|
||||
void setId(const std::string &id) {
|
||||
mId = id;
|
||||
}
|
||||
virtual std::string getId() const = 0;
|
||||
|
||||
uint32_t getFlags() const {
|
||||
return mFlags;
|
||||
|
@ -73,22 +67,37 @@ namespace EsmTool
|
|||
class Record : public RecordBase
|
||||
{
|
||||
T mData;
|
||||
bool mIsDeleted;
|
||||
|
||||
public:
|
||||
Record()
|
||||
: mIsDeleted(false)
|
||||
{}
|
||||
|
||||
std::string getId() const {
|
||||
return mData.mId;
|
||||
}
|
||||
|
||||
T &get() {
|
||||
return mData;
|
||||
}
|
||||
|
||||
void save(ESM::ESMWriter &esm) {
|
||||
mData.save(esm);
|
||||
mData.save(esm, mIsDeleted);
|
||||
}
|
||||
|
||||
void load(ESM::ESMReader &esm) {
|
||||
mData.load(esm);
|
||||
mData.load(esm, mIsDeleted);
|
||||
}
|
||||
|
||||
void print();
|
||||
};
|
||||
|
||||
template<> std::string Record<ESM::Cell>::getId() const;
|
||||
template<> std::string Record<ESM::Land>::getId() const;
|
||||
template<> std::string Record<ESM::MagicEffect>::getId() const;
|
||||
template<> std::string Record<ESM::Pathgrid>::getId() const;
|
||||
template<> std::string Record<ESM::Skill>::getId() const;
|
||||
|
||||
template<> void Record<ESM::Activator>::print();
|
||||
template<> void Record<ESM::Potion>::print();
|
||||
|
|
|
@ -158,9 +158,9 @@ namespace ESSImport
|
|||
void ConvertCell::read(ESM::ESMReader &esm)
|
||||
{
|
||||
ESM::Cell cell;
|
||||
std::string id = esm.getHNString("NAME");
|
||||
cell.mName = id;
|
||||
cell.load(esm, false);
|
||||
bool isDeleted = false;
|
||||
|
||||
cell.load(esm, isDeleted, false);
|
||||
|
||||
// I wonder what 0x40 does?
|
||||
if (cell.isExterior() && cell.mData.mFlags & 0x20)
|
||||
|
@ -169,7 +169,7 @@ namespace ESSImport
|
|||
}
|
||||
|
||||
// note if the player is in a nameless exterior cell, we will assign the cellId later based on player position
|
||||
if (id == mContext->mPlayerCellName)
|
||||
if (cell.mName == mContext->mPlayerCellName)
|
||||
{
|
||||
mContext->mPlayer.mCellId = cell.getCellId();
|
||||
}
|
||||
|
@ -277,7 +277,7 @@ namespace ESSImport
|
|||
if (cell.isExterior())
|
||||
mExtCells[std::make_pair(cell.mData.mX, cell.mData.mY)] = newcell;
|
||||
else
|
||||
mIntCells[id] = newcell;
|
||||
mIntCells[cell.mName] = newcell;
|
||||
}
|
||||
|
||||
void ConvertCell::writeCell(const Cell &cell, ESM::ESMWriter& esm)
|
||||
|
|
|
@ -54,6 +54,8 @@ public:
|
|||
|
||||
void setContext(Context& context) { mContext = &context; }
|
||||
|
||||
/// @note The load method of ESM records accept the deleted flag as a parameter.
|
||||
/// I don't know can the DELE sub-record appear in saved games, so the deleted flag will be ignored.
|
||||
virtual void read(ESM::ESMReader& esm)
|
||||
{
|
||||
}
|
||||
|
@ -78,10 +80,11 @@ public:
|
|||
|
||||
virtual void read(ESM::ESMReader& esm)
|
||||
{
|
||||
std::string id = esm.getHNString("NAME");
|
||||
T record;
|
||||
record.load(esm);
|
||||
mRecords[id] = record;
|
||||
bool isDeleted = false;
|
||||
|
||||
record.load(esm, isDeleted);
|
||||
mRecords[record.mId] = record;
|
||||
}
|
||||
|
||||
virtual void write(ESM::ESMWriter& esm)
|
||||
|
@ -89,7 +92,6 @@ public:
|
|||
for (typename std::map<std::string, T>::const_iterator it = mRecords.begin(); it != mRecords.end(); ++it)
|
||||
{
|
||||
esm.startRecord(T::sRecordId);
|
||||
esm.writeHNString("NAME", it->first);
|
||||
it->second.save(esm);
|
||||
esm.endRecord(T::sRecordId);
|
||||
}
|
||||
|
@ -105,14 +107,15 @@ public:
|
|||
virtual void read(ESM::ESMReader &esm)
|
||||
{
|
||||
ESM::NPC npc;
|
||||
std::string id = esm.getHNString("NAME");
|
||||
npc.load(esm);
|
||||
if (id != "player")
|
||||
bool isDeleted = false;
|
||||
|
||||
npc.load(esm, isDeleted);
|
||||
if (npc.mId != "player")
|
||||
{
|
||||
// Handles changes to the NPC struct, but since there is no index here
|
||||
// it will apply to ALL instances of the class. seems to be the reason for the
|
||||
// "feature" in MW where changing AI settings of one guard will change it for all guards of that refID.
|
||||
mContext->mNpcs[Misc::StringUtils::lowerCase(id)] = npc;
|
||||
mContext->mNpcs[Misc::StringUtils::lowerCase(npc.mId)] = npc;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -142,9 +145,10 @@ public:
|
|||
{
|
||||
// See comment in ConvertNPC
|
||||
ESM::Creature creature;
|
||||
std::string id = esm.getHNString("NAME");
|
||||
creature.load(esm);
|
||||
mContext->mCreatures[Misc::StringUtils::lowerCase(id)] = creature;
|
||||
bool isDeleted = false;
|
||||
|
||||
creature.load(esm, isDeleted);
|
||||
mContext->mCreatures[Misc::StringUtils::lowerCase(creature.mId)] = creature;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -157,18 +161,19 @@ class ConvertGlobal : public DefaultConverter<ESM::Global>
|
|||
public:
|
||||
virtual void read(ESM::ESMReader &esm)
|
||||
{
|
||||
std::string id = esm.getHNString("NAME");
|
||||
ESM::Global global;
|
||||
global.load(esm);
|
||||
if (Misc::StringUtils::ciEqual(id, "gamehour"))
|
||||
bool isDeleted = false;
|
||||
|
||||
global.load(esm, isDeleted);
|
||||
if (Misc::StringUtils::ciEqual(global.mId, "gamehour"))
|
||||
mContext->mHour = global.mValue.getFloat();
|
||||
if (Misc::StringUtils::ciEqual(id, "day"))
|
||||
if (Misc::StringUtils::ciEqual(global.mId, "day"))
|
||||
mContext->mDay = global.mValue.getInteger();
|
||||
if (Misc::StringUtils::ciEqual(id, "month"))
|
||||
if (Misc::StringUtils::ciEqual(global.mId, "month"))
|
||||
mContext->mMonth = global.mValue.getInteger();
|
||||
if (Misc::StringUtils::ciEqual(id, "year"))
|
||||
if (Misc::StringUtils::ciEqual(global.mId, "year"))
|
||||
mContext->mYear = global.mValue.getInteger();
|
||||
mRecords[id] = global;
|
||||
mRecords[global.mId] = global;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -177,14 +182,14 @@ class ConvertClass : public DefaultConverter<ESM::Class>
|
|||
public:
|
||||
virtual void read(ESM::ESMReader &esm)
|
||||
{
|
||||
std::string id = esm.getHNString("NAME");
|
||||
ESM::Class class_;
|
||||
class_.load(esm);
|
||||
bool isDeleted = false;
|
||||
|
||||
if (id == "NEWCLASSID_CHARGEN")
|
||||
class_.load(esm, isDeleted);
|
||||
if (class_.mId == "NEWCLASSID_CHARGEN")
|
||||
mContext->mCustomPlayerClassName = class_.mName;
|
||||
|
||||
mRecords[id] = class_;
|
||||
mRecords[class_.mId] = class_;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -193,13 +198,14 @@ class ConvertBook : public DefaultConverter<ESM::Book>
|
|||
public:
|
||||
virtual void read(ESM::ESMReader &esm)
|
||||
{
|
||||
std::string id = esm.getHNString("NAME");
|
||||
ESM::Book book;
|
||||
book.load(esm);
|
||||
if (book.mData.mSkillID == -1)
|
||||
mContext->mPlayer.mObject.mNpcStats.mUsedIds.push_back(Misc::StringUtils::lowerCase(id));
|
||||
bool isDeleted = false;
|
||||
|
||||
mRecords[id] = book;
|
||||
book.load(esm, isDeleted);
|
||||
if (book.mData.mSkillID == -1)
|
||||
mContext->mPlayer.mObject.mNpcStats.mUsedIds.push_back(Misc::StringUtils::lowerCase(book.mId));
|
||||
|
||||
mRecords[book.mId] = book;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -371,11 +377,12 @@ class ConvertFACT : public Converter
|
|||
public:
|
||||
virtual void read(ESM::ESMReader& esm)
|
||||
{
|
||||
std::string id = esm.getHNString("NAME");
|
||||
ESM::Faction faction;
|
||||
faction.load(esm);
|
||||
bool isDeleted = false;
|
||||
|
||||
faction.load(esm, isDeleted);
|
||||
std::string id = Misc::StringUtils::lowerCase(faction.mId);
|
||||
|
||||
Misc::StringUtils::toLower(id);
|
||||
for (std::map<std::string, int>::const_iterator it = faction.mReactions.begin(); it != faction.mReactions.end(); ++it)
|
||||
{
|
||||
std::string faction2 = Misc::StringUtils::lowerCase(it->first);
|
||||
|
@ -391,7 +398,7 @@ public:
|
|||
virtual void read(ESM::ESMReader &esm)
|
||||
{
|
||||
std::string itemid = esm.getHNString("NAME");
|
||||
Misc::StringUtils::toLower(itemid);
|
||||
Misc::StringUtils::lowerCaseInPlace(itemid);
|
||||
|
||||
while (esm.isNextSub("FNAM") || esm.isNextSub("ONAM"))
|
||||
{
|
||||
|
|
|
@ -32,7 +32,8 @@ namespace ESSImport
|
|||
if (esm.isNextSub("MNAM"))
|
||||
esm.skipHSub();
|
||||
|
||||
ESM::CellRef::loadData(esm);
|
||||
bool isDeleted = false;
|
||||
ESM::CellRef::loadData(esm, isDeleted);
|
||||
|
||||
mHasACDT = false;
|
||||
if (esm.isNextSub("ACDT"))
|
||||
|
|
|
@ -54,7 +54,7 @@ namespace
|
|||
*(image->data(x,y)+2) = *it++;
|
||||
*(image->data(x,y)+1) = *it++;
|
||||
*image->data(x,y) = *it++;
|
||||
it++; // skip alpha
|
||||
++it; // skip alpha
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -394,7 +394,7 @@ namespace ESSImport
|
|||
}
|
||||
|
||||
writer.startRecord(ESM::REC_NPC_);
|
||||
writer.writeHNString("NAME", "player");
|
||||
context.mPlayerBase.mId = "player";
|
||||
context.mPlayerBase.save(writer);
|
||||
writer.endRecord(ESM::REC_NPC_);
|
||||
|
||||
|
|
|
@ -32,7 +32,8 @@ namespace ESSImport
|
|||
item.mSCRI.load(esm);
|
||||
|
||||
// for XSOL and XCHG seen so far, but probably others too
|
||||
item.ESM::CellRef::loadData(esm);
|
||||
bool isDeleted = false;
|
||||
item.ESM::CellRef::loadData(esm, isDeleted);
|
||||
|
||||
int charge=-1;
|
||||
esm.getHNOT(charge, "XHLT");
|
||||
|
|
|
@ -7,8 +7,6 @@ set(LAUNCHER
|
|||
textslotmsgbox.cpp
|
||||
settingspage.cpp
|
||||
|
||||
settings/graphicssettings.cpp
|
||||
|
||||
utils/profilescombobox.cpp
|
||||
utils/textinputdialog.cpp
|
||||
utils/lineedit.cpp
|
||||
|
@ -24,8 +22,6 @@ set(LAUNCHER_HEADER
|
|||
textslotmsgbox.hpp
|
||||
settingspage.hpp
|
||||
|
||||
settings/graphicssettings.hpp
|
||||
|
||||
utils/profilescombobox.hpp
|
||||
utils/textinputdialog.hpp
|
||||
utils/lineedit.hpp
|
||||
|
|
|
@ -75,7 +75,7 @@ bool Launcher::DataFilesPage::loadSettings()
|
|||
QStringList profiles = mLauncherSettings.getContentLists();
|
||||
QString currentProfile = mLauncherSettings.getCurrentContentListName();
|
||||
|
||||
qDebug() << "current profile is: " << currentProfile;
|
||||
qDebug() << "The current profile is: " << currentProfile;
|
||||
|
||||
foreach (const QString &item, profiles)
|
||||
addProfile (item, false);
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
#include <components/contentselector/model/naturalsort.hpp>
|
||||
|
||||
#include "settings/graphicssettings.hpp"
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
QString getAspect(int x, int y)
|
||||
{
|
||||
|
@ -32,10 +32,10 @@ QString getAspect(int x, int y)
|
|||
return QString(QString::number(xaspect) + ":" + QString::number(yaspect));
|
||||
}
|
||||
|
||||
Launcher::GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, GraphicsSettings &graphicsSetting, QWidget *parent)
|
||||
Launcher::GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, Settings::Manager &engineSettings, QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, mCfgMgr(cfg)
|
||||
, mGraphicsSettings(graphicsSetting)
|
||||
, mEngineSettings(engineSettings)
|
||||
{
|
||||
setObjectName ("GraphicsPage");
|
||||
setupUi(this);
|
||||
|
@ -80,25 +80,26 @@ bool Launcher::GraphicsPage::loadSettings()
|
|||
if (!setupSDL())
|
||||
return false;
|
||||
|
||||
if (mGraphicsSettings.value(QString("Video/vsync")) == QLatin1String("true"))
|
||||
if (mEngineSettings.getBool("vsync", "Video"))
|
||||
vSyncCheckBox->setCheckState(Qt::Checked);
|
||||
|
||||
if (mGraphicsSettings.value(QString("Video/fullscreen")) == QLatin1String("true"))
|
||||
if (mEngineSettings.getBool("fullscreen", "Video"))
|
||||
fullScreenCheckBox->setCheckState(Qt::Checked);
|
||||
|
||||
if (mGraphicsSettings.value(QString("Video/window border")) == QLatin1String("true"))
|
||||
if (mEngineSettings.getBool("window border", "Video"))
|
||||
windowBorderCheckBox->setCheckState(Qt::Checked);
|
||||
|
||||
int aaIndex = antiAliasingComboBox->findText(mGraphicsSettings.value(QString("Video/antialiasing")));
|
||||
// aaValue is the actual value (0, 1, 2, 4, 8, 16)
|
||||
int aaValue = mEngineSettings.getInt("antialiasing", "Video");
|
||||
// aaIndex is the index into the allowed values in the pull down.
|
||||
int aaIndex = antiAliasingComboBox->findText(QString::number(aaValue));
|
||||
if (aaIndex != -1)
|
||||
antiAliasingComboBox->setCurrentIndex(aaIndex);
|
||||
|
||||
QString width = mGraphicsSettings.value(QString("Video/resolution x"));
|
||||
QString height = mGraphicsSettings.value(QString("Video/resolution y"));
|
||||
QString resolution = width + QString(" x ") + height;
|
||||
QString screen = mGraphicsSettings.value(QString("Video/screen"));
|
||||
|
||||
screenComboBox->setCurrentIndex(screen.toInt());
|
||||
int width = mEngineSettings.getInt("resolution x", "Video");
|
||||
int height = mEngineSettings.getInt("resolution y", "Video");
|
||||
QString resolution = QString::number(width) + QString(" x ") + QString::number(height);
|
||||
screenComboBox->setCurrentIndex(mEngineSettings.getInt("screen", "Video"));
|
||||
|
||||
int resIndex = resolutionComboBox->findText(resolution, Qt::MatchStartsWith);
|
||||
|
||||
|
@ -107,9 +108,8 @@ bool Launcher::GraphicsPage::loadSettings()
|
|||
resolutionComboBox->setCurrentIndex(resIndex);
|
||||
} else {
|
||||
customRadioButton->toggle();
|
||||
customWidthSpinBox->setValue(width.toInt());
|
||||
customHeightSpinBox->setValue(height.toInt());
|
||||
|
||||
customWidthSpinBox->setValue(width);
|
||||
customHeightSpinBox->setValue(height);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -117,31 +117,46 @@ bool Launcher::GraphicsPage::loadSettings()
|
|||
|
||||
void Launcher::GraphicsPage::saveSettings()
|
||||
{
|
||||
vSyncCheckBox->checkState() ? mGraphicsSettings.setValue(QString("Video/vsync"), QString("true"))
|
||||
: mGraphicsSettings.setValue(QString("Video/vsync"), QString("false"));
|
||||
// Ensure we only set the new settings if they changed. This is to avoid cluttering the
|
||||
// user settings file (which by definition should only contain settings the user has touched)
|
||||
bool cVSync = vSyncCheckBox->checkState();
|
||||
if (cVSync != mEngineSettings.getBool("vsync", "Video"))
|
||||
mEngineSettings.setBool("vsync", "Video", cVSync);
|
||||
|
||||
fullScreenCheckBox->checkState() ? mGraphicsSettings.setValue(QString("Video/fullscreen"), QString("true"))
|
||||
: mGraphicsSettings.setValue(QString("Video/fullscreen"), QString("false"));
|
||||
bool cFullScreen = fullScreenCheckBox->checkState();
|
||||
if (cFullScreen != mEngineSettings.getBool("fullscreen", "Video"))
|
||||
mEngineSettings.setBool("fullscreen", "Video", cFullScreen);
|
||||
|
||||
windowBorderCheckBox->checkState() ? mGraphicsSettings.setValue(QString("Video/window border"), QString("true"))
|
||||
: mGraphicsSettings.setValue(QString("Video/window border"), QString("false"));
|
||||
|
||||
mGraphicsSettings.setValue(QString("Video/antialiasing"), antiAliasingComboBox->currentText());
|
||||
bool cWindowBorder = windowBorderCheckBox->checkState();
|
||||
if (cWindowBorder != mEngineSettings.getBool("window border", "Video"))
|
||||
mEngineSettings.setBool("window border", "Video", cWindowBorder);
|
||||
|
||||
int cAAValue = antiAliasingComboBox->currentText().toInt();
|
||||
if (cAAValue != mEngineSettings.getInt("antialiasing", "Video"))
|
||||
mEngineSettings.setInt("antialiasing", "Video", cAAValue);
|
||||
|
||||
int cWidth = 0;
|
||||
int cHeight = 0;
|
||||
if (standardRadioButton->isChecked()) {
|
||||
QRegExp resolutionRe(QString("(\\d+) x (\\d+).*"));
|
||||
|
||||
if (resolutionRe.exactMatch(resolutionComboBox->currentText().simplified())) {
|
||||
mGraphicsSettings.setValue(QString("Video/resolution x"), resolutionRe.cap(1));
|
||||
mGraphicsSettings.setValue(QString("Video/resolution y"), resolutionRe.cap(2));
|
||||
cWidth = resolutionRe.cap(1).toInt();
|
||||
cHeight = resolutionRe.cap(2).toInt();
|
||||
}
|
||||
} else {
|
||||
mGraphicsSettings.setValue(QString("Video/resolution x"), QString::number(customWidthSpinBox->value()));
|
||||
mGraphicsSettings.setValue(QString("Video/resolution y"), QString::number(customHeightSpinBox->value()));
|
||||
cWidth = customWidthSpinBox->value();
|
||||
cHeight = customHeightSpinBox->value();
|
||||
}
|
||||
|
||||
mGraphicsSettings.setValue(QString("Video/screen"), QString::number(screenComboBox->currentIndex()));
|
||||
if (cWidth != mEngineSettings.getInt("resolution x", "Video"))
|
||||
mEngineSettings.setInt("resolution x", "Video", cWidth);
|
||||
|
||||
if (cHeight != mEngineSettings.getInt("resolution y", "Video"))
|
||||
mEngineSettings.setInt("resolution y", "Video", cHeight);
|
||||
|
||||
int cScreen = screenComboBox->currentIndex();
|
||||
if (cScreen != mEngineSettings.getInt("screen", "Video"))
|
||||
mEngineSettings.setInt("screen", "Video", cScreen);
|
||||
}
|
||||
|
||||
QStringList Launcher::GraphicsPage::getAvailableResolutions(int screen)
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
#include "ui_graphicspage.h"
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
namespace Files { struct ConfigurationManager; }
|
||||
|
||||
namespace Launcher
|
||||
|
@ -16,7 +18,7 @@ namespace Launcher
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GraphicsPage(Files::ConfigurationManager &cfg, GraphicsSettings &graphicsSettings, QWidget *parent = 0);
|
||||
GraphicsPage(Files::ConfigurationManager &cfg, Settings::Manager &engineSettings, QWidget *parent = 0);
|
||||
|
||||
void saveSettings();
|
||||
bool loadSettings();
|
||||
|
@ -30,7 +32,7 @@ namespace Launcher
|
|||
|
||||
private:
|
||||
Files::ConfigurationManager &mCfgMgr;
|
||||
GraphicsSettings &mGraphicsSettings;
|
||||
Settings::Manager &mEngineSettings;
|
||||
|
||||
QStringList getAvailableResolutions(int screen);
|
||||
QRect getMaximumResolution();
|
||||
|
|
|
@ -41,15 +41,6 @@ int main(int argc, char *argv[])
|
|||
dir.cdUp();
|
||||
dir.cdUp();
|
||||
}
|
||||
|
||||
// force Qt to load only LOCAL plugins, don't touch system Qt installation
|
||||
QDir pluginsPath(QCoreApplication::applicationDirPath());
|
||||
pluginsPath.cdUp();
|
||||
pluginsPath.cd("Plugins");
|
||||
|
||||
QStringList libraryPaths;
|
||||
libraryPaths << pluginsPath.path() << QCoreApplication::applicationDirPath();
|
||||
app.setLibraryPaths(libraryPaths);
|
||||
#endif
|
||||
|
||||
QDir::setCurrent(dir.absolutePath());
|
||||
|
@ -60,10 +51,6 @@ int main(int argc, char *argv[])
|
|||
if (result == Launcher::FirstRunDialogResultFailure)
|
||||
return 0;
|
||||
|
||||
// if (!mainWin.setup()) {
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
if (result == Launcher::FirstRunDialogResultContinue)
|
||||
mainWin.show();
|
||||
|
||||
|
|
|
@ -24,6 +24,15 @@
|
|||
|
||||
using namespace Process;
|
||||
|
||||
void cfgError(const QString& title, const QString& msg) {
|
||||
QMessageBox msgBox;
|
||||
msgBox.setWindowTitle(title);
|
||||
msgBox.setIcon(QMessageBox::Critical);
|
||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||
msgBox.setText(msg);
|
||||
msgBox.exec();
|
||||
}
|
||||
|
||||
Launcher::MainDialog::MainDialog(QWidget *parent)
|
||||
: QMainWindow(parent), mGameSettings (mCfgMgr)
|
||||
{
|
||||
|
@ -105,7 +114,7 @@ void Launcher::MainDialog::createPages()
|
|||
{
|
||||
mPlayPage = new PlayPage(this);
|
||||
mDataFilesPage = new DataFilesPage(mCfgMgr, mGameSettings, mLauncherSettings, this);
|
||||
mGraphicsPage = new GraphicsPage(mCfgMgr, mGraphicsSettings, this);
|
||||
mGraphicsPage = new GraphicsPage(mCfgMgr, mEngineSettings, this);
|
||||
mSettingsPage = new SettingsPage(mCfgMgr, mGameSettings, mLauncherSettings, this);
|
||||
|
||||
// Set the combobox of the play page to imitate the combobox on the datafilespage
|
||||
|
@ -248,6 +257,8 @@ void Launcher::MainDialog::changePage(QListWidgetItem *current, QListWidgetItem
|
|||
|
||||
bool Launcher::MainDialog::setupLauncherSettings()
|
||||
{
|
||||
mLauncherSettings.clear();
|
||||
|
||||
mLauncherSettings.setMultiValueEnabled(true);
|
||||
|
||||
QString userPath = QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str());
|
||||
|
@ -257,18 +268,14 @@ bool Launcher::MainDialog::setupLauncherSettings()
|
|||
paths.append(userPath + QString(Config::LauncherSettings::sLauncherConfigFileName));
|
||||
|
||||
foreach (const QString &path, paths) {
|
||||
qDebug() << "Loading config file:" << qPrintable(path);
|
||||
qDebug() << "Loading config file:" << path.toUtf8().constData();
|
||||
QFile file(path);
|
||||
if (file.exists()) {
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
QMessageBox msgBox;
|
||||
msgBox.setWindowTitle(tr("Error opening OpenMW configuration file"));
|
||||
msgBox.setIcon(QMessageBox::Critical);
|
||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||
msgBox.setText(tr("<br><b>Could not open %0 for reading</b><br><br> \
|
||||
Please make sure you have the right permissions \
|
||||
and try again.<br>").arg(file.fileName()));
|
||||
msgBox.exec();
|
||||
cfgError(tr("Error opening OpenMW configuration file"),
|
||||
tr("<br><b>Could not open %0 for reading</b><br><br> \
|
||||
Please make sure you have the right permissions \
|
||||
and try again.<br>").arg(file.fileName()));
|
||||
return false;
|
||||
}
|
||||
QTextStream stream(&file);
|
||||
|
@ -284,6 +291,8 @@ bool Launcher::MainDialog::setupLauncherSettings()
|
|||
|
||||
bool Launcher::MainDialog::setupGameSettings()
|
||||
{
|
||||
mGameSettings.clear();
|
||||
|
||||
QString userPath = QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str());
|
||||
QString globalPath = QString::fromUtf8(mCfgMgr.getGlobalPath().string().c_str());
|
||||
|
||||
|
@ -292,18 +301,14 @@ bool Launcher::MainDialog::setupGameSettings()
|
|||
QString path = userPath + QLatin1String("openmw.cfg");
|
||||
QFile file(path);
|
||||
|
||||
qDebug() << "Loading config file:" << qPrintable(path);
|
||||
qDebug() << "Loading config file:" << path.toUtf8().constData();
|
||||
|
||||
if (file.exists()) {
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
QMessageBox msgBox;
|
||||
msgBox.setWindowTitle(tr("Error opening OpenMW configuration file"));
|
||||
msgBox.setIcon(QMessageBox::Critical);
|
||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||
msgBox.setText(tr("<br><b>Could not open %0 for reading</b><br><br> \
|
||||
Please make sure you have the right permissions \
|
||||
and try again.<br>").arg(file.fileName()));
|
||||
msgBox.exec();
|
||||
cfgError(tr("Error opening OpenMW configuration file"),
|
||||
tr("<br><b>Could not open %0 for reading</b><br><br> \
|
||||
Please make sure you have the right permissions \
|
||||
and try again.<br>").arg(file.fileName()));
|
||||
return false;
|
||||
}
|
||||
QTextStream stream(&file);
|
||||
|
@ -319,19 +324,15 @@ bool Launcher::MainDialog::setupGameSettings()
|
|||
paths.append(userPath + QString("openmw.cfg"));
|
||||
|
||||
foreach (const QString &path, paths) {
|
||||
qDebug() << "Loading config file:" << qPrintable(path);
|
||||
qDebug() << "Loading config file:" << path.toUtf8().constData();
|
||||
|
||||
QFile file(path);
|
||||
if (file.exists()) {
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
QMessageBox msgBox;
|
||||
msgBox.setWindowTitle(tr("Error opening OpenMW configuration file"));
|
||||
msgBox.setIcon(QMessageBox::Critical);
|
||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||
msgBox.setText(tr("<br><b>Could not open %0 for reading</b><br><br> \
|
||||
Please make sure you have the right permissions \
|
||||
and try again.<br>").arg(file.fileName()));
|
||||
msgBox.exec();
|
||||
cfgError(tr("Error opening OpenMW configuration file"),
|
||||
tr("<br><b>Could not open %0 for reading</b><br><br> \
|
||||
Please make sure you have the right permissions \
|
||||
and try again.<br>").arg(file.fileName()));
|
||||
return false;
|
||||
}
|
||||
QTextStream stream(&file);
|
||||
|
@ -383,53 +384,54 @@ bool Launcher::MainDialog::setupGameSettings()
|
|||
|
||||
bool Launcher::MainDialog::setupGraphicsSettings()
|
||||
{
|
||||
mGraphicsSettings.setMultiValueEnabled(false);
|
||||
// This method is almost a copy of OMW::Engine::loadSettings(). They should definitely
|
||||
// remain consistent, and possibly be merged into a shared component. At the very least
|
||||
// the filenames should be in the CfgMgr component.
|
||||
|
||||
QString userPath = QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str());
|
||||
QString globalPath = QString::fromUtf8(mCfgMgr.getGlobalPath().string().c_str());
|
||||
// Ensure to clear previous settings in case we had already loaded settings.
|
||||
mEngineSettings.clear();
|
||||
|
||||
QFile localDefault(QString("settings-default.cfg"));
|
||||
QFile globalDefault(globalPath + QString("settings-default.cfg"));
|
||||
// Create the settings manager and load default settings file
|
||||
const std::string localDefault = (mCfgMgr.getLocalPath() / "settings-default.cfg").string();
|
||||
const std::string globalDefault = (mCfgMgr.getGlobalPath() / "settings-default.cfg").string();
|
||||
std::string defaultPath;
|
||||
|
||||
if (!localDefault.exists() && !globalDefault.exists()) {
|
||||
QMessageBox msgBox;
|
||||
msgBox.setWindowTitle(tr("Error reading OpenMW configuration file"));
|
||||
msgBox.setIcon(QMessageBox::Critical);
|
||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||
msgBox.setText(tr("<br><b>Could not find settings-default.cfg</b><br><br> \
|
||||
The problem may be due to an incomplete installation of OpenMW.<br> \
|
||||
Reinstalling OpenMW may resolve the problem."));
|
||||
msgBox.exec();
|
||||
// Prefer the settings-default.cfg in the current directory.
|
||||
if (boost::filesystem::exists(localDefault))
|
||||
defaultPath = localDefault;
|
||||
else if (boost::filesystem::exists(globalDefault))
|
||||
defaultPath = globalDefault;
|
||||
// Something's very wrong if we can't find the file at all.
|
||||
else {
|
||||
cfgError(tr("Error reading OpenMW configuration file"),
|
||||
tr("<br><b>Could not find settings-default.cfg</b><br><br> \
|
||||
The problem may be due to an incomplete installation of OpenMW.<br> \
|
||||
Reinstalling OpenMW may resolve the problem."));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load the default settings, report any parsing errors.
|
||||
try {
|
||||
mEngineSettings.loadDefault(defaultPath);
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
std::string msg = std::string("<br><b>Error reading settings-default.cfg</b><br><br>") + e.what();
|
||||
cfgError(tr("Error reading OpenMW configuration file"), tr(msg.c_str()));
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList paths;
|
||||
paths.append(globalPath + QString("settings-default.cfg"));
|
||||
paths.append(QString("settings-default.cfg"));
|
||||
paths.append(userPath + QString("settings.cfg"));
|
||||
// Load user settings if they exist
|
||||
const std::string userPath = (mCfgMgr.getUserConfigPath() / "settings.cfg").string();
|
||||
// User settings are not required to exist, so if they don't we're done.
|
||||
if (!boost::filesystem::exists(userPath)) return true;
|
||||
|
||||
foreach (const QString &path, paths) {
|
||||
qDebug() << "Loading config file:" << qPrintable(path);
|
||||
QFile file(path);
|
||||
if (file.exists()) {
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
QMessageBox msgBox;
|
||||
msgBox.setWindowTitle(tr("Error opening OpenMW configuration file"));
|
||||
msgBox.setIcon(QMessageBox::Critical);
|
||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||
msgBox.setText(tr("<br><b>Could not open %0 for reading</b><br><br> \
|
||||
Please make sure you have the right permissions \
|
||||
and try again.<br>").arg(file.fileName()));
|
||||
msgBox.exec();
|
||||
return false;
|
||||
}
|
||||
QTextStream stream(&file);
|
||||
stream.setCodec(QTextCodec::codecForName("UTF-8"));
|
||||
|
||||
mGraphicsSettings.readFile(stream);
|
||||
}
|
||||
file.close();
|
||||
try {
|
||||
mEngineSettings.loadUser(userPath);
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
std::string msg = std::string("<br><b>Error reading settings.cfg</b><br><br>") + e.what();
|
||||
cfgError(tr("Error reading OpenMW configuration file"), tr(msg.c_str()));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -478,15 +480,11 @@ bool Launcher::MainDialog::writeSettings()
|
|||
|
||||
if (!dir.exists()) {
|
||||
if (!dir.mkpath(userPath)) {
|
||||
QMessageBox msgBox;
|
||||
msgBox.setWindowTitle(tr("Error creating OpenMW configuration directory"));
|
||||
msgBox.setIcon(QMessageBox::Critical);
|
||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||
msgBox.setText(tr("<br><b>Could not create %0</b><br><br> \
|
||||
Please make sure you have the right permissions \
|
||||
and try again.<br>").arg(userPath));
|
||||
msgBox.exec();
|
||||
return false;
|
||||
cfgError(tr("Error creating OpenMW configuration directory"),
|
||||
tr("<br><b>Could not create %0</b><br><br> \
|
||||
Please make sure you have the right permissions \
|
||||
and try again.<br>").arg(userPath));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -495,15 +493,11 @@ bool Launcher::MainDialog::writeSettings()
|
|||
|
||||
if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) {
|
||||
// File cannot be opened or created
|
||||
QMessageBox msgBox;
|
||||
msgBox.setWindowTitle(tr("Error writing OpenMW configuration file"));
|
||||
msgBox.setIcon(QMessageBox::Critical);
|
||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||
msgBox.setText(tr("<br><b>Could not open or create %0 for writing</b><br><br> \
|
||||
Please make sure you have the right permissions \
|
||||
and try again.<br>").arg(file.fileName()));
|
||||
msgBox.exec();
|
||||
return false;
|
||||
cfgError(tr("Error writing OpenMW configuration file"),
|
||||
tr("<br><b>Could not open or create %0 for writing</b><br><br> \
|
||||
Please make sure you have the right permissions \
|
||||
and try again.<br>").arg(file.fileName()));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -511,44 +505,30 @@ bool Launcher::MainDialog::writeSettings()
|
|||
file.close();
|
||||
|
||||
// Graphics settings
|
||||
file.setFileName(userPath + QString("settings.cfg"));
|
||||
|
||||
if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) {
|
||||
// File cannot be opened or created
|
||||
QMessageBox msgBox;
|
||||
msgBox.setWindowTitle(tr("Error writing OpenMW configuration file"));
|
||||
msgBox.setIcon(QMessageBox::Critical);
|
||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||
msgBox.setText(tr("<br><b>Could not open or create %0 for writing</b><br><br> \
|
||||
Please make sure you have the right permissions \
|
||||
and try again.<br>").arg(file.fileName()));
|
||||
msgBox.exec();
|
||||
return false;
|
||||
const std::string settingsPath = (mCfgMgr.getUserConfigPath() / "settings.cfg").string();
|
||||
try {
|
||||
mEngineSettings.saveUser(settingsPath);
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
std::string msg = "<br><b>Error writing settings.cfg</b><br><br>" +
|
||||
settingsPath + "<br><br>" + e.what();
|
||||
cfgError(tr("Error writing user settings file"), tr(msg.c_str()));
|
||||
return false;
|
||||
}
|
||||
|
||||
QTextStream stream(&file);
|
||||
stream.setDevice(&file);
|
||||
stream.setCodec(QTextCodec::codecForName("UTF-8"));
|
||||
|
||||
mGraphicsSettings.writeFile(stream);
|
||||
file.close();
|
||||
|
||||
// Launcher settings
|
||||
file.setFileName(userPath + QString(Config::LauncherSettings::sLauncherConfigFileName));
|
||||
|
||||
if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) {
|
||||
// File cannot be opened or created
|
||||
QMessageBox msgBox;
|
||||
msgBox.setWindowTitle(tr("Error writing Launcher configuration file"));
|
||||
msgBox.setIcon(QMessageBox::Critical);
|
||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||
msgBox.setText(tr("<br><b>Could not open or create %0 for writing</b><br><br> \
|
||||
Please make sure you have the right permissions \
|
||||
and try again.<br>").arg(file.fileName()));
|
||||
msgBox.exec();
|
||||
return false;
|
||||
cfgError(tr("Error writing Launcher configuration file"),
|
||||
tr("<br><b>Could not open or create %0 for writing</b><br><br> \
|
||||
Please make sure you have the right permissions \
|
||||
and try again.<br>").arg(file.fileName()));
|
||||
return false;
|
||||
}
|
||||
|
||||
QTextStream stream(&file);
|
||||
stream.setDevice(&file);
|
||||
stream.setCodec(QTextCodec::codecForName("UTF-8"));
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#include <components/config/gamesettings.hpp>
|
||||
#include <components/config/launchersettings.hpp>
|
||||
|
||||
#include "settings/graphicssettings.hpp"
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
|
@ -50,7 +50,6 @@ namespace Launcher
|
|||
explicit MainDialog(QWidget *parent = 0);
|
||||
~MainDialog();
|
||||
|
||||
bool setup();
|
||||
FirstRunDialogResult showFirstRunDialog();
|
||||
|
||||
bool reloadSettings();
|
||||
|
@ -65,6 +64,8 @@ namespace Launcher
|
|||
void wizardFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
|
||||
private:
|
||||
bool setup();
|
||||
|
||||
void createIcons();
|
||||
void createPages();
|
||||
|
||||
|
@ -93,7 +94,7 @@ namespace Launcher
|
|||
Files::ConfigurationManager mCfgMgr;
|
||||
|
||||
Config::GameSettings mGameSettings;
|
||||
GraphicsSettings mGraphicsSettings;
|
||||
Settings::Manager mEngineSettings;
|
||||
Config::LauncherSettings mLauncherSettings;
|
||||
|
||||
};
|
||||
|
|
|
@ -2,20 +2,11 @@
|
|||
|
||||
#include <QListView>
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#include <QPlastiqueStyle>
|
||||
#endif
|
||||
|
||||
Launcher::PlayPage::PlayPage(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
setObjectName ("PlayPage");
|
||||
setupUi(this);
|
||||
|
||||
// Hacks to get the stylesheet look properly
|
||||
#ifdef Q_OS_MAC
|
||||
QPlastiqueStyle *style = new QPlastiqueStyle;
|
||||
profilesComboBox->setStyle(style);
|
||||
#endif
|
||||
profilesComboBox->setView(new QListView());
|
||||
|
||||
connect(profilesComboBox, SIGNAL(activated(int)), this, SIGNAL (signalProfileChanged(int)));
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
#include "graphicssettings.hpp"
|
||||
|
||||
#include <QTextStream>
|
||||
#include <QString>
|
||||
#include <QRegExp>
|
||||
#include <QMap>
|
||||
|
||||
Launcher::GraphicsSettings::GraphicsSettings()
|
||||
{
|
||||
}
|
||||
|
||||
Launcher::GraphicsSettings::~GraphicsSettings()
|
||||
{
|
||||
}
|
||||
|
||||
bool Launcher::GraphicsSettings::writeFile(QTextStream &stream)
|
||||
{
|
||||
QString sectionPrefix;
|
||||
QRegExp sectionRe("([^/]+)/(.+)$");
|
||||
QMap<QString, QString> settings = SettingsBase::getSettings();
|
||||
|
||||
QMapIterator<QString, QString> i(settings);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
|
||||
QString prefix;
|
||||
QString key;
|
||||
|
||||
if (sectionRe.exactMatch(i.key())) {
|
||||
prefix = sectionRe.cap(1);
|
||||
key = sectionRe.cap(2);
|
||||
}
|
||||
|
||||
if (sectionPrefix != prefix) {
|
||||
sectionPrefix = prefix;
|
||||
stream << "\n[" << prefix << "]\n";
|
||||
}
|
||||
|
||||
stream << key << " = " << i.value() << "\n";
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
#ifndef GRAPHICSSETTINGS_HPP
|
||||
#define GRAPHICSSETTINGS_HPP
|
||||
|
||||
#include <components/config/settingsbase.hpp>
|
||||
|
||||
namespace Launcher
|
||||
{
|
||||
class GraphicsSettings : public Config::SettingsBase<QMap<QString, QString> >
|
||||
{
|
||||
public:
|
||||
GraphicsSettings();
|
||||
~GraphicsSettings();
|
||||
|
||||
bool writeFile(QTextStream &stream);
|
||||
|
||||
};
|
||||
}
|
||||
#endif // GRAPHICSSETTINGS_HPP
|
|
@ -1,5 +1,6 @@
|
|||
#include "importer.hpp"
|
||||
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
@ -20,7 +21,6 @@ MwIniImporter::MwIniImporter()
|
|||
{
|
||||
const char *map[][2] =
|
||||
{
|
||||
{ "fps", "General:Show FPS" },
|
||||
{ "no-sound", "General:Disable Audio" },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
@ -639,6 +639,9 @@ MwIniImporter::MwIniImporter()
|
|||
"Blood:Texture Name 1",
|
||||
"Blood:Texture Name 2",
|
||||
|
||||
// werewolf (Bloodmoon)
|
||||
"General:Werewolf FOV",
|
||||
|
||||
0
|
||||
};
|
||||
|
||||
|
@ -847,7 +850,7 @@ void MwIniImporter::importGameFiles(multistrmap &cfg, const multistrmap &ini, co
|
|||
|
||||
for(std::vector<std::string>::const_iterator entry = it->second.begin(); entry!=it->second.end(); ++entry) {
|
||||
std::string filetype(entry->substr(entry->length()-3));
|
||||
Misc::StringUtils::toLower(filetype);
|
||||
Misc::StringUtils::lowerCaseInPlace(filetype);
|
||||
|
||||
if(filetype.compare("esm") == 0 || filetype.compare("esp") == 0) {
|
||||
boost::filesystem::path filepath(gameFilesDir);
|
||||
|
@ -895,8 +898,13 @@ std::time_t MwIniImporter::lastWriteTime(const boost::filesystem::path& filename
|
|||
boost::filesystem::path resolved = filename;
|
||||
#endif
|
||||
writeTime = boost::filesystem::last_write_time(resolved);
|
||||
std::cout << "content file: " << resolved << " timestamp = (" << writeTime <<
|
||||
") " << asctime(localtime(&writeTime)) << std::endl;
|
||||
|
||||
// print timestamp
|
||||
const int size=1024;
|
||||
char timeStrBuffer[size];
|
||||
if (std::strftime(timeStrBuffer, size, "%x %X", localtime(&writeTime)) > 0)
|
||||
std::cout << "content file: " << resolved << " timestamp = (" << writeTime <<
|
||||
") " << timeStrBuffer << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -26,7 +26,7 @@ opencs_units_noqt (model/world
|
|||
universalid record commands columnbase columnimp scriptcontext cell refidcollection
|
||||
refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection resources resourcesmanager scope
|
||||
pathgrid landtexture land nestedtablewrapper nestedcollection nestedcoladapterimp nestedinfocollection
|
||||
idcompletionmanager metadata
|
||||
idcompletionmanager metadata defaultgmsts
|
||||
)
|
||||
|
||||
opencs_hdrs_noqt (model/world
|
||||
|
@ -42,7 +42,7 @@ opencs_units_noqt (model/tools
|
|||
mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck
|
||||
birthsigncheck spellcheck referencecheck referenceablecheck scriptcheck bodypartcheck
|
||||
startscriptcheck search searchoperation searchstage pathgridcheck soundgencheck magiceffectcheck
|
||||
mergestages
|
||||
mergestages gmstcheck
|
||||
)
|
||||
|
||||
opencs_hdrs_noqt (model/tools
|
||||
|
@ -94,7 +94,7 @@ opencs_units_noqt (view/render
|
|||
)
|
||||
|
||||
opencs_hdrs_noqt (view/render
|
||||
elements
|
||||
mask
|
||||
)
|
||||
|
||||
|
||||
|
@ -106,31 +106,16 @@ opencs_units_noqt (view/tools
|
|||
subviews
|
||||
)
|
||||
|
||||
opencs_units (view/settings
|
||||
settingwindow
|
||||
dialog
|
||||
page
|
||||
view
|
||||
booleanview
|
||||
textview
|
||||
listview
|
||||
rangeview
|
||||
resizeablestackedwidget
|
||||
spinbox
|
||||
opencs_units (view/prefs
|
||||
dialogue pagebase page
|
||||
)
|
||||
|
||||
opencs_units_noqt (view/settings
|
||||
frame
|
||||
opencs_units (model/prefs
|
||||
state setting intsetting doublesetting boolsetting enumsetting coloursetting
|
||||
)
|
||||
|
||||
opencs_units (model/settings
|
||||
usersettings
|
||||
setting
|
||||
connector
|
||||
)
|
||||
|
||||
opencs_hdrs_noqt (model/settings
|
||||
support
|
||||
opencs_units_noqt (model/prefs
|
||||
category
|
||||
)
|
||||
|
||||
opencs_units_noqt (model/filter
|
||||
|
@ -205,7 +190,13 @@ if(APPLE)
|
|||
endif(APPLE)
|
||||
|
||||
target_link_libraries(openmw-cs
|
||||
${OPENSCENEGRAPH_LIBRARIES}
|
||||
${OSG_LIBRARIES}
|
||||
${OPENTHREADS_LIBRARIES}
|
||||
${OSGUTIL_LIBRARIES}
|
||||
${OSGVIEWER_LIBRARIES}
|
||||
${OSGGA_LIBRARIES}
|
||||
${OSGFX_LIBRARIES}
|
||||
${OSGQT_LIBRARIES}
|
||||
${Boost_SYSTEM_LIBRARY}
|
||||
${Boost_FILESYSTEM_LIBRARY}
|
||||
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include <components/vfs/manager.hpp>
|
||||
#include <components/vfs/registerarchives.hpp>
|
||||
|
||||
#include <components/fallback/validate.hpp>
|
||||
|
||||
#include <components/nifosg/nifloader.hpp>
|
||||
|
||||
#include "model/doc/document.hpp"
|
||||
|
@ -17,8 +19,10 @@
|
|||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
using namespace Fallback;
|
||||
|
||||
CS::Editor::Editor ()
|
||||
: mUserSettings (mCfgMgr), mDocumentManager (mCfgMgr),
|
||||
: mSettingsState (mCfgMgr), mDocumentManager (mCfgMgr),
|
||||
mViewManager (mDocumentManager), mPid(""),
|
||||
mLock(), mMerge (mDocumentManager),
|
||||
mIpcServerName ("org.openmw.OpenCS"), mServer(NULL), mClientSocket(NULL)
|
||||
|
@ -27,9 +31,6 @@ CS::Editor::Editor ()
|
|||
|
||||
setupDataFiles (config.first);
|
||||
|
||||
CSMSettings::UserSettings::instance().loadSettings ("opencs.ini");
|
||||
mSettings.setModel (CSMSettings::UserSettings::instance());
|
||||
|
||||
NifOsg::Loader::setShowMarkers(true);
|
||||
|
||||
mVFS.reset(new VFS::Manager(mFsStrict));
|
||||
|
@ -103,6 +104,8 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi
|
|||
("resources", boost::program_options::value<std::string>()->default_value("resources"))
|
||||
("fallback-archive", boost::program_options::value<std::vector<std::string> >()->
|
||||
default_value(std::vector<std::string>(), "fallback-archive")->multitoken())
|
||||
("fallback", boost::program_options::value<FallbackMap>()->default_value(FallbackMap(), "")
|
||||
->multitoken()->composing(), "fallback values")
|
||||
("script-blacklist", boost::program_options::value<std::vector<std::string> >()->default_value(std::vector<std::string>(), "")
|
||||
->multitoken(), "exclude specified script from the verifier (if the use of the blacklist is enabled)")
|
||||
("script-blacklist-use", boost::program_options::value<bool>()->implicit_value(true)
|
||||
|
@ -117,6 +120,8 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi
|
|||
|
||||
mDocumentManager.setResourceDir (mResources = variables["resources"].as<std::string>());
|
||||
|
||||
mDocumentManager.setFallbackMap (variables["fallback"].as<FallbackMap>().mMap);
|
||||
|
||||
if (variables["script-blacklist-use"].as<bool>())
|
||||
mDocumentManager.setBlacklistedScripts (
|
||||
variables["script-blacklist"].as<std::vector<std::string> >());
|
||||
|
|
|
@ -17,15 +17,16 @@
|
|||
|
||||
#include <components/files/multidircollection.hpp>
|
||||
|
||||
#include "model/settings/usersettings.hpp"
|
||||
#include "model/doc/documentmanager.hpp"
|
||||
|
||||
#include "model/prefs/state.hpp"
|
||||
|
||||
#include "view/doc/viewmanager.hpp"
|
||||
#include "view/doc/startup.hpp"
|
||||
#include "view/doc/filedialog.hpp"
|
||||
#include "view/doc/newgame.hpp"
|
||||
|
||||
#include "view/settings/dialog.hpp"
|
||||
#include "view/prefs/dialogue.hpp"
|
||||
|
||||
#include "view/tools/merge.hpp"
|
||||
|
||||
|
@ -49,12 +50,12 @@ namespace CS
|
|||
std::auto_ptr<VFS::Manager> mVFS;
|
||||
|
||||
Files::ConfigurationManager mCfgMgr;
|
||||
CSMSettings::UserSettings mUserSettings;
|
||||
CSMPrefs::State mSettingsState;
|
||||
CSMDoc::DocumentManager mDocumentManager;
|
||||
CSVDoc::ViewManager mViewManager;
|
||||
CSVDoc::StartupDialogue mStartup;
|
||||
CSVDoc::NewGameDialogue mNewGame;
|
||||
CSVSettings::Dialog mSettings;
|
||||
CSVPrefs::Dialogue mSettings;
|
||||
CSVDoc::FileDialog mFileDialog;
|
||||
boost::filesystem::path mLocal;
|
||||
boost::filesystem::path mResources;
|
||||
|
|
|
@ -43,6 +43,10 @@ class Application : public QApplication
|
|||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#ifdef Q_OS_MAC
|
||||
setenv("OSG_GL_TEXTURE_STORAGE", "OFF", 0);
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
// To allow background thread drawing in OSG
|
||||
|
@ -64,15 +68,6 @@ int main(int argc, char *argv[])
|
|||
dir.cdUp();
|
||||
}
|
||||
QDir::setCurrent(dir.absolutePath());
|
||||
|
||||
// force Qt to load only LOCAL plugins, don't touch system Qt installation
|
||||
QDir pluginsPath(QCoreApplication::applicationDirPath());
|
||||
pluginsPath.cdUp();
|
||||
pluginsPath.cd("Plugins");
|
||||
|
||||
QStringList libraryPaths;
|
||||
libraryPaths << pluginsPath.path() << QCoreApplication::applicationDirPath();
|
||||
application.setLibraryPaths(libraryPaths);
|
||||
#endif
|
||||
|
||||
application.setWindowIcon (QIcon (":./openmw-cs.png"));
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -25,9 +25,13 @@
|
|||
|
||||
class QAbstractItemModel;
|
||||
|
||||
namespace Fallback
|
||||
{
|
||||
class Map;
|
||||
}
|
||||
|
||||
namespace VFS
|
||||
{
|
||||
|
||||
class Manager;
|
||||
}
|
||||
|
||||
|
@ -66,6 +70,7 @@ namespace CSMDoc
|
|||
Saving mSavingOperation;
|
||||
OperationHolder mSaving;
|
||||
boost::filesystem::path mResDir;
|
||||
const Fallback::Map* mFallbackMap;
|
||||
Blacklist mBlacklist;
|
||||
Runner mRunner;
|
||||
bool mDirty;
|
||||
|
@ -101,6 +106,7 @@ namespace CSMDoc
|
|||
Document (const VFS::Manager* vfs, const Files::ConfigurationManager& configuration,
|
||||
const std::vector< boost::filesystem::path >& files, bool new_,
|
||||
const boost::filesystem::path& savePath, const boost::filesystem::path& resDir,
|
||||
const Fallback::Map* fallback,
|
||||
ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager,
|
||||
const std::vector<std::string>& blacklistedScripts);
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ CSMDoc::Document *CSMDoc::DocumentManager::makeDocument (
|
|||
const std::vector< boost::filesystem::path >& files,
|
||||
const boost::filesystem::path& savePath, bool new_)
|
||||
{
|
||||
return new Document (mVFS, mConfiguration, files, new_, savePath, mResDir, mEncoding, mResourcesManager, mBlacklistedScripts);
|
||||
return new Document (mVFS, mConfiguration, files, new_, savePath, mResDir, &mFallbackMap, mEncoding, mResourcesManager, mBlacklistedScripts);
|
||||
}
|
||||
|
||||
void CSMDoc::DocumentManager::insertDocument (CSMDoc::Document *document)
|
||||
|
@ -100,6 +100,11 @@ void CSMDoc::DocumentManager::setResourceDir (const boost::filesystem::path& par
|
|||
mResDir = boost::filesystem::system_complete(parResDir);
|
||||
}
|
||||
|
||||
void CSMDoc::DocumentManager::setFallbackMap(const std::map<std::string, std::string>& fallbackMap)
|
||||
{
|
||||
mFallbackMap = Fallback::Map(fallbackMap);
|
||||
}
|
||||
|
||||
void CSMDoc::DocumentManager::setEncoding (ToUTF8::FromType encoding)
|
||||
{
|
||||
mEncoding = encoding;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <QThread>
|
||||
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
#include <components/fallback/fallback.hpp>
|
||||
|
||||
#include "../world/resourcesmanager.hpp"
|
||||
|
||||
|
@ -67,6 +68,8 @@ namespace CSMDoc
|
|||
|
||||
void setResourceDir (const boost::filesystem::path& parResDir);
|
||||
|
||||
void setFallbackMap (const std::map<std::string, std::string>& fallbackMap);
|
||||
|
||||
void setEncoding (ToUTF8::FromType encoding);
|
||||
|
||||
void setBlacklistedScripts (const std::vector<std::string>& scriptIds);
|
||||
|
@ -78,6 +81,7 @@ namespace CSMDoc
|
|||
private:
|
||||
|
||||
boost::filesystem::path mResDir;
|
||||
Fallback::Map mFallbackMap;
|
||||
|
||||
private slots:
|
||||
|
||||
|
|
|
@ -45,13 +45,12 @@ void CSMDoc::Loader::load()
|
|||
|
||||
bool done = false;
|
||||
|
||||
const int batchingSize = 50;
|
||||
|
||||
try
|
||||
{
|
||||
if (iter->second.mRecordsLeft)
|
||||
{
|
||||
Messages messages (Message::Severity_Error);
|
||||
const int batchingSize = 50;
|
||||
for (int i=0; i<batchingSize; ++i) // do not flood the system with update signals
|
||||
if (document->getData().continueLoading (messages))
|
||||
{
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include <QTimer>
|
||||
|
||||
#include "../world/universalid.hpp"
|
||||
#include "../settings/usersettings.hpp"
|
||||
|
||||
#include "state.hpp"
|
||||
#include "stage.hpp"
|
||||
|
@ -23,9 +22,6 @@ void CSMDoc::Operation::prepareStages()
|
|||
{
|
||||
iter->second = iter->first->setup();
|
||||
mTotalSteps += iter->second;
|
||||
|
||||
for (std::map<QString, QStringList>::const_iterator iter2 (mSettings.begin()); iter2!=mSettings.end(); ++iter2)
|
||||
iter->first->updateUserSetting (iter2->first, iter2->second);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -47,7 +43,7 @@ CSMDoc::Operation::~Operation()
|
|||
void CSMDoc::Operation::run()
|
||||
{
|
||||
mTimer->stop();
|
||||
|
||||
|
||||
if (!mConnected)
|
||||
{
|
||||
connect (mTimer, SIGNAL (timeout()), this, SLOT (executeStage()));
|
||||
|
@ -64,14 +60,6 @@ void CSMDoc::Operation::appendStage (Stage *stage)
|
|||
mStages.push_back (std::make_pair (stage, 0));
|
||||
}
|
||||
|
||||
void CSMDoc::Operation::configureSettings (const std::vector<QString>& settings)
|
||||
{
|
||||
for (std::vector<QString>::const_iterator iter (settings.begin()); iter!=settings.end(); ++iter)
|
||||
{
|
||||
mSettings.insert (std::make_pair (*iter, CSMSettings::UserSettings::instance().definitions (*iter)));
|
||||
}
|
||||
}
|
||||
|
||||
void CSMDoc::Operation::setDefaultSeverity (Message::Severity severity)
|
||||
{
|
||||
mDefaultSeverity = severity;
|
||||
|
@ -101,14 +89,6 @@ void CSMDoc::Operation::abort()
|
|||
mCurrentStage = mStages.end();
|
||||
}
|
||||
|
||||
void CSMDoc::Operation::updateUserSetting (const QString& name, const QStringList& value)
|
||||
{
|
||||
std::map<QString, QStringList>::iterator iter = mSettings.find (name);
|
||||
|
||||
if (iter!=mSettings.end())
|
||||
iter->second = value;
|
||||
}
|
||||
|
||||
void CSMDoc::Operation::executeStage()
|
||||
{
|
||||
if (!mPrepared)
|
||||
|
@ -116,7 +96,7 @@ void CSMDoc::Operation::executeStage()
|
|||
prepareStages();
|
||||
mPrepared = true;
|
||||
}
|
||||
|
||||
|
||||
Messages messages (mDefaultSeverity);
|
||||
|
||||
while (mCurrentStage!=mStages.end())
|
||||
|
|
|
@ -34,7 +34,6 @@ namespace CSMDoc
|
|||
bool mError;
|
||||
bool mConnected;
|
||||
QTimer *mTimer;
|
||||
std::map<QString, QStringList> mSettings;
|
||||
bool mPrepared;
|
||||
Message::Severity mDefaultSeverity;
|
||||
|
||||
|
@ -53,11 +52,6 @@ namespace CSMDoc
|
|||
///
|
||||
/// \attention Do no call this function while this Operation is running.
|
||||
|
||||
/// Specify settings to be passed on to stages.
|
||||
///
|
||||
/// \attention Do no call this function while this Operation is running.
|
||||
void configureSettings (const std::vector<QString>& settings);
|
||||
|
||||
/// \attention Do no call this function while this Operation is running.
|
||||
void setDefaultSeverity (Message::Severity severity);
|
||||
|
||||
|
@ -77,8 +71,6 @@ namespace CSMDoc
|
|||
|
||||
void run();
|
||||
|
||||
void updateUserSetting (const QString& name, const QStringList& value);
|
||||
|
||||
private slots:
|
||||
|
||||
void executeStage();
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#include "operationholder.hpp"
|
||||
|
||||
#include "../settings/usersettings.hpp"
|
||||
|
||||
#include "operation.hpp"
|
||||
|
||||
CSMDoc::OperationHolder::OperationHolder (Operation *operation) : mRunning (false)
|
||||
|
@ -30,9 +28,6 @@ void CSMDoc::OperationHolder::setOperation (Operation *operation)
|
|||
connect (this, SIGNAL (abortSignal()), mOperation, SLOT (abort()));
|
||||
|
||||
connect (&mThread, SIGNAL (started()), mOperation, SLOT (run()));
|
||||
|
||||
connect (&CSMSettings::UserSettings::instance(), SIGNAL (userSettingUpdated (const QString&, const QStringList&)),
|
||||
mOperation, SLOT (updateUserSetting (const QString&, const QStringList&)));
|
||||
}
|
||||
|
||||
bool CSMDoc::OperationHolder::isRunning() const
|
||||
|
|
|
@ -99,84 +99,77 @@ int CSMDoc::WriteDialogueCollectionStage::setup()
|
|||
|
||||
void CSMDoc::WriteDialogueCollectionStage::perform (int stage, Messages& messages)
|
||||
{
|
||||
ESM::ESMWriter& writer = mState.getWriter();
|
||||
const CSMWorld::Record<ESM::Dialogue>& topic = mTopics.getRecord (stage);
|
||||
|
||||
CSMWorld::RecordBase::State state = topic.mState;
|
||||
|
||||
if (state==CSMWorld::RecordBase::State_Deleted)
|
||||
if (topic.mState == CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
// if the topic is deleted, we do not need to bother with INFO records.
|
||||
|
||||
/// \todo wrote record with delete flag
|
||||
|
||||
ESM::Dialogue dialogue = topic.get();
|
||||
writer.startRecord(dialogue.sRecordId);
|
||||
dialogue.save(writer, true);
|
||||
writer.endRecord(dialogue.sRecordId);
|
||||
return;
|
||||
}
|
||||
|
||||
// Test, if we need to save anything associated info records.
|
||||
bool infoModified = false;
|
||||
|
||||
CSMWorld::InfoCollection::Range range = mInfos.getTopicRange (topic.get().mId);
|
||||
|
||||
for (CSMWorld::InfoCollection::RecordConstIterator iter (range.first); iter!=range.second; ++iter)
|
||||
{
|
||||
CSMWorld::RecordBase::State state = iter->mState;
|
||||
|
||||
if (state==CSMWorld::RecordBase::State_Modified ||
|
||||
state==CSMWorld::RecordBase::State_ModifiedOnly ||
|
||||
state==CSMWorld::RecordBase::State_Deleted)
|
||||
if (iter->isModified() || iter->mState == CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
infoModified = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (state==CSMWorld::RecordBase::State_Modified ||
|
||||
state==CSMWorld::RecordBase::State_ModifiedOnly ||
|
||||
infoModified)
|
||||
if (topic.isModified() || infoModified)
|
||||
{
|
||||
mState.getWriter().startRecord (topic.mModified.sRecordId);
|
||||
mState.getWriter().writeHNCString ("NAME", topic.mModified.mId);
|
||||
topic.mModified.save (mState.getWriter());
|
||||
mState.getWriter().endRecord (topic.mModified.sRecordId);
|
||||
if (infoModified && topic.mState != CSMWorld::RecordBase::State_Modified
|
||||
&& topic.mState != CSMWorld::RecordBase::State_ModifiedOnly)
|
||||
{
|
||||
mState.getWriter().startRecord (topic.mBase.sRecordId);
|
||||
topic.mBase.save (mState.getWriter(), topic.mState == CSMWorld::RecordBase::State_Deleted);
|
||||
mState.getWriter().endRecord (topic.mBase.sRecordId);
|
||||
}
|
||||
else
|
||||
{
|
||||
mState.getWriter().startRecord (topic.mModified.sRecordId);
|
||||
topic.mModified.save (mState.getWriter(), topic.mState == CSMWorld::RecordBase::State_Deleted);
|
||||
mState.getWriter().endRecord (topic.mModified.sRecordId);
|
||||
}
|
||||
|
||||
// write modified selected info records
|
||||
for (CSMWorld::InfoCollection::RecordConstIterator iter (range.first); iter!=range.second;
|
||||
++iter)
|
||||
for (CSMWorld::InfoCollection::RecordConstIterator iter (range.first); iter!=range.second; ++iter)
|
||||
{
|
||||
CSMWorld::RecordBase::State state = iter->mState;
|
||||
|
||||
if (state==CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
/// \todo wrote record with delete flag
|
||||
}
|
||||
else if (state==CSMWorld::RecordBase::State_Modified ||
|
||||
state==CSMWorld::RecordBase::State_ModifiedOnly)
|
||||
if (iter->isModified() || iter->mState == CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
ESM::DialInfo info = iter->get();
|
||||
info.mId = info.mId.substr (info.mId.find_last_of ('#')+1);
|
||||
|
||||
info.mPrev = "";
|
||||
if (iter!=range.first)
|
||||
{
|
||||
CSMWorld::InfoCollection::RecordConstIterator prev = iter;
|
||||
--prev;
|
||||
|
||||
info.mPrev =
|
||||
prev->mModified.mId.substr (prev->mModified.mId.find_last_of ('#')+1);
|
||||
info.mPrev = prev->get().mId.substr (prev->get().mId.find_last_of ('#')+1);
|
||||
}
|
||||
|
||||
CSMWorld::InfoCollection::RecordConstIterator next = iter;
|
||||
++next;
|
||||
|
||||
info.mNext = "";
|
||||
if (next!=range.second)
|
||||
{
|
||||
info.mNext =
|
||||
next->mModified.mId.substr (next->mModified.mId.find_last_of ('#')+1);
|
||||
info.mNext = next->get().mId.substr (next->get().mId.find_last_of ('#')+1);
|
||||
}
|
||||
|
||||
mState.getWriter().startRecord (info.sRecordId);
|
||||
mState.getWriter().writeHNCString ("INAM", info.mId);
|
||||
info.save (mState.getWriter());
|
||||
mState.getWriter().endRecord (info.sRecordId);
|
||||
writer.startRecord (info.sRecordId);
|
||||
info.save (writer, iter->mState == CSMWorld::RecordBase::State_Deleted);
|
||||
writer.endRecord (info.sRecordId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -224,9 +217,7 @@ void CSMDoc::CollectionReferencesStage::perform (int stage, Messages& messages)
|
|||
const CSMWorld::Record<CSMWorld::CellRef>& record =
|
||||
mDocument.getData().getReferences().getRecord (i);
|
||||
|
||||
if (record.mState==CSMWorld::RecordBase::State_Deleted ||
|
||||
record.mState==CSMWorld::RecordBase::State_Modified ||
|
||||
record.mState==CSMWorld::RecordBase::State_ModifiedOnly)
|
||||
if (record.isModified() || record.mState == CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
std::string cellId = record.get().mOriginalCell.empty() ?
|
||||
record.get().mCell : record.get().mOriginalCell;
|
||||
|
@ -268,36 +259,34 @@ int CSMDoc::WriteCellCollectionStage::setup()
|
|||
|
||||
void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages)
|
||||
{
|
||||
const CSMWorld::Record<CSMWorld::Cell>& cell =
|
||||
mDocument.getData().getCells().getRecord (stage);
|
||||
ESM::ESMWriter& writer = mState.getWriter();
|
||||
const CSMWorld::Record<CSMWorld::Cell>& cell = mDocument.getData().getCells().getRecord (stage);
|
||||
|
||||
std::map<std::string, std::deque<int> >::const_iterator references =
|
||||
mState.getSubRecords().find (Misc::StringUtils::lowerCase (cell.get().mId));
|
||||
|
||||
if (cell.mState==CSMWorld::RecordBase::State_Modified ||
|
||||
cell.mState==CSMWorld::RecordBase::State_ModifiedOnly ||
|
||||
if (cell.isModified() ||
|
||||
cell.mState == CSMWorld::RecordBase::State_Deleted ||
|
||||
references!=mState.getSubRecords().end())
|
||||
{
|
||||
bool interior = cell.get().mId.substr (0, 1)!="#";
|
||||
CSMWorld::Cell cellRecord = cell.get();
|
||||
bool interior = cellRecord.mId.substr (0, 1)!="#";
|
||||
|
||||
// write cell data
|
||||
mState.getWriter().startRecord (cell.mModified.sRecordId);
|
||||
|
||||
mState.getWriter().writeHNOCString ("NAME", cell.get().mName);
|
||||
|
||||
ESM::Cell cell2 = cell.get();
|
||||
writer.startRecord (cellRecord.sRecordId);
|
||||
|
||||
if (interior)
|
||||
cell2.mData.mFlags |= ESM::Cell::Interior;
|
||||
cellRecord.mData.mFlags |= ESM::Cell::Interior;
|
||||
else
|
||||
{
|
||||
cell2.mData.mFlags &= ~ESM::Cell::Interior;
|
||||
cellRecord.mData.mFlags &= ~ESM::Cell::Interior;
|
||||
|
||||
std::istringstream stream (cell.get().mId.c_str());
|
||||
std::istringstream stream (cellRecord.mId.c_str());
|
||||
char ignore;
|
||||
stream >> ignore >> cell2.mData.mX >> cell2.mData.mY;
|
||||
stream >> ignore >> cellRecord.mData.mX >> cellRecord.mData.mY;
|
||||
}
|
||||
cell2.save (mState.getWriter());
|
||||
|
||||
cellRecord.save (writer, cell.mState == CSMWorld::RecordBase::State_Deleted);
|
||||
|
||||
// write references
|
||||
if (references!=mState.getSubRecords().end())
|
||||
|
@ -308,24 +297,25 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages)
|
|||
const CSMWorld::Record<CSMWorld::CellRef>& ref =
|
||||
mDocument.getData().getReferences().getRecord (*iter);
|
||||
|
||||
if (ref.mState==CSMWorld::RecordBase::State_Modified ||
|
||||
ref.mState==CSMWorld::RecordBase::State_ModifiedOnly)
|
||||
if (ref.isModified() || ref.mState == CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
CSMWorld::CellRef refRecord = ref.get();
|
||||
|
||||
// recalculate the ref's cell location
|
||||
std::ostringstream stream;
|
||||
if (!interior)
|
||||
{
|
||||
std::pair<int, int> index = ref.get().getCellIndex();
|
||||
std::pair<int, int> index = refRecord.getCellIndex();
|
||||
stream << "#" << index.first << " " << index.second;
|
||||
}
|
||||
|
||||
// An empty mOriginalCell is meant to indicate that it is the same as
|
||||
// the current cell. It is possible that a moved ref is moved again.
|
||||
if ((ref.get().mOriginalCell.empty() ? ref.get().mCell : ref.get().mOriginalCell)
|
||||
if ((refRecord.mOriginalCell.empty() ? refRecord.mCell : refRecord.mOriginalCell)
|
||||
!= stream.str() && !interior)
|
||||
{
|
||||
ESM::MovedCellRef moved;
|
||||
moved.mRefNum = ref.get().mRefNum;
|
||||
moved.mRefNum = refRecord.mRefNum;
|
||||
|
||||
// Need to fill mTarget with the ref's new position.
|
||||
std::istringstream istream (stream.str().c_str());
|
||||
|
@ -333,24 +323,16 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages)
|
|||
char ignore;
|
||||
istream >> ignore >> moved.mTarget[0] >> moved.mTarget[1];
|
||||
|
||||
ref.get().mRefNum.save (mState.getWriter(), false, "MVRF");
|
||||
mState.getWriter().writeHNT ("CNDT", moved.mTarget, 8);
|
||||
refRecord.mRefNum.save (writer, false, "MVRF");
|
||||
writer.writeHNT ("CNDT", moved.mTarget, 8);
|
||||
}
|
||||
|
||||
ref.get().save (mState.getWriter());
|
||||
}
|
||||
else if (ref.mState==CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
/// \todo write record with delete flag
|
||||
refRecord.save (writer, false, false, ref.mState == CSMWorld::RecordBase::State_Deleted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mState.getWriter().endRecord (cell.mModified.sRecordId);
|
||||
}
|
||||
else if (cell.mState==CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
/// \todo write record with delete flag
|
||||
writer.endRecord (cellRecord.sRecordId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -367,11 +349,11 @@ int CSMDoc::WritePathgridCollectionStage::setup()
|
|||
|
||||
void CSMDoc::WritePathgridCollectionStage::perform (int stage, Messages& messages)
|
||||
{
|
||||
const CSMWorld::Record<CSMWorld::Pathgrid>& pathgrid =
|
||||
ESM::ESMWriter& writer = mState.getWriter();
|
||||
const CSMWorld::Record<CSMWorld::Pathgrid>& pathgrid =
|
||||
mDocument.getData().getPathgrids().getRecord (stage);
|
||||
|
||||
if (pathgrid.mState==CSMWorld::RecordBase::State_Modified ||
|
||||
pathgrid.mState==CSMWorld::RecordBase::State_ModifiedOnly)
|
||||
if (pathgrid.isModified() || pathgrid.mState == CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
CSMWorld::Pathgrid record = pathgrid.get();
|
||||
|
||||
|
@ -384,15 +366,9 @@ void CSMDoc::WritePathgridCollectionStage::perform (int stage, Messages& message
|
|||
else
|
||||
record.mCell = record.mId;
|
||||
|
||||
mState.getWriter().startRecord (record.sRecordId);
|
||||
|
||||
record.save (mState.getWriter());
|
||||
|
||||
mState.getWriter().endRecord (record.sRecordId);
|
||||
}
|
||||
else if (pathgrid.mState==CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
/// \todo write record with delete flag
|
||||
writer.startRecord (record.sRecordId);
|
||||
record.save (writer, pathgrid.mState == CSMWorld::RecordBase::State_Deleted);
|
||||
writer.endRecord (record.sRecordId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -409,26 +385,16 @@ int CSMDoc::WriteLandCollectionStage::setup()
|
|||
|
||||
void CSMDoc::WriteLandCollectionStage::perform (int stage, Messages& messages)
|
||||
{
|
||||
const CSMWorld::Record<CSMWorld::Land>& land =
|
||||
ESM::ESMWriter& writer = mState.getWriter();
|
||||
const CSMWorld::Record<CSMWorld::Land>& land =
|
||||
mDocument.getData().getLand().getRecord (stage);
|
||||
|
||||
if (land.mState==CSMWorld::RecordBase::State_Modified ||
|
||||
land.mState==CSMWorld::RecordBase::State_ModifiedOnly)
|
||||
if (land.isModified() || land.mState == CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
const CSMWorld::Land& record = land.get();
|
||||
|
||||
mState.getWriter().startRecord (record.sRecordId);
|
||||
|
||||
record.save (mState.getWriter());
|
||||
|
||||
if (const ESM::Land::LandData *data = record.getLandData (record.mDataTypes))
|
||||
data->save (mState.getWriter());
|
||||
|
||||
mState.getWriter().endRecord (record.sRecordId);
|
||||
}
|
||||
else if (land.mState==CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
/// \todo write record with delete flag
|
||||
CSMWorld::Land record = land.get();
|
||||
writer.startRecord (record.sRecordId);
|
||||
record.save (writer, land.mState == CSMWorld::RecordBase::State_Deleted);
|
||||
writer.endRecord (record.sRecordId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -445,25 +411,16 @@ int CSMDoc::WriteLandTextureCollectionStage::setup()
|
|||
|
||||
void CSMDoc::WriteLandTextureCollectionStage::perform (int stage, Messages& messages)
|
||||
{
|
||||
const CSMWorld::Record<CSMWorld::LandTexture>& landTexture =
|
||||
ESM::ESMWriter& writer = mState.getWriter();
|
||||
const CSMWorld::Record<CSMWorld::LandTexture>& landTexture =
|
||||
mDocument.getData().getLandTextures().getRecord (stage);
|
||||
|
||||
if (landTexture.mState==CSMWorld::RecordBase::State_Modified ||
|
||||
landTexture.mState==CSMWorld::RecordBase::State_ModifiedOnly)
|
||||
if (landTexture.isModified() || landTexture.mState == CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
CSMWorld::LandTexture record = landTexture.get();
|
||||
|
||||
mState.getWriter().startRecord (record.sRecordId);
|
||||
|
||||
mState.getWriter().writeHNString("NAME", record.mId);
|
||||
|
||||
record.save (mState.getWriter());
|
||||
|
||||
mState.getWriter().endRecord (record.sRecordId);
|
||||
}
|
||||
else if (landTexture.mState==CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
/// \todo write record with delete flag
|
||||
writer.startRecord (record.sRecordId);
|
||||
record.save (writer, landTexture.mState == CSMWorld::RecordBase::State_Deleted);
|
||||
writer.endRecord (record.sRecordId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -100,26 +100,17 @@ namespace CSMDoc
|
|||
if (CSMWorld::getScopeFromId (mCollection.getRecord (stage).get().mId)!=mScope)
|
||||
return;
|
||||
|
||||
ESM::ESMWriter& writer = mState.getWriter();
|
||||
CSMWorld::RecordBase::State state = mCollection.getRecord (stage).mState;
|
||||
typename CollectionT::ESXRecord record = mCollection.getRecord (stage).get();
|
||||
|
||||
if (state==CSMWorld::RecordBase::State_Modified ||
|
||||
state==CSMWorld::RecordBase::State_ModifiedOnly)
|
||||
if (state == CSMWorld::RecordBase::State_Modified ||
|
||||
state == CSMWorld::RecordBase::State_ModifiedOnly ||
|
||||
state == CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
// FIXME: A quick Workaround to support records which should not write
|
||||
// NAME, including SKIL, MGEF and SCPT. If there are many more
|
||||
// idcollection records that doesn't use NAME then a more generic
|
||||
// solution may be required.
|
||||
uint32_t name = mCollection.getRecord (stage).mModified.sRecordId;
|
||||
mState.getWriter().startRecord (name);
|
||||
|
||||
if(name != ESM::REC_SKIL && name != ESM::REC_MGEF && name != ESM::REC_SCPT)
|
||||
mState.getWriter().writeHNCString ("NAME", mCollection.getId (stage));
|
||||
mCollection.getRecord (stage).mModified.save (mState.getWriter());
|
||||
mState.getWriter().endRecord (mCollection.getRecord (stage).mModified.sRecordId);
|
||||
}
|
||||
else if (state==CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
/// \todo write record with delete flag
|
||||
writer.startRecord (record.sRecordId);
|
||||
record.save (writer, state == CSMWorld::RecordBase::State_Deleted);
|
||||
writer.endRecord (record.sRecordId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#include "stage.hpp"
|
||||
|
||||
CSMDoc::Stage::~Stage() {}
|
||||
|
||||
void CSMDoc::Stage::updateUserSetting (const QString& name, const QStringList& value) {}
|
||||
|
|
|
@ -23,11 +23,7 @@ namespace CSMDoc
|
|||
|
||||
virtual void perform (int stage, Messages& messages) = 0;
|
||||
///< Messages resulting from this stage will be appended to \a messages.
|
||||
|
||||
/// Default-implementation: ignore
|
||||
virtual void updateUserSetting (const QString& name, const QStringList& value);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
47
apps/opencs/model/prefs/boolsetting.cpp
Normal file
47
apps/opencs/model/prefs/boolsetting.cpp
Normal file
|
@ -0,0 +1,47 @@
|
|||
|
||||
#include "boolsetting.hpp"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QMutexLocker>
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "category.hpp"
|
||||
#include "state.hpp"
|
||||
|
||||
CSMPrefs::BoolSetting::BoolSetting (Category *parent, Settings::Manager *values,
|
||||
QMutex *mutex, const std::string& key, const std::string& label, bool default_)
|
||||
: Setting (parent, values, mutex, key, label), mDefault (default_)
|
||||
{}
|
||||
|
||||
CSMPrefs::BoolSetting& CSMPrefs::BoolSetting::setTooltip (const std::string& tooltip)
|
||||
{
|
||||
mTooltip = tooltip;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::pair<QWidget *, QWidget *> CSMPrefs::BoolSetting::makeWidgets (QWidget *parent)
|
||||
{
|
||||
QCheckBox *widget = new QCheckBox (QString::fromUtf8 (getLabel().c_str()), parent);
|
||||
widget->setCheckState (mDefault ? Qt::Checked : Qt::Unchecked);
|
||||
|
||||
if (!mTooltip.empty())
|
||||
{
|
||||
QString tooltip = QString::fromUtf8 (mTooltip.c_str());
|
||||
widget->setToolTip (tooltip);
|
||||
}
|
||||
|
||||
connect (widget, SIGNAL (stateChanged (int)), this, SLOT (valueChanged (int)));
|
||||
|
||||
return std::make_pair (static_cast<QWidget *> (0), widget);
|
||||
}
|
||||
|
||||
void CSMPrefs::BoolSetting::valueChanged (int value)
|
||||
{
|
||||
{
|
||||
QMutexLocker lock (getMutex());
|
||||
getValues().setBool (getKey(), getParent()->getKey(), value);
|
||||
}
|
||||
|
||||
getParent()->getState()->update (*this);
|
||||
}
|
31
apps/opencs/model/prefs/boolsetting.hpp
Normal file
31
apps/opencs/model/prefs/boolsetting.hpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
#ifndef CSM_PREFS_BOOLSETTING_H
|
||||
#define CSM_PREFS_BOOLSETTING_H
|
||||
|
||||
#include "setting.hpp"
|
||||
|
||||
namespace CSMPrefs
|
||||
{
|
||||
class BoolSetting : public Setting
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
std::string mTooltip;
|
||||
bool mDefault;
|
||||
|
||||
public:
|
||||
|
||||
BoolSetting (Category *parent, Settings::Manager *values,
|
||||
QMutex *mutex, const std::string& key, const std::string& label, bool default_);
|
||||
|
||||
BoolSetting& setTooltip (const std::string& tooltip);
|
||||
|
||||
/// Return label, input widget.
|
||||
virtual std::pair<QWidget *, QWidget *> makeWidgets (QWidget *parent);
|
||||
|
||||
private slots:
|
||||
|
||||
void valueChanged (int value);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
51
apps/opencs/model/prefs/category.cpp
Normal file
51
apps/opencs/model/prefs/category.cpp
Normal file
|
@ -0,0 +1,51 @@
|
|||
|
||||
#include "category.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "setting.hpp"
|
||||
#include "state.hpp"
|
||||
|
||||
CSMPrefs::Category::Category (State *parent, const std::string& key)
|
||||
: mParent (parent), mKey (key)
|
||||
{}
|
||||
|
||||
const std::string& CSMPrefs::Category::getKey() const
|
||||
{
|
||||
return mKey;
|
||||
}
|
||||
|
||||
CSMPrefs::State *CSMPrefs::Category::getState() const
|
||||
{
|
||||
return mParent;
|
||||
}
|
||||
|
||||
void CSMPrefs::Category::addSetting (Setting *setting)
|
||||
{
|
||||
mSettings.push_back (setting);
|
||||
}
|
||||
|
||||
CSMPrefs::Category::Iterator CSMPrefs::Category::begin()
|
||||
{
|
||||
return mSettings.begin();
|
||||
}
|
||||
|
||||
CSMPrefs::Category::Iterator CSMPrefs::Category::end()
|
||||
{
|
||||
return mSettings.end();
|
||||
}
|
||||
|
||||
CSMPrefs::Setting& CSMPrefs::Category::operator[] (const std::string& key)
|
||||
{
|
||||
for (Iterator iter = mSettings.begin(); iter!=mSettings.end(); ++iter)
|
||||
if ((*iter)->getKey()==key)
|
||||
return **iter;
|
||||
|
||||
throw std::logic_error ("Invalid user setting: " + key);
|
||||
}
|
||||
|
||||
void CSMPrefs::Category::update()
|
||||
{
|
||||
for (Iterator iter = mSettings.begin(); iter!=mSettings.end(); ++iter)
|
||||
mParent->update (**iter);
|
||||
}
|
45
apps/opencs/model/prefs/category.hpp
Normal file
45
apps/opencs/model/prefs/category.hpp
Normal file
|
@ -0,0 +1,45 @@
|
|||
#ifndef CSM_PREFS_CATEGORY_H
|
||||
#define CSM_PREFS_CATEGORY_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace CSMPrefs
|
||||
{
|
||||
class State;
|
||||
class Setting;
|
||||
|
||||
class Category
|
||||
{
|
||||
public:
|
||||
|
||||
typedef std::vector<Setting *> Container;
|
||||
typedef Container::iterator Iterator;
|
||||
|
||||
private:
|
||||
|
||||
State *mParent;
|
||||
std::string mKey;
|
||||
Container mSettings;
|
||||
|
||||
public:
|
||||
|
||||
Category (State *parent, const std::string& key);
|
||||
|
||||
const std::string& getKey() const;
|
||||
|
||||
State *getState() const;
|
||||
|
||||
void addSetting (Setting *setting);
|
||||
|
||||
Iterator begin();
|
||||
|
||||
Iterator end();
|
||||
|
||||
Setting& operator[] (const std::string& key);
|
||||
|
||||
void update();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
52
apps/opencs/model/prefs/coloursetting.cpp
Normal file
52
apps/opencs/model/prefs/coloursetting.cpp
Normal file
|
@ -0,0 +1,52 @@
|
|||
|
||||
#include "coloursetting.hpp"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QMutexLocker>
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "../../view/widget/coloreditor.hpp"
|
||||
|
||||
#include "category.hpp"
|
||||
#include "state.hpp"
|
||||
|
||||
CSMPrefs::ColourSetting::ColourSetting (Category *parent, Settings::Manager *values,
|
||||
QMutex *mutex, const std::string& key, const std::string& label, QColor default_)
|
||||
: Setting (parent, values, mutex, key, label), mDefault (default_)
|
||||
{}
|
||||
|
||||
CSMPrefs::ColourSetting& CSMPrefs::ColourSetting::setTooltip (const std::string& tooltip)
|
||||
{
|
||||
mTooltip = tooltip;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::pair<QWidget *, QWidget *> CSMPrefs::ColourSetting::makeWidgets (QWidget *parent)
|
||||
{
|
||||
QLabel *label = new QLabel (QString::fromUtf8 (getLabel().c_str()), parent);
|
||||
|
||||
CSVWidget::ColorEditor *widget = new CSVWidget::ColorEditor (mDefault, parent);
|
||||
|
||||
if (!mTooltip.empty())
|
||||
{
|
||||
QString tooltip = QString::fromUtf8 (mTooltip.c_str());
|
||||
label->setToolTip (tooltip);
|
||||
widget->setToolTip (tooltip);
|
||||
}
|
||||
|
||||
connect (widget, SIGNAL (pickingFinished()), this, SLOT (valueChanged()));
|
||||
|
||||
return std::make_pair (label, widget);
|
||||
}
|
||||
|
||||
void CSMPrefs::ColourSetting::valueChanged()
|
||||
{
|
||||
CSVWidget::ColorEditor& widget = dynamic_cast<CSVWidget::ColorEditor&> (*sender());
|
||||
{
|
||||
QMutexLocker lock (getMutex());
|
||||
getValues().setString (getKey(), getParent()->getKey(), widget.color().name().toUtf8().data());
|
||||
}
|
||||
|
||||
getParent()->getState()->update (*this);
|
||||
}
|
34
apps/opencs/model/prefs/coloursetting.hpp
Normal file
34
apps/opencs/model/prefs/coloursetting.hpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
#ifndef CSM_PREFS_COLOURSETTING_H
|
||||
#define CSM_PREFS_COLOURSETTING_H
|
||||
|
||||
#include "setting.hpp"
|
||||
|
||||
#include <QColor>
|
||||
|
||||
namespace CSMPrefs
|
||||
{
|
||||
class ColourSetting : public Setting
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
std::string mTooltip;
|
||||
QColor mDefault;
|
||||
|
||||
public:
|
||||
|
||||
ColourSetting (Category *parent, Settings::Manager *values,
|
||||
QMutex *mutex, const std::string& key, const std::string& label,
|
||||
QColor default_);
|
||||
|
||||
ColourSetting& setTooltip (const std::string& tooltip);
|
||||
|
||||
/// Return label, input widget.
|
||||
virtual std::pair<QWidget *, QWidget *> makeWidgets (QWidget *parent);
|
||||
|
||||
private slots:
|
||||
|
||||
void valueChanged();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
75
apps/opencs/model/prefs/doublesetting.cpp
Normal file
75
apps/opencs/model/prefs/doublesetting.cpp
Normal file
|
@ -0,0 +1,75 @@
|
|||
|
||||
#include "doublesetting.hpp"
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <QLabel>
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QMutexLocker>
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "category.hpp"
|
||||
#include "state.hpp"
|
||||
|
||||
CSMPrefs::DoubleSetting::DoubleSetting (Category *parent, Settings::Manager *values,
|
||||
QMutex *mutex, const std::string& key, const std::string& label, double default_)
|
||||
: Setting (parent, values, mutex, key, label),
|
||||
mMin (0), mMax (std::numeric_limits<double>::max()),
|
||||
mDefault (default_)
|
||||
{}
|
||||
|
||||
CSMPrefs::DoubleSetting& CSMPrefs::DoubleSetting::setRange (double min, double max)
|
||||
{
|
||||
mMin = min;
|
||||
mMax = max;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CSMPrefs::DoubleSetting& CSMPrefs::DoubleSetting::setMin (double min)
|
||||
{
|
||||
mMin = min;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CSMPrefs::DoubleSetting& CSMPrefs::DoubleSetting::setMax (double max)
|
||||
{
|
||||
mMax = max;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CSMPrefs::DoubleSetting& CSMPrefs::DoubleSetting::setTooltip (const std::string& tooltip)
|
||||
{
|
||||
mTooltip = tooltip;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::pair<QWidget *, QWidget *> CSMPrefs::DoubleSetting::makeWidgets (QWidget *parent)
|
||||
{
|
||||
QLabel *label = new QLabel (QString::fromUtf8 (getLabel().c_str()), parent);
|
||||
|
||||
QDoubleSpinBox *widget = new QDoubleSpinBox (parent);
|
||||
widget->setRange (mMin, mMax);
|
||||
widget->setValue (mDefault);
|
||||
|
||||
if (!mTooltip.empty())
|
||||
{
|
||||
QString tooltip = QString::fromUtf8 (mTooltip.c_str());
|
||||
label->setToolTip (tooltip);
|
||||
widget->setToolTip (tooltip);
|
||||
}
|
||||
|
||||
connect (widget, SIGNAL (valueChanged (double)), this, SLOT (valueChanged (double)));
|
||||
|
||||
return std::make_pair (label, widget);
|
||||
}
|
||||
|
||||
void CSMPrefs::DoubleSetting::valueChanged (double value)
|
||||
{
|
||||
{
|
||||
QMutexLocker lock (getMutex());
|
||||
getValues().setFloat (getKey(), getParent()->getKey(), value);
|
||||
}
|
||||
|
||||
getParent()->getState()->update (*this);
|
||||
}
|
41
apps/opencs/model/prefs/doublesetting.hpp
Normal file
41
apps/opencs/model/prefs/doublesetting.hpp
Normal file
|
@ -0,0 +1,41 @@
|
|||
#ifndef CSM_PREFS_DOUBLESETTING_H
|
||||
#define CSM_PREFS_DOUBLESETTING_H
|
||||
|
||||
#include "setting.hpp"
|
||||
|
||||
namespace CSMPrefs
|
||||
{
|
||||
class DoubleSetting : public Setting
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
double mMin;
|
||||
double mMax;
|
||||
std::string mTooltip;
|
||||
double mDefault;
|
||||
|
||||
public:
|
||||
|
||||
DoubleSetting (Category *parent, Settings::Manager *values,
|
||||
QMutex *mutex, const std::string& key, const std::string& label,
|
||||
double default_);
|
||||
|
||||
// defaults to [0, std::numeric_limits<double>::max()]
|
||||
DoubleSetting& setRange (double min, double max);
|
||||
|
||||
DoubleSetting& setMin (double min);
|
||||
|
||||
DoubleSetting& setMax (double max);
|
||||
|
||||
DoubleSetting& setTooltip (const std::string& tooltip);
|
||||
|
||||
/// Return label, input widget.
|
||||
virtual std::pair<QWidget *, QWidget *> makeWidgets (QWidget *parent);
|
||||
|
||||
private slots:
|
||||
|
||||
void valueChanged (double value);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
112
apps/opencs/model/prefs/enumsetting.cpp
Normal file
112
apps/opencs/model/prefs/enumsetting.cpp
Normal file
|
@ -0,0 +1,112 @@
|
|||
|
||||
#include "enumsetting.hpp"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QComboBox>
|
||||
#include <QMutexLocker>
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "category.hpp"
|
||||
#include "state.hpp"
|
||||
|
||||
|
||||
CSMPrefs::EnumValue::EnumValue (const std::string& value, const std::string& tooltip)
|
||||
: mValue (value), mTooltip (tooltip)
|
||||
{}
|
||||
|
||||
CSMPrefs::EnumValue::EnumValue (const char *value)
|
||||
: mValue (value)
|
||||
{}
|
||||
|
||||
|
||||
CSMPrefs::EnumValues& CSMPrefs::EnumValues::add (const EnumValues& values)
|
||||
{
|
||||
mValues.insert (mValues.end(), values.mValues.begin(), values.mValues.end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
CSMPrefs::EnumValues& CSMPrefs::EnumValues::add (const EnumValue& value)
|
||||
{
|
||||
mValues.push_back (value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CSMPrefs::EnumValues& CSMPrefs::EnumValues::add (const std::string& value, const std::string& tooltip)
|
||||
{
|
||||
mValues.push_back (EnumValue (value, tooltip));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
CSMPrefs::EnumSetting::EnumSetting (Category *parent, Settings::Manager *values,
|
||||
QMutex *mutex, const std::string& key, const std::string& label, const EnumValue& default_)
|
||||
: Setting (parent, values, mutex, key, label), mDefault (default_)
|
||||
{}
|
||||
|
||||
CSMPrefs::EnumSetting& CSMPrefs::EnumSetting::setTooltip (const std::string& tooltip)
|
||||
{
|
||||
mTooltip = tooltip;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CSMPrefs::EnumSetting& CSMPrefs::EnumSetting::addValues (const EnumValues& values)
|
||||
{
|
||||
mValues.add (values);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CSMPrefs::EnumSetting& CSMPrefs::EnumSetting::addValue (const EnumValue& value)
|
||||
{
|
||||
mValues.add (value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CSMPrefs::EnumSetting& CSMPrefs::EnumSetting::addValue (const std::string& value, const std::string& tooltip)
|
||||
{
|
||||
mValues.add (value, tooltip);
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::pair<QWidget *, QWidget *> CSMPrefs::EnumSetting::makeWidgets (QWidget *parent)
|
||||
{
|
||||
QLabel *label = new QLabel (QString::fromUtf8 (getLabel().c_str()), parent);
|
||||
|
||||
QComboBox *widget = new QComboBox (parent);
|
||||
|
||||
int index = 0;
|
||||
|
||||
for (int i=0; i<static_cast<int> (mValues.mValues.size()); ++i)
|
||||
{
|
||||
if (mDefault.mValue==mValues.mValues[i].mValue)
|
||||
index = i;
|
||||
|
||||
widget->addItem (QString::fromUtf8 (mValues.mValues[i].mValue.c_str()));
|
||||
|
||||
if (!mValues.mValues[i].mTooltip.empty())
|
||||
widget->setItemData (i, QString::fromUtf8 (mValues.mValues[i].mTooltip.c_str()),
|
||||
Qt::ToolTipRole);
|
||||
}
|
||||
|
||||
widget->setCurrentIndex (index);
|
||||
|
||||
if (!mTooltip.empty())
|
||||
{
|
||||
QString tooltip = QString::fromUtf8 (mTooltip.c_str());
|
||||
label->setToolTip (tooltip);
|
||||
}
|
||||
|
||||
connect (widget, SIGNAL (currentIndexChanged (int)), this, SLOT (valueChanged (int)));
|
||||
|
||||
return std::make_pair (label, widget);
|
||||
}
|
||||
|
||||
void CSMPrefs::EnumSetting::valueChanged (int value)
|
||||
{
|
||||
{
|
||||
QMutexLocker lock (getMutex());
|
||||
getValues().setString (getKey(), getParent()->getKey(), mValues.mValues.at (value).mValue);
|
||||
}
|
||||
|
||||
getParent()->getState()->update (*this);
|
||||
}
|
62
apps/opencs/model/prefs/enumsetting.hpp
Normal file
62
apps/opencs/model/prefs/enumsetting.hpp
Normal file
|
@ -0,0 +1,62 @@
|
|||
#ifndef CSM_PREFS_ENUMSETTING_H
|
||||
#define CSM_PREFS_ENUMSETTING_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "setting.hpp"
|
||||
|
||||
namespace CSMPrefs
|
||||
{
|
||||
struct EnumValue
|
||||
{
|
||||
std::string mValue;
|
||||
std::string mTooltip;
|
||||
|
||||
EnumValue (const std::string& value, const std::string& tooltip = "");
|
||||
|
||||
EnumValue (const char *value);
|
||||
};
|
||||
|
||||
struct EnumValues
|
||||
{
|
||||
std::vector<EnumValue> mValues;
|
||||
|
||||
EnumValues& add (const EnumValues& values);
|
||||
|
||||
EnumValues& add (const EnumValue& value);
|
||||
|
||||
EnumValues& add (const std::string& value, const std::string& tooltip);
|
||||
};
|
||||
|
||||
class EnumSetting : public Setting
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
std::string mTooltip;
|
||||
EnumValue mDefault;
|
||||
EnumValues mValues;
|
||||
|
||||
public:
|
||||
|
||||
EnumSetting (Category *parent, Settings::Manager *values,
|
||||
QMutex *mutex, const std::string& key, const std::string& label,
|
||||
const EnumValue& default_);
|
||||
|
||||
EnumSetting& setTooltip (const std::string& tooltip);
|
||||
|
||||
EnumSetting& addValues (const EnumValues& values);
|
||||
|
||||
EnumSetting& addValue (const EnumValue& value);
|
||||
|
||||
EnumSetting& addValue (const std::string& value, const std::string& tooltip);
|
||||
|
||||
/// Return label, input widget.
|
||||
virtual std::pair<QWidget *, QWidget *> makeWidgets (QWidget *parent);
|
||||
|
||||
private slots:
|
||||
|
||||
void valueChanged (int value);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
74
apps/opencs/model/prefs/intsetting.cpp
Normal file
74
apps/opencs/model/prefs/intsetting.cpp
Normal file
|
@ -0,0 +1,74 @@
|
|||
|
||||
#include "intsetting.hpp"
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <QLabel>
|
||||
#include <QSpinBox>
|
||||
#include <QMutexLocker>
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "category.hpp"
|
||||
#include "state.hpp"
|
||||
|
||||
CSMPrefs::IntSetting::IntSetting (Category *parent, Settings::Manager *values,
|
||||
QMutex *mutex, const std::string& key, const std::string& label, int default_)
|
||||
: Setting (parent, values, mutex, key, label), mMin (0), mMax (std::numeric_limits<int>::max()),
|
||||
mDefault (default_)
|
||||
{}
|
||||
|
||||
CSMPrefs::IntSetting& CSMPrefs::IntSetting::setRange (int min, int max)
|
||||
{
|
||||
mMin = min;
|
||||
mMax = max;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CSMPrefs::IntSetting& CSMPrefs::IntSetting::setMin (int min)
|
||||
{
|
||||
mMin = min;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CSMPrefs::IntSetting& CSMPrefs::IntSetting::setMax (int max)
|
||||
{
|
||||
mMax = max;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CSMPrefs::IntSetting& CSMPrefs::IntSetting::setTooltip (const std::string& tooltip)
|
||||
{
|
||||
mTooltip = tooltip;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::pair<QWidget *, QWidget *> CSMPrefs::IntSetting::makeWidgets (QWidget *parent)
|
||||
{
|
||||
QLabel *label = new QLabel (QString::fromUtf8 (getLabel().c_str()), parent);
|
||||
|
||||
QSpinBox *widget = new QSpinBox (parent);
|
||||
widget->setRange (mMin, mMax);
|
||||
widget->setValue (mDefault);
|
||||
|
||||
if (!mTooltip.empty())
|
||||
{
|
||||
QString tooltip = QString::fromUtf8 (mTooltip.c_str());
|
||||
label->setToolTip (tooltip);
|
||||
widget->setToolTip (tooltip);
|
||||
}
|
||||
|
||||
connect (widget, SIGNAL (valueChanged (int)), this, SLOT (valueChanged (int)));
|
||||
|
||||
return std::make_pair (label, widget);
|
||||
}
|
||||
|
||||
void CSMPrefs::IntSetting::valueChanged (int value)
|
||||
{
|
||||
{
|
||||
QMutexLocker lock (getMutex());
|
||||
getValues().setInt (getKey(), getParent()->getKey(), value);
|
||||
}
|
||||
|
||||
getParent()->getState()->update (*this);
|
||||
}
|
40
apps/opencs/model/prefs/intsetting.hpp
Normal file
40
apps/opencs/model/prefs/intsetting.hpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
#ifndef CSM_PREFS_INTSETTING_H
|
||||
#define CSM_PREFS_INTSETTING_H
|
||||
|
||||
#include "setting.hpp"
|
||||
|
||||
namespace CSMPrefs
|
||||
{
|
||||
class IntSetting : public Setting
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
int mMin;
|
||||
int mMax;
|
||||
std::string mTooltip;
|
||||
int mDefault;
|
||||
|
||||
public:
|
||||
|
||||
IntSetting (Category *parent, Settings::Manager *values,
|
||||
QMutex *mutex, const std::string& key, const std::string& label, int default_);
|
||||
|
||||
// defaults to [0, std::numeric_limits<int>::max()]
|
||||
IntSetting& setRange (int min, int max);
|
||||
|
||||
IntSetting& setMin (int min);
|
||||
|
||||
IntSetting& setMax (int max);
|
||||
|
||||
IntSetting& setTooltip (const std::string& tooltip);
|
||||
|
||||
/// Return label, input widget.
|
||||
virtual std::pair<QWidget *, QWidget *> makeWidgets (QWidget *parent);
|
||||
|
||||
private slots:
|
||||
|
||||
void valueChanged (int value);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
97
apps/opencs/model/prefs/setting.cpp
Normal file
97
apps/opencs/model/prefs/setting.cpp
Normal file
|
@ -0,0 +1,97 @@
|
|||
|
||||
#include "setting.hpp"
|
||||
|
||||
#include <QColor>
|
||||
#include <QMutexLocker>
|
||||
|
||||
#include "category.hpp"
|
||||
#include "state.hpp"
|
||||
|
||||
Settings::Manager& CSMPrefs::Setting::getValues()
|
||||
{
|
||||
return *mValues;
|
||||
}
|
||||
|
||||
QMutex *CSMPrefs::Setting::getMutex()
|
||||
{
|
||||
return mMutex;
|
||||
}
|
||||
|
||||
CSMPrefs::Setting::Setting (Category *parent, Settings::Manager *values, QMutex *mutex,
|
||||
const std::string& key, const std::string& label)
|
||||
: QObject (parent->getState()), mParent (parent), mValues (values), mMutex (mutex), mKey (key),
|
||||
mLabel (label)
|
||||
{}
|
||||
|
||||
CSMPrefs::Setting:: ~Setting() {}
|
||||
|
||||
std::pair<QWidget *, QWidget *> CSMPrefs::Setting::makeWidgets (QWidget *parent)
|
||||
{
|
||||
return std::pair<QWidget *, QWidget *> (0, 0);
|
||||
}
|
||||
|
||||
const CSMPrefs::Category *CSMPrefs::Setting::getParent() const
|
||||
{
|
||||
return mParent;
|
||||
}
|
||||
|
||||
const std::string& CSMPrefs::Setting::getKey() const
|
||||
{
|
||||
return mKey;
|
||||
}
|
||||
|
||||
const std::string& CSMPrefs::Setting::getLabel() const
|
||||
{
|
||||
return mLabel;
|
||||
}
|
||||
|
||||
int CSMPrefs::Setting::toInt() const
|
||||
{
|
||||
QMutexLocker lock (mMutex);
|
||||
return mValues->getInt (mKey, mParent->getKey());
|
||||
}
|
||||
|
||||
double CSMPrefs::Setting::toDouble() const
|
||||
{
|
||||
QMutexLocker lock (mMutex);
|
||||
return mValues->getFloat (mKey, mParent->getKey());
|
||||
}
|
||||
|
||||
std::string CSMPrefs::Setting::toString() const
|
||||
{
|
||||
QMutexLocker lock (mMutex);
|
||||
return mValues->getString (mKey, mParent->getKey());
|
||||
}
|
||||
|
||||
bool CSMPrefs::Setting::isTrue() const
|
||||
{
|
||||
QMutexLocker lock (mMutex);
|
||||
return mValues->getBool (mKey, mParent->getKey());
|
||||
}
|
||||
|
||||
QColor CSMPrefs::Setting::toColor() const
|
||||
{
|
||||
// toString() handles lock
|
||||
return QColor (QString::fromUtf8 (toString().c_str()));
|
||||
}
|
||||
|
||||
bool CSMPrefs::operator== (const Setting& setting, const std::string& key)
|
||||
{
|
||||
std::string fullKey = setting.getParent()->getKey() + "/" + setting.getKey();
|
||||
return fullKey==key;
|
||||
}
|
||||
|
||||
bool CSMPrefs::operator== (const std::string& key, const Setting& setting)
|
||||
{
|
||||
return setting==key;
|
||||
}
|
||||
|
||||
bool CSMPrefs::operator!= (const Setting& setting, const std::string& key)
|
||||
{
|
||||
return !(setting==key);
|
||||
}
|
||||
|
||||
bool CSMPrefs::operator!= (const std::string& key, const Setting& setting)
|
||||
{
|
||||
return !(key==setting);
|
||||
}
|
74
apps/opencs/model/prefs/setting.hpp
Normal file
74
apps/opencs/model/prefs/setting.hpp
Normal file
|
@ -0,0 +1,74 @@
|
|||
#ifndef CSM_PREFS_SETTING_H
|
||||
#define CSM_PREFS_SETTING_H
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class QWidget;
|
||||
class QColor;
|
||||
class QMutex;
|
||||
|
||||
namespace Settings
|
||||
{
|
||||
class Manager;
|
||||
}
|
||||
|
||||
namespace CSMPrefs
|
||||
{
|
||||
class Category;
|
||||
|
||||
class Setting : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Category *mParent;
|
||||
Settings::Manager *mValues;
|
||||
QMutex *mMutex;
|
||||
std::string mKey;
|
||||
std::string mLabel;
|
||||
|
||||
protected:
|
||||
|
||||
Settings::Manager& getValues();
|
||||
|
||||
QMutex *getMutex();
|
||||
|
||||
public:
|
||||
|
||||
Setting (Category *parent, Settings::Manager *values, QMutex *mutex, const std::string& key, const std::string& label);
|
||||
|
||||
virtual ~Setting();
|
||||
|
||||
/// Return label, input widget.
|
||||
///
|
||||
/// \note first can be a 0-pointer, which means that the label is part of the input
|
||||
/// widget.
|
||||
virtual std::pair<QWidget *, QWidget *> makeWidgets (QWidget *parent);
|
||||
|
||||
const Category *getParent() const;
|
||||
|
||||
const std::string& getKey() const;
|
||||
|
||||
const std::string& getLabel() const;
|
||||
|
||||
int toInt() const;
|
||||
|
||||
double toDouble() const;
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
bool isTrue() const;
|
||||
|
||||
QColor toColor() const;
|
||||
};
|
||||
|
||||
// note: fullKeys have the format categoryKey/settingKey
|
||||
bool operator== (const Setting& setting, const std::string& fullKey);
|
||||
bool operator== (const std::string& fullKey, const Setting& setting);
|
||||
bool operator!= (const Setting& setting, const std::string& fullKey);
|
||||
bool operator!= (const std::string& fullKey, const Setting& setting);
|
||||
}
|
||||
|
||||
#endif
|
410
apps/opencs/model/prefs/state.cpp
Normal file
410
apps/opencs/model/prefs/state.cpp
Normal file
|
@ -0,0 +1,410 @@
|
|||
|
||||
#include "state.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
#include "intsetting.hpp"
|
||||
#include "doublesetting.hpp"
|
||||
#include "boolsetting.hpp"
|
||||
#include "coloursetting.hpp"
|
||||
|
||||
CSMPrefs::State *CSMPrefs::State::sThis = 0;
|
||||
|
||||
void CSMPrefs::State::load()
|
||||
{
|
||||
// default settings file
|
||||
boost::filesystem::path local = mConfigurationManager.getLocalPath() / mConfigFile;
|
||||
boost::filesystem::path global = mConfigurationManager.getGlobalPath() / mConfigFile;
|
||||
|
||||
if (boost::filesystem::exists (local))
|
||||
mSettings.loadDefault (local.string());
|
||||
else if (boost::filesystem::exists (global))
|
||||
mSettings.loadDefault (global.string());
|
||||
else
|
||||
throw std::runtime_error ("No default settings file found! Make sure the file \"openmw-cs.cfg\" was properly installed.");
|
||||
|
||||
// user settings file
|
||||
boost::filesystem::path user = mConfigurationManager.getUserConfigPath() / mConfigFile;
|
||||
|
||||
if (boost::filesystem::exists (user))
|
||||
mSettings.loadUser (user.string());
|
||||
}
|
||||
|
||||
void CSMPrefs::State::declare()
|
||||
{
|
||||
declareCategory ("Windows");
|
||||
declareInt ("default-width", "Default window width", 800).
|
||||
setTooltip ("Newly opened top-level windows will open with this width.").
|
||||
setMin (80);
|
||||
declareInt ("default-height", "Default window height", 600).
|
||||
setTooltip ("Newly opened top-level windows will open with this height.").
|
||||
setMin (80);
|
||||
declareBool ("show-statusbar", "Show Status Bar", true).
|
||||
setTooltip ("If a newly open top level window is showing status bars or not. "
|
||||
" Note that this does not affect existing windows.");
|
||||
declareSeparator();
|
||||
declareBool ("reuse", "Reuse Subviews", true).
|
||||
setTooltip ("When a new subview is requested and a matching subview already "
|
||||
" exist, do not open a new subview and use the existing one instead.");
|
||||
declareInt ("max-subviews", "Maximum number of subviews per top-level window", 256).
|
||||
setTooltip ("If the maximum number is reached and a new subview is opened "
|
||||
"it will be placed into a new top-level window.").
|
||||
setRange (1, 256);
|
||||
declareBool ("hide-subview", "Hide single subview", false).
|
||||
setTooltip ("When a view contains only a single subview, hide the subview title "
|
||||
"bar and if this subview is closed also close the view (unless it is the last "
|
||||
"view for this document)");
|
||||
declareInt ("minimum-width", "Minimum subview width", 325).
|
||||
setTooltip ("Minimum width of subviews.").
|
||||
setRange (50, 10000);
|
||||
declareSeparator();
|
||||
EnumValue scrollbarOnly ("Scrollbar Only", "Simple addition of scrollbars, the view window "
|
||||
"does not grow automatically.");
|
||||
declareEnum ("mainwindow-scrollbar", "Horizontal scrollbar mode for main window.", scrollbarOnly).
|
||||
addValue (scrollbarOnly).
|
||||
addValue ("Grow Only", "The view window grows as subviews are added. No scrollbars.").
|
||||
addValue ("Grow then Scroll", "The view window grows. The scrollbar appears once it cannot grow any further.");
|
||||
declareBool ("grow-limit", "Grow Limit Screen", false).
|
||||
setTooltip ("When \"Grow then Scroll\" option is selected, the window size grows to"
|
||||
" the width of the virtual desktop. \nIf this option is selected the the window growth"
|
||||
"is limited to the current screen.");
|
||||
|
||||
declareCategory ("Records");
|
||||
EnumValue iconAndText ("Icon and Text");
|
||||
EnumValues recordValues;
|
||||
recordValues.add (iconAndText).add ("Icon Only").add ("Text Only");
|
||||
declareEnum ("status-format", "Modification status display format", iconAndText).
|
||||
addValues (recordValues);
|
||||
declareEnum ("type-format", "ID type display format", iconAndText).
|
||||
addValues (recordValues);
|
||||
|
||||
declareCategory ("ID Tables");
|
||||
EnumValue inPlaceEdit ("Edit in Place", "Edit the clicked cell");
|
||||
EnumValue editRecord ("Edit Record", "Open a dialogue subview for the clicked record");
|
||||
EnumValue view ("View", "Open a scene subview for the clicked record (not available everywhere)");
|
||||
EnumValue editRecordAndClose ("Edit Record and Close");
|
||||
EnumValues doubleClickValues;
|
||||
doubleClickValues.add (inPlaceEdit).add (editRecord).add (view).add ("Revert").
|
||||
add ("Delete").add (editRecordAndClose).
|
||||
add ("View and Close", "Open a scene subview for the clicked record and close the table subview");
|
||||
declareEnum ("double", "Double Click", inPlaceEdit).addValues (doubleClickValues);
|
||||
declareEnum ("double-s", "Shift Double Click", editRecord).addValues (doubleClickValues);
|
||||
declareEnum ("double-c", "Control Double Click", view).addValues (doubleClickValues);
|
||||
declareEnum ("double-sc", "Shift Control Double Click", editRecordAndClose).addValues (doubleClickValues);
|
||||
declareSeparator();
|
||||
EnumValue jumpAndSelect ("Jump and Select", "Scroll new record into view and make it the selection");
|
||||
declareEnum ("jump-to-added", "Action on adding or cloning a record", jumpAndSelect).
|
||||
addValue (jumpAndSelect).
|
||||
addValue ("Jump Only", "Scroll new record into view").
|
||||
addValue ("No Jump", "No special action");
|
||||
declareBool ("extended-config",
|
||||
"Manually specify affected record types for an extended delete/revert", false).
|
||||
setTooltip ("Delete and revert commands have an extended form that also affects "
|
||||
"associated records.\n\n"
|
||||
"If this option is enabled, types of affected records are selected "
|
||||
"manually before a command execution.\nOtherwise, all associated "
|
||||
"records are deleted/reverted immediately.");
|
||||
|
||||
declareCategory ("ID Dialogues");
|
||||
declareBool ("toolbar", "Show toolbar", true);
|
||||
|
||||
declareCategory ("Reports");
|
||||
EnumValue actionNone ("None");
|
||||
EnumValue actionEdit ("Edit", "Open a table or dialogue suitable for addressing the listed report");
|
||||
EnumValue actionRemove ("Remove", "Remove the report from the report table");
|
||||
EnumValue actionEditAndRemove ("Edit And Remove", "Open a table or dialogue suitable for addressing the listed report, then remove the report from the report table");
|
||||
EnumValues reportValues;
|
||||
reportValues.add (actionNone).add (actionEdit).add (actionRemove).add (actionEditAndRemove);
|
||||
declareEnum ("double", "Double Click", actionEdit).addValues (reportValues);
|
||||
declareEnum ("double-s", "Shift Double Click", actionRemove).addValues (reportValues);
|
||||
declareEnum ("double-c", "Control Double Click", actionEditAndRemove).addValues (reportValues);
|
||||
declareEnum ("double-sc", "Shift Control Double Click", actionNone).addValues (reportValues);
|
||||
|
||||
declareCategory ("Search & Replace");
|
||||
declareInt ("char-before", "Characters before search string", 10).
|
||||
setTooltip ("Maximum number of character to display in search result before the searched text");
|
||||
declareInt ("char-after", "Characters after search string", 10).
|
||||
setTooltip ("Maximum number of character to display in search result after the searched text");
|
||||
declareBool ("auto-delete", "Delete row from result table after a successful replace", true);
|
||||
|
||||
declareCategory ("Scripts");
|
||||
declareBool ("show-linenum", "Show Line Numbers", true).
|
||||
setTooltip ("Show line numbers to the left of the script editor window."
|
||||
"The current row and column numbers of the text cursor are shown at the bottom.");
|
||||
declareBool ("mono-font", "Use monospace font", true);
|
||||
EnumValue warningsNormal ("Normal", "Report warnings as warning");
|
||||
declareEnum ("warnings", "Warning Mode", warningsNormal).
|
||||
addValue ("Ignore", "Do not report warning").
|
||||
addValue (warningsNormal).
|
||||
addValue ("Strcit", "Promote warning to an error");
|
||||
declareBool ("toolbar", "Show toolbar", true);
|
||||
declareInt ("compile-delay", "Delay between updating of source errors", 100).
|
||||
setTooltip ("Delay in milliseconds").
|
||||
setRange (0, 10000);
|
||||
declareInt ("error-height", "Initial height of the error panel", 100).
|
||||
setRange (100, 10000);
|
||||
declareSeparator();
|
||||
declareColour ("colour-int", "Highlight Colour: Integer Literals", QColor ("darkmagenta"));
|
||||
declareColour ("colour-float", "Highlight Colour: Float Literals", QColor ("magenta"));
|
||||
declareColour ("colour-name", "Highlight Colour: Names", QColor ("grey"));
|
||||
declareColour ("colour-keyword", "Highlight Colour: Keywords", QColor ("red"));
|
||||
declareColour ("colour-special", "Highlight Colour: Special Characters", QColor ("darkorange"));
|
||||
declareColour ("colour-comment", "Highlight Colour: Comments", QColor ("green"));
|
||||
declareColour ("colour-id", "Highlight Colour: IDs", QColor ("blue"));
|
||||
|
||||
declareCategory ("General Input");
|
||||
declareBool ("cycle", "Cyclic next/previous", false).
|
||||
setTooltip ("When using next/previous functions at the last/first item of a "
|
||||
"list go to the first/last item");
|
||||
|
||||
declareCategory ("3D Scene Input");
|
||||
EnumValue left ("Left Mouse-Button");
|
||||
EnumValue cLeft ("Ctrl-Left Mouse-Button");
|
||||
EnumValue right ("Right Mouse-Button");
|
||||
EnumValue cRight ("Ctrl-Right Mouse-Button");
|
||||
EnumValue middle ("Middle Mouse-Button");
|
||||
EnumValue cMiddle ("Ctrl-Middle Mouse-Button");
|
||||
EnumValues inputButtons;
|
||||
inputButtons.add (left).add (cLeft).add (right).add (cRight).add (middle).add (cMiddle);
|
||||
declareEnum ("p-navi", "Primary Camera Navigation Button", left).addValues (inputButtons);
|
||||
declareEnum ("s-navi", "Secondary Camera Navigation Button", cLeft).addValues (inputButtons);
|
||||
declareEnum ("p-edit", "Primary Editing Button", right).addValues (inputButtons);
|
||||
declareEnum ("s-edit", "Secondary Editing Button", cRight).addValues (inputButtons);
|
||||
declareEnum ("p-select", "Primary Selection Button", middle).addValues (inputButtons);
|
||||
declareEnum ("s-select", "Secondary Selection Button", cMiddle).addValues (inputButtons);
|
||||
declareSeparator();
|
||||
declareBool ("context-select", "Context Sensitive Selection", false);
|
||||
declareDouble ("drag-factor", "Mouse sensitivity during drag operations", 1.0).
|
||||
setRange (0.001, 100.0);
|
||||
declareDouble ("drag-wheel-factor", "Mouse wheel sensitivity during drag operations", 1.0).
|
||||
setRange (0.001, 100.0);
|
||||
declareDouble ("drag-shift-factor",
|
||||
"Shift-acceleration factor during drag operations", 4.0).
|
||||
setTooltip ("Acceleration factor during drag operations while holding down shift").
|
||||
setRange (0.001, 100.0);
|
||||
|
||||
declareCategory ("Tooltips");
|
||||
declareBool ("scene", "Show Tooltips in 3D scenes", true);
|
||||
declareBool ("scene-hide-basic", "Hide basic 3D scenes tooltips", false);
|
||||
declareInt ("scene-delay", "Tooltip delay in milliseconds", 500).
|
||||
setMin (1);
|
||||
|
||||
EnumValue createAndInsert ("Create cell and insert");
|
||||
EnumValue showAndInsert ("Show cell and insert");
|
||||
EnumValue dontInsert ("Discard");
|
||||
EnumValue insertAnyway ("Insert anyway");
|
||||
EnumValues insertOutsideCell;
|
||||
insertOutsideCell.add (createAndInsert).add (dontInsert).add (insertAnyway);
|
||||
EnumValues insertOutsideVisibleCell;
|
||||
insertOutsideVisibleCell.add (showAndInsert).add (dontInsert).add (insertAnyway);
|
||||
|
||||
declareCategory ("Scene Drops");
|
||||
declareInt ("distance", "Drop Distance", 50).
|
||||
setTooltip ("If an instance drop can not be placed against another object at the "
|
||||
"insert point, it will be placed by this distance from the insert point instead");
|
||||
declareEnum ("outside-drop", "Handling drops outside of cells", createAndInsert).
|
||||
addValues (insertOutsideCell);
|
||||
declareEnum ("outside-visible-drop", "Handling drops outside of visible cells", showAndInsert).
|
||||
addValues (insertOutsideVisibleCell);
|
||||
}
|
||||
|
||||
void CSMPrefs::State::declareCategory (const std::string& key)
|
||||
{
|
||||
std::map<std::string, Category>::iterator iter = mCategories.find (key);
|
||||
|
||||
if (iter!=mCategories.end())
|
||||
{
|
||||
mCurrentCategory = iter;
|
||||
}
|
||||
else
|
||||
{
|
||||
mCurrentCategory =
|
||||
mCategories.insert (std::make_pair (key, Category (this, key))).first;
|
||||
}
|
||||
}
|
||||
|
||||
CSMPrefs::IntSetting& CSMPrefs::State::declareInt (const std::string& key,
|
||||
const std::string& label, int default_)
|
||||
{
|
||||
if (mCurrentCategory==mCategories.end())
|
||||
throw std::logic_error ("no category for setting");
|
||||
|
||||
std::ostringstream stream;
|
||||
stream << default_;
|
||||
setDefault (key, stream.str());
|
||||
|
||||
default_ = mSettings.getInt (key, mCurrentCategory->second.getKey());
|
||||
|
||||
CSMPrefs::IntSetting *setting =
|
||||
new CSMPrefs::IntSetting (&mCurrentCategory->second, &mSettings, &mMutex, key, label,
|
||||
default_);
|
||||
|
||||
mCurrentCategory->second.addSetting (setting);
|
||||
|
||||
return *setting;
|
||||
}
|
||||
|
||||
CSMPrefs::DoubleSetting& CSMPrefs::State::declareDouble (const std::string& key,
|
||||
const std::string& label, double default_)
|
||||
{
|
||||
if (mCurrentCategory==mCategories.end())
|
||||
throw std::logic_error ("no category for setting");
|
||||
|
||||
std::ostringstream stream;
|
||||
stream << default_;
|
||||
setDefault (key, stream.str());
|
||||
|
||||
default_ = mSettings.getFloat (key, mCurrentCategory->second.getKey());
|
||||
|
||||
CSMPrefs::DoubleSetting *setting =
|
||||
new CSMPrefs::DoubleSetting (&mCurrentCategory->second, &mSettings, &mMutex,
|
||||
key, label, default_);
|
||||
|
||||
mCurrentCategory->second.addSetting (setting);
|
||||
|
||||
return *setting;
|
||||
}
|
||||
|
||||
CSMPrefs::BoolSetting& CSMPrefs::State::declareBool (const std::string& key,
|
||||
const std::string& label, bool default_)
|
||||
{
|
||||
if (mCurrentCategory==mCategories.end())
|
||||
throw std::logic_error ("no category for setting");
|
||||
|
||||
setDefault (key, default_ ? "true" : "false");
|
||||
|
||||
default_ = mSettings.getBool (key, mCurrentCategory->second.getKey());
|
||||
|
||||
CSMPrefs::BoolSetting *setting =
|
||||
new CSMPrefs::BoolSetting (&mCurrentCategory->second, &mSettings, &mMutex, key, label,
|
||||
default_);
|
||||
|
||||
mCurrentCategory->second.addSetting (setting);
|
||||
|
||||
return *setting;
|
||||
}
|
||||
|
||||
CSMPrefs::EnumSetting& CSMPrefs::State::declareEnum (const std::string& key,
|
||||
const std::string& label, EnumValue default_)
|
||||
{
|
||||
if (mCurrentCategory==mCategories.end())
|
||||
throw std::logic_error ("no category for setting");
|
||||
|
||||
setDefault (key, default_.mValue);
|
||||
|
||||
default_.mValue = mSettings.getString (key, mCurrentCategory->second.getKey());
|
||||
|
||||
CSMPrefs::EnumSetting *setting =
|
||||
new CSMPrefs::EnumSetting (&mCurrentCategory->second, &mSettings, &mMutex, key, label,
|
||||
default_);
|
||||
|
||||
mCurrentCategory->second.addSetting (setting);
|
||||
|
||||
return *setting;
|
||||
}
|
||||
|
||||
CSMPrefs::ColourSetting& CSMPrefs::State::declareColour (const std::string& key,
|
||||
const std::string& label, QColor default_)
|
||||
{
|
||||
if (mCurrentCategory==mCategories.end())
|
||||
throw std::logic_error ("no category for setting");
|
||||
|
||||
setDefault (key, default_.name().toUtf8().data());
|
||||
|
||||
default_.setNamedColor (QString::fromUtf8 (mSettings.getString (key, mCurrentCategory->second.getKey()).c_str()));
|
||||
|
||||
CSMPrefs::ColourSetting *setting =
|
||||
new CSMPrefs::ColourSetting (&mCurrentCategory->second, &mSettings, &mMutex, key, label,
|
||||
default_);
|
||||
|
||||
mCurrentCategory->second.addSetting (setting);
|
||||
|
||||
return *setting;
|
||||
}
|
||||
|
||||
void CSMPrefs::State::declareSeparator()
|
||||
{
|
||||
if (mCurrentCategory==mCategories.end())
|
||||
throw std::logic_error ("no category for setting");
|
||||
|
||||
CSMPrefs::Setting *setting =
|
||||
new CSMPrefs::Setting (&mCurrentCategory->second, &mSettings, &mMutex, "", "");
|
||||
|
||||
mCurrentCategory->second.addSetting (setting);
|
||||
}
|
||||
|
||||
void CSMPrefs::State::setDefault (const std::string& key, const std::string& default_)
|
||||
{
|
||||
Settings::CategorySetting fullKey (mCurrentCategory->second.getKey(), key);
|
||||
|
||||
Settings::CategorySettingValueMap::iterator iter =
|
||||
mSettings.mDefaultSettings.find (fullKey);
|
||||
|
||||
if (iter==mSettings.mDefaultSettings.end())
|
||||
mSettings.mDefaultSettings.insert (std::make_pair (fullKey, default_));
|
||||
}
|
||||
|
||||
CSMPrefs::State::State (const Files::ConfigurationManager& configurationManager)
|
||||
: mConfigFile ("openmw-cs.cfg"), mConfigurationManager (configurationManager),
|
||||
mCurrentCategory (mCategories.end())
|
||||
{
|
||||
if (sThis)
|
||||
throw std::logic_error ("An instance of CSMPRefs::State already exists");
|
||||
|
||||
load();
|
||||
declare();
|
||||
|
||||
sThis = this;
|
||||
}
|
||||
|
||||
CSMPrefs::State::~State()
|
||||
{
|
||||
sThis = 0;
|
||||
}
|
||||
|
||||
void CSMPrefs::State::save()
|
||||
{
|
||||
boost::filesystem::path user = mConfigurationManager.getUserConfigPath() / mConfigFile;
|
||||
mSettings.saveUser (user.string());
|
||||
}
|
||||
|
||||
CSMPrefs::State::Iterator CSMPrefs::State::begin()
|
||||
{
|
||||
return mCategories.begin();
|
||||
}
|
||||
|
||||
CSMPrefs::State::Iterator CSMPrefs::State::end()
|
||||
{
|
||||
return mCategories.end();
|
||||
}
|
||||
|
||||
CSMPrefs::Category& CSMPrefs::State::operator[] (const std::string& key)
|
||||
{
|
||||
Iterator iter = mCategories.find (key);
|
||||
|
||||
if (iter==mCategories.end())
|
||||
throw std::logic_error ("Invalid user settings category: " + key);
|
||||
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
void CSMPrefs::State::update (const Setting& setting)
|
||||
{
|
||||
emit (settingChanged (&setting));
|
||||
}
|
||||
|
||||
CSMPrefs::State& CSMPrefs::State::get()
|
||||
{
|
||||
if (!sThis)
|
||||
throw std::logic_error ("No instance of CSMPrefs::State");
|
||||
|
||||
return *sThis;
|
||||
}
|
||||
|
||||
|
||||
CSMPrefs::State& CSMPrefs::get()
|
||||
{
|
||||
return State::get();
|
||||
}
|
105
apps/opencs/model/prefs/state.hpp
Normal file
105
apps/opencs/model/prefs/state.hpp
Normal file
|
@ -0,0 +1,105 @@
|
|||
#ifndef CSV_PREFS_STATE_H
|
||||
#define CSM_PREFS_STATE_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <QObject>
|
||||
#include <QMutex>
|
||||
|
||||
#ifndef Q_MOC_RUN
|
||||
#include <components/files/configurationmanager.hpp>
|
||||
#endif
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "category.hpp"
|
||||
#include "setting.hpp"
|
||||
#include "enumsetting.hpp"
|
||||
|
||||
class QColor;
|
||||
|
||||
namespace CSMPrefs
|
||||
{
|
||||
class IntSetting;
|
||||
class DoubleSetting;
|
||||
class BoolSetting;
|
||||
class ColourSetting;
|
||||
|
||||
/// \brief User settings state
|
||||
///
|
||||
/// \note Access to the user settings is thread-safe once all declarations and loading has
|
||||
/// been completed.
|
||||
class State : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
static State *sThis;
|
||||
|
||||
public:
|
||||
|
||||
typedef std::map<std::string, Category> Collection;
|
||||
typedef Collection::iterator Iterator;
|
||||
|
||||
private:
|
||||
|
||||
const std::string mConfigFile;
|
||||
const Files::ConfigurationManager& mConfigurationManager;
|
||||
Settings::Manager mSettings;
|
||||
Collection mCategories;
|
||||
Iterator mCurrentCategory;
|
||||
QMutex mMutex;
|
||||
|
||||
// not implemented
|
||||
State (const State&);
|
||||
State& operator= (const State&);
|
||||
|
||||
private:
|
||||
|
||||
void load();
|
||||
|
||||
void declare();
|
||||
|
||||
void declareCategory (const std::string& key);
|
||||
|
||||
IntSetting& declareInt (const std::string& key, const std::string& label, int default_);
|
||||
DoubleSetting& declareDouble (const std::string& key, const std::string& label, double default_);
|
||||
|
||||
BoolSetting& declareBool (const std::string& key, const std::string& label, bool default_);
|
||||
|
||||
EnumSetting& declareEnum (const std::string& key, const std::string& label, EnumValue default_);
|
||||
|
||||
ColourSetting& declareColour (const std::string& key, const std::string& label, QColor default_);
|
||||
|
||||
void declareSeparator();
|
||||
|
||||
void setDefault (const std::string& key, const std::string& default_);
|
||||
|
||||
public:
|
||||
|
||||
State (const Files::ConfigurationManager& configurationManager);
|
||||
|
||||
~State();
|
||||
|
||||
void save();
|
||||
|
||||
Iterator begin();
|
||||
|
||||
Iterator end();
|
||||
|
||||
Category& operator[](const std::string& key);
|
||||
|
||||
void update (const Setting& setting);
|
||||
|
||||
static State& get();
|
||||
|
||||
signals:
|
||||
|
||||
void settingChanged (const CSMPrefs::Setting *setting);
|
||||
};
|
||||
|
||||
// convenience function
|
||||
State& get();
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,128 +0,0 @@
|
|||
#include "connector.hpp"
|
||||
#include "../../view/settings/view.hpp"
|
||||
#include "../../view/settings/page.hpp"
|
||||
|
||||
CSMSettings::Connector::Connector(CSVSettings::View *master,
|
||||
QObject *parent)
|
||||
: QObject(parent), mMasterView (master)
|
||||
{}
|
||||
|
||||
void CSMSettings::Connector::addSlaveView (CSVSettings::View *view,
|
||||
QList <QStringList> &masterProxyValues)
|
||||
{
|
||||
mSlaveViews.append (view);
|
||||
|
||||
mProxyListMap[view->viewKey()].append (masterProxyValues);
|
||||
}
|
||||
|
||||
QList <QStringList> CSMSettings::Connector::getSlaveViewValues() const
|
||||
{
|
||||
QList <QStringList> list;
|
||||
|
||||
foreach (const CSVSettings::View *view, mSlaveViews)
|
||||
list.append (view->selectedValues());
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
bool CSMSettings::Connector::proxyListsMatch (
|
||||
const QList <QStringList> &list1,
|
||||
const QList <QStringList> &list2) const
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
for (int i = 0; i < list1.size(); i++)
|
||||
{
|
||||
success = stringListsMatch (list1.at(i), list2.at(i));
|
||||
|
||||
if (!success)
|
||||
break;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void CSMSettings::Connector::slotUpdateMaster() const
|
||||
{
|
||||
//list of the current values for each slave.
|
||||
QList <QStringList> slaveValueList = getSlaveViewValues();
|
||||
|
||||
int masterColumn = -1;
|
||||
|
||||
/*
|
||||
* A row in the master view is one of the values in the
|
||||
* master view's data model. This corresponds directly to the number of
|
||||
* values in a proxy list contained in the ProxyListMap member.
|
||||
* Thus, we iterate each "column" in the master proxy list
|
||||
* (one for each vlaue in the master. Each column represents
|
||||
* one master value's corresponding list of slave values. We examine
|
||||
* each master value's list, comparing it to the current slave value list,
|
||||
* stopping when we find a match using proxyListsMatch().
|
||||
*
|
||||
* If no match is found, clear the master view's value
|
||||
*/
|
||||
|
||||
for (int i = 0; i < mMasterView->rowCount(); i++)
|
||||
{
|
||||
QList <QStringList> proxyValueList;
|
||||
|
||||
foreach (const QString &settingKey, mProxyListMap.keys())
|
||||
{
|
||||
// append the proxy value list stored in the i'th column
|
||||
// for each setting key. A setting key is the id of the setting
|
||||
// in page.name format.
|
||||
proxyValueList.append (mProxyListMap.value(settingKey).at(i));
|
||||
}
|
||||
|
||||
if (proxyListsMatch (slaveValueList, proxyValueList))
|
||||
{
|
||||
masterColumn = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QString masterValue = mMasterView->value (masterColumn);
|
||||
|
||||
mMasterView->setSelectedValue (masterValue);
|
||||
}
|
||||
|
||||
void CSMSettings::Connector::slotUpdateSlaves() const
|
||||
{
|
||||
int row = mMasterView->currentIndex();
|
||||
|
||||
if (row == -1)
|
||||
return;
|
||||
|
||||
//iterate the proxy lists for the chosen master index
|
||||
//and pass the list to each slave for updating
|
||||
for (int i = 0; i < mSlaveViews.size(); i++)
|
||||
{
|
||||
QList <QStringList> proxyList =
|
||||
mProxyListMap.value(mSlaveViews.at(i)->viewKey());
|
||||
|
||||
mSlaveViews.at(i)->setSelectedValues (proxyList.at(row));
|
||||
}
|
||||
}
|
||||
|
||||
bool CSMSettings::Connector::stringListsMatch (
|
||||
const QStringList &list1,
|
||||
const QStringList &list2) const
|
||||
{
|
||||
//returns a "sloppy" match, verifying that each list contains all the same
|
||||
//items, though not necessarily in the same order.
|
||||
|
||||
if (list1.size() != list2.size())
|
||||
return false;
|
||||
|
||||
QStringList tempList(list2);
|
||||
|
||||
//iterate each value in the list, removing one occurrence of the value in
|
||||
//the other list. If no corresponding value is found, test fails
|
||||
foreach (const QString &value, list1)
|
||||
{
|
||||
if (!tempList.contains(value))
|
||||
return false;
|
||||
|
||||
tempList.removeOne(value);
|
||||
}
|
||||
return true;
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
#ifndef CSMSETTINGS_CONNECTOR_HPP
|
||||
#define CSMSETTINGS_CONNECTOR_HPP
|
||||
|
||||
#include <QObject>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QStringList>
|
||||
|
||||
#include "support.hpp"
|
||||
|
||||
namespace CSVSettings {
|
||||
class View;
|
||||
}
|
||||
|
||||
namespace CSMSettings {
|
||||
|
||||
class Connector : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
CSVSettings::View *mMasterView;
|
||||
|
||||
///map using the view pointer as a key to it's index value
|
||||
QList <CSVSettings::View *> mSlaveViews;
|
||||
|
||||
///list of proxy values for each master value.
|
||||
///value list order is indexed to the master value index.
|
||||
QMap < QString, QList <QStringList> > mProxyListMap;
|
||||
|
||||
public:
|
||||
explicit Connector(CSVSettings::View *master,
|
||||
QObject *parent = 0);
|
||||
|
||||
///Set the view which acts as a proxy for other setting views
|
||||
void setMasterView (CSVSettings::View *view);
|
||||
|
||||
///Add a view to be updated / update to the master
|
||||
void addSlaveView (CSVSettings::View *view,
|
||||
QList <QStringList> &masterProxyValues);
|
||||
|
||||
private:
|
||||
|
||||
///loosely matches lists of proxy values across registered slaves
|
||||
///against a proxy value list for a given master value
|
||||
bool proxyListsMatch (const QList <QStringList> &list1,
|
||||
const QList <QStringList> &list2) const;
|
||||
|
||||
///loosely matches two string lists
|
||||
bool stringListsMatch (const QStringList &list1,
|
||||
const QStringList &list2) const;
|
||||
|
||||
///retrieves current values of registered slave views
|
||||
QList <QStringList> getSlaveViewValues() const;
|
||||
|
||||
public slots:
|
||||
|
||||
///updates slave views with proxy values associated with current
|
||||
///master value
|
||||
void slotUpdateSlaves() const;
|
||||
|
||||
///updates master value associated with the currently selected
|
||||
///slave values, if applicable.
|
||||
void slotUpdateMaster() const;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // CSMSETTINGS_CONNECTOR_HPP
|
|
@ -1,414 +0,0 @@
|
|||
#include "setting.hpp"
|
||||
#include "support.hpp"
|
||||
|
||||
CSMSettings::Setting::Setting(SettingType typ, const QString &settingName,
|
||||
const QString &pageName, const QString& label)
|
||||
: mIsEditorSetting (true)
|
||||
{
|
||||
buildDefaultSetting();
|
||||
|
||||
int settingType = static_cast <int> (typ);
|
||||
|
||||
//even-numbered setting types are multi-valued
|
||||
if ((settingType % 2) == 0)
|
||||
setProperty (Property_IsMultiValue, QVariant(true).toString());
|
||||
|
||||
//view type is related to setting type by an order of magnitude
|
||||
setProperty (Property_SettingType, QVariant (settingType).toString());
|
||||
setProperty (Property_Page, pageName);
|
||||
setProperty (Property_Name, settingName);
|
||||
setProperty (Property_Label, label.isEmpty() ? settingName : label);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::buildDefaultSetting()
|
||||
{
|
||||
int arrLen = sizeof(sPropertyDefaults) / sizeof (*sPropertyDefaults);
|
||||
|
||||
for (int i = 0; i < arrLen; i++)
|
||||
{
|
||||
QStringList propertyList;
|
||||
|
||||
if (i <Property_DefaultValues)
|
||||
propertyList.append (sPropertyDefaults[i]);
|
||||
|
||||
mProperties.append (propertyList);
|
||||
}
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::addProxy (const Setting *setting,
|
||||
const QStringList &vals)
|
||||
{
|
||||
if (serializable())
|
||||
setSerializable (false);
|
||||
|
||||
QList <QStringList> list;
|
||||
|
||||
foreach (const QString &val, vals)
|
||||
list << (QStringList() << val);
|
||||
|
||||
mProxies [setting->page() + '/' + setting->name()] = list;
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::addProxy (const Setting *setting,
|
||||
const QList <QStringList> &list)
|
||||
{
|
||||
if (serializable())
|
||||
setProperty (Property_Serializable, false);
|
||||
|
||||
mProxies [setting->page() + '/' + setting->name()] = list;
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setColumnSpan (int value)
|
||||
{
|
||||
setProperty (Property_ColumnSpan, value);
|
||||
}
|
||||
|
||||
int CSMSettings::Setting::columnSpan() const
|
||||
{
|
||||
return property (Property_ColumnSpan).at(0).toInt();
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setDeclaredValues (QStringList list)
|
||||
{
|
||||
setProperty (Property_DeclaredValues, list);
|
||||
}
|
||||
|
||||
QStringList CSMSettings::Setting::declaredValues() const
|
||||
{
|
||||
return property (Property_DeclaredValues);
|
||||
}
|
||||
|
||||
QStringList CSMSettings::Setting::property (SettingProperty prop) const
|
||||
{
|
||||
if (prop >= mProperties.size())
|
||||
return QStringList();
|
||||
|
||||
return mProperties.at(prop);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setDefaultValue (int value)
|
||||
{
|
||||
setDefaultValues (QStringList() << QVariant (value).toString());
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setDefaultValue (double value)
|
||||
{
|
||||
setDefaultValues (QStringList() << QVariant (value).toString());
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setDefaultValue (const QString &value)
|
||||
{
|
||||
setDefaultValues (QStringList() << value);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setDefaultValues (const QStringList &values)
|
||||
{
|
||||
setProperty (Property_DefaultValues, values);
|
||||
}
|
||||
|
||||
QStringList CSMSettings::Setting::defaultValues() const
|
||||
{
|
||||
return property (Property_DefaultValues);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setDelimiter (const QString &value)
|
||||
{
|
||||
setProperty (Property_Delimiter, value);
|
||||
}
|
||||
|
||||
QString CSMSettings::Setting::delimiter() const
|
||||
{
|
||||
return property (Property_Delimiter).at(0);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setEditorSetting(bool state)
|
||||
{
|
||||
mIsEditorSetting = true;
|
||||
}
|
||||
|
||||
bool CSMSettings::Setting::isEditorSetting() const
|
||||
{
|
||||
return mIsEditorSetting;
|
||||
}
|
||||
void CSMSettings::Setting::setIsMultiLine (bool state)
|
||||
{
|
||||
setProperty (Property_IsMultiLine, state);
|
||||
}
|
||||
|
||||
bool CSMSettings::Setting::isMultiLine() const
|
||||
{
|
||||
return (property (Property_IsMultiLine).at(0) == "true");
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setIsMultiValue (bool state)
|
||||
{
|
||||
setProperty (Property_IsMultiValue, state);
|
||||
}
|
||||
|
||||
bool CSMSettings::Setting::isMultiValue() const
|
||||
{
|
||||
return (property (Property_IsMultiValue).at(0) == "true");
|
||||
}
|
||||
|
||||
const CSMSettings::ProxyValueMap &CSMSettings::Setting::proxyLists() const
|
||||
{
|
||||
return mProxies;
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setSerializable (bool state)
|
||||
{
|
||||
setProperty (Property_Serializable, state);
|
||||
}
|
||||
|
||||
bool CSMSettings::Setting::serializable() const
|
||||
{
|
||||
return (property (Property_Serializable).at(0) == "true");
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setSpecialValueText(const QString &text)
|
||||
{
|
||||
setProperty (Property_SpecialValueText, text);
|
||||
}
|
||||
|
||||
QString CSMSettings::Setting::specialValueText() const
|
||||
{
|
||||
return property (Property_SpecialValueText).at(0);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setName (const QString &value)
|
||||
{
|
||||
setProperty (Property_Name, value);
|
||||
}
|
||||
|
||||
QString CSMSettings::Setting::name() const
|
||||
{
|
||||
return property (Property_Name).at(0);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setPage (const QString &value)
|
||||
{
|
||||
setProperty (Property_Page, value);
|
||||
}
|
||||
|
||||
QString CSMSettings::Setting::page() const
|
||||
{
|
||||
return property (Property_Page).at(0);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setStyleSheet (const QString &value)
|
||||
{
|
||||
setProperty (Property_StyleSheet, value);
|
||||
}
|
||||
|
||||
QString CSMSettings::Setting::styleSheet() const
|
||||
{
|
||||
return property (Property_StyleSheet).at(0);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setPrefix (const QString &value)
|
||||
{
|
||||
setProperty (Property_Prefix, value);
|
||||
}
|
||||
|
||||
QString CSMSettings::Setting::prefix() const
|
||||
{
|
||||
return property (Property_Prefix).at(0);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setRowSpan (const int value)
|
||||
{
|
||||
setProperty (Property_RowSpan, value);
|
||||
}
|
||||
|
||||
int CSMSettings::Setting::rowSpan () const
|
||||
{
|
||||
return property (Property_RowSpan).at(0).toInt();
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setSingleStep (int value)
|
||||
{
|
||||
setProperty (Property_SingleStep, value);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setSingleStep (double value)
|
||||
{
|
||||
setProperty (Property_SingleStep, value);
|
||||
}
|
||||
|
||||
QString CSMSettings::Setting::singleStep() const
|
||||
{
|
||||
return property (Property_SingleStep).at(0);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setSuffix (const QString &value)
|
||||
{
|
||||
setProperty (Property_Suffix, value);
|
||||
}
|
||||
|
||||
QString CSMSettings::Setting::suffix() const
|
||||
{
|
||||
return property (Property_Suffix).at(0);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setTickInterval (int value)
|
||||
{
|
||||
setProperty (Property_TickInterval, value);
|
||||
}
|
||||
|
||||
int CSMSettings::Setting::tickInterval () const
|
||||
{
|
||||
return property (Property_TickInterval).at(0).toInt();
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setTicksAbove (bool state)
|
||||
{
|
||||
setProperty (Property_TicksAbove, state);
|
||||
}
|
||||
|
||||
bool CSMSettings::Setting::ticksAbove() const
|
||||
{
|
||||
return (property (Property_TicksAbove).at(0) == "true");
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setTicksBelow (bool state)
|
||||
{
|
||||
setProperty (Property_TicksBelow, state);
|
||||
}
|
||||
|
||||
bool CSMSettings::Setting::ticksBelow() const
|
||||
{
|
||||
return (property (Property_TicksBelow).at(0) == "true");
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setType (int settingType)
|
||||
{
|
||||
setProperty (Property_SettingType, settingType);
|
||||
}
|
||||
|
||||
CSMSettings::SettingType CSMSettings::Setting::type() const
|
||||
{
|
||||
return static_cast <CSMSettings::SettingType> ( property (
|
||||
Property_SettingType).at(0).toInt());
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setRange (int min, int max)
|
||||
{
|
||||
setProperty (Property_Minimum, min);
|
||||
setProperty (Property_Maximum, max);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setRange (double min, double max)
|
||||
{
|
||||
setProperty (Property_Minimum, min);
|
||||
setProperty (Property_Maximum, max);
|
||||
}
|
||||
|
||||
QString CSMSettings::Setting::maximum() const
|
||||
{
|
||||
return property (Property_Maximum).at(0);
|
||||
}
|
||||
|
||||
QString CSMSettings::Setting::minimum() const
|
||||
{
|
||||
return property (Property_Minimum).at(0);
|
||||
}
|
||||
|
||||
CSVSettings::ViewType CSMSettings::Setting::viewType() const
|
||||
{
|
||||
return static_cast <CSVSettings::ViewType> ( property (
|
||||
Property_SettingType).at(0).toInt() / 10);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setViewColumn (int value)
|
||||
{
|
||||
setProperty (Property_ViewColumn, value);
|
||||
}
|
||||
|
||||
int CSMSettings::Setting::viewColumn() const
|
||||
{
|
||||
return property (Property_ViewColumn).at(0).toInt();
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setViewLocation (int row, int column)
|
||||
{
|
||||
setViewRow (row);
|
||||
setViewColumn (column);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setViewRow (int value)
|
||||
{
|
||||
setProperty (Property_ViewRow, value);
|
||||
}
|
||||
|
||||
int CSMSettings::Setting::viewRow() const
|
||||
{
|
||||
return property (Property_ViewRow).at(0).toInt();
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setWidgetWidth (int value)
|
||||
{
|
||||
setProperty (Property_WidgetWidth, value);
|
||||
}
|
||||
|
||||
int CSMSettings::Setting::widgetWidth() const
|
||||
{
|
||||
return property (Property_WidgetWidth).at(0).toInt();
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setWrapping (bool state)
|
||||
{
|
||||
setProperty (Property_Wrapping, state);
|
||||
}
|
||||
|
||||
bool CSMSettings::Setting::wrapping() const
|
||||
{
|
||||
return (property (Property_Wrapping).at(0) == "true");
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setLabel (const QString& label)
|
||||
{
|
||||
setProperty (Property_Label, label);
|
||||
}
|
||||
|
||||
QString CSMSettings::Setting::getLabel() const
|
||||
{
|
||||
return property (Property_Label).at (0);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setToolTip (const QString& toolTip)
|
||||
{
|
||||
setProperty (Property_ToolTip, toolTip);
|
||||
}
|
||||
|
||||
QString CSMSettings::Setting::getToolTip() const
|
||||
{
|
||||
return property (Property_ToolTip).at (0);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setProperty (SettingProperty prop, bool value)
|
||||
{
|
||||
setProperty (prop, QStringList() << QVariant (value).toString());
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setProperty (SettingProperty prop, int value)
|
||||
{
|
||||
setProperty (prop, QStringList() << QVariant (value).toString());
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setProperty (SettingProperty prop, double value)
|
||||
{
|
||||
setProperty (prop, QStringList() << QVariant (value).toString());
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setProperty (SettingProperty prop,
|
||||
const QString &value)
|
||||
{
|
||||
setProperty (prop, QStringList() << value);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setProperty (SettingProperty prop,
|
||||
const QStringList &value)
|
||||
{
|
||||
if (prop < mProperties.size())
|
||||
mProperties.replace (prop, value);
|
||||
}
|
|
@ -1,159 +0,0 @@
|
|||
#ifndef CSMSETTINGS_SETTING_HPP
|
||||
#define CSMSETTINGS_SETTING_HPP
|
||||
|
||||
#include <QStringList>
|
||||
#include <QMap>
|
||||
#include "support.hpp"
|
||||
|
||||
namespace CSMSettings
|
||||
{
|
||||
//QString is the setting id in the form of "page/name"
|
||||
//QList is a list of stringlists of proxy values.
|
||||
//Order is important! Proxy stringlists are matched against
|
||||
//master values by their position in the QList.
|
||||
typedef QMap <QString, QList <QStringList> > ProxyValueMap;
|
||||
|
||||
///Setting class is the interface for the User Settings. It contains
|
||||
///a great deal of boiler plate to provide the core API functions, as
|
||||
///well as the property() functions which use enumeration to be iterable.
|
||||
///This makes the Setting class capable of being manipulated by script.
|
||||
///See CSMSettings::support.hpp for enumerations / string values.
|
||||
class Setting
|
||||
{
|
||||
QList <QStringList> mProperties;
|
||||
QStringList mDefaults;
|
||||
|
||||
bool mIsEditorSetting;
|
||||
|
||||
ProxyValueMap mProxies;
|
||||
|
||||
public:
|
||||
|
||||
Setting(SettingType typ, const QString &settingName,
|
||||
const QString &pageName, const QString& label = "");
|
||||
|
||||
void addProxy (const Setting *setting, const QStringList &vals);
|
||||
void addProxy (const Setting *setting, const QList <QStringList> &list);
|
||||
|
||||
const QList <QStringList> &properties() const { return mProperties; }
|
||||
const ProxyValueMap &proxies() const { return mProxies; }
|
||||
|
||||
void setColumnSpan (int value);
|
||||
int columnSpan() const;
|
||||
|
||||
void setDeclaredValues (QStringList list);
|
||||
QStringList declaredValues() const;
|
||||
|
||||
void setDefaultValue (int value);
|
||||
void setDefaultValue (double value);
|
||||
void setDefaultValue (const QString &value);
|
||||
|
||||
void setDefaultValues (const QStringList &values);
|
||||
QStringList defaultValues() const;
|
||||
|
||||
void setDelimiter (const QString &value);
|
||||
QString delimiter() const;
|
||||
|
||||
void setEditorSetting (bool state);
|
||||
bool isEditorSetting() const;
|
||||
|
||||
void setIsMultiLine (bool state);
|
||||
bool isMultiLine() const;
|
||||
|
||||
void setIsMultiValue (bool state);
|
||||
bool isMultiValue() const;
|
||||
|
||||
void setMask (const QString &value);
|
||||
QString mask() const;
|
||||
|
||||
void setRange (int min, int max);
|
||||
void setRange (double min, double max);
|
||||
|
||||
QString maximum() const;
|
||||
|
||||
QString minimum() const;
|
||||
|
||||
void setName (const QString &value);
|
||||
QString name() const;
|
||||
|
||||
void setPage (const QString &value);
|
||||
QString page() const;
|
||||
|
||||
void setStyleSheet (const QString &value);
|
||||
QString styleSheet() const;
|
||||
|
||||
void setPrefix (const QString &value);
|
||||
QString prefix() const;
|
||||
|
||||
void setRowSpan (const int value);
|
||||
int rowSpan() const;
|
||||
|
||||
const ProxyValueMap &proxyLists() const;
|
||||
|
||||
void setSerializable (bool state);
|
||||
bool serializable() const;
|
||||
|
||||
void setSpecialValueText (const QString &text);
|
||||
QString specialValueText() const;
|
||||
|
||||
void setSingleStep (int value);
|
||||
void setSingleStep (double value);
|
||||
QString singleStep() const;
|
||||
|
||||
void setSuffix (const QString &value);
|
||||
QString suffix() const;
|
||||
|
||||
void setTickInterval (int value);
|
||||
int tickInterval() const;
|
||||
|
||||
void setTicksAbove (bool state);
|
||||
bool ticksAbove() const;
|
||||
|
||||
void setTicksBelow (bool state);
|
||||
bool ticksBelow() const;
|
||||
|
||||
void setViewColumn (int value);
|
||||
int viewColumn() const;
|
||||
|
||||
void setViewLocation (int row = -1, int column = -1);
|
||||
|
||||
void setViewRow (int value);
|
||||
int viewRow() const;
|
||||
|
||||
void setType (int settingType);
|
||||
CSMSettings::SettingType type() const;
|
||||
|
||||
CSVSettings::ViewType viewType() const;
|
||||
|
||||
void setWrapping (bool state);
|
||||
bool wrapping() const;
|
||||
|
||||
void setWidgetWidth (int value);
|
||||
int widgetWidth() const;
|
||||
|
||||
/// This is the text the user gets to see.
|
||||
void setLabel (const QString& label);
|
||||
QString getLabel() const;
|
||||
|
||||
void setToolTip (const QString& toolTip);
|
||||
QString getToolTip() const;
|
||||
|
||||
///returns the specified property value
|
||||
QStringList property (SettingProperty prop) const;
|
||||
|
||||
///boilerplate code to convert setting values of common types
|
||||
void setProperty (SettingProperty prop, bool value);
|
||||
void setProperty (SettingProperty prop, int value);
|
||||
void setProperty (SettingProperty prop, double value);
|
||||
void setProperty (SettingProperty prop, const QString &value);
|
||||
void setProperty (SettingProperty prop, const QStringList &value);
|
||||
|
||||
void addProxy (Setting* setting,
|
||||
QMap <QString, QStringList> &proxyMap);
|
||||
|
||||
protected:
|
||||
void buildDefaultSetting();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // CSMSETTINGS_SETTING_HPP
|
|
@ -1,149 +0,0 @@
|
|||
#ifndef SETTING_SUPPORT_HPP
|
||||
#define SETTING_SUPPORT_HPP
|
||||
|
||||
#include <Qt>
|
||||
#include <QPair>
|
||||
#include <QList>
|
||||
#include <QVariant>
|
||||
#include <QStringList>
|
||||
|
||||
//Enums
|
||||
namespace CSMSettings
|
||||
{
|
||||
///Enumerated properties for scripting
|
||||
enum SettingProperty
|
||||
{
|
||||
Property_Name = 0,
|
||||
Property_Page = 1,
|
||||
Property_SettingType = 2,
|
||||
Property_IsMultiValue = 3,
|
||||
Property_IsMultiLine = 4,
|
||||
Property_WidgetWidth = 5,
|
||||
Property_ViewRow = 6,
|
||||
Property_ViewColumn = 7,
|
||||
Property_Delimiter = 8,
|
||||
Property_Serializable = 9,
|
||||
Property_ColumnSpan = 10,
|
||||
Property_RowSpan = 11,
|
||||
Property_Minimum = 12,
|
||||
Property_Maximum = 13,
|
||||
Property_SpecialValueText = 14,
|
||||
Property_Prefix = 15,
|
||||
Property_Suffix = 16,
|
||||
Property_SingleStep = 17,
|
||||
Property_Wrapping = 18,
|
||||
Property_TickInterval = 19,
|
||||
Property_TicksAbove = 20,
|
||||
Property_TicksBelow = 21,
|
||||
Property_StyleSheet = 22,
|
||||
Property_Label = 23,
|
||||
Property_ToolTip = 24,
|
||||
|
||||
//Stringlists should always be the last items
|
||||
Property_DefaultValues = 25,
|
||||
Property_DeclaredValues = 26,
|
||||
Property_DefinedValues = 27,
|
||||
Property_Proxies = 28
|
||||
};
|
||||
|
||||
///Basic setting widget types.
|
||||
enum SettingType
|
||||
{
|
||||
/*
|
||||
* 0 - 9 - Boolean widgets
|
||||
* 10-19 - List widgets
|
||||
* 21-29 - Range widgets
|
||||
* 31-39 - Text widgets
|
||||
*
|
||||
* Each range corresponds to a View_Type enum by a factor of 10.
|
||||
*
|
||||
* Even-numbered values are single-value widgets
|
||||
* Odd-numbered values are multi-valued widgets
|
||||
*/
|
||||
|
||||
Type_CheckBox = 0,
|
||||
Type_RadioButton = 1,
|
||||
Type_ListView = 10,
|
||||
Type_ComboBox = 11,
|
||||
Type_SpinBox = 21,
|
||||
Type_DoubleSpinBox = 23,
|
||||
Type_Slider = 25,
|
||||
Type_Dial = 27,
|
||||
Type_TextArea = 30,
|
||||
Type_LineEdit = 31,
|
||||
Type_Undefined = 40
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace CSVSettings
|
||||
{
|
||||
///Categorical view types which encompass the setting widget types
|
||||
enum ViewType
|
||||
{
|
||||
ViewType_Boolean = 0,
|
||||
ViewType_List = 1,
|
||||
ViewType_Range = 2,
|
||||
ViewType_Text = 3,
|
||||
ViewType_Undefined = 4
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
namespace CSMSettings
|
||||
{
|
||||
///used to construct default settings in the Setting class
|
||||
struct PropertyDefaultValues
|
||||
{
|
||||
int id;
|
||||
QString name;
|
||||
QVariant value;
|
||||
};
|
||||
|
||||
///strings which correspond to setting values. These strings represent
|
||||
///the script language keywords which would be used to declare setting
|
||||
///views for 3rd party addons
|
||||
const QString sPropertyNames[] =
|
||||
{
|
||||
"name", "page", "setting_type", "is_multi_value",
|
||||
"is_multi_line", "widget_width", "view_row", "view_column", "delimiter",
|
||||
"is_serializable","column_span", "row_span", "minimum", "maximum",
|
||||
"special_value_text", "prefix", "suffix", "single_step", "wrapping",
|
||||
"tick_interval", "ticks_above", "ticks_below", "stylesheet",
|
||||
"defaults", "declarations", "definitions", "proxies"
|
||||
};
|
||||
|
||||
///Default values for a setting. Used in setting creation.
|
||||
const QString sPropertyDefaults[] =
|
||||
{
|
||||
"", //name
|
||||
"", //page
|
||||
"40", //setting type
|
||||
"false", //multivalue
|
||||
"false", //multiline
|
||||
"7", //widget width
|
||||
"-1", //view row
|
||||
"-1", //view column
|
||||
",", //delimiter
|
||||
"true", //serialized
|
||||
"1", //column span
|
||||
"1", //row span
|
||||
"0", //value range
|
||||
"0", //value minimum
|
||||
"0", //value maximum
|
||||
"", //special text
|
||||
"", //prefix
|
||||
"", //suffix
|
||||
"false", //wrapping
|
||||
"1", //tick interval
|
||||
"false", //ticks above
|
||||
"true", //ticks below
|
||||
"", //StyleSheet
|
||||
"", //default values
|
||||
"", //declared values
|
||||
"", //defined values
|
||||
"" //proxy values
|
||||
};
|
||||
}
|
||||
|
||||
#endif // VIEW_SUPPORT_HPP
|
|
@ -1,801 +0,0 @@
|
|||
#include "usersettings.hpp"
|
||||
|
||||
#include <QSettings>
|
||||
#include <QFile>
|
||||
|
||||
#include <components/files/configurationmanager.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
#include <boost/version.hpp>
|
||||
|
||||
#include "setting.hpp"
|
||||
#include "support.hpp"
|
||||
#include <QTextCodec>
|
||||
#include <QDebug>
|
||||
|
||||
/**
|
||||
* Workaround for problems with whitespaces in paths in older versions of Boost library
|
||||
*/
|
||||
#if (BOOST_VERSION <= 104600)
|
||||
namespace boost
|
||||
{
|
||||
|
||||
template<>
|
||||
inline boost::filesystem::path lexical_cast<boost::filesystem::path, std::string>(const std::string& arg)
|
||||
{
|
||||
return boost::filesystem::path(arg);
|
||||
}
|
||||
|
||||
} /* namespace boost */
|
||||
#endif /* (BOOST_VERSION <= 104600) */
|
||||
|
||||
CSMSettings::UserSettings *CSMSettings::UserSettings::sUserSettingsInstance = 0;
|
||||
|
||||
CSMSettings::UserSettings::UserSettings (const Files::ConfigurationManager& configurationManager)
|
||||
: mCfgMgr (configurationManager)
|
||||
, mSettingDefinitions(NULL)
|
||||
{
|
||||
assert(!sUserSettingsInstance);
|
||||
sUserSettingsInstance = this;
|
||||
|
||||
buildSettingModelDefaults();
|
||||
}
|
||||
|
||||
void CSMSettings::UserSettings::buildSettingModelDefaults()
|
||||
{
|
||||
/*
|
||||
declareSection ("3d-render", "3D Rendering");
|
||||
{
|
||||
Setting *farClipDist = createSetting (Type_DoubleSpinBox, "far-clip-distance", "Far clipping distance");
|
||||
farClipDist->setDefaultValue (300000);
|
||||
farClipDist->setRange (0, 1000000);
|
||||
farClipDist->setToolTip ("The maximum distance objects are still rendered at.");
|
||||
|
||||
QString defaultValue = "None";
|
||||
Setting *antialiasing = createSetting (Type_ComboBox, "antialiasing", "Antialiasing");
|
||||
antialiasing->setDeclaredValues (QStringList()
|
||||
<< defaultValue << "MSAA 2" << "MSAA 4" << "MSAA 8" << "MSAA 16");
|
||||
antialiasing->setDefaultValue (defaultValue);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
declareSection ("scene-input", "Scene Input");
|
||||
{
|
||||
Setting *fastFactor = createSetting (Type_SpinBox, "fast-factor",
|
||||
"Fast movement factor");
|
||||
fastFactor->setDefaultValue (4);
|
||||
fastFactor->setRange (1, 100);
|
||||
fastFactor->setToolTip (
|
||||
"Factor by which movement is speed up while the shift key is held down.");
|
||||
}
|
||||
*/
|
||||
|
||||
declareSection ("window", "Window");
|
||||
{
|
||||
Setting *preDefined = createSetting (Type_ComboBox, "pre-defined",
|
||||
"Default window size");
|
||||
preDefined->setEditorSetting (false);
|
||||
preDefined->setDeclaredValues (
|
||||
QStringList() << "640 x 480" << "800 x 600" << "1024 x 768" << "1440 x 900");
|
||||
preDefined->setViewLocation (1, 1);
|
||||
preDefined->setColumnSpan (2);
|
||||
preDefined->setToolTip ("Newly opened top-level windows will open with this size "
|
||||
"(picked from a list of pre-defined values)");
|
||||
|
||||
Setting *width = createSetting (Type_LineEdit, "default-width",
|
||||
"Default window width");
|
||||
width->setDefaultValues (QStringList() << "1024");
|
||||
width->setViewLocation (2, 1);
|
||||
width->setColumnSpan (1);
|
||||
width->setToolTip ("Newly opened top-level windows will open with this width.");
|
||||
preDefined->addProxy (width, QStringList() << "640" << "800" << "1024" << "1440");
|
||||
|
||||
Setting *height = createSetting (Type_LineEdit, "default-height",
|
||||
"Default window height");
|
||||
height->setDefaultValues (QStringList() << "768");
|
||||
height->setViewLocation (2, 2);
|
||||
height->setColumnSpan (1);
|
||||
height->setToolTip ("Newly opened top-level windows will open with this height.");
|
||||
preDefined->addProxy (height, QStringList() << "480" << "600" << "768" << "900");
|
||||
|
||||
Setting *reuse = createSetting (Type_CheckBox, "reuse", "Reuse Subviews");
|
||||
reuse->setDefaultValue ("true");
|
||||
reuse->setToolTip ("When a new subview is requested and a matching subview already "
|
||||
" exist, do not open a new subview and use the existing one instead.");
|
||||
|
||||
Setting *statusBar = createSetting (Type_CheckBox, "show-statusbar", "Show Status Bar");
|
||||
statusBar->setDefaultValue ("true");
|
||||
statusBar->setToolTip ("If a newly open top level window is showing status bars or not. "
|
||||
" Note that this does not affect existing windows.");
|
||||
|
||||
Setting *maxSubView = createSetting (Type_SpinBox, "max-subviews",
|
||||
"Maximum number of subviews per top-level window");
|
||||
maxSubView->setDefaultValue (256);
|
||||
maxSubView->setRange (1, 256);
|
||||
maxSubView->setToolTip ("If the maximum number is reached and a new subview is opened "
|
||||
"it will be placed into a new top-level window.");
|
||||
|
||||
Setting *hide = createSetting (Type_CheckBox, "hide-subview", "Hide single subview");
|
||||
hide->setDefaultValue ("false");
|
||||
hide->setToolTip ("When a view contains only a single subview, hide the subview title "
|
||||
"bar and if this subview is closed also close the view (unless it is the last "
|
||||
"view for this document)");
|
||||
|
||||
Setting *minWidth = createSetting (Type_SpinBox, "minimum-width",
|
||||
"Minimum subview width");
|
||||
minWidth->setDefaultValue (325);
|
||||
minWidth->setRange (50, 10000);
|
||||
minWidth->setToolTip ("Minimum width of subviews.");
|
||||
|
||||
QString defaultScroll = "Scrollbar Only";
|
||||
QStringList scrollValues = QStringList() << defaultScroll << "Grow Only" << "Grow then Scroll";
|
||||
|
||||
Setting *mainwinScroll = createSetting (Type_RadioButton, "mainwindow-scrollbar",
|
||||
"Add a horizontal scrollbar to the main view window.");
|
||||
mainwinScroll->setDefaultValue (defaultScroll);
|
||||
mainwinScroll->setDeclaredValues (scrollValues);
|
||||
mainwinScroll->setToolTip ("Scrollbar Only: Simple addition of scrollbars, the view window does not grow"
|
||||
" automatically.\n"
|
||||
"Grow Only: Original Editor behaviour. The view window grows as subviews are added. No scrollbars.\n"
|
||||
"Grow then Scroll: The view window grows. The scrollbar appears once it cannot grow any further.");
|
||||
|
||||
Setting *grow = createSetting (Type_CheckBox, "grow-limit", "Grow Limit Screen");
|
||||
grow->setDefaultValue ("false");
|
||||
grow->setToolTip ("When \"Grow then Scroll\" option is selected, the window size grows to"
|
||||
" the width of the virtual desktop. \nIf this option is selected the the window growth"
|
||||
"is limited to the current screen.");
|
||||
}
|
||||
|
||||
declareSection ("records", "Records");
|
||||
{
|
||||
QString defaultValue = "Icon and Text";
|
||||
QStringList values = QStringList() << defaultValue << "Icon Only" << "Text Only";
|
||||
|
||||
Setting *rsd = createSetting (Type_RadioButton, "status-format",
|
||||
"Modification status display format");
|
||||
rsd->setDefaultValue (defaultValue);
|
||||
rsd->setDeclaredValues (values);
|
||||
|
||||
Setting *ritd = createSetting (Type_RadioButton, "type-format",
|
||||
"ID type display format");
|
||||
ritd->setDefaultValue (defaultValue);
|
||||
ritd->setDeclaredValues (values);
|
||||
}
|
||||
|
||||
declareSection ("table-input", "ID Tables");
|
||||
{
|
||||
QString inPlaceEdit ("Edit in Place");
|
||||
QString editRecord ("Edit Record");
|
||||
QString view ("View");
|
||||
QString editRecordAndClose ("Edit Record and Close");
|
||||
|
||||
QStringList values;
|
||||
values
|
||||
<< "None" << inPlaceEdit << editRecord << view << "Revert" << "Delete"
|
||||
<< editRecordAndClose << "View and Close";
|
||||
|
||||
QString toolTip = "<ul>"
|
||||
"<li>None</li>"
|
||||
"<li>Edit in Place: Edit the clicked cell</li>"
|
||||
"<li>Edit Record: Open a dialogue subview for the clicked record</li>"
|
||||
"<li>View: Open a scene subview for the clicked record (not available everywhere)</li>"
|
||||
"<li>Revert: Revert record</li>"
|
||||
"<li>Delete: Delete recordy</li>"
|
||||
"<li>Edit Record and Close: Open a dialogue subview for the clicked record and close the table subview</li>"
|
||||
"<li>View And Close: Open a scene subview for the clicked record and close the table subview</li>"
|
||||
"</ul>";
|
||||
|
||||
Setting *doubleClick = createSetting (Type_ComboBox, "double", "Double Click");
|
||||
doubleClick->setDeclaredValues (values);
|
||||
doubleClick->setDefaultValue (inPlaceEdit);
|
||||
doubleClick->setToolTip ("Action on double click in table:<p>" + toolTip);
|
||||
|
||||
Setting *shiftDoubleClick = createSetting (Type_ComboBox, "double-s",
|
||||
"Shift Double Click");
|
||||
shiftDoubleClick->setDeclaredValues (values);
|
||||
shiftDoubleClick->setDefaultValue (editRecord);
|
||||
shiftDoubleClick->setToolTip ("Action on shift double click in table:<p>" + toolTip);
|
||||
|
||||
Setting *ctrlDoubleClick = createSetting (Type_ComboBox, "double-c",
|
||||
"Control Double Click");
|
||||
ctrlDoubleClick->setDeclaredValues (values);
|
||||
ctrlDoubleClick->setDefaultValue (view);
|
||||
ctrlDoubleClick->setToolTip ("Action on control double click in table:<p>" + toolTip);
|
||||
|
||||
Setting *shiftCtrlDoubleClick = createSetting (Type_ComboBox, "double-sc",
|
||||
"Shift Control Double Click");
|
||||
shiftCtrlDoubleClick->setDeclaredValues (values);
|
||||
shiftCtrlDoubleClick->setDefaultValue (editRecordAndClose);
|
||||
shiftCtrlDoubleClick->setToolTip ("Action on shift control double click in table:<p>" + toolTip);
|
||||
|
||||
QString defaultValue = "Jump and Select";
|
||||
QStringList jumpValues = QStringList() << defaultValue << "Jump Only" << "No Jump";
|
||||
|
||||
Setting *jumpToAdded = createSetting (Type_RadioButton, "jump-to-added",
|
||||
"Jump to the added or cloned record.");
|
||||
jumpToAdded->setDefaultValue (defaultValue);
|
||||
jumpToAdded->setDeclaredValues (jumpValues);
|
||||
|
||||
Setting *extendedConfig = createSetting (Type_CheckBox, "extended-config",
|
||||
"Manually specify affected record types for an extended delete/revert");
|
||||
extendedConfig->setDefaultValue("false");
|
||||
extendedConfig->setToolTip("Delete and revert commands have an extended form that also affects "
|
||||
"associated records.\n\n"
|
||||
"If this option is enabled, types of affected records are selected "
|
||||
"manually before a command execution.\nOtherwise, all associated "
|
||||
"records are deleted/reverted immediately.");
|
||||
}
|
||||
|
||||
declareSection ("dialogues", "ID Dialogues");
|
||||
{
|
||||
Setting *toolbar = createSetting (Type_CheckBox, "toolbar", "Show toolbar");
|
||||
toolbar->setDefaultValue ("true");
|
||||
}
|
||||
|
||||
declareSection ("report-input", "Reports");
|
||||
{
|
||||
QString none ("None");
|
||||
QString edit ("Edit");
|
||||
QString remove ("Remove");
|
||||
QString editAndRemove ("Edit And Remove");
|
||||
|
||||
QStringList values;
|
||||
values << none << edit << remove << editAndRemove;
|
||||
|
||||
QString toolTip = "<ul>"
|
||||
"<li>None</li>"
|
||||
"<li>Edit: Open a table or dialogue suitable for addressing the listed report</li>"
|
||||
"<li>Remove: Remove the report from the report table</li>"
|
||||
"<li>Edit and Remove: Open a table or dialogue suitable for addressing the listed report, then remove the report from the report table</li>"
|
||||
"</ul>";
|
||||
|
||||
Setting *doubleClick = createSetting (Type_ComboBox, "double", "Double Click");
|
||||
doubleClick->setDeclaredValues (values);
|
||||
doubleClick->setDefaultValue (edit);
|
||||
doubleClick->setToolTip ("Action on double click in report table:<p>" + toolTip);
|
||||
|
||||
Setting *shiftDoubleClick = createSetting (Type_ComboBox, "double-s",
|
||||
"Shift Double Click");
|
||||
shiftDoubleClick->setDeclaredValues (values);
|
||||
shiftDoubleClick->setDefaultValue (remove);
|
||||
shiftDoubleClick->setToolTip ("Action on shift double click in report table:<p>" + toolTip);
|
||||
|
||||
Setting *ctrlDoubleClick = createSetting (Type_ComboBox, "double-c",
|
||||
"Control Double Click");
|
||||
ctrlDoubleClick->setDeclaredValues (values);
|
||||
ctrlDoubleClick->setDefaultValue (editAndRemove);
|
||||
ctrlDoubleClick->setToolTip ("Action on control double click in report table:<p>" + toolTip);
|
||||
|
||||
Setting *shiftCtrlDoubleClick = createSetting (Type_ComboBox, "double-sc",
|
||||
"Shift Control Double Click");
|
||||
shiftCtrlDoubleClick->setDeclaredValues (values);
|
||||
shiftCtrlDoubleClick->setDefaultValue (none);
|
||||
shiftCtrlDoubleClick->setToolTip ("Action on shift control double click in report table:<p>" + toolTip);
|
||||
}
|
||||
|
||||
declareSection ("search", "Search & Replace");
|
||||
{
|
||||
Setting *before = createSetting (Type_SpinBox, "char-before",
|
||||
"Characters before search string");
|
||||
before->setDefaultValue (10);
|
||||
before->setRange (0, 1000);
|
||||
before->setToolTip ("Maximum number of character to display in search result before the searched text");
|
||||
|
||||
Setting *after = createSetting (Type_SpinBox, "char-after",
|
||||
"Characters after search string");
|
||||
after->setDefaultValue (10);
|
||||
after->setRange (0, 1000);
|
||||
after->setToolTip ("Maximum number of character to display in search result after the searched text");
|
||||
|
||||
Setting *autoDelete = createSetting (Type_CheckBox, "auto-delete", "Delete row from result table after a successful replace");
|
||||
autoDelete->setDefaultValue ("true");
|
||||
}
|
||||
|
||||
declareSection ("script-editor", "Scripts");
|
||||
{
|
||||
Setting *lineNum = createSetting (Type_CheckBox, "show-linenum", "Show Line Numbers");
|
||||
lineNum->setDefaultValue ("true");
|
||||
lineNum->setToolTip ("Show line numbers to the left of the script editor window."
|
||||
"The current row and column numbers of the text cursor are shown at the bottom.");
|
||||
|
||||
Setting *monoFont = createSetting (Type_CheckBox, "mono-font", "Use monospace font");
|
||||
monoFont->setDefaultValue ("true");
|
||||
monoFont->setToolTip ("Whether to use monospaced fonts on script edit subview.");
|
||||
|
||||
QString tooltip =
|
||||
"\n#RGB (each of R, G, and B is a single hex digit)"
|
||||
"\n#RRGGBB"
|
||||
"\n#RRRGGGBBB"
|
||||
"\n#RRRRGGGGBBBB"
|
||||
"\nA name from the list of colors defined in the list of SVG color keyword names."
|
||||
"\nX11 color names may also work.";
|
||||
|
||||
QString modeNormal ("Normal");
|
||||
|
||||
QStringList modes;
|
||||
modes << "Ignore" << modeNormal << "Strict";
|
||||
|
||||
Setting *warnings = createSetting (Type_ComboBox, "warnings",
|
||||
"Warning Mode");
|
||||
warnings->setDeclaredValues (modes);
|
||||
warnings->setDefaultValue (modeNormal);
|
||||
warnings->setToolTip ("<ul>How to handle warning messages during compilation:<p>"
|
||||
"<li>Ignore: Do not report warning</li>"
|
||||
"<li>Normal: Report warning as a warning</li>"
|
||||
"<li>Strict: Promote warning to an error</li>"
|
||||
"</ul>");
|
||||
|
||||
Setting *toolbar = createSetting (Type_CheckBox, "toolbar", "Show toolbar");
|
||||
toolbar->setDefaultValue ("true");
|
||||
|
||||
Setting *delay = createSetting (Type_SpinBox, "compile-delay",
|
||||
"Delay between updating of source errors");
|
||||
delay->setDefaultValue (100);
|
||||
delay->setRange (0, 10000);
|
||||
delay->setToolTip ("Delay in milliseconds");
|
||||
|
||||
Setting *formatInt = createSetting (Type_LineEdit, "colour-int", "Highlight Colour: Int");
|
||||
formatInt->setDefaultValues (QStringList() << "Dark magenta");
|
||||
formatInt->setToolTip ("(Default: Green) Use one of the following formats:" + tooltip);
|
||||
|
||||
Setting *formatFloat = createSetting (Type_LineEdit, "colour-float", "Highlight Colour: Float");
|
||||
formatFloat->setDefaultValues (QStringList() << "Magenta");
|
||||
formatFloat->setToolTip ("(Default: Magenta) Use one of the following formats:" + tooltip);
|
||||
|
||||
Setting *formatName = createSetting (Type_LineEdit, "colour-name", "Highlight Colour: Name");
|
||||
formatName->setDefaultValues (QStringList() << "Gray");
|
||||
formatName->setToolTip ("(Default: Gray) Use one of the following formats:" + tooltip);
|
||||
|
||||
Setting *formatKeyword = createSetting (Type_LineEdit, "colour-keyword", "Highlight Colour: Keyword");
|
||||
formatKeyword->setDefaultValues (QStringList() << "Red");
|
||||
formatKeyword->setToolTip ("(Default: Red) Use one of the following formats:" + tooltip);
|
||||
|
||||
Setting *formatSpecial = createSetting (Type_LineEdit, "colour-special", "Highlight Colour: Special");
|
||||
formatSpecial->setDefaultValues (QStringList() << "Dark yellow");
|
||||
formatSpecial->setToolTip ("(Default: Dark yellow) Use one of the following formats:" + tooltip);
|
||||
|
||||
Setting *formatComment = createSetting (Type_LineEdit, "colour-comment", "Highlight Colour: Comment");
|
||||
formatComment->setDefaultValues (QStringList() << "Green");
|
||||
formatComment->setToolTip ("(Default: Green) Use one of the following formats:" + tooltip);
|
||||
|
||||
Setting *formatId = createSetting (Type_LineEdit, "colour-id", "Highlight Colour: Id");
|
||||
formatId->setDefaultValues (QStringList() << "Blue");
|
||||
formatId->setToolTip ("(Default: Blue) Use one of the following formats:" + tooltip);
|
||||
}
|
||||
|
||||
declareSection ("general-input", "General Input");
|
||||
{
|
||||
Setting *cycle = createSetting (Type_CheckBox, "cycle", "Cyclic next/previous");
|
||||
cycle->setDefaultValue ("false");
|
||||
cycle->setToolTip ("When using next/previous functions at the last/first item of a "
|
||||
"list go to the first/last item");
|
||||
}
|
||||
|
||||
declareSection ("scene-input", "3D Scene Input");
|
||||
{
|
||||
QString left ("Left Mouse-Button");
|
||||
QString cLeft ("Ctrl-Left Mouse-Button");
|
||||
QString right ("Right Mouse-Button");
|
||||
QString cRight ("Ctrl-Right Mouse-Button");
|
||||
QString middle ("Middle Mouse-Button");
|
||||
QString cMiddle ("Ctrl-Middle Mouse-Button");
|
||||
|
||||
QStringList values;
|
||||
values << left << cLeft << right << cRight << middle << cMiddle;
|
||||
|
||||
Setting *primaryNavigation = createSetting (Type_ComboBox, "p-navi", "Primary Camera Navigation Button");
|
||||
primaryNavigation->setDeclaredValues (values);
|
||||
primaryNavigation->setDefaultValue (left);
|
||||
|
||||
Setting *secondaryNavigation = createSetting (Type_ComboBox, "s-navi", "Secondary Camera Navigation Button");
|
||||
secondaryNavigation->setDeclaredValues (values);
|
||||
secondaryNavigation->setDefaultValue (cLeft);
|
||||
|
||||
Setting *primaryEditing = createSetting (Type_ComboBox, "p-edit", "Primary Editing Button");
|
||||
primaryEditing->setDeclaredValues (values);
|
||||
primaryEditing->setDefaultValue (right);
|
||||
|
||||
Setting *secondaryEditing = createSetting (Type_ComboBox, "s-edit", "Secondary Editing Button");
|
||||
secondaryEditing->setDeclaredValues (values);
|
||||
secondaryEditing->setDefaultValue (cRight);
|
||||
|
||||
Setting *selection = createSetting (Type_ComboBox, "select", "Selection Button");
|
||||
selection->setDeclaredValues (values);
|
||||
selection->setDefaultValue (middle);
|
||||
|
||||
Setting *contextSensitive = createSetting (Type_CheckBox, "context-select", "Context Sensitive Selection");
|
||||
contextSensitive->setDefaultValue ("false");
|
||||
|
||||
Setting *dragMouseSensitivity = createSetting (Type_DoubleSpinBox, "drag-factor",
|
||||
"Mouse sensitivity during drag operations");
|
||||
dragMouseSensitivity->setDefaultValue (1.0);
|
||||
dragMouseSensitivity->setRange (0.001, 100.0);
|
||||
|
||||
Setting *dragWheelSensitivity = createSetting (Type_DoubleSpinBox, "drag-wheel-factor",
|
||||
"Mouse wheel sensitivity during drag operations");
|
||||
dragWheelSensitivity->setDefaultValue (1.0);
|
||||
dragWheelSensitivity->setRange (0.001, 100.0);
|
||||
|
||||
Setting *dragShiftFactor = createSetting (Type_DoubleSpinBox, "drag-shift-factor",
|
||||
"Acceleration factor during drag operations while holding down shift");
|
||||
dragShiftFactor->setDefaultValue (4.0);
|
||||
dragShiftFactor->setRange (0.001, 100.0);
|
||||
}
|
||||
|
||||
{
|
||||
/******************************************************************
|
||||
* There are three types of values:
|
||||
*
|
||||
* Declared values
|
||||
*
|
||||
* Pre-determined values, typically for
|
||||
* combobox drop downs and boolean (radiobutton / checkbox) labels.
|
||||
* These values represent the total possible list of values that
|
||||
* may define a setting. No other values are allowed.
|
||||
*
|
||||
* Defined values
|
||||
*
|
||||
* Values which represent the actual, current value of
|
||||
* a setting. For settings with declared values, this must be one
|
||||
* or several declared values, as appropriate.
|
||||
*
|
||||
* Proxy values
|
||||
* Values the proxy master updates the proxy slave when
|
||||
* it's own definition is set / changed. These are definitions for
|
||||
* proxy slave settings, but must match any declared values the
|
||||
* proxy slave has, if any.
|
||||
*******************************************************************/
|
||||
/*
|
||||
//create setting objects, specifying the basic widget type,
|
||||
//the page name, and the view name
|
||||
|
||||
Setting *masterBoolean = createSetting (Type_RadioButton, section,
|
||||
"Master Proxy");
|
||||
|
||||
Setting *slaveBoolean = createSetting (Type_CheckBox, section,
|
||||
"Proxy Checkboxes");
|
||||
|
||||
Setting *slaveSingleText = createSetting (Type_LineEdit, section,
|
||||
"Proxy TextBox 1");
|
||||
|
||||
Setting *slaveMultiText = createSetting (Type_LineEdit, section,
|
||||
"ProxyTextBox 2");
|
||||
|
||||
Setting *slaveAlphaSpinbox = createSetting (Type_SpinBox, section,
|
||||
"Alpha Spinbox");
|
||||
|
||||
Setting *slaveIntegerSpinbox = createSetting (Type_SpinBox, section,
|
||||
"Int Spinbox");
|
||||
|
||||
Setting *slaveDoubleSpinbox = createSetting (Type_DoubleSpinBox,
|
||||
section, "Double Spinbox");
|
||||
|
||||
Setting *slaveSlider = createSetting (Type_Slider, section, "Slider");
|
||||
|
||||
Setting *slaveDial = createSetting (Type_Dial, section, "Dial");
|
||||
|
||||
//set declared values for selected views
|
||||
masterBoolean->setDeclaredValues (QStringList()
|
||||
<< "Profile One" << "Profile Two"
|
||||
<< "Profile Three" << "Profile Four");
|
||||
|
||||
slaveBoolean->setDeclaredValues (QStringList()
|
||||
<< "One" << "Two" << "Three" << "Four" << "Five");
|
||||
|
||||
slaveAlphaSpinbox->setDeclaredValues (QStringList()
|
||||
<< "One" << "Two" << "Three" << "Four");
|
||||
|
||||
|
||||
masterBoolean->addProxy (slaveBoolean, QList <QStringList>()
|
||||
<< (QStringList() << "One" << "Three")
|
||||
<< (QStringList() << "One" << "Three")
|
||||
<< (QStringList() << "One" << "Three" << "Five")
|
||||
<< (QStringList() << "Two" << "Four")
|
||||
);
|
||||
|
||||
masterBoolean->addProxy (slaveSingleText, QList <QStringList>()
|
||||
<< (QStringList() << "Text A")
|
||||
<< (QStringList() << "Text B")
|
||||
<< (QStringList() << "Text A")
|
||||
<< (QStringList() << "Text C")
|
||||
);
|
||||
|
||||
masterBoolean->addProxy (slaveMultiText, QList <QStringList>()
|
||||
<< (QStringList() << "One" << "Three")
|
||||
<< (QStringList() << "One" << "Three")
|
||||
<< (QStringList() << "One" << "Three" << "Five")
|
||||
<< (QStringList() << "Two" << "Four")
|
||||
);
|
||||
|
||||
masterBoolean->addProxy (slaveAlphaSpinbox, QList <QStringList>()
|
||||
<< (QStringList() << "Four")
|
||||
<< (QStringList() << "Three")
|
||||
<< (QStringList() << "Two")
|
||||
<< (QStringList() << "One"));
|
||||
|
||||
masterBoolean->addProxy (slaveIntegerSpinbox, QList <QStringList> ()
|
||||
<< (QStringList() << "0")
|
||||
<< (QStringList() << "7")
|
||||
<< (QStringList() << "14")
|
||||
<< (QStringList() << "21"));
|
||||
|
||||
masterBoolean->addProxy (slaveDoubleSpinbox, QList <QStringList> ()
|
||||
<< (QStringList() << "0.17")
|
||||
<< (QStringList() << "0.34")
|
||||
<< (QStringList() << "0.51")
|
||||
<< (QStringList() << "0.68"));
|
||||
|
||||
masterBoolean->addProxy (slaveSlider, QList <QStringList> ()
|
||||
<< (QStringList() << "25")
|
||||
<< (QStringList() << "50")
|
||||
<< (QStringList() << "75")
|
||||
<< (QStringList() << "100")
|
||||
);
|
||||
|
||||
masterBoolean->addProxy (slaveDial, QList <QStringList> ()
|
||||
<< (QStringList() << "25")
|
||||
<< (QStringList() << "50")
|
||||
<< (QStringList() << "75")
|
||||
<< (QStringList() << "100")
|
||||
);
|
||||
|
||||
//settings with proxies are not serialized by default
|
||||
//other settings non-serialized for demo purposes
|
||||
slaveBoolean->setSerializable (false);
|
||||
slaveSingleText->setSerializable (false);
|
||||
slaveMultiText->setSerializable (false);
|
||||
slaveAlphaSpinbox->setSerializable (false);
|
||||
slaveIntegerSpinbox->setSerializable (false);
|
||||
slaveDoubleSpinbox->setSerializable (false);
|
||||
slaveSlider->setSerializable (false);
|
||||
slaveDial->setSerializable (false);
|
||||
|
||||
slaveBoolean->setDefaultValues (QStringList()
|
||||
<< "One" << "Three" << "Five");
|
||||
|
||||
slaveSingleText->setDefaultValue ("Text A");
|
||||
|
||||
slaveMultiText->setDefaultValues (QStringList()
|
||||
<< "One" << "Three" << "Five");
|
||||
|
||||
slaveSingleText->setWidgetWidth (24);
|
||||
slaveMultiText->setWidgetWidth (24);
|
||||
|
||||
slaveAlphaSpinbox->setDefaultValue ("Two");
|
||||
slaveAlphaSpinbox->setWidgetWidth (20);
|
||||
//slaveAlphaSpinbox->setPrefix ("No. ");
|
||||
//slaveAlphaSpinbox->setSuffix ("!");
|
||||
slaveAlphaSpinbox->setWrapping (true);
|
||||
|
||||
slaveIntegerSpinbox->setDefaultValue (14);
|
||||
slaveIntegerSpinbox->setMinimum (0);
|
||||
slaveIntegerSpinbox->setMaximum (58);
|
||||
slaveIntegerSpinbox->setPrefix ("$");
|
||||
slaveIntegerSpinbox->setSuffix (".00");
|
||||
slaveIntegerSpinbox->setWidgetWidth (10);
|
||||
slaveIntegerSpinbox->setSpecialValueText ("Nothing!");
|
||||
|
||||
slaveDoubleSpinbox->setDefaultValue (0.51);
|
||||
slaveDoubleSpinbox->setSingleStep(0.17);
|
||||
slaveDoubleSpinbox->setMaximum(4.0);
|
||||
|
||||
slaveSlider->setMinimum (0);
|
||||
slaveSlider->setMaximum (100);
|
||||
slaveSlider->setDefaultValue (75);
|
||||
slaveSlider->setWidgetWidth (100);
|
||||
slaveSlider->setTicksAbove (true);
|
||||
slaveSlider->setTickInterval (25);
|
||||
|
||||
slaveDial->setMinimum (0);
|
||||
slaveDial->setMaximum (100);
|
||||
slaveDial->setSingleStep (5);
|
||||
slaveDial->setDefaultValue (75);
|
||||
slaveDial->setTickInterval (25);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
CSMSettings::UserSettings::~UserSettings()
|
||||
{
|
||||
sUserSettingsInstance = 0;
|
||||
}
|
||||
|
||||
void CSMSettings::UserSettings::loadSettings (const QString &fileName)
|
||||
{
|
||||
QString userFilePath = QString::fromUtf8
|
||||
(mCfgMgr.getUserConfigPath().string().c_str());
|
||||
|
||||
QString globalFilePath = QString::fromUtf8
|
||||
(mCfgMgr.getGlobalPath().string().c_str());
|
||||
|
||||
QString otherFilePath = globalFilePath;
|
||||
|
||||
//test for local only if global fails (uninstalled copy)
|
||||
if (!QFile (globalFilePath + fileName).exists())
|
||||
{
|
||||
//if global is invalid, use the local path
|
||||
otherFilePath = QString::fromUtf8
|
||||
(mCfgMgr.getLocalPath().string().c_str());
|
||||
}
|
||||
|
||||
QSettings::setPath
|
||||
(QSettings::IniFormat, QSettings::UserScope, userFilePath);
|
||||
|
||||
QSettings::setPath
|
||||
(QSettings::IniFormat, QSettings::SystemScope, otherFilePath);
|
||||
|
||||
mSettingDefinitions = new QSettings
|
||||
(QSettings::IniFormat, QSettings::UserScope, "opencs", QString(), this);
|
||||
}
|
||||
|
||||
// if the key is not found create one with a default value
|
||||
QString CSMSettings::UserSettings::setting(const QString &viewKey, const QString &value)
|
||||
{
|
||||
if(mSettingDefinitions->contains(viewKey))
|
||||
return settingValue(viewKey);
|
||||
else if(value != QString())
|
||||
{
|
||||
mSettingDefinitions->setValue (viewKey, QStringList() << value);
|
||||
return value;
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
bool CSMSettings::UserSettings::hasSettingDefinitions (const QString &viewKey) const
|
||||
{
|
||||
return (mSettingDefinitions->contains (viewKey));
|
||||
}
|
||||
|
||||
void CSMSettings::UserSettings::setDefinitions
|
||||
(const QString &key, const QStringList &list)
|
||||
{
|
||||
mSettingDefinitions->setValue (key, list);
|
||||
}
|
||||
|
||||
void CSMSettings::UserSettings::saveDefinitions() const
|
||||
{
|
||||
mSettingDefinitions->sync();
|
||||
}
|
||||
|
||||
QString CSMSettings::UserSettings::settingValue (const QString &settingKey)
|
||||
{
|
||||
QStringList defs;
|
||||
|
||||
if (!mSettingDefinitions->contains (settingKey))
|
||||
return QString();
|
||||
|
||||
defs = mSettingDefinitions->value (settingKey).toStringList();
|
||||
|
||||
if (defs.isEmpty())
|
||||
return QString();
|
||||
|
||||
return defs.at(0);
|
||||
}
|
||||
|
||||
CSMSettings::UserSettings& CSMSettings::UserSettings::instance()
|
||||
{
|
||||
assert(sUserSettingsInstance);
|
||||
return *sUserSettingsInstance;
|
||||
}
|
||||
|
||||
void CSMSettings::UserSettings::updateUserSetting(const QString &settingKey,
|
||||
const QStringList &list)
|
||||
{
|
||||
mSettingDefinitions->setValue (settingKey ,list);
|
||||
|
||||
emit userSettingUpdated (settingKey, list);
|
||||
}
|
||||
|
||||
CSMSettings::Setting *CSMSettings::UserSettings::findSetting
|
||||
(const QString &pageName, const QString &settingName)
|
||||
{
|
||||
foreach (Setting *setting, mSettings)
|
||||
{
|
||||
if (setting->name() == settingName)
|
||||
{
|
||||
if (setting->page() == pageName)
|
||||
return setting;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CSMSettings::UserSettings::removeSetting
|
||||
(const QString &pageName, const QString &settingName)
|
||||
{
|
||||
if (mSettings.isEmpty())
|
||||
return;
|
||||
|
||||
QList <Setting *>::iterator removeIterator = mSettings.begin();
|
||||
|
||||
while (removeIterator != mSettings.end())
|
||||
{
|
||||
if ((*removeIterator)->name() == settingName)
|
||||
{
|
||||
if ((*removeIterator)->page() == pageName)
|
||||
{
|
||||
mSettings.erase (removeIterator);
|
||||
break;
|
||||
}
|
||||
}
|
||||
removeIterator++;
|
||||
}
|
||||
}
|
||||
|
||||
CSMSettings::SettingPageMap CSMSettings::UserSettings::settingPageMap() const
|
||||
{
|
||||
SettingPageMap pageMap;
|
||||
|
||||
foreach (Setting *setting, mSettings)
|
||||
{
|
||||
SettingPageMap::iterator iter = pageMap.find (setting->page());
|
||||
|
||||
if (iter==pageMap.end())
|
||||
{
|
||||
QPair<QString, QList <Setting *> > value;
|
||||
|
||||
std::map<QString, QString>::const_iterator iter2 =
|
||||
mSectionLabels.find (setting->page());
|
||||
|
||||
value.first = iter2!=mSectionLabels.end() ? iter2->second : "";
|
||||
|
||||
iter = pageMap.insert (setting->page(), value);
|
||||
}
|
||||
|
||||
iter->second.append (setting);
|
||||
}
|
||||
|
||||
return pageMap;
|
||||
}
|
||||
|
||||
CSMSettings::Setting *CSMSettings::UserSettings::createSetting
|
||||
(CSMSettings::SettingType type, const QString &name, const QString& label)
|
||||
{
|
||||
Setting *setting = new Setting (type, name, mSection, label);
|
||||
|
||||
// set useful defaults
|
||||
int row = 1;
|
||||
|
||||
if (!mSettings.empty())
|
||||
row = mSettings.back()->viewRow()+1;
|
||||
|
||||
setting->setViewLocation (row, 1);
|
||||
|
||||
setting->setColumnSpan (3);
|
||||
|
||||
int width = 10;
|
||||
|
||||
if (type==Type_CheckBox)
|
||||
width = 40;
|
||||
|
||||
setting->setWidgetWidth (width);
|
||||
|
||||
if (type==Type_CheckBox)
|
||||
setting->setStyleSheet ("QGroupBox { border: 0px; }");
|
||||
|
||||
if (type==Type_CheckBox)
|
||||
setting->setDeclaredValues(QStringList() << "true" << "false");
|
||||
|
||||
if (type==Type_CheckBox)
|
||||
setting->setSpecialValueText (setting->getLabel());
|
||||
|
||||
//add declaration to the model
|
||||
mSettings.append (setting);
|
||||
|
||||
return setting;
|
||||
}
|
||||
|
||||
void CSMSettings::UserSettings::declareSection (const QString& page, const QString& label)
|
||||
{
|
||||
mSection = page;
|
||||
mSectionLabels[page] = label;
|
||||
}
|
||||
|
||||
QStringList CSMSettings::UserSettings::definitions (const QString &viewKey) const
|
||||
{
|
||||
if (mSettingDefinitions->contains (viewKey))
|
||||
return mSettingDefinitions->value (viewKey).toStringList();
|
||||
|
||||
return QStringList();
|
||||
}
|
|
@ -1,107 +0,0 @@
|
|||
#ifndef USERSETTINGS_HPP
|
||||
#define USERSETTINGS_HPP
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <QList>
|
||||
#include <QStringList>
|
||||
#include <QString>
|
||||
#include <QMap>
|
||||
#include <QPair>
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include "support.hpp"
|
||||
|
||||
#ifndef Q_MOC_RUN
|
||||
#include <components/files/configurationmanager.hpp>
|
||||
#endif
|
||||
|
||||
namespace Files { typedef std::vector<boost::filesystem::path> PathContainer;
|
||||
struct ConfigurationManager;}
|
||||
|
||||
class QFile;
|
||||
class QSettings;
|
||||
|
||||
namespace CSMSettings {
|
||||
|
||||
class Setting;
|
||||
typedef QMap <QString, QPair<QString, QList <Setting *> > > SettingPageMap;
|
||||
|
||||
class UserSettings: public QObject
|
||||
{
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
static UserSettings *sUserSettingsInstance;
|
||||
const Files::ConfigurationManager& mCfgMgr;
|
||||
|
||||
QSettings *mSettingDefinitions;
|
||||
QList <Setting *> mSettings;
|
||||
QString mSection;
|
||||
std::map<QString, QString> mSectionLabels;
|
||||
|
||||
public:
|
||||
|
||||
/// Singleton implementation
|
||||
static UserSettings& instance();
|
||||
|
||||
UserSettings (const Files::ConfigurationManager& configurationManager);
|
||||
~UserSettings();
|
||||
|
||||
UserSettings (UserSettings const &); //not implemented
|
||||
UserSettings& operator= (UserSettings const &); //not implemented
|
||||
|
||||
/// Retrieves the settings file at all three levels (global, local and user).
|
||||
void loadSettings (const QString &fileName);
|
||||
|
||||
/// Updates QSettings and syncs with the ini file
|
||||
void setDefinitions (const QString &key, const QStringList &defs);
|
||||
|
||||
QString settingValue (const QString &settingKey);
|
||||
|
||||
///retrieve a setting object from a given page and setting name
|
||||
Setting *findSetting
|
||||
(const QString &pageName, const QString &settingName = QString());
|
||||
|
||||
///remove a setting from the list
|
||||
void removeSetting
|
||||
(const QString &pageName, const QString &settingName);
|
||||
|
||||
///Retrieve a map of the settings, keyed by page name
|
||||
SettingPageMap settingPageMap() const;
|
||||
|
||||
///Returns a string list of defined vlaues for the specified setting
|
||||
///in "page/name" format.
|
||||
QStringList definitions (const QString &viewKey) const;
|
||||
|
||||
///Test to indicate whether or not a setting has any definitions
|
||||
bool hasSettingDefinitions (const QString &viewKey) const;
|
||||
|
||||
///Save any unsaved changes in the QSettings object
|
||||
void saveDefinitions() const;
|
||||
|
||||
QString setting(const QString &viewKey, const QString &value = QString());
|
||||
|
||||
private:
|
||||
|
||||
void buildSettingModelDefaults();
|
||||
|
||||
///add a new setting to the model and return it
|
||||
Setting *createSetting (CSMSettings::SettingType type, const QString &name,
|
||||
const QString& label);
|
||||
|
||||
/// Set the section for createSetting calls.
|
||||
///
|
||||
/// Sections can be declared multiple times.
|
||||
void declareSection (const QString& page, const QString& label);
|
||||
|
||||
signals:
|
||||
|
||||
void userSettingUpdated (const QString &, const QStringList &);
|
||||
|
||||
public slots:
|
||||
|
||||
void updateUserSetting (const QString &, const QStringList &);
|
||||
};
|
||||
}
|
||||
#endif // USERSETTINGS_HPP
|
123
apps/opencs/model/tools/gmstcheck.cpp
Normal file
123
apps/opencs/model/tools/gmstcheck.cpp
Normal file
|
@ -0,0 +1,123 @@
|
|||
#include "gmstcheck.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "../world/defaultgmsts.hpp"
|
||||
|
||||
CSMTools::GmstCheckStage::GmstCheckStage(const CSMWorld::IdCollection<ESM::GameSetting>& gameSettings)
|
||||
: mGameSettings(gameSettings)
|
||||
{}
|
||||
|
||||
int CSMTools::GmstCheckStage::setup()
|
||||
{
|
||||
return mGameSettings.getSize();
|
||||
}
|
||||
|
||||
void CSMTools::GmstCheckStage::perform(int stage, CSMDoc::Messages& messages)
|
||||
{
|
||||
const CSMWorld::Record<ESM::GameSetting>& record = mGameSettings.getRecord (stage);
|
||||
|
||||
if (record.isDeleted())
|
||||
return;
|
||||
|
||||
const ESM::GameSetting& gmst = record.get();
|
||||
|
||||
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Gmst, gmst.mId);
|
||||
|
||||
// Test for empty string
|
||||
if (gmst.mValue.getType() == ESM::VT_String && gmst.mValue.getString().empty())
|
||||
messages.add(id, gmst.mId + " is an empty string", "", CSMDoc::Message::Severity_Warning);
|
||||
|
||||
// Checking type and limits
|
||||
// optimization - compare it to lists based on naming convention (f-float,i-int,s-string)
|
||||
if (gmst.mId[0] == 'f')
|
||||
{
|
||||
for (size_t i = 0; i < CSMWorld::DefaultGmsts::FloatCount; ++i)
|
||||
{
|
||||
if (gmst.mId == CSMWorld::DefaultGmsts::Floats[i])
|
||||
{
|
||||
if (gmst.mValue.getType() != ESM::VT_Float)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << "Expected float type for " << gmst.mId << " but found "
|
||||
<< varTypeToString(gmst.mValue.getType()) << " type";
|
||||
|
||||
messages.add(id, stream.str(), "", CSMDoc::Message::Severity_Error);
|
||||
}
|
||||
|
||||
if (gmst.mValue.getFloat() < CSMWorld::DefaultGmsts::FloatLimits[i*2])
|
||||
messages.add(id, gmst.mId + " is less than the suggested range", "",
|
||||
CSMDoc::Message::Severity_Warning);
|
||||
|
||||
if (gmst.mValue.getFloat() > CSMWorld::DefaultGmsts::FloatLimits[i*2+1])
|
||||
messages.add(id, gmst.mId + " is more than the suggested range", "",
|
||||
CSMDoc::Message::Severity_Warning);
|
||||
|
||||
break; // for loop
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (gmst.mId[0] == 'i')
|
||||
{
|
||||
for (size_t i = 0; i < CSMWorld::DefaultGmsts::IntCount; ++i)
|
||||
{
|
||||
if (gmst.mId == CSMWorld::DefaultGmsts::Ints[i])
|
||||
{
|
||||
if (gmst.mValue.getType() != ESM::VT_Int)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << "Expected int type for " << gmst.mId << " but found "
|
||||
<< varTypeToString(gmst.mValue.getType()) << " type";
|
||||
|
||||
messages.add(id, stream.str(), "", CSMDoc::Message::Severity_Error);
|
||||
}
|
||||
|
||||
if (gmst.mValue.getInteger() < CSMWorld::DefaultGmsts::IntLimits[i*2])
|
||||
messages.add(id, gmst.mId + " is less than the suggested range", "",
|
||||
CSMDoc::Message::Severity_Warning);
|
||||
|
||||
if (gmst.mValue.getInteger() > CSMWorld::DefaultGmsts::IntLimits[i*2+1])
|
||||
messages.add(id, gmst.mId + " is more than the suggested range", "",
|
||||
CSMDoc::Message::Severity_Warning);
|
||||
|
||||
break; // for loop
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (gmst.mId[0] == 's')
|
||||
{
|
||||
for (size_t i = 0; i < CSMWorld::DefaultGmsts::StringCount; ++i)
|
||||
{
|
||||
if (gmst.mId == CSMWorld::DefaultGmsts::Strings[i])
|
||||
{
|
||||
ESM::VarType type = gmst.mValue.getType();
|
||||
|
||||
if (type != ESM::VT_String && type != ESM::VT_None)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << "Expected string or none type for " << gmst.mId << " but found "
|
||||
<< varTypeToString(gmst.mValue.getType()) << " type";
|
||||
|
||||
messages.add(id, stream.str(), "", CSMDoc::Message::Severity_Error);
|
||||
}
|
||||
|
||||
break; // for loop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string CSMTools::GmstCheckStage::varTypeToString(ESM::VarType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ESM::VT_Unknown: return "unknown";
|
||||
case ESM::VT_None: return "none";
|
||||
case ESM::VT_Short: return "short";
|
||||
case ESM::VT_Int: return "int";
|
||||
case ESM::VT_Long: return "long";
|
||||
case ESM::VT_Float: return "float";
|
||||
case ESM::VT_String: return "string";
|
||||
default: return "unhandled";
|
||||
}
|
||||
}
|
34
apps/opencs/model/tools/gmstcheck.hpp
Normal file
34
apps/opencs/model/tools/gmstcheck.hpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
#ifndef CSM_TOOLS_GMSTCHECK_H
|
||||
#define CSM_TOOLS_GMSTCHECK_H
|
||||
|
||||
#include <components/esm/loadgmst.hpp>
|
||||
|
||||
#include "../world/idcollection.hpp"
|
||||
|
||||
#include "../doc/stage.hpp"
|
||||
|
||||
namespace CSMTools
|
||||
{
|
||||
/// \brief VerifyStage: make sure that GMSTs are alright
|
||||
class GmstCheckStage : public CSMDoc::Stage
|
||||
{
|
||||
public:
|
||||
|
||||
GmstCheckStage(const CSMWorld::IdCollection<ESM::GameSetting>& gameSettings);
|
||||
|
||||
virtual int setup();
|
||||
///< \return number of steps
|
||||
|
||||
virtual void perform(int stage, CSMDoc::Messages& messages);
|
||||
///< Messages resulting from this stage will be appended to \a messages
|
||||
|
||||
private:
|
||||
|
||||
const CSMWorld::IdCollection<ESM::GameSetting>& mGameSettings;
|
||||
|
||||
std::string varTypeToString(ESM::VarType);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
namespace
|
||||
{
|
||||
void addMessageIfNotEmpty(CSMDoc::Messages &messages, const CSMWorld::UniversalId &id, const std::string text)
|
||||
void addMessageIfNotEmpty(CSMDoc::Messages &messages, const CSMWorld::UniversalId &id, const std::string& text)
|
||||
{
|
||||
if (!text.empty())
|
||||
{
|
||||
|
|
|
@ -397,6 +397,9 @@ void CSMTools::ReferenceableCheckStage::containerCheck(
|
|||
//checking for name
|
||||
if (container.mName.empty())
|
||||
messages.push_back (std::make_pair (id, container.mId + " has an empty name"));
|
||||
|
||||
//checking contained items
|
||||
inventoryListCheck(container.mInventory.mList, messages, id.toString());
|
||||
|
||||
// Check that mentioned scripts exist
|
||||
scriptCheck<ESM::Container>(container, messages, id.toString());
|
||||
|
@ -468,6 +471,12 @@ void CSMTools::ReferenceableCheckStage::creatureCheck (
|
|||
if (creature.mData.mGold < 0) //It seems that this is for gold in merchant creatures
|
||||
messages.push_back (std::make_pair (id, creature.mId + " has negative gold "));
|
||||
|
||||
if (creature.mScale == 0)
|
||||
messages.push_back (std::make_pair (id, creature.mId + " has zero scale value"));
|
||||
|
||||
// Check inventory
|
||||
inventoryListCheck(creature.mInventory.mList, messages, id.toString());
|
||||
|
||||
// Check that mentioned scripts exist
|
||||
scriptCheck<ESM::Creature>(creature, messages, id.toString());
|
||||
}
|
||||
|
@ -739,6 +748,9 @@ void CSMTools::ReferenceableCheckStage::npcCheck (
|
|||
|
||||
//TODO: reputation, Disposition, rank, everything else
|
||||
|
||||
// Check inventory
|
||||
inventoryListCheck(npc.mInventory.mList, messages, id.toString());
|
||||
|
||||
// Check that mentioned scripts exist
|
||||
scriptCheck<ESM::NPC>(npc, messages, id.toString());
|
||||
}
|
||||
|
@ -888,6 +900,45 @@ void CSMTools::ReferenceableCheckStage::finalCheck (CSMDoc::Messages& messages)
|
|||
"There is no player record"));
|
||||
}
|
||||
|
||||
void CSMTools::ReferenceableCheckStage::inventoryListCheck(
|
||||
const std::vector<ESM::ContItem>& itemList,
|
||||
CSMDoc::Messages& messages,
|
||||
const std::string& id)
|
||||
{
|
||||
for (size_t i = 0; i < itemList.size(); ++i)
|
||||
{
|
||||
std::string itemName = itemList[i].mItem.toString();
|
||||
CSMWorld::RefIdData::LocalIndex localIndex = mReferencables.searchId(itemName);
|
||||
|
||||
if (localIndex.first == -1)
|
||||
messages.push_back (std::make_pair (id,
|
||||
id + " contains non-existing item (" + itemName + ")"));
|
||||
else
|
||||
{
|
||||
// Needs to accomodate Containers, Creatures, and NPCs
|
||||
switch (localIndex.second)
|
||||
{
|
||||
case CSMWorld::UniversalId::Type_Potion:
|
||||
case CSMWorld::UniversalId::Type_Apparatus:
|
||||
case CSMWorld::UniversalId::Type_Armor:
|
||||
case CSMWorld::UniversalId::Type_Book:
|
||||
case CSMWorld::UniversalId::Type_Clothing:
|
||||
case CSMWorld::UniversalId::Type_Ingredient:
|
||||
case CSMWorld::UniversalId::Type_Light:
|
||||
case CSMWorld::UniversalId::Type_Lockpick:
|
||||
case CSMWorld::UniversalId::Type_Miscellaneous:
|
||||
case CSMWorld::UniversalId::Type_Probe:
|
||||
case CSMWorld::UniversalId::Type_Repair:
|
||||
case CSMWorld::UniversalId::Type_Weapon:
|
||||
case CSMWorld::UniversalId::Type_ItemLevelledList:
|
||||
break;
|
||||
default:
|
||||
messages.push_back (std::make_pair(id,
|
||||
id + " contains item of invalid type (" + itemName + ")"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Templates begins here
|
||||
|
||||
|
|
|
@ -47,7 +47,9 @@ namespace CSMTools
|
|||
//FINAL CHECK
|
||||
void finalCheck (CSMDoc::Messages& messages);
|
||||
|
||||
//TEMPLATE CHECKS
|
||||
//Convenience functions
|
||||
void inventoryListCheck(const std::vector<ESM::ContItem>& itemList, CSMDoc::Messages& messages, const std::string& id);
|
||||
|
||||
template<typename ITEM> void inventoryItemCheck(const ITEM& someItem,
|
||||
CSMDoc::Messages& messages,
|
||||
const std::string& someID,
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
#include "../world/data.hpp"
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
CSMDoc::Message::Severity CSMTools::ScriptCheckStage::getSeverity (Type type)
|
||||
{
|
||||
switch (type)
|
||||
|
@ -46,7 +48,7 @@ void CSMTools::ScriptCheckStage::report (const std::string& message, Type type)
|
|||
|
||||
std::ostringstream stream;
|
||||
stream << "script " << mFile << ": " << message;
|
||||
|
||||
|
||||
mMessages->add (id, stream.str(), "", getSeverity (type));
|
||||
}
|
||||
|
||||
|
@ -62,6 +64,15 @@ CSMTools::ScriptCheckStage::ScriptCheckStage (const CSMDoc::Document& document)
|
|||
|
||||
int CSMTools::ScriptCheckStage::setup()
|
||||
{
|
||||
std::string warnings = CSMPrefs::get()["Scripts"]["warnings"].toString();
|
||||
|
||||
if (warnings=="Ignore")
|
||||
mWarningMode = Mode_Ignore;
|
||||
else if (warnings=="Normal")
|
||||
mWarningMode = Mode_Normal;
|
||||
else if (warnings=="Strict")
|
||||
mWarningMode = Mode_Strict;
|
||||
|
||||
mContext.clear();
|
||||
mMessages = 0;
|
||||
mId.clear();
|
||||
|
@ -110,22 +121,9 @@ void CSMTools::ScriptCheckStage::perform (int stage, CSMDoc::Messages& messages)
|
|||
|
||||
std::ostringstream stream;
|
||||
stream << "script " << mFile << ": " << error.what();
|
||||
|
||||
|
||||
messages.add (id, stream.str(), "", CSMDoc::Message::Severity_SeriousError);
|
||||
}
|
||||
|
||||
mMessages = 0;
|
||||
}
|
||||
|
||||
void CSMTools::ScriptCheckStage::updateUserSetting (const QString& name, const QStringList& value)
|
||||
{
|
||||
if (name=="script-editor/warnings" && !value.isEmpty())
|
||||
{
|
||||
if (value.at (0)=="Ignore")
|
||||
mWarningMode = Mode_Ignore;
|
||||
else if (value.at (0)=="Normal")
|
||||
mWarningMode = Mode_Normal;
|
||||
else if (value.at (0)=="Strict")
|
||||
mWarningMode = Mode_Strict;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace CSMTools
|
|||
WarningMode mWarningMode;
|
||||
|
||||
CSMDoc::Message::Severity getSeverity (Type type);
|
||||
|
||||
|
||||
virtual void report (const std::string& message, const Compiler::TokenLoc& loc, Type type);
|
||||
///< Report error to the user.
|
||||
|
||||
|
@ -50,8 +50,6 @@ namespace CSMTools
|
|||
|
||||
virtual void perform (int stage, CSMDoc::Messages& messages);
|
||||
///< Messages resulting from this tage will be appended to \a messages.
|
||||
|
||||
virtual void updateUserSetting (const QString& name, const QStringList& value);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -120,24 +120,25 @@ QString CSMTools::Search::flatten (const QString& text) const
|
|||
return flat;
|
||||
}
|
||||
|
||||
CSMTools::Search::Search() : mType (Type_None), mPaddingBefore (10), mPaddingAfter (10) {}
|
||||
CSMTools::Search::Search() : mType (Type_None), mValue (0), mIdColumn (0), mTypeColumn (0),
|
||||
mPaddingBefore (10), mPaddingAfter (10) {}
|
||||
|
||||
CSMTools::Search::Search (Type type, const std::string& value)
|
||||
: mType (type), mText (value), mPaddingBefore (10), mPaddingAfter (10)
|
||||
: mType (type), mText (value), mValue (0), mIdColumn (0), mTypeColumn (0), mPaddingBefore (10), mPaddingAfter (10)
|
||||
{
|
||||
if (type!=Type_Text && type!=Type_Id)
|
||||
throw std::logic_error ("Invalid search parameter (string)");
|
||||
}
|
||||
|
||||
CSMTools::Search::Search (Type type, const QRegExp& value)
|
||||
: mType (type), mRegExp (value), mPaddingBefore (10), mPaddingAfter (10)
|
||||
: mType (type), mRegExp (value), mValue (0), mIdColumn (0), mTypeColumn (0), mPaddingBefore (10), mPaddingAfter (10)
|
||||
{
|
||||
if (type!=Type_TextRegEx && type!=Type_IdRegEx)
|
||||
throw std::logic_error ("Invalid search parameter (RegExp)");
|
||||
}
|
||||
|
||||
CSMTools::Search::Search (Type type, int value)
|
||||
: mType (type), mValue (value), mPaddingBefore (10), mPaddingAfter (10)
|
||||
: mType (type), mValue (value), mIdColumn (0), mTypeColumn (0), mPaddingBefore (10), mPaddingAfter (10)
|
||||
{
|
||||
if (type!=Type_RecordState)
|
||||
throw std::logic_error ("invalid search parameter (int)");
|
||||
|
|
|
@ -26,7 +26,7 @@ void CSMTools::SoundGenCheckStage::perform(int stage, CSMDoc::Messages &messages
|
|||
return;
|
||||
}
|
||||
|
||||
const ESM::SoundGenerator soundGen = record.get();
|
||||
const ESM::SoundGenerator& soundGen = record.get();
|
||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_SoundGen, soundGen.mId);
|
||||
|
||||
if (!soundGen.mCreature.empty())
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "soundgencheck.hpp"
|
||||
#include "magiceffectcheck.hpp"
|
||||
#include "mergeoperation.hpp"
|
||||
#include "gmstcheck.hpp"
|
||||
|
||||
CSMDoc::OperationHolder *CSMTools::Tools::get (int type)
|
||||
{
|
||||
|
@ -53,11 +54,6 @@ CSMDoc::OperationHolder *CSMTools::Tools::getVerifier()
|
|||
{
|
||||
mVerifierOperation = new CSMDoc::Operation (CSMDoc::State_Verifying, false);
|
||||
|
||||
std::vector<QString> settings;
|
||||
settings.push_back ("script-editor/warnings");
|
||||
|
||||
mVerifierOperation->configureSettings (settings);
|
||||
|
||||
connect (&mVerifier, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int)));
|
||||
connect (&mVerifier, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool)));
|
||||
connect (&mVerifier, SIGNAL (reportMessage (const CSMDoc::Message&, int)),
|
||||
|
@ -115,6 +111,8 @@ CSMDoc::OperationHolder *CSMTools::Tools::getVerifier()
|
|||
mData.getReferenceables(),
|
||||
mData.getResources (CSMWorld::UniversalId::Type_Icons),
|
||||
mData.getResources (CSMWorld::UniversalId::Type_Textures)));
|
||||
|
||||
mVerifierOperation->appendStage (new GmstCheckStage (mData.getGmsts()));
|
||||
|
||||
mVerifier.setOperation (mVerifierOperation);
|
||||
}
|
||||
|
|
|
@ -2,18 +2,15 @@
|
|||
|
||||
#include <sstream>
|
||||
|
||||
void CSMWorld::Cell::load (ESM::ESMReader &esm)
|
||||
void CSMWorld::Cell::load (ESM::ESMReader &esm, bool &isDeleted)
|
||||
{
|
||||
mName = mId;
|
||||
ESM::Cell::load (esm, isDeleted, false);
|
||||
|
||||
ESM::Cell::load (esm, false);
|
||||
|
||||
if (!(mData.mFlags & Interior))
|
||||
mId = mName;
|
||||
if (isExterior())
|
||||
{
|
||||
std::ostringstream stream;
|
||||
|
||||
stream << "#" << mData.mX << " " << mData.mY;
|
||||
|
||||
mId = stream.str();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace CSMWorld
|
|||
{
|
||||
std::string mId;
|
||||
|
||||
void load (ESM::ESMReader &esm);
|
||||
void load (ESM::ESMReader &esm, bool &isDeleted);
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -43,6 +43,12 @@ namespace CSMWorld
|
|||
template<typename ESXRecordT, typename IdAccessorT = IdAccessor<ESXRecordT> >
|
||||
class Collection : public CollectionBase
|
||||
{
|
||||
public:
|
||||
|
||||
typedef ESXRecordT ESXRecord;
|
||||
|
||||
private:
|
||||
|
||||
std::vector<Record<ESXRecordT> > mRecords;
|
||||
std::map<std::string, int> mIndex;
|
||||
std::vector<Column<ESXRecordT> *> mColumns;
|
||||
|
|
|
@ -86,6 +86,10 @@ bool CSMWorld::ColumnBase::isId (Display display)
|
|||
Display_InfoCondVar,
|
||||
Display_InfoCondComp,
|
||||
|
||||
Display_EffectSkill,
|
||||
Display_EffectAttribute,
|
||||
Display_IngredEffectId,
|
||||
|
||||
Display_None
|
||||
};
|
||||
|
||||
|
|
|
@ -14,6 +14,13 @@ namespace CSMWorld
|
|||
{
|
||||
struct ColumnBase
|
||||
{
|
||||
enum TableEditModes
|
||||
{
|
||||
TableEdit_None, // no editing
|
||||
TableEdit_Full, // edit cells and add/remove rows
|
||||
TableEdit_FixedRows // edit cells only
|
||||
};
|
||||
|
||||
enum Roles
|
||||
{
|
||||
Role_Flags = Qt::UserRole,
|
||||
|
@ -124,6 +131,10 @@ namespace CSMWorld
|
|||
Display_String32,
|
||||
Display_LongString256,
|
||||
|
||||
Display_EffectSkill, // must display at least one, unlike Display_Skill
|
||||
Display_EffectAttribute, // must display at least one, unlike Display_Attribute
|
||||
Display_IngredEffectId, // display none allowed, unlike Display_EffectId
|
||||
|
||||
//top level columns that nest other columns
|
||||
Display_NestedHeader
|
||||
};
|
||||
|
@ -186,8 +197,8 @@ namespace CSMWorld
|
|||
template<typename ESXRecordT>
|
||||
struct NestedParentColumn : public Column<ESXRecordT>
|
||||
{
|
||||
NestedParentColumn (int id, int flags = ColumnBase::Flag_Dialogue) : Column<ESXRecordT> (id,
|
||||
ColumnBase::Display_NestedHeader, flags)
|
||||
NestedParentColumn (int id, int flags = ColumnBase::Flag_Dialogue, bool fixedRows = false)
|
||||
: Column<ESXRecordT> (id, ColumnBase::Display_NestedHeader, flags), mFixedRows(fixedRows)
|
||||
{}
|
||||
|
||||
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
||||
|
@ -198,13 +209,20 @@ namespace CSMWorld
|
|||
|
||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
{
|
||||
return true; // required by IdTree::hasChildren()
|
||||
// by default editable; also see IdTree::hasChildren()
|
||||
if (mFixedRows)
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_FixedRows);
|
||||
else
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
}
|
||||
|
||||
virtual bool isEditable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
bool mFixedRows;
|
||||
};
|
||||
|
||||
struct NestedChildColumn : public NestableColumn
|
||||
|
@ -219,4 +237,6 @@ namespace CSMWorld
|
|||
};
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(CSMWorld::ColumnBase::TableEditModes)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -93,7 +93,7 @@ void CSMWorld::CommandDispatcher::setEditLock (bool locked)
|
|||
void CSMWorld::CommandDispatcher::setSelection (const std::vector<std::string>& selection)
|
||||
{
|
||||
mSelection = selection;
|
||||
std::for_each (mSelection.begin(), mSelection.end(), Misc::StringUtils::toLower);
|
||||
std::for_each (mSelection.begin(), mSelection.end(), Misc::StringUtils::lowerCaseInPlace);
|
||||
std::sort (mSelection.begin(), mSelection.end());
|
||||
}
|
||||
|
||||
|
|
|
@ -59,9 +59,10 @@ int CSMWorld::Data::count (RecordBase::State state, const CollectionBase& collec
|
|||
return number;
|
||||
}
|
||||
|
||||
CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourcesManager)
|
||||
CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourcesManager, const Fallback::Map* fallback)
|
||||
: mEncoder (encoding), mPathgrids (mCells), mRefs (mCells),
|
||||
mResourcesManager (resourcesManager), mReader (0), mDialogue (0), mReaderIndex(0), mResourceSystem(new Resource::ResourceSystem(resourcesManager.getVFS()))
|
||||
mResourcesManager (resourcesManager), mFallbackMap(fallback),
|
||||
mReader (0), mDialogue (0), mReaderIndex(0), mResourceSystem(new Resource::ResourceSystem(resourcesManager.getVFS()))
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
|
@ -136,7 +137,8 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
|
|||
mRaces.getNestableColumn(index)->addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_SpellId, ColumnBase::Display_Spell));
|
||||
// Race attributes
|
||||
mRaces.addColumn (new NestedParentColumn<ESM::Race> (Columns::ColumnId_RaceAttributes));
|
||||
mRaces.addColumn (new NestedParentColumn<ESM::Race> (Columns::ColumnId_RaceAttributes,
|
||||
ColumnBase::Flag_Dialogue, true)); // fixed rows table
|
||||
index = mRaces.getColumns()-1;
|
||||
mRaces.addAdapter (std::make_pair(&mRaces.getColumn(index), new RaceAttributeAdapter()));
|
||||
mRaces.getNestableColumn(index)->addColumn(
|
||||
|
@ -147,7 +149,8 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
|
|||
mRaces.getNestableColumn(index)->addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_Female, ColumnBase::Display_Integer));
|
||||
// Race skill bonus
|
||||
mRaces.addColumn (new NestedParentColumn<ESM::Race> (Columns::ColumnId_RaceSkillBonus));
|
||||
mRaces.addColumn (new NestedParentColumn<ESM::Race> (Columns::ColumnId_RaceSkillBonus,
|
||||
ColumnBase::Flag_Dialogue, true)); // fixed rows table
|
||||
index = mRaces.getColumns()-1;
|
||||
mRaces.addAdapter (std::make_pair(&mRaces.getColumn(index), new RaceSkillsBonusAdapter()));
|
||||
mRaces.getNestableColumn(index)->addColumn(
|
||||
|
@ -213,9 +216,9 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
|
|||
mSpells.getNestableColumn(index)->addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_EffectId, ColumnBase::Display_EffectId));
|
||||
mSpells.getNestableColumn(index)->addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_Skill, ColumnBase::Display_SkillId));
|
||||
new NestedChildColumn (Columns::ColumnId_Skill, ColumnBase::Display_EffectSkill));
|
||||
mSpells.getNestableColumn(index)->addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_Attribute));
|
||||
new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_EffectAttribute));
|
||||
mSpells.getNestableColumn(index)->addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_EffectRange, ColumnBase::Display_EffectRange));
|
||||
mSpells.getNestableColumn(index)->addColumn(
|
||||
|
@ -329,9 +332,9 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
|
|||
mEnchantments.getNestableColumn(index)->addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_EffectId, ColumnBase::Display_EffectId));
|
||||
mEnchantments.getNestableColumn(index)->addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_Skill, ColumnBase::Display_SkillId));
|
||||
new NestedChildColumn (Columns::ColumnId_Skill, ColumnBase::Display_EffectSkill));
|
||||
mEnchantments.getNestableColumn(index)->addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_Attribute));
|
||||
new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_EffectAttribute));
|
||||
mEnchantments.getNestableColumn(index)->addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_EffectRange, ColumnBase::Display_EffectRange));
|
||||
mEnchantments.getNestableColumn(index)->addColumn(
|
||||
|
@ -1008,41 +1011,43 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages)
|
|||
|
||||
case ESM::REC_DIAL:
|
||||
{
|
||||
std::string id = mReader->getHNOString ("NAME");
|
||||
|
||||
ESM::Dialogue record;
|
||||
record.mId = id;
|
||||
record.load (*mReader);
|
||||
bool isDeleted = false;
|
||||
|
||||
if (record.mType==ESM::Dialogue::Journal)
|
||||
{
|
||||
mJournals.load (record, mBase);
|
||||
mDialogue = &mJournals.getRecord (id).get();
|
||||
}
|
||||
else if (record.mType==ESM::Dialogue::Deleted)
|
||||
{
|
||||
mDialogue = 0; // record vector can be shuffled around which would make pointer
|
||||
// to record invalid
|
||||
record.load (*mReader, isDeleted);
|
||||
|
||||
if (mJournals.tryDelete (id))
|
||||
if (isDeleted)
|
||||
{
|
||||
// record vector can be shuffled around which would make pointer to record invalid
|
||||
mDialogue = 0;
|
||||
|
||||
if (mJournals.tryDelete (record.mId))
|
||||
{
|
||||
/// \todo handle info records
|
||||
mJournalInfos.removeDialogueInfos(record.mId);
|
||||
}
|
||||
else if (mTopics.tryDelete (id))
|
||||
else if (mTopics.tryDelete (record.mId))
|
||||
{
|
||||
/// \todo handle info records
|
||||
mTopicInfos.removeDialogueInfos(record.mId);
|
||||
}
|
||||
else
|
||||
{
|
||||
messages.add (UniversalId::Type_None,
|
||||
"Trying to delete dialogue record " + id + " which does not exist",
|
||||
"Trying to delete dialogue record " + record.mId + " which does not exist",
|
||||
"", CSMDoc::Message::Severity_Warning);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mTopics.load (record, mBase);
|
||||
mDialogue = &mTopics.getRecord (id).get();
|
||||
if (record.mType == ESM::Dialogue::Journal)
|
||||
{
|
||||
mJournals.load (record, mBase);
|
||||
mDialogue = &mJournals.getRecord (record.mId).get();
|
||||
}
|
||||
else
|
||||
{
|
||||
mTopics.load (record, mBase);
|
||||
mDialogue = &mTopics.getRecord (record.mId).get();
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -1197,3 +1202,8 @@ const VFS::Manager* CSMWorld::Data::getVFS() const
|
|||
{
|
||||
return mResourcesManager.getVFS();
|
||||
}
|
||||
|
||||
const Fallback::Map* CSMWorld::Data::getFallbackMap() const
|
||||
{
|
||||
return mFallbackMap;
|
||||
}
|
||||
|
|
|
@ -58,6 +58,11 @@ namespace VFS
|
|||
class Manager;
|
||||
}
|
||||
|
||||
namespace Fallback
|
||||
{
|
||||
class Map;
|
||||
}
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
class ESMReader;
|
||||
|
@ -104,6 +109,7 @@ namespace CSMWorld
|
|||
IdCollection<ESM::Filter> mFilters;
|
||||
Collection<MetaData> mMetaData;
|
||||
const ResourcesManager& mResourcesManager;
|
||||
const Fallback::Map* mFallbackMap;
|
||||
std::vector<QAbstractItemModel *> mModels;
|
||||
std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex;
|
||||
ESM::ESMReader *mReader;
|
||||
|
@ -132,12 +138,14 @@ namespace CSMWorld
|
|||
|
||||
public:
|
||||
|
||||
Data (ToUTF8::FromType encoding, const ResourcesManager& resourcesManager);
|
||||
Data (ToUTF8::FromType encoding, const ResourcesManager& resourcesManager, const Fallback::Map* fallback);
|
||||
|
||||
virtual ~Data();
|
||||
|
||||
const VFS::Manager* getVFS() const;
|
||||
|
||||
const Fallback::Map* getFallbackMap() const;
|
||||
|
||||
boost::shared_ptr<Resource::ResourceSystem> getResourceSystem();
|
||||
|
||||
boost::shared_ptr<const Resource::ResourceSystem> getResourceSystem() const;
|
||||
|
|
2336
apps/opencs/model/world/defaultgmsts.cpp
Normal file
2336
apps/opencs/model/world/defaultgmsts.cpp
Normal file
File diff suppressed because it is too large
Load diff
34
apps/opencs/model/world/defaultgmsts.hpp
Normal file
34
apps/opencs/model/world/defaultgmsts.hpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
#ifndef CSM_WORLD_DEFAULTGMSTS_H
|
||||
#define CSM_WORLD_DEFAULTGMSTS_H
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace CSMWorld {
|
||||
namespace DefaultGmsts {
|
||||
|
||||
const size_t FloatCount = 258;
|
||||
const size_t IntCount = 89;
|
||||
const size_t StringCount = 1174;
|
||||
|
||||
const size_t OptionalFloatCount = 42;
|
||||
const size_t OptionalIntCount = 4;
|
||||
const size_t OptionalStringCount = 26;
|
||||
|
||||
extern const char* Floats[];
|
||||
extern const char * Ints[];
|
||||
extern const char * Strings[];
|
||||
|
||||
extern const char * OptionalFloats[];
|
||||
extern const char * OptionalInts[];
|
||||
extern const char * OptionalStrings[];
|
||||
|
||||
extern const float FloatsDefaultValues[];
|
||||
extern const int IntsDefaultValues[];
|
||||
|
||||
extern const float FloatLimits[];
|
||||
extern const int IntLimits[];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -11,7 +11,7 @@ namespace CSMWorld
|
|||
template<typename ESXRecordT, typename IdAccessorT = IdAccessor<ESXRecordT> >
|
||||
class IdCollection : public Collection<ESXRecordT, IdAccessorT>
|
||||
{
|
||||
virtual void loadRecord (ESXRecordT& record, ESM::ESMReader& reader);
|
||||
virtual void loadRecord (ESXRecordT& record, ESM::ESMReader& reader, bool& isDeleted);
|
||||
|
||||
public:
|
||||
|
||||
|
@ -33,77 +33,46 @@ namespace CSMWorld
|
|||
|
||||
template<typename ESXRecordT, typename IdAccessorT>
|
||||
void IdCollection<ESXRecordT, IdAccessorT>::loadRecord (ESXRecordT& record,
|
||||
ESM::ESMReader& reader)
|
||||
ESM::ESMReader& reader,
|
||||
bool& isDeleted)
|
||||
{
|
||||
record.load (reader);
|
||||
record.load (reader, isDeleted);
|
||||
}
|
||||
|
||||
template<typename ESXRecordT, typename IdAccessorT>
|
||||
int IdCollection<ESXRecordT, IdAccessorT>::load (ESM::ESMReader& reader, bool base)
|
||||
{
|
||||
std::string id = reader.getHNOString ("NAME");
|
||||
ESXRecordT record;
|
||||
bool isDeleted = false;
|
||||
|
||||
if (reader.isNextSub ("DELE"))
|
||||
loadRecord (record, reader, isDeleted);
|
||||
|
||||
std::string id = IdAccessorT().getId (record);
|
||||
int index = this->searchId (id);
|
||||
|
||||
if (isDeleted)
|
||||
{
|
||||
int index = Collection<ESXRecordT, IdAccessorT>::searchId (id);
|
||||
|
||||
reader.skipRecord();
|
||||
|
||||
if (index==-1)
|
||||
{
|
||||
// deleting a record that does not exist
|
||||
|
||||
// ignore it for now
|
||||
|
||||
/// \todo report the problem to the user
|
||||
}
|
||||
else if (base)
|
||||
{
|
||||
Collection<ESXRecordT, IdAccessorT>::removeRows (index, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Record<ESXRecordT> record = Collection<ESXRecordT, IdAccessorT>::getRecord (index);
|
||||
record.mState = RecordBase::State_Deleted;
|
||||
this->setRecord (index, record);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
if (base)
|
||||
{
|
||||
this->removeRows (index, 1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Record<ESXRecordT> baseRecord = this->getRecord (index);
|
||||
baseRecord.mState = RecordBase::State_Deleted;
|
||||
this->setRecord (index, baseRecord);
|
||||
return index;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESXRecordT record;
|
||||
|
||||
// Sometimes id (i.e. NAME of the cell) may be different to the id we stored
|
||||
// earlier. e.g. NAME == "Vivec, Arena" but id == "#-4 11". Sometime NAME is
|
||||
// missing altogether for scripts or cells.
|
||||
//
|
||||
// In such cases the returned index will be -1. We then try updating the
|
||||
// IdAccessor's id manually (e.g. set mId of the record to "Vivec, Arena")
|
||||
// and try getting the index once more after loading the record. The mId of the
|
||||
// record would have changed to "#-4 11" after the load, and searchId() should find
|
||||
// it (if this is a modify)
|
||||
int index = this->searchId (id);
|
||||
|
||||
if (index==-1)
|
||||
IdAccessorT().getId (record) = id;
|
||||
else
|
||||
{
|
||||
record = this->getRecord (index).get();
|
||||
}
|
||||
|
||||
loadRecord (record, reader);
|
||||
|
||||
if (index==-1)
|
||||
{
|
||||
std::string newId = IdAccessorT().getId(record);
|
||||
int newIndex = this->searchId(newId);
|
||||
if (newIndex != -1 && id != newId)
|
||||
index = newIndex;
|
||||
}
|
||||
|
||||
return load (record, base, index);
|
||||
}
|
||||
return load (record, base, index);
|
||||
}
|
||||
|
||||
template<typename ESXRecordT, typename IdAccessorT>
|
||||
|
|
|
@ -106,21 +106,20 @@ bool CSMWorld::InfoCollection::reorderRows (int baseIndex, const std::vector<int
|
|||
|
||||
void CSMWorld::InfoCollection::load (ESM::ESMReader& reader, bool base, const ESM::Dialogue& dialogue)
|
||||
{
|
||||
std::string id = Misc::StringUtils::lowerCase (dialogue.mId) + "#" +
|
||||
reader.getHNOString ("INAM");
|
||||
Info info;
|
||||
bool isDeleted = false;
|
||||
|
||||
if (reader.isNextSub ("DELE"))
|
||||
info.load (reader, isDeleted);
|
||||
std::string id = Misc::StringUtils::lowerCase (dialogue.mId) + "#" + info.mId;
|
||||
|
||||
if (isDeleted)
|
||||
{
|
||||
int index = searchId (id);
|
||||
|
||||
reader.skipRecord();
|
||||
|
||||
if (index==-1)
|
||||
{
|
||||
// deleting a record that does not exist
|
||||
|
||||
// ignore it for now
|
||||
|
||||
/// \todo report the problem to the user
|
||||
}
|
||||
else if (base)
|
||||
|
@ -136,12 +135,9 @@ void CSMWorld::InfoCollection::load (ESM::ESMReader& reader, bool base, const ES
|
|||
}
|
||||
else
|
||||
{
|
||||
Info record;
|
||||
record.mTopicId = dialogue.mId;
|
||||
record.mId = id;
|
||||
record.load (reader);
|
||||
|
||||
load (record, base);
|
||||
info.mTopicId = dialogue.mId;
|
||||
info.mId = id;
|
||||
load (info, base);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -193,3 +189,39 @@ CSMWorld::InfoCollection::Range CSMWorld::InfoCollection::getTopicRange (const s
|
|||
|
||||
return Range (begin, end);
|
||||
}
|
||||
|
||||
void CSMWorld::InfoCollection::removeDialogueInfos(const std::string& dialogueId)
|
||||
{
|
||||
std::string id = Misc::StringUtils::lowerCase(dialogueId);
|
||||
std::vector<int> erasedRecords;
|
||||
|
||||
std::map<std::string, int>::const_iterator current = getIdMap().lower_bound(id);
|
||||
std::map<std::string, int>::const_iterator end = getIdMap().end();
|
||||
for (; current != end; ++current)
|
||||
{
|
||||
Record<Info> record = getRecord(current->second);
|
||||
|
||||
if (Misc::StringUtils::ciEqual(dialogueId, record.get().mTopicId))
|
||||
{
|
||||
if (record.mState == RecordBase::State_ModifiedOnly)
|
||||
{
|
||||
erasedRecords.push_back(current->second);
|
||||
}
|
||||
else
|
||||
{
|
||||
record.mState = RecordBase::State_Deleted;
|
||||
setRecord(current->second, record);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (!erasedRecords.empty())
|
||||
{
|
||||
removeRows(erasedRecords.back(), 1);
|
||||
erasedRecords.pop_back();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,8 @@ namespace CSMWorld
|
|||
Range getTopicRange (const std::string& topic) const;
|
||||
///< Return iterators that point to the beginning and past the end of the range for
|
||||
/// the given topic.
|
||||
|
||||
void removeDialogueInfos(const std::string& dialogueId);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -4,13 +4,12 @@
|
|||
|
||||
namespace CSMWorld
|
||||
{
|
||||
void Land::load(ESM::ESMReader &esm)
|
||||
void Land::load(ESM::ESMReader &esm, bool &isDeleted)
|
||||
{
|
||||
ESM::Land::load(esm);
|
||||
ESM::Land::load(esm, isDeleted);
|
||||
|
||||
std::ostringstream stream;
|
||||
stream << "#" << mX << " " << mY;
|
||||
|
||||
mId = stream.str();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,13 +10,12 @@ namespace CSMWorld
|
|||
/// \brief Wrapper for Land record. Encodes X and Y cell index in the ID.
|
||||
///
|
||||
/// \todo Add worldspace support to the Land record.
|
||||
/// \todo Add a proper copy constructor (currently worked around using shared_ptr)
|
||||
struct Land : public ESM::Land
|
||||
{
|
||||
std::string mId;
|
||||
|
||||
/// Loads the metadata and ID
|
||||
void load (ESM::ESMReader &esm);
|
||||
void load (ESM::ESMReader &esm, bool &isDeleted);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -4,10 +4,9 @@
|
|||
|
||||
namespace CSMWorld
|
||||
{
|
||||
|
||||
void LandTexture::load(ESM::ESMReader &esm)
|
||||
void LandTexture::load(ESM::ESMReader &esm, bool &isDeleted)
|
||||
{
|
||||
ESM::LandTexture::load(esm);
|
||||
ESM::LandTexture::load(esm, isDeleted);
|
||||
|
||||
mPluginIndex = esm.getIndex();
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace CSMWorld
|
|||
{
|
||||
int mPluginIndex;
|
||||
|
||||
void load (ESM::ESMReader &esm);
|
||||
void load (ESM::ESMReader &esm, bool &isDeleted);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -277,7 +277,7 @@ namespace CSMWorld
|
|||
// WARNING: Assumed that the table view has the same order as std::map
|
||||
std::map<std::string, int>::iterator iter = reactions.begin();
|
||||
for(int i = 0; i < rowToRemove; ++i)
|
||||
iter++;
|
||||
++iter;
|
||||
reactions.erase(iter);
|
||||
|
||||
record.setModified (faction);
|
||||
|
@ -314,7 +314,7 @@ namespace CSMWorld
|
|||
// WARNING: Assumed that the table view has the same order as std::map
|
||||
std::map<std::string, int>::const_iterator iter = reactions.begin();
|
||||
for(int i = 0; i < subRowIndex; ++i)
|
||||
iter++;
|
||||
++iter;
|
||||
switch (subColIndex)
|
||||
{
|
||||
case 0: return QString((*iter).first.c_str());
|
||||
|
@ -337,7 +337,7 @@ namespace CSMWorld
|
|||
// WARNING: Assumed that the table view has the same order as std::map
|
||||
std::map<std::string, int>::iterator iter = reactions.begin();
|
||||
for(int i = 0; i < subRowIndex; ++i)
|
||||
iter++;
|
||||
++iter;
|
||||
|
||||
std::string factionId = (*iter).first;
|
||||
int reaction = (*iter).second;
|
||||
|
@ -606,7 +606,7 @@ namespace CSMWorld
|
|||
funcMap["09"] = "PC Fatigue";
|
||||
funcMap["10"] = "PC Strength";
|
||||
funcMap["11"] = "PC Block";
|
||||
funcMap["12"] = "PC Armoror";
|
||||
funcMap["12"] = "PC Armorer";
|
||||
funcMap["13"] = "PC Medium Armor";
|
||||
funcMap["14"] = "PC Heavy Armor";
|
||||
funcMap["15"] = "PC Blunt Weapon";
|
||||
|
|
|
@ -317,8 +317,34 @@ namespace CSMWorld
|
|||
else
|
||||
throw std::runtime_error("Magic effects ID unexpected value");
|
||||
}
|
||||
case 1: return effect.mSkill;
|
||||
case 2: return effect.mAttribute;
|
||||
case 1:
|
||||
{
|
||||
switch (effect.mEffectID)
|
||||
{
|
||||
case ESM::MagicEffect::DrainSkill:
|
||||
case ESM::MagicEffect::DamageSkill:
|
||||
case ESM::MagicEffect::RestoreSkill:
|
||||
case ESM::MagicEffect::FortifySkill:
|
||||
case ESM::MagicEffect::AbsorbSkill:
|
||||
return effect.mSkill;
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
switch (effect.mEffectID)
|
||||
{
|
||||
case ESM::MagicEffect::DrainAttribute:
|
||||
case ESM::MagicEffect::DamageAttribute:
|
||||
case ESM::MagicEffect::RestoreAttribute:
|
||||
case ESM::MagicEffect::FortifyAttribute:
|
||||
case ESM::MagicEffect::AbsorbAttribute:
|
||||
return effect.mAttribute;
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
if (effect.mRange >=0 && effect.mRange <=2)
|
||||
|
|
|
@ -4,33 +4,28 @@
|
|||
|
||||
#include <sstream>
|
||||
|
||||
void CSMWorld::Pathgrid::load (ESM::ESMReader &esm, const IdCollection<Cell>& cells)
|
||||
void CSMWorld::Pathgrid::load (ESM::ESMReader &esm, bool &isDeleted, const IdCollection<Cell>& cells)
|
||||
{
|
||||
load (esm);
|
||||
load (esm, isDeleted);
|
||||
|
||||
// correct ID
|
||||
if (!mId.empty() && mId[0]!='#' && cells.searchId (mId)==-1)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
|
||||
stream << "#" << mData.mX << " " << mData.mY;
|
||||
|
||||
mId = stream.str();
|
||||
}
|
||||
}
|
||||
|
||||
void CSMWorld::Pathgrid::load (ESM::ESMReader &esm)
|
||||
void CSMWorld::Pathgrid::load (ESM::ESMReader &esm, bool &isDeleted)
|
||||
{
|
||||
ESM::Pathgrid::load (esm);
|
||||
ESM::Pathgrid::load (esm, isDeleted);
|
||||
|
||||
mId = mCell;
|
||||
if (mCell.empty())
|
||||
{
|
||||
std::ostringstream stream;
|
||||
|
||||
stream << "#" << mData.mX << " " << mData.mY;
|
||||
|
||||
mId = stream.str();
|
||||
}
|
||||
else
|
||||
mId = mCell;
|
||||
}
|
||||
|
|
|
@ -20,9 +20,8 @@ namespace CSMWorld
|
|||
{
|
||||
std::string mId;
|
||||
|
||||
void load (ESM::ESMReader &esm, const IdCollection<Cell>& cells);
|
||||
|
||||
void load (ESM::ESMReader &esm);
|
||||
void load (ESM::ESMReader &esm, bool &isDeleted, const IdCollection<Cell>& cells);
|
||||
void load (ESM::ESMReader &esm, bool &isDeleted);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -19,12 +19,11 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool
|
|||
Cell& cell2 = base ? cell.mBase : cell.mModified;
|
||||
|
||||
CellRef ref;
|
||||
|
||||
bool deleted = false;
|
||||
ESM::MovedCellRef mref;
|
||||
bool isDeleted = false;
|
||||
|
||||
// hack to initialise mindex
|
||||
while (!(mref.mRefNum.mIndex = 0) && ESM::Cell::getNextRef(reader, ref, deleted, 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
|
||||
// original cell will always be equal the current cell).
|
||||
|
@ -49,17 +48,6 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool
|
|||
// https://forum.openmw.org/viewtopic.php?f=6&t=577&start=30
|
||||
ref.mOriginalCell = cell2.mId;
|
||||
|
||||
if (deleted)
|
||||
{
|
||||
// FIXME: how to mark the record deleted?
|
||||
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Cell,
|
||||
mCells.getId (cellIndex));
|
||||
|
||||
messages.add (id, "Moved reference "+ref.mRefID+" is in DELE state");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// It is not always possibe to ignore moved references sub-record and
|
||||
// calculate from coordinates. Some mods may place the ref in positions
|
||||
// outside normal bounds, resulting in non sensical cell id's. This often
|
||||
|
@ -91,7 +79,7 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool
|
|||
break;
|
||||
}
|
||||
|
||||
if (deleted)
|
||||
if (isDeleted)
|
||||
{
|
||||
if (iter==cache.end())
|
||||
{
|
||||
|
@ -99,7 +87,6 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool
|
|||
mCells.getId (cellIndex));
|
||||
|
||||
messages.add (id, "Attempt to delete a non-existing reference");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -107,7 +94,7 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool
|
|||
|
||||
Record<CellRef> record = getRecord (index);
|
||||
|
||||
if (record.mState==RecordBase::State_BaseOnly)
|
||||
if (base)
|
||||
{
|
||||
removeRows (index, 1);
|
||||
cache.erase (iter);
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include <utility>
|
||||
|
||||
#include <components/esm/loadcont.hpp>
|
||||
#include <components/esm/loadmgef.hpp>
|
||||
|
||||
#include "nestedtablewrapper.hpp"
|
||||
|
||||
CSMWorld::PotionColumns::PotionColumns (const InventoryColumns& columns)
|
||||
|
@ -25,8 +27,9 @@ QVariant CSMWorld::PotionRefIdAdapter::getData (const RefIdColumn *column, const
|
|||
if (column==mAutoCalc)
|
||||
return record.get().mData.mAutoCalc!=0;
|
||||
|
||||
// to show nested tables in dialogue subview, see IdTree::hasChildren()
|
||||
if (column==mColumns.mEffects)
|
||||
return true; // to show nested tables in dialogue subview, see IdTree::hasChildren()
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
|
||||
return InventoryRefIdAdapter<ESM::Potion>::getData (column, data, index);
|
||||
}
|
||||
|
@ -52,6 +55,156 @@ void CSMWorld::PotionRefIdAdapter::setData (const RefIdColumn *column, RefIdData
|
|||
}
|
||||
|
||||
|
||||
CSMWorld::IngredientColumns::IngredientColumns (const InventoryColumns& columns)
|
||||
: InventoryColumns (columns) {}
|
||||
|
||||
CSMWorld::IngredientRefIdAdapter::IngredientRefIdAdapter (const IngredientColumns& columns)
|
||||
: InventoryRefIdAdapter<ESM::Ingredient> (UniversalId::Type_Ingredient, columns),
|
||||
mColumns(columns)
|
||||
{}
|
||||
|
||||
QVariant CSMWorld::IngredientRefIdAdapter::getData (const RefIdColumn *column, const RefIdData& data,
|
||||
int index) const
|
||||
{
|
||||
if (column==mColumns.mEffects)
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_FixedRows);
|
||||
|
||||
return InventoryRefIdAdapter<ESM::Ingredient>::getData (column, data, index);
|
||||
}
|
||||
|
||||
void CSMWorld::IngredientRefIdAdapter::setData (const RefIdColumn *column, RefIdData& data, int index,
|
||||
const QVariant& value) const
|
||||
{
|
||||
InventoryRefIdAdapter<ESM::Ingredient>::setData (column, data, index, value);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
CSMWorld::IngredEffectRefIdAdapter::IngredEffectRefIdAdapter()
|
||||
: mType(UniversalId::Type_Ingredient)
|
||||
{}
|
||||
|
||||
CSMWorld::IngredEffectRefIdAdapter::~IngredEffectRefIdAdapter()
|
||||
{}
|
||||
|
||||
void CSMWorld::IngredEffectRefIdAdapter::addNestedRow (const RefIdColumn *column,
|
||||
RefIdData& data, int index, int position) const
|
||||
{
|
||||
// Do nothing, this table cannot be changed by the user
|
||||
}
|
||||
|
||||
void CSMWorld::IngredEffectRefIdAdapter::removeNestedRow (const RefIdColumn *column,
|
||||
RefIdData& data, int index, int rowToRemove) const
|
||||
{
|
||||
// Do nothing, this table cannot be changed by the user
|
||||
}
|
||||
|
||||
void CSMWorld::IngredEffectRefIdAdapter::setNestedTable (const RefIdColumn* column,
|
||||
RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const
|
||||
{
|
||||
Record<ESM::Ingredient>& record =
|
||||
static_cast<Record<ESM::Ingredient>&> (data.getRecord (RefIdData::LocalIndex (index, mType)));
|
||||
ESM::Ingredient ingredient = record.get();
|
||||
|
||||
ingredient.mData =
|
||||
static_cast<const NestedTableWrapper<std::vector<typename ESM::Ingredient::IRDTstruct> >&>(nestedTable).mNestedTable.at(0);
|
||||
|
||||
record.setModified (ingredient);
|
||||
}
|
||||
|
||||
CSMWorld::NestedTableWrapperBase* CSMWorld::IngredEffectRefIdAdapter::nestedTable (const RefIdColumn* column,
|
||||
const RefIdData& data, int index) const
|
||||
{
|
||||
const Record<ESM::Ingredient>& record =
|
||||
static_cast<const Record<ESM::Ingredient>&> (data.getRecord (RefIdData::LocalIndex (index, mType)));
|
||||
|
||||
// return the whole struct
|
||||
std::vector<typename ESM::Ingredient::IRDTstruct> wrap;
|
||||
wrap.push_back(record.get().mData);
|
||||
|
||||
// deleted by dtor of NestedTableStoring
|
||||
return new NestedTableWrapper<std::vector<typename ESM::Ingredient::IRDTstruct> >(wrap);
|
||||
}
|
||||
|
||||
QVariant CSMWorld::IngredEffectRefIdAdapter::getNestedData (const RefIdColumn *column,
|
||||
const RefIdData& data, int index, int subRowIndex, int subColIndex) const
|
||||
{
|
||||
const Record<ESM::Ingredient>& record =
|
||||
static_cast<const Record<ESM::Ingredient>&> (data.getRecord (RefIdData::LocalIndex (index, mType)));
|
||||
|
||||
if (subRowIndex < 0 || subRowIndex >= 4)
|
||||
throw std::runtime_error ("index out of range");
|
||||
|
||||
switch (subColIndex)
|
||||
{
|
||||
case 0: return record.get().mData.mEffectID[subRowIndex];
|
||||
case 1:
|
||||
{
|
||||
switch (record.get().mData.mEffectID[subRowIndex])
|
||||
{
|
||||
case ESM::MagicEffect::DrainSkill:
|
||||
case ESM::MagicEffect::DamageSkill:
|
||||
case ESM::MagicEffect::RestoreSkill:
|
||||
case ESM::MagicEffect::FortifySkill:
|
||||
case ESM::MagicEffect::AbsorbSkill:
|
||||
return record.get().mData.mSkills[subRowIndex];
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
switch (record.get().mData.mEffectID[subRowIndex])
|
||||
{
|
||||
case ESM::MagicEffect::DrainAttribute:
|
||||
case ESM::MagicEffect::DamageAttribute:
|
||||
case ESM::MagicEffect::RestoreAttribute:
|
||||
case ESM::MagicEffect::FortifyAttribute:
|
||||
case ESM::MagicEffect::AbsorbAttribute:
|
||||
return record.get().mData.mAttributes[subRowIndex];
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
default:
|
||||
throw std::runtime_error("Trying to access non-existing column in the nested table!");
|
||||
}
|
||||
}
|
||||
|
||||
void CSMWorld::IngredEffectRefIdAdapter::setNestedData (const RefIdColumn *column,
|
||||
RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const
|
||||
{
|
||||
Record<ESM::Ingredient>& record =
|
||||
static_cast<Record<ESM::Ingredient>&> (data.getRecord (RefIdData::LocalIndex (row, mType)));
|
||||
ESM::Ingredient ingredient = record.get();
|
||||
|
||||
if (subRowIndex < 0 || subRowIndex >= 4)
|
||||
throw std::runtime_error ("index out of range");
|
||||
|
||||
switch(subColIndex)
|
||||
{
|
||||
case 0: ingredient.mData.mEffectID[subRowIndex] = value.toInt(); break;
|
||||
case 1: ingredient.mData.mSkills[subRowIndex] = value.toInt(); break;
|
||||
case 2: ingredient.mData.mAttributes[subRowIndex] = value.toInt(); break;
|
||||
default:
|
||||
throw std::runtime_error("Trying to access non-existing column in the nested table!");
|
||||
}
|
||||
|
||||
record.setModified (ingredient);
|
||||
}
|
||||
|
||||
int CSMWorld::IngredEffectRefIdAdapter::getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const
|
||||
{
|
||||
return 3; // effect, skill, attribute
|
||||
}
|
||||
|
||||
int CSMWorld::IngredEffectRefIdAdapter::getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const
|
||||
{
|
||||
return 4; // up to 4 effects
|
||||
}
|
||||
|
||||
|
||||
CSMWorld::ApparatusRefIdAdapter::ApparatusRefIdAdapter (const InventoryColumns& columns,
|
||||
const RefIdColumn *type, const RefIdColumn *quality)
|
||||
: InventoryRefIdAdapter<ESM::Apparatus> (UniversalId::Type_Apparatus, columns),
|
||||
|
@ -118,7 +271,7 @@ QVariant CSMWorld::ArmorRefIdAdapter::getData (const RefIdColumn *column,
|
|||
return record.get().mData.mArmor;
|
||||
|
||||
if (column==mPartRef)
|
||||
return true; // to show nested tables in dialogue subview, see IdTree::hasChildren()
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
|
||||
return EnchantableRefIdAdapter<ESM::Armor>::getData (column, data, index);
|
||||
}
|
||||
|
@ -206,7 +359,7 @@ QVariant CSMWorld::ClothingRefIdAdapter::getData (const RefIdColumn *column,
|
|||
return record.get().mData.mType;
|
||||
|
||||
if (column==mPartRef)
|
||||
return true; // to show nested tables in dialogue subview, see IdTree::hasChildren()
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
|
||||
return EnchantableRefIdAdapter<ESM::Clothing>::getData (column, data, index);
|
||||
}
|
||||
|
@ -254,7 +407,7 @@ QVariant CSMWorld::ContainerRefIdAdapter::getData (const RefIdColumn *column,
|
|||
return (record.get().mFlags & ESM::Container::Respawn)!=0;
|
||||
|
||||
if (column==mContent)
|
||||
return true; // Required to show nested tables in dialogue subview
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
|
||||
return NameRefIdAdapter<ESM::Container>::getData (column, data, index);
|
||||
}
|
||||
|
@ -323,13 +476,13 @@ QVariant CSMWorld::CreatureRefIdAdapter::getData (const RefIdColumn *column, con
|
|||
return QString::fromUtf8 (record.get().mOriginal.c_str());
|
||||
|
||||
if (column==mColumns.mAttributes)
|
||||
return true; // Required to show nested tables in dialogue subview
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_FixedRows);
|
||||
|
||||
if (column==mColumns.mAttacks)
|
||||
return true; // Required to show nested tables in dialogue subview
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_FixedRows);
|
||||
|
||||
if (column==mColumns.mMisc)
|
||||
return true; // Required to show nested items in dialogue subview
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
|
||||
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
|
||||
mColumns.mFlags.find (column);
|
||||
|
@ -569,13 +722,13 @@ QVariant CSMWorld::NpcRefIdAdapter::getData (const RefIdColumn *column, const Re
|
|||
if (column==mColumns.mAttributes || column==mColumns.mSkills)
|
||||
{
|
||||
if ((record.get().mFlags & ESM::NPC::Autocalc) != 0)
|
||||
return QVariant(QVariant::UserType);
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_None);
|
||||
else
|
||||
return true;
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_FixedRows);
|
||||
}
|
||||
|
||||
if (column==mColumns.mMisc)
|
||||
return true;
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
|
||||
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
|
||||
mColumns.mFlags.find (column);
|
||||
|
@ -1000,7 +1153,7 @@ QVariant CSMWorld::CreatureAttributesRefIdAdapter::getNestedData (const RefIdCol
|
|||
const Record<ESM::Creature>& record =
|
||||
static_cast<const Record<ESM::Creature>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature)));
|
||||
|
||||
const ESM::Creature creature = record.get();
|
||||
const ESM::Creature& creature = record.get();
|
||||
|
||||
if (subColIndex == 0)
|
||||
return subRowIndex;
|
||||
|
@ -1106,7 +1259,7 @@ QVariant CSMWorld::CreatureAttackRefIdAdapter::getNestedData (const RefIdColumn
|
|||
const Record<ESM::Creature>& record =
|
||||
static_cast<const Record<ESM::Creature>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature)));
|
||||
|
||||
const ESM::Creature creature = record.get();
|
||||
const ESM::Creature& creature = record.get();
|
||||
|
||||
if (subRowIndex < 0 || subRowIndex > 2 || subColIndex < 0 || subColIndex > 2)
|
||||
throw std::runtime_error ("index out of range");
|
||||
|
@ -1184,7 +1337,7 @@ QVariant CSMWorld::CreatureMiscRefIdAdapter::getNestedData (const RefIdColumn *c
|
|||
const Record<ESM::Creature>& record =
|
||||
static_cast<const Record<ESM::Creature>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature)));
|
||||
|
||||
const ESM::Creature creature = record.get();
|
||||
const ESM::Creature& creature = record.get();
|
||||
|
||||
switch (subColIndex)
|
||||
{
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <components/esm/loadnpc.hpp>
|
||||
#include <components/esm/loadcrea.hpp>
|
||||
|
||||
#include "columnbase.hpp"
|
||||
#include "record.hpp"
|
||||
#include "refiddata.hpp"
|
||||
#include "universalid.hpp"
|
||||
|
@ -340,6 +341,66 @@ namespace CSMWorld
|
|||
///< If the data type does not match an exception is thrown.
|
||||
};
|
||||
|
||||
struct IngredientColumns : public InventoryColumns
|
||||
{
|
||||
const RefIdColumn *mEffects;
|
||||
|
||||
IngredientColumns (const InventoryColumns& columns);
|
||||
};
|
||||
|
||||
class IngredientRefIdAdapter : public InventoryRefIdAdapter<ESM::Ingredient>
|
||||
{
|
||||
IngredientColumns mColumns;
|
||||
|
||||
public:
|
||||
|
||||
IngredientRefIdAdapter (const IngredientColumns& columns);
|
||||
|
||||
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
|
||||
const;
|
||||
|
||||
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
|
||||
const QVariant& value) const;
|
||||
///< If the data type does not match an exception is thrown.
|
||||
};
|
||||
|
||||
class IngredEffectRefIdAdapter : public NestedRefIdAdapterBase
|
||||
{
|
||||
UniversalId::Type mType;
|
||||
|
||||
// not implemented
|
||||
IngredEffectRefIdAdapter (const IngredEffectRefIdAdapter&);
|
||||
IngredEffectRefIdAdapter& operator= (const IngredEffectRefIdAdapter&);
|
||||
|
||||
public:
|
||||
|
||||
IngredEffectRefIdAdapter();
|
||||
|
||||
virtual ~IngredEffectRefIdAdapter();
|
||||
|
||||
virtual void addNestedRow (const RefIdColumn *column,
|
||||
RefIdData& data, int index, int position) const;
|
||||
|
||||
virtual void removeNestedRow (const RefIdColumn *column,
|
||||
RefIdData& data, int index, int rowToRemove) const;
|
||||
|
||||
virtual void setNestedTable (const RefIdColumn* column,
|
||||
RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const;
|
||||
|
||||
virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column,
|
||||
const RefIdData& data, int index) const;
|
||||
|
||||
virtual QVariant getNestedData (const RefIdColumn *column,
|
||||
const RefIdData& data, int index, int subRowIndex, int subColIndex) const;
|
||||
|
||||
virtual void setNestedData (const RefIdColumn *column,
|
||||
RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const;
|
||||
|
||||
virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const;
|
||||
|
||||
virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const;
|
||||
};
|
||||
|
||||
struct EnchantableColumns : public InventoryColumns
|
||||
{
|
||||
const RefIdColumn *mEnchantment;
|
||||
|
@ -536,16 +597,16 @@ namespace CSMWorld
|
|||
return record.get().mAiData.mAlarm;
|
||||
|
||||
if (column==mActors.mInventory)
|
||||
return true; // to show nested tables in dialogue subview, see IdTree::hasChildren()
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
|
||||
if (column==mActors.mSpells)
|
||||
return true; // to show nested tables in dialogue subview, see IdTree::hasChildren()
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
|
||||
if (column==mActors.mDestinations)
|
||||
return true; // to show nested tables in dialogue subview, see IdTree::hasChildren()
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
|
||||
if (column==mActors.mAiPackages)
|
||||
return true; // to show nested tables in dialogue subview, see IdTree::hasChildren()
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
|
||||
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
|
||||
mActors.mServices.find (column);
|
||||
|
@ -2020,7 +2081,7 @@ namespace CSMWorld
|
|||
int index) const
|
||||
{
|
||||
if (column==mLevList.mLevList || column == mLevList.mNestedListLevList)
|
||||
return true; // to show nested tables in dialogue subview, see IdTree::hasChildren()
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
|
||||
return BaseRefIdAdapter<RecordT>::getData (column, data, index);
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue