mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 12:53:53 +00:00
Merge branch 'cc9cii' into Feature-1278
Conflicts: apps/opencs/CMakeLists.txt apps/opencs/model/world/nestedcoladapterimp.cpp apps/opencs/view/render/cell.cpp apps/opencs/view/render/worldspacewidget.cpp
This commit is contained in:
commit
9716b671f1
502 changed files with 10734 additions and 2688 deletions
|
@ -38,10 +38,10 @@ before_script:
|
||||||
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then ./CI/before_script.osx.sh; fi
|
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then ./CI/before_script.osx.sh; fi
|
||||||
script:
|
script:
|
||||||
- cd ./build
|
- cd ./build
|
||||||
- if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then ${ANALYZE}make -j4; fi
|
- if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then ${ANALYZE}make -j2; fi
|
||||||
- if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi
|
- if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi
|
||||||
after_script:
|
|
||||||
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi
|
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi
|
||||||
|
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then cd .. && ./CI/check_tabs.sh; fi
|
||||||
notifications:
|
notifications:
|
||||||
recipients:
|
recipients:
|
||||||
- corrmage+travis-ci@gmail.com
|
- corrmage+travis-ci@gmail.com
|
||||||
|
|
|
@ -19,6 +19,7 @@ Programmers
|
||||||
Alexander Nadeau (wareya)
|
Alexander Nadeau (wareya)
|
||||||
Alexander Olofsson (Ace)
|
Alexander Olofsson (Ace)
|
||||||
Artem Kotsynyak (greye)
|
Artem Kotsynyak (greye)
|
||||||
|
artemutin
|
||||||
Arthur Moore (EmperorArthur)
|
Arthur Moore (EmperorArthur)
|
||||||
athile
|
athile
|
||||||
Bret Curtis (psi29a)
|
Bret Curtis (psi29a)
|
||||||
|
@ -59,6 +60,7 @@ Programmers
|
||||||
Julien Voisin (jvoisin/ap0)
|
Julien Voisin (jvoisin/ap0)
|
||||||
Karl-Felix Glatzer (k1ll)
|
Karl-Felix Glatzer (k1ll)
|
||||||
Kevin Poitra (PuppyKevin)
|
Kevin Poitra (PuppyKevin)
|
||||||
|
Koncord
|
||||||
Lars Söderberg (Lazaroth)
|
Lars Söderberg (Lazaroth)
|
||||||
lazydev
|
lazydev
|
||||||
Leon Saunders (emoose)
|
Leon Saunders (emoose)
|
||||||
|
@ -109,6 +111,7 @@ Programmers
|
||||||
viadanna
|
viadanna
|
||||||
Vincent Heuken
|
Vincent Heuken
|
||||||
vocollapse
|
vocollapse
|
||||||
|
zelurker
|
||||||
|
|
||||||
Manual
|
Manual
|
||||||
------
|
------
|
||||||
|
|
9
CI/check_tabs.sh
Executable file
9
CI/check_tabs.sh
Executable file
|
@ -0,0 +1,9 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
OUTPUT=$(grep -nRP '\t' --include=\*.{cpp,hpp,c,h} apps components)
|
||||||
|
|
||||||
|
if [[ $OUTPUT ]] ; then
|
||||||
|
echo "Error: Tab characters found!"
|
||||||
|
echo $OUTPUT
|
||||||
|
exit 1
|
||||||
|
fi
|
|
@ -98,25 +98,29 @@ endif()
|
||||||
cmake_minimum_required(VERSION 2.6)
|
cmake_minimum_required(VERSION 2.6)
|
||||||
|
|
||||||
# Sound setup
|
# Sound setup
|
||||||
set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE SWRESAMPLE AVRESAMPLE)
|
|
||||||
unset(FFMPEG_LIBRARIES CACHE)
|
unset(FFMPEG_LIBRARIES CACHE)
|
||||||
find_package(FFmpeg)
|
|
||||||
|
find_package(FFmpeg REQUIRED)
|
||||||
|
|
||||||
|
set (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${SWSCALE_LIBRARY})
|
||||||
|
|
||||||
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 )
|
||||||
message(FATAL_ERROR "FFmpeg component required, but not found!")
|
message(FATAL_ERROR "FFmpeg component required, but not found!")
|
||||||
endif()
|
endif()
|
||||||
set(SOUND_INPUT_INCLUDES ${FFMPEG_INCLUDE_DIRS})
|
set(SOUND_INPUT_INCLUDES ${FFMPEG_INCLUDE_DIRS})
|
||||||
set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES} ${SWSCALE_LIBRARIES})
|
|
||||||
if( SWRESAMPLE_FOUND )
|
if( SWRESAMPLE_FOUND )
|
||||||
add_definitions(-DHAVE_LIBSWRESAMPLE)
|
add_definitions(-DHAVE_LIBSWRESAMPLE)
|
||||||
set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES} ${SWRESAMPLE_LIBRARIES})
|
set (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${SWRESAMPLE_LIBRARIES})
|
||||||
else()
|
else()
|
||||||
if( AVRESAMPLE_FOUND )
|
if( AVRESAMPLE_FOUND )
|
||||||
set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES} ${AVRESAMPLE_LIBRARIES})
|
set (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${AVRESAMPLE_LIBRARIES})
|
||||||
else()
|
else()
|
||||||
message(FATAL_ERROR "Install either libswresample (FFmpeg) or libavresample (Libav).")
|
message(FATAL_ERROR "Install either libswresample (FFmpeg) or libavresample (Libav).")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES})
|
||||||
|
|
||||||
# TinyXML
|
# TinyXML
|
||||||
option(USE_SYSTEM_TINYXML "Use system TinyXML library instead of internal." OFF)
|
option(USE_SYSTEM_TINYXML "Use system TinyXML library instead of internal." OFF)
|
||||||
if(USE_SYSTEM_TINYXML)
|
if(USE_SYSTEM_TINYXML)
|
||||||
|
@ -151,6 +155,19 @@ endif()
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
|
|
||||||
|
set(DESIRED_QT_VERSION 4 CACHE STRING "The QT version OpenMW should use (4 or 5)")
|
||||||
|
message(STATUS "Using Qt${DESIRED_QT_VERSION}")
|
||||||
|
|
||||||
|
if (DESIRED_QT_VERSION MATCHES 4)
|
||||||
|
find_package(Qt4 REQUIRED COMPONENTS QtCore QtGui QtNetwork)
|
||||||
|
else()
|
||||||
|
find_package(Qt5Widgets REQUIRED)
|
||||||
|
find_package(Qt5Core REQUIRED)
|
||||||
|
find_package(Qt5Network REQUIRED)
|
||||||
|
# Instruct CMake to run moc automatically when needed.
|
||||||
|
#set(CMAKE_AUTOMOC ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Fix for not visible pthreads functions for linker with glibc 2.15
|
# Fix for not visible pthreads functions for linker with glibc 2.15
|
||||||
if (UNIX AND NOT APPLE)
|
if (UNIX AND NOT APPLE)
|
||||||
find_package (Threads)
|
find_package (Threads)
|
||||||
|
@ -171,7 +188,7 @@ if (HAVE_UNORDERED_MAP)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
set(BOOST_COMPONENTS system filesystem program_options)
|
set(BOOST_COMPONENTS system filesystem program_options thread wave)
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} locale)
|
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} locale)
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
|
@ -347,6 +364,8 @@ configure_file(${OpenMW_SOURCE_DIR}/files/gamecontrollerdb.txt
|
||||||
if (NOT WIN32 AND NOT APPLE)
|
if (NOT WIN32 AND NOT APPLE)
|
||||||
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.desktop
|
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.desktop
|
||||||
"${OpenMW_BINARY_DIR}/openmw.desktop")
|
"${OpenMW_BINARY_DIR}/openmw.desktop")
|
||||||
|
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.appdata.xml
|
||||||
|
"${OpenMW_BINARY_DIR}/openmw.appdata.xml")
|
||||||
configure_file(${OpenMW_SOURCE_DIR}/files/openmw-cs.desktop
|
configure_file(${OpenMW_SOURCE_DIR}/files/openmw-cs.desktop
|
||||||
"${OpenMW_BINARY_DIR}/openmw-cs.desktop")
|
"${OpenMW_BINARY_DIR}/openmw-cs.desktop")
|
||||||
endif()
|
endif()
|
||||||
|
@ -404,6 +423,9 @@ IF(NOT WIN32 AND NOT APPLE)
|
||||||
IF(BUILD_ESMTOOL)
|
IF(BUILD_ESMTOOL)
|
||||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/esmtool" DESTINATION "${BINDIR}" )
|
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/esmtool" DESTINATION "${BINDIR}" )
|
||||||
ENDIF(BUILD_ESMTOOL)
|
ENDIF(BUILD_ESMTOOL)
|
||||||
|
IF(BUILD_NIFTEST)
|
||||||
|
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/niftest" DESTINATION "${BINDIR}" )
|
||||||
|
ENDIF(BUILD_NIFTEST)
|
||||||
IF(BUILD_MWINIIMPORTER)
|
IF(BUILD_MWINIIMPORTER)
|
||||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw-iniimporter" DESTINATION "${BINDIR}" )
|
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw-iniimporter" DESTINATION "${BINDIR}" )
|
||||||
ENDIF(BUILD_MWINIIMPORTER)
|
ENDIF(BUILD_MWINIIMPORTER)
|
||||||
|
@ -430,6 +452,7 @@ IF(NOT WIN32 AND NOT APPLE)
|
||||||
# Install icon and desktop file
|
# Install icon and desktop file
|
||||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.desktop" DESTINATION "${DATAROOTDIR}/applications" COMPONENT "openmw")
|
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.desktop" DESTINATION "${DATAROOTDIR}/applications" COMPONENT "openmw")
|
||||||
INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.png" DESTINATION "${ICONDIR}" COMPONENT "openmw")
|
INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.png" DESTINATION "${ICONDIR}" COMPONENT "openmw")
|
||||||
|
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.appdata.xml" DESTINATION "${DATAROOTDIR}/appdata" COMPONENT "openmw")
|
||||||
IF(BUILD_OPENCS)
|
IF(BUILD_OPENCS)
|
||||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw-cs.desktop" DESTINATION "${DATAROOTDIR}/applications" COMPONENT "opencs")
|
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw-cs.desktop" DESTINATION "${DATAROOTDIR}/applications" COMPONENT "opencs")
|
||||||
INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/opencs/openmw-cs.png" DESTINATION "${ICONDIR}" COMPONENT "opencs")
|
INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/opencs/openmw-cs.png" DESTINATION "${ICONDIR}" COMPONENT "opencs")
|
||||||
|
@ -600,6 +623,10 @@ if (BUILD_WIZARD)
|
||||||
add_subdirectory(apps/wizard)
|
add_subdirectory(apps/wizard)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (BUILD_NIFTEST)
|
||||||
|
add_subdirectory(apps/niftest)
|
||||||
|
endif(BUILD_NIFTEST)
|
||||||
|
|
||||||
# UnitTests
|
# UnitTests
|
||||||
if (BUILD_UNITTESTS)
|
if (BUILD_UNITTESTS)
|
||||||
add_subdirectory( apps/openmw_test_suite )
|
add_subdirectory( apps/openmw_test_suite )
|
||||||
|
|
16
CONTRIBUTING.md
Normal file
16
CONTRIBUTING.md
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
Description
|
||||||
|
===========
|
||||||
|
|
||||||
|
Your pull request description should include (if applicable):
|
||||||
|
|
||||||
|
* A link back to the bug report or forum discussion that prompted the change
|
||||||
|
* Summary of the changes made
|
||||||
|
* Reasoning / motivation behind the change
|
||||||
|
* What testing you have carried out to verify the change
|
||||||
|
|
||||||
|
Other notes
|
||||||
|
===========
|
||||||
|
|
||||||
|
* Separate your work into multiple pull requests whenever possible. As a rule of thumb, each feature and each bugfix should go into a separate PR, unless they are closely related or dependent upon each other. Small pull requests are easier to review, and are less likely to require further changes before we can merge them. A "mega" pull request with lots of unrelated commits in it is likely to get held up in review for a long time.
|
||||||
|
* Feel free to submit incomplete pull requests. Even if the work can not be merged yet, pull requests are a great place to collect early feedback. Just make sure to mark it as *[Incomplete]* or *[Do not merge yet]* in the title.
|
||||||
|
* If you plan on contributing often, please read the [Developer Reference](https://wiki.openmw.org/index.php?title=Developer_Reference) on our wiki, especially the [Policies and Standards](https://wiki.openmw.org/index.php?title=Policies_and_Standards).
|
|
@ -9,7 +9,8 @@ add_executable(bsatool
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(bsatool
|
target_link_libraries(bsatool
|
||||||
${Boost_LIBRARIES}
|
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||||
|
${Boost_FILESYSTEM_LIBRARY}
|
||||||
components
|
components
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ add_executable(esmtool
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(esmtool
|
target_link_libraries(esmtool
|
||||||
${Boost_LIBRARIES}
|
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||||
components
|
components
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -830,12 +830,12 @@ std::string npcFlags(int flags)
|
||||||
std::string properties = "";
|
std::string properties = "";
|
||||||
if (flags == 0) properties += "[None] ";
|
if (flags == 0) properties += "[None] ";
|
||||||
// Mythicmods and the ESM component differ. Mythicmods says
|
// Mythicmods and the ESM component differ. Mythicmods says
|
||||||
// 0x8=None and 0x10=AutoCalc, while our code defines 0x8 as
|
// 0x8=None and 0x10=AutoCalc, while our code previously defined
|
||||||
// AutoCalc. The former seems to be correct. All Bethesda
|
// 0x8 as AutoCalc. The former seems to be correct. All Bethesda
|
||||||
// records have bit 0x8 set. A suspiciously large portion of
|
// records have bit 0x8 set. Previously, suspiciously large portion
|
||||||
// females have autocalc turned off.
|
// of females had autocalc turned off.
|
||||||
if (flags & ESM::NPC::Autocalc) properties += "Unknown ";
|
if (flags & 0x00000008) properties += "Unknown ";
|
||||||
if (flags & 0x00000010) properties += "Autocalc ";
|
if (flags & ESM::NPC::Autocalc) properties += "Autocalc ";
|
||||||
if (flags & ESM::NPC::Female) properties += "Female ";
|
if (flags & ESM::NPC::Female) properties += "Female ";
|
||||||
if (flags & ESM::NPC::Respawn) properties += "Respawn ";
|
if (flags & ESM::NPC::Respawn) properties += "Respawn ";
|
||||||
if (flags & ESM::NPC::Essential) properties += "Essential ";
|
if (flags & ESM::NPC::Essential) properties += "Essential ";
|
||||||
|
@ -847,8 +847,8 @@ std::string npcFlags(int flags)
|
||||||
// however the only unknown bit occurs on ALL records, and
|
// however the only unknown bit occurs on ALL records, and
|
||||||
// relatively few NPCs have this bit set.
|
// relatively few NPCs have this bit set.
|
||||||
int unused = (0xFFFFFFFF ^
|
int unused = (0xFFFFFFFF ^
|
||||||
(ESM::NPC::Autocalc|
|
(0x00000008|
|
||||||
0x00000010|
|
ESM::NPC::Autocalc|
|
||||||
ESM::NPC::Female|
|
ESM::NPC::Female|
|
||||||
ESM::NPC::Respawn|
|
ESM::NPC::Respawn|
|
||||||
ESM::NPC::Essential|
|
ESM::NPC::Essential|
|
||||||
|
|
|
@ -841,19 +841,13 @@ void Record<ESM::Land>::print()
|
||||||
std::cout << " Flags: " << landFlags(mData.mFlags) << std::endl;
|
std::cout << " Flags: " << landFlags(mData.mFlags) << std::endl;
|
||||||
std::cout << " DataTypes: " << mData.mDataTypes << std::endl;
|
std::cout << " DataTypes: " << mData.mDataTypes << std::endl;
|
||||||
|
|
||||||
// Seems like this should done with reference counting in the
|
if (const ESM::Land::LandData *data = mData.getLandData (mData.mDataTypes))
|
||||||
// loader to me. But I'm not really knowledgable about this
|
|
||||||
// record type yet. --Cory
|
|
||||||
bool wasLoaded = (mData.mDataLoaded != 0);
|
|
||||||
if (mData.mDataTypes) mData.loadData(mData.mDataTypes);
|
|
||||||
if (mData.mDataLoaded)
|
|
||||||
{
|
{
|
||||||
std::cout << " Height Offset: " << mData.mLandData->mHeightOffset << std::endl;
|
std::cout << " Height Offset: " << data->mHeightOffset << std::endl;
|
||||||
// Lots of missing members.
|
// Lots of missing members.
|
||||||
std::cout << " Unknown1: " << mData.mLandData->mUnk1 << std::endl;
|
std::cout << " Unknown1: " << data->mUnk1 << std::endl;
|
||||||
std::cout << " Unknown2: " << mData.mLandData->mUnk2 << std::endl;
|
std::cout << " Unknown2: " << data->mUnk2 << std::endl;
|
||||||
}
|
}
|
||||||
if (!wasLoaded) mData.unloadData();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
|
|
@ -33,7 +33,8 @@ add_executable(openmw-essimporter
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(openmw-essimporter
|
target_link_libraries(openmw-essimporter
|
||||||
${Boost_LIBRARIES}
|
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||||
|
${Boost_FILESYSTEM_LIBRARY}
|
||||||
components
|
components
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -41,9 +41,9 @@ namespace ESSImport
|
||||||
{
|
{
|
||||||
for (int i=0; i<ESM::Skill::Length; ++i)
|
for (int i=0; i<ESM::Skill::Length; ++i)
|
||||||
{
|
{
|
||||||
npcStats.mSkills[i].mRegular.mMod = actorData.mSkills[i][1];
|
npcStats.mSkills[i].mMod = actorData.mSkills[i][1];
|
||||||
npcStats.mSkills[i].mRegular.mCurrent = actorData.mSkills[i][1];
|
npcStats.mSkills[i].mCurrent = actorData.mSkills[i][1];
|
||||||
npcStats.mSkills[i].mRegular.mBase = actorData.mSkills[i][0];
|
npcStats.mSkills[i].mBase = actorData.mSkills[i][0];
|
||||||
}
|
}
|
||||||
|
|
||||||
npcStats.mTimeToStartDrowning = actorData.mACDT.mBreathMeter;
|
npcStats.mTimeToStartDrowning = actorData.mACDT.mBreathMeter;
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace ESSImport
|
||||||
for (int i=0; i<8; ++i)
|
for (int i=0; i<8; ++i)
|
||||||
out.mObject.mNpcStats.mSkillIncrease[i] = pcdt.mPNAM.mSkillIncreases[i];
|
out.mObject.mNpcStats.mSkillIncrease[i] = pcdt.mPNAM.mSkillIncreases[i];
|
||||||
for (int i=0; i<27; ++i)
|
for (int i=0; i<27; ++i)
|
||||||
out.mObject.mNpcStats.mSkills[i].mRegular.mProgress = pcdt.mPNAM.mSkillProgress[i];
|
out.mObject.mNpcStats.mSkills[i].mProgress = pcdt.mPNAM.mSkillProgress[i];
|
||||||
out.mObject.mNpcStats.mLevelProgress = pcdt.mPNAM.mLevelProgress;
|
out.mObject.mNpcStats.mLevelProgress = pcdt.mPNAM.mLevelProgress;
|
||||||
|
|
||||||
if (pcdt.mPNAM.mDrawState & PCDT::DrawState_Weapon)
|
if (pcdt.mPNAM.mDrawState & PCDT::DrawState_Weapon)
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
#include "importer.hpp"
|
#include "importer.hpp"
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
#include <OgreRoot.h>
|
#include <OgreRoot.h>
|
||||||
|
#include <OgreLogManager.h>
|
||||||
|
|
||||||
#include <components/esm/esmreader.hpp>
|
#include <components/esm/esmreader.hpp>
|
||||||
#include <components/esm/esmwriter.hpp>
|
#include <components/esm/esmwriter.hpp>
|
||||||
|
@ -292,7 +296,7 @@ namespace ESSImport
|
||||||
|
|
||||||
ESM::ESMWriter writer;
|
ESM::ESMWriter writer;
|
||||||
|
|
||||||
writer.setFormat (ESM::Header::CurrentFormat);
|
writer.setFormat (ESM::SavedGame::sCurrentFormat);
|
||||||
|
|
||||||
std::ofstream stream(mOutFile.c_str(), std::ios::binary);
|
std::ofstream stream(mOutFile.c_str(), std::ios::binary);
|
||||||
// all unused
|
// all unused
|
||||||
|
|
|
@ -57,7 +57,6 @@ set(LAUNCHER_UI
|
||||||
|
|
||||||
source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER})
|
source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER})
|
||||||
|
|
||||||
find_package(Qt4 REQUIRED)
|
|
||||||
set(QT_USE_QTGUI 1)
|
set(QT_USE_QTGUI 1)
|
||||||
|
|
||||||
# Set some platform specific settings
|
# Set some platform specific settings
|
||||||
|
@ -66,12 +65,17 @@ if(WIN32)
|
||||||
set(QT_USE_QTMAIN TRUE)
|
set(QT_USE_QTMAIN TRUE)
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
|
|
||||||
QT4_ADD_RESOURCES(RCC_SRCS ${CMAKE_SOURCE_DIR}/files/launcher/launcher.qrc)
|
if (DESIRED_QT_VERSION MATCHES 4)
|
||||||
QT4_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC})
|
include(${QT_USE_FILE})
|
||||||
QT4_WRAP_UI(UI_HDRS ${LAUNCHER_UI})
|
QT4_ADD_RESOURCES(RCC_SRCS ${CMAKE_SOURCE_DIR}/files/launcher/launcher.qrc)
|
||||||
|
QT4_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC})
|
||||||
|
QT4_WRAP_UI(UI_HDRS ${LAUNCHER_UI})
|
||||||
|
else()
|
||||||
|
QT5_ADD_RESOURCES(RCC_SRCS ${CMAKE_SOURCE_DIR}/files/launcher/launcher.qrc)
|
||||||
|
QT5_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC})
|
||||||
|
QT5_WRAP_UI(UI_HDRS ${LAUNCHER_UI})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
include(${QT_USE_FILE})
|
|
||||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||||
if(NOT WIN32)
|
if(NOT WIN32)
|
||||||
include_directories(${LIBUNSHIELD_INCLUDE_DIR})
|
include_directories(${LIBUNSHIELD_INCLUDE_DIR})
|
||||||
|
@ -88,17 +92,27 @@ add_executable(openmw-launcher
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(openmw-launcher
|
target_link_libraries(openmw-launcher
|
||||||
${Boost_LIBRARIES}
|
|
||||||
${OGRE_LIBRARIES}
|
${OGRE_LIBRARIES}
|
||||||
${OGRE_STATIC_PLUGINS}
|
${OGRE_STATIC_PLUGINS}
|
||||||
${SDL2_LIBRARY_ONLY}
|
${SDL2_LIBRARY_ONLY}
|
||||||
${QT_LIBRARIES}
|
|
||||||
components
|
components
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (DESIRED_QT_VERSION MATCHES 4)
|
||||||
|
target_link_libraries(openmw-launcher ${QT_QTGUI_LIBRARY} ${QT_QTCORE_LIBRARY})
|
||||||
|
if(WIN32)
|
||||||
|
target_link_libraries(openmw-launcher ${QT_QTMAIN_LIBRARY})
|
||||||
|
endif(WIN32)
|
||||||
|
else()
|
||||||
|
qt5_use_modules(openmw-launcher Widgets Core)
|
||||||
|
if (WIN32)
|
||||||
|
target_link_libraries(Qt5::WinMain)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
if (BUILD_WITH_CODE_COVERAGE)
|
if (BUILD_WITH_CODE_COVERAGE)
|
||||||
add_definitions (--coverage)
|
add_definitions (--coverage)
|
||||||
target_link_libraries(openmw-launcher gcov)
|
target_link_libraries(openmw-launcher gcov)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -54,9 +54,6 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
QDir::setCurrent(dir.absolutePath());
|
QDir::setCurrent(dir.absolutePath());
|
||||||
|
|
||||||
// Support non-latin characters
|
|
||||||
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
|
|
||||||
|
|
||||||
Launcher::MainDialog mainWin;
|
Launcher::MainDialog mainWin;
|
||||||
|
|
||||||
Launcher::FirstRunDialogResult result = mainWin.showFirstRunDialog();
|
Launcher::FirstRunDialogResult result = mainWin.showFirstRunDialog();
|
||||||
|
|
|
@ -309,11 +309,11 @@ bool Launcher::MainDialog::setupGameSettings()
|
||||||
mGameSettings.readUserFile(stream);
|
mGameSettings.readUserFile(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now the rest
|
// Now the rest - priority: user > local > global
|
||||||
QStringList paths;
|
QStringList paths;
|
||||||
paths.append(userPath + QString("openmw.cfg"));
|
|
||||||
paths.append(QString("openmw.cfg"));
|
|
||||||
paths.append(globalPath + QString("openmw.cfg"));
|
paths.append(globalPath + QString("openmw.cfg"));
|
||||||
|
paths.append(QString("openmw.cfg"));
|
||||||
|
paths.append(userPath + QString("openmw.cfg"));
|
||||||
|
|
||||||
foreach (const QString &path, paths) {
|
foreach (const QString &path, paths) {
|
||||||
qDebug() << "Loading config file:" << qPrintable(path);
|
qDebug() << "Loading config file:" << qPrintable(path);
|
||||||
|
|
|
@ -14,10 +14,16 @@ add_executable(openmw-iniimporter
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(openmw-iniimporter
|
target_link_libraries(openmw-iniimporter
|
||||||
${Boost_LIBRARIES}
|
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||||
|
${Boost_FILESYSTEM_LIBRARY}
|
||||||
components
|
components
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
target_link_libraries(openmw-iniimporter
|
||||||
|
${Boost_LOCALE_LIBRARY})
|
||||||
|
endif()
|
||||||
|
|
||||||
if (MINGW)
|
if (MINGW)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -municode")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -municode")
|
||||||
endif()
|
endif()
|
||||||
|
|
19
apps/niftest/CMakeLists.txt
Normal file
19
apps/niftest/CMakeLists.txt
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
set(NIFTEST
|
||||||
|
niftest.cpp
|
||||||
|
)
|
||||||
|
source_group(components\\nif\\tests FILES ${NIFTEST})
|
||||||
|
|
||||||
|
# Main executable
|
||||||
|
add_executable(niftest
|
||||||
|
${NIFTEST}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(niftest
|
||||||
|
${Boost_FILESYSTEM_LIBRARY}
|
||||||
|
components
|
||||||
|
)
|
||||||
|
|
||||||
|
if (BUILD_WITH_CODE_COVERAGE)
|
||||||
|
add_definitions (--coverage)
|
||||||
|
target_link_libraries(niftest gcov)
|
||||||
|
endif()
|
165
apps/niftest/niftest.cpp
Normal file
165
apps/niftest/niftest.cpp
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
///Program to test .nif files both on the FileSystem and in BSA archives.
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include <components/nif/niffile.hpp>
|
||||||
|
#include <components/files/constrainedfilestream.hpp>
|
||||||
|
#include <components/vfs/manager.hpp>
|
||||||
|
#include <components/vfs/bsaarchive.hpp>
|
||||||
|
#include <components/vfs/filesystemarchive.hpp>
|
||||||
|
|
||||||
|
#include <boost/program_options.hpp>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
|
// Create local aliases for brevity
|
||||||
|
namespace bpo = boost::program_options;
|
||||||
|
namespace bfs = boost::filesystem;
|
||||||
|
|
||||||
|
///See if the file has the named extension
|
||||||
|
bool hasExtension(std::string filename, std::string extensionToFind)
|
||||||
|
{
|
||||||
|
std::string extension = filename.substr(filename.find_last_of(".")+1);
|
||||||
|
|
||||||
|
//Convert strings to lower case for comparison
|
||||||
|
std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
|
||||||
|
std::transform(extensionToFind.begin(), extensionToFind.end(), extensionToFind.begin(), ::tolower);
|
||||||
|
|
||||||
|
if(extension == extensionToFind)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
///See if the file has the "nif" extension.
|
||||||
|
bool isNIF(std::string filename)
|
||||||
|
{
|
||||||
|
return hasExtension(filename,"nif");
|
||||||
|
}
|
||||||
|
///See if the file has the "bsa" extension.
|
||||||
|
bool isBSA(std::string filename)
|
||||||
|
{
|
||||||
|
return hasExtension(filename,"bsa");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check all the nif files in a given VFS::Archive
|
||||||
|
/// \note Takes ownership!
|
||||||
|
/// \note Can not read a bsa file inside of a bsa file.
|
||||||
|
void readVFS(VFS::Archive* anArchive,std::string archivePath = "")
|
||||||
|
{
|
||||||
|
VFS::Manager myManager(true);
|
||||||
|
myManager.addArchive(anArchive);
|
||||||
|
myManager.buildIndex();
|
||||||
|
|
||||||
|
std::map<std::string, VFS::File*> files=myManager.getIndex();
|
||||||
|
for(std::map<std::string, VFS::File*>::const_iterator it=files.begin(); it!=files.end(); ++it)
|
||||||
|
{
|
||||||
|
std::string name = it->first;
|
||||||
|
|
||||||
|
try{
|
||||||
|
if(isNIF(name))
|
||||||
|
{
|
||||||
|
// std::cout << "Decoding: " << name << std::endl;
|
||||||
|
Nif::NIFFile temp_nif(myManager.get(name),archivePath+name);
|
||||||
|
}
|
||||||
|
else if(isBSA(name))
|
||||||
|
{
|
||||||
|
if(!archivePath.empty() && !isBSA(archivePath))
|
||||||
|
{
|
||||||
|
// std::cout << "Reading BSA File: " << name << std::endl;
|
||||||
|
readVFS(new VFS::BsaArchive(archivePath+name),archivePath+name+"/");
|
||||||
|
// std::cout << "Done with BSA File: " << name << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
std::cerr << "ERROR, an exception has occurred: " << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> parseOptions (int argc, char** argv)
|
||||||
|
{
|
||||||
|
bpo::options_description desc("Ensure that OpenMW can use the provided NIF and BSA files\n\n"
|
||||||
|
"Usages:\n"
|
||||||
|
" niftool <nif files, BSA files, or directories>\n"
|
||||||
|
" Scan the file or directories for nif errors.\n\n"
|
||||||
|
"Allowed options");
|
||||||
|
desc.add_options()
|
||||||
|
("help,h", "print help message.")
|
||||||
|
("input-file", bpo::value< std::vector<std::string> >(), "input file")
|
||||||
|
;
|
||||||
|
|
||||||
|
//Default option if none provided
|
||||||
|
bpo::positional_options_description p;
|
||||||
|
p.add("input-file", -1);
|
||||||
|
|
||||||
|
bpo::variables_map variables;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
bpo::parsed_options valid_opts = bpo::command_line_parser(argc, argv).
|
||||||
|
options(desc).positional(p).run();
|
||||||
|
bpo::store(valid_opts, variables);
|
||||||
|
}
|
||||||
|
catch(std::exception &e)
|
||||||
|
{
|
||||||
|
std::cout << "ERROR parsing arguments: " << e.what() << "\n\n"
|
||||||
|
<< desc << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bpo::notify(variables);
|
||||||
|
if (variables.count ("help"))
|
||||||
|
{
|
||||||
|
std::cout << desc << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (variables.count("input-file"))
|
||||||
|
{
|
||||||
|
return variables["input-file"].as< std::vector<std::string> >();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "No input files or directories specified!" << std::endl;
|
||||||
|
std::cout << desc << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
std::vector<std::string> files = parseOptions (argc, argv);
|
||||||
|
|
||||||
|
// std::cout << "Reading Files" << std::endl;
|
||||||
|
for(std::vector<std::string>::const_iterator it=files.begin(); it!=files.end(); ++it)
|
||||||
|
{
|
||||||
|
std::string name = *it;
|
||||||
|
|
||||||
|
try{
|
||||||
|
if(isNIF(name))
|
||||||
|
{
|
||||||
|
//std::cout << "Decoding: " << name << std::endl;
|
||||||
|
Nif::NIFFile temp_nif(Files::openConstrainedFileStream(name.c_str()),name);
|
||||||
|
}
|
||||||
|
else if(isBSA(name))
|
||||||
|
{
|
||||||
|
// std::cout << "Reading BSA File: " << name << std::endl;
|
||||||
|
readVFS(new VFS::BsaArchive(name));
|
||||||
|
}
|
||||||
|
else if(bfs::is_directory(bfs::path(name)))
|
||||||
|
{
|
||||||
|
// std::cout << "Reading All Files in: " << name << std::endl;
|
||||||
|
readVFS(new VFS::FileSystemArchive(name),name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "ERROR: \"" << name << "\" is not a nif file, bsa file, or directory!" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
std::cerr << "ERROR, an exception has occurred: " << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -18,16 +18,16 @@ opencs_hdrs_noqt (model/doc
|
||||||
|
|
||||||
|
|
||||||
opencs_units (model/world
|
opencs_units (model/world
|
||||||
idtable idtableproxymodel regionmap data commanddispatcher idtablebase resourcetable
|
idtable idtableproxymodel regionmap data commanddispatcher idtablebase resourcetable nestedtableproxymodel idtree infotableproxymodel
|
||||||
nestedtableproxymodel idtree pathgridcommands
|
pathgridcommands
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
opencs_units_noqt (model/world
|
opencs_units_noqt (model/world
|
||||||
universalid record commands columnbase scriptcontext cell refidcollection
|
universalid record commands columnbase columnimp scriptcontext cell refidcollection
|
||||||
refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection resources resourcesmanager scope
|
refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection resources resourcesmanager scope
|
||||||
pathgrid landtexture land nestedtablewrapper nestedcollection nestedcoladapterimp nestedinfocollection
|
pathgrid landtexture land nestedtablewrapper nestedcollection nestedcoladapterimp nestedinfocollection
|
||||||
idcompletionmanager
|
idcompletionmanager npcstats metadata
|
||||||
)
|
)
|
||||||
|
|
||||||
opencs_hdrs_noqt (model/world
|
opencs_hdrs_noqt (model/world
|
||||||
|
@ -36,13 +36,18 @@ opencs_hdrs_noqt (model/world
|
||||||
|
|
||||||
|
|
||||||
opencs_units (model/tools
|
opencs_units (model/tools
|
||||||
tools reportmodel
|
tools reportmodel mergeoperation
|
||||||
)
|
)
|
||||||
|
|
||||||
opencs_units_noqt (model/tools
|
opencs_units_noqt (model/tools
|
||||||
mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck
|
mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck
|
||||||
birthsigncheck spellcheck referencecheck referenceablecheck scriptcheck bodypartcheck
|
birthsigncheck spellcheck referencecheck referenceablecheck scriptcheck bodypartcheck
|
||||||
startscriptcheck search searchoperation searchstage pathgridcheck
|
startscriptcheck search searchoperation searchstage pathgridcheck soundgencheck magiceffectcheck
|
||||||
|
mergestages
|
||||||
|
)
|
||||||
|
|
||||||
|
opencs_hdrs_noqt (model/tools
|
||||||
|
mergestate
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -63,19 +68,20 @@ opencs_hdrs_noqt (view/doc
|
||||||
|
|
||||||
opencs_units (view/world
|
opencs_units (view/world
|
||||||
table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator
|
table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator
|
||||||
cellcreator referenceablecreator referencecreator scenesubview
|
cellcreator referenceablecreator startscriptcreator referencecreator scenesubview
|
||||||
infocreator scriptedit dialoguesubview previewsubview regionmap dragrecordtable nestedtable
|
infocreator scriptedit dialoguesubview previewsubview regionmap dragrecordtable nestedtable
|
||||||
dialoguespinbox
|
dialoguespinbox recordbuttonbar tableeditidaction scripterrortable extendedcommandconfigurator
|
||||||
)
|
)
|
||||||
|
|
||||||
opencs_units_noqt (view/world
|
opencs_units_noqt (view/world
|
||||||
subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate
|
subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate
|
||||||
scripthighlighter idvalidator dialoguecreator physicssystem idcompletiondelegate
|
scripthighlighter idvalidator dialoguecreator physicssystem idcompletiondelegate
|
||||||
|
colordelegate dragdroputils
|
||||||
)
|
)
|
||||||
|
|
||||||
opencs_units (view/widget
|
opencs_units (view/widget
|
||||||
scenetoolbar scenetool scenetoolmode pushbutton scenetooltoggle scenetoolrun modebutton
|
scenetoolbar scenetool scenetoolmode pushbutton scenetooltoggle scenetoolrun modebutton
|
||||||
scenetooltoggle2 completerpopup
|
scenetooltoggle2 completerpopup coloreditor colorpickerpopup droplineedit
|
||||||
)
|
)
|
||||||
|
|
||||||
opencs_units (view/render
|
opencs_units (view/render
|
||||||
|
@ -95,7 +101,7 @@ opencs_hdrs_noqt (view/render
|
||||||
|
|
||||||
|
|
||||||
opencs_units (view/tools
|
opencs_units (view/tools
|
||||||
reportsubview reporttable searchsubview searchbox
|
reportsubview reporttable searchsubview searchbox merge
|
||||||
)
|
)
|
||||||
|
|
||||||
opencs_units_noqt (view/tools
|
opencs_units_noqt (view/tools
|
||||||
|
@ -155,19 +161,16 @@ if(WIN32)
|
||||||
set(QT_USE_QTMAIN TRUE)
|
set(QT_USE_QTMAIN TRUE)
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
|
|
||||||
set(BOOST_COMPONENTS system filesystem program_options thread wave)
|
if (DESIRED_QT_VERSION MATCHES 4)
|
||||||
if(WIN32)
|
include(${QT_USE_FILE})
|
||||||
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} locale)
|
qt4_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI})
|
||||||
endif(WIN32)
|
qt4_wrap_cpp(OPENCS_MOC_SRC ${OPENCS_HDR_QT})
|
||||||
|
qt4_add_resources(OPENCS_RES_SRC ${OPENCS_RES})
|
||||||
find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS})
|
else()
|
||||||
|
qt5_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI})
|
||||||
find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork REQUIRED)
|
qt5_wrap_cpp(OPENCS_MOC_SRC ${OPENCS_HDR_QT})
|
||||||
include(${QT_USE_FILE})
|
qt5_add_resources(OPENCS_RES_SRC ${OPENCS_RES})
|
||||||
|
endif()
|
||||||
qt4_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI})
|
|
||||||
qt4_wrap_cpp(OPENCS_MOC_SRC ${OPENCS_HDR_QT})
|
|
||||||
qt4_add_resources(OPENCS_RES_SRC ${OPENCS_RES})
|
|
||||||
|
|
||||||
# for compiled .ui files
|
# for compiled .ui files
|
||||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
@ -208,12 +211,36 @@ target_link_libraries(openmw-cs
|
||||||
${OGRE_Overlay_LIBRARIES}
|
${OGRE_Overlay_LIBRARIES}
|
||||||
${OGRE_STATIC_PLUGINS}
|
${OGRE_STATIC_PLUGINS}
|
||||||
${SHINY_LIBRARIES}
|
${SHINY_LIBRARIES}
|
||||||
${Boost_LIBRARIES}
|
${Boost_SYSTEM_LIBRARY}
|
||||||
|
${Boost_FILESYSTEM_LIBRARY}
|
||||||
|
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||||
|
${Boost_WAVE_LIBRARY}
|
||||||
${BULLET_LIBRARIES}
|
${BULLET_LIBRARIES}
|
||||||
${QT_LIBRARIES}
|
|
||||||
components
|
components
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (DESIRED_QT_VERSION MATCHES 4)
|
||||||
|
target_link_libraries(openmw-cs
|
||||||
|
${QT_QTGUI_LIBRARY}
|
||||||
|
${QT_QTCORE_LIBRARY}
|
||||||
|
${QT_QTNETWORK_LIBRARY})
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
target_link_libraries(openmw-cs ${QT_QTMAIN_LIBRARY})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
else()
|
||||||
|
qt5_use_modules(openmw-cs Widgets Core Network)
|
||||||
|
if (WIN32)
|
||||||
|
target_link_libraries(Qt5::WinMain)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
target_link_libraries(openmw-cs ${Boost_LOCALE_LIBRARY})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
INSTALL(TARGETS openmw-cs BUNDLE DESTINATION OpenMW COMPONENT BUNDLE)
|
INSTALL(TARGETS openmw-cs BUNDLE DESTINATION OpenMW COMPONENT BUNDLE)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "editor.hpp"
|
#include "editor.hpp"
|
||||||
|
|
||||||
#include <openengine/bullet/BulletShapeLoader.h>
|
#include <openengine/bullet/BulletShapeLoader.h>
|
||||||
|
@ -7,6 +6,9 @@
|
||||||
#include <QLocalServer>
|
#include <QLocalServer>
|
||||||
#include <QLocalSocket>
|
#include <QLocalSocket>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <QSplashScreen>
|
||||||
|
#include <QFont>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
#include <OgreRoot.h>
|
#include <OgreRoot.h>
|
||||||
#include <OgreRenderWindow.h>
|
#include <OgreRenderWindow.h>
|
||||||
|
@ -24,7 +26,8 @@
|
||||||
CS::Editor::Editor (OgreInit::OgreInit& ogreInit)
|
CS::Editor::Editor (OgreInit::OgreInit& ogreInit)
|
||||||
: mUserSettings (mCfgMgr), mOverlaySystem (0), mDocumentManager (mCfgMgr),
|
: mUserSettings (mCfgMgr), mOverlaySystem (0), mDocumentManager (mCfgMgr),
|
||||||
mViewManager (mDocumentManager), mPid(""),
|
mViewManager (mDocumentManager), mPid(""),
|
||||||
mLock(), mIpcServerName ("org.openmw.OpenCS"), mServer(NULL), mClientSocket(NULL)
|
mLock(), mMerge (mDocumentManager),
|
||||||
|
mIpcServerName ("org.openmw.OpenCS"), mServer(NULL), mClientSocket(NULL)
|
||||||
{
|
{
|
||||||
std::pair<Files::PathContainer, std::vector<std::string> > config = readConfig();
|
std::pair<Files::PathContainer, std::vector<std::string> > config = readConfig();
|
||||||
|
|
||||||
|
@ -46,9 +49,12 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit)
|
||||||
|
|
||||||
mNewGame.setLocalData (mLocal);
|
mNewGame.setLocalData (mLocal);
|
||||||
mFileDialog.setLocalData (mLocal);
|
mFileDialog.setLocalData (mLocal);
|
||||||
|
mMerge.setLocalData (mLocal);
|
||||||
|
|
||||||
connect (&mDocumentManager, SIGNAL (documentAdded (CSMDoc::Document *)),
|
connect (&mDocumentManager, SIGNAL (documentAdded (CSMDoc::Document *)),
|
||||||
this, SLOT (documentAdded (CSMDoc::Document *)));
|
this, SLOT (documentAdded (CSMDoc::Document *)));
|
||||||
|
connect (&mDocumentManager, SIGNAL (documentAboutToBeRemoved (CSMDoc::Document *)),
|
||||||
|
this, SLOT (documentAboutToBeRemoved (CSMDoc::Document *)));
|
||||||
connect (&mDocumentManager, SIGNAL (lastDocumentDeleted()),
|
connect (&mDocumentManager, SIGNAL (lastDocumentDeleted()),
|
||||||
this, SLOT (lastDocumentDeleted()));
|
this, SLOT (lastDocumentDeleted()));
|
||||||
|
|
||||||
|
@ -56,6 +62,7 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit)
|
||||||
connect (&mViewManager, SIGNAL (newAddonRequest ()), this, SLOT (createAddon ()));
|
connect (&mViewManager, SIGNAL (newAddonRequest ()), this, SLOT (createAddon ()));
|
||||||
connect (&mViewManager, SIGNAL (loadDocumentRequest ()), this, SLOT (loadDocument ()));
|
connect (&mViewManager, SIGNAL (loadDocumentRequest ()), this, SLOT (loadDocument ()));
|
||||||
connect (&mViewManager, SIGNAL (editSettingsRequest()), this, SLOT (showSettings ()));
|
connect (&mViewManager, SIGNAL (editSettingsRequest()), this, SLOT (showSettings ()));
|
||||||
|
connect (&mViewManager, SIGNAL (mergeDocument (CSMDoc::Document *)), this, SLOT (mergeDocument (CSMDoc::Document *)));
|
||||||
|
|
||||||
connect (&mStartup, SIGNAL (createGame()), this, SLOT (createGame ()));
|
connect (&mStartup, SIGNAL (createGame()), this, SLOT (createGame ()));
|
||||||
connect (&mStartup, SIGNAL (createAddon()), this, SLOT (createAddon ()));
|
connect (&mStartup, SIGNAL (createAddon()), this, SLOT (createAddon ()));
|
||||||
|
@ -95,7 +102,7 @@ void CS::Editor::setupDataFiles (const Files::PathContainer& dataDirs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfig()
|
std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfig(bool quiet)
|
||||||
{
|
{
|
||||||
boost::program_options::variables_map variables;
|
boost::program_options::variables_map variables;
|
||||||
boost::program_options::options_description desc("Syntax: openmw-cs <options>\nAllowed options");
|
boost::program_options::options_description desc("Syntax: openmw-cs <options>\nAllowed options");
|
||||||
|
@ -115,7 +122,7 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi
|
||||||
|
|
||||||
boost::program_options::notify(variables);
|
boost::program_options::notify(variables);
|
||||||
|
|
||||||
mCfgMgr.readConfiguration(variables, desc);
|
mCfgMgr.readConfiguration(variables, desc, quiet);
|
||||||
|
|
||||||
mDocumentManager.setEncoding (
|
mDocumentManager.setEncoding (
|
||||||
ToUTF8::calculateEncoding (variables["encoding"].as<std::string>()));
|
ToUTF8::calculateEncoding (variables["encoding"].as<std::string>()));
|
||||||
|
@ -156,15 +163,23 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi
|
||||||
}
|
}
|
||||||
|
|
||||||
dataDirs.insert (dataDirs.end(), dataLocal.begin(), dataLocal.end());
|
dataDirs.insert (dataDirs.end(), dataLocal.begin(), dataLocal.end());
|
||||||
|
Files::PathContainer canonicalPaths;
|
||||||
|
|
||||||
//iterate the data directories and add them to the file dialog for loading
|
//iterate the data directories and add them to the file dialog for loading
|
||||||
for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter)
|
for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter)
|
||||||
{
|
{
|
||||||
|
boost::filesystem::path p = boost::filesystem::canonical(*iter);
|
||||||
|
Files::PathContainer::iterator it = std::find(canonicalPaths.begin(), canonicalPaths.end(), p);
|
||||||
|
if (it == canonicalPaths.end())
|
||||||
|
canonicalPaths.push_back(p);
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
QString path = QString::fromUtf8 (iter->string().c_str());
|
QString path = QString::fromUtf8 (iter->string().c_str());
|
||||||
mFileDialog.addFiles(path);
|
mFileDialog.addFiles(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_pair (dataDirs, variables["fallback-archive"].as<std::vector<std::string> >());
|
return std::make_pair (canonicalPaths, variables["fallback-archive"].as<std::vector<std::string> >());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CS::Editor::createGame()
|
void CS::Editor::createGame()
|
||||||
|
@ -195,6 +210,11 @@ void CS::Editor::cancelCreateGame()
|
||||||
void CS::Editor::createAddon()
|
void CS::Editor::createAddon()
|
||||||
{
|
{
|
||||||
mStartup.hide();
|
mStartup.hide();
|
||||||
|
|
||||||
|
mFileDialog.clearFiles();
|
||||||
|
std::pair<Files::PathContainer, std::vector<std::string> > config = readConfig(/*quiet*/true);
|
||||||
|
setupDataFiles (config.first);
|
||||||
|
|
||||||
mFileDialog.showDialog (CSVDoc::ContentAction_New);
|
mFileDialog.showDialog (CSVDoc::ContentAction_New);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,6 +235,11 @@ void CS::Editor::cancelFileDialog()
|
||||||
void CS::Editor::loadDocument()
|
void CS::Editor::loadDocument()
|
||||||
{
|
{
|
||||||
mStartup.hide();
|
mStartup.hide();
|
||||||
|
|
||||||
|
mFileDialog.clearFiles();
|
||||||
|
std::pair<Files::PathContainer, std::vector<std::string> > config = readConfig(/*quiet*/true);
|
||||||
|
setupDataFiles (config.first);
|
||||||
|
|
||||||
mFileDialog.showDialog (CSVDoc::ContentAction_Edit);
|
mFileDialog.showDialog (CSVDoc::ContentAction_Edit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,6 +268,7 @@ void CS::Editor::createNewFile (const boost::filesystem::path &savePath)
|
||||||
mDocumentManager.addDocument (files, savePath, true);
|
mDocumentManager.addDocument (files, savePath, true);
|
||||||
|
|
||||||
mFileDialog.hide();
|
mFileDialog.hide();
|
||||||
|
showSplashMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CS::Editor::createNewGame (const boost::filesystem::path& file)
|
void CS::Editor::createNewGame (const boost::filesystem::path& file)
|
||||||
|
@ -254,6 +280,7 @@ void CS::Editor::createNewGame (const boost::filesystem::path& file)
|
||||||
mDocumentManager.addDocument (files, file, true);
|
mDocumentManager.addDocument (files, file, true);
|
||||||
|
|
||||||
mNewGame.hide();
|
mNewGame.hide();
|
||||||
|
showSplashMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CS::Editor::showStartup()
|
void CS::Editor::showStartup()
|
||||||
|
@ -307,12 +334,12 @@ bool CS::Editor::makeIPCServer()
|
||||||
mServer->close();
|
mServer->close();
|
||||||
fullPath.remove(QRegExp("dummy$"));
|
fullPath.remove(QRegExp("dummy$"));
|
||||||
fullPath += mIpcServerName;
|
fullPath += mIpcServerName;
|
||||||
if(boost::filesystem::exists(fullPath.toStdString().c_str()))
|
if(boost::filesystem::exists(fullPath.toUtf8().constData()))
|
||||||
{
|
{
|
||||||
// TODO: compare pid of the current process with that in the file
|
// TODO: compare pid of the current process with that in the file
|
||||||
std::cout << "Detected unclean shutdown." << std::endl;
|
std::cout << "Detected unclean shutdown." << std::endl;
|
||||||
// delete the stale file
|
// delete the stale file
|
||||||
if(remove(fullPath.toStdString().c_str()))
|
if(remove(fullPath.toUtf8().constData()))
|
||||||
std::cerr << "ERROR removing stale connection file" << std::endl;
|
std::cerr << "ERROR removing stale connection file" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -468,9 +495,65 @@ std::auto_ptr<sh::Factory> CS::Editor::setupGraphics()
|
||||||
void CS::Editor::documentAdded (CSMDoc::Document *document)
|
void CS::Editor::documentAdded (CSMDoc::Document *document)
|
||||||
{
|
{
|
||||||
mViewManager.addView (document);
|
mViewManager.addView (document);
|
||||||
|
showSplashMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CS::Editor::documentAboutToBeRemoved (CSMDoc::Document *document)
|
||||||
|
{
|
||||||
|
if (mMerge.getDocument()==document)
|
||||||
|
mMerge.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CS::Editor::lastDocumentDeleted()
|
void CS::Editor::lastDocumentDeleted()
|
||||||
{
|
{
|
||||||
QApplication::quit();
|
QApplication::quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CS::Editor::showSplashMessage()
|
||||||
|
{
|
||||||
|
CSMSettings::UserSettings &settings = CSMSettings::UserSettings::instance();
|
||||||
|
if(settings.settingValue ("filter/project-added") == "true" ||
|
||||||
|
settings.settingValue ("filter/project-modified") == "true")
|
||||||
|
{
|
||||||
|
QPixmap img(QPixmap(":./openmw-cs.png"));
|
||||||
|
|
||||||
|
QString msgTop("You have active global filters.");
|
||||||
|
QString msgBottom("Some rows may be hidden!");
|
||||||
|
QFont splashFont(QFont("Arial", 16, QFont::Bold)); // TODO: use system font?
|
||||||
|
//splashFont.setStretch(125);
|
||||||
|
|
||||||
|
QFontMetrics fm(splashFont);
|
||||||
|
int msgWidth = std::max(fm.width(msgTop), fm.width(msgBottom));
|
||||||
|
img.scaledToWidth(msgWidth);
|
||||||
|
|
||||||
|
QSplashScreen *splash = new QSplashScreen(img, Qt::WindowStaysOnTopHint);
|
||||||
|
splash->setFont(splashFont);
|
||||||
|
splash->resize(msgWidth+20, splash->height()+fm.lineSpacing()*2+20); // add some margin
|
||||||
|
|
||||||
|
// try to center the message near the center of the saved window
|
||||||
|
QWidget dummy;
|
||||||
|
bool xWorkaround = settings.settingValue ("window/x-save-state-workaround").toStdString() == "true";
|
||||||
|
if (settings.settingValue ("window/save-state").toStdString() == "true" &&
|
||||||
|
!(xWorkaround && settings.settingValue ("window/maximized").toStdString() == "true"))
|
||||||
|
{
|
||||||
|
dummy.restoreGeometry(settings.value("window/geometry").toByteArray());
|
||||||
|
splash->move(dummy.x()+std::max(0, (dummy.width()-msgWidth)/2),
|
||||||
|
dummy.y()+std::max(0, (dummy.height()-splash->height())/2));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
splash->move(std::max(0, splash->x()-msgWidth/2), splash->y());
|
||||||
|
|
||||||
|
splash->show();
|
||||||
|
splash->showMessage(msgTop+"\n"+msgBottom, Qt::AlignHCenter|Qt::AlignBottom, Qt::red);
|
||||||
|
QTimer::singleShot(4000, splash, SLOT(close())); // 4 seconds should be enough
|
||||||
|
splash->raise(); // for X windows
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CS::Editor::mergeDocument (CSMDoc::Document *document)
|
||||||
|
{
|
||||||
|
mMerge.configure (document);
|
||||||
|
mMerge.show();
|
||||||
|
mMerge.raise();
|
||||||
|
mMerge.activateWindow();
|
||||||
|
}
|
||||||
|
|
|
@ -32,11 +32,18 @@
|
||||||
#include "view/settings/dialog.hpp"
|
#include "view/settings/dialog.hpp"
|
||||||
#include "view/render/overlaysystem.hpp"
|
#include "view/render/overlaysystem.hpp"
|
||||||
|
|
||||||
|
#include "view/tools/merge.hpp"
|
||||||
|
|
||||||
namespace OgreInit
|
namespace OgreInit
|
||||||
{
|
{
|
||||||
class OgreInit;
|
class OgreInit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace CSMDoc
|
||||||
|
{
|
||||||
|
class Document;
|
||||||
|
}
|
||||||
|
|
||||||
namespace CS
|
namespace CS
|
||||||
{
|
{
|
||||||
class Editor : public QObject
|
class Editor : public QObject
|
||||||
|
@ -59,10 +66,13 @@ namespace CS
|
||||||
boost::interprocess::file_lock mLock;
|
boost::interprocess::file_lock mLock;
|
||||||
boost::filesystem::ofstream mPidFile;
|
boost::filesystem::ofstream mPidFile;
|
||||||
bool mFsStrict;
|
bool mFsStrict;
|
||||||
|
CSVTools::Merge mMerge;
|
||||||
|
|
||||||
|
void showSplashMessage();
|
||||||
|
|
||||||
void setupDataFiles (const Files::PathContainer& dataDirs);
|
void setupDataFiles (const Files::PathContainer& dataDirs);
|
||||||
|
|
||||||
std::pair<Files::PathContainer, std::vector<std::string> > readConfig();
|
std::pair<Files::PathContainer, std::vector<std::string> > readConfig(bool quiet=false);
|
||||||
///< \return data paths
|
///< \return data paths
|
||||||
|
|
||||||
// not implemented
|
// not implemented
|
||||||
|
@ -101,8 +111,12 @@ namespace CS
|
||||||
|
|
||||||
void documentAdded (CSMDoc::Document *document);
|
void documentAdded (CSMDoc::Document *document);
|
||||||
|
|
||||||
|
void documentAboutToBeRemoved (CSMDoc::Document *document);
|
||||||
|
|
||||||
void lastDocumentDeleted();
|
void lastDocumentDeleted();
|
||||||
|
|
||||||
|
void mergeDocument (CSMDoc::Document *document);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
QString mIpcServerName;
|
QString mIpcServerName;
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "editor.hpp"
|
#include "editor.hpp"
|
||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
@ -13,6 +12,8 @@
|
||||||
|
|
||||||
#include <components/ogreinit/ogreinit.hpp>
|
#include <components/ogreinit/ogreinit.hpp>
|
||||||
|
|
||||||
|
#include "model/doc/messages.hpp"
|
||||||
|
|
||||||
#include "model/world/universalid.hpp"
|
#include "model/world/universalid.hpp"
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
|
@ -52,6 +53,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
qRegisterMetaType<std::string> ("std::string");
|
qRegisterMetaType<std::string> ("std::string");
|
||||||
qRegisterMetaType<CSMWorld::UniversalId> ("CSMWorld::UniversalId");
|
qRegisterMetaType<CSMWorld::UniversalId> ("CSMWorld::UniversalId");
|
||||||
|
qRegisterMetaType<CSMDoc::Message> ("CSMDoc::Message");
|
||||||
|
|
||||||
OgreInit::OgreInit ogreInit;
|
OgreInit::OgreInit ogreInit;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "blacklist.hpp"
|
#include "blacklist.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
|
@ -799,9 +799,9 @@ void CSMDoc::Document::addGmsts()
|
||||||
"sBookSkillMessage",
|
"sBookSkillMessage",
|
||||||
"sBounty",
|
"sBounty",
|
||||||
"sBreath",
|
"sBreath",
|
||||||
"sBribe",
|
"sBribe 10 Gold",
|
||||||
"sBribe",
|
"sBribe 100 Gold",
|
||||||
"sBribe",
|
"sBribe 1000 Gold",
|
||||||
"sBribeFail",
|
"sBribeFail",
|
||||||
"sBribeSuccess",
|
"sBribeSuccess",
|
||||||
"sBuy",
|
"sBuy",
|
||||||
|
@ -2251,14 +2251,14 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
|
||||||
ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager,
|
ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager,
|
||||||
const std::vector<std::string>& blacklistedScripts)
|
const std::vector<std::string>& blacklistedScripts)
|
||||||
: mSavePath (savePath), mContentFiles (files), mNew (new_), mData (encoding, resourcesManager),
|
: mSavePath (savePath), mContentFiles (files), mNew (new_), mData (encoding, resourcesManager),
|
||||||
mTools (*this),
|
mTools (*this, encoding),
|
||||||
mProjectPath ((configuration.getUserDataPath() / "projects") /
|
mProjectPath ((configuration.getUserDataPath() / "projects") /
|
||||||
(savePath.filename().string() + ".project")),
|
(savePath.filename().string() + ".project")),
|
||||||
mSavingOperation (*this, mProjectPath, encoding),
|
mSavingOperation (*this, mProjectPath, encoding),
|
||||||
mSaving (&mSavingOperation),
|
mSaving (&mSavingOperation),
|
||||||
mResDir(resDir),
|
mResDir(resDir),
|
||||||
mRunner (mProjectPath), mPhysics(boost::shared_ptr<CSVWorld::PhysicsSystem>()),
|
mRunner (mProjectPath), mPhysics(boost::shared_ptr<CSVWorld::PhysicsSystem>()),
|
||||||
mIdCompletionManager(mData)
|
mDirty (false), mIdCompletionManager(mData)
|
||||||
{
|
{
|
||||||
if (mContentFiles.empty())
|
if (mContentFiles.empty())
|
||||||
throw std::runtime_error ("Empty content file sequence");
|
throw std::runtime_error ("Empty content file sequence");
|
||||||
|
@ -2272,7 +2272,7 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
|
||||||
|
|
||||||
if (boost::filesystem::exists (customFiltersPath))
|
if (boost::filesystem::exists (customFiltersPath))
|
||||||
{
|
{
|
||||||
destination << std::ifstream(customFiltersPath.c_str(), std::ios::binary).rdbuf();
|
destination << std::ifstream(customFiltersPath.string().c_str(), std::ios::binary).rdbuf();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2282,9 +2282,6 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
|
||||||
|
|
||||||
if (mNew)
|
if (mNew)
|
||||||
{
|
{
|
||||||
mData.setDescription ("");
|
|
||||||
mData.setAuthor ("");
|
|
||||||
|
|
||||||
if (mContentFiles.size()==1)
|
if (mContentFiles.size()==1)
|
||||||
createBase();
|
createBase();
|
||||||
}
|
}
|
||||||
|
@ -2299,13 +2296,15 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
|
||||||
|
|
||||||
connect (&mTools, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int)));
|
connect (&mTools, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int)));
|
||||||
connect (&mTools, SIGNAL (done (int, bool)), this, SLOT (operationDone (int, bool)));
|
connect (&mTools, SIGNAL (done (int, bool)), this, SLOT (operationDone (int, bool)));
|
||||||
|
connect (&mTools, SIGNAL (mergeDone (CSMDoc::Document*)),
|
||||||
|
this, SIGNAL (mergeDone (CSMDoc::Document*)));
|
||||||
|
|
||||||
connect (&mSaving, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int)));
|
connect (&mSaving, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int)));
|
||||||
connect (&mSaving, SIGNAL (done (int, bool)), this, SLOT (operationDone (int, bool)));
|
connect (&mSaving, SIGNAL (done (int, bool)), this, SLOT (operationDone (int, bool)));
|
||||||
|
|
||||||
connect (
|
connect (
|
||||||
&mSaving, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)),
|
&mSaving, SIGNAL (reportMessage (const CSMDoc::Message&, int)),
|
||||||
this, SLOT (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)));
|
this, SLOT (reportMessage (const CSMDoc::Message&, int)));
|
||||||
|
|
||||||
connect (&mRunner, SIGNAL (runStateChanged()), this, SLOT (runStateChanged()));
|
connect (&mRunner, SIGNAL (runStateChanged()), this, SLOT (runStateChanged()));
|
||||||
}
|
}
|
||||||
|
@ -2323,7 +2322,7 @@ int CSMDoc::Document::getState() const
|
||||||
{
|
{
|
||||||
int state = 0;
|
int state = 0;
|
||||||
|
|
||||||
if (!mUndoStack.isClean())
|
if (!mUndoStack.isClean() || mDirty)
|
||||||
state |= State_Modified;
|
state |= State_Modified;
|
||||||
|
|
||||||
if (mSaving.isRunning())
|
if (mSaving.isRunning())
|
||||||
|
@ -2369,9 +2368,9 @@ void CSMDoc::Document::save()
|
||||||
emit stateChanged (getState(), this);
|
emit stateChanged (getState(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::UniversalId CSMDoc::Document::verify()
|
CSMWorld::UniversalId CSMDoc::Document::verify (const CSMWorld::UniversalId& reportId)
|
||||||
{
|
{
|
||||||
CSMWorld::UniversalId id = mTools.runVerifier();
|
CSMWorld::UniversalId id = mTools.runVerifier (reportId);
|
||||||
emit stateChanged (getState(), this);
|
emit stateChanged (getState(), this);
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
@ -2388,6 +2387,12 @@ void CSMDoc::Document::runSearch (const CSMWorld::UniversalId& searchId, const C
|
||||||
emit stateChanged (getState(), this);
|
emit stateChanged (getState(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMDoc::Document::runMerge (std::auto_ptr<CSMDoc::Document> target)
|
||||||
|
{
|
||||||
|
mTools.runMerge (target);
|
||||||
|
emit stateChanged (getState(), this);
|
||||||
|
}
|
||||||
|
|
||||||
void CSMDoc::Document::abortOperation (int type)
|
void CSMDoc::Document::abortOperation (int type)
|
||||||
{
|
{
|
||||||
if (type==State_Saving)
|
if (type==State_Saving)
|
||||||
|
@ -2401,15 +2406,17 @@ void CSMDoc::Document::modificationStateChanged (bool clean)
|
||||||
emit stateChanged (getState(), this);
|
emit stateChanged (getState(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMDoc::Document::reportMessage (const CSMWorld::UniversalId& id, const std::string& message,
|
void CSMDoc::Document::reportMessage (const CSMDoc::Message& message, int type)
|
||||||
const std::string& hint, int type)
|
|
||||||
{
|
{
|
||||||
/// \todo find a better way to get these messages to the user.
|
/// \todo find a better way to get these messages to the user.
|
||||||
std::cout << message << std::endl;
|
std::cout << message.mMessage << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMDoc::Document::operationDone (int type, bool failed)
|
void CSMDoc::Document::operationDone (int type, bool failed)
|
||||||
{
|
{
|
||||||
|
if (type==CSMDoc::State_Saving && !failed)
|
||||||
|
mDirty = false;
|
||||||
|
|
||||||
emit stateChanged (getState(), this);
|
emit stateChanged (getState(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2494,3 +2501,8 @@ CSMWorld::IdCompletionManager &CSMDoc::Document::getIdCompletionManager()
|
||||||
{
|
{
|
||||||
return mIdCompletionManager;
|
return mIdCompletionManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMDoc::Document::flagAsDirty()
|
||||||
|
{
|
||||||
|
mDirty = true;
|
||||||
|
}
|
||||||
|
|
|
@ -67,6 +67,8 @@ namespace CSMDoc
|
||||||
Blacklist mBlacklist;
|
Blacklist mBlacklist;
|
||||||
Runner mRunner;
|
Runner mRunner;
|
||||||
boost::shared_ptr<CSVWorld::PhysicsSystem> mPhysics;
|
boost::shared_ptr<CSVWorld::PhysicsSystem> mPhysics;
|
||||||
|
bool mDirty;
|
||||||
|
|
||||||
CSMWorld::IdCompletionManager mIdCompletionManager;
|
CSMWorld::IdCompletionManager mIdCompletionManager;
|
||||||
|
|
||||||
// It is important that the undo stack is declared last, because on desctruction it fires a signal, that is connected to a slot, that is
|
// It is important that the undo stack is declared last, because on desctruction it fires a signal, that is connected to a slot, that is
|
||||||
|
@ -120,12 +122,14 @@ namespace CSMDoc
|
||||||
|
|
||||||
void save();
|
void save();
|
||||||
|
|
||||||
CSMWorld::UniversalId verify();
|
CSMWorld::UniversalId verify (const CSMWorld::UniversalId& reportId = CSMWorld::UniversalId());
|
||||||
|
|
||||||
CSMWorld::UniversalId newSearch();
|
CSMWorld::UniversalId newSearch();
|
||||||
|
|
||||||
void runSearch (const CSMWorld::UniversalId& searchId, const CSMTools::Search& search);
|
void runSearch (const CSMWorld::UniversalId& searchId, const CSMTools::Search& search);
|
||||||
|
|
||||||
|
void runMerge (std::auto_ptr<CSMDoc::Document> target);
|
||||||
|
|
||||||
void abortOperation (int type);
|
void abortOperation (int type);
|
||||||
|
|
||||||
const CSMWorld::Data& getData() const;
|
const CSMWorld::Data& getData() const;
|
||||||
|
@ -148,18 +152,23 @@ namespace CSMDoc
|
||||||
|
|
||||||
CSMWorld::IdCompletionManager &getIdCompletionManager();
|
CSMWorld::IdCompletionManager &getIdCompletionManager();
|
||||||
|
|
||||||
|
void flagAsDirty();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void stateChanged (int state, CSMDoc::Document *document);
|
void stateChanged (int state, CSMDoc::Document *document);
|
||||||
|
|
||||||
void progress (int current, int max, int type, int threads, CSMDoc::Document *document);
|
void progress (int current, int max, int type, int threads, CSMDoc::Document *document);
|
||||||
|
|
||||||
|
/// \attention When this signal is emitted, *this hands over the ownership of the
|
||||||
|
/// document. This signal must be handled to avoid a leak.
|
||||||
|
void mergeDone (CSMDoc::Document *document);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void modificationStateChanged (bool clean);
|
void modificationStateChanged (bool clean);
|
||||||
|
|
||||||
void reportMessage (const CSMWorld::UniversalId& id, const std::string& message,
|
void reportMessage (const CSMDoc::Message& message, int type);
|
||||||
const std::string& hint, int type);
|
|
||||||
|
|
||||||
void operationDone (int type, bool failed);
|
void operationDone (int type, bool failed);
|
||||||
|
|
||||||
|
@ -172,4 +181,3 @@ namespace CSMDoc
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "documentmanager.hpp"
|
#include "documentmanager.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
@ -57,10 +56,24 @@ bool CSMDoc::DocumentManager::isEmpty()
|
||||||
void CSMDoc::DocumentManager::addDocument (const std::vector<boost::filesystem::path>& files, const boost::filesystem::path& savePath,
|
void CSMDoc::DocumentManager::addDocument (const std::vector<boost::filesystem::path>& files, const boost::filesystem::path& savePath,
|
||||||
bool new_)
|
bool new_)
|
||||||
{
|
{
|
||||||
Document *document = new Document (mConfiguration, files, new_, savePath, mResDir, mEncoding, mResourcesManager, mBlacklistedScripts);
|
Document *document = makeDocument (files, savePath, new_);
|
||||||
|
insertDocument (document);
|
||||||
|
}
|
||||||
|
|
||||||
|
CSMDoc::Document *CSMDoc::DocumentManager::makeDocument (
|
||||||
|
const std::vector< boost::filesystem::path >& files,
|
||||||
|
const boost::filesystem::path& savePath, bool new_)
|
||||||
|
{
|
||||||
|
return new Document (mConfiguration, files, new_, savePath, mResDir, mEncoding, mResourcesManager, mBlacklistedScripts);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMDoc::DocumentManager::insertDocument (CSMDoc::Document *document)
|
||||||
|
{
|
||||||
mDocuments.push_back (document);
|
mDocuments.push_back (document);
|
||||||
|
|
||||||
|
connect (document, SIGNAL (mergeDone (CSMDoc::Document*)),
|
||||||
|
this, SLOT (insertDocument (CSMDoc::Document*)));
|
||||||
|
|
||||||
emit loadRequest (document);
|
emit loadRequest (document);
|
||||||
|
|
||||||
mLoader.hasThingsToDo().wakeAll();
|
mLoader.hasThingsToDo().wakeAll();
|
||||||
|
@ -73,6 +86,8 @@ void CSMDoc::DocumentManager::removeDocument (CSMDoc::Document *document)
|
||||||
if (iter==mDocuments.end())
|
if (iter==mDocuments.end())
|
||||||
throw std::runtime_error ("removing invalid document");
|
throw std::runtime_error ("removing invalid document");
|
||||||
|
|
||||||
|
emit documentAboutToBeRemoved (document);
|
||||||
|
|
||||||
mDocuments.erase (iter);
|
mDocuments.erase (iter);
|
||||||
document->deleteLater();
|
document->deleteLater();
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,15 @@ namespace CSMDoc
|
||||||
///< \param new_ Do not load the last content file in \a files and instead create in an
|
///< \param new_ Do not load the last content file in \a files and instead create in an
|
||||||
/// appropriate way.
|
/// appropriate way.
|
||||||
|
|
||||||
|
/// Create a new document. The ownership of the created document is transferred to
|
||||||
|
/// the calling function. The DocumentManager does not manage it. Loading has not
|
||||||
|
/// taken place at the point when the document is returned.
|
||||||
|
///
|
||||||
|
/// \param new_ Do not load the last content file in \a files and instead create in an
|
||||||
|
/// appropriate way.
|
||||||
|
Document *makeDocument (const std::vector< boost::filesystem::path >& files,
|
||||||
|
const boost::filesystem::path& savePath, bool new_);
|
||||||
|
|
||||||
void setResourceDir (const boost::filesystem::path& parResDir);
|
void setResourceDir (const boost::filesystem::path& parResDir);
|
||||||
|
|
||||||
void setEncoding (ToUTF8::FromType encoding);
|
void setEncoding (ToUTF8::FromType encoding);
|
||||||
|
@ -79,10 +88,16 @@ namespace CSMDoc
|
||||||
void removeDocument (CSMDoc::Document *document);
|
void removeDocument (CSMDoc::Document *document);
|
||||||
///< Emits the lastDocumentDeleted signal, if applicable.
|
///< Emits the lastDocumentDeleted signal, if applicable.
|
||||||
|
|
||||||
|
/// Hand over document to *this. The ownership is transferred. The DocumentManager
|
||||||
|
/// will initiate the load procedure, if necessary
|
||||||
|
void insertDocument (CSMDoc::Document *document);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void documentAdded (CSMDoc::Document *document);
|
void documentAdded (CSMDoc::Document *document);
|
||||||
|
|
||||||
|
void documentAboutToBeRemoved (CSMDoc::Document *document);
|
||||||
|
|
||||||
void loadRequest (CSMDoc::Document *document);
|
void loadRequest (CSMDoc::Document *document);
|
||||||
|
|
||||||
void lastDocumentDeleted();
|
void lastDocumentDeleted();
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "loader.hpp"
|
#include "loader.hpp"
|
||||||
|
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
@ -52,7 +51,7 @@ void CSMDoc::Loader::load()
|
||||||
{
|
{
|
||||||
if (iter->second.mRecordsLeft)
|
if (iter->second.mRecordsLeft)
|
||||||
{
|
{
|
||||||
CSMDoc::Messages messages;
|
Messages messages (Message::Severity_Error);
|
||||||
for (int i=0; i<batchingSize; ++i) // do not flood the system with update signals
|
for (int i=0; i<batchingSize; ++i) // do not flood the system with update signals
|
||||||
if (document->getData().continueLoading (messages))
|
if (document->getData().continueLoading (messages))
|
||||||
{
|
{
|
||||||
|
@ -68,7 +67,7 @@ void CSMDoc::Loader::load()
|
||||||
for (CSMDoc::Messages::Iterator iter (messages.begin());
|
for (CSMDoc::Messages::Iterator iter (messages.begin());
|
||||||
iter!=messages.end(); ++iter)
|
iter!=messages.end(); ++iter)
|
||||||
{
|
{
|
||||||
document->getReport (log)->add (iter->mId, iter->mMessage);
|
document->getReport (log)->add (*iter);
|
||||||
emit loadMessage (document, iter->mMessage);
|
emit loadMessage (document, iter->mMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,38 @@
|
||||||
|
|
||||||
#include "messages.hpp"
|
#include "messages.hpp"
|
||||||
|
|
||||||
void CSMDoc::Messages::add (const CSMWorld::UniversalId& id, const std::string& message,
|
CSMDoc::Message::Message() {}
|
||||||
const std::string& hint)
|
|
||||||
{
|
|
||||||
Message data;
|
|
||||||
data.mId = id;
|
|
||||||
data.mMessage = message;
|
|
||||||
data.mHint = hint;
|
|
||||||
|
|
||||||
mMessages.push_back (data);
|
CSMDoc::Message::Message (const CSMWorld::UniversalId& id, const std::string& message,
|
||||||
|
const std::string& hint, Severity severity)
|
||||||
|
: mId (id), mMessage (message), mHint (hint), mSeverity (severity)
|
||||||
|
{}
|
||||||
|
|
||||||
|
std::string CSMDoc::Message::toString (Severity severity)
|
||||||
|
{
|
||||||
|
switch (severity)
|
||||||
|
{
|
||||||
|
case CSMDoc::Message::Severity_Info: return "Information";
|
||||||
|
case CSMDoc::Message::Severity_Warning: return "Warning";
|
||||||
|
case CSMDoc::Message::Severity_Error: return "Error";
|
||||||
|
case CSMDoc::Message::Severity_SeriousError: return "Serious Error";
|
||||||
|
case CSMDoc::Message::Severity_Default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CSMDoc::Messages::Messages (Message::Severity default_)
|
||||||
|
: mDefault (default_)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void CSMDoc::Messages::add (const CSMWorld::UniversalId& id, const std::string& message,
|
||||||
|
const std::string& hint, Message::Severity severity)
|
||||||
|
{
|
||||||
|
if (severity==Message::Severity_Default)
|
||||||
|
severity = mDefault;
|
||||||
|
|
||||||
|
mMessages.push_back (Message (id, message, hint, severity));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMDoc::Messages::push_back (const std::pair<CSMWorld::UniversalId, std::string>& data)
|
void CSMDoc::Messages::push_back (const std::pair<CSMWorld::UniversalId, std::string>& data)
|
||||||
|
|
|
@ -4,20 +4,43 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <QMetaType>
|
||||||
|
|
||||||
#include "../world/universalid.hpp"
|
#include "../world/universalid.hpp"
|
||||||
|
|
||||||
namespace CSMDoc
|
namespace CSMDoc
|
||||||
{
|
{
|
||||||
|
struct Message
|
||||||
|
{
|
||||||
|
enum Severity
|
||||||
|
{
|
||||||
|
Severity_Info = 0, // no problem
|
||||||
|
Severity_Warning = 1, // a potential problem, but we are probably fine
|
||||||
|
Severity_Error = 2, // an error; we are not fine
|
||||||
|
Severity_SeriousError = 3, // an error so bad we can't even be sure if we are
|
||||||
|
// reporting it correctly
|
||||||
|
Severity_Default = 4
|
||||||
|
};
|
||||||
|
|
||||||
|
CSMWorld::UniversalId mId;
|
||||||
|
std::string mMessage;
|
||||||
|
std::string mHint;
|
||||||
|
Severity mSeverity;
|
||||||
|
|
||||||
|
Message();
|
||||||
|
|
||||||
|
Message (const CSMWorld::UniversalId& id, const std::string& message,
|
||||||
|
const std::string& hint, Severity severity);
|
||||||
|
|
||||||
|
static std::string toString (Severity severity);
|
||||||
|
};
|
||||||
|
|
||||||
class Messages
|
class Messages
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
struct Message
|
// \deprecated Use CSMDoc::Message directly instead.
|
||||||
{
|
typedef CSMDoc::Message Message;
|
||||||
CSMWorld::UniversalId mId;
|
|
||||||
std::string mMessage;
|
|
||||||
std::string mHint;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::vector<Message> Collection;
|
typedef std::vector<Message> Collection;
|
||||||
|
|
||||||
|
@ -26,11 +49,15 @@ namespace CSMDoc
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Collection mMessages;
|
Collection mMessages;
|
||||||
|
Message::Severity mDefault;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
Messages (Message::Severity default_);
|
||||||
|
|
||||||
void add (const CSMWorld::UniversalId& id, const std::string& message,
|
void add (const CSMWorld::UniversalId& id, const std::string& message,
|
||||||
const std::string& hint = "");
|
const std::string& hint = "",
|
||||||
|
Message::Severity severity = Message::Severity_Default);
|
||||||
|
|
||||||
/// \deprecated Use add instead.
|
/// \deprecated Use add instead.
|
||||||
void push_back (const std::pair<CSMWorld::UniversalId, std::string>& data);
|
void push_back (const std::pair<CSMWorld::UniversalId, std::string>& data);
|
||||||
|
@ -41,4 +68,6 @@ namespace CSMDoc
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE (CSMDoc::Message)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "operation.hpp"
|
#include "operation.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -7,6 +6,7 @@
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
#include "../world/universalid.hpp"
|
#include "../world/universalid.hpp"
|
||||||
|
#include "../settings/usersettings.hpp"
|
||||||
|
|
||||||
#include "state.hpp"
|
#include "state.hpp"
|
||||||
#include "stage.hpp"
|
#include "stage.hpp"
|
||||||
|
@ -23,13 +23,17 @@ void CSMDoc::Operation::prepareStages()
|
||||||
{
|
{
|
||||||
iter->second = iter->first->setup();
|
iter->second = iter->first->setup();
|
||||||
mTotalSteps += iter->second;
|
mTotalSteps += iter->second;
|
||||||
|
|
||||||
|
for (std::map<QString, QStringList>::const_iterator iter2 (mSettings.begin()); iter2!=mSettings.end(); ++iter2)
|
||||||
|
iter->first->updateUserSetting (iter2->first, iter2->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMDoc::Operation::Operation (int type, bool ordered, bool finalAlways)
|
CSMDoc::Operation::Operation (int type, bool ordered, bool finalAlways)
|
||||||
: mType (type), mStages(std::vector<std::pair<Stage *, int> >()), mCurrentStage(mStages.begin()),
|
: mType (type), mStages(std::vector<std::pair<Stage *, int> >()), mCurrentStage(mStages.begin()),
|
||||||
mCurrentStep(0), mCurrentStepTotal(0), mTotalSteps(0), mOrdered (ordered),
|
mCurrentStep(0), mCurrentStepTotal(0), mTotalSteps(0), mOrdered (ordered),
|
||||||
mFinalAlways (finalAlways), mError(false), mConnected (false)
|
mFinalAlways (finalAlways), mError(false), mConnected (false), mPrepared (false),
|
||||||
|
mDefaultSeverity (Message::Severity_Error)
|
||||||
{
|
{
|
||||||
mTimer = new QTimer (this);
|
mTimer = new QTimer (this);
|
||||||
}
|
}
|
||||||
|
@ -50,7 +54,7 @@ void CSMDoc::Operation::run()
|
||||||
mConnected = true;
|
mConnected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareStages();
|
mPrepared = false;
|
||||||
|
|
||||||
mTimer->start (0);
|
mTimer->start (0);
|
||||||
}
|
}
|
||||||
|
@ -60,6 +64,19 @@ void CSMDoc::Operation::appendStage (Stage *stage)
|
||||||
mStages.push_back (std::make_pair (stage, 0));
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
bool CSMDoc::Operation::hasError() const
|
bool CSMDoc::Operation::hasError() const
|
||||||
{
|
{
|
||||||
return mError;
|
return mError;
|
||||||
|
@ -84,9 +101,23 @@ void CSMDoc::Operation::abort()
|
||||||
mCurrentStage = mStages.end();
|
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()
|
void CSMDoc::Operation::executeStage()
|
||||||
{
|
{
|
||||||
Messages messages;
|
if (!mPrepared)
|
||||||
|
{
|
||||||
|
prepareStages();
|
||||||
|
mPrepared = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Messages messages (mDefaultSeverity);
|
||||||
|
|
||||||
while (mCurrentStage!=mStages.end())
|
while (mCurrentStage!=mStages.end())
|
||||||
{
|
{
|
||||||
|
@ -103,7 +134,7 @@ void CSMDoc::Operation::executeStage()
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
emit reportMessage (CSMWorld::UniversalId(), e.what(), "", mType);
|
emit reportMessage (Message (CSMWorld::UniversalId(), e.what(), "", Message::Severity_SeriousError), mType);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +146,7 @@ void CSMDoc::Operation::executeStage()
|
||||||
emit progress (mCurrentStepTotal, mTotalSteps ? mTotalSteps : 1, mType);
|
emit progress (mCurrentStepTotal, mTotalSteps ? mTotalSteps : 1, mType);
|
||||||
|
|
||||||
for (Messages::Iterator iter (messages.begin()); iter!=messages.end(); ++iter)
|
for (Messages::Iterator iter (messages.begin()); iter!=messages.end(); ++iter)
|
||||||
emit reportMessage (iter->mId, iter->mMessage, iter->mHint, mType);
|
emit reportMessage (*iter, mType);
|
||||||
|
|
||||||
if (mCurrentStage==mStages.end())
|
if (mCurrentStage==mStages.end())
|
||||||
operationDone();
|
operationDone();
|
||||||
|
|
|
@ -2,9 +2,13 @@
|
||||||
#define CSM_DOC_OPERATION_H
|
#define CSM_DOC_OPERATION_H
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
#include "messages.hpp"
|
||||||
|
|
||||||
namespace CSMWorld
|
namespace CSMWorld
|
||||||
{
|
{
|
||||||
|
@ -30,6 +34,9 @@ namespace CSMDoc
|
||||||
bool mError;
|
bool mError;
|
||||||
bool mConnected;
|
bool mConnected;
|
||||||
QTimer *mTimer;
|
QTimer *mTimer;
|
||||||
|
std::map<QString, QStringList> mSettings;
|
||||||
|
bool mPrepared;
|
||||||
|
Message::Severity mDefaultSeverity;
|
||||||
|
|
||||||
void prepareStages();
|
void prepareStages();
|
||||||
|
|
||||||
|
@ -46,14 +53,21 @@ namespace CSMDoc
|
||||||
///
|
///
|
||||||
/// \attention Do no call this function while this Operation is running.
|
/// \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);
|
||||||
|
|
||||||
bool hasError() const;
|
bool hasError() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void progress (int current, int max, int type);
|
void progress (int current, int max, int type);
|
||||||
|
|
||||||
void reportMessage (const CSMWorld::UniversalId& id, const std::string& message,
|
void reportMessage (const CSMDoc::Message& message, int type);
|
||||||
const std::string& hint, int type);
|
|
||||||
|
|
||||||
void done (int type, bool failed);
|
void done (int type, bool failed);
|
||||||
|
|
||||||
|
@ -63,11 +77,15 @@ namespace CSMDoc
|
||||||
|
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
|
void updateUserSetting (const QString& name, const QStringList& value);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void executeStage();
|
void executeStage();
|
||||||
|
|
||||||
void operationDone();
|
protected slots:
|
||||||
|
|
||||||
|
virtual void operationDone();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
#include "operationholder.hpp"
|
#include "operationholder.hpp"
|
||||||
|
|
||||||
|
#include "../settings/usersettings.hpp"
|
||||||
|
|
||||||
#include "operation.hpp"
|
#include "operation.hpp"
|
||||||
|
|
||||||
CSMDoc::OperationHolder::OperationHolder (Operation *operation) : mRunning (false)
|
CSMDoc::OperationHolder::OperationHolder (Operation *operation) : mRunning (false)
|
||||||
|
@ -19,8 +20,8 @@ void CSMDoc::OperationHolder::setOperation (Operation *operation)
|
||||||
this, SIGNAL (progress (int, int, int)));
|
this, SIGNAL (progress (int, int, int)));
|
||||||
|
|
||||||
connect (
|
connect (
|
||||||
mOperation, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)),
|
mOperation, SIGNAL (reportMessage (const CSMDoc::Message&, int)),
|
||||||
this, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)));
|
this, SIGNAL (reportMessage (const CSMDoc::Message&, int)));
|
||||||
|
|
||||||
connect (
|
connect (
|
||||||
mOperation, SIGNAL (done (int, bool)),
|
mOperation, SIGNAL (done (int, bool)),
|
||||||
|
@ -29,6 +30,9 @@ void CSMDoc::OperationHolder::setOperation (Operation *operation)
|
||||||
connect (this, SIGNAL (abortSignal()), mOperation, SLOT (abort()));
|
connect (this, SIGNAL (abortSignal()), mOperation, SLOT (abort()));
|
||||||
|
|
||||||
connect (&mThread, SIGNAL (started()), mOperation, SLOT (run()));
|
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
|
bool CSMDoc::OperationHolder::isRunning() const
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
|
#include "messages.hpp"
|
||||||
|
|
||||||
namespace CSMWorld
|
namespace CSMWorld
|
||||||
{
|
{
|
||||||
class UniversalId;
|
class UniversalId;
|
||||||
|
@ -44,8 +46,7 @@ namespace CSMDoc
|
||||||
|
|
||||||
void progress (int current, int max, int type);
|
void progress (int current, int max, int type);
|
||||||
|
|
||||||
void reportMessage (const CSMWorld::UniversalId& id, const std::string& message,
|
void reportMessage (const CSMDoc::Message& message, int type);
|
||||||
const std::string& hint, int type);
|
|
||||||
|
|
||||||
void done (int type, bool failed);
|
void done (int type, bool failed);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "runner.hpp"
|
#include "runner.hpp"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "saving.hpp"
|
#include "saving.hpp"
|
||||||
|
|
||||||
#include "../world/data.hpp"
|
#include "../world/data.hpp"
|
||||||
|
@ -81,22 +80,25 @@ CSMDoc::Saving::Saving (Document& document, const boost::filesystem::path& proje
|
||||||
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::StartScript> >
|
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::StartScript> >
|
||||||
(mDocument.getData().getStartScripts(), mState));
|
(mDocument.getData().getStartScripts(), mState));
|
||||||
|
|
||||||
appendStage (new WriteDialogueCollectionStage (mDocument, mState, false));
|
|
||||||
|
|
||||||
appendStage (new WriteDialogueCollectionStage (mDocument, mState, true));
|
|
||||||
|
|
||||||
appendStage (new WriteRefIdCollectionStage (mDocument, mState));
|
appendStage (new WriteRefIdCollectionStage (mDocument, mState));
|
||||||
|
|
||||||
appendStage (new CollectionReferencesStage (mDocument, mState));
|
appendStage (new CollectionReferencesStage (mDocument, mState));
|
||||||
|
|
||||||
appendStage (new WriteCellCollectionStage (mDocument, mState));
|
appendStage (new WriteCellCollectionStage (mDocument, mState));
|
||||||
|
|
||||||
|
// Dialogue can reference objects and cells so must be written after these records for vanilla-compatible files
|
||||||
|
|
||||||
|
appendStage (new WriteDialogueCollectionStage (mDocument, mState, false));
|
||||||
|
|
||||||
|
appendStage (new WriteDialogueCollectionStage (mDocument, mState, true));
|
||||||
|
|
||||||
appendStage (new WritePathgridCollectionStage (mDocument, mState));
|
appendStage (new WritePathgridCollectionStage (mDocument, mState));
|
||||||
|
|
||||||
appendStage (new WriteLandCollectionStage (mDocument, mState));
|
|
||||||
|
|
||||||
appendStage (new WriteLandTextureCollectionStage (mDocument, mState));
|
appendStage (new WriteLandTextureCollectionStage (mDocument, mState));
|
||||||
|
|
||||||
|
// references Land Textures
|
||||||
|
appendStage (new WriteLandCollectionStage (mDocument, mState));
|
||||||
|
|
||||||
// close file and clean up
|
// close file and clean up
|
||||||
appendStage (new CloseSaveStage (mState));
|
appendStage (new CloseSaveStage (mState));
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "savingstages.hpp"
|
#include "savingstages.hpp"
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
@ -53,18 +52,16 @@ void CSMDoc::WriteHeaderStage::perform (int stage, Messages& messages)
|
||||||
|
|
||||||
mState.getWriter().clearMaster();
|
mState.getWriter().clearMaster();
|
||||||
|
|
||||||
mState.getWriter().setFormat (0);
|
|
||||||
|
|
||||||
if (mSimple)
|
if (mSimple)
|
||||||
{
|
{
|
||||||
mState.getWriter().setAuthor ("");
|
mState.getWriter().setAuthor ("");
|
||||||
mState.getWriter().setDescription ("");
|
mState.getWriter().setDescription ("");
|
||||||
mState.getWriter().setRecordCount (0);
|
mState.getWriter().setRecordCount (0);
|
||||||
|
mState.getWriter().setFormat (ESM::Header::CurrentFormat);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mState.getWriter().setAuthor (mDocument.getData().getAuthor());
|
mDocument.getData().getMetaData().save (mState.getWriter());
|
||||||
mState.getWriter().setDescription (mDocument.getData().getDescription());
|
|
||||||
mState.getWriter().setRecordCount (
|
mState.getWriter().setRecordCount (
|
||||||
mDocument.getData().count (CSMWorld::RecordBase::State_Modified) +
|
mDocument.getData().count (CSMWorld::RecordBase::State_Modified) +
|
||||||
mDocument.getData().count (CSMWorld::RecordBase::State_ModifiedOnly) +
|
mDocument.getData().count (CSMWorld::RecordBase::State_ModifiedOnly) +
|
||||||
|
@ -136,24 +133,35 @@ void CSMDoc::WriteDialogueCollectionStage::perform (int stage, Messages& message
|
||||||
if (state==CSMWorld::RecordBase::State_Modified ||
|
if (state==CSMWorld::RecordBase::State_Modified ||
|
||||||
state==CSMWorld::RecordBase::State_ModifiedOnly ||
|
state==CSMWorld::RecordBase::State_ModifiedOnly ||
|
||||||
infoModified)
|
infoModified)
|
||||||
|
{
|
||||||
|
if (infoModified && state != CSMWorld::RecordBase::State_Modified
|
||||||
|
&& state != CSMWorld::RecordBase::State_ModifiedOnly)
|
||||||
|
{
|
||||||
|
mState.getWriter().startRecord (topic.mBase.sRecordId);
|
||||||
|
mState.getWriter().writeHNCString ("NAME", topic.mBase.mId);
|
||||||
|
topic.mBase.save (mState.getWriter());
|
||||||
|
mState.getWriter().endRecord (topic.mBase.sRecordId);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
mState.getWriter().startRecord (topic.mModified.sRecordId);
|
mState.getWriter().startRecord (topic.mModified.sRecordId);
|
||||||
mState.getWriter().writeHNCString ("NAME", topic.mModified.mId);
|
mState.getWriter().writeHNCString ("NAME", topic.mModified.mId);
|
||||||
topic.mModified.save (mState.getWriter());
|
topic.mModified.save (mState.getWriter());
|
||||||
mState.getWriter().endRecord (topic.mModified.sRecordId);
|
mState.getWriter().endRecord (topic.mModified.sRecordId);
|
||||||
|
}
|
||||||
|
|
||||||
// write modified selected info records
|
// write modified selected info records
|
||||||
for (CSMWorld::InfoCollection::RecordConstIterator iter (range.first); iter!=range.second;
|
for (CSMWorld::InfoCollection::RecordConstIterator iter (range.first); iter!=range.second;
|
||||||
++iter)
|
++iter)
|
||||||
{
|
{
|
||||||
CSMWorld::RecordBase::State state = iter->mState;
|
CSMWorld::RecordBase::State infoState = iter->mState;
|
||||||
|
|
||||||
if (state==CSMWorld::RecordBase::State_Deleted)
|
if (infoState==CSMWorld::RecordBase::State_Deleted)
|
||||||
{
|
{
|
||||||
/// \todo wrote record with delete flag
|
/// \todo wrote record with delete flag
|
||||||
}
|
}
|
||||||
else if (state==CSMWorld::RecordBase::State_Modified ||
|
else if (infoState==CSMWorld::RecordBase::State_Modified ||
|
||||||
state==CSMWorld::RecordBase::State_ModifiedOnly)
|
infoState==CSMWorld::RecordBase::State_ModifiedOnly)
|
||||||
{
|
{
|
||||||
ESM::DialInfo info = iter->get();
|
ESM::DialInfo info = iter->get();
|
||||||
info.mId = info.mId.substr (info.mId.find_last_of ('#')+1);
|
info.mId = info.mId.substr (info.mId.find_last_of ('#')+1);
|
||||||
|
@ -418,15 +426,16 @@ void CSMDoc::WriteLandCollectionStage::perform (int stage, Messages& messages)
|
||||||
if (land.mState==CSMWorld::RecordBase::State_Modified ||
|
if (land.mState==CSMWorld::RecordBase::State_Modified ||
|
||||||
land.mState==CSMWorld::RecordBase::State_ModifiedOnly)
|
land.mState==CSMWorld::RecordBase::State_ModifiedOnly)
|
||||||
{
|
{
|
||||||
CSMWorld::Land record = land.get();
|
const CSMWorld::Land& record = land.get();
|
||||||
|
|
||||||
mState.getWriter().startRecord (record.mLand->sRecordId);
|
mState.getWriter().startRecord (record.sRecordId);
|
||||||
|
|
||||||
record.mLand->save (mState.getWriter());
|
record.save (mState.getWriter());
|
||||||
if(record.mLand->mLandData)
|
|
||||||
record.mLand->mLandData->save (mState.getWriter());
|
|
||||||
|
|
||||||
mState.getWriter().endRecord (record.mLand->sRecordId);
|
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)
|
else if (land.mState==CSMWorld::RecordBase::State_Deleted)
|
||||||
{
|
{
|
||||||
|
@ -457,6 +466,8 @@ void CSMDoc::WriteLandTextureCollectionStage::perform (int stage, Messages& mess
|
||||||
|
|
||||||
mState.getWriter().startRecord (record.sRecordId);
|
mState.getWriter().startRecord (record.sRecordId);
|
||||||
|
|
||||||
|
mState.getWriter().writeHNString("NAME", record.mId);
|
||||||
|
|
||||||
record.save (mState.getWriter());
|
record.save (mState.getWriter());
|
||||||
|
|
||||||
mState.getWriter().endRecord (record.sRecordId);
|
mState.getWriter().endRecord (record.sRecordId);
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "savingstate.hpp"
|
#include "savingstate.hpp"
|
||||||
|
|
||||||
#include "operation.hpp"
|
#include "operation.hpp"
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
|
|
||||||
#include "stage.hpp"
|
#include "stage.hpp"
|
||||||
|
|
||||||
CSMDoc::Stage::~Stage() {}
|
CSMDoc::Stage::~Stage() {}
|
||||||
|
|
||||||
|
void CSMDoc::Stage::updateUserSetting (const QString& name, const QStringList& value) {}
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
#include "messages.hpp"
|
#include "messages.hpp"
|
||||||
|
|
||||||
|
class QString;
|
||||||
|
|
||||||
namespace CSMDoc
|
namespace CSMDoc
|
||||||
{
|
{
|
||||||
class Stage
|
class Stage
|
||||||
|
@ -21,6 +23,9 @@ namespace CSMDoc
|
||||||
|
|
||||||
virtual void perform (int stage, Messages& messages) = 0;
|
virtual void perform (int stage, Messages& messages) = 0;
|
||||||
///< Messages resulting from this stage will be appended to \a messages.
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
|
|
||||||
|
/// Default-implementation: ignore
|
||||||
|
virtual void updateUserSetting (const QString& name, const QStringList& value);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ namespace CSMDoc
|
||||||
|
|
||||||
State_Saving = 16,
|
State_Saving = 16,
|
||||||
State_Verifying = 32,
|
State_Verifying = 32,
|
||||||
State_Compiling = 64, // not implemented yet
|
State_Merging = 64,
|
||||||
State_Searching = 128,
|
State_Searching = 128,
|
||||||
State_Loading = 256 // pseudo-state; can not be encountered in a loaded document
|
State_Loading = 256 // pseudo-state; can not be encountered in a loaded document
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "andnode.hpp"
|
#include "andnode.hpp"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "booleannode.hpp"
|
#include "booleannode.hpp"
|
||||||
|
|
||||||
CSMFilter::BooleanNode::BooleanNode (bool true_) : mTrue (true_) {}
|
CSMFilter::BooleanNode::BooleanNode (bool true_) : mTrue (true_) {}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "leafnode.hpp"
|
#include "leafnode.hpp"
|
||||||
|
|
||||||
std::vector<int> CSMFilter::LeafNode::getReferencedColumns() const
|
std::vector<int> CSMFilter::LeafNode::getReferencedColumns() const
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "narynode.hpp"
|
#include "narynode.hpp"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "node.hpp"
|
#include "node.hpp"
|
||||||
|
|
||||||
CSMFilter::Node::Node() {}
|
CSMFilter::Node::Node() {}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "notnode.hpp"
|
#include "notnode.hpp"
|
||||||
|
|
||||||
CSMFilter::NotNode::NotNode (boost::shared_ptr<Node> child) : UnaryNode (child, "not") {}
|
CSMFilter::NotNode::NotNode (boost::shared_ptr<Node> child) : UnaryNode (child, "not") {}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "ornode.hpp"
|
#include "ornode.hpp"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "parser.hpp"
|
#include "parser.hpp"
|
||||||
|
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "textnode.hpp"
|
#include "textnode.hpp"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "unarynode.hpp"
|
#include "unarynode.hpp"
|
||||||
|
|
||||||
CSMFilter::UnaryNode::UnaryNode (boost::shared_ptr<Node> child, const std::string& name)
|
CSMFilter::UnaryNode::UnaryNode (boost::shared_ptr<Node> child, const std::string& name)
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "valuenode.hpp"
|
#include "valuenode.hpp"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
|
@ -161,6 +161,16 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
|
||||||
grow->setToolTip ("When \"Grow then Scroll\" option is selected, the window size grows to"
|
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"
|
" the width of the virtual desktop. \nIf this option is selected the the window growth"
|
||||||
"is limited to the current screen.");
|
"is limited to the current screen.");
|
||||||
|
|
||||||
|
Setting *saveState = createSetting (Type_CheckBox, "save-state", "Save window size and position");
|
||||||
|
saveState->setDefaultValue ("true");
|
||||||
|
saveState->setToolTip ("Remember window size and position between editing sessions.");
|
||||||
|
|
||||||
|
Setting *saveX = createSetting (Type_CheckBox, "x-save-state-workaround", "X windows workaround");
|
||||||
|
saveX->setDefaultValue ("false");
|
||||||
|
saveX->setToolTip ("Some X window managers don't remember the windows state before being"
|
||||||
|
" maximized. In such environments exiting while maximized will correctly start in a maximized"
|
||||||
|
" window, but restoring back to the normal size won't work. Try this workaround.");
|
||||||
}
|
}
|
||||||
|
|
||||||
declareSection ("records", "Records");
|
declareSection ("records", "Records");
|
||||||
|
@ -179,7 +189,7 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
|
||||||
ritd->setDeclaredValues (values);
|
ritd->setDeclaredValues (values);
|
||||||
}
|
}
|
||||||
|
|
||||||
declareSection ("table-input", "Table Input");
|
declareSection ("table-input", "ID Tables");
|
||||||
{
|
{
|
||||||
QString inPlaceEdit ("Edit in Place");
|
QString inPlaceEdit ("Edit in Place");
|
||||||
QString editRecord ("Edit Record");
|
QString editRecord ("Edit Record");
|
||||||
|
@ -232,6 +242,67 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
|
||||||
"Jump to the added or cloned record.");
|
"Jump to the added or cloned record.");
|
||||||
jumpToAdded->setDefaultValue (defaultValue);
|
jumpToAdded->setDefaultValue (defaultValue);
|
||||||
jumpToAdded->setDeclaredValues (jumpValues);
|
jumpToAdded->setDeclaredValues (jumpValues);
|
||||||
|
|
||||||
|
Setting *jumpToModified = createSetting (Type_CheckBox, "jump-to-modified", "Jump to modified Record");
|
||||||
|
jumpToModified->setDefaultValue ("true");
|
||||||
|
jumpToModified->setToolTip ("Whether to jump to the modified record. This setting effects the instances table only."
|
||||||
|
"\nCan be useful in finding the moved or modified object instance while 3D editing.");
|
||||||
|
|
||||||
|
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");
|
declareSection ("search", "Search & Replace");
|
||||||
|
@ -252,12 +323,12 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
|
||||||
autoDelete->setDefaultValue ("true");
|
autoDelete->setDefaultValue ("true");
|
||||||
}
|
}
|
||||||
|
|
||||||
declareSection ("script-editor", "Script Editor");
|
declareSection ("script-editor", "Scripts");
|
||||||
{
|
{
|
||||||
Setting *lineNum = createSetting (Type_CheckBox, "show-linenum", "Show Line Numbers");
|
Setting *lineNum = createSetting (Type_CheckBox, "show-linenum", "Show Line Numbers");
|
||||||
lineNum->setDefaultValue ("true");
|
lineNum->setDefaultValue ("true");
|
||||||
lineNum->setToolTip ("Show line numbers to the left of the script editor window."
|
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.");
|
" 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");
|
Setting *monoFont = createSetting (Type_CheckBox, "mono-font", "Use monospace font");
|
||||||
monoFont->setDefaultValue ("true");
|
monoFont->setDefaultValue ("true");
|
||||||
|
@ -271,6 +342,30 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
|
||||||
"\nA name from the list of colors defined in the list of SVG color keyword names."
|
"\nA name from the list of colors defined in the list of SVG color keyword names."
|
||||||
"\nX11 color names may also work.";
|
"\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");
|
Setting *formatInt = createSetting (Type_LineEdit, "colour-int", "Highlight Colour: Int");
|
||||||
formatInt->setDefaultValues (QStringList() << "Dark magenta");
|
formatInt->setDefaultValues (QStringList() << "Dark magenta");
|
||||||
formatInt->setToolTip ("(Default: Green) Use one of the following formats:" + tooltip);
|
formatInt->setToolTip ("(Default: Green) Use one of the following formats:" + tooltip);
|
||||||
|
@ -300,6 +395,27 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
|
||||||
formatId->setToolTip ("(Default: Blue) Use one of the following formats:" + tooltip);
|
formatId->setToolTip ("(Default: Blue) Use one of the following formats:" + tooltip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declareSection ("filter", "Global Filter");
|
||||||
|
{
|
||||||
|
Setting *projAdded = createSetting (Type_CheckBox, "project-added", "Project::added initial value");
|
||||||
|
projAdded->setDefaultValue ("false");
|
||||||
|
projAdded->setToolTip ("Show records added by the project when opening a table."
|
||||||
|
" Other records are filterd out.");
|
||||||
|
|
||||||
|
Setting *projModified = createSetting (Type_CheckBox, "project-modified", "Project::modified initial value");
|
||||||
|
projModified->setDefaultValue ("false");
|
||||||
|
projModified->setToolTip ("Show records modified by the project when opening a table."
|
||||||
|
" Other records are filterd out.");
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
* There are three types of values:
|
* There are three types of values:
|
||||||
|
@ -520,6 +636,21 @@ QString CSMSettings::UserSettings::setting(const QString &viewKey, const QString
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVariant CSMSettings::UserSettings::value(const QString &viewKey, const QVariant &value)
|
||||||
|
{
|
||||||
|
if(value != QVariant())
|
||||||
|
{
|
||||||
|
mSettingDefinitions->setValue (viewKey, value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
else if(mSettingDefinitions->contains(viewKey))
|
||||||
|
{
|
||||||
|
return mSettingDefinitions->value (viewKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
bool CSMSettings::UserSettings::hasSettingDefinitions (const QString &viewKey) const
|
bool CSMSettings::UserSettings::hasSettingDefinitions (const QString &viewKey) const
|
||||||
{
|
{
|
||||||
return (mSettingDefinitions->contains (viewKey));
|
return (mSettingDefinitions->contains (viewKey));
|
||||||
|
|
|
@ -82,6 +82,8 @@ namespace CSMSettings {
|
||||||
|
|
||||||
QString setting(const QString &viewKey, const QString &value = QString());
|
QString setting(const QString &viewKey, const QString &value = QString());
|
||||||
|
|
||||||
|
QVariant value(const QString &viewKey, const QVariant &value = QVariant());
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void buildSettingModelDefaults();
|
void buildSettingModelDefaults();
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "birthsigncheck.hpp"
|
#include "birthsigncheck.hpp"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "classcheck.hpp"
|
#include "classcheck.hpp"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "factioncheck.hpp"
|
#include "factioncheck.hpp"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
133
apps/opencs/model/tools/magiceffectcheck.cpp
Normal file
133
apps/opencs/model/tools/magiceffectcheck.cpp
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
#include "magiceffectcheck.hpp"
|
||||||
|
|
||||||
|
#include <components/misc/resourcehelpers.hpp>
|
||||||
|
|
||||||
|
#include "../world/resources.hpp"
|
||||||
|
#include "../world/data.hpp"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
void addMessageIfNotEmpty(CSMDoc::Messages &messages, const CSMWorld::UniversalId &id, const std::string text)
|
||||||
|
{
|
||||||
|
if (!text.empty())
|
||||||
|
{
|
||||||
|
messages.push_back(std::make_pair(id, text));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSMTools::MagicEffectCheckStage::isTextureExists(const std::string &texture, bool isIcon) const
|
||||||
|
{
|
||||||
|
const CSMWorld::Resources &textures = isIcon ? mIcons : mTextures;
|
||||||
|
bool exists = false;
|
||||||
|
|
||||||
|
if (textures.searchId(texture) != -1)
|
||||||
|
{
|
||||||
|
exists = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string ddsTexture = texture;
|
||||||
|
if (Misc::ResourceHelpers::changeExtensionToDds(ddsTexture) && textures.searchId(ddsTexture) != -1)
|
||||||
|
{
|
||||||
|
exists = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return exists;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CSMTools::MagicEffectCheckStage::checkReferenceable(const std::string &id,
|
||||||
|
const CSMWorld::UniversalId &type,
|
||||||
|
const std::string &column) const
|
||||||
|
{
|
||||||
|
std::string error;
|
||||||
|
if (!id.empty())
|
||||||
|
{
|
||||||
|
CSMWorld::RefIdData::LocalIndex index = mReferenceables.getDataSet().searchId(id);
|
||||||
|
if (index.first == -1)
|
||||||
|
{
|
||||||
|
error = "No such " + column + " '" + id + "'";
|
||||||
|
}
|
||||||
|
else if (index.second != type.getType())
|
||||||
|
{
|
||||||
|
error = column + " is not of type " + type.getTypeName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CSMTools::MagicEffectCheckStage::checkSound(const std::string &id, const std::string &column) const
|
||||||
|
{
|
||||||
|
std::string error;
|
||||||
|
if (!id.empty() && mSounds.searchId(id) == -1)
|
||||||
|
{
|
||||||
|
error = "No such " + column + " '" + id + "'";
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSMTools::MagicEffectCheckStage::MagicEffectCheckStage(const CSMWorld::IdCollection<ESM::MagicEffect> &effects,
|
||||||
|
const CSMWorld::IdCollection<ESM::Sound> &sounds,
|
||||||
|
const CSMWorld::RefIdCollection &referenceables,
|
||||||
|
const CSMWorld::Resources &icons,
|
||||||
|
const CSMWorld::Resources &textures)
|
||||||
|
: mMagicEffects(effects),
|
||||||
|
mSounds(sounds),
|
||||||
|
mReferenceables(referenceables),
|
||||||
|
mIcons(icons),
|
||||||
|
mTextures(textures)
|
||||||
|
{}
|
||||||
|
|
||||||
|
int CSMTools::MagicEffectCheckStage::setup()
|
||||||
|
{
|
||||||
|
return mMagicEffects.getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMTools::MagicEffectCheckStage::perform(int stage, CSMDoc::Messages &messages)
|
||||||
|
{
|
||||||
|
ESM::MagicEffect effect = mMagicEffects.getRecord(stage).get();
|
||||||
|
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_MagicEffect, effect.mId);
|
||||||
|
|
||||||
|
if (effect.mData.mBaseCost < 0.0f)
|
||||||
|
{
|
||||||
|
messages.push_back(std::make_pair(id, "Base Cost is negative"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (effect.mIcon.empty())
|
||||||
|
{
|
||||||
|
messages.push_back(std::make_pair(id, "Icon is not specified"));
|
||||||
|
}
|
||||||
|
else if (!isTextureExists(effect.mIcon, true))
|
||||||
|
{
|
||||||
|
messages.push_back(std::make_pair(id, "No such Icon '" + effect.mIcon + "'"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!effect.mParticle.empty() && !isTextureExists(effect.mParticle, false))
|
||||||
|
{
|
||||||
|
messages.push_back(std::make_pair(id, "No such Particle '" + effect.mParticle + "'"));
|
||||||
|
}
|
||||||
|
|
||||||
|
addMessageIfNotEmpty(messages,
|
||||||
|
id,
|
||||||
|
checkReferenceable(effect.mCasting, CSMWorld::UniversalId::Type_Static, "Casting Object"));
|
||||||
|
addMessageIfNotEmpty(messages,
|
||||||
|
id,
|
||||||
|
checkReferenceable(effect.mHit, CSMWorld::UniversalId::Type_Static, "Hit Object"));
|
||||||
|
addMessageIfNotEmpty(messages,
|
||||||
|
id,
|
||||||
|
checkReferenceable(effect.mArea, CSMWorld::UniversalId::Type_Static, "Area Object"));
|
||||||
|
addMessageIfNotEmpty(messages,
|
||||||
|
id,
|
||||||
|
checkReferenceable(effect.mBolt, CSMWorld::UniversalId::Type_Weapon, "Bolt Object"));
|
||||||
|
|
||||||
|
addMessageIfNotEmpty(messages, id, checkSound(effect.mCastSound, "Casting Sound"));
|
||||||
|
addMessageIfNotEmpty(messages, id, checkSound(effect.mHitSound, "Hit Sound"));
|
||||||
|
addMessageIfNotEmpty(messages, id, checkSound(effect.mAreaSound, "Area Sound"));
|
||||||
|
addMessageIfNotEmpty(messages, id, checkSound(effect.mBoltSound, "Bolt Sound"));
|
||||||
|
|
||||||
|
if (effect.mDescription.empty())
|
||||||
|
{
|
||||||
|
messages.push_back(std::make_pair(id, "Description is empty"));
|
||||||
|
}
|
||||||
|
}
|
50
apps/opencs/model/tools/magiceffectcheck.hpp
Normal file
50
apps/opencs/model/tools/magiceffectcheck.hpp
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
#ifndef CSM_TOOLS_MAGICEFFECTCHECK_HPP
|
||||||
|
#define CSM_TOOLS_MAGICEFFECTCHECK_HPP
|
||||||
|
|
||||||
|
#include <components/esm/loadmgef.hpp>
|
||||||
|
#include <components/esm/loadsoun.hpp>
|
||||||
|
|
||||||
|
#include "../world/idcollection.hpp"
|
||||||
|
#include "../world/refidcollection.hpp"
|
||||||
|
|
||||||
|
#include "../doc/stage.hpp"
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
class Resources;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CSMTools
|
||||||
|
{
|
||||||
|
/// \brief VerifyStage: make sure that magic effect records are internally consistent
|
||||||
|
class MagicEffectCheckStage : public CSMDoc::Stage
|
||||||
|
{
|
||||||
|
const CSMWorld::IdCollection<ESM::MagicEffect> &mMagicEffects;
|
||||||
|
const CSMWorld::IdCollection<ESM::Sound> &mSounds;
|
||||||
|
const CSMWorld::RefIdCollection &mReferenceables;
|
||||||
|
const CSMWorld::Resources &mIcons;
|
||||||
|
const CSMWorld::Resources &mTextures;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isTextureExists(const std::string &texture, bool isIcon) const;
|
||||||
|
|
||||||
|
std::string checkReferenceable(const std::string &id,
|
||||||
|
const CSMWorld::UniversalId &type,
|
||||||
|
const std::string &column) const;
|
||||||
|
std::string checkSound(const std::string &id, const std::string &column) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MagicEffectCheckStage(const CSMWorld::IdCollection<ESM::MagicEffect> &effects,
|
||||||
|
const CSMWorld::IdCollection<ESM::Sound> &sounds,
|
||||||
|
const CSMWorld::RefIdCollection &referenceables,
|
||||||
|
const CSMWorld::Resources &icons,
|
||||||
|
const CSMWorld::Resources &textures);
|
||||||
|
|
||||||
|
virtual int setup();
|
||||||
|
///< \return number of steps
|
||||||
|
virtual void perform (int stage, CSMDoc::Messages &messages);
|
||||||
|
///< Messages resulting from this tage will be appended to \a messages.
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "mandatoryid.hpp"
|
#include "mandatoryid.hpp"
|
||||||
|
|
||||||
#include "../world/collectionbase.hpp"
|
#include "../world/collectionbase.hpp"
|
||||||
|
|
59
apps/opencs/model/tools/mergeoperation.cpp
Normal file
59
apps/opencs/model/tools/mergeoperation.cpp
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
|
||||||
|
#include "mergeoperation.hpp"
|
||||||
|
|
||||||
|
#include "../doc/state.hpp"
|
||||||
|
#include "../doc/document.hpp"
|
||||||
|
|
||||||
|
#include "mergestages.hpp"
|
||||||
|
|
||||||
|
CSMTools::MergeOperation::MergeOperation (CSMDoc::Document& document, ToUTF8::FromType encoding)
|
||||||
|
: CSMDoc::Operation (CSMDoc::State_Merging, true), mState (document)
|
||||||
|
{
|
||||||
|
appendStage (new StartMergeStage (mState));
|
||||||
|
|
||||||
|
appendStage (new MergeIdCollectionStage<ESM::Global> (mState, &CSMWorld::Data::getGlobals));
|
||||||
|
appendStage (new MergeIdCollectionStage<ESM::GameSetting> (mState, &CSMWorld::Data::getGmsts));
|
||||||
|
appendStage (new MergeIdCollectionStage<ESM::Skill> (mState, &CSMWorld::Data::getSkills));
|
||||||
|
appendStage (new MergeIdCollectionStage<ESM::Class> (mState, &CSMWorld::Data::getClasses));
|
||||||
|
appendStage (new MergeIdCollectionStage<ESM::Faction> (mState, &CSMWorld::Data::getFactions));
|
||||||
|
appendStage (new MergeIdCollectionStage<ESM::Race> (mState, &CSMWorld::Data::getRaces));
|
||||||
|
appendStage (new MergeIdCollectionStage<ESM::Sound> (mState, &CSMWorld::Data::getSounds));
|
||||||
|
appendStage (new MergeIdCollectionStage<ESM::Script> (mState, &CSMWorld::Data::getScripts));
|
||||||
|
appendStage (new MergeIdCollectionStage<ESM::Region> (mState, &CSMWorld::Data::getRegions));
|
||||||
|
appendStage (new MergeIdCollectionStage<ESM::BirthSign> (mState, &CSMWorld::Data::getBirthsigns));
|
||||||
|
appendStage (new MergeIdCollectionStage<ESM::Spell> (mState, &CSMWorld::Data::getSpells));
|
||||||
|
appendStage (new MergeIdCollectionStage<ESM::Dialogue> (mState, &CSMWorld::Data::getTopics));
|
||||||
|
appendStage (new MergeIdCollectionStage<ESM::Dialogue> (mState, &CSMWorld::Data::getJournals));
|
||||||
|
appendStage (new MergeIdCollectionStage<CSMWorld::Cell> (mState, &CSMWorld::Data::getCells));
|
||||||
|
appendStage (new MergeIdCollectionStage<ESM::Filter> (mState, &CSMWorld::Data::getFilters));
|
||||||
|
appendStage (new MergeIdCollectionStage<ESM::Enchantment> (mState, &CSMWorld::Data::getEnchantments));
|
||||||
|
appendStage (new MergeIdCollectionStage<ESM::BodyPart> (mState, &CSMWorld::Data::getBodyParts));
|
||||||
|
appendStage (new MergeIdCollectionStage<ESM::DebugProfile> (mState, &CSMWorld::Data::getDebugProfiles));
|
||||||
|
appendStage (new MergeIdCollectionStage<ESM::SoundGenerator> (mState, &CSMWorld::Data::getSoundGens));
|
||||||
|
appendStage (new MergeIdCollectionStage<ESM::MagicEffect> (mState, &CSMWorld::Data::getMagicEffects));
|
||||||
|
appendStage (new MergeIdCollectionStage<ESM::StartScript> (mState, &CSMWorld::Data::getStartScripts));
|
||||||
|
appendStage (new MergeIdCollectionStage<CSMWorld::Pathgrid, CSMWorld::SubCellCollection<CSMWorld::Pathgrid> > (mState, &CSMWorld::Data::getPathgrids));
|
||||||
|
appendStage (new MergeIdCollectionStage<CSMWorld::Info, CSMWorld::InfoCollection> (mState, &CSMWorld::Data::getTopicInfos));
|
||||||
|
appendStage (new MergeIdCollectionStage<CSMWorld::Info, CSMWorld::InfoCollection> (mState, &CSMWorld::Data::getJournalInfos));
|
||||||
|
appendStage (new MergeRefIdsStage (mState));
|
||||||
|
appendStage (new MergeReferencesStage (mState));
|
||||||
|
appendStage (new MergeReferencesStage (mState));
|
||||||
|
appendStage (new ListLandTexturesMergeStage (mState));
|
||||||
|
appendStage (new MergeLandTexturesStage (mState));
|
||||||
|
appendStage (new MergeLandStage (mState));
|
||||||
|
|
||||||
|
appendStage (new FinishMergedDocumentStage (mState, encoding));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMTools::MergeOperation::setTarget (std::auto_ptr<CSMDoc::Document> document)
|
||||||
|
{
|
||||||
|
mState.mTarget = document;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMTools::MergeOperation::operationDone()
|
||||||
|
{
|
||||||
|
CSMDoc::Operation::operationDone();
|
||||||
|
|
||||||
|
if (mState.mCompleted)
|
||||||
|
emit mergeDone (mState.mTarget.release());
|
||||||
|
}
|
45
apps/opencs/model/tools/mergeoperation.hpp
Normal file
45
apps/opencs/model/tools/mergeoperation.hpp
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#ifndef CSM_TOOLS_MERGEOPERATION_H
|
||||||
|
#define CSM_TOOLS_MERGEOPERATION_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <components/to_utf8/to_utf8.hpp>
|
||||||
|
|
||||||
|
#include "../doc/operation.hpp"
|
||||||
|
|
||||||
|
#include "mergestate.hpp"
|
||||||
|
|
||||||
|
namespace CSMDoc
|
||||||
|
{
|
||||||
|
class Document;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CSMTools
|
||||||
|
{
|
||||||
|
class MergeOperation : public CSMDoc::Operation
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
MergeState mState;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
MergeOperation (CSMDoc::Document& document, ToUTF8::FromType encoding);
|
||||||
|
|
||||||
|
/// \attention Do not call this function while a merge is running.
|
||||||
|
void setTarget (std::auto_ptr<CSMDoc::Document> document);
|
||||||
|
|
||||||
|
protected slots:
|
||||||
|
|
||||||
|
virtual void operationDone();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
/// \attention When this signal is emitted, *this hands over the ownership of the
|
||||||
|
/// document. This signal must be handled to avoid a leak.
|
||||||
|
void mergeDone (CSMDoc::Document *document);
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
258
apps/opencs/model/tools/mergestages.cpp
Normal file
258
apps/opencs/model/tools/mergestages.cpp
Normal file
|
@ -0,0 +1,258 @@
|
||||||
|
|
||||||
|
#include "mergestages.hpp"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
|
#include "mergestate.hpp"
|
||||||
|
|
||||||
|
#include "../doc/document.hpp"
|
||||||
|
#include "../world/data.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
CSMTools::StartMergeStage::StartMergeStage (MergeState& state)
|
||||||
|
: mState (state)
|
||||||
|
{}
|
||||||
|
|
||||||
|
int CSMTools::StartMergeStage::setup()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMTools::StartMergeStage::perform (int stage, CSMDoc::Messages& messages)
|
||||||
|
{
|
||||||
|
mState.mCompleted = false;
|
||||||
|
mState.mTextureIndices.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CSMTools::FinishMergedDocumentStage::FinishMergedDocumentStage (MergeState& state, ToUTF8::FromType encoding)
|
||||||
|
: mState (state), mEncoder (encoding)
|
||||||
|
{}
|
||||||
|
|
||||||
|
int CSMTools::FinishMergedDocumentStage::setup()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMTools::FinishMergedDocumentStage::perform (int stage, CSMDoc::Messages& messages)
|
||||||
|
{
|
||||||
|
// We know that the content file list contains at least two entries and that the first one
|
||||||
|
// does exist on disc (otherwise it would have been impossible to initiate a merge on that
|
||||||
|
// document).
|
||||||
|
boost::filesystem::path path = mState.mSource.getContentFiles()[0];
|
||||||
|
|
||||||
|
ESM::ESMReader reader;
|
||||||
|
reader.setEncoder (&mEncoder);
|
||||||
|
reader.open (path.string());
|
||||||
|
|
||||||
|
CSMWorld::MetaData source;
|
||||||
|
source.mId = "sys::meta";
|
||||||
|
source.load (reader);
|
||||||
|
|
||||||
|
CSMWorld::MetaData target = mState.mTarget->getData().getMetaData();
|
||||||
|
|
||||||
|
target.mAuthor = source.mAuthor;
|
||||||
|
target.mDescription = source.mDescription;
|
||||||
|
|
||||||
|
mState.mTarget->getData().setMetaData (target);
|
||||||
|
|
||||||
|
mState.mCompleted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CSMTools::MergeRefIdsStage::MergeRefIdsStage (MergeState& state) : mState (state) {}
|
||||||
|
|
||||||
|
int CSMTools::MergeRefIdsStage::setup()
|
||||||
|
{
|
||||||
|
return mState.mSource.getData().getReferenceables().getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMTools::MergeRefIdsStage::perform (int stage, CSMDoc::Messages& messages)
|
||||||
|
{
|
||||||
|
mState.mSource.getData().getReferenceables().copyTo (
|
||||||
|
stage, mState.mTarget->getData().getReferenceables());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CSMTools::MergeReferencesStage::MergeReferencesStage (MergeState& state)
|
||||||
|
: mState (state)
|
||||||
|
{}
|
||||||
|
|
||||||
|
int CSMTools::MergeReferencesStage::setup()
|
||||||
|
{
|
||||||
|
mIndex.clear();
|
||||||
|
return mState.mSource.getData().getReferences().getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMTools::MergeReferencesStage::perform (int stage, CSMDoc::Messages& messages)
|
||||||
|
{
|
||||||
|
const CSMWorld::Record<CSMWorld::CellRef>& record =
|
||||||
|
mState.mSource.getData().getReferences().getRecord (stage);
|
||||||
|
|
||||||
|
if (!record.isDeleted())
|
||||||
|
{
|
||||||
|
CSMWorld::CellRef ref = record.get();
|
||||||
|
|
||||||
|
ref.mOriginalCell = ref.mCell;
|
||||||
|
|
||||||
|
ref.mRefNum.mIndex = mIndex[Misc::StringUtils::lowerCase (ref.mCell)]++;
|
||||||
|
ref.mRefNum.mContentFile = 0;
|
||||||
|
|
||||||
|
CSMWorld::Record<CSMWorld::CellRef> newRecord (
|
||||||
|
CSMWorld::RecordBase::State_ModifiedOnly, 0, &ref);
|
||||||
|
|
||||||
|
mState.mTarget->getData().getReferences().appendRecord (newRecord);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CSMTools::ListLandTexturesMergeStage::ListLandTexturesMergeStage (MergeState& state)
|
||||||
|
: mState (state)
|
||||||
|
{}
|
||||||
|
|
||||||
|
int CSMTools::ListLandTexturesMergeStage::setup()
|
||||||
|
{
|
||||||
|
return mState.mSource.getData().getLand().getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMTools::ListLandTexturesMergeStage::perform (int stage, CSMDoc::Messages& messages)
|
||||||
|
{
|
||||||
|
const CSMWorld::Record<CSMWorld::Land>& record =
|
||||||
|
mState.mSource.getData().getLand().getRecord (stage);
|
||||||
|
|
||||||
|
if (!record.isDeleted())
|
||||||
|
{
|
||||||
|
const CSMWorld::Land& land = record.get();
|
||||||
|
|
||||||
|
// make sure record is loaded
|
||||||
|
land.loadData (ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML |
|
||||||
|
ESM::Land::DATA_VCLR | ESM::Land::DATA_VTEX | ESM::Land::DATA_WNAM);
|
||||||
|
|
||||||
|
if (const ESM::Land::LandData *data = land.getLandData (ESM::Land::DATA_VTEX))
|
||||||
|
{
|
||||||
|
// list texture indices
|
||||||
|
std::pair<uint16_t, int> key;
|
||||||
|
key.second = land.mPlugin;
|
||||||
|
|
||||||
|
for (int i=0; i<ESM::Land::LAND_NUM_TEXTURES; ++i)
|
||||||
|
{
|
||||||
|
key.first = data->mTextures[i];
|
||||||
|
|
||||||
|
mState.mTextureIndices[key] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CSMTools::MergeLandTexturesStage::MergeLandTexturesStage (MergeState& state)
|
||||||
|
: mState (state), mNext (mState.mTextureIndices.end())
|
||||||
|
{}
|
||||||
|
|
||||||
|
int CSMTools::MergeLandTexturesStage::setup()
|
||||||
|
{
|
||||||
|
// Should use the size of mState.mTextureIndices instead, but that is not available at this
|
||||||
|
// point. Unless there are any errors in the land and land texture records this will not
|
||||||
|
// make a difference.
|
||||||
|
return mState.mSource.getData().getLandTextures().getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMTools::MergeLandTexturesStage::perform (int stage, CSMDoc::Messages& messages)
|
||||||
|
{
|
||||||
|
if (stage==0)
|
||||||
|
mNext = mState.mTextureIndices.begin();
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (mNext==mState.mTextureIndices.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
mNext->second = stage+1;
|
||||||
|
|
||||||
|
std::ostringstream stream;
|
||||||
|
stream << mNext->first.first-1 << "_" << mNext->first.second;
|
||||||
|
|
||||||
|
int index = mState.mSource.getData().getLandTextures().searchId (stream.str());
|
||||||
|
|
||||||
|
if (index!=-1)
|
||||||
|
{
|
||||||
|
CSMWorld::LandTexture texture =
|
||||||
|
mState.mSource.getData().getLandTextures().getRecord (index).get();
|
||||||
|
|
||||||
|
std::ostringstream stream;
|
||||||
|
stream << mNext->second-1 << "_0";
|
||||||
|
|
||||||
|
texture.mIndex = mNext->second-1;
|
||||||
|
texture.mId = stream.str();
|
||||||
|
|
||||||
|
CSMWorld::Record<CSMWorld::LandTexture> newRecord (
|
||||||
|
CSMWorld::RecordBase::State_ModifiedOnly, 0, &texture);
|
||||||
|
|
||||||
|
mState.mTarget->getData().getLandTextures().appendRecord (newRecord);
|
||||||
|
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
++mNext;
|
||||||
|
}
|
||||||
|
while (!found);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CSMTools::MergeLandStage::MergeLandStage (MergeState& state) : mState (state) {}
|
||||||
|
|
||||||
|
int CSMTools::MergeLandStage::setup()
|
||||||
|
{
|
||||||
|
return mState.mSource.getData().getLand().getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMTools::MergeLandStage::perform (int stage, CSMDoc::Messages& messages)
|
||||||
|
{
|
||||||
|
const CSMWorld::Record<CSMWorld::Land>& record =
|
||||||
|
mState.mSource.getData().getLand().getRecord (stage);
|
||||||
|
|
||||||
|
if (!record.isDeleted())
|
||||||
|
{
|
||||||
|
const CSMWorld::Land& land = record.get();
|
||||||
|
|
||||||
|
land.loadData (ESM::Land::DATA_VCLR | ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML |
|
||||||
|
ESM::Land::DATA_VTEX | ESM::Land::DATA_WNAM);
|
||||||
|
|
||||||
|
CSMWorld::Land newLand (land);
|
||||||
|
|
||||||
|
newLand.mEsm = 0; // avoid potential dangling pointer (ESMReader isn't needed anyway,
|
||||||
|
// because record is already fully loaded)
|
||||||
|
newLand.mPlugin = 0;
|
||||||
|
|
||||||
|
if (land.mDataTypes & ESM::Land::DATA_VTEX)
|
||||||
|
{
|
||||||
|
// adjust land texture references
|
||||||
|
if (ESM::Land::LandData *data = newLand.getLandData())
|
||||||
|
{
|
||||||
|
std::pair<uint16_t, int> key;
|
||||||
|
key.second = land.mPlugin;
|
||||||
|
|
||||||
|
for (int i=0; i<ESM::Land::LAND_NUM_TEXTURES; ++i)
|
||||||
|
{
|
||||||
|
key.first = data->mTextures[i];
|
||||||
|
std::map<std::pair<uint16_t, int>, int>::const_iterator iter =
|
||||||
|
mState.mTextureIndices.find (key);
|
||||||
|
|
||||||
|
if (iter!=mState.mTextureIndices.end())
|
||||||
|
data->mTextures[i] = iter->second;
|
||||||
|
else
|
||||||
|
data->mTextures[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CSMWorld::Record<CSMWorld::Land> newRecord (
|
||||||
|
CSMWorld::RecordBase::State_ModifiedOnly, 0, &newLand);
|
||||||
|
|
||||||
|
mState.mTarget->getData().getLand().appendRecord (newRecord);
|
||||||
|
}
|
||||||
|
}
|
166
apps/opencs/model/tools/mergestages.hpp
Normal file
166
apps/opencs/model/tools/mergestages.hpp
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
#ifndef CSM_TOOLS_MERGESTAGES_H
|
||||||
|
#define CSM_TOOLS_MERGESTAGES_H
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <components/to_utf8/to_utf8.hpp>
|
||||||
|
|
||||||
|
#include "../doc/stage.hpp"
|
||||||
|
|
||||||
|
#include "../world/data.hpp"
|
||||||
|
|
||||||
|
#include "mergestate.hpp"
|
||||||
|
|
||||||
|
namespace CSMTools
|
||||||
|
{
|
||||||
|
class StartMergeStage : public CSMDoc::Stage
|
||||||
|
{
|
||||||
|
MergeState& mState;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
StartMergeStage (MergeState& state);
|
||||||
|
|
||||||
|
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.
|
||||||
|
};
|
||||||
|
|
||||||
|
class FinishMergedDocumentStage : public CSMDoc::Stage
|
||||||
|
{
|
||||||
|
MergeState& mState;
|
||||||
|
ToUTF8::Utf8Encoder mEncoder;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
FinishMergedDocumentStage (MergeState& state, ToUTF8::FromType encoding);
|
||||||
|
|
||||||
|
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.
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename RecordType, typename Collection = CSMWorld::IdCollection<RecordType> >
|
||||||
|
class MergeIdCollectionStage : public CSMDoc::Stage
|
||||||
|
{
|
||||||
|
MergeState& mState;
|
||||||
|
Collection& (CSMWorld::Data::*mAccessor)();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
MergeIdCollectionStage (MergeState& state, Collection& (CSMWorld::Data::*accessor)());
|
||||||
|
|
||||||
|
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.
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename RecordType, typename Collection>
|
||||||
|
MergeIdCollectionStage<RecordType, Collection>::MergeIdCollectionStage (MergeState& state, Collection& (CSMWorld::Data::*accessor)())
|
||||||
|
: mState (state), mAccessor (accessor)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template<typename RecordType, typename Collection>
|
||||||
|
int MergeIdCollectionStage<RecordType, Collection>::setup()
|
||||||
|
{
|
||||||
|
return (mState.mSource.getData().*mAccessor)().getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename RecordType, typename Collection>
|
||||||
|
void MergeIdCollectionStage<RecordType, Collection>::perform (int stage, CSMDoc::Messages& messages)
|
||||||
|
{
|
||||||
|
const Collection& source = (mState.mSource.getData().*mAccessor)();
|
||||||
|
Collection& target = (mState.mTarget->getData().*mAccessor)();
|
||||||
|
|
||||||
|
const CSMWorld::Record<RecordType>& record = source.getRecord (stage);
|
||||||
|
|
||||||
|
if (!record.isDeleted())
|
||||||
|
target.appendRecord (CSMWorld::Record<RecordType> (CSMWorld::RecordBase::State_ModifiedOnly, 0, &record.get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
class MergeRefIdsStage : public CSMDoc::Stage
|
||||||
|
{
|
||||||
|
MergeState& mState;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
MergeRefIdsStage (MergeState& state);
|
||||||
|
|
||||||
|
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.
|
||||||
|
};
|
||||||
|
|
||||||
|
class MergeReferencesStage : public CSMDoc::Stage
|
||||||
|
{
|
||||||
|
MergeState& mState;
|
||||||
|
std::map<std::string, int> mIndex;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
MergeReferencesStage (MergeState& state);
|
||||||
|
|
||||||
|
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.
|
||||||
|
};
|
||||||
|
|
||||||
|
class ListLandTexturesMergeStage : public CSMDoc::Stage
|
||||||
|
{
|
||||||
|
MergeState& mState;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
ListLandTexturesMergeStage (MergeState& state);
|
||||||
|
|
||||||
|
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.
|
||||||
|
};
|
||||||
|
|
||||||
|
class MergeLandTexturesStage : public CSMDoc::Stage
|
||||||
|
{
|
||||||
|
MergeState& mState;
|
||||||
|
std::map<std::pair<uint16_t, int>, int>::iterator mNext;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
MergeLandTexturesStage (MergeState& state);
|
||||||
|
|
||||||
|
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.
|
||||||
|
};
|
||||||
|
|
||||||
|
class MergeLandStage : public CSMDoc::Stage
|
||||||
|
{
|
||||||
|
MergeState& mState;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
MergeLandStage (MergeState& state);
|
||||||
|
|
||||||
|
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.
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
24
apps/opencs/model/tools/mergestate.hpp
Normal file
24
apps/opencs/model/tools/mergestate.hpp
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef CSM_TOOLS_MERGESTATE_H
|
||||||
|
#define CSM_TOOLS_MERGESTATE_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include "../doc/document.hpp"
|
||||||
|
|
||||||
|
namespace CSMTools
|
||||||
|
{
|
||||||
|
struct MergeState
|
||||||
|
{
|
||||||
|
std::auto_ptr<CSMDoc::Document> mTarget;
|
||||||
|
CSMDoc::Document& mSource;
|
||||||
|
bool mCompleted;
|
||||||
|
std::map<std::pair<uint16_t, int>, int> mTextureIndices; // (texture, content file) -> new texture
|
||||||
|
|
||||||
|
MergeState (CSMDoc::Document& source) : mSource (source), mCompleted (false) {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -30,9 +30,9 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message
|
||||||
|
|
||||||
// check the number of pathgrid points
|
// check the number of pathgrid points
|
||||||
if (pathgrid.mData.mS2 > static_cast<int>(pathgrid.mPoints.size()))
|
if (pathgrid.mData.mS2 > static_cast<int>(pathgrid.mPoints.size()))
|
||||||
messages.push_back (std::make_pair (id, pathgrid.mId + " has less points than expected"));
|
messages.add (id, pathgrid.mId + " has less points than expected", "", CSMDoc::Message::Severity_Error);
|
||||||
else if (pathgrid.mData.mS2 > static_cast<int>(pathgrid.mPoints.size()))
|
else if (pathgrid.mData.mS2 > static_cast<int>(pathgrid.mPoints.size()))
|
||||||
messages.push_back (std::make_pair (id, pathgrid.mId + " has more points than expected"));
|
messages.add (id, pathgrid.mId + " has more points than expected", "", CSMDoc::Message::Severity_Error);
|
||||||
|
|
||||||
std::vector<CSMTools::Point> pointList(pathgrid.mPoints.size());
|
std::vector<CSMTools::Point> pointList(pathgrid.mPoints.size());
|
||||||
std::vector<int> duplList;
|
std::vector<int> duplList;
|
||||||
|
@ -51,7 +51,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message
|
||||||
std::ostringstream ss;
|
std::ostringstream ss;
|
||||||
ss << "has a duplicate edge between points" << pathgrid.mEdges[i].mV0
|
ss << "has a duplicate edge between points" << pathgrid.mEdges[i].mV0
|
||||||
<< " and " << pathgrid.mEdges[i].mV1;
|
<< " and " << pathgrid.mEdges[i].mV1;
|
||||||
messages.push_back (std::make_pair (id, pathgrid.mId + ss.str()));
|
messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Error);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message
|
||||||
{
|
{
|
||||||
std::ostringstream ss;
|
std::ostringstream ss;
|
||||||
ss << " has an edge connecting a non-existent point " << pathgrid.mEdges[i].mV0;
|
ss << " has an edge connecting a non-existent point " << pathgrid.mEdges[i].mV0;
|
||||||
messages.push_back (std::make_pair (id, pathgrid.mId + ss.str()));
|
messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,13 +75,13 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message
|
||||||
{
|
{
|
||||||
std::ostringstream ss;
|
std::ostringstream ss;
|
||||||
ss << " has has less edges than expected for point " << i;
|
ss << " has has less edges than expected for point " << i;
|
||||||
messages.push_back (std::make_pair (id, pathgrid.mId + ss.str()));
|
messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Error);
|
||||||
}
|
}
|
||||||
else if (pathgrid.mPoints[i].mConnectionNum < pointList[i].mConnectionNum)
|
else if (pathgrid.mPoints[i].mConnectionNum < pointList[i].mConnectionNum)
|
||||||
{
|
{
|
||||||
std::ostringstream ss;
|
std::ostringstream ss;
|
||||||
ss << " has has more edges than expected for point " << i;
|
ss << " has has more edges than expected for point " << i;
|
||||||
messages.push_back (std::make_pair (id, pathgrid.mId + ss.str()));
|
messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that edges are bidirectional
|
// check that edges are bidirectional
|
||||||
|
@ -101,7 +101,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message
|
||||||
{
|
{
|
||||||
std::ostringstream ss;
|
std::ostringstream ss;
|
||||||
ss << " has a missing edge between points " << i << " and " << pointList[i].mOtherIndex[j];
|
ss << " has a missing edge between points " << i << " and " << pointList[i].mOtherIndex[j];
|
||||||
messages.push_back (std::make_pair (id, pathgrid.mId + ss.str()));
|
messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message
|
||||||
<< ") x=" << pathgrid.mPoints[i].mX
|
<< ") x=" << pathgrid.mPoints[i].mX
|
||||||
<< ", y=" << pathgrid.mPoints[i].mY
|
<< ", y=" << pathgrid.mPoints[i].mY
|
||||||
<< ", z=" << pathgrid.mPoints[i].mZ;
|
<< ", z=" << pathgrid.mPoints[i].mZ;
|
||||||
messages.push_back (std::make_pair (id, pathgrid.mId + ss.str()));
|
messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Warning);
|
||||||
|
|
||||||
duplList.push_back(i);
|
duplList.push_back(i);
|
||||||
break;
|
break;
|
||||||
|
@ -143,7 +143,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message
|
||||||
<< ") x=" << pathgrid.mPoints[i].mX
|
<< ") x=" << pathgrid.mPoints[i].mX
|
||||||
<< ", y=" << pathgrid.mPoints[i].mY
|
<< ", y=" << pathgrid.mPoints[i].mY
|
||||||
<< ", z=" << pathgrid.mPoints[i].mZ;
|
<< ", z=" << pathgrid.mPoints[i].mZ;
|
||||||
messages.push_back (std::make_pair (id, pathgrid.mId + ss.str()));
|
messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Warning);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "racecheck.hpp"
|
#include "racecheck.hpp"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
|
@ -468,6 +468,9 @@ void CSMTools::ReferenceableCheckStage::creatureCheck (
|
||||||
if (creature.mData.mGold < 0) //It seems that this is for gold in merchant creatures
|
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 "));
|
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 that mentioned scripts exist
|
// Check that mentioned scripts exist
|
||||||
scriptCheck<ESM::Creature>(creature, messages, id.toString());
|
scriptCheck<ESM::Creature>(creature, messages, id.toString());
|
||||||
}
|
}
|
||||||
|
@ -648,7 +651,7 @@ void CSMTools::ReferenceableCheckStage::npcCheck (
|
||||||
|
|
||||||
if (npc.mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS) //12 = autocalculated
|
if (npc.mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS) //12 = autocalculated
|
||||||
{
|
{
|
||||||
if ((npc.mFlags & ESM::NPC::Autocalc) == 0) //0x0008 = autocalculated flag
|
if ((npc.mFlags & ESM::NPC::Autocalc) == 0) //0x0010 = autocalculated flag
|
||||||
{
|
{
|
||||||
messages.push_back (std::make_pair (id, npc.mId + " mNpdtType or flags mismatch!")); //should not happend?
|
messages.push_back (std::make_pair (id, npc.mId + " mNpdtType or flags mismatch!")); //should not happend?
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "regioncheck.hpp"
|
#include "regioncheck.hpp"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "reportmodel.hpp"
|
#include "reportmodel.hpp"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
@ -6,24 +5,18 @@
|
||||||
|
|
||||||
#include "../world/columns.hpp"
|
#include "../world/columns.hpp"
|
||||||
|
|
||||||
CSMTools::ReportModel::Line::Line (const CSMWorld::UniversalId& id, const std::string& message,
|
CSMTools::ReportModel::ReportModel (bool fieldColumn, bool severityColumn)
|
||||||
const std::string& hint)
|
: mColumnField (-1), mColumnSeverity (-1)
|
||||||
: mId (id), mMessage (message), mHint (hint)
|
|
||||||
{}
|
|
||||||
|
|
||||||
CSMTools::ReportModel::ReportModel (bool fieldColumn)
|
|
||||||
{
|
{
|
||||||
if (fieldColumn)
|
int index = 3;
|
||||||
{
|
|
||||||
mColumnField = 3;
|
|
||||||
mColumnDescription = 4;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mColumnDescription = 3;
|
|
||||||
|
|
||||||
mColumnField = -1;
|
if (severityColumn)
|
||||||
}
|
mColumnSeverity = index++;
|
||||||
|
|
||||||
|
if (fieldColumn)
|
||||||
|
mColumnField = index++;
|
||||||
|
|
||||||
|
mColumnDescription = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CSMTools::ReportModel::rowCount (const QModelIndex & parent) const
|
int CSMTools::ReportModel::rowCount (const QModelIndex & parent) const
|
||||||
|
@ -89,6 +82,12 @@ QVariant CSMTools::ReportModel::data (const QModelIndex & index, int role) const
|
||||||
return QString::fromUtf8 (field.c_str());
|
return QString::fromUtf8 (field.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (index.column()==mColumnSeverity)
|
||||||
|
{
|
||||||
|
return QString::fromUtf8 (
|
||||||
|
CSMDoc::Message::toString (mRows.at (index.row()).mSeverity).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,6 +111,9 @@ QVariant CSMTools::ReportModel::headerData (int section, Qt::Orientation orienta
|
||||||
if (section==mColumnField)
|
if (section==mColumnField)
|
||||||
return "Field";
|
return "Field";
|
||||||
|
|
||||||
|
if (section==mColumnSeverity)
|
||||||
|
return "Severity";
|
||||||
|
|
||||||
return "-";
|
return "-";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,19 +134,18 @@ bool CSMTools::ReportModel::removeRows (int row, int count, const QModelIndex& p
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::ReportModel::add (const CSMWorld::UniversalId& id, const std::string& message,
|
void CSMTools::ReportModel::add (const CSMDoc::Message& message)
|
||||||
const std::string& hint)
|
|
||||||
{
|
{
|
||||||
beginInsertRows (QModelIndex(), mRows.size(), mRows.size());
|
beginInsertRows (QModelIndex(), mRows.size(), mRows.size());
|
||||||
|
|
||||||
mRows.push_back (Line (id, message, hint));
|
mRows.push_back (message);
|
||||||
|
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::ReportModel::flagAsReplaced (int index)
|
void CSMTools::ReportModel::flagAsReplaced (int index)
|
||||||
{
|
{
|
||||||
Line& line = mRows.at (index);
|
CSMDoc::Message& line = mRows.at (index);
|
||||||
std::string hint = line.mHint;
|
std::string hint = line.mHint;
|
||||||
|
|
||||||
if (hint.empty() || hint[0]!='R')
|
if (hint.empty() || hint[0]!='R')
|
||||||
|
@ -176,3 +177,16 @@ void CSMTools::ReportModel::clear()
|
||||||
endRemoveRows();
|
endRemoveRows();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CSMTools::ReportModel::countErrors() const
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for (std::vector<CSMDoc::Messages::Message>::const_iterator iter (mRows.begin());
|
||||||
|
iter!=mRows.end(); ++iter)
|
||||||
|
if (iter->mSeverity==CSMDoc::Message::Severity_Error ||
|
||||||
|
iter->mSeverity==CSMDoc::Message::Severity_SeriousError)
|
||||||
|
++count;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
#include <QAbstractTableModel>
|
#include <QAbstractTableModel>
|
||||||
|
|
||||||
|
#include "../doc/messages.hpp"
|
||||||
|
|
||||||
#include "../world/universalid.hpp"
|
#include "../world/universalid.hpp"
|
||||||
|
|
||||||
namespace CSMTools
|
namespace CSMTools
|
||||||
|
@ -14,17 +16,7 @@ namespace CSMTools
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
struct Line
|
std::vector<CSMDoc::Messages::Message> mRows;
|
||||||
{
|
|
||||||
Line (const CSMWorld::UniversalId& id, const std::string& message,
|
|
||||||
const std::string& hint);
|
|
||||||
|
|
||||||
CSMWorld::UniversalId mId;
|
|
||||||
std::string mMessage;
|
|
||||||
std::string mHint;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<Line> mRows;
|
|
||||||
|
|
||||||
// Fixed columns
|
// Fixed columns
|
||||||
enum Columns
|
enum Columns
|
||||||
|
@ -35,10 +27,11 @@ namespace CSMTools
|
||||||
// Configurable columns
|
// Configurable columns
|
||||||
int mColumnDescription;
|
int mColumnDescription;
|
||||||
int mColumnField;
|
int mColumnField;
|
||||||
|
int mColumnSeverity;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ReportModel (bool fieldColumn = false);
|
ReportModel (bool fieldColumn = false, bool severityColumn = true);
|
||||||
|
|
||||||
virtual int rowCount (const QModelIndex & parent = QModelIndex()) const;
|
virtual int rowCount (const QModelIndex & parent = QModelIndex()) const;
|
||||||
|
|
||||||
|
@ -50,8 +43,7 @@ namespace CSMTools
|
||||||
|
|
||||||
virtual bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex());
|
virtual bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex());
|
||||||
|
|
||||||
void add (const CSMWorld::UniversalId& id, const std::string& message,
|
void add (const CSMDoc::Message& message);
|
||||||
const std::string& hint = "");
|
|
||||||
|
|
||||||
void flagAsReplaced (int index);
|
void flagAsReplaced (int index);
|
||||||
|
|
||||||
|
@ -60,6 +52,9 @@ namespace CSMTools
|
||||||
std::string getHint (int row) const;
|
std::string getHint (int row) const;
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
// Return number of messages with Error or SeriousError severity.
|
||||||
|
int countErrors() const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "scriptcheck.hpp"
|
#include "scriptcheck.hpp"
|
||||||
|
|
||||||
#include <components/compiler/tokenloc.hpp>
|
#include <components/compiler/tokenloc.hpp>
|
||||||
|
@ -11,6 +10,17 @@
|
||||||
|
|
||||||
#include "../world/data.hpp"
|
#include "../world/data.hpp"
|
||||||
|
|
||||||
|
CSMDoc::Message::Severity CSMTools::ScriptCheckStage::getSeverity (Type type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case WarningMessage: return CSMDoc::Message::Severity_Warning;
|
||||||
|
case ErrorMessage: return CSMDoc::Message::Severity_Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CSMDoc::Message::Severity_SeriousError;
|
||||||
|
}
|
||||||
|
|
||||||
void CSMTools::ScriptCheckStage::report (const std::string& message, const Compiler::TokenLoc& loc,
|
void CSMTools::ScriptCheckStage::report (const std::string& message, const Compiler::TokenLoc& loc,
|
||||||
Type type)
|
Type type)
|
||||||
{
|
{
|
||||||
|
@ -18,11 +28,6 @@ void CSMTools::ScriptCheckStage::report (const std::string& message, const Compi
|
||||||
|
|
||||||
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId);
|
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId);
|
||||||
|
|
||||||
if (type==ErrorMessage)
|
|
||||||
stream << "error ";
|
|
||||||
else
|
|
||||||
stream << "warning ";
|
|
||||||
|
|
||||||
stream
|
stream
|
||||||
<< "script " << mFile
|
<< "script " << mFile
|
||||||
<< ", line " << loc.mLine << ", column " << loc.mColumn
|
<< ", line " << loc.mLine << ", column " << loc.mColumn
|
||||||
|
@ -32,19 +37,21 @@ void CSMTools::ScriptCheckStage::report (const std::string& message, const Compi
|
||||||
|
|
||||||
hintStream << "l:" << loc.mLine << " " << loc.mColumn;
|
hintStream << "l:" << loc.mLine << " " << loc.mColumn;
|
||||||
|
|
||||||
mMessages->add (id, stream.str(), hintStream.str());
|
mMessages->add (id, stream.str(), hintStream.str(), getSeverity (type));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::ScriptCheckStage::report (const std::string& message, Type type)
|
void CSMTools::ScriptCheckStage::report (const std::string& message, Type type)
|
||||||
{
|
{
|
||||||
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId);
|
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId);
|
||||||
|
|
||||||
mMessages->push_back (std::make_pair (id,
|
std::ostringstream stream;
|
||||||
(type==ErrorMessage ? "error: " : "warning: ") + message));
|
stream << "script " << mFile << ": " << message;
|
||||||
|
|
||||||
|
mMessages->add (id, stream.str(), "", getSeverity (type));
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMTools::ScriptCheckStage::ScriptCheckStage (const CSMDoc::Document& document)
|
CSMTools::ScriptCheckStage::ScriptCheckStage (const CSMDoc::Document& document)
|
||||||
: mDocument (document), mContext (document.getData()), mMessages (0)
|
: mDocument (document), mContext (document.getData()), mMessages (0), mWarningMode (Mode_Ignore)
|
||||||
{
|
{
|
||||||
/// \todo add an option to configure warning mode
|
/// \todo add an option to configure warning mode
|
||||||
setWarningsMode (0);
|
setWarningsMode (0);
|
||||||
|
@ -58,6 +65,7 @@ int CSMTools::ScriptCheckStage::setup()
|
||||||
mContext.clear();
|
mContext.clear();
|
||||||
mMessages = 0;
|
mMessages = 0;
|
||||||
mId.clear();
|
mId.clear();
|
||||||
|
Compiler::ErrorHandler::reset();
|
||||||
|
|
||||||
return mDocument.getData().getScripts().getSize();
|
return mDocument.getData().getScripts().getSize();
|
||||||
}
|
}
|
||||||
|
@ -72,6 +80,13 @@ void CSMTools::ScriptCheckStage::perform (int stage, CSMDoc::Messages& messages)
|
||||||
|
|
||||||
mMessages = &messages;
|
mMessages = &messages;
|
||||||
|
|
||||||
|
switch (mWarningMode)
|
||||||
|
{
|
||||||
|
case Mode_Ignore: setWarningsMode (0); break;
|
||||||
|
case Mode_Normal: setWarningsMode (1); break;
|
||||||
|
case Mode_Strict: setWarningsMode (2); break;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const CSMWorld::Data& data = mDocument.getData();
|
const CSMWorld::Data& data = mDocument.getData();
|
||||||
|
@ -93,9 +108,24 @@ void CSMTools::ScriptCheckStage::perform (int stage, CSMDoc::Messages& messages)
|
||||||
{
|
{
|
||||||
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId);
|
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId);
|
||||||
|
|
||||||
messages.push_back (std::make_pair (id,
|
std::ostringstream stream;
|
||||||
std::string ("Critical compile error: ") + error.what()));
|
stream << "script " << mFile << ": " << error.what();
|
||||||
|
|
||||||
|
messages.add (id, stream.str(), "", CSMDoc::Message::Severity_SeriousError);
|
||||||
}
|
}
|
||||||
|
|
||||||
mMessages = 0;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -18,12 +18,22 @@ namespace CSMTools
|
||||||
/// \brief VerifyStage: make sure that scripts compile
|
/// \brief VerifyStage: make sure that scripts compile
|
||||||
class ScriptCheckStage : public CSMDoc::Stage, private Compiler::ErrorHandler
|
class ScriptCheckStage : public CSMDoc::Stage, private Compiler::ErrorHandler
|
||||||
{
|
{
|
||||||
|
enum WarningMode
|
||||||
|
{
|
||||||
|
Mode_Ignore,
|
||||||
|
Mode_Normal,
|
||||||
|
Mode_Strict
|
||||||
|
};
|
||||||
|
|
||||||
const CSMDoc::Document& mDocument;
|
const CSMDoc::Document& mDocument;
|
||||||
Compiler::Extensions mExtensions;
|
Compiler::Extensions mExtensions;
|
||||||
CSMWorld::ScriptContext mContext;
|
CSMWorld::ScriptContext mContext;
|
||||||
std::string mId;
|
std::string mId;
|
||||||
std::string mFile;
|
std::string mFile;
|
||||||
CSMDoc::Messages *mMessages;
|
CSMDoc::Messages *mMessages;
|
||||||
|
WarningMode mWarningMode;
|
||||||
|
|
||||||
|
CSMDoc::Message::Severity getSeverity (Type type);
|
||||||
|
|
||||||
virtual void report (const std::string& message, const Compiler::TokenLoc& loc, Type type);
|
virtual void report (const std::string& message, const Compiler::TokenLoc& loc, Type type);
|
||||||
///< Report error to the user.
|
///< Report error to the user.
|
||||||
|
@ -40,6 +50,8 @@ namespace CSMTools
|
||||||
|
|
||||||
virtual void perform (int stage, CSMDoc::Messages& messages);
|
virtual void perform (int stage, CSMDoc::Messages& messages);
|
||||||
///< Messages resulting from this tage will be appended to \a messages.
|
///< Messages resulting from this tage will be appended to \a messages.
|
||||||
|
|
||||||
|
virtual void updateUserSetting (const QString& name, const QStringList& value);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "search.hpp"
|
#include "search.hpp"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
@ -280,7 +279,7 @@ void CSMTools::Search::replace (CSMDoc::Document& document, CSMWorld::IdTableBas
|
||||||
bool CSMTools::Search::verify (CSMDoc::Document& document, CSMWorld::IdTableBase *model,
|
bool CSMTools::Search::verify (CSMDoc::Document& document, CSMWorld::IdTableBase *model,
|
||||||
const CSMWorld::UniversalId& id, const std::string& messageHint) const
|
const CSMWorld::UniversalId& id, const std::string& messageHint) const
|
||||||
{
|
{
|
||||||
CSMDoc::Messages messages;
|
CSMDoc::Messages messages (CSMDoc::Message::Severity_Info);
|
||||||
|
|
||||||
int row = model->getModelIndex (id.getId(),
|
int row = model->getModelIndex (id.getId(),
|
||||||
model->findColumnIndex (CSMWorld::Columns::ColumnId_Id)).row();
|
model->findColumnIndex (CSMWorld::Columns::ColumnId_Id)).row();
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "searchoperation.hpp"
|
#include "searchoperation.hpp"
|
||||||
|
|
||||||
#include "../doc/state.hpp"
|
#include "../doc/state.hpp"
|
||||||
|
@ -21,6 +20,8 @@ CSMTools::SearchOperation::SearchOperation (CSMDoc::Document& document)
|
||||||
iter!=types.end(); ++iter)
|
iter!=types.end(); ++iter)
|
||||||
appendStage (new SearchStage (&dynamic_cast<CSMWorld::IdTableBase&> (
|
appendStage (new SearchStage (&dynamic_cast<CSMWorld::IdTableBase&> (
|
||||||
*document.getData().getTableModel (*iter))));
|
*document.getData().getTableModel (*iter))));
|
||||||
|
|
||||||
|
setDefaultSeverity (CSMDoc::Message::Severity_Info);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::SearchOperation::configure (const Search& search)
|
void CSMTools::SearchOperation::configure (const Search& search)
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "searchstage.hpp"
|
#include "searchstage.hpp"
|
||||||
|
|
||||||
#include "../world/idtablebase.hpp"
|
#include "../world/idtablebase.hpp"
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "skillcheck.hpp"
|
#include "skillcheck.hpp"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "soundcheck.hpp"
|
#include "soundcheck.hpp"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
53
apps/opencs/model/tools/soundgencheck.cpp
Normal file
53
apps/opencs/model/tools/soundgencheck.cpp
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
#include "soundgencheck.hpp"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "../world/refiddata.hpp"
|
||||||
|
#include "../world/universalid.hpp"
|
||||||
|
|
||||||
|
CSMTools::SoundGenCheckStage::SoundGenCheckStage(const CSMWorld::IdCollection<ESM::SoundGenerator> &soundGens,
|
||||||
|
const CSMWorld::IdCollection<ESM::Sound> &sounds,
|
||||||
|
const CSMWorld::RefIdCollection &referenceables)
|
||||||
|
: mSoundGens(soundGens),
|
||||||
|
mSounds(sounds),
|
||||||
|
mReferenceables(referenceables)
|
||||||
|
{}
|
||||||
|
|
||||||
|
int CSMTools::SoundGenCheckStage::setup()
|
||||||
|
{
|
||||||
|
return mSoundGens.getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMTools::SoundGenCheckStage::perform(int stage, CSMDoc::Messages &messages)
|
||||||
|
{
|
||||||
|
const CSMWorld::Record<ESM::SoundGenerator> &record = mSoundGens.getRecord(stage);
|
||||||
|
if (record.isDeleted())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ESM::SoundGenerator soundGen = record.get();
|
||||||
|
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_SoundGen, soundGen.mId);
|
||||||
|
|
||||||
|
if (!soundGen.mCreature.empty())
|
||||||
|
{
|
||||||
|
CSMWorld::RefIdData::LocalIndex creatureIndex = mReferenceables.getDataSet().searchId(soundGen.mCreature);
|
||||||
|
if (creatureIndex.first == -1)
|
||||||
|
{
|
||||||
|
messages.push_back(std::make_pair(id, "No such creature '" + soundGen.mCreature + "'"));
|
||||||
|
}
|
||||||
|
else if (creatureIndex.second != CSMWorld::UniversalId::Type_Creature)
|
||||||
|
{
|
||||||
|
messages.push_back(std::make_pair(id, "'" + soundGen.mCreature + "' is not a creature"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (soundGen.mSound.empty())
|
||||||
|
{
|
||||||
|
messages.push_back(std::make_pair(id, "Sound is not specified"));
|
||||||
|
}
|
||||||
|
else if (mSounds.searchId(soundGen.mSound) == -1)
|
||||||
|
{
|
||||||
|
messages.push_back(std::make_pair(id, "No such sound '" + soundGen.mSound + "'"));
|
||||||
|
}
|
||||||
|
}
|
30
apps/opencs/model/tools/soundgencheck.hpp
Normal file
30
apps/opencs/model/tools/soundgencheck.hpp
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef CSM_TOOLS_SOUNDGENCHECK_HPP
|
||||||
|
#define CSM_TOOLS_SOUNDGENCHECK_HPP
|
||||||
|
|
||||||
|
#include "../world/data.hpp"
|
||||||
|
|
||||||
|
#include "../doc/stage.hpp"
|
||||||
|
|
||||||
|
namespace CSMTools
|
||||||
|
{
|
||||||
|
/// \brief VerifyStage: make sure that sound gen records are internally consistent
|
||||||
|
class SoundGenCheckStage : public CSMDoc::Stage
|
||||||
|
{
|
||||||
|
const CSMWorld::IdCollection<ESM::SoundGenerator> &mSoundGens;
|
||||||
|
const CSMWorld::IdCollection<ESM::Sound> &mSounds;
|
||||||
|
const CSMWorld::RefIdCollection &mReferenceables;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SoundGenCheckStage(const CSMWorld::IdCollection<ESM::SoundGenerator> &soundGens,
|
||||||
|
const CSMWorld::IdCollection<ESM::Sound> &sounds,
|
||||||
|
const CSMWorld::RefIdCollection &referenceables);
|
||||||
|
|
||||||
|
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.
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "spellcheck.hpp"
|
#include "spellcheck.hpp"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "startscriptcheck.hpp"
|
#include "startscriptcheck.hpp"
|
||||||
|
|
||||||
#include <components/misc/stringops.hpp>
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "tools.hpp"
|
#include "tools.hpp"
|
||||||
|
|
||||||
#include <QThreadPool>
|
#include <QThreadPool>
|
||||||
|
@ -27,6 +26,9 @@
|
||||||
#include "startscriptcheck.hpp"
|
#include "startscriptcheck.hpp"
|
||||||
#include "searchoperation.hpp"
|
#include "searchoperation.hpp"
|
||||||
#include "pathgridcheck.hpp"
|
#include "pathgridcheck.hpp"
|
||||||
|
#include "soundgencheck.hpp"
|
||||||
|
#include "magiceffectcheck.hpp"
|
||||||
|
#include "mergeoperation.hpp"
|
||||||
|
|
||||||
CSMDoc::OperationHolder *CSMTools::Tools::get (int type)
|
CSMDoc::OperationHolder *CSMTools::Tools::get (int type)
|
||||||
{
|
{
|
||||||
|
@ -34,6 +36,7 @@ CSMDoc::OperationHolder *CSMTools::Tools::get (int type)
|
||||||
{
|
{
|
||||||
case CSMDoc::State_Verifying: return &mVerifier;
|
case CSMDoc::State_Verifying: return &mVerifier;
|
||||||
case CSMDoc::State_Searching: return &mSearch;
|
case CSMDoc::State_Searching: return &mSearch;
|
||||||
|
case CSMDoc::State_Merging: return &mMerge;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -50,11 +53,15 @@ CSMDoc::OperationHolder *CSMTools::Tools::getVerifier()
|
||||||
{
|
{
|
||||||
mVerifierOperation = new CSMDoc::Operation (CSMDoc::State_Verifying, false);
|
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 (progress (int, int, int)), this, SIGNAL (progress (int, int, int)));
|
||||||
connect (&mVerifier, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool)));
|
connect (&mVerifier, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool)));
|
||||||
connect (&mVerifier,
|
connect (&mVerifier, SIGNAL (reportMessage (const CSMDoc::Message&, int)),
|
||||||
SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)),
|
this, SLOT (verifierMessage (const CSMDoc::Message&, int)));
|
||||||
this, SLOT (verifierMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)));
|
|
||||||
|
|
||||||
std::vector<std::string> mandatoryIds; // I want C++11, damn it!
|
std::vector<std::string> mandatoryIds; // I want C++11, damn it!
|
||||||
mandatoryIds.push_back ("Day");
|
mandatoryIds.push_back ("Day");
|
||||||
|
@ -99,15 +106,25 @@ CSMDoc::OperationHolder *CSMTools::Tools::getVerifier()
|
||||||
|
|
||||||
mVerifierOperation->appendStage (new PathgridCheckStage (mData.getPathgrids()));
|
mVerifierOperation->appendStage (new PathgridCheckStage (mData.getPathgrids()));
|
||||||
|
|
||||||
|
mVerifierOperation->appendStage (new SoundGenCheckStage (mData.getSoundGens(),
|
||||||
|
mData.getSounds(),
|
||||||
|
mData.getReferenceables()));
|
||||||
|
|
||||||
|
mVerifierOperation->appendStage (new MagicEffectCheckStage (mData.getMagicEffects(),
|
||||||
|
mData.getSounds(),
|
||||||
|
mData.getReferenceables(),
|
||||||
|
mData.getResources (CSMWorld::UniversalId::Type_Icons),
|
||||||
|
mData.getResources (CSMWorld::UniversalId::Type_Textures)));
|
||||||
|
|
||||||
mVerifier.setOperation (mVerifierOperation);
|
mVerifier.setOperation (mVerifierOperation);
|
||||||
}
|
}
|
||||||
|
|
||||||
return &mVerifier;
|
return &mVerifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMTools::Tools::Tools (CSMDoc::Document& document)
|
CSMTools::Tools::Tools (CSMDoc::Document& document, ToUTF8::FromType encoding)
|
||||||
: mDocument (document), mData (document.getData()), mVerifierOperation (0),
|
: mDocument (document), mData (document.getData()), mVerifierOperation (0),
|
||||||
mSearchOperation (0), mNextReportNumber (0)
|
mSearchOperation (0), mMergeOperation (0), mNextReportNumber (0), mEncoding (encoding)
|
||||||
{
|
{
|
||||||
// index 0: load error log
|
// index 0: load error log
|
||||||
mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel));
|
mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel));
|
||||||
|
@ -115,9 +132,12 @@ CSMTools::Tools::Tools (CSMDoc::Document& document)
|
||||||
|
|
||||||
connect (&mSearch, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int)));
|
connect (&mSearch, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int)));
|
||||||
connect (&mSearch, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool)));
|
connect (&mSearch, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool)));
|
||||||
connect (&mSearch,
|
connect (&mSearch, SIGNAL (reportMessage (const CSMDoc::Message&, int)),
|
||||||
SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)),
|
this, SLOT (verifierMessage (const CSMDoc::Message&, int)));
|
||||||
this, SLOT (verifierMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)));
|
|
||||||
|
connect (&mMerge, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int)));
|
||||||
|
connect (&mMerge, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool)));
|
||||||
|
// don't need to connect report message, since there are no messages for merge
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMTools::Tools::~Tools()
|
CSMTools::Tools::~Tools()
|
||||||
|
@ -134,23 +154,34 @@ CSMTools::Tools::~Tools()
|
||||||
delete mSearchOperation;
|
delete mSearchOperation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mMergeOperation)
|
||||||
|
{
|
||||||
|
mMerge.abortAndWait();
|
||||||
|
delete mMergeOperation;
|
||||||
|
}
|
||||||
|
|
||||||
for (std::map<int, ReportModel *>::iterator iter (mReports.begin()); iter!=mReports.end(); ++iter)
|
for (std::map<int, ReportModel *>::iterator iter (mReports.begin()); iter!=mReports.end(); ++iter)
|
||||||
delete iter->second;
|
delete iter->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::UniversalId CSMTools::Tools::runVerifier()
|
CSMWorld::UniversalId CSMTools::Tools::runVerifier (const CSMWorld::UniversalId& reportId)
|
||||||
{
|
{
|
||||||
mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel));
|
int reportNumber = reportId.getType()==CSMWorld::UniversalId::Type_VerificationResults ?
|
||||||
mActiveReports[CSMDoc::State_Verifying] = mNextReportNumber-1;
|
reportId.getIndex() : mNextReportNumber++;
|
||||||
|
|
||||||
|
if (mReports.find (reportNumber)==mReports.end())
|
||||||
|
mReports.insert (std::make_pair (reportNumber, new ReportModel));
|
||||||
|
|
||||||
|
mActiveReports[CSMDoc::State_Verifying] = reportNumber;
|
||||||
|
|
||||||
getVerifier()->start();
|
getVerifier()->start();
|
||||||
|
|
||||||
return CSMWorld::UniversalId (CSMWorld::UniversalId::Type_VerificationResults, mNextReportNumber-1);
|
return CSMWorld::UniversalId (CSMWorld::UniversalId::Type_VerificationResults, reportNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::UniversalId CSMTools::Tools::newSearch()
|
CSMWorld::UniversalId CSMTools::Tools::newSearch()
|
||||||
{
|
{
|
||||||
mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel (true)));
|
mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel (true, false)));
|
||||||
|
|
||||||
return CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Search, mNextReportNumber-1);
|
return CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Search, mNextReportNumber-1);
|
||||||
}
|
}
|
||||||
|
@ -170,6 +201,25 @@ void CSMTools::Tools::runSearch (const CSMWorld::UniversalId& searchId, const Se
|
||||||
mSearch.start();
|
mSearch.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMTools::Tools::runMerge (std::auto_ptr<CSMDoc::Document> target)
|
||||||
|
{
|
||||||
|
// not setting an active report, because merge does not produce messages
|
||||||
|
|
||||||
|
if (!mMergeOperation)
|
||||||
|
{
|
||||||
|
mMergeOperation = new MergeOperation (mDocument, mEncoding);
|
||||||
|
mMerge.setOperation (mMergeOperation);
|
||||||
|
connect (mMergeOperation, SIGNAL (mergeDone (CSMDoc::Document*)),
|
||||||
|
this, SIGNAL (mergeDone (CSMDoc::Document*)));
|
||||||
|
}
|
||||||
|
|
||||||
|
target->flagAsDirty();
|
||||||
|
|
||||||
|
mMergeOperation->setTarget (target);
|
||||||
|
|
||||||
|
mMerge.start();
|
||||||
|
}
|
||||||
|
|
||||||
void CSMTools::Tools::abortOperation (int type)
|
void CSMTools::Tools::abortOperation (int type)
|
||||||
{
|
{
|
||||||
if (CSMDoc::OperationHolder *operation = get (type))
|
if (CSMDoc::OperationHolder *operation = get (type))
|
||||||
|
@ -182,6 +232,7 @@ int CSMTools::Tools::getRunningOperations() const
|
||||||
{
|
{
|
||||||
CSMDoc::State_Verifying,
|
CSMDoc::State_Verifying,
|
||||||
CSMDoc::State_Searching,
|
CSMDoc::State_Searching,
|
||||||
|
CSMDoc::State_Merging,
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -205,12 +256,10 @@ CSMTools::ReportModel *CSMTools::Tools::getReport (const CSMWorld::UniversalId&
|
||||||
return mReports.at (id.getIndex());
|
return mReports.at (id.getIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::Tools::verifierMessage (const CSMWorld::UniversalId& id, const std::string& message,
|
void CSMTools::Tools::verifierMessage (const CSMDoc::Message& message, int type)
|
||||||
const std::string& hint, int type)
|
|
||||||
{
|
{
|
||||||
std::map<int, int>::iterator iter = mActiveReports.find (type);
|
std::map<int, int>::iterator iter = mActiveReports.find (type);
|
||||||
|
|
||||||
if (iter!=mActiveReports.end())
|
if (iter!=mActiveReports.end())
|
||||||
mReports[iter->second]->add (id, message, hint);
|
mReports[iter->second]->add (message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
#ifndef CSM_TOOLS_TOOLS_H
|
#ifndef CSM_TOOLS_TOOLS_H
|
||||||
#define CSM_TOOLS_TOOLS_H
|
#define CSM_TOOLS_TOOLS_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <components/to_utf8/to_utf8.hpp>
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
#include <map>
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
#include "../doc/operationholder.hpp"
|
#include "../doc/operationholder.hpp"
|
||||||
|
|
||||||
|
@ -24,6 +29,7 @@ namespace CSMTools
|
||||||
class ReportModel;
|
class ReportModel;
|
||||||
class Search;
|
class Search;
|
||||||
class SearchOperation;
|
class SearchOperation;
|
||||||
|
class MergeOperation;
|
||||||
|
|
||||||
class Tools : public QObject
|
class Tools : public QObject
|
||||||
{
|
{
|
||||||
|
@ -35,9 +41,12 @@ namespace CSMTools
|
||||||
CSMDoc::OperationHolder mVerifier;
|
CSMDoc::OperationHolder mVerifier;
|
||||||
SearchOperation *mSearchOperation;
|
SearchOperation *mSearchOperation;
|
||||||
CSMDoc::OperationHolder mSearch;
|
CSMDoc::OperationHolder mSearch;
|
||||||
|
MergeOperation *mMergeOperation;
|
||||||
|
CSMDoc::OperationHolder mMerge;
|
||||||
std::map<int, ReportModel *> mReports;
|
std::map<int, ReportModel *> mReports;
|
||||||
int mNextReportNumber;
|
int mNextReportNumber;
|
||||||
std::map<int, int> mActiveReports; // type, report number
|
std::map<int, int> mActiveReports; // type, report number
|
||||||
|
ToUTF8::FromType mEncoding;
|
||||||
|
|
||||||
// not implemented
|
// not implemented
|
||||||
Tools (const Tools&);
|
Tools (const Tools&);
|
||||||
|
@ -53,18 +62,23 @@ namespace CSMTools
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Tools (CSMDoc::Document& document);
|
Tools (CSMDoc::Document& document, ToUTF8::FromType encoding);
|
||||||
|
|
||||||
virtual ~Tools();
|
virtual ~Tools();
|
||||||
|
|
||||||
CSMWorld::UniversalId runVerifier();
|
/// \param reportId If a valid VerificationResults ID, run verifier for the
|
||||||
///< \return ID of the report for this verification run
|
/// specified report instead of creating a new one.
|
||||||
|
///
|
||||||
|
/// \return ID of the report for this verification run
|
||||||
|
CSMWorld::UniversalId runVerifier (const CSMWorld::UniversalId& reportId = CSMWorld::UniversalId());
|
||||||
|
|
||||||
/// Return ID of the report for this search.
|
/// Return ID of the report for this search.
|
||||||
CSMWorld::UniversalId newSearch();
|
CSMWorld::UniversalId newSearch();
|
||||||
|
|
||||||
void runSearch (const CSMWorld::UniversalId& searchId, const Search& search);
|
void runSearch (const CSMWorld::UniversalId& searchId, const Search& search);
|
||||||
|
|
||||||
|
void runMerge (std::auto_ptr<CSMDoc::Document> target);
|
||||||
|
|
||||||
void abortOperation (int type);
|
void abortOperation (int type);
|
||||||
///< \attention The operation is not aborted immediately.
|
///< \attention The operation is not aborted immediately.
|
||||||
|
|
||||||
|
@ -75,14 +89,17 @@ namespace CSMTools
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void verifierMessage (const CSMWorld::UniversalId& id, const std::string& message,
|
void verifierMessage (const CSMDoc::Message& message, int type);
|
||||||
const std::string& hint, int type);
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void progress (int current, int max, int type);
|
void progress (int current, int max, int type);
|
||||||
|
|
||||||
void done (int type, bool failed);
|
void done (int type, bool failed);
|
||||||
|
|
||||||
|
/// \attention When this signal is emitted, *this hands over the ownership of the
|
||||||
|
/// document. This signal must be handled to avoid a leak.
|
||||||
|
void mergeDone (CSMDoc::Document *document);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "cell.hpp"
|
#include "cell.hpp"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "cellcoordinates.hpp"
|
#include "cellcoordinates.hpp"
|
||||||
|
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "cellselection.hpp"
|
#include "cellselection.hpp"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "collectionbase.hpp"
|
#include "collectionbase.hpp"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
|
@ -77,16 +77,18 @@ bool CSMWorld::ColumnBase::isId (Display display)
|
||||||
Display_Video,
|
Display_Video,
|
||||||
|
|
||||||
Display_Id,
|
Display_Id,
|
||||||
Display_SkillImpact,
|
Display_SkillId,
|
||||||
Display_EffectRange,
|
Display_EffectRange,
|
||||||
Display_EffectId,
|
Display_EffectId,
|
||||||
Display_PartRefType,
|
Display_PartRefType,
|
||||||
Display_AiPackageType,
|
Display_AiPackageType,
|
||||||
Display_YesNo,
|
|
||||||
Display_InfoCondFunc,
|
Display_InfoCondFunc,
|
||||||
Display_InfoCondVar,
|
Display_InfoCondVar,
|
||||||
Display_InfoCondComp,
|
Display_InfoCondComp,
|
||||||
Display_RaceSkill,
|
|
||||||
|
Display_EffectSkill,
|
||||||
|
Display_EffectAttribute,
|
||||||
|
Display_IngredEffectId,
|
||||||
|
|
||||||
Display_None
|
Display_None
|
||||||
};
|
};
|
||||||
|
@ -100,7 +102,8 @@ bool CSMWorld::ColumnBase::isId (Display display)
|
||||||
|
|
||||||
bool CSMWorld::ColumnBase::isText (Display display)
|
bool CSMWorld::ColumnBase::isText (Display display)
|
||||||
{
|
{
|
||||||
return display==Display_String || display==Display_LongString;
|
return display==Display_String || display==Display_LongString ||
|
||||||
|
display==Display_String32 || display==Display_LongString256;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CSMWorld::ColumnBase::isScript (Display display)
|
bool CSMWorld::ColumnBase::isScript (Display display)
|
||||||
|
|
|
@ -14,6 +14,13 @@ namespace CSMWorld
|
||||||
{
|
{
|
||||||
struct ColumnBase
|
struct ColumnBase
|
||||||
{
|
{
|
||||||
|
enum TableEditModes
|
||||||
|
{
|
||||||
|
TableEdit_None, // no editing
|
||||||
|
TableEdit_Full, // edit cells and add/remove rows
|
||||||
|
TableEdit_FixedRows // edit cells only
|
||||||
|
};
|
||||||
|
|
||||||
enum Roles
|
enum Roles
|
||||||
{
|
{
|
||||||
Role_Flags = Qt::UserRole,
|
Role_Flags = Qt::UserRole,
|
||||||
|
@ -113,16 +120,20 @@ namespace CSMWorld
|
||||||
Display_SoundGeneratorType,
|
Display_SoundGeneratorType,
|
||||||
Display_School,
|
Display_School,
|
||||||
Display_Id,
|
Display_Id,
|
||||||
Display_SkillImpact,
|
Display_SkillId,
|
||||||
Display_EffectRange,
|
Display_EffectRange,
|
||||||
Display_EffectId,
|
Display_EffectId,
|
||||||
Display_PartRefType,
|
Display_PartRefType,
|
||||||
Display_AiPackageType,
|
Display_AiPackageType,
|
||||||
Display_YesNo,
|
|
||||||
Display_InfoCondFunc,
|
Display_InfoCondFunc,
|
||||||
Display_InfoCondVar,
|
Display_InfoCondVar,
|
||||||
Display_InfoCondComp,
|
Display_InfoCondComp,
|
||||||
Display_RaceSkill,
|
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
|
//top level columns that nest other columns
|
||||||
Display_NestedHeader
|
Display_NestedHeader
|
||||||
|
@ -186,19 +197,32 @@ namespace CSMWorld
|
||||||
template<typename ESXRecordT>
|
template<typename ESXRecordT>
|
||||||
struct NestedParentColumn : public Column<ESXRecordT>
|
struct NestedParentColumn : public Column<ESXRecordT>
|
||||||
{
|
{
|
||||||
NestedParentColumn (int id, int flags = ColumnBase::Flag_Dialogue) : Column<ESXRecordT> (id,
|
NestedParentColumn (int id, int flags = ColumnBase::Flag_Dialogue, bool fixedRows = false)
|
||||||
ColumnBase::Display_NestedHeader, flags)
|
: Column<ESXRecordT> (id, ColumnBase::Display_NestedHeader, flags), mFixedRows(fixedRows)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
||||||
|
{
|
||||||
|
// There is nothing to do here.
|
||||||
|
// This prevents exceptions from parent's implementation
|
||||||
|
}
|
||||||
|
|
||||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
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
|
virtual bool isEditable() const
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool mFixedRows;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NestedChildColumn : public NestableColumn
|
struct NestedChildColumn : public NestableColumn
|
||||||
|
@ -213,4 +237,6 @@ namespace CSMWorld
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(CSMWorld::ColumnBase::TableEditModes)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
28
apps/opencs/model/world/columnimp.cpp
Normal file
28
apps/opencs/model/world/columnimp.cpp
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#include "columnimp.hpp"
|
||||||
|
|
||||||
|
CSMWorld::BodyPartRaceColumn::BodyPartRaceColumn(const MeshTypeColumn<ESM::BodyPart> *meshType)
|
||||||
|
: mMeshType(meshType)
|
||||||
|
{}
|
||||||
|
|
||||||
|
QVariant CSMWorld::BodyPartRaceColumn::get(const Record<ESM::BodyPart> &record) const
|
||||||
|
{
|
||||||
|
if (mMeshType != NULL && mMeshType->get(record) == ESM::BodyPart::MT_Skin)
|
||||||
|
{
|
||||||
|
return QString::fromUtf8(record.get().mRace.c_str());
|
||||||
|
}
|
||||||
|
return QVariant(QVariant::UserType);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::BodyPartRaceColumn::set(Record<ESM::BodyPart> &record, const QVariant &data)
|
||||||
|
{
|
||||||
|
ESM::BodyPart record2 = record.get();
|
||||||
|
|
||||||
|
record2.mRace = data.toString().toUtf8().constData();
|
||||||
|
|
||||||
|
record.setModified(record2);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSMWorld::BodyPartRaceColumn::isEditable() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -9,6 +9,10 @@
|
||||||
|
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
|
|
||||||
|
#include <components/esm/loadbody.hpp>
|
||||||
|
#include <components/esm/loadskil.hpp>
|
||||||
|
#include <components/esm/loadrace.hpp>
|
||||||
|
|
||||||
#include "columnbase.hpp"
|
#include "columnbase.hpp"
|
||||||
#include "columns.hpp"
|
#include "columns.hpp"
|
||||||
#include "info.hpp"
|
#include "info.hpp"
|
||||||
|
@ -694,7 +698,7 @@ namespace CSMWorld
|
||||||
|
|
||||||
QColor colour = data.value<QColor>();
|
QColor colour = data.value<QColor>();
|
||||||
|
|
||||||
record2.mMapColor = colour.rgb() & 0xffffff;
|
record2.mMapColor = (colour.blue() << 16) | (colour.green() << 8) | colour.red();
|
||||||
|
|
||||||
record.setModified (record2);
|
record.setModified (record2);
|
||||||
}
|
}
|
||||||
|
@ -1911,8 +1915,8 @@ namespace CSMWorld
|
||||||
template<typename ESXRecordT>
|
template<typename ESXRecordT>
|
||||||
struct MeshTypeColumn : public Column<ESXRecordT>
|
struct MeshTypeColumn : public Column<ESXRecordT>
|
||||||
{
|
{
|
||||||
MeshTypeColumn()
|
MeshTypeColumn(int flags = ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue)
|
||||||
: Column<ESXRecordT> (Columns::ColumnId_MeshType, ColumnBase::Display_MeshType)
|
: Column<ESXRecordT> (Columns::ColumnId_MeshType, ColumnBase::Display_MeshType, flags)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||||
|
@ -2308,6 +2312,89 @@ namespace CSMWorld
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename ESXRecordT>
|
||||||
|
struct FormatColumn : public Column<ESXRecordT>
|
||||||
|
{
|
||||||
|
FormatColumn()
|
||||||
|
: Column<ESXRecordT> (Columns::ColumnId_FileFormat, ColumnBase::Display_Integer)
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||||
|
{
|
||||||
|
return record.get().mFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isEditable() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ESXRecordT>
|
||||||
|
struct AuthorColumn : public Column<ESXRecordT>
|
||||||
|
{
|
||||||
|
AuthorColumn()
|
||||||
|
: Column<ESXRecordT> (Columns::ColumnId_Author, ColumnBase::Display_String32)
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||||
|
{
|
||||||
|
return QString::fromUtf8 (record.get().mAuthor.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
||||||
|
{
|
||||||
|
ESXRecordT record2 = record.get();
|
||||||
|
|
||||||
|
record2.mAuthor = data.toString().toUtf8().constData();
|
||||||
|
|
||||||
|
record.setModified (record2);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isEditable() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ESXRecordT>
|
||||||
|
struct FileDescriptionColumn : public Column<ESXRecordT>
|
||||||
|
{
|
||||||
|
FileDescriptionColumn()
|
||||||
|
: Column<ESXRecordT> (Columns::ColumnId_FileDescription, ColumnBase::Display_LongString256)
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||||
|
{
|
||||||
|
return QString::fromUtf8 (record.get().mDescription.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
||||||
|
{
|
||||||
|
ESXRecordT record2 = record.get();
|
||||||
|
|
||||||
|
record2.mDescription = data.toString().toUtf8().constData();
|
||||||
|
|
||||||
|
record.setModified (record2);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isEditable() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BodyPartRaceColumn : public RaceColumn<ESM::BodyPart>
|
||||||
|
{
|
||||||
|
const MeshTypeColumn<ESM::BodyPart> *mMeshType;
|
||||||
|
|
||||||
|
BodyPartRaceColumn(const MeshTypeColumn<ESM::BodyPart> *meshType);
|
||||||
|
|
||||||
|
virtual QVariant get(const Record<ESM::BodyPart> &record) const;
|
||||||
|
virtual void set(Record<ESM::BodyPart> &record, const QVariant &data);
|
||||||
|
virtual bool isEditable() const;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "columns.hpp"
|
#include "columns.hpp"
|
||||||
|
|
||||||
#include <components/misc/stringops.hpp>
|
#include <components/misc/stringops.hpp>
|
||||||
|
@ -35,6 +34,8 @@ namespace CSMWorld
|
||||||
{ ColumnId_Volume, "Volume" },
|
{ ColumnId_Volume, "Volume" },
|
||||||
{ ColumnId_MinRange, "Min Range" },
|
{ ColumnId_MinRange, "Min Range" },
|
||||||
{ ColumnId_MaxRange, "Max Range" },
|
{ ColumnId_MaxRange, "Max Range" },
|
||||||
|
{ ColumnId_MinMagnitude, "Min Magnitude" },
|
||||||
|
{ ColumnId_MaxMagnitude, "Max Magnitude" },
|
||||||
{ ColumnId_SoundFile, "Sound File" },
|
{ ColumnId_SoundFile, "Sound File" },
|
||||||
{ ColumnId_MapColour, "Map Colour" },
|
{ ColumnId_MapColour, "Map Colour" },
|
||||||
{ ColumnId_SleepEncounter, "Sleep Encounter" },
|
{ ColumnId_SleepEncounter, "Sleep Encounter" },
|
||||||
|
@ -70,7 +71,6 @@ namespace CSMWorld
|
||||||
{ ColumnId_Weight, "Weight" },
|
{ ColumnId_Weight, "Weight" },
|
||||||
{ ColumnId_EnchantmentPoints, "Enchantment Points" },
|
{ ColumnId_EnchantmentPoints, "Enchantment Points" },
|
||||||
{ ColumnId_Quality, "Quality" },
|
{ ColumnId_Quality, "Quality" },
|
||||||
{ ColumnId_Ai, "AI" },
|
|
||||||
{ ColumnId_AiHello, "AI Hello" },
|
{ ColumnId_AiHello, "AI Hello" },
|
||||||
{ ColumnId_AiFlee, "AI Flee" },
|
{ ColumnId_AiFlee, "AI Flee" },
|
||||||
{ ColumnId_AiFight, "AI Fight" },
|
{ ColumnId_AiFight, "AI Fight" },
|
||||||
|
@ -92,7 +92,7 @@ namespace CSMWorld
|
||||||
{ ColumnId_Trainer, "Trainer" },
|
{ ColumnId_Trainer, "Trainer" },
|
||||||
{ ColumnId_Spellmaking, "Spellmaking" },
|
{ ColumnId_Spellmaking, "Spellmaking" },
|
||||||
{ ColumnId_EnchantingService, "Enchanting Service" },
|
{ ColumnId_EnchantingService, "Enchanting Service" },
|
||||||
{ ColumnId_RepairService, "Repair Serivce" },
|
{ ColumnId_RepairService, "Repair Service" },
|
||||||
{ ColumnId_ApparatusType, "Apparatus Type" },
|
{ ColumnId_ApparatusType, "Apparatus Type" },
|
||||||
{ ColumnId_ArmorType, "Armor Type" },
|
{ ColumnId_ArmorType, "Armor Type" },
|
||||||
{ ColumnId_Health, "Health" },
|
{ ColumnId_Health, "Health" },
|
||||||
|
@ -107,7 +107,6 @@ namespace CSMWorld
|
||||||
{ ColumnId_OriginalCreature, "Original Creature" },
|
{ ColumnId_OriginalCreature, "Original Creature" },
|
||||||
{ ColumnId_Biped, "Biped" },
|
{ ColumnId_Biped, "Biped" },
|
||||||
{ ColumnId_HasWeapon, "Has Weapon" },
|
{ ColumnId_HasWeapon, "Has Weapon" },
|
||||||
{ ColumnId_NoMovement, "No Movement" },
|
|
||||||
{ ColumnId_Swims, "Swims" },
|
{ ColumnId_Swims, "Swims" },
|
||||||
{ ColumnId_Flies, "Flies" },
|
{ ColumnId_Flies, "Flies" },
|
||||||
{ ColumnId_Walks, "Walks" },
|
{ ColumnId_Walks, "Walks" },
|
||||||
|
@ -199,8 +198,6 @@ namespace CSMWorld
|
||||||
{ ColumnId_RotY, "Rotation Y"},
|
{ ColumnId_RotY, "Rotation Y"},
|
||||||
{ ColumnId_RotZ, "Rotation Z"},
|
{ ColumnId_RotZ, "Rotation Z"},
|
||||||
|
|
||||||
{ ColumnId_Skill, "Skill" },
|
|
||||||
|
|
||||||
{ ColumnId_OwnerGlobal, "Owner Global" },
|
{ ColumnId_OwnerGlobal, "Owner Global" },
|
||||||
{ ColumnId_DefaultProfile, "Default Profile" },
|
{ ColumnId_DefaultProfile, "Default Profile" },
|
||||||
{ ColumnId_BypassNewGame, "Bypass New Game" },
|
{ ColumnId_BypassNewGame, "Bypass New Game" },
|
||||||
|
@ -252,7 +249,7 @@ namespace CSMWorld
|
||||||
{ ColumnId_AiWanderDist, "Wander Dist" },
|
{ ColumnId_AiWanderDist, "Wander Dist" },
|
||||||
{ ColumnId_AiDuration, "Ai Duration" },
|
{ ColumnId_AiDuration, "Ai Duration" },
|
||||||
{ ColumnId_AiWanderToD, "Wander ToD" },
|
{ ColumnId_AiWanderToD, "Wander ToD" },
|
||||||
{ ColumnId_AiWanderIdle, "Wander Idle" },
|
//{ ColumnId_AiWanderIdle, "Wander Idle" },
|
||||||
{ ColumnId_AiWanderRepeat, "Wander Repeat" },
|
{ ColumnId_AiWanderRepeat, "Wander Repeat" },
|
||||||
{ ColumnId_AiActivateName, "Activate" },
|
{ ColumnId_AiActivateName, "Activate" },
|
||||||
{ ColumnId_AiTargetId, "Target ID" },
|
{ ColumnId_AiTargetId, "Target ID" },
|
||||||
|
@ -265,13 +262,13 @@ namespace CSMWorld
|
||||||
|
|
||||||
{ ColumnId_LevelledList,"Levelled List" },
|
{ ColumnId_LevelledList,"Levelled List" },
|
||||||
{ ColumnId_LevelledItemId,"Levelled Item" },
|
{ ColumnId_LevelledItemId,"Levelled Item" },
|
||||||
{ ColumnId_LevelledItemLevel,"Level" },
|
{ ColumnId_LevelledItemLevel,"Item Level" },
|
||||||
{ ColumnId_LevelledItemType, "Calculate all levels <= player" },
|
{ ColumnId_LevelledItemType, "Calculate all levels <= player" },
|
||||||
{ ColumnId_LevelledItemTypeEach, "Select a new item each instance" },
|
{ ColumnId_LevelledItemTypeEach, "Select a new item each instance" },
|
||||||
{ ColumnId_LevelledItemChanceNone, "Chance None" },
|
{ ColumnId_LevelledItemChanceNone, "Chance None" },
|
||||||
|
|
||||||
{ ColumnId_PowerList, "Powers" },
|
{ ColumnId_PowerList, "Powers" },
|
||||||
{ ColumnId_SkillImpact, "Skills" },
|
{ ColumnId_Skill, "Skill" },
|
||||||
|
|
||||||
{ ColumnId_InfoList, "Info List" },
|
{ ColumnId_InfoList, "Info List" },
|
||||||
{ ColumnId_InfoCondition, "Info Conditions" },
|
{ ColumnId_InfoCondition, "Info Conditions" },
|
||||||
|
@ -281,26 +278,24 @@ namespace CSMWorld
|
||||||
{ ColumnId_InfoCondValue, "Values" },
|
{ ColumnId_InfoCondValue, "Values" },
|
||||||
{ ColumnId_OriginalCell, "Original Cell" },
|
{ ColumnId_OriginalCell, "Original Cell" },
|
||||||
|
|
||||||
{ ColumnId_NpcAttributes, "Attributes" },
|
{ ColumnId_NpcAttributes, "NPC Attributes" },
|
||||||
{ ColumnId_NpcSkills, "Skills" },
|
{ ColumnId_NpcSkills, "NPC Skill" },
|
||||||
{ ColumnId_UChar, "Value [0..255]" },
|
{ ColumnId_UChar, "Value [0..255]" },
|
||||||
{ ColumnId_NpcMisc, "Misc" },
|
{ ColumnId_NpcMisc, "NPC Misc" },
|
||||||
{ ColumnId_NpcLevel, "Level" },
|
{ ColumnId_Level, "Level" },
|
||||||
{ ColumnId_NpcFactionID, "Faction ID" },
|
{ ColumnId_NpcFactionID, "Faction ID" },
|
||||||
{ ColumnId_NpcHealth, "Health" },
|
|
||||||
{ ColumnId_NpcMana, "Mana" },
|
{ ColumnId_Mana, "Mana" },
|
||||||
{ ColumnId_NpcFatigue, "Fatigue" },
|
{ ColumnId_Fatigue, "Fatigue" },
|
||||||
{ ColumnId_NpcDisposition, "Disposition" },
|
{ ColumnId_NpcDisposition, "NPC Disposition" },
|
||||||
{ ColumnId_NpcReputation, "Reputation" },
|
{ ColumnId_NpcReputation, "Reputation" },
|
||||||
{ ColumnId_NpcRank, "Rank" },
|
{ ColumnId_NpcRank, "NPC Rank" },
|
||||||
{ ColumnId_NpcGold, "Gold" },
|
{ ColumnId_Gold, "Gold" },
|
||||||
{ ColumnId_NpcPersistence, "Persistent" },
|
{ ColumnId_NpcPersistence, "Persistent" },
|
||||||
|
|
||||||
{ ColumnId_RaceAttributes, "Attributes" },
|
{ ColumnId_RaceAttributes, "Race Attributes" },
|
||||||
{ ColumnId_RaceMaleValue, "Male" },
|
{ ColumnId_Male, "Male" },
|
||||||
{ ColumnId_RaceFemaleValue, "Female" },
|
|
||||||
{ ColumnId_RaceSkillBonus, "Skill Bonus" },
|
{ ColumnId_RaceSkillBonus, "Skill Bonus" },
|
||||||
{ ColumnId_RaceSkill, "Skills" },
|
|
||||||
{ ColumnId_RaceBonus, "Bonus" },
|
{ ColumnId_RaceBonus, "Bonus" },
|
||||||
|
|
||||||
{ ColumnId_Interior, "Interior" },
|
{ ColumnId_Interior, "Interior" },
|
||||||
|
@ -311,6 +306,30 @@ namespace CSMWorld
|
||||||
{ ColumnId_WaterLevel, "Water Level" },
|
{ ColumnId_WaterLevel, "Water Level" },
|
||||||
{ ColumnId_MapColor, "Map Color" },
|
{ ColumnId_MapColor, "Map Color" },
|
||||||
|
|
||||||
|
{ ColumnId_FileFormat, "File Format" },
|
||||||
|
{ ColumnId_FileDescription, "File Description" },
|
||||||
|
{ ColumnId_Author, "Author" },
|
||||||
|
|
||||||
|
{ ColumnId_CreatureAttributes, "Creature Attributes" },
|
||||||
|
{ ColumnId_AttributeValue, "Attrib Value" },
|
||||||
|
{ ColumnId_CreatureAttack, "Creature Attack" },
|
||||||
|
{ ColumnId_MinAttack, "Min Attack" },
|
||||||
|
{ ColumnId_MaxAttack, "Max Attack" },
|
||||||
|
{ ColumnId_CreatureMisc, "Creature Misc" },
|
||||||
|
|
||||||
|
{ ColumnId_Idle1, "Idle 1" },
|
||||||
|
{ ColumnId_Idle2, "Idle 2" },
|
||||||
|
{ ColumnId_Idle3, "Idle 3" },
|
||||||
|
{ ColumnId_Idle4, "Idle 4" },
|
||||||
|
{ ColumnId_Idle5, "Idle 5" },
|
||||||
|
{ ColumnId_Idle6, "Idle 6" },
|
||||||
|
{ ColumnId_Idle7, "Idle 7" },
|
||||||
|
{ ColumnId_Idle8, "Idle 8" },
|
||||||
|
|
||||||
|
{ ColumnId_SpellSrc, "From Race" },
|
||||||
|
{ ColumnId_SpellCost, "Cast Cost" },
|
||||||
|
{ ColumnId_SpellChance, "Cast Chance" },
|
||||||
|
|
||||||
{ ColumnId_UseValue1, "Use value 1" },
|
{ ColumnId_UseValue1, "Use value 1" },
|
||||||
{ ColumnId_UseValue2, "Use value 2" },
|
{ ColumnId_UseValue2, "Use value 2" },
|
||||||
{ ColumnId_UseValue3, "Use value 3" },
|
{ ColumnId_UseValue3, "Use value 3" },
|
||||||
|
@ -532,11 +551,6 @@ namespace
|
||||||
"AI Wander", "AI Travel", "AI Follow", "AI Escort", "AI Activate", 0
|
"AI Wander", "AI Travel", "AI Follow", "AI Escort", "AI Activate", 0
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *sAiWanderRepeat[] =
|
|
||||||
{
|
|
||||||
"No", "Yes", 0
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char *sInfoCondFunc[] =
|
static const char *sInfoCondFunc[] =
|
||||||
{
|
{
|
||||||
" ", "Function", "Global", "Local", "Journal",
|
" ", "Function", "Global", "Local", "Journal",
|
||||||
|
@ -571,17 +585,15 @@ namespace
|
||||||
case CSMWorld::Columns::ColumnId_MeshType: return sMeshTypes;
|
case CSMWorld::Columns::ColumnId_MeshType: return sMeshTypes;
|
||||||
case CSMWorld::Columns::ColumnId_SoundGeneratorType: return sSoundGeneratorType;
|
case CSMWorld::Columns::ColumnId_SoundGeneratorType: return sSoundGeneratorType;
|
||||||
case CSMWorld::Columns::ColumnId_School: return sSchools;
|
case CSMWorld::Columns::ColumnId_School: return sSchools;
|
||||||
case CSMWorld::Columns::ColumnId_SkillImpact: return sSkills;
|
case CSMWorld::Columns::ColumnId_Skill: return sSkills;
|
||||||
case CSMWorld::Columns::ColumnId_EffectRange: return sEffectRange;
|
case CSMWorld::Columns::ColumnId_EffectRange: return sEffectRange;
|
||||||
case CSMWorld::Columns::ColumnId_EffectId: return sEffectId;
|
case CSMWorld::Columns::ColumnId_EffectId: return sEffectId;
|
||||||
case CSMWorld::Columns::ColumnId_PartRefType: return sPartRefType;
|
case CSMWorld::Columns::ColumnId_PartRefType: return sPartRefType;
|
||||||
case CSMWorld::Columns::ColumnId_AiPackageType: return sAiPackageType;
|
case CSMWorld::Columns::ColumnId_AiPackageType: return sAiPackageType;
|
||||||
case CSMWorld::Columns::ColumnId_AiWanderRepeat: return sAiWanderRepeat;
|
|
||||||
case CSMWorld::Columns::ColumnId_InfoCondFunc: return sInfoCondFunc;
|
case CSMWorld::Columns::ColumnId_InfoCondFunc: return sInfoCondFunc;
|
||||||
// FIXME: don't have dynamic value enum delegate, use Display_String for now
|
// FIXME: don't have dynamic value enum delegate, use Display_String for now
|
||||||
//case CSMWorld::Columns::ColumnId_InfoCond: return sInfoCond;
|
//case CSMWorld::Columns::ColumnId_InfoCond: return sInfoCond;
|
||||||
case CSMWorld::Columns::ColumnId_InfoCondComp: return sInfoCondComp;
|
case CSMWorld::Columns::ColumnId_InfoCondComp: return sInfoCondComp;
|
||||||
case CSMWorld::Columns::ColumnId_RaceSkill: return sSkills;
|
|
||||||
|
|
||||||
default: return 0;
|
default: return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ namespace CSMWorld
|
||||||
ColumnId_Weight = 50,
|
ColumnId_Weight = 50,
|
||||||
ColumnId_EnchantmentPoints = 51,
|
ColumnId_EnchantmentPoints = 51,
|
||||||
ColumnId_Quality = 52,
|
ColumnId_Quality = 52,
|
||||||
ColumnId_Ai = 53,
|
// unused
|
||||||
ColumnId_AiHello = 54,
|
ColumnId_AiHello = 54,
|
||||||
ColumnId_AiFlee = 55,
|
ColumnId_AiFlee = 55,
|
||||||
ColumnId_AiFight = 56,
|
ColumnId_AiFight = 56,
|
||||||
|
@ -102,7 +102,7 @@ namespace CSMWorld
|
||||||
ColumnId_OriginalCreature = 87,
|
ColumnId_OriginalCreature = 87,
|
||||||
ColumnId_Biped = 88,
|
ColumnId_Biped = 88,
|
||||||
ColumnId_HasWeapon = 89,
|
ColumnId_HasWeapon = 89,
|
||||||
ColumnId_NoMovement = 90,
|
// used for SpellSrc
|
||||||
ColumnId_Swims = 91,
|
ColumnId_Swims = 91,
|
||||||
ColumnId_Flies = 92,
|
ColumnId_Flies = 92,
|
||||||
ColumnId_Walks = 93,
|
ColumnId_Walks = 93,
|
||||||
|
@ -189,7 +189,7 @@ namespace CSMWorld
|
||||||
ColumnId_RotX = 174,
|
ColumnId_RotX = 174,
|
||||||
ColumnId_RotY = 175,
|
ColumnId_RotY = 175,
|
||||||
ColumnId_RotZ = 176,
|
ColumnId_RotZ = 176,
|
||||||
ColumnId_Skill = 177,
|
// used for SpellCost
|
||||||
ColumnId_OwnerGlobal = 178,
|
ColumnId_OwnerGlobal = 178,
|
||||||
ColumnId_DefaultProfile = 179,
|
ColumnId_DefaultProfile = 179,
|
||||||
ColumnId_BypassNewGame = 180,
|
ColumnId_BypassNewGame = 180,
|
||||||
|
@ -241,7 +241,7 @@ namespace CSMWorld
|
||||||
ColumnId_AiWanderDist = 221,
|
ColumnId_AiWanderDist = 221,
|
||||||
ColumnId_AiDuration = 222,
|
ColumnId_AiDuration = 222,
|
||||||
ColumnId_AiWanderToD = 223,
|
ColumnId_AiWanderToD = 223,
|
||||||
ColumnId_AiWanderIdle = 224,
|
// unused
|
||||||
ColumnId_AiWanderRepeat = 225,
|
ColumnId_AiWanderRepeat = 225,
|
||||||
ColumnId_AiActivateName = 226,
|
ColumnId_AiActivateName = 226,
|
||||||
// use ColumnId_PosX, etc for AI destinations
|
// use ColumnId_PosX, etc for AI destinations
|
||||||
|
@ -261,7 +261,7 @@ namespace CSMWorld
|
||||||
ColumnId_LevelledItemChanceNone = 238,
|
ColumnId_LevelledItemChanceNone = 238,
|
||||||
|
|
||||||
ColumnId_PowerList = 239,
|
ColumnId_PowerList = 239,
|
||||||
ColumnId_SkillImpact = 240, // impact from magic effects
|
ColumnId_Skill = 240,
|
||||||
|
|
||||||
ColumnId_InfoList = 241,
|
ColumnId_InfoList = 241,
|
||||||
ColumnId_InfoCondition = 242,
|
ColumnId_InfoCondition = 242,
|
||||||
|
@ -276,22 +276,22 @@ namespace CSMWorld
|
||||||
ColumnId_NpcSkills = 249,
|
ColumnId_NpcSkills = 249,
|
||||||
ColumnId_UChar = 250,
|
ColumnId_UChar = 250,
|
||||||
ColumnId_NpcMisc = 251,
|
ColumnId_NpcMisc = 251,
|
||||||
ColumnId_NpcLevel = 252,
|
ColumnId_Level = 252,
|
||||||
ColumnId_NpcFactionID = 253,
|
ColumnId_NpcFactionID = 253,
|
||||||
ColumnId_NpcHealth = 254,
|
// used for SpellChance
|
||||||
ColumnId_NpcMana = 255,
|
ColumnId_Mana = 255,
|
||||||
ColumnId_NpcFatigue = 256,
|
ColumnId_Fatigue = 256,
|
||||||
ColumnId_NpcDisposition = 257,
|
ColumnId_NpcDisposition = 257,
|
||||||
ColumnId_NpcReputation = 258,
|
ColumnId_NpcReputation = 258,
|
||||||
ColumnId_NpcRank = 259,
|
ColumnId_NpcRank = 259,
|
||||||
ColumnId_NpcGold = 260,
|
ColumnId_Gold = 260,
|
||||||
ColumnId_NpcPersistence = 261,
|
ColumnId_NpcPersistence = 261,
|
||||||
|
|
||||||
ColumnId_RaceAttributes = 262,
|
ColumnId_RaceAttributes = 262,
|
||||||
ColumnId_RaceMaleValue = 263,
|
ColumnId_Male = 263,
|
||||||
ColumnId_RaceFemaleValue = 264,
|
// unused
|
||||||
ColumnId_RaceSkillBonus = 265,
|
ColumnId_RaceSkillBonus = 265,
|
||||||
ColumnId_RaceSkill = 266,
|
// unused
|
||||||
ColumnId_RaceBonus = 267,
|
ColumnId_RaceBonus = 267,
|
||||||
|
|
||||||
ColumnId_Interior = 268,
|
ColumnId_Interior = 268,
|
||||||
|
@ -302,6 +302,33 @@ namespace CSMWorld
|
||||||
ColumnId_WaterLevel = 273,
|
ColumnId_WaterLevel = 273,
|
||||||
ColumnId_MapColor = 274,
|
ColumnId_MapColor = 274,
|
||||||
|
|
||||||
|
ColumnId_FileFormat = 275,
|
||||||
|
ColumnId_FileDescription = 276,
|
||||||
|
ColumnId_Author = 277,
|
||||||
|
|
||||||
|
ColumnId_MinMagnitude = 278,
|
||||||
|
ColumnId_MaxMagnitude = 279,
|
||||||
|
|
||||||
|
ColumnId_CreatureAttributes = 280,
|
||||||
|
ColumnId_AttributeValue = 281,
|
||||||
|
ColumnId_CreatureAttack = 282,
|
||||||
|
ColumnId_MinAttack = 283,
|
||||||
|
ColumnId_MaxAttack = 284,
|
||||||
|
ColumnId_CreatureMisc = 285,
|
||||||
|
|
||||||
|
ColumnId_Idle1 = 286,
|
||||||
|
ColumnId_Idle2 = 287,
|
||||||
|
ColumnId_Idle3 = 288,
|
||||||
|
ColumnId_Idle4 = 289,
|
||||||
|
ColumnId_Idle5 = 290,
|
||||||
|
ColumnId_Idle6 = 291,
|
||||||
|
ColumnId_Idle7 = 292,
|
||||||
|
ColumnId_Idle8 = 293,
|
||||||
|
|
||||||
|
ColumnId_SpellSrc = 90,
|
||||||
|
ColumnId_SpellCost = 177,
|
||||||
|
ColumnId_SpellChance = 254,
|
||||||
|
|
||||||
// Allocated to a separate value range, so we don't get a collision should we ever need
|
// Allocated to a separate value range, so we don't get a collision should we ever need
|
||||||
// to extend the number of use values.
|
// to extend the number of use values.
|
||||||
ColumnId_UseValue1 = 0x10000,
|
ColumnId_UseValue1 = 0x10000,
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "commanddispatcher.hpp"
|
#include "commanddispatcher.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
|
@ -21,19 +21,31 @@ CSMWorld::ModifyCommand::ModifyCommand (QAbstractItemModel& model, const QModelI
|
||||||
// Replace proxy with actual model
|
// Replace proxy with actual model
|
||||||
mIndex = proxy->mapToSource (index);
|
mIndex = proxy->mapToSource (index);
|
||||||
mModel = proxy->sourceModel();
|
mModel = proxy->sourceModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mIndex.parent().isValid())
|
||||||
|
{
|
||||||
setText ("Modify " + dynamic_cast<CSMWorld::IdTree*>(mModel)->nestedHeaderData (
|
setText ("Modify " + dynamic_cast<CSMWorld::IdTree*>(mModel)->nestedHeaderData (
|
||||||
mIndex.parent().column(), mIndex.column(), Qt::Horizontal, Qt::DisplayRole).toString());
|
mIndex.parent().column(), mIndex.column(), Qt::Horizontal, Qt::DisplayRole).toString());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
setText ("Modify " + mModel->headerData (mIndex.column(), Qt::Horizontal, Qt::DisplayRole).toString());
|
setText ("Modify " + mModel->headerData (mIndex.column(), Qt::Horizontal, Qt::DisplayRole).toString());
|
||||||
|
}
|
||||||
|
|
||||||
// Remember record state before the modification
|
// Remember record state before the modification
|
||||||
if (CSMWorld::IdTable *table = dynamic_cast<IdTable *>(mModel))
|
if (CSMWorld::IdTable *table = dynamic_cast<IdTable *>(mModel))
|
||||||
{
|
{
|
||||||
mHasRecordState = true;
|
mHasRecordState = true;
|
||||||
int stateColumnIndex = table->findColumnIndex(Columns::ColumnId_Modification);
|
int stateColumnIndex = table->findColumnIndex(Columns::ColumnId_Modification);
|
||||||
mRecordStateIndex = table->index(mIndex.row(), stateColumnIndex);
|
|
||||||
|
int rowIndex = mIndex.row();
|
||||||
|
if (mIndex.parent().isValid())
|
||||||
|
{
|
||||||
|
rowIndex = mIndex.parent().row();
|
||||||
|
}
|
||||||
|
|
||||||
|
mRecordStateIndex = table->index(rowIndex, stateColumnIndex);
|
||||||
mOldRecordState = static_cast<CSMWorld::RecordBase::State>(table->data(mRecordStateIndex).toInt());
|
mOldRecordState = static_cast<CSMWorld::RecordBase::State>(table->data(mRecordStateIndex).toInt());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,6 +70,25 @@ void CSMWorld::CreateCommand::applyModifications()
|
||||||
{
|
{
|
||||||
for (std::map<int, QVariant>::const_iterator iter (mValues.begin()); iter!=mValues.end(); ++iter)
|
for (std::map<int, QVariant>::const_iterator iter (mValues.begin()); iter!=mValues.end(); ++iter)
|
||||||
mModel.setData (mModel.getModelIndex (mId, iter->first), iter->second);
|
mModel.setData (mModel.getModelIndex (mId, iter->first), iter->second);
|
||||||
|
|
||||||
|
if (!mNestedValues.empty())
|
||||||
|
{
|
||||||
|
CSMWorld::IdTree *tree = dynamic_cast<CSMWorld::IdTree *>(&mModel);
|
||||||
|
if (tree == NULL)
|
||||||
|
{
|
||||||
|
throw std::logic_error("CSMWorld::CreateCommand: Attempt to add nested values to the non-nested model");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<int, std::pair<int, QVariant> >::const_iterator current = mNestedValues.begin();
|
||||||
|
std::map<int, std::pair<int, QVariant> >::const_iterator end = mNestedValues.end();
|
||||||
|
for (; current != end; ++current)
|
||||||
|
{
|
||||||
|
QModelIndex index = tree->index(0,
|
||||||
|
current->second.first,
|
||||||
|
tree->getNestedModelIndex(mId, current->first));
|
||||||
|
tree->setData(index, current->second.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::CreateCommand::CreateCommand (IdTable& model, const std::string& id, QUndoCommand* parent)
|
CSMWorld::CreateCommand::CreateCommand (IdTable& model, const std::string& id, QUndoCommand* parent)
|
||||||
|
@ -71,6 +102,11 @@ void CSMWorld::CreateCommand::addValue (int column, const QVariant& value)
|
||||||
mValues[column] = value;
|
mValues[column] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMWorld::CreateCommand::addNestedValue(int parentColumn, int nestedColumn, const QVariant &value)
|
||||||
|
{
|
||||||
|
mNestedValues[parentColumn] = std::make_pair(nestedColumn, value);
|
||||||
|
}
|
||||||
|
|
||||||
void CSMWorld::CreateCommand::setType (UniversalId::Type type)
|
void CSMWorld::CreateCommand::setType (UniversalId::Type type)
|
||||||
{
|
{
|
||||||
mType = type;
|
mType = type;
|
||||||
|
@ -258,21 +294,24 @@ CSMWorld::DeleteNestedCommand::DeleteNestedCommand (IdTree& model,
|
||||||
std::string title =
|
std::string title =
|
||||||
model.headerData(parentColumn, Qt::Horizontal, Qt::DisplayRole).toString().toUtf8().constData();
|
model.headerData(parentColumn, Qt::Horizontal, Qt::DisplayRole).toString().toUtf8().constData();
|
||||||
setText (("Delete row in " + title + " sub-table of " + mId).c_str());
|
setText (("Delete row in " + title + " sub-table of " + mId).c_str());
|
||||||
|
|
||||||
|
QModelIndex parentIndex = mModel.getModelIndex(mId, mParentColumn);
|
||||||
|
mModifyParentCommand = new ModifyCommand(mModel, parentIndex, parentIndex.data(Qt::EditRole), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMWorld::DeleteNestedCommand::redo()
|
void CSMWorld::DeleteNestedCommand::redo()
|
||||||
{
|
{
|
||||||
const QModelIndex& parentIndex = mModel.getModelIndex(mId, mParentColumn);
|
QModelIndex parentIndex = mModel.getModelIndex(mId, mParentColumn);
|
||||||
|
|
||||||
mModel.removeRows (mNestedRow, 1, parentIndex);
|
mModel.removeRows (mNestedRow, 1, parentIndex);
|
||||||
|
mModifyParentCommand->redo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CSMWorld::DeleteNestedCommand::undo()
|
void CSMWorld::DeleteNestedCommand::undo()
|
||||||
{
|
{
|
||||||
const QModelIndex& parentIndex = mModel.getModelIndex(mId, mParentColumn);
|
QModelIndex parentIndex = mModel.getModelIndex(mId, mParentColumn);
|
||||||
|
|
||||||
mModel.setNestedTable(parentIndex, getOld());
|
mModel.setNestedTable(parentIndex, getOld());
|
||||||
|
mModifyParentCommand->undo();
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::AddNestedCommand::AddNestedCommand(IdTree& model, const std::string& id, int nestedRow, int parentColumn, QUndoCommand* parent)
|
CSMWorld::AddNestedCommand::AddNestedCommand(IdTree& model, const std::string& id, int nestedRow, int parentColumn, QUndoCommand* parent)
|
||||||
|
@ -286,20 +325,23 @@ CSMWorld::AddNestedCommand::AddNestedCommand(IdTree& model, const std::string& i
|
||||||
std::string title =
|
std::string title =
|
||||||
model.headerData(parentColumn, Qt::Horizontal, Qt::DisplayRole).toString().toUtf8().constData();
|
model.headerData(parentColumn, Qt::Horizontal, Qt::DisplayRole).toString().toUtf8().constData();
|
||||||
setText (("Add row in " + title + " sub-table of " + mId).c_str());
|
setText (("Add row in " + title + " sub-table of " + mId).c_str());
|
||||||
|
|
||||||
|
QModelIndex parentIndex = mModel.getModelIndex(mId, mParentColumn);
|
||||||
|
mModifyParentCommand = new ModifyCommand(mModel, parentIndex, parentIndex.data(Qt::EditRole), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMWorld::AddNestedCommand::redo()
|
void CSMWorld::AddNestedCommand::redo()
|
||||||
{
|
{
|
||||||
const QModelIndex& parentIndex = mModel.getModelIndex(mId, mParentColumn);
|
QModelIndex parentIndex = mModel.getModelIndex(mId, mParentColumn);
|
||||||
|
|
||||||
mModel.addNestedRow (parentIndex, mNewRow);
|
mModel.addNestedRow (parentIndex, mNewRow);
|
||||||
|
mModifyParentCommand->redo();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMWorld::AddNestedCommand::undo()
|
void CSMWorld::AddNestedCommand::undo()
|
||||||
{
|
{
|
||||||
const QModelIndex& parentIndex = mModel.getModelIndex(mId, mParentColumn);
|
QModelIndex parentIndex = mModel.getModelIndex(mId, mParentColumn);
|
||||||
|
|
||||||
mModel.setNestedTable(parentIndex, getOld());
|
mModel.setNestedTable(parentIndex, getOld());
|
||||||
|
mModifyParentCommand->undo();
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::NestedTableStoring::NestedTableStoring(const IdTree& model, const std::string& id, int parentColumn)
|
CSMWorld::NestedTableStoring::NestedTableStoring(const IdTree& model, const std::string& id, int parentColumn)
|
||||||
|
|
|
@ -47,6 +47,9 @@ namespace CSMWorld
|
||||||
class CreateCommand : public QUndoCommand
|
class CreateCommand : public QUndoCommand
|
||||||
{
|
{
|
||||||
std::map<int, QVariant> mValues;
|
std::map<int, QVariant> mValues;
|
||||||
|
std::map<int, std::pair<int, QVariant> > mNestedValues;
|
||||||
|
///< Parameter order: a parent column, a nested column, a data.
|
||||||
|
///< A nested row has index of 0.
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -67,6 +70,8 @@ namespace CSMWorld
|
||||||
|
|
||||||
void addValue (int column, const QVariant& value);
|
void addValue (int column, const QVariant& value);
|
||||||
|
|
||||||
|
void addNestedValue(int parentColumn, int nestedColumn, const QVariant &value);
|
||||||
|
|
||||||
virtual void redo();
|
virtual void redo();
|
||||||
|
|
||||||
virtual void undo();
|
virtual void undo();
|
||||||
|
@ -194,6 +199,9 @@ namespace CSMWorld
|
||||||
|
|
||||||
int mNestedRow;
|
int mNestedRow;
|
||||||
|
|
||||||
|
// The command to redo/undo the Modified status of a record
|
||||||
|
ModifyCommand *mModifyParentCommand;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DeleteNestedCommand (IdTree& model,
|
DeleteNestedCommand (IdTree& model,
|
||||||
|
@ -214,6 +222,9 @@ namespace CSMWorld
|
||||||
|
|
||||||
int mParentColumn;
|
int mParentColumn;
|
||||||
|
|
||||||
|
// The command to redo/undo the Modified status of a record
|
||||||
|
ModifyCommand *mModifyParentCommand;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
AddNestedCommand(IdTree& model,
|
AddNestedCommand(IdTree& model,
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "data.hpp"
|
#include "data.hpp"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
@ -11,6 +10,10 @@
|
||||||
#include <components/esm/loadglob.hpp>
|
#include <components/esm/loadglob.hpp>
|
||||||
#include <components/esm/cellref.hpp>
|
#include <components/esm/cellref.hpp>
|
||||||
|
|
||||||
|
#include <components/autocalc/autocalc.hpp>
|
||||||
|
#include <components/autocalc/autocalcspell.hpp>
|
||||||
|
#include <components/autocalc/store.hpp>
|
||||||
|
|
||||||
#include "idtable.hpp"
|
#include "idtable.hpp"
|
||||||
#include "idtree.hpp"
|
#include "idtree.hpp"
|
||||||
#include "columnimp.hpp"
|
#include "columnimp.hpp"
|
||||||
|
@ -19,6 +22,71 @@
|
||||||
#include "resourcesmanager.hpp"
|
#include "resourcesmanager.hpp"
|
||||||
#include "resourcetable.hpp"
|
#include "resourcetable.hpp"
|
||||||
#include "nestedcoladapterimp.hpp"
|
#include "nestedcoladapterimp.hpp"
|
||||||
|
#include "npcstats.hpp"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
class CSStore : public AutoCalc::StoreCommon
|
||||||
|
{
|
||||||
|
const CSMWorld::IdCollection<ESM::GameSetting>& mGmstTable;
|
||||||
|
const CSMWorld::IdCollection<ESM::Skill>& mSkillTable;
|
||||||
|
const CSMWorld::IdCollection<ESM::MagicEffect>& mMagicEffectTable;
|
||||||
|
const CSMWorld::NestedIdCollection<ESM::Spell>& mSpells;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
CSStore(const CSMWorld::IdCollection<ESM::GameSetting>& gmst,
|
||||||
|
const CSMWorld::IdCollection<ESM::Skill>& skills,
|
||||||
|
const CSMWorld::IdCollection<ESM::MagicEffect>& magicEffects,
|
||||||
|
const CSMWorld::NestedIdCollection<ESM::Spell>& spells)
|
||||||
|
: mGmstTable(gmst), mSkillTable(skills), mMagicEffectTable(magicEffects), mSpells(spells)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
~CSStore() {}
|
||||||
|
|
||||||
|
virtual int findGmstInt(const std::string& name) const
|
||||||
|
{
|
||||||
|
return mGmstTable.getRecord(name).get().getInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual float findGmstFloat(const std::string& name) const
|
||||||
|
{
|
||||||
|
return mGmstTable.getRecord(name).get().getFloat();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const ESM::Skill *findSkill(int index) const
|
||||||
|
{
|
||||||
|
// if the skill does not exist, throws std::runtime_error ("invalid ID: " + id)
|
||||||
|
return &mSkillTable.getRecord(ESM::Skill::indexToId(index)).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const ESM::MagicEffect* findMagicEffect(int id) const
|
||||||
|
{
|
||||||
|
// if the magic effect does not exist, throws std::runtime_error ("invalid ID: " + id)
|
||||||
|
return &mMagicEffectTable.getRecord(ESM::MagicEffect::indexToId((short)id)).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void getSpells(std::vector<ESM::Spell*>& spells)
|
||||||
|
{
|
||||||
|
// prepare data in a format used by OpenMW store
|
||||||
|
for (int index = 0; index < mSpells.getSize(); ++index)
|
||||||
|
spells.push_back(const_cast<ESM::Spell *>(&mSpells.getRecord(index).get()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned short autoCalculateMana(AutoCalc::StatsBase& stats)
|
||||||
|
{
|
||||||
|
return stats.getBaseAttribute(ESM::Attribute::Intelligence) * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned short autoCalculateFatigue(AutoCalc::StatsBase& stats)
|
||||||
|
{
|
||||||
|
return stats.getBaseAttribute(ESM::Attribute::Strength)
|
||||||
|
+ stats.getBaseAttribute(ESM::Attribute::Willpower)
|
||||||
|
+ stats.getBaseAttribute(ESM::Attribute::Agility)
|
||||||
|
+ stats.getBaseAttribute(ESM::Attribute::Endurance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CSMWorld::Data::addModel (QAbstractItemModel *model, UniversalId::Type type, bool update)
|
void CSMWorld::Data::addModel (QAbstractItemModel *model, UniversalId::Type type, bool update)
|
||||||
{
|
{
|
||||||
|
@ -61,7 +129,7 @@ int CSMWorld::Data::count (RecordBase::State state, const CollectionBase& collec
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourcesManager)
|
CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourcesManager)
|
||||||
: mEncoder (encoding), mPathgrids (mCells), mRefs (mCells),
|
: mEncoder (encoding), mPathgrids (mCells), mReferenceables(self()), mRefs (mCells),
|
||||||
mResourcesManager (resourcesManager), mReader (0), mDialogue (0), mReaderIndex(0)
|
mResourcesManager (resourcesManager), mReader (0), mDialogue (0), mReaderIndex(0)
|
||||||
{
|
{
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
@ -137,22 +205,24 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
|
||||||
mRaces.getNestableColumn(index)->addColumn(
|
mRaces.getNestableColumn(index)->addColumn(
|
||||||
new NestedChildColumn (Columns::ColumnId_SpellId, ColumnBase::Display_Spell));
|
new NestedChildColumn (Columns::ColumnId_SpellId, ColumnBase::Display_Spell));
|
||||||
// Race attributes
|
// 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;
|
index = mRaces.getColumns()-1;
|
||||||
mRaces.addAdapter (std::make_pair(&mRaces.getColumn(index), new RaceAttributeAdapter()));
|
mRaces.addAdapter (std::make_pair(&mRaces.getColumn(index), new RaceAttributeAdapter()));
|
||||||
mRaces.getNestableColumn(index)->addColumn(
|
mRaces.getNestableColumn(index)->addColumn(
|
||||||
new NestedChildColumn (Columns::ColumnId_RaceAttributes, ColumnBase::Display_String,
|
new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_Attribute,
|
||||||
ColumnBase::Flag_Dialogue, false));
|
ColumnBase::Flag_Dialogue, false));
|
||||||
mRaces.getNestableColumn(index)->addColumn(
|
mRaces.getNestableColumn(index)->addColumn(
|
||||||
new NestedChildColumn (Columns::ColumnId_RaceMaleValue, ColumnBase::Display_Integer));
|
new NestedChildColumn (Columns::ColumnId_Male, ColumnBase::Display_Integer));
|
||||||
mRaces.getNestableColumn(index)->addColumn(
|
mRaces.getNestableColumn(index)->addColumn(
|
||||||
new NestedChildColumn (Columns::ColumnId_RaceFemaleValue, ColumnBase::Display_Integer));
|
new NestedChildColumn (Columns::ColumnId_Female, ColumnBase::Display_Integer));
|
||||||
// Race skill bonus
|
// 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;
|
index = mRaces.getColumns()-1;
|
||||||
mRaces.addAdapter (std::make_pair(&mRaces.getColumn(index), new RaceSkillsBonusAdapter()));
|
mRaces.addAdapter (std::make_pair(&mRaces.getColumn(index), new RaceSkillsBonusAdapter()));
|
||||||
mRaces.getNestableColumn(index)->addColumn(
|
mRaces.getNestableColumn(index)->addColumn(
|
||||||
new NestedChildColumn (Columns::ColumnId_RaceSkill, ColumnBase::Display_RaceSkill));
|
new NestedChildColumn (Columns::ColumnId_Skill, ColumnBase::Display_SkillId));
|
||||||
mRaces.getNestableColumn(index)->addColumn(
|
mRaces.getNestableColumn(index)->addColumn(
|
||||||
new NestedChildColumn (Columns::ColumnId_RaceBonus, ColumnBase::Display_Integer));
|
new NestedChildColumn (Columns::ColumnId_RaceBonus, ColumnBase::Display_Integer));
|
||||||
|
|
||||||
|
@ -202,7 +272,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
|
||||||
mSpells.addColumn (new RecordStateColumn<ESM::Spell>);
|
mSpells.addColumn (new RecordStateColumn<ESM::Spell>);
|
||||||
mSpells.addColumn (new FixedRecordTypeColumn<ESM::Spell> (UniversalId::Type_Spell));
|
mSpells.addColumn (new FixedRecordTypeColumn<ESM::Spell> (UniversalId::Type_Spell));
|
||||||
mSpells.addColumn (new NameColumn<ESM::Spell>);
|
mSpells.addColumn (new NameColumn<ESM::Spell>);
|
||||||
mSpells.addColumn (new SpellTypeColumn<ESM::Spell>);
|
mSpells.addColumn (new SpellTypeColumn<ESM::Spell>); // ColumnId_SpellType
|
||||||
mSpells.addColumn (new CostColumn<ESM::Spell>);
|
mSpells.addColumn (new CostColumn<ESM::Spell>);
|
||||||
mSpells.addColumn (new FlagColumn<ESM::Spell> (Columns::ColumnId_AutoCalc, 0x1));
|
mSpells.addColumn (new FlagColumn<ESM::Spell> (Columns::ColumnId_AutoCalc, 0x1));
|
||||||
mSpells.addColumn (new FlagColumn<ESM::Spell> (Columns::ColumnId_StarterSpell, 0x2));
|
mSpells.addColumn (new FlagColumn<ESM::Spell> (Columns::ColumnId_StarterSpell, 0x2));
|
||||||
|
@ -214,9 +284,9 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
|
||||||
mSpells.getNestableColumn(index)->addColumn(
|
mSpells.getNestableColumn(index)->addColumn(
|
||||||
new NestedChildColumn (Columns::ColumnId_EffectId, ColumnBase::Display_EffectId));
|
new NestedChildColumn (Columns::ColumnId_EffectId, ColumnBase::Display_EffectId));
|
||||||
mSpells.getNestableColumn(index)->addColumn(
|
mSpells.getNestableColumn(index)->addColumn(
|
||||||
new NestedChildColumn (Columns::ColumnId_SkillImpact, ColumnBase::Display_SkillImpact));
|
new NestedChildColumn (Columns::ColumnId_Skill, ColumnBase::Display_EffectSkill));
|
||||||
mSpells.getNestableColumn(index)->addColumn(
|
mSpells.getNestableColumn(index)->addColumn(
|
||||||
new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_Attribute));
|
new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_EffectAttribute));
|
||||||
mSpells.getNestableColumn(index)->addColumn(
|
mSpells.getNestableColumn(index)->addColumn(
|
||||||
new NestedChildColumn (Columns::ColumnId_EffectRange, ColumnBase::Display_EffectRange));
|
new NestedChildColumn (Columns::ColumnId_EffectRange, ColumnBase::Display_EffectRange));
|
||||||
mSpells.getNestableColumn(index)->addColumn(
|
mSpells.getNestableColumn(index)->addColumn(
|
||||||
|
@ -224,9 +294,9 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
|
||||||
mSpells.getNestableColumn(index)->addColumn(
|
mSpells.getNestableColumn(index)->addColumn(
|
||||||
new NestedChildColumn (Columns::ColumnId_Duration, ColumnBase::Display_Integer)); // reuse from light
|
new NestedChildColumn (Columns::ColumnId_Duration, ColumnBase::Display_Integer)); // reuse from light
|
||||||
mSpells.getNestableColumn(index)->addColumn(
|
mSpells.getNestableColumn(index)->addColumn(
|
||||||
new NestedChildColumn (Columns::ColumnId_MinRange, ColumnBase::Display_Integer)); // reuse from sound
|
new NestedChildColumn (Columns::ColumnId_MinMagnitude, ColumnBase::Display_Integer));
|
||||||
mSpells.getNestableColumn(index)->addColumn(
|
mSpells.getNestableColumn(index)->addColumn(
|
||||||
new NestedChildColumn (Columns::ColumnId_MaxRange, ColumnBase::Display_Integer)); // reuse from sound
|
new NestedChildColumn (Columns::ColumnId_MaxMagnitude, ColumnBase::Display_Integer));
|
||||||
|
|
||||||
mTopics.addColumn (new StringIdColumn<ESM::Dialogue>);
|
mTopics.addColumn (new StringIdColumn<ESM::Dialogue>);
|
||||||
mTopics.addColumn (new RecordStateColumn<ESM::Dialogue>);
|
mTopics.addColumn (new RecordStateColumn<ESM::Dialogue>);
|
||||||
|
@ -330,9 +400,9 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
|
||||||
mEnchantments.getNestableColumn(index)->addColumn(
|
mEnchantments.getNestableColumn(index)->addColumn(
|
||||||
new NestedChildColumn (Columns::ColumnId_EffectId, ColumnBase::Display_EffectId));
|
new NestedChildColumn (Columns::ColumnId_EffectId, ColumnBase::Display_EffectId));
|
||||||
mEnchantments.getNestableColumn(index)->addColumn(
|
mEnchantments.getNestableColumn(index)->addColumn(
|
||||||
new NestedChildColumn (Columns::ColumnId_SkillImpact, ColumnBase::Display_SkillImpact));
|
new NestedChildColumn (Columns::ColumnId_Skill, ColumnBase::Display_EffectSkill));
|
||||||
mEnchantments.getNestableColumn(index)->addColumn(
|
mEnchantments.getNestableColumn(index)->addColumn(
|
||||||
new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_Attribute));
|
new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_EffectAttribute));
|
||||||
mEnchantments.getNestableColumn(index)->addColumn(
|
mEnchantments.getNestableColumn(index)->addColumn(
|
||||||
new NestedChildColumn (Columns::ColumnId_EffectRange, ColumnBase::Display_EffectRange));
|
new NestedChildColumn (Columns::ColumnId_EffectRange, ColumnBase::Display_EffectRange));
|
||||||
mEnchantments.getNestableColumn(index)->addColumn(
|
mEnchantments.getNestableColumn(index)->addColumn(
|
||||||
|
@ -340,9 +410,9 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
|
||||||
mEnchantments.getNestableColumn(index)->addColumn(
|
mEnchantments.getNestableColumn(index)->addColumn(
|
||||||
new NestedChildColumn (Columns::ColumnId_Duration, ColumnBase::Display_Integer)); // reuse from light
|
new NestedChildColumn (Columns::ColumnId_Duration, ColumnBase::Display_Integer)); // reuse from light
|
||||||
mEnchantments.getNestableColumn(index)->addColumn(
|
mEnchantments.getNestableColumn(index)->addColumn(
|
||||||
new NestedChildColumn (Columns::ColumnId_MinRange, ColumnBase::Display_Integer)); // reuse from sound
|
new NestedChildColumn (Columns::ColumnId_MinMagnitude, ColumnBase::Display_Integer));
|
||||||
mEnchantments.getNestableColumn(index)->addColumn(
|
mEnchantments.getNestableColumn(index)->addColumn(
|
||||||
new NestedChildColumn (Columns::ColumnId_MaxRange, ColumnBase::Display_Integer)); // reuse from sound
|
new NestedChildColumn (Columns::ColumnId_MaxMagnitude, ColumnBase::Display_Integer));
|
||||||
|
|
||||||
mBodyParts.addColumn (new StringIdColumn<ESM::BodyPart>);
|
mBodyParts.addColumn (new StringIdColumn<ESM::BodyPart>);
|
||||||
mBodyParts.addColumn (new RecordStateColumn<ESM::BodyPart>);
|
mBodyParts.addColumn (new RecordStateColumn<ESM::BodyPart>);
|
||||||
|
@ -352,9 +422,12 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
|
||||||
mBodyParts.addColumn (new FlagColumn<ESM::BodyPart> (Columns::ColumnId_Female, ESM::BodyPart::BPF_Female));
|
mBodyParts.addColumn (new FlagColumn<ESM::BodyPart> (Columns::ColumnId_Female, ESM::BodyPart::BPF_Female));
|
||||||
mBodyParts.addColumn (new FlagColumn<ESM::BodyPart> (Columns::ColumnId_Playable,
|
mBodyParts.addColumn (new FlagColumn<ESM::BodyPart> (Columns::ColumnId_Playable,
|
||||||
ESM::BodyPart::BPF_NotPlayable, ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, true));
|
ESM::BodyPart::BPF_NotPlayable, ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, true));
|
||||||
mBodyParts.addColumn (new MeshTypeColumn<ESM::BodyPart>);
|
|
||||||
|
int meshTypeFlags = ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh;
|
||||||
|
MeshTypeColumn<ESM::BodyPart> *meshTypeColumn = new MeshTypeColumn<ESM::BodyPart>(meshTypeFlags);
|
||||||
|
mBodyParts.addColumn (meshTypeColumn);
|
||||||
mBodyParts.addColumn (new ModelColumn<ESM::BodyPart>);
|
mBodyParts.addColumn (new ModelColumn<ESM::BodyPart>);
|
||||||
mBodyParts.addColumn (new RaceColumn<ESM::BodyPart>);
|
mBodyParts.addColumn (new BodyPartRaceColumn(meshTypeColumn));
|
||||||
|
|
||||||
mSoundGens.addColumn (new StringIdColumn<ESM::SoundGenerator>);
|
mSoundGens.addColumn (new StringIdColumn<ESM::SoundGenerator>);
|
||||||
mSoundGens.addColumn (new RecordStateColumn<ESM::SoundGenerator>);
|
mSoundGens.addColumn (new RecordStateColumn<ESM::SoundGenerator>);
|
||||||
|
@ -475,6 +548,23 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
|
||||||
mDebugProfiles.addColumn (new ScriptColumn<ESM::DebugProfile> (
|
mDebugProfiles.addColumn (new ScriptColumn<ESM::DebugProfile> (
|
||||||
ScriptColumn<ESM::DebugProfile>::Type_Lines));
|
ScriptColumn<ESM::DebugProfile>::Type_Lines));
|
||||||
|
|
||||||
|
mMetaData.appendBlankRecord ("sys::meta");
|
||||||
|
|
||||||
|
mMetaData.addColumn (new StringIdColumn<MetaData> (true));
|
||||||
|
mMetaData.addColumn (new RecordStateColumn<MetaData>);
|
||||||
|
mMetaData.addColumn (new FixedRecordTypeColumn<MetaData> (UniversalId::Type_MetaData));
|
||||||
|
mMetaData.addColumn (new FormatColumn<MetaData>);
|
||||||
|
mMetaData.addColumn (new AuthorColumn<MetaData>);
|
||||||
|
mMetaData.addColumn (new FileDescriptionColumn<MetaData>);
|
||||||
|
|
||||||
|
mLandTextures.addColumn (new StringIdColumn<LandTexture>);
|
||||||
|
mLandTextures.addColumn (new RecordStateColumn<LandTexture>);
|
||||||
|
mLandTextures.addColumn (new FixedRecordTypeColumn<LandTexture> (UniversalId::Type_LandTexture));
|
||||||
|
|
||||||
|
mLand.addColumn (new StringIdColumn<Land>);
|
||||||
|
mLand.addColumn (new RecordStateColumn<Land>);
|
||||||
|
mLand.addColumn (new FixedRecordTypeColumn<Land> (UniversalId::Type_Land));
|
||||||
|
|
||||||
addModel (new IdTable (&mGlobals), UniversalId::Type_Global);
|
addModel (new IdTable (&mGlobals), UniversalId::Type_Global);
|
||||||
addModel (new IdTable (&mGmsts), UniversalId::Type_Gmst);
|
addModel (new IdTable (&mGmsts), UniversalId::Type_Gmst);
|
||||||
addModel (new IdTable (&mSkills), UniversalId::Type_Skill);
|
addModel (new IdTable (&mSkills), UniversalId::Type_Skill);
|
||||||
|
@ -515,12 +605,44 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
|
||||||
UniversalId::Type_Texture);
|
UniversalId::Type_Texture);
|
||||||
addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_Videos)),
|
addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_Videos)),
|
||||||
UniversalId::Type_Video);
|
UniversalId::Type_Video);
|
||||||
|
addModel (new IdTable (&mMetaData), UniversalId::Type_MetaData);
|
||||||
|
addModel (new IdTable (&mLand), UniversalId::Type_Land);
|
||||||
|
addModel (new IdTable (&mLandTextures), UniversalId::Type_LandTexture);
|
||||||
|
|
||||||
|
// for autocalc updates when gmst/race/class/skils tables change
|
||||||
|
CSMWorld::IdTable *gmsts =
|
||||||
|
static_cast<CSMWorld::IdTable*>(getTableModel(UniversalId::Type_Gmst));
|
||||||
|
CSMWorld::IdTable *skills =
|
||||||
|
static_cast<CSMWorld::IdTable*>(getTableModel(UniversalId::Type_Skill));
|
||||||
|
CSMWorld::IdTable *classes =
|
||||||
|
static_cast<CSMWorld::IdTable*>(getTableModel(UniversalId::Type_Class));
|
||||||
|
CSMWorld::IdTree *races =
|
||||||
|
static_cast<CSMWorld::IdTree*>(getTableModel(UniversalId::Type_Race));
|
||||||
|
CSMWorld::IdTree *objects =
|
||||||
|
static_cast<CSMWorld::IdTree*>(getTableModel(UniversalId::Type_Referenceable));
|
||||||
|
|
||||||
|
connect (gmsts, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
|
||||||
|
this, SLOT (gmstDataChanged (const QModelIndex&, const QModelIndex&)));
|
||||||
|
connect (skills, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
|
||||||
|
this, SLOT (skillDataChanged (const QModelIndex&, const QModelIndex&)));
|
||||||
|
connect (classes, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
|
||||||
|
this, SLOT (classDataChanged (const QModelIndex&, const QModelIndex&)));
|
||||||
|
connect (races, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
|
||||||
|
this, SLOT (raceDataChanged (const QModelIndex&, const QModelIndex&)));
|
||||||
|
connect (objects, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
|
||||||
|
this, SLOT (npcDataChanged (const QModelIndex&, const QModelIndex&)));
|
||||||
|
connect (this, SIGNAL (updateNpcAutocalc (int, const std::string&)),
|
||||||
|
objects, SLOT (updateNpcAutocalc (int, const std::string&)));
|
||||||
|
connect (this, SIGNAL (cacheNpcStats (const std::string&, NpcStats*)),
|
||||||
|
this, SLOT (cacheNpcStatsEvent (const std::string&, NpcStats*)));
|
||||||
|
|
||||||
mRefLoadCache.clear(); // clear here rather than startLoading() and continueLoading() for multiple content files
|
mRefLoadCache.clear(); // clear here rather than startLoading() and continueLoading() for multiple content files
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::Data::~Data()
|
CSMWorld::Data::~Data()
|
||||||
{
|
{
|
||||||
|
clearNpcStatsCache();
|
||||||
|
|
||||||
for (std::vector<QAbstractItemModel *>::iterator iter (mModels.begin()); iter!=mModels.end(); ++iter)
|
for (std::vector<QAbstractItemModel *>::iterator iter (mModels.begin()); iter!=mModels.end(); ++iter)
|
||||||
delete *iter;
|
delete *iter;
|
||||||
|
|
||||||
|
@ -753,11 +875,21 @@ const CSMWorld::IdCollection<CSMWorld::Land>& CSMWorld::Data::getLand() const
|
||||||
return mLand;
|
return mLand;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CSMWorld::IdCollection<CSMWorld::Land>& CSMWorld::Data::getLand()
|
||||||
|
{
|
||||||
|
return mLand;
|
||||||
|
}
|
||||||
|
|
||||||
const CSMWorld::IdCollection<CSMWorld::LandTexture>& CSMWorld::Data::getLandTextures() const
|
const CSMWorld::IdCollection<CSMWorld::LandTexture>& CSMWorld::Data::getLandTextures() const
|
||||||
{
|
{
|
||||||
return mLandTextures;
|
return mLandTextures;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CSMWorld::IdCollection<CSMWorld::LandTexture>& CSMWorld::Data::getLandTextures()
|
||||||
|
{
|
||||||
|
return mLandTextures;
|
||||||
|
}
|
||||||
|
|
||||||
const CSMWorld::IdCollection<ESM::SoundGenerator>& CSMWorld::Data::getSoundGens() const
|
const CSMWorld::IdCollection<ESM::SoundGenerator>& CSMWorld::Data::getSoundGens() const
|
||||||
{
|
{
|
||||||
return mSoundGens;
|
return mSoundGens;
|
||||||
|
@ -803,6 +935,17 @@ const CSMWorld::Resources& CSMWorld::Data::getResources (const UniversalId& id)
|
||||||
return mResourcesManager.get (id.getType());
|
return mResourcesManager.get (id.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CSMWorld::MetaData& CSMWorld::Data::getMetaData() const
|
||||||
|
{
|
||||||
|
return mMetaData.getRecord (0).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::Data::setMetaData (const MetaData& metaData)
|
||||||
|
{
|
||||||
|
Record<MetaData> record (RecordBase::State_ModifiedOnly, 0, &metaData);
|
||||||
|
mMetaData.setRecord (0, record);
|
||||||
|
}
|
||||||
|
|
||||||
QAbstractItemModel *CSMWorld::Data::getTableModel (const CSMWorld::UniversalId& id)
|
QAbstractItemModel *CSMWorld::Data::getTableModel (const CSMWorld::UniversalId& id)
|
||||||
{
|
{
|
||||||
std::map<UniversalId::Type, QAbstractItemModel *>::iterator iter = mModelIndex.find (id.getType());
|
std::map<UniversalId::Type, QAbstractItemModel *>::iterator iter = mModelIndex.find (id.getType());
|
||||||
|
@ -847,8 +990,14 @@ int CSMWorld::Data::startLoading (const boost::filesystem::path& path, bool base
|
||||||
mBase = base;
|
mBase = base;
|
||||||
mProject = project;
|
mProject = project;
|
||||||
|
|
||||||
mAuthor = mReader->getAuthor();
|
if (!mProject && !mBase)
|
||||||
mDescription = mReader->getDesc();
|
{
|
||||||
|
MetaData metaData;
|
||||||
|
metaData.mId = "sys::meta";
|
||||||
|
metaData.load (*mReader);
|
||||||
|
|
||||||
|
mMetaData.setRecord (0, Record<MetaData> (RecordBase::State_ModifiedOnly, 0, &metaData));
|
||||||
|
}
|
||||||
|
|
||||||
return mReader->getRecordCount();
|
return mReader->getRecordCount();
|
||||||
}
|
}
|
||||||
|
@ -908,8 +1057,10 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages)
|
||||||
{
|
{
|
||||||
int index = mLand.load(*mReader, mBase);
|
int index = mLand.load(*mReader, mBase);
|
||||||
|
|
||||||
if (index!=-1 && !mBase)
|
// Load all land data for now. A future optimisation may only load non-base data
|
||||||
mLand.getRecord (index).mModified.mLand->loadData (
|
// if a suitable mechanism for avoiding race conditions can be established.
|
||||||
|
if (index!=-1/* && !mBase*/)
|
||||||
|
mLand.getRecord (index).get().loadData (
|
||||||
ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | ESM::Land::DATA_VCLR |
|
ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | ESM::Land::DATA_VCLR |
|
||||||
ESM::Land::DATA_VTEX | ESM::Land::DATA_WNAM);
|
ESM::Land::DATA_VTEX | ESM::Land::DATA_WNAM);
|
||||||
|
|
||||||
|
@ -923,7 +1074,7 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages)
|
||||||
{
|
{
|
||||||
// log an error and continue loading the refs to the last loaded cell
|
// log an error and continue loading the refs to the last loaded cell
|
||||||
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_None);
|
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_None);
|
||||||
messages.add (id, "Logic error: cell index out of bounds");
|
messages.add (id, "Logic error: cell index out of bounds", "", CSMDoc::Message::Severity_Error);
|
||||||
index = mCells.getSize()-1;
|
index = mCells.getSize()-1;
|
||||||
}
|
}
|
||||||
std::string cellId = Misc::StringUtils::lowerCase (mCells.getId (index));
|
std::string cellId = Misc::StringUtils::lowerCase (mCells.getId (index));
|
||||||
|
@ -984,7 +1135,8 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
messages.add (UniversalId::Type_None,
|
messages.add (UniversalId::Type_None,
|
||||||
"Trying to delete dialogue record " + id + " which does not exist");
|
"Trying to delete dialogue record " + id + " which does not exist",
|
||||||
|
"", CSMDoc::Message::Severity_Warning);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1001,7 +1153,7 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages)
|
||||||
if (!mDialogue)
|
if (!mDialogue)
|
||||||
{
|
{
|
||||||
messages.add (UniversalId::Type_None,
|
messages.add (UniversalId::Type_None,
|
||||||
"Found info record not following a dialogue record");
|
"Found info record not following a dialogue record", "", CSMDoc::Message::Severity_Error);
|
||||||
|
|
||||||
mReader->skipRecord();
|
mReader->skipRecord();
|
||||||
break;
|
break;
|
||||||
|
@ -1044,7 +1196,8 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages)
|
||||||
|
|
||||||
if (unhandledRecord)
|
if (unhandledRecord)
|
||||||
{
|
{
|
||||||
messages.add (UniversalId::Type_None, "Unsupported record type: " + n.toString());
|
messages.add (UniversalId::Type_None, "Unsupported record type: " + n.toString(), "",
|
||||||
|
CSMDoc::Message::Severity_Error);
|
||||||
|
|
||||||
mReader->skipRecord();
|
mReader->skipRecord();
|
||||||
}
|
}
|
||||||
|
@ -1101,26 +1254,6 @@ int CSMWorld::Data::count (RecordBase::State state) const
|
||||||
count (state, mPathgrids);
|
count (state, mPathgrids);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMWorld::Data::setDescription (const std::string& description)
|
|
||||||
{
|
|
||||||
mDescription = description;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CSMWorld::Data::getDescription() const
|
|
||||||
{
|
|
||||||
return mDescription;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSMWorld::Data::setAuthor (const std::string& author)
|
|
||||||
{
|
|
||||||
mAuthor = author;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CSMWorld::Data::getAuthor() const
|
|
||||||
{
|
|
||||||
return mAuthor;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> CSMWorld::Data::getIds (bool listDeleted) const
|
std::vector<std::string> CSMWorld::Data::getIds (bool listDeleted) const
|
||||||
{
|
{
|
||||||
std::vector<std::string> ids;
|
std::vector<std::string> ids;
|
||||||
|
@ -1159,3 +1292,276 @@ void CSMWorld::Data::rowsChanged (const QModelIndex& parent, int start, int end)
|
||||||
{
|
{
|
||||||
emit idListChanged();
|
emit idListChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CSMWorld::Data& CSMWorld::Data::self ()
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::Data::skillDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight)
|
||||||
|
{
|
||||||
|
// mData.mAttribute (affects attributes skill bonus autocalc)
|
||||||
|
// mData.mSpecialization (affects skills autocalc)
|
||||||
|
CSMWorld::IdTable *skillModel =
|
||||||
|
static_cast<CSMWorld::IdTable*>(getTableModel(CSMWorld::UniversalId::Type_Skill));
|
||||||
|
|
||||||
|
int attributeColumn = skillModel->findColumnIndex(CSMWorld::Columns::ColumnId_Attribute);
|
||||||
|
int specialisationColumn = skillModel->findColumnIndex(CSMWorld::Columns::ColumnId_Specialisation);
|
||||||
|
|
||||||
|
if ((topLeft.column() <= attributeColumn && attributeColumn <= bottomRight.column())
|
||||||
|
|| (topLeft.column() <= specialisationColumn && specialisationColumn <= bottomRight.column()))
|
||||||
|
{
|
||||||
|
clearNpcStatsCache();
|
||||||
|
|
||||||
|
std::string empty;
|
||||||
|
emit updateNpcAutocalc(0/*all*/, empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::Data::classDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight)
|
||||||
|
{
|
||||||
|
// update autocalculated attributes/skills of every NPC with matching class
|
||||||
|
// - mData.mAttribute[2]
|
||||||
|
// - mData.mSkills[5][2]
|
||||||
|
// - mData.mSpecialization
|
||||||
|
CSMWorld::IdTable *classModel =
|
||||||
|
static_cast<CSMWorld::IdTable*>(getTableModel(CSMWorld::UniversalId::Type_Class));
|
||||||
|
|
||||||
|
int attribute1Column = classModel->findColumnIndex(CSMWorld::Columns::ColumnId_Attribute1); // +1
|
||||||
|
int majorSkill1Column = classModel->findColumnIndex(CSMWorld::Columns::ColumnId_MajorSkill1); // +4
|
||||||
|
int minorSkill1Column = classModel->findColumnIndex(CSMWorld::Columns::ColumnId_MinorSkill1); // +4
|
||||||
|
int specialisationColumn = classModel->findColumnIndex(CSMWorld::Columns::ColumnId_Specialisation);
|
||||||
|
|
||||||
|
if ((topLeft.column() > attribute1Column+1 || attribute1Column > bottomRight.column())
|
||||||
|
&& (topLeft.column() > majorSkill1Column+4 || majorSkill1Column > bottomRight.column())
|
||||||
|
&& (topLeft.column() > minorSkill1Column+4 || minorSkill1Column > bottomRight.column())
|
||||||
|
&& (topLeft.column() > specialisationColumn || specialisationColumn > bottomRight.column()))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the affected class
|
||||||
|
int idColumn = classModel->findColumnIndex(CSMWorld::Columns::ColumnId_Id);
|
||||||
|
for (int classRow = topLeft.row(); classRow <= bottomRight.row(); ++classRow)
|
||||||
|
{
|
||||||
|
clearNpcStatsCache();
|
||||||
|
|
||||||
|
std::string classId =
|
||||||
|
classModel->data(classModel->index(classRow, idColumn)).toString().toUtf8().constData();
|
||||||
|
emit updateNpcAutocalc(1/*class*/, classId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::Data::raceDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight)
|
||||||
|
{
|
||||||
|
// affects racial bonus attributes & skills
|
||||||
|
// - mData.mAttributeValues[]
|
||||||
|
// - mData.mBonus[].mBonus
|
||||||
|
// - mPowers.mList[]
|
||||||
|
CSMWorld::IdTree *raceModel =
|
||||||
|
static_cast<CSMWorld::IdTree*>(getTableModel(CSMWorld::UniversalId::Type_Race));
|
||||||
|
|
||||||
|
int attrColumn = raceModel->findColumnIndex(CSMWorld::Columns::ColumnId_RaceAttributes);
|
||||||
|
int bonusColumn = raceModel->findColumnIndex(CSMWorld::Columns::ColumnId_RaceSkillBonus);
|
||||||
|
int powersColumn = raceModel->findColumnIndex(CSMWorld::Columns::ColumnId_PowerList);
|
||||||
|
|
||||||
|
bool match = false;
|
||||||
|
int raceRow = topLeft.row();
|
||||||
|
int raceEnd = bottomRight.row();
|
||||||
|
if (topLeft.parent().isValid() && bottomRight.parent().isValid())
|
||||||
|
{
|
||||||
|
if ((topLeft.parent().column() <= attrColumn && attrColumn <= bottomRight.parent().column())
|
||||||
|
|| (topLeft.parent().column() <= bonusColumn && bonusColumn <= bottomRight.parent().column())
|
||||||
|
|| (topLeft.parent().column() <= powersColumn && powersColumn <= bottomRight.parent().column()))
|
||||||
|
{
|
||||||
|
match = true; // TODO: check for specific nested column?
|
||||||
|
raceRow = topLeft.parent().row();
|
||||||
|
raceEnd = bottomRight.parent().row();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((topLeft.column() <= attrColumn && attrColumn <= bottomRight.column())
|
||||||
|
|| (topLeft.column() <= bonusColumn && bonusColumn <= bottomRight.column())
|
||||||
|
|| (topLeft.column() <= powersColumn && powersColumn <= bottomRight.column()))
|
||||||
|
{
|
||||||
|
match = true; // maybe the whole table changed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!match)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// update autocalculated attributes/skills of every NPC with matching race
|
||||||
|
int idColumn = raceModel->findColumnIndex(CSMWorld::Columns::ColumnId_Id);
|
||||||
|
for (; raceRow <= raceEnd; ++raceRow)
|
||||||
|
{
|
||||||
|
clearNpcStatsCache();
|
||||||
|
|
||||||
|
std::string raceId =
|
||||||
|
raceModel->data(raceModel->index(raceRow, idColumn)).toString().toUtf8().constData();
|
||||||
|
emit updateNpcAutocalc(2/*race*/, raceId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::Data::npcDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight)
|
||||||
|
{
|
||||||
|
// TODO: for now always recalculate
|
||||||
|
clearNpcStatsCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::Data::gmstDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight)
|
||||||
|
{
|
||||||
|
static const QStringList gmsts(QStringList()<< "fNPCbaseMagickaMult" << "fAutoSpellChance"
|
||||||
|
<< "fEffectCostMult" << "iAutoSpellAlterationMax" << "iAutoSpellConjurationMax"
|
||||||
|
<< "iAutoSpellDestructionMax" << "iAutoSpellIllusionMax" << "iAutoSpellMysticismMax"
|
||||||
|
<< "iAutoSpellRestorationMax" << "iAutoSpellTimesCanCast" << "iAutoSpellAttSkillMin");
|
||||||
|
|
||||||
|
bool match = false;
|
||||||
|
for (int row = topLeft.row(); row <= bottomRight.row(); ++row)
|
||||||
|
{
|
||||||
|
if (gmsts.contains(mGmsts.getRecord(row).get().mId.c_str()))
|
||||||
|
{
|
||||||
|
match = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!match)
|
||||||
|
return;
|
||||||
|
|
||||||
|
clearNpcStatsCache();
|
||||||
|
|
||||||
|
std::string empty;
|
||||||
|
emit updateNpcAutocalc(0/*all*/, empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::Data::clearNpcStatsCache ()
|
||||||
|
{
|
||||||
|
for (std::map<std::string, CSMWorld::NpcStats*>::iterator it (mNpcStatCache.begin());
|
||||||
|
it != mNpcStatCache.end(); ++it)
|
||||||
|
delete it->second;
|
||||||
|
|
||||||
|
mNpcStatCache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
CSMWorld::NpcStats* CSMWorld::Data::npcAutoCalculate(const ESM::NPC& npc) const
|
||||||
|
{
|
||||||
|
CSMWorld::NpcStats * cachedStats = getCachedNpcData (npc.mId);
|
||||||
|
if (cachedStats)
|
||||||
|
return cachedStats;
|
||||||
|
|
||||||
|
int raceIndex = mRaces.searchId(npc.mRace);
|
||||||
|
int classIndex = mClasses.searchId(npc.mClass);
|
||||||
|
// this can happen when creating a new game from scratch
|
||||||
|
if (raceIndex == -1 || classIndex == -1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const ESM::Race *race = &mRaces.getRecord(raceIndex).get();
|
||||||
|
const ESM::Class *class_ = &mClasses.getRecord(classIndex).get();
|
||||||
|
|
||||||
|
bool autoCalc = npc.mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS;
|
||||||
|
short level = npc.mNpdt52.mLevel;
|
||||||
|
if (autoCalc)
|
||||||
|
level = npc.mNpdt12.mLevel;
|
||||||
|
|
||||||
|
std::auto_ptr<CSMWorld::NpcStats> stats (new CSMWorld::NpcStats());
|
||||||
|
|
||||||
|
CSStore store(mGmsts, mSkills, mMagicEffects, mSpells);
|
||||||
|
|
||||||
|
if (autoCalc)
|
||||||
|
{
|
||||||
|
AutoCalc::autoCalcAttributesImpl (&npc, race, class_, level, *stats, &store);
|
||||||
|
|
||||||
|
stats->setHealth(autoCalculateHealth(level, class_, *stats));
|
||||||
|
stats->setMana(autoCalculateMana(*stats));
|
||||||
|
stats->setFatigue(autoCalculateFatigue(*stats));
|
||||||
|
|
||||||
|
AutoCalc::autoCalcSkillsImpl(&npc, race, class_, level, *stats, &store);
|
||||||
|
|
||||||
|
AutoCalc::autoCalculateSpells(race, *stats, &store);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (std::vector<std::string>::const_iterator it = npc.mSpells.mList.begin();
|
||||||
|
it != npc.mSpells.mList.end(); ++it)
|
||||||
|
{
|
||||||
|
stats->addSpell(*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// update spell info
|
||||||
|
const std::vector<std::string> &racePowers = race->mPowers.mList;
|
||||||
|
for (unsigned int i = 0; i < racePowers.size(); ++i)
|
||||||
|
{
|
||||||
|
int type = -1;
|
||||||
|
int spellIndex = mSpells.searchId(racePowers[i]);
|
||||||
|
if (spellIndex != -1)
|
||||||
|
type = mSpells.getRecord(spellIndex).get().mData.mType;
|
||||||
|
stats->addPowers(racePowers[i], type);
|
||||||
|
}
|
||||||
|
// cost/chance
|
||||||
|
int skills[ESM::Skill::Length];
|
||||||
|
if (autoCalc)
|
||||||
|
for (int i = 0; i< ESM::Skill::Length; ++i)
|
||||||
|
skills[i] = stats->getBaseSkill(i);
|
||||||
|
else
|
||||||
|
for (int i = 0; i< ESM::Skill::Length; ++i)
|
||||||
|
skills[i] = npc.mNpdt52.mSkills[i];
|
||||||
|
|
||||||
|
int attributes[ESM::Attribute::Length];
|
||||||
|
if (autoCalc)
|
||||||
|
for (int i = 0; i< ESM::Attribute::Length; ++i)
|
||||||
|
attributes[i] = stats->getBaseAttribute(i);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
attributes[ESM::Attribute::Strength] = npc.mNpdt52.mStrength;
|
||||||
|
attributes[ESM::Attribute::Willpower] = npc.mNpdt52.mWillpower;
|
||||||
|
attributes[ESM::Attribute::Agility] = npc.mNpdt52.mAgility;
|
||||||
|
attributes[ESM::Attribute::Speed] = npc.mNpdt52.mSpeed;
|
||||||
|
attributes[ESM::Attribute::Endurance] = npc.mNpdt52.mEndurance;
|
||||||
|
attributes[ESM::Attribute::Personality] = npc.mNpdt52.mPersonality;
|
||||||
|
attributes[ESM::Attribute::Luck] = npc.mNpdt52.mLuck;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<CSMWorld::SpellInfo>& spells = stats->spells();
|
||||||
|
for (std::vector<SpellInfo>::const_iterator it = spells.begin(); it != spells.end(); ++it)
|
||||||
|
{
|
||||||
|
int cost = -1;
|
||||||
|
int spellIndex = mSpells.searchId((*it).mName);
|
||||||
|
const ESM::Spell* spell = 0;
|
||||||
|
if (spellIndex != -1)
|
||||||
|
{
|
||||||
|
spell = &mSpells.getRecord(spellIndex).get();
|
||||||
|
cost = spell->mData.mCost;
|
||||||
|
|
||||||
|
int school;
|
||||||
|
float skillTerm;
|
||||||
|
AutoCalc::calcWeakestSchool(spell, skills, school, skillTerm, &store);
|
||||||
|
float chance = calcAutoCastChance(spell, skills, attributes, school, &store);
|
||||||
|
|
||||||
|
stats->addCostAndChance((*it).mName, cost, (int)ceil(chance)); // percent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stats.get() == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
CSMWorld::NpcStats *result = stats.release();
|
||||||
|
emit cacheNpcStats (npc.mId, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::Data::cacheNpcStatsEvent (const std::string& id, CSMWorld::NpcStats *stats)
|
||||||
|
{
|
||||||
|
mNpcStatCache[id] = stats;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSMWorld::NpcStats* CSMWorld::Data::getCachedNpcData (const std::string& id) const
|
||||||
|
{
|
||||||
|
std::map<std::string, CSMWorld::NpcStats*>::const_iterator it = mNpcStatCache.find(id);
|
||||||
|
if (it != mNpcStatCache.end())
|
||||||
|
return it->second;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue