1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-16 17:19:56 +00:00

Merge branch 'master' into pathgrid-edit

Conflicts:
	apps/opencs/view/render/cell.cpp
This commit is contained in:
cc9cii 2015-04-18 15:47:45 +10:00
commit 03578129c7
447 changed files with 5427 additions and 2978 deletions

View file

@ -21,6 +21,14 @@ addons:
build_command_prepend: "cmake ."
build_command: "make -j3"
branch_pattern: coverity_scan
matrix:
include:
- os: linux
env:
ANALYZE="scan-build-3.6 --use-cc clang-3.6 --use-c++ clang++-3.6 "
compiler: clang
allow_failures:
- env: ANALYZE="scan-build-3.6 --use-cc clang-3.6 --use-c++ clang++-3.6 "
before_install:
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./CI/before_install.linux.sh; fi
@ -30,7 +38,7 @@ before_script:
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then ./CI/before_script.osx.sh; fi
script:
- cd ./build
- if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then make -j4; fi
- if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then ${ANALYZE}make -j4; 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

View file

@ -39,6 +39,7 @@ Programmers
Eli2
Emanuel Guével (potatoesmaster)
eroen
escondida
Evgeniy Mineev (sandstranger)
Fil Krynicki (filkry)
Gašper Sedej

View file

@ -1,3 +1,42 @@
0.35.1
------
Bug #781: incorrect trajectory of the sun
Bug #1079: Wrong starting position in "Character Stuff Wonderland"
Bug #1443: Repetitive taking of a stolen object is repetitively considered as a crime
Bug #1533: Divine Intervention goes to the wrong place.
Bug #1714: No visual indicator for time passed during training
Bug #1916: Telekinesis does not allow safe opening of traps
Bug #2227: Editor: addon file name inconsistency
Bug #2271: Player can melee enemies from water with impunity
Bug #2275: Objects with bigger scale move further using Move script
Bug #2285: Aryon's Dominator enchantment does not work properly
Bug #2290: No punishment for stealing gold from owned containers
Bug #2328: Launcher does not respond to Ctrl+C
Bug #2334: Drag-and-drop on a content file in the launcher creates duplicate items
Bug #2338: Arrows reclaimed from corpses do not stack sometimes
Bug #2344: Launcher - Settings importer running correctly?
Bug #2346: Launcher - Importing plugins into content list screws up the load order
Bug #2348: Mod: H.E.L.L.U.V.A. Handy Holdables does not appear in the content list
Bug #2353: Detect Animal detects dead creatures
Bug #2354: Cmake does not respect LIB_SUFFIX
Bug #2356: Active magic set inactive when switching magic items
Bug #2361: ERROR: ESM Error: Previous record contains unread bytes
Bug #2382: Switching spells with "next spell" or "previous spell" while holding shift promps delete spell dialog
Bug #2388: Regression: Can't toggle map on/off
Bug #2392: MOD Shrines - Restore Health and Cancel Options adds 100 health points
Bug #2394: List of Data Files tab in openmw-laucher needs to show all content files.
Bug #2402: Editor: skills saved incorrectly
Bug #2408: Equipping a constant effect Restore Health/Magicka/Fatigue item will permanently boost the stat it's restoring
Bug #2415: It is now possible to fall off the prison ship into the water when starting a new game
Bug #2419: MOD MCA crash to desktop
Bug #2420: Game crashes when character enters a certain area
Bug #2421: infinite loop when using cycle weapon without having a weapon
Feature #2221: Cannot dress dead NPCs
Feature #2349: Check CMake sets correct MSVC compiler settings for release build.
Feature #2397: Set default values for global mandatory records.
Feature #2412: Basic joystick support
0.35.0
------

View file

@ -1,7 +1,12 @@
#!/bin/sh
export CXX=g++
export CC=gcc
if [ "${ANALYZE}" ]; then
if [ $(lsb_release -sc) = "precise" ]; then
echo "yes" | sudo apt-add-repository ppa:ubuntu-toolchain-r/test
fi
echo "yes" | sudo add-apt-repository "deb http://llvm.org/apt/`lsb_release -sc`/ llvm-toolchain-`lsb_release -sc`-3.6 main"
wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key|sudo apt-key add -
fi
echo "yes" | sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse"
echo "yes" | sudo apt-add-repository ppa:openmw/openmw
@ -10,6 +15,7 @@ sudo apt-get install -qq libgtest-dev google-mock
sudo apt-get install -qq libboost-filesystem-dev libboost-program-options-dev libboost-system-dev libboost-thread-dev libboost-wave-dev
sudo apt-get install -qq libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libavresample-dev
sudo apt-get install -qq libbullet-dev libogre-1.9-dev libmygui-dev libsdl2-dev libunshield-dev libtinyxml-dev libopenal-dev libqt4-dev
if [ "${ANALYZE}" ]; then sudo apt-get install -qq clang-3.6; fi
sudo mkdir /usr/src/gtest/build
cd /usr/src/gtest/build
sudo cmake .. -DBUILD_SHARED_LIBS=1

View file

@ -2,4 +2,6 @@
mkdir build
cd build
cmake .. -DBUILD_WITH_CODE_COVERAGE=1 -DBUILD_UNITTESTS=1 -DCMAKE_INSTALL_PREFIX=/usr -DBINDIR=/usr/games -DCMAKE_BUILD_TYPE="RelWithDebInfo" -DUSE_SYSTEM_TINYXML=TRUE
export CODE_COVERAGE=1
if [ "${CC}" = "clang" ]; then export CODE_COVERAGE=0; fi
${ANALYZE}cmake .. -DBUILD_WITH_CODE_COVERAGE=${CODE_COVERAGE} -DBUILD_UNITTESTS=1 -DCMAKE_INSTALL_PREFIX=/usr -DBINDIR=/usr/games -DCMAKE_BUILD_TYPE="RelWithDebInfo" -DUSE_SYSTEM_TINYXML=TRUE

View file

@ -20,7 +20,7 @@ message(STATUS "Configuring OpenMW...")
set(OPENMW_VERSION_MAJOR 0)
set(OPENMW_VERSION_MINOR 35)
set(OPENMW_VERSION_RELEASE 0)
set(OPENMW_VERSION_RELEASE 1)
set(OPENMW_VERSION_COMMITHASH "")
set(OPENMW_VERSION_TAGHASH "")
@ -97,43 +97,6 @@ endif()
# We probably support older versions than this.
cmake_minimum_required(VERSION 2.6)
# source directory: libs
set(LIBS_DIR ${CMAKE_SOURCE_DIR}/libs)
set(OENGINE_OGRE
${LIBS_DIR}/openengine/ogre/renderer.cpp
${LIBS_DIR}/openengine/ogre/lights.cpp
${LIBS_DIR}/openengine/ogre/selectionbuffer.cpp
${LIBS_DIR}/openengine/ogre/imagerotate.cpp
)
set(OENGINE_GUI
${LIBS_DIR}/openengine/gui/loglistener.cpp
${LIBS_DIR}/openengine/gui/manager.cpp
${LIBS_DIR}/openengine/gui/layout.cpp
)
set(OENGINE_BULLET
${LIBS_DIR}/openengine/bullet/BtOgre.cpp
${LIBS_DIR}/openengine/bullet/BtOgreExtras.h
${LIBS_DIR}/openengine/bullet/BtOgreGP.h
${LIBS_DIR}/openengine/bullet/BtOgrePG.h
${LIBS_DIR}/openengine/bullet/physic.cpp
${LIBS_DIR}/openengine/bullet/physic.hpp
${LIBS_DIR}/openengine/bullet/BulletShapeLoader.cpp
${LIBS_DIR}/openengine/bullet/BulletShapeLoader.h
${LIBS_DIR}/openengine/bullet/trace.cpp
${LIBS_DIR}/openengine/bullet/trace.h
)
set(OENGINE_ALL ${OENGINE_OGRE} ${OENGINE_GUI} ${OENGINE_BULLET})
source_group(libs\\openengine FILES ${OENGINE_ALL})
set(OPENMW_LIBS ${OENGINE_ALL})
set(OPENMW_LIBS_HEADER)
# Sound setup
set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE SWRESAMPLE AVRESAMPLE)
unset(FFMPEG_LIBRARIES CACHE)
@ -266,7 +229,8 @@ endif ()
endif(WIN32)
endif(OGRE_STATIC)
include_directories("."
include_directories("." ${LIBS_DIR}
SYSTEM
${OGRE_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Ogre ${OGRE_INCLUDE_DIR}/OGRE ${OGRE_INCLUDE_DIRS} ${OGRE_PLUGIN_INCLUDE_DIRS}
${OGRE_INCLUDE_DIR}/Overlay ${OGRE_Overlay_INCLUDE_DIR}
${SDL2_INCLUDE_DIR}
@ -275,7 +239,7 @@ include_directories("."
${MYGUI_INCLUDE_DIRS}
${MYGUI_PLATFORM_INCLUDE_DIRS}
${OPENAL_INCLUDE_DIR}
${LIBS_DIR}
${BULLET_INCLUDE_DIRS}
)
link_directories(${SDL2_LIBRARY_DIRS} ${Boost_LIBRARY_DIRS} ${OGRE_LIB_DIR} ${MYGUI_LIB_DIR})
@ -375,6 +339,9 @@ configure_file(${OpenMW_SOURCE_DIR}/files/opencs.ini
configure_file(${OpenMW_SOURCE_DIR}/files/opencs/defaultfilters
"${OpenMW_BINARY_DIR}/resources/defaultfilters" COPYONLY)
configure_file(${OpenMW_SOURCE_DIR}/files/gamecontrollerdb.txt
"${OpenMW_BINARY_DIR}/gamecontrollerdb.txt")
if (NOT WIN32 AND NOT APPLE)
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.desktop
"${OpenMW_BINARY_DIR}/openmw.desktop")
@ -382,22 +349,30 @@ if (NOT WIN32 AND NOT APPLE)
"${OpenMW_BINARY_DIR}/openmw-cs.desktop")
endif()
# Compiler settings
if (CMAKE_COMPILER_IS_GNUCC)
SET(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unused-parameter -Wno-reorder -std=c++98 -pedantic -Wno-long-long ${CMAKE_CXX_FLAGS}")
# CXX Compiler settings
if (CMAKE_CXX_COMPILER_ID STREQUAL GNU OR CMAKE_CXX_COMPILER_ID STREQUAL Clang)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unused-parameter -Wno-reorder -std=c++98 -pedantic -Wno-long-long")
if (CMAKE_CXX_COMPILER_ID STREQUAL Clang AND NOT APPLE)
execute_process(COMMAND ${CMAKE_C_COMPILER} --version OUTPUT_VARIABLE CLANG_VERSION)
string(REGEX REPLACE ".*version ([0-9\\.]*).*" "\\1" CLANG_VERSION ${CLANG_VERSION})
if ("${CLANG_VERSION}" VERSION_GREATER 3.6 OR "${CLANG_VERSION}" VERSION_EQUAL 3.6)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-potentially-evaluated-expression")
endif ("${CLANG_VERSION}" VERSION_GREATER 3.6 OR "${CLANG_VERSION}" VERSION_EQUAL 3.6)
endif(CMAKE_CXX_COMPILER_ID STREQUAL Clang AND NOT APPLE)
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
OUTPUT_VARIABLE GCC_VERSION)
if ("${GCC_VERSION}" VERSION_GREATER 4.6 OR "${GCC_VERSION}" VERSION_EQUAL 4.6)
SET(CMAKE_CXX_FLAGS "-Wno-unused-but-set-parameter ${CMAKE_CXX_FLAGS}")
endif("${GCC_VERSION}" VERSION_GREATER 4.6 OR "${GCC_VERSION}" VERSION_EQUAL 4.6)
if (CMAKE_CXX_COMPILER_ID STREQUAL GNU AND "${GCC_VERSION}" VERSION_GREATER 4.6 OR "${GCC_VERSION}" VERSION_EQUAL 4.6)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-but-set-parameter")
endif(CMAKE_CXX_COMPILER_ID STREQUAL GNU AND "${GCC_VERSION}" VERSION_GREATER 4.6 OR "${GCC_VERSION}" VERSION_EQUAL 4.6)
elseif (MSVC)
# Enable link-time code generation globally for all linking
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG")
set(CMAKE_STATIC_LINKER_FLAGS_RELEASE "${CMAKE_STATIC_LINKER_FLAGS_RELEASE} /LTCG")
endif (CMAKE_COMPILER_IS_GNUCC)
endif (CMAKE_CXX_COMPILER_ID STREQUAL GNU OR CMAKE_CXX_COMPILER_ID STREQUAL Clang)
IF(NOT WIN32 AND NOT APPLE)
# Linux building
@ -462,6 +437,8 @@ IF(NOT WIN32 AND NOT APPLE)
INSTALL(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")
INSTALL(FILES "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "${SYSCONFDIR}" RENAME "openmw.cfg" COMPONENT "openmw")
INSTALL(FILES "${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")
IF(BUILD_OPENCS)
INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION "${SYSCONFDIR}" COMPONENT "opencs")
ENDIF(BUILD_OPENCS)
@ -482,6 +459,7 @@ if(WIN32)
"${OpenMW_SOURCE_DIR}/Docs/license/DejaVu Font License.txt"
"${OpenMW_BINARY_DIR}/settings-default.cfg"
"${OpenMW_BINARY_DIR}/transparency-overrides.cfg"
"${OpenMW_BINARY_DIR}/gamecontrollerdb.txt"
"${OpenMW_BINARY_DIR}/Release/openmw.exe"
DESTINATION ".")
@ -566,6 +544,10 @@ if(WIN32)
include(CPack)
endif(WIN32)
# Libs
include_directories(libs)
add_subdirectory(libs/openengine)
# Extern
add_subdirectory (extern/shiny)
add_subdirectory (extern/ogre-ffmpeg-videoplayer)
@ -699,61 +681,23 @@ if (WIN32)
set(WARNINGS "${WARNINGS} /wd${d}")
endforeach(d)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNINGS} ${MT_BUILD}")
# boost::wave has a few issues with signed / unsigned conversions, so we suppress those here
set(SHINY_WARNINGS "${WARNINGS} /wd4245")
set_target_properties(shiny PROPERTIES COMPILE_FLAGS "${SHINY_WARNINGS} ${MT_BUILD}")
set_target_properties(shiny.OgrePlatform PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
set_target_properties(sdl4ogre PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
# oics uses tinyxml, which has an initialized but unused variable
set(OICS_WARNINGS "${WARNINGS} /wd4189")
set_target_properties(oics PROPERTIES COMPILE_FLAGS "${OICS_WARNINGS} ${MT_BUILD}")
set_target_properties(components PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
set_target_properties(ogre-ffmpeg-videoplayer PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
if (BUILD_MYGUI_PLUGIN)
set_target_properties(Plugin_MyGUI_OpenMW_Resources PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
endif (BUILD_MYGUI_PLUGIN)
if (BUILD_LAUNCHER)
set_target_properties(openmw-launcher PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
endif (BUILD_LAUNCHER)
set_target_properties(openmw PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
if (BUILD_BSATOOL)
set_target_properties(bsatool PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
endif (BUILD_BSATOOL)
if (BUILD_ESMTOOL)
set_target_properties(esmtool PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
endif (BUILD_ESMTOOL)
if (BUILD_WIZARD)
set_target_properties(openmw-wizard PROPERTIES COMPILE_FLAGS ${WARNINGS})
endif (BUILD_WIZARD)
if (BUILD_OPENCS)
# QT triggers an informational warning that the object layout may differ when compiled with /vd2
set(OPENCS_WARNINGS "${WARNINGS} ${MT_BUILD} /wd4435")
set_target_properties(openmw-cs PROPERTIES COMPILE_FLAGS ${OPENCS_WARNINGS})
endif (BUILD_OPENCS)
if (BUILD_ESSIMPORTER)
set_target_properties(openmw-essimporter PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
endif (BUILD_ESSIMPORTER)
if (BUILD_MWINIIMPORTER)
set_target_properties(openmw-iniimporter PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
endif (BUILD_MWINIIMPORTER)
endif(MSVC)
# Same for MinGW
if (MINGW)
if (USE_DEBUG_CONSOLE)
set_target_properties(openmw PROPERTIES LINK_FLAGS_DEBUG "-Wl,-subsystem,console")
set_target_properties(openmw PROPERTIES LINK_FLAGS_RELWITHDEBINFO "-Wl,-subsystem,console")
set_target_properties(openmw PROPERTIES COMPILE_DEFINITIONS_DEBUG "_CONSOLE")
else(USE_DEBUG_CONSOLE)
set_target_properties(openmw PROPERTIES LINK_FLAGS_DEBUG "-Wl,-subsystem,windows")
set_target_properties(openmw PROPERTIES LINK_FLAGS_RELWITHDEBINFO "-Wl,-subsystem,windows")
endif(USE_DEBUG_CONSOLE)
set_target_properties(openmw PROPERTIES LINK_FLAGS_RELEASE "-Wl,-subsystem,console")
set_target_properties(openmw PROPERTIES LINK_FLAGS_MINSIZEREL "-Wl,-subsystem,console")
set_target_properties(openmw PROPERTIES COMPILE_DEFINITIONS_RELEASE "_CONSOLE")
endif(MINGW)
# TODO: At some point release builds should not use the console but rather write to a log file
#set_target_properties(openmw PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS")
#set_target_properties(openmw PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS")
@ -767,6 +711,7 @@ if (APPLE)
install(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
install(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" RENAME "openmw.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
install(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
install(FILES "${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
install(FILES "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
install(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)

View file

@ -6,7 +6,7 @@ OpenMW
OpenMW is an attempt at recreating the engine for the popular role-playing game
Morrowind by Bethesda Softworks. You need to own and install the original game for OpenMW to work.
* Version: 0.35.0
* Version: 0.35.1
* License: GPL (see docs/license/GPL3.txt for more information)
* Website: http://www.openmw.org
* IRC: #openmw on irc.freenode.net
@ -23,7 +23,7 @@ Getting Started
* [Testing the game](https://wiki.openmw.org/index.php?title=Testing)
* [How to contribute](https://wiki.openmw.org/index.php?title=Contribution_Wanted)
* [Report a bug](http://bugs.openmw.org/projects/openmw) - read the [guidelines](https://wiki.openmw.org/index.php?title=Bug_Reporting_Guidelines) before submitting your first bug!
* [Known issues] (http://bugs.openmw.org/projects/openmw/issues?utf8=%E2%9C%93&set_filter=1&f%5B%5D=status_id&op%5Bstatus_id%5D=%3D&v%5Bstatus_id%5D%5B%5D=7&f%5B%5D=tracker_id&op%5Btracker_id%5D=%3D&v%5Btracker_id%5D%5B%5D=1&f%5B%5D=&c%5B%5D=project&c%5B%5D=tracker&c%5B%5D=status&c%5B%5D=priority&c%5B%5D=subject&c%5B%5D=assigned_to&c%5B%5D=updated_on&group_by=tracker)
* [Known issues](http://bugs.openmw.org/projects/openmw/issues?utf8=%E2%9C%93&set_filter=1&f%5B%5D=status_id&op%5Bstatus_id%5D=%3D&v%5Bstatus_id%5D%5B%5D=7&f%5B%5D=tracker_id&op%5Btracker_id%5D=%3D&v%5Btracker_id%5D%5B%5D=1&f%5B%5D=&c%5B%5D=project&c%5B%5D=tracker&c%5B%5D=status&c%5B%5D=priority&c%5B%5D=subject&c%5B%5D=assigned_to&c%5B%5D=updated_on&group_by=tracker)
The data path
-------------
@ -68,9 +68,9 @@ Command line options
of the blacklist is enabled)
--script-blacklist-use [=arg(=1)] (=1)
enable script blacklisting
--load-savegame arg load a save game file on game startup
(specify an absolute filename or a
filename relative to the current
--load-savegame arg load a save game file on game startup
(specify an absolute filename or a
filename relative to the current
working directory)
--skip-menu [=arg(=1)] (=0) skip main menu on game startup
--new-game [=arg(=1)] (=0) run new game sequence (ignored if

View file

@ -460,7 +460,7 @@ int clone(Arguments& info)
for (Stats::iterator it = stats.begin(); it != stats.end(); ++it)
{
name.val = it->first;
float amount = it->second;
int amount = it->second;
std::cout << std::setw(digitCount) << amount << " " << name.toString() << " ";
if (++i % 3 == 0)

View file

@ -6,6 +6,9 @@
#include <boost/format.hpp>
namespace
{
void printAIPackage(ESM::AIPackage p)
{
std::cout << " AI Type: " << aiTypeLabel(p.mType)
@ -16,7 +19,7 @@ void printAIPackage(ESM::AIPackage p)
std::cout << " Duration: " << p.mWander.mDuration << std::endl;
std::cout << " Time of Day: " << (int)p.mWander.mTimeOfDay << std::endl;
if (p.mWander.mShouldRepeat != 1)
std::cout << " Should repeat: " << (bool)p.mWander.mShouldRepeat << std::endl;
std::cout << " Should repeat: " << (bool)(p.mWander.mShouldRepeat != 0) << std::endl;
std::cout << " Idle: ";
for (int i = 0; i != 8; i++)
@ -149,6 +152,26 @@ void printEffectList(ESM::EffectList effects)
}
}
void printTransport(const std::vector<ESM::Transport::Dest>& transport)
{
std::vector<ESM::Transport::Dest>::const_iterator dit;
for (dit = transport.begin(); dit != transport.end(); ++dit)
{
std::cout << " Destination Position: "
<< boost::format("%12.3f") % dit->mPos.pos[0] << ","
<< boost::format("%12.3f") % dit->mPos.pos[1] << ","
<< boost::format("%12.3f") % dit->mPos.pos[2] << ")" << std::endl;
std::cout << " Destination Rotation: "
<< boost::format("%9.6f") % dit->mPos.rot[0] << ","
<< boost::format("%9.6f") % dit->mPos.rot[1] << ","
<< boost::format("%9.6f") % dit->mPos.rot[2] << ")" << std::endl;
if (dit->mCellName != "")
std::cout << " Destination Cell: " << dit->mCellName << std::endl;
}
}
}
namespace EsmTool {
RecordBase *
@ -631,6 +654,8 @@ void Record<ESM::Creature>::print()
for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); ++sit)
std::cout << " Spell: " << *sit << std::endl;
printTransport(mData.getTransport());
std::cout << " Artifical Intelligence: " << mData.mHasAI << std::endl;
std::cout << " AI Hello:" << (int)mData.mAiData.mHello << std::endl;
std::cout << " AI Fight:" << (int)mData.mAiData.mFight << std::endl;
@ -1042,20 +1067,7 @@ void Record<ESM::NPC>::print()
for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); ++sit)
std::cout << " Spell: " << *sit << std::endl;
std::vector<ESM::NPC::Dest>::iterator dit;
for (dit = mData.mTransport.begin(); dit != mData.mTransport.end(); ++dit)
{
std::cout << " Destination Position: "
<< boost::format("%12.3f") % dit->mPos.pos[0] << ","
<< boost::format("%12.3f") % dit->mPos.pos[1] << ","
<< boost::format("%12.3f") % dit->mPos.pos[2] << ")" << std::endl;
std::cout << " Destination Rotation: "
<< boost::format("%9.6f") % dit->mPos.rot[0] << ","
<< boost::format("%9.6f") % dit->mPos.rot[1] << ","
<< boost::format("%9.6f") % dit->mPos.rot[2] << ")" << std::endl;
if (dit->mCellName != "")
std::cout << " Destination Cell: " << dit->mCellName << std::endl;
}
printTransport(mData.getTransport());
std::cout << " Artifical Intelligence: " << mData.mHasAI << std::endl;
std::cout << " AI Hello:" << (int)mData.mAiData.mHello << std::endl;
@ -1253,7 +1265,7 @@ void Record<ESM::Spell>::print()
template<>
void Record<ESM::StartScript>::print()
{
std::cout << "Start Script: " << mData.mScript << std::endl;
std::cout << "Start Script: " << mData.mId << std::endl;
std::cout << "Start Data: " << mData.mData << std::endl;
}

View file

@ -23,18 +23,18 @@ namespace ESSImport
}
for (int i=0; i<8; ++i)
{
cStats.mAttributes[i].mBase = acdt.mAttributes[i][1];
cStats.mAttributes[i].mMod = acdt.mAttributes[i][0];
cStats.mAttributes[i].mCurrent = acdt.mAttributes[i][0];
cStats.mAttributes[i].mBase = static_cast<int>(acdt.mAttributes[i][1]);
cStats.mAttributes[i].mMod = static_cast<int>(acdt.mAttributes[i][0]);
cStats.mAttributes[i].mCurrent = static_cast<int>(acdt.mAttributes[i][0]);
}
cStats.mGoldPool = acdt.mGoldPool;
cStats.mTalkedTo = acdt.mFlags & TalkedToPlayer;
cStats.mAttacked = acdt.mFlags & Attacked;
cStats.mTalkedTo = (acdt.mFlags & TalkedToPlayer) != 0;
cStats.mAttacked = (acdt.mFlags & Attacked) != 0;
}
void convertACSC (const ACSC& acsc, ESM::CreatureStats& cStats)
{
cStats.mDead = acsc.mFlags & Dead;
cStats.mDead = (acsc.mFlags & Dead) != 0;
}
void convertNpcData (const ActorData& actorData, ESM::NpcStats& npcStats)

View file

@ -553,7 +553,7 @@ public:
ESM::WeatherState weather;
weather.mCurrentWeather = toString(mGame.mGMDT.mCurrentWeather);
weather.mNextWeather = toString(mGame.mGMDT.mNextWeather);
weather.mRemainingTransitionTime = mGame.mGMDT.mWeatherTransition/100.f*(0.015*24*3600);
weather.mRemainingTransitionTime = mGame.mGMDT.mWeatherTransition/100.f*(0.015f*24*3600);
weather.mHour = mContext->mHour;
weather.mWindSpeed = 0.f;
weather.mTimePassed = 0.0;

View file

@ -43,7 +43,7 @@ namespace ESSImport
{
unsigned int deleted;
esm.getHT(deleted);
mDeleted = (deleted >> 24) & 0x2; // the other 3 bytes seem to be uninitialized garbage
mDeleted = ((deleted >> 24) & 0x2) != 0; // the other 3 bytes seem to be uninitialized garbage
}
if (esm.isNextSub("MVRF"))

View file

@ -903,4 +903,4 @@ std::time_t MwIniImporter::lastWriteTime(const boost::filesystem::path& filename
std::cout << "content file: " << filename << " not found" << std::endl;
}
return writeTime;
}
}

View file

@ -110,7 +110,7 @@ int wmain(int argc, wchar_t *wargv[]) {
std::cerr << "cfg file does not exist" << std::endl;
MwIniImporter importer;
importer.setVerbose(vm.count("verbose"));
importer.setVerbose(vm.count("verbose") != 0);
// Font encoding settings
std::string encoding(vm["encoding"].as<std::string>());

View file

@ -5,7 +5,7 @@ set (OPENCS_SRC main.cpp
opencs_units (. editor)
opencs_units (model/doc
document operation saving documentmanager loader runner
document operation saving documentmanager loader runner operationholder
)
opencs_units_noqt (model/doc
@ -40,6 +40,7 @@ opencs_units (model/tools
opencs_units_noqt (model/tools
mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck
birthsigncheck spellcheck referencecheck referenceablecheck scriptcheck bodypartcheck
startscriptcheck search searchoperation searchstage
)
@ -91,7 +92,7 @@ opencs_hdrs_noqt (view/render
opencs_units (view/tools
reportsubview reporttable
reportsubview reporttable searchsubview searchbox
)
opencs_units_noqt (view/tools
@ -165,7 +166,8 @@ 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})
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${BULLET_INCLUDE_DIRS})
# for compiled .ui files
include_directories(${CMAKE_CURRENT_BINARY_DIR})
if(APPLE)
set (OPENCS_MAC_ICON ${CMAKE_SOURCE_DIR}/files/mac/openmw-cs.icns)
@ -175,7 +177,6 @@ endif(APPLE)
add_executable(openmw-cs
MACOSX_BUNDLE
${OENGINE_BULLET}
${OPENCS_SRC}
${OPENCS_UI_HDR}
${OPENCS_MOC_SRC}
@ -199,6 +200,7 @@ if(APPLE)
endif(APPLE)
target_link_libraries(openmw-cs
${OENGINE_LIBRARY}
${OGRE_LIBRARIES}
${OGRE_Overlay_LIBRARIES}
${OGRE_STATIC_PLUGINS}

View file

@ -28,4 +28,4 @@ void CSMDoc::Blacklist::add (CSMWorld::UniversalId::Type type,
std::transform (ids.begin(), ids.end(), list.begin()+size, Misc::StringUtils::lowerCase);
std::sort (list.begin(), list.end());
}
}

View file

@ -2254,7 +2254,8 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
mTools (*this), mResDir(resDir),
mProjectPath ((configuration.getUserDataPath() / "projects") /
(savePath.filename().string() + ".project")),
mSaving (*this, mProjectPath, encoding),
mSavingOperation (*this, mProjectPath, encoding),
mSaving (&mSavingOperation),
mRunner (mProjectPath), mPhysics(boost::shared_ptr<CSVWorld::PhysicsSystem>())
{
if (mContentFiles.empty())
@ -2373,6 +2374,17 @@ CSMWorld::UniversalId CSMDoc::Document::verify()
return id;
}
CSMWorld::UniversalId CSMDoc::Document::newSearch()
{
return mTools.newSearch();
}
void CSMDoc::Document::runSearch (const CSMWorld::UniversalId& searchId, const CSMTools::Search& search)
{
return mTools.runSearch (searchId, search);
}
void CSMDoc::Document::abortOperation (int type)
{
if (type==State_Saving)

View file

@ -20,6 +20,7 @@
#include "saving.hpp"
#include "blacklist.hpp"
#include "runner.hpp"
#include "operationholder.hpp"
class QAbstractItemModel;
@ -32,7 +33,7 @@ namespace ESM
namespace Files
{
class ConfigurationManager;
struct ConfigurationManager;
}
namespace CSMWorld
@ -59,7 +60,8 @@ namespace CSMDoc
CSMWorld::Data mData;
CSMTools::Tools mTools;
boost::filesystem::path mProjectPath;
Saving mSaving;
Saving mSavingOperation;
OperationHolder mSaving;
boost::filesystem::path mResDir;
Blacklist mBlacklist;
Runner mRunner;
@ -118,6 +120,10 @@ namespace CSMDoc
CSMWorld::UniversalId verify();
CSMWorld::UniversalId newSearch();
void runSearch (const CSMWorld::UniversalId& searchId, const CSMTools::Search& search);
void abortOperation (int type);
const CSMWorld::Data& getData() const;

View file

@ -107,4 +107,4 @@ void CSMDoc::DocumentManager::documentNotLoaded (Document *document, const std::
if (error.empty()) // do not remove the document yet, if we have an error
removeDocument (document);
}
}

View file

@ -17,7 +17,7 @@
namespace Files
{
class ConfigurationManager;
struct ConfigurationManager;
}
namespace CSMDoc
@ -50,7 +50,7 @@ namespace CSMDoc
///< \param new_ Do not load the last content file in \a files and instead create in an
/// appropriate way.
void setResourceDir (const boost::filesystem::path& parResDir);
void setResourceDir (const boost::filesystem::path& parResDir);
void setEncoding (ToUTF8::FromType encoding);
@ -61,7 +61,7 @@ namespace CSMDoc
private:
boost::filesystem::path mResDir;
boost::filesystem::path mResDir;
private slots:
@ -99,4 +99,4 @@ namespace CSMDoc
};
}
#endif
#endif

View file

@ -25,4 +25,4 @@ CSMDoc::Messages::Iterator CSMDoc::Messages::begin() const
CSMDoc::Messages::Iterator CSMDoc::Messages::end() const
{
return mMessages.end();
}
}

View file

@ -29,9 +29,9 @@ void CSMDoc::Operation::prepareStages()
CSMDoc::Operation::Operation (int type, bool ordered, bool finalAlways)
: mType (type), mStages(std::vector<std::pair<Stage *, int> >()), mCurrentStage(mStages.begin()),
mCurrentStep(0), mCurrentStepTotal(0), mTotalSteps(0), mOrdered (ordered),
mFinalAlways (finalAlways), mError(false)
mFinalAlways (finalAlways), mError(false), mConnected (false)
{
connect (this, SIGNAL (finished()), this, SLOT (operationDone()));
mTimer = new QTimer (this);
}
CSMDoc::Operation::~Operation()
@ -42,15 +42,17 @@ CSMDoc::Operation::~Operation()
void CSMDoc::Operation::run()
{
mTimer->stop();
if (!mConnected)
{
connect (mTimer, SIGNAL (timeout()), this, SLOT (executeStage()));
mConnected = true;
}
prepareStages();
QTimer timer;
timer.connect (&timer, SIGNAL (timeout()), this, SLOT (executeStage()));
timer.start (0);
exec();
mTimer->start (0);
}
void CSMDoc::Operation::appendStage (Stage *stage)
@ -65,7 +67,7 @@ bool CSMDoc::Operation::hasError() const
void CSMDoc::Operation::abort()
{
if (!isRunning())
if (!mTimer->isActive())
return;
mError = true;
@ -116,10 +118,11 @@ void CSMDoc::Operation::executeStage()
emit reportMessage (iter->mId, iter->mMessage, iter->mHint, mType);
if (mCurrentStage==mStages.end())
exit();
operationDone();
}
void CSMDoc::Operation::operationDone()
{
mTimer->stop();
emit done (mType, mError);
}

View file

@ -3,7 +3,8 @@
#include <vector>
#include <QThread>
#include <QObject>
#include <QTimer>
namespace CSMWorld
{
@ -14,7 +15,7 @@ namespace CSMDoc
{
class Stage;
class Operation : public QThread
class Operation : public QObject
{
Q_OBJECT
@ -27,6 +28,8 @@ namespace CSMDoc
int mOrdered;
bool mFinalAlways;
bool mError;
bool mConnected;
QTimer *mTimer;
void prepareStages();
@ -38,8 +41,6 @@ namespace CSMDoc
virtual ~Operation();
virtual void run();
void appendStage (Stage *stage);
///< The ownership of \a stage is transferred to *this.
///
@ -60,6 +61,8 @@ namespace CSMDoc
void abort();
void run();
private slots:
void executeStage();
@ -68,4 +71,4 @@ namespace CSMDoc
};
}
#endif
#endif

View file

@ -0,0 +1,65 @@
#include "operationholder.hpp"
#include "operation.hpp"
CSMDoc::OperationHolder::OperationHolder (Operation *operation) : mRunning (false)
{
if (operation)
setOperation (operation);
}
void CSMDoc::OperationHolder::setOperation (Operation *operation)
{
mOperation = operation;
mOperation->moveToThread (&mThread);
connect (
mOperation, SIGNAL (progress (int, int, int)),
this, SIGNAL (progress (int, int, int)));
connect (
mOperation, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)),
this, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)));
connect (
mOperation, SIGNAL (done (int, bool)),
this, SLOT (doneSlot (int, bool)));
connect (this, SIGNAL (abortSignal()), mOperation, SLOT (abort()));
connect (&mThread, SIGNAL (started()), mOperation, SLOT (run()));
}
bool CSMDoc::OperationHolder::isRunning() const
{
return mRunning;
}
void CSMDoc::OperationHolder::start()
{
mRunning = true;
mThread.start();
}
void CSMDoc::OperationHolder::abort()
{
mRunning = false;
emit abortSignal();
}
void CSMDoc::OperationHolder::abortAndWait()
{
if (mRunning)
{
mThread.quit();
mThread.wait();
}
}
void CSMDoc::OperationHolder::doneSlot (int type, bool failed)
{
mRunning = false;
mThread.quit();
emit done (type, failed);
}

View file

@ -0,0 +1,56 @@
#ifndef CSM_DOC_OPERATIONHOLDER_H
#define CSM_DOC_OPERATIONHOLDER_H
#include <QObject>
#include <QThread>
namespace CSMWorld
{
class UniversalId;
}
namespace CSMDoc
{
class Operation;
class OperationHolder : public QObject
{
Q_OBJECT
QThread mThread;
Operation *mOperation;
bool mRunning;
public:
OperationHolder (Operation *operation = 0);
void setOperation (Operation *operation);
bool isRunning() const;
void start();
void abort();
// Abort and wait until thread has finished.
void abortAndWait();
private slots:
void doneSlot (int type, bool failed);
signals:
void progress (int current, int max, int type);
void reportMessage (const CSMWorld::UniversalId& id, const std::string& message,
const std::string& hint, int type);
void done (int type, bool failed);
void abortSignal();
};
}
#endif

View file

@ -6,7 +6,7 @@
#include <QTemporaryFile>
#include <QTextStream>
#include "operation.hpp"
#include "operationholder.hpp"
CSMDoc::Runner::Runner (const boost::filesystem::path& projectPath)
: mRunning (false), mStartup (0), mProjectPath (projectPath)
@ -145,7 +145,7 @@ void CSMDoc::Runner::readyReadStandardOutput()
}
CSMDoc::SaveWatcher::SaveWatcher (Runner *runner, Operation *operation)
CSMDoc::SaveWatcher::SaveWatcher (Runner *runner, OperationHolder *operation)
: QObject (runner), mRunner (runner)
{
connect (operation, SIGNAL (done (int, bool)), this, SLOT (saveDone (int, bool)));

View file

@ -16,6 +16,8 @@ class QTemporaryFile;
namespace CSMDoc
{
class OperationHolder;
class Runner : public QObject
{
Q_OBJECT
@ -74,7 +76,7 @@ namespace CSMDoc
public:
/// *this attaches itself to runner
SaveWatcher (Runner *runner, Operation *operation);
SaveWatcher (Runner *runner, OperationHolder *operation);
private slots:

View file

@ -78,6 +78,9 @@ CSMDoc::Saving::Saving (Document& document, const boost::filesystem::path& proje
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::MagicEffect> >
(mDocument.getData().getMagicEffects(), mState));
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::StartScript> >
(mDocument.getData().getStartScripts(), mState));
appendStage (new WriteDialogueCollectionStage (mDocument, mState, false));
appendStage (new WriteDialogueCollectionStage (mDocument, mState, true));
@ -90,8 +93,12 @@ CSMDoc::Saving::Saving (Document& document, const boost::filesystem::path& proje
appendStage (new WritePathgridCollectionStage (mDocument, mState));
appendStage (new WriteLandCollectionStage (mDocument, mState));
appendStage (new WriteLandTextureCollectionStage (mDocument, mState));
// close file and clean up
appendStage (new CloseSaveStage (mState));
appendStage (new FinalSavingStage (mDocument, mState));
}
}

View file

@ -90,7 +90,7 @@ void CSMDoc::WriteHeaderStage::perform (int stage, Messages& messages)
CSMDoc::WriteDialogueCollectionStage::WriteDialogueCollectionStage (Document& document,
SavingState& state, bool journal)
: mDocument (document), mState (state),
: mState (state),
mTopics (journal ? document.getData().getJournals() : document.getData().getTopics()),
mInfos (journal ? document.getData().getJournalInfos() : document.getData().getTopicInfos())
{}
@ -353,6 +353,74 @@ void CSMDoc::WritePathgridCollectionStage::perform (int stage, Messages& message
}
CSMDoc::WriteLandCollectionStage::WriteLandCollectionStage (Document& document,
SavingState& state)
: mDocument (document), mState (state)
{}
int CSMDoc::WriteLandCollectionStage::setup()
{
return mDocument.getData().getLand().getSize();
}
void CSMDoc::WriteLandCollectionStage::perform (int stage, Messages& messages)
{
const CSMWorld::Record<CSMWorld::Land>& land =
mDocument.getData().getLand().getRecord (stage);
if (land.mState==CSMWorld::RecordBase::State_Modified ||
land.mState==CSMWorld::RecordBase::State_ModifiedOnly)
{
CSMWorld::Land record = land.get();
mState.getWriter().startRecord (record.mLand->sRecordId);
record.mLand->save (mState.getWriter());
if(record.mLand->mLandData)
record.mLand->mLandData->save (mState.getWriter());
mState.getWriter().endRecord (record.mLand->sRecordId);
}
else if (land.mState==CSMWorld::RecordBase::State_Deleted)
{
/// \todo write record with delete flag
}
}
CSMDoc::WriteLandTextureCollectionStage::WriteLandTextureCollectionStage (Document& document,
SavingState& state)
: mDocument (document), mState (state)
{}
int CSMDoc::WriteLandTextureCollectionStage::setup()
{
return mDocument.getData().getLandTextures().getSize();
}
void CSMDoc::WriteLandTextureCollectionStage::perform (int stage, Messages& messages)
{
const CSMWorld::Record<CSMWorld::LandTexture>& landTexture =
mDocument.getData().getLandTextures().getRecord (stage);
if (landTexture.mState==CSMWorld::RecordBase::State_Modified ||
landTexture.mState==CSMWorld::RecordBase::State_ModifiedOnly)
{
CSMWorld::LandTexture record = landTexture.get();
mState.getWriter().startRecord (record.sRecordId);
record.save (mState.getWriter());
mState.getWriter().endRecord (record.sRecordId);
}
else if (landTexture.mState==CSMWorld::RecordBase::State_Deleted)
{
/// \todo write record with delete flag
}
}
CSMDoc::CloseSaveStage::CloseSaveStage (SavingState& state)
: mState (state)
{}

View file

@ -7,6 +7,8 @@
#include "../world/idcollection.hpp"
#include "../world/scope.hpp"
#include <components/esm/defs.hpp>
#include "savingstate.hpp"
namespace ESM
@ -103,8 +105,15 @@ namespace CSMDoc
if (state==CSMWorld::RecordBase::State_Modified ||
state==CSMWorld::RecordBase::State_ModifiedOnly)
{
mState.getWriter().startRecord (mCollection.getRecord (stage).mModified.sRecordId);
mState.getWriter().writeHNCString ("NAME", mCollection.getId (stage));
// FIXME: A quick Workaround to support records which should not write
// NAME, including SKIL, MGEF and SCPT. If there are many more
// idcollection records that doesn't use NAME then a more generic
// solution may be required.
uint32_t name = mCollection.getRecord (stage).mModified.sRecordId;
mState.getWriter().startRecord (name);
if(name != ESM::REC_SKIL && name != ESM::REC_MGEF && name != ESM::REC_SCPT)
mState.getWriter().writeHNCString ("NAME", mCollection.getId (stage));
mCollection.getRecord (stage).mModified.save (mState.getWriter());
mState.getWriter().endRecord (mCollection.getRecord (stage).mModified.sRecordId);
}
@ -117,7 +126,6 @@ namespace CSMDoc
class WriteDialogueCollectionStage : public Stage
{
Document& mDocument;
SavingState& mState;
const CSMWorld::IdCollection<ESM::Dialogue>& mTopics;
CSMWorld::InfoCollection& mInfos;
@ -200,6 +208,40 @@ namespace CSMDoc
///< Messages resulting from this stage will be appended to \a messages.
};
class WriteLandCollectionStage : public Stage
{
Document& mDocument;
SavingState& mState;
public:
WriteLandCollectionStage (Document& document, SavingState& state);
virtual int setup();
///< \return number of steps
virtual void perform (int stage, Messages& messages);
///< Messages resulting from this stage will be appended to \a messages.
};
class WriteLandTextureCollectionStage : public Stage
{
Document& mDocument;
SavingState& mState;
public:
WriteLandTextureCollectionStage (Document& document, SavingState& state);
virtual int setup();
///< \return number of steps
virtual void perform (int stage, Messages& messages);
///< Messages resulting from this stage will be appended to \a messages.
};
class CloseSaveStage : public Stage
{
SavingState& mState;

View file

@ -1,4 +1,4 @@
#include "stage.hpp"
CSMDoc::Stage::~Stage() {}
CSMDoc::Stage::~Stage() {}

View file

@ -13,7 +13,7 @@ namespace CSMDoc
State_Saving = 16,
State_Verifying = 32,
State_Compiling = 64, // not implemented yet
State_Searching = 128, // not implemented yet
State_Searching = 128,
State_Loading = 256 // pseudo-state; can not be encountered in a loaded document
};
}

View file

@ -12,4 +12,4 @@ bool CSMFilter::BooleanNode::test (const CSMWorld::IdTableBase& table, int row,
std::string CSMFilter::BooleanNode::toString (bool numericColumns) const
{
return mTrue ? "true" : "false";
}
}

View file

@ -26,4 +26,4 @@ namespace CSMFilter
};
}
#endif
#endif

View file

@ -3,4 +3,4 @@
CSMFilter::Node::Node() {}
CSMFilter::Node::~Node() {}
CSMFilter::Node::~Node() {}

View file

@ -7,4 +7,4 @@ bool CSMFilter::NotNode::test (const CSMWorld::IdTableBase& table, int row,
const std::map<int, int>& columns) const
{
return !getChild().test (table, row, columns);
}
}

View file

@ -82,4 +82,4 @@ std::string CSMFilter::TextNode::toString (bool numericColumns) const
stream << ", \"" << mText << "\")";
return stream.str();
}
}

View file

@ -23,4 +23,4 @@ std::vector<int> CSMFilter::UnaryNode::getReferencedColumns() const
std::string CSMFilter::UnaryNode::toString (bool numericColumns) const
{
return mName + " " + mChild->toString (numericColumns);
}
}

View file

@ -94,4 +94,4 @@ std::string CSMFilter::ValueNode::toString (bool numericColumns) const
stream << ")";
return stream.str();
}
}

View file

@ -208,6 +208,21 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
shiftCtrlDoubleClick->setToolTip ("Action on shift control double click in table:<p>" + toolTip);
}
declareSection ("search", "Search & Replace");
{
Setting *before = createSetting (Type_SpinBox, "char-before",
"Characters before search string");
before->setDefaultValue (10);
before->setRange (0, 1000);
before->setToolTip ("Maximum number of character to display in search result before the searched text");
Setting *after = createSetting (Type_SpinBox, "char-after",
"Characters after search string");
after->setDefaultValue (10);
after->setRange (0, 1000);
after->setToolTip ("Maximum number of character to display in search result after the searched text");
}
{
/******************************************************************
* There are three types of values:

View file

@ -41,4 +41,4 @@ void CSMTools::BirthsignCheckStage::perform (int stage, CSMDoc::Messages& messag
/// \todo test if the texture exists
/// \todo check data members that can't be edited in the table view
}
}

View file

@ -32,4 +32,4 @@ namespace CSMTools
};
}
#endif
#endif

View file

@ -65,4 +65,4 @@ void CSMTools::ClassCheckStage::perform (int stage, CSMDoc::Messages& messages)
messages.push_back (std::make_pair (id,
ESM::Skill::indexToId (iter->first) + " is listed more than once"));
}
}
}

View file

@ -20,4 +20,4 @@ void CSMTools::MandatoryIdStage::perform (int stage, CSMDoc::Messages& messages)
if (mIdCollection.searchId (mIds.at (stage))==-1 ||
mIdCollection.getRecord (mIds.at (stage)).isDeleted())
messages.add (mCollectionId, "Missing mandatory record: " + mIds.at (stage));
}
}

View file

@ -70,4 +70,4 @@ void CSMTools::RaceCheckStage::perform (int stage, CSMDoc::Messages& messages)
performFinal (messages);
else
performPerRecord (stage, messages);
}
}

View file

@ -48,10 +48,6 @@ void CSMTools::ReferenceCheckStage::perform(int stage, CSMDoc::Messages &message
}
}
// Check if referenced object is in valid cell
if (mCells.searchId(cellRef.mCell) == -1)
messages.push_back(std::make_pair(id, " is referencing object from non existing cell " + cellRef.mCell));
// If object have owner, check if that owner reference is valid
if (!cellRef.mOwner.empty() && mReferencables.searchId(cellRef.mOwner) == -1)
messages.push_back(std::make_pair(id, " has non existing owner " + cellRef.mOwner));
@ -70,9 +66,9 @@ void CSMTools::ReferenceCheckStage::perform(int stage, CSMDoc::Messages &message
// Check item's faction rank
if (hasFaction && cellRef.mFactionRank < -1)
messages.push_back(std::make_pair(id, " has faction set but has invalid faction rank " + cellRef.mFactionRank));
messages.push_back(std::make_pair(id, " has faction set but has invalid faction rank " + boost::lexical_cast<std::string>(cellRef.mFactionRank)));
else if (!hasFaction && cellRef.mFactionRank != -2)
messages.push_back(std::make_pair(id, " has invalid faction rank " + cellRef.mFactionRank));
messages.push_back(std::make_pair(id, " has invalid faction rank " + boost::lexical_cast<std::string>(cellRef.mFactionRank)));
// If door have destination cell, check if that reference is valid
if (!cellRef.mDestCell.empty())

View file

@ -26,4 +26,4 @@ namespace CSMTools
};
}
#endif // CSM_TOOLS_REFERENCECHECK_H
#endif // CSM_TOOLS_REFERENCECHECK_H

View file

@ -35,4 +35,4 @@ void CSMTools::RegionCheckStage::perform (int stage, CSMDoc::Messages& messages)
/// \todo test that the ID in mSleeplist exists
/// \todo check data members that can't be edited in the table view
}
}

View file

@ -2,6 +2,29 @@
#include "reportmodel.hpp"
#include <stdexcept>
#include <sstream>
#include "../world/columns.hpp"
CSMTools::ReportModel::Line::Line (const CSMWorld::UniversalId& id, const std::string& message,
const std::string& hint)
: mId (id), mMessage (message), mHint (hint)
{}
CSMTools::ReportModel::ReportModel (bool fieldColumn)
{
if (fieldColumn)
{
mColumnField = 3;
mColumnDescription = 4;
}
else
{
mColumnDescription = 3;
mColumnField = -1;
}
}
int CSMTools::ReportModel::rowCount (const QModelIndex & parent) const
{
@ -16,7 +39,7 @@ int CSMTools::ReportModel::columnCount (const QModelIndex & parent) const
if (parent.isValid())
return 0;
return 3;
return mColumnDescription+1;
}
QVariant CSMTools::ReportModel::data (const QModelIndex & index, int role) const
@ -24,13 +47,49 @@ QVariant CSMTools::ReportModel::data (const QModelIndex & index, int role) const
if (role!=Qt::DisplayRole)
return QVariant();
if (index.column()==0)
return static_cast<int> (mRows.at (index.row()).first.getType());
switch (index.column())
{
case Column_Type:
if (index.column()==1)
return QString::fromUtf8 (mRows.at (index.row()).second.first.c_str());
return static_cast<int> (mRows.at (index.row()).mId.getType());
case Column_Id:
{
CSMWorld::UniversalId id = mRows.at (index.row()).mId;
return QString::fromUtf8 (mRows.at (index.row()).second.second.c_str());
if (id.getArgumentType()==CSMWorld::UniversalId::ArgumentType_Id)
return QString::fromUtf8 (id.getId().c_str());
return QString ("-");
}
case Column_Hint:
return QString::fromUtf8 (mRows.at (index.row()).mHint.c_str());
}
if (index.column()==mColumnDescription)
return QString::fromUtf8 (mRows.at (index.row()).mMessage.c_str());
if (index.column()==mColumnField)
{
std::string field;
std::istringstream stream (mRows.at (index.row()).mHint);
char type, ignore;
int fieldIndex;
if ((stream >> type >> ignore >> fieldIndex) && (type=='r' || type=='R'))
{
field = CSMWorld::Columns::getName (
static_cast<CSMWorld::Columns::ColumnId> (fieldIndex));
}
return QString::fromUtf8 (field.c_str());
}
return QVariant();
}
QVariant CSMTools::ReportModel::headerData (int section, Qt::Orientation orientation, int role) const
@ -41,13 +100,19 @@ QVariant CSMTools::ReportModel::headerData (int section, Qt::Orientation orienta
if (orientation==Qt::Vertical)
return QVariant();
if (section==0)
return "Type";
switch (section)
{
case Column_Type: return "Type";
case Column_Id: return "ID";
}
if (section==1)
if (section==mColumnDescription)
return "Description";
return "Hint";
if (section==mColumnField)
return "Field";
return "-";
}
bool CSMTools::ReportModel::removeRows (int row, int count, const QModelIndex& parent)
@ -64,18 +129,43 @@ void CSMTools::ReportModel::add (const CSMWorld::UniversalId& id, const std::str
const std::string& hint)
{
beginInsertRows (QModelIndex(), mRows.size(), mRows.size());
mRows.push_back (std::make_pair (id, std::make_pair (message, hint)));
mRows.push_back (Line (id, message, hint));
endInsertRows();
}
void CSMTools::ReportModel::flagAsReplaced (int index)
{
Line& line = mRows.at (index);
std::string hint = line.mHint;
if (hint.empty() || hint[0]!='R')
throw std::logic_error ("trying to flag message as replaced that is not replaceable");
hint[0] = 'r';
line.mHint = hint;
emit dataChanged (this->index (index, 0), this->index (index, columnCount()));
}
const CSMWorld::UniversalId& CSMTools::ReportModel::getUniversalId (int row) const
{
return mRows.at (row).first;
return mRows.at (row).mId;
}
std::string CSMTools::ReportModel::getHint (int row) const
{
return mRows.at (row).second.second;
}
return mRows.at (row).mHint;
}
void CSMTools::ReportModel::clear()
{
if (!mRows.empty())
{
beginRemoveRows (QModelIndex(), 0, mRows.size()-1);
mRows.clear();
endRemoveRows();
}
}

View file

@ -14,10 +14,32 @@ namespace CSMTools
{
Q_OBJECT
std::vector<std::pair<CSMWorld::UniversalId, std::pair<std::string, std::string> > > mRows;
struct Line
{
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
enum Columns
{
Column_Type = 0, Column_Id = 1, Column_Hint = 2
};
// Configurable columns
int mColumnDescription;
int mColumnField;
public:
ReportModel (bool fieldColumn = false);
virtual int rowCount (const QModelIndex & parent = QModelIndex()) const;
virtual int columnCount (const QModelIndex & parent = QModelIndex()) const;
@ -27,13 +49,17 @@ namespace CSMTools
virtual QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
virtual bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex());
void add (const CSMWorld::UniversalId& id, const std::string& message,
const std::string& hint = "");
void flagAsReplaced (int index);
const CSMWorld::UniversalId& getUniversalId (int row) const;
std::string getHint (int row) const;
void clear();
};
}

View file

@ -98,4 +98,4 @@ void CSMTools::ScriptCheckStage::perform (int stage, CSMDoc::Messages& messages)
}
mMessages = 0;
}
}

View file

@ -0,0 +1,279 @@
#include "search.hpp"
#include <stdexcept>
#include <sstream>
#include "../doc/messages.hpp"
#include "../doc/document.hpp"
#include "../world/idtablebase.hpp"
#include "../world/columnbase.hpp"
#include "../world/universalid.hpp"
#include "../world/commands.hpp"
void CSMTools::Search::searchTextCell (const CSMWorld::IdTableBase *model,
const QModelIndex& index, const CSMWorld::UniversalId& id, bool writable,
CSMDoc::Messages& messages) const
{
// using QString here for easier handling of case folding.
QString search = QString::fromUtf8 (mText.c_str());
QString text = model->data (index).toString();
int pos = 0;
while ((pos = text.indexOf (search, pos, Qt::CaseInsensitive))!=-1)
{
std::ostringstream hint;
hint
<< (writable ? 'R' : 'r')
<<": "
<< model->getColumnId (index.column())
<< " " << pos
<< " " << search.length();
messages.add (id, formatDescription (text, pos, search.length()).toUtf8().data(), hint.str());
pos += search.length();
}
}
void CSMTools::Search::searchRegExCell (const CSMWorld::IdTableBase *model,
const QModelIndex& index, const CSMWorld::UniversalId& id, bool writable,
CSMDoc::Messages& messages) const
{
QString text = model->data (index).toString();
int pos = 0;
while ((pos = mRegExp.indexIn (text, pos))!=-1)
{
int length = mRegExp.matchedLength();
std::ostringstream hint;
hint
<< (writable ? 'R' : 'r')
<<": "
<< model->getColumnId (index.column())
<< " " << pos
<< " " << length;
messages.add (id, formatDescription (text, pos, length).toUtf8().data(), hint.str());
pos += length;
}
}
void CSMTools::Search::searchRecordStateCell (const CSMWorld::IdTableBase *model,
const QModelIndex& index, const CSMWorld::UniversalId& id, bool writable, CSMDoc::Messages& messages) const
{
if (writable)
throw std::logic_error ("Record state can not be modified by search and replace");
int data = model->data (index).toInt();
if (data==mValue)
{
std::vector<std::string> states =
CSMWorld::Columns::getEnums (CSMWorld::Columns::ColumnId_Modification);
std::ostringstream message;
message << states.at (data);
std::ostringstream hint;
hint << "r: " << model->getColumnId (index.column());
messages.add (id, message.str(), hint.str());
}
}
QString CSMTools::Search::formatDescription (const QString& description, int pos, int length) const
{
QString text (description);
// split
QString highlight = flatten (text.mid (pos, length));
QString before = flatten (mPaddingBefore>=pos ?
text.mid (0, pos) : text.mid (pos-mPaddingBefore, mPaddingBefore));
QString after = flatten (text.mid (pos+length, mPaddingAfter));
// compensate for Windows nonsense
text.remove ('\r');
// join
text = before + "<b>" + highlight + "</b>" + after;
// improve layout for single line display
text.replace ("\n", "&lt;CR>");
text.replace ('\t', ' ');
return text;
}
QString CSMTools::Search::flatten (const QString& text) const
{
QString flat (text);
flat.replace ("&", "&amp;");
flat.replace ("<", "&lt;");
return flat;
}
CSMTools::Search::Search() : mType (Type_None), mPaddingBefore (10), mPaddingAfter (10) {}
CSMTools::Search::Search (Type type, const std::string& value)
: mType (type), mText (value), mPaddingBefore (10), mPaddingAfter (10)
{
if (type!=Type_Text && type!=Type_Id)
throw std::logic_error ("Invalid search parameter (string)");
}
CSMTools::Search::Search (Type type, const QRegExp& value)
: mType (type), mRegExp (value), mPaddingBefore (10), mPaddingAfter (10)
{
if (type!=Type_TextRegEx && type!=Type_IdRegEx)
throw std::logic_error ("Invalid search parameter (RegExp)");
}
CSMTools::Search::Search (Type type, int value)
: mType (type), mValue (value), mPaddingBefore (10), mPaddingAfter (10)
{
if (type!=Type_RecordState)
throw std::logic_error ("invalid search parameter (int)");
}
void CSMTools::Search::configure (const CSMWorld::IdTableBase *model)
{
mColumns.clear();
int columns = model->columnCount();
for (int i=0; i<columns; ++i)
{
CSMWorld::ColumnBase::Display display = static_cast<CSMWorld::ColumnBase::Display> (
model->headerData (
i, Qt::Horizontal, static_cast<int> (CSMWorld::ColumnBase::Role_Display)).toInt());
bool consider = false;
switch (mType)
{
case Type_Text:
case Type_TextRegEx:
if (CSMWorld::ColumnBase::isText (display) ||
CSMWorld::ColumnBase::isScript (display))
{
consider = true;
}
break;
case Type_Id:
case Type_IdRegEx:
if (CSMWorld::ColumnBase::isId (display) ||
CSMWorld::ColumnBase::isScript (display))
{
consider = true;
}
break;
case Type_RecordState:
if (display==CSMWorld::ColumnBase::Display_RecordState)
consider = true;
break;
case Type_None:
break;
}
if (consider)
mColumns.insert (i);
}
mIdColumn = model->findColumnIndex (CSMWorld::Columns::ColumnId_Id);
mTypeColumn = model->findColumnIndex (CSMWorld::Columns::ColumnId_RecordType);
}
void CSMTools::Search::searchRow (const CSMWorld::IdTableBase *model, int row,
CSMDoc::Messages& messages) const
{
for (std::set<int>::const_iterator iter (mColumns.begin()); iter!=mColumns.end(); ++iter)
{
QModelIndex index = model->index (row, *iter);
CSMWorld::UniversalId::Type type = static_cast<CSMWorld::UniversalId::Type> (
model->data (model->index (row, mTypeColumn)).toInt());
CSMWorld::UniversalId id (
type, model->data (model->index (row, mIdColumn)).toString().toUtf8().data());
bool writable = model->flags (index) & Qt::ItemIsEditable;
switch (mType)
{
case Type_Text:
case Type_Id:
searchTextCell (model, index, id, writable, messages);
break;
case Type_TextRegEx:
case Type_IdRegEx:
searchRegExCell (model, index, id, writable, messages);
break;
case Type_RecordState:
searchRecordStateCell (model, index, id, writable, messages);
break;
case Type_None:
break;
}
}
}
void CSMTools::Search::setPadding (int before, int after)
{
mPaddingBefore = before;
mPaddingAfter = after;
}
void CSMTools::Search::replace (CSMDoc::Document& document, CSMWorld::IdTableBase *model,
const CSMWorld::UniversalId& id, const std::string& messageHint,
const std::string& replaceText) const
{
std::istringstream stream (messageHint.c_str());
char hint, ignore;
int columnId, pos, length;
if (stream >> hint >> ignore >> columnId >> pos >> length)
{
int column =
model->findColumnIndex (static_cast<CSMWorld::Columns::ColumnId> (columnId));
QModelIndex index = model->getModelIndex (id.getId(), column);
std::string text = model->data (index).toString().toUtf8().constData();
std::string before = text.substr (0, pos);
std::string after = text.substr (pos+length);
std::string newText = before + replaceText + after;
document.getUndoStack().push (
new CSMWorld::ModifyCommand (*model, index, QString::fromUtf8 (newText.c_str())));
}
}

View file

@ -0,0 +1,96 @@
#ifndef CSM_TOOLS_SEARCH_H
#define CSM_TOOLS_SEARCH_H
#include <string>
#include <set>
#include <QRegExp>
#include <QMetaType>
class QModelIndex;
namespace CSMDoc
{
class Messages;
class Document;
}
namespace CSMWorld
{
class IdTableBase;
class UniversalId;
}
namespace CSMTools
{
class Search
{
public:
enum Type
{
Type_Text = 0,
Type_TextRegEx = 1,
Type_Id = 2,
Type_IdRegEx = 3,
Type_RecordState = 4,
Type_None
};
private:
Type mType;
std::string mText;
QRegExp mRegExp;
int mValue;
std::set<int> mColumns;
int mIdColumn;
int mTypeColumn;
int mPaddingBefore;
int mPaddingAfter;
void searchTextCell (const CSMWorld::IdTableBase *model, const QModelIndex& index,
const CSMWorld::UniversalId& id, bool writable, CSMDoc::Messages& messages) const;
void searchRegExCell (const CSMWorld::IdTableBase *model, const QModelIndex& index,
const CSMWorld::UniversalId& id, bool writable, CSMDoc::Messages& messages) const;
void searchRecordStateCell (const CSMWorld::IdTableBase *model,
const QModelIndex& index, const CSMWorld::UniversalId& id, bool writable,
CSMDoc::Messages& messages) const;
QString formatDescription (const QString& description, int pos, int length) const;
QString flatten (const QString& text) const;
public:
Search();
Search (Type type, const std::string& value);
Search (Type type, const QRegExp& value);
Search (Type type, int value);
// Configure search for the specified model.
void configure (const CSMWorld::IdTableBase *model);
// Search row in \a model and store results in \a messages.
//
// \attention *this needs to be configured for \a model.
void searchRow (const CSMWorld::IdTableBase *model, int row,
CSMDoc::Messages& messages) const;
void setPadding (int before, int after);
// Configuring *this for the model is not necessary when calling this function.
void replace (CSMDoc::Document& document, CSMWorld::IdTableBase *model,
const CSMWorld::UniversalId& id, const std::string& messageHint,
const std::string& replaceText) const;
};
}
Q_DECLARE_METATYPE (CSMTools::Search)
#endif

View file

@ -0,0 +1,40 @@
#include "searchoperation.hpp"
#include "../doc/state.hpp"
#include "../doc/document.hpp"
#include "../world/data.hpp"
#include "../world/idtablebase.hpp"
#include "searchstage.hpp"
CSMTools::SearchOperation::SearchOperation (CSMDoc::Document& document)
: CSMDoc::Operation (CSMDoc::State_Searching, false)
{
std::vector<CSMWorld::UniversalId::Type> types = CSMWorld::UniversalId::listTypes (
CSMWorld::UniversalId::Class_RecordList |
CSMWorld::UniversalId::Class_ResourceList
);
for (std::vector<CSMWorld::UniversalId::Type>::const_iterator iter (types.begin());
iter!=types.end(); ++iter)
appendStage (new SearchStage (&dynamic_cast<CSMWorld::IdTableBase&> (
*document.getData().getTableModel (*iter))));
}
void CSMTools::SearchOperation::configure (const Search& search)
{
mSearch = search;
}
void CSMTools::SearchOperation::appendStage (SearchStage *stage)
{
CSMDoc::Operation::appendStage (stage);
stage->setOperation (this);
}
const CSMTools::Search& CSMTools::SearchOperation::getSearch() const
{
return mSearch;
}

View file

@ -0,0 +1,38 @@
#ifndef CSM_TOOLS_SEARCHOPERATION_H
#define CSM_TOOLS_SEARCHOPERATION_H
#include "../doc/operation.hpp"
#include "search.hpp"
namespace CSMDoc
{
class Document;
}
namespace CSMTools
{
class SearchStage;
class SearchOperation : public CSMDoc::Operation
{
Search mSearch;
public:
SearchOperation (CSMDoc::Document& document);
/// \attention Do not call this function while a search is running.
void configure (const Search& search);
void appendStage (SearchStage *stage);
///< The ownership of \a stage is transferred to *this.
///
/// \attention Do no call this function while this Operation is running.
const Search& getSearch() const;
};
}
#endif

View file

@ -0,0 +1,30 @@
#include "searchstage.hpp"
#include "../world/idtablebase.hpp"
#include "searchoperation.hpp"
CSMTools::SearchStage::SearchStage (const CSMWorld::IdTableBase *model)
: mModel (model), mOperation (0)
{}
int CSMTools::SearchStage::setup()
{
if (mOperation)
mSearch = mOperation->getSearch();
mSearch.configure (mModel);
return mModel->rowCount();
}
void CSMTools::SearchStage::perform (int stage, CSMDoc::Messages& messages)
{
mSearch.searchRow (mModel, stage, messages);
}
void CSMTools::SearchStage::setOperation (const SearchOperation *operation)
{
mOperation = operation;
}

View file

@ -0,0 +1,37 @@
#ifndef CSM_TOOLS_SEARCHSTAGE_H
#define CSM_TOOLS_SEARCHSTAGE_H
#include "../doc/stage.hpp"
#include "search.hpp"
namespace CSMWorld
{
class IdTableBase;
}
namespace CSMTools
{
class SearchOperation;
class SearchStage : public CSMDoc::Stage
{
const CSMWorld::IdTableBase *mModel;
Search mSearch;
const SearchOperation *mOperation;
public:
SearchStage (const CSMWorld::IdTableBase *model);
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.
void setOperation (const SearchOperation *operation);
};
}
#endif

View file

@ -39,4 +39,4 @@ void CSMTools::SkillCheckStage::perform (int stage, CSMDoc::Messages& messages)
if (skill.mDescription.empty())
messages.push_back (std::make_pair (id, skill.mId + " has an empty description"));
}
}

View file

@ -31,4 +31,4 @@ void CSMTools::SoundCheckStage::perform (int stage, CSMDoc::Messages& messages)
messages.push_back (std::make_pair (id, "Maximum range larger than minimum range"));
/// \todo check, if the sound file exists
}
}

View file

@ -37,4 +37,4 @@ void CSMTools::SpellCheckStage::perform (int stage, CSMDoc::Messages& messages)
messages.push_back (std::make_pair (id, spell.mId + " has a negative spell costs"));
/// \todo check data members that can't be edited in the table view
}
}

View file

@ -0,0 +1,31 @@
#include "startscriptcheck.hpp"
#include <components/misc/stringops.hpp>
CSMTools::StartScriptCheckStage::StartScriptCheckStage (
const CSMWorld::IdCollection<ESM::StartScript>& startScripts,
const CSMWorld::IdCollection<ESM::Script>& scripts)
: mStartScripts (startScripts), mScripts (scripts)
{}
void CSMTools::StartScriptCheckStage::perform(int stage, CSMDoc::Messages& messages)
{
const CSMWorld::Record<ESM::StartScript>& record = mStartScripts.getRecord (stage);
if (record.isDeleted())
return;
std::string scriptId = record.get().mId;
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_StartScript, scriptId);
if (mScripts.searchId (Misc::StringUtils::lowerCase (scriptId))==-1)
messages.push_back (
std::make_pair (id, "Start script " + scriptId + " does not exist"));
}
int CSMTools::StartScriptCheckStage::setup()
{
return mStartScripts.getSize();
}

View file

@ -0,0 +1,28 @@
#ifndef CSM_TOOLS_STARTSCRIPTCHECK_H
#define CSM_TOOLS_STARTSCRIPTCHECK_H
#include <components/esm/loadsscr.hpp>
#include <components/esm/loadscpt.hpp>
#include "../doc/stage.hpp"
#include "../world/idcollection.hpp"
namespace CSMTools
{
class StartScriptCheckStage : public CSMDoc::Stage
{
const CSMWorld::IdCollection<ESM::StartScript>& mStartScripts;
const CSMWorld::IdCollection<ESM::Script>& mScripts;
public:
StartScriptCheckStage (const CSMWorld::IdCollection<ESM::StartScript>& startScripts,
const CSMWorld::IdCollection<ESM::Script>& scripts);
virtual void perform(int stage, CSMDoc::Messages& messages);
virtual int setup();
};
}
#endif

View file

@ -24,31 +24,34 @@
#include "scriptcheck.hpp"
#include "bodypartcheck.hpp"
#include "referencecheck.hpp"
#include "startscriptcheck.hpp"
#include "searchoperation.hpp"
CSMDoc::Operation *CSMTools::Tools::get (int type)
CSMDoc::OperationHolder *CSMTools::Tools::get (int type)
{
switch (type)
{
case CSMDoc::State_Verifying: return mVerifier;
case CSMDoc::State_Verifying: return &mVerifier;
case CSMDoc::State_Searching: return &mSearch;
}
return 0;
}
const CSMDoc::Operation *CSMTools::Tools::get (int type) const
const CSMDoc::OperationHolder *CSMTools::Tools::get (int type) const
{
return const_cast<Tools *> (this)->get (type);
}
CSMDoc::Operation *CSMTools::Tools::getVerifier()
CSMDoc::OperationHolder *CSMTools::Tools::getVerifier()
{
if (!mVerifier)
if (!mVerifierOperation)
{
mVerifier = new CSMDoc::Operation (CSMDoc::State_Verifying, false);
mVerifierOperation = new CSMDoc::Operation (CSMDoc::State_Verifying, false);
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,
connect (&mVerifier, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int)));
connect (&mVerifier, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool)));
connect (&mVerifier,
SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)),
this, SLOT (verifierMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)));
@ -59,54 +62,75 @@ CSMDoc::Operation *CSMTools::Tools::getVerifier()
mandatoryIds.push_back ("Month");
mandatoryIds.push_back ("PCRace");
mVerifier->appendStage (new MandatoryIdStage (mData.getGlobals(),
mVerifierOperation->appendStage (new MandatoryIdStage (mData.getGlobals(),
CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Globals), mandatoryIds));
mVerifier->appendStage (new SkillCheckStage (mData.getSkills()));
mVerifierOperation->appendStage (new SkillCheckStage (mData.getSkills()));
mVerifier->appendStage (new ClassCheckStage (mData.getClasses()));
mVerifierOperation->appendStage (new ClassCheckStage (mData.getClasses()));
mVerifier->appendStage (new FactionCheckStage (mData.getFactions()));
mVerifierOperation->appendStage (new FactionCheckStage (mData.getFactions()));
mVerifier->appendStage (new RaceCheckStage (mData.getRaces()));
mVerifierOperation->appendStage (new RaceCheckStage (mData.getRaces()));
mVerifier->appendStage (new SoundCheckStage (mData.getSounds()));
mVerifierOperation->appendStage (new SoundCheckStage (mData.getSounds()));
mVerifier->appendStage (new RegionCheckStage (mData.getRegions()));
mVerifierOperation->appendStage (new RegionCheckStage (mData.getRegions()));
mVerifier->appendStage (new BirthsignCheckStage (mData.getBirthsigns()));
mVerifierOperation->appendStage (new BirthsignCheckStage (mData.getBirthsigns()));
mVerifier->appendStage (new SpellCheckStage (mData.getSpells()));
mVerifierOperation->appendStage (new SpellCheckStage (mData.getSpells()));
mVerifier->appendStage (new ReferenceableCheckStage (mData.getReferenceables().getDataSet(), mData.getRaces(), mData.getClasses(), mData.getFactions()));
mVerifierOperation->appendStage (new ReferenceableCheckStage (mData.getReferenceables().getDataSet(), mData.getRaces(), mData.getClasses(), mData.getFactions()));
mVerifier->appendStage (new ReferenceCheckStage(mData.getReferences(), mData.getReferenceables(), mData.getCells(), mData.getFactions()));
mVerifierOperation->appendStage (new ReferenceCheckStage(mData.getReferences(), mData.getReferenceables(), mData.getCells(), mData.getFactions()));
mVerifier->appendStage (new ScriptCheckStage (mDocument));
mVerifierOperation->appendStage (new ScriptCheckStage (mDocument));
mVerifier->appendStage(
mVerifierOperation->appendStage (new StartScriptCheckStage (mData.getStartScripts(), mData.getScripts()));
mVerifierOperation->appendStage(
new BodyPartCheckStage(
mData.getBodyParts(),
mData.getResources(
CSMWorld::UniversalId( CSMWorld::UniversalId::Type_Meshes )),
mData.getRaces() ));
mVerifier.setOperation (mVerifierOperation);
}
return mVerifier;
return &mVerifier;
}
CSMTools::Tools::Tools (CSMDoc::Document& document)
: mDocument (document), mData (document.getData()), mVerifier (0), mNextReportNumber (0)
: mDocument (document), mData (document.getData()), mVerifierOperation (0), mNextReportNumber (0),
mSearchOperation (0)
{
// index 0: load error log
mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel));
mActiveReports.insert (std::make_pair (CSMDoc::State_Loading, 0));
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 (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)),
this, SLOT (verifierMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)));
}
CSMTools::Tools::~Tools()
{
delete mVerifier;
if (mVerifierOperation)
{
mVerifier.abortAndWait();
delete mVerifierOperation;
}
if (mSearchOperation)
{
mSearch.abortAndWait();
delete mSearchOperation;
}
for (std::map<int, ReportModel *>::iterator iter (mReports.begin()); iter!=mReports.end(); ++iter)
delete iter->second;
}
@ -121,9 +145,31 @@ CSMWorld::UniversalId CSMTools::Tools::runVerifier()
return CSMWorld::UniversalId (CSMWorld::UniversalId::Type_VerificationResults, mNextReportNumber-1);
}
CSMWorld::UniversalId CSMTools::Tools::newSearch()
{
mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel (true)));
return CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Search, mNextReportNumber-1);
}
void CSMTools::Tools::runSearch (const CSMWorld::UniversalId& searchId, const Search& search)
{
mActiveReports[CSMDoc::State_Searching] = searchId.getIndex();
if (!mSearchOperation)
{
mSearchOperation = new SearchOperation (mDocument);
mSearch.setOperation (mSearchOperation);
}
mSearchOperation->configure (search);
mSearch.start();
}
void CSMTools::Tools::abortOperation (int type)
{
if (CSMDoc::Operation *operation = get (type))
if (CSMDoc::OperationHolder *operation = get (type))
operation->abort();
}
@ -132,13 +178,14 @@ int CSMTools::Tools::getRunningOperations() const
static const int sOperations[] =
{
CSMDoc::State_Verifying,
CSMDoc::State_Searching,
-1
};
int result = 0;
for (int i=0; sOperations[i]!=-1; ++i)
if (const CSMDoc::Operation *operation = get (sOperations[i]))
if (const CSMDoc::OperationHolder *operation = get (sOperations[i]))
if (operation->isRunning())
result |= sOperations[i];
@ -148,9 +195,10 @@ int CSMTools::Tools::getRunningOperations() const
CSMTools::ReportModel *CSMTools::Tools::getReport (const CSMWorld::UniversalId& id)
{
if (id.getType()!=CSMWorld::UniversalId::Type_VerificationResults &&
id.getType()!=CSMWorld::UniversalId::Type_LoadErrorLog)
id.getType()!=CSMWorld::UniversalId::Type_LoadErrorLog &&
id.getType()!=CSMWorld::UniversalId::Type_Search)
throw std::logic_error ("invalid request for report model: " + id.toString());
return mReports.at (id.getIndex());
}

View file

@ -5,6 +5,8 @@
#include <map>
#include "../doc/operationholder.hpp"
namespace CSMWorld
{
class Data;
@ -20,6 +22,8 @@ namespace CSMDoc
namespace CSMTools
{
class ReportModel;
class Search;
class SearchOperation;
class Tools : public QObject
{
@ -27,7 +31,10 @@ namespace CSMTools
CSMDoc::Document& mDocument;
CSMWorld::Data& mData;
CSMDoc::Operation *mVerifier;
CSMDoc::Operation *mVerifierOperation;
CSMDoc::OperationHolder mVerifier;
SearchOperation *mSearchOperation;
CSMDoc::OperationHolder mSearch;
std::map<int, ReportModel *> mReports;
int mNextReportNumber;
std::map<int, int> mActiveReports; // type, report number
@ -36,12 +43,12 @@ namespace CSMTools
Tools (const Tools&);
Tools& operator= (const Tools&);
CSMDoc::Operation *getVerifier();
CSMDoc::OperationHolder *getVerifier();
CSMDoc::Operation *get (int type);
CSMDoc::OperationHolder *get (int type);
///< Returns a 0-pointer, if operation hasn't been used yet.
const CSMDoc::Operation *get (int type) const;
const CSMDoc::OperationHolder *get (int type) const;
///< Returns a 0-pointer, if operation hasn't been used yet.
public:
@ -53,6 +60,11 @@ namespace CSMTools
CSMWorld::UniversalId runVerifier();
///< \return ID of the report for this verification run
/// Return ID of the report for this search.
CSMWorld::UniversalId newSearch();
void runSearch (const CSMWorld::UniversalId& searchId, const Search& search);
void abortOperation (int type);
///< \attention The operation is not aborted immediately.

View file

@ -21,4 +21,4 @@ namespace CSMWorld
};
}
#endif
#endif

View file

@ -28,4 +28,4 @@ int CSMWorld::CollectionBase::findColumnIndex (Columns::ColumnId id) const
throw std::logic_error ("invalid column index");
return index;
}
}

View file

@ -106,4 +106,4 @@ namespace CSMWorld
};
}
#endif
#endif

View file

@ -19,7 +19,80 @@ std::string CSMWorld::ColumnBase::getTitle() const
return Columns::getName (static_cast<Columns::ColumnId> (mColumnId));
}
int CSMWorld::ColumnBase::getId() const
int CSMWorld::ColumnBase::getId() const
{
return mColumnId;
}
}
bool CSMWorld::ColumnBase::isId (Display display)
{
static const Display ids[] =
{
Display_Skill,
Display_Class,
Display_Faction,
Display_Race,
Display_Sound,
Display_Region,
Display_Birthsign,
Display_Spell,
Display_Cell,
Display_Referenceable,
Display_Activator,
Display_Potion,
Display_Apparatus,
Display_Armor,
Display_Book,
Display_Clothing,
Display_Container,
Display_Creature,
Display_Door,
Display_Ingredient,
Display_CreatureLevelledList,
Display_ItemLevelledList,
Display_Light,
Display_Lockpick,
Display_Miscellaneous,
Display_Npc,
Display_Probe,
Display_Repair,
Display_Static,
Display_Weapon,
Display_Reference,
Display_Filter,
Display_Topic,
Display_Journal,
Display_TopicInfo,
Display_JournalInfo,
Display_Scene,
Display_GlobalVariable,
Display_Script,
Display_Mesh,
Display_Icon,
Display_Music,
Display_SoundRes,
Display_Texture,
Display_Video,
Display_Id,
Display_None
};
for (int i=0; ids[i]!=Display_None; ++i)
if (ids[i]==display)
return true;
return false;
}
bool CSMWorld::ColumnBase::isText (Display display)
{
return display==Display_String || display==Display_LongString;
}
bool CSMWorld::ColumnBase::isScript (Display display)
{
return display==Display_ScriptFile || display==Display_ScriptLines;
}

View file

@ -101,9 +101,11 @@ namespace CSMWorld
Display_Texture,
Display_Video,
Display_Colour,
Display_ScriptFile,
Display_ScriptLines, // console context
Display_SoundGeneratorType,
Display_School
Display_School,
Display_Id
};
int mColumnId;
@ -122,6 +124,12 @@ namespace CSMWorld
virtual std::string getTitle() const;
virtual int getId() const;
static bool isId (Display display);
static bool isText (Display display);
static bool isScript (Display display);
};
template<typename ESXRecordT>

View file

@ -43,7 +43,7 @@ namespace CSMWorld
struct StringIdColumn : public Column<ESXRecordT>
{
StringIdColumn (bool hidden = false)
: Column<ESXRecordT> (Columns::ColumnId_Id, ColumnBase::Display_String,
: Column<ESXRecordT> (Columns::ColumnId_Id, ColumnBase::Display_Id,
hidden ? 0 : ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue)
{}
@ -818,7 +818,7 @@ namespace CSMWorld
ScriptColumn (Type type)
: Column<ESXRecordT> (Columns::ColumnId_ScriptText,
type==Type_File ? ColumnBase::Display_Script : ColumnBase::Display_ScriptLines,
type==Type_File ? ColumnBase::Display_ScriptFile : ColumnBase::Display_ScriptLines,
type==Type_File ? 0 : ColumnBase::Flag_Dialogue)
{}

View file

@ -264,4 +264,4 @@ void CSMWorld::CommandDispatcher::executeExtendedRevert()
if (mExtendedTypes.size()>1)
mDocument.getUndoStack().endMacro();
}
}

View file

@ -170,4 +170,4 @@ void CSMWorld::CloneCommand::redo()
void CSMWorld::CloneCommand::undo()
{
mModel.removeRow (mModel.getModelIndex (mId, 0).row());
}
}

View file

@ -20,7 +20,7 @@ namespace CSMWorld
{
class IdTable;
class IdTable;
class RecordBase;
struct RecordBase;
class ModifyCommand : public QUndoCommand
{
@ -141,4 +141,4 @@ namespace CSMWorld
};
}
#endif
#endif

View file

@ -254,6 +254,10 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
mPathgrids.addColumn (new RecordStateColumn<Pathgrid>);
mPathgrids.addColumn (new FixedRecordTypeColumn<Pathgrid> (UniversalId::Type_Pathgrid));
mStartScripts.addColumn (new StringIdColumn<ESM::StartScript>);
mStartScripts.addColumn (new RecordStateColumn<ESM::StartScript>);
mStartScripts.addColumn (new FixedRecordTypeColumn<ESM::StartScript> (UniversalId::Type_StartScript));
mRefs.addColumn (new StringIdColumn<CellRef> (true));
mRefs.addColumn (new RecordStateColumn<CellRef>);
mRefs.addColumn (new FixedRecordTypeColumn<CellRef> (UniversalId::Type_Reference));
@ -327,6 +331,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
addModel (new IdTable (&mSoundGens), UniversalId::Type_SoundGen);
addModel (new IdTable (&mMagicEffects), UniversalId::Type_MagicEffect);
addModel (new IdTable (&mPathgrids), UniversalId::Type_Pathgrid);
addModel (new IdTable (&mStartScripts), UniversalId::Type_StartScript);
addModel (new IdTable (&mReferenceables, IdTable::Feature_Preview),
UniversalId::Type_Referenceable);
addModel (new IdTable (&mRefs, IdTable::Feature_ViewCell | IdTable::Feature_Preview), UniversalId::Type_Reference);
@ -615,6 +620,16 @@ CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& CSMWorld::Data::getPathgrids()
return mPathgrids;
}
const CSMWorld::IdCollection<ESM::StartScript>& CSMWorld::Data::getStartScripts() const
{
return mStartScripts;
}
CSMWorld::IdCollection<ESM::StartScript>& CSMWorld::Data::getStartScripts()
{
return mStartScripts;
}
const CSMWorld::Resources& CSMWorld::Data::getResources (const UniversalId& id) const
{
return mResourcesManager.get (id.getType());
@ -719,6 +734,7 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages)
case ESM::REC_SNDG: mSoundGens.load (*mReader, mBase); break;
case ESM::REC_MGEF: mMagicEffects.load (*mReader, mBase); break;
case ESM::REC_PGRD: mPathgrids.load (*mReader, mBase); break;
case ESM::REC_SSCR: mStartScripts.load (*mReader, mBase); break;
case ESM::REC_LTEX: mLandTextures.load (*mReader, mBase); break;
@ -729,7 +745,7 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages)
if (index!=-1 && !mBase)
mLand.getRecord (index).mModified.mLand->loadData (
ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | ESM::Land::DATA_VCLR |
ESM::Land::DATA_VTEX);
ESM::Land::DATA_VTEX | ESM::Land::DATA_WNAM);
break;
}

View file

@ -25,6 +25,7 @@
#include <components/esm/loadbody.hpp>
#include <components/esm/loadsndg.hpp>
#include <components/esm/loadmgef.hpp>
#include <components/esm/loadsscr.hpp>
#include <components/esm/debugprofile.hpp>
#include <components/esm/filter.hpp>
@ -80,6 +81,7 @@ namespace CSMWorld
SubCellCollection<Pathgrid> mPathgrids;
IdCollection<ESM::DebugProfile> mDebugProfiles;
IdCollection<ESM::SoundGenerator> mSoundGens;
IdCollection<ESM::StartScript> mStartScripts;
InfoCollection mTopicInfos;
InfoCollection mJournalInfos;
IdCollection<Cell> mCells;
@ -225,6 +227,10 @@ namespace CSMWorld
SubCellCollection<Pathgrid>& getPathgrids();
const IdCollection<ESM::StartScript>& getStartScripts() const;
IdCollection<ESM::StartScript>& getStartScripts();
/// Throws an exception, if \a id does not match a resources list.
const Resources& getResources (const UniversalId& id) const;

View file

@ -10,7 +10,7 @@
namespace CSMWorld
{
class CollectionBase;
class RecordBase;
struct RecordBase;
class IdTable : public IdTableBase
{
@ -82,7 +82,7 @@ namespace CSMWorld
/// Is \a id flagged as deleted?
virtual bool isDeleted (const std::string& id) const;
int getColumnId(int column) const;
virtual int getColumnId(int column) const;
};
}

View file

@ -6,4 +6,4 @@ CSMWorld::IdTableBase::IdTableBase (unsigned int features) : mFeatures (features
unsigned int CSMWorld::IdTableBase::getFeatures() const
{
return mFeatures;
}
}

View file

@ -60,6 +60,8 @@ namespace CSMWorld
/// Is \a id flagged as deleted?
virtual bool isDeleted (const std::string& id) const = 0;
virtual int getColumnId (int column) const = 0;
unsigned int getFeatures() const;
};
}

View file

@ -26,7 +26,7 @@ void CSMWorld::InfoCollection::load (const Info& record, bool base)
if (!record2.get().mPrev.empty())
{
index = getIndex (record2.get().mPrev, topic);
index = getInfoIndex (record2.get().mPrev, topic);
if (index!=-1)
++index;
@ -34,7 +34,7 @@ void CSMWorld::InfoCollection::load (const Info& record, bool base)
if (index==-1 && !record2.get().mNext.empty())
{
index = getIndex (record2.get().mNext, topic);
index = getInfoIndex (record2.get().mNext, topic);
}
if (index==-1)
@ -60,7 +60,7 @@ void CSMWorld::InfoCollection::load (const Info& record, bool base)
}
}
int CSMWorld::InfoCollection::getIndex (const std::string& id, const std::string& topic) const
int CSMWorld::InfoCollection::getInfoIndex (const std::string& id, const std::string& topic) const
{
std::string fullId = Misc::StringUtils::lowerCase (topic) + "#" + id;

View file

@ -6,7 +6,7 @@
namespace ESM
{
class Dialogue;
struct Dialogue;
}
namespace CSMWorld
@ -22,7 +22,7 @@ namespace CSMWorld
void load (const Info& record, bool base);
int getIndex (const std::string& id, const std::string& topic) const;
int getInfoIndex (const std::string& id, const std::string& topic) const;
///< Return index for record \a id or -1 (if not present; deleted records are considered)
///
/// \param id info ID without topic prefix
@ -47,4 +47,4 @@ namespace CSMWorld
};
}
#endif
#endif

View file

@ -26,4 +26,4 @@ namespace CSMWorld
};
}
#endif
#endif

View file

@ -18,4 +18,4 @@ bool CSMWorld::RecordBase::isErased() const
bool CSMWorld::RecordBase::isModified() const
{
return mState==State_Modified || mState==State_ModifiedOnly;
}
}

View file

@ -22,6 +22,8 @@ namespace CSMWorld
virtual RecordBase *clone() const = 0;
virtual RecordBase *modifiedCopy() const = 0;
virtual void assign (const RecordBase& record) = 0;
///< Will throw an exception if the types don't match.
@ -38,8 +40,15 @@ namespace CSMWorld
ESXRecordT mBase;
ESXRecordT mModified;
Record();
Record(State state,
const ESXRecordT *base = 0, const ESXRecordT *modified = 0);
virtual RecordBase *clone() const;
virtual RecordBase *modifiedCopy() const;
virtual void assign (const RecordBase& record);
const ESXRecordT& get() const;
@ -58,6 +67,29 @@ namespace CSMWorld
///< Merge modified into base.
};
template <typename ESXRecordT>
Record<ESXRecordT>::Record()
: mBase(), mModified()
{ }
template <typename ESXRecordT>
Record<ESXRecordT>::Record(State state, const ESXRecordT *base, const ESXRecordT *modified)
{
if(base)
mBase = *base;
if(modified)
mModified = *modified;
this->mState = state;
}
template <typename ESXRecordT>
RecordBase *Record<ESXRecordT>::modifiedCopy() const
{
return new Record<ESXRecordT> (State_ModifiedOnly, 0, &(this->get()));
}
template <typename ESXRecordT>
RecordBase *Record<ESXRecordT>::clone() const
{

View file

@ -5,4 +5,4 @@ CSMWorld::CellRef::CellRef()
{
mRefNum.mIndex = 0;
mRefNum.mContentFile = 0;
}
}

View file

@ -5,8 +5,6 @@
namespace CSMWorld
{
class Cell;
/// \brief Wrapper for CellRef sub record
struct CellRef : public ESM::CellRef
{

View file

@ -12,7 +12,7 @@
namespace CSMWorld
{
struct Cell;
struct UniversalId;
class UniversalId;
/// \brief References in cells
class RefCollection : public Collection<CellRef>

View file

@ -3,4 +3,4 @@
CSMWorld::RefIdAdapter::RefIdAdapter() {}
CSMWorld::RefIdAdapter::~RefIdAdapter() {}
CSMWorld::RefIdAdapter::~RefIdAdapter() {}

View file

@ -9,7 +9,7 @@ namespace CSMWorld
{
class RefIdColumn;
class RefIdData;
class RecordBase;
struct RecordBase;
class RefIdAdapter
{
@ -35,4 +35,4 @@ namespace CSMWorld
};
}
#endif
#endif

View file

@ -156,10 +156,16 @@ namespace CSMWorld
Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
RecordT record2 = record.get();
if (column==mModel.mModel)
record.get().mModel = value.toString().toUtf8().constData();
record2.mModel = value.toString().toUtf8().constData();
else
{
BaseRefIdAdapter<RecordT>::setData (column, data, index, value);
return;
}
record.setModified(record2);
}
struct NameColumns : public ModelColumns
@ -216,12 +222,18 @@ namespace CSMWorld
Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
RecordT record2 = record.get();
if (column==mName.mName)
record.get().mName = value.toString().toUtf8().constData();
record2.mName = value.toString().toUtf8().constData();
else if (column==mName.mScript)
record.get().mScript = value.toString().toUtf8().constData();
record2.mScript = value.toString().toUtf8().constData();
else
{
ModelRefIdAdapter<RecordT>::setData (column, data, index, value);
return;
}
record.setModified(record2);
}
struct InventoryColumns : public NameColumns
@ -283,14 +295,20 @@ namespace CSMWorld
Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
RecordT record2 = record.get();
if (column==mInventory.mIcon)
record.get().mIcon = value.toString().toUtf8().constData();
record2.mIcon = value.toString().toUtf8().constData();
else if (column==mInventory.mWeight)
record.get().mData.mWeight = value.toFloat();
record2.mData.mWeight = value.toFloat();
else if (column==mInventory.mValue)
record.get().mData.mValue = value.toInt();
record2.mData.mValue = value.toInt();
else
{
NameRefIdAdapter<RecordT>::setData (column, data, index, value);
return;
}
record.setModified(record2);
}
class PotionRefIdAdapter : public InventoryRefIdAdapter<ESM::Potion>
@ -364,12 +382,18 @@ namespace CSMWorld
Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
RecordT record2 = record.get();
if (column==mEnchantable.mEnchantment)
record.get().mEnchant = value.toString().toUtf8().constData();
record2.mEnchant = value.toString().toUtf8().constData();
else if (column==mEnchantable.mEnchantmentPoints)
record.get().mData.mEnchant = value.toInt();
record2.mData.mEnchant = value.toInt();
else
{
InventoryRefIdAdapter<RecordT>::setData (column, data, index, value);
return;
}
record.setModified(record2);
}
struct ToolColumns : public InventoryColumns
@ -426,12 +450,18 @@ namespace CSMWorld
Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
RecordT record2 = record.get();
if (column==mTools.mQuality)
record.get().mData.mQuality = value.toFloat();
record2.mData.mQuality = value.toFloat();
else if (column==mTools.mUses)
record.get().mData.mUses = value.toInt();
record2.mData.mUses = value.toInt();
else
{
InventoryRefIdAdapter<RecordT>::setData (column, data, index, value);
return;
}
record.setModified(record2);
}
struct ActorColumns : public NameColumns
@ -508,16 +538,17 @@ namespace CSMWorld
Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
RecordT record2 = record.get();
if (column==mActors.mHasAi)
record.get().mHasAI = value.toInt();
record2.mHasAI = value.toInt();
else if (column==mActors.mHello)
record.get().mAiData.mHello = value.toInt();
record2.mAiData.mHello = value.toInt();
else if (column==mActors.mFlee)
record.get().mAiData.mFlee = value.toInt();
record2.mAiData.mFlee = value.toInt();
else if (column==mActors.mFight)
record.get().mAiData.mFight = value.toInt();
record2.mAiData.mFight = value.toInt();
else if (column==mActors.mAlarm)
record.get().mAiData.mAlarm = value.toInt();
record2.mAiData.mAlarm = value.toInt();
else
{
typename std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
@ -525,13 +556,18 @@ namespace CSMWorld
if (iter!=mActors.mServices.end())
{
if (value.toInt()!=0)
record.get().mAiData.mServices |= iter->second;
record2.mAiData.mServices |= iter->second;
else
record.get().mAiData.mServices &= ~iter->second;
record2.mAiData.mServices &= ~iter->second;
}
else
{
NameRefIdAdapter<RecordT>::setData (column, data, index, value);
return;
}
}
record.setModified(record2);
}
class ApparatusRefIdAdapter : public InventoryRefIdAdapter<ESM::Apparatus>

View file

@ -40,7 +40,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
{
BaseColumns baseColumns;
mColumns.push_back (RefIdColumn (Columns::ColumnId_Id, ColumnBase::Display_String,
mColumns.push_back (RefIdColumn (Columns::ColumnId_Id, ColumnBase::Display_Id,
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false));
baseColumns.mId = &mColumns.back();
mColumns.push_back (RefIdColumn (Columns::ColumnId_Modification, ColumnBase::Display_RecordState,
@ -470,8 +470,7 @@ void CSMWorld::RefIdCollection::cloneRecord(const std::string& origin,
const std::string& destination,
const CSMWorld::UniversalId::Type type)
{
std::auto_ptr<RecordBase> newRecord(mData.getRecord(mData.searchId(origin)).clone());
newRecord->mState = RecordBase::State_ModifiedOnly;
std::auto_ptr<RecordBase> newRecord(mData.getRecord(mData.searchId(origin)).modifiedCopy());
mAdapters.find(type)->second->setId(*newRecord, destination);
mData.insertRecord(*newRecord, type, destination);
}

View file

@ -503,4 +503,4 @@ void CSMWorld::RegionMap::cellsChanged (const QModelIndex& topLeft, const QModel
// columns we are interested in. If not we can exit the function here and avoid all updating.
addCells (topLeft.row(), bottomRight.row());
}
}

View file

@ -105,4 +105,4 @@ int CSMWorld::Resources::searchId (const std::string& id) const
CSMWorld::UniversalId::Type CSMWorld::Resources::getType() const
{
return mType;
}
}

View file

@ -30,4 +30,4 @@ const CSMWorld::Resources& CSMWorld::ResourcesManager::get (UniversalId::Type ty
throw std::logic_error ("Unknown resource type");
return iter->second;
}
}

View file

@ -25,4 +25,4 @@ namespace CSMWorld
};
}
#endif
#endif

View file

@ -60,7 +60,7 @@ QVariant CSMWorld::ResourceTable::headerData (int section, Qt::Orientation orien
return Columns::getName (Columns::ColumnId_Id).c_str();
if (role==ColumnBase::Role_Display)
return ColumnBase::Display_String;
return ColumnBase::Display_Id;
break;
@ -143,4 +143,15 @@ std::pair<CSMWorld::UniversalId, std::string> CSMWorld::ResourceTable::view (int
bool CSMWorld::ResourceTable::isDeleted (const std::string& id) const
{
return false;
}
}
int CSMWorld::ResourceTable::getColumnId (int column) const
{
switch (column)
{
case 0: return Columns::ColumnId_Id;
case 1: return Columns::ColumnId_RecordType;
}
return -1;
}

View file

@ -51,6 +51,8 @@ namespace CSMWorld
/// Is \a id flagged as deleted?
virtual bool isDeleted (const std::string& id) const;
virtual int getColumnId (int column) const;
};
}

View file

@ -22,4 +22,4 @@ CSMWorld::Scope CSMWorld::getScopeFromId (const std::string& id)
return Scope_Session;
return Scope_Content;
}
}

View file

@ -120,4 +120,4 @@ void CSMWorld::ScriptContext::clear()
mIds.clear();
mIdsUpdated = false;
mLocals.clear();
}
}

View file

@ -55,6 +55,7 @@ namespace
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_SoundGens, "Sound Generators", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MagicEffects, "Magic Effects", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Pathgrids, "Pathgrids", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_StartScripts, "Start Scripts", 0 },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
};
@ -118,6 +119,7 @@ namespace
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_SoundGen, "Sound Generator", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MagicEffect, "Magic Effect", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Pathgrid, "Pathgrid", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_StartScript, "Start Script", 0 },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
};
@ -126,6 +128,7 @@ namespace
{
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_VerificationResults, "Verification Results", 0 },
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_LoadErrorLog, "Load Error Log", 0 },
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_Search, "Global Search", 0 },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
};
}
@ -345,6 +348,25 @@ std::vector<CSMWorld::UniversalId::Type> CSMWorld::UniversalId::listReferenceabl
return list;
}
std::vector<CSMWorld::UniversalId::Type> CSMWorld::UniversalId::listTypes (int classes)
{
std::vector<CSMWorld::UniversalId::Type> list;
for (int i=0; sNoArg[i].mName; ++i)
if (sNoArg[i].mClass & classes)
list.push_back (sNoArg[i].mType);
for (int i=0; sIdArg[i].mName; ++i)
if (sIdArg[i].mClass & classes)
list.push_back (sIdArg[i].mType);
for (int i=0; sIndexArg[i].mName; ++i)
if (sIndexArg[i].mClass & classes)
list.push_back (sIndexArg[i].mType);
return list;
}
CSMWorld::UniversalId::Type CSMWorld::UniversalId::getParentType (Type type)
{
for (int i=0; sIdArg[i].mType; ++i)

View file

@ -16,16 +16,16 @@ namespace CSMWorld
enum Class
{
Class_None = 0,
Class_Record,
Class_RefRecord, // referenceable record
Class_SubRecord,
Class_RecordList,
Class_Collection, // multiple types of records combined
Class_Transient, // not part of the world data or the project data
Class_NonRecord, // record like data that is not part of the world
Class_Resource, ///< \attention Resource IDs are unique only within the
Class_Record = 1,
Class_RefRecord = 2, // referenceable record
Class_SubRecord = 4,
Class_RecordList = 8,
Class_Collection = 16, // multiple types of records combined
Class_Transient = 32, // not part of the world data or the project data
Class_NonRecord = 64, // record like data that is not part of the world
Class_Resource = 128, ///< \attention Resource IDs are unique only within the
/// respective collection
Class_ResourceList
Class_ResourceList = 256
};
enum ArgumentType
@ -128,6 +128,9 @@ namespace CSMWorld
Type_MagicEffect,
Type_Pathgrids,
Type_Pathgrid,
Type_StartScripts,
Type_StartScript,
Type_Search,
Type_RunLog
};
@ -178,6 +181,8 @@ namespace CSMWorld
static std::vector<Type> listReferenceableTypes();
static std::vector<Type> listTypes (int classes);
/// If \a type is a SubRecord, RefRecord or Record type return the type of the table
/// that contains records of type \a type.
/// Otherwise return Type_None.

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