Merge branch 'master' of https://github.com/OpenMW/openmw into osg

Conflicts:
	apps/opencs/model/doc/document.cpp
	apps/opencs/model/doc/documentmanager.cpp
	components/CMakeLists.txt
	components/bsa/resources.cpp
	components/nif/data.hpp
	components/nif/node.cpp
	components/nifogre/mesh.hpp
	components/nifogre/ogrenifloader.cpp
	components/nifogre/particles.cpp
This commit is contained in:
scrawl 2015-03-27 17:30:48 +01:00
commit 236d628884
480 changed files with 5184 additions and 3591 deletions

View file

@ -21,6 +21,14 @@ addons:
build_command_prepend: "cmake ." build_command_prepend: "cmake ."
build_command: "make -j3" build_command: "make -j3"
branch_pattern: coverity_scan 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: before_install:
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./CI/before_install.linux.sh; fi - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./CI/before_install.linux.sh; fi
@ -30,8 +38,8 @@ before_script:
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then ./CI/before_script.osx.sh; fi - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then ./CI/before_script.osx.sh; fi
script: script:
- cd ./build - cd ./build
- if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then 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 - if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi
after_script: after_script:
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi
notifications: notifications:

View file

@ -39,6 +39,8 @@ Programmers
Eli2 Eli2
Emanuel Guével (potatoesmaster) Emanuel Guével (potatoesmaster)
eroen eroen
escondida
Evgeniy Mineev (sandstranger)
Fil Krynicki (filkry) Fil Krynicki (filkry)
Gašper Sedej Gašper Sedej
gugus/gus gugus/gus
@ -91,7 +93,6 @@ Programmers
Rohit Nirmal Rohit Nirmal
Roman Melnik (Kromgart) Roman Melnik (Kromgart)
Roman Proskuryakov (humbug) Roman Proskuryakov (humbug)
sandstranger
Sandy Carter (bwrsandman) Sandy Carter (bwrsandman)
Scott Howard Scott Howard
Sebastian Wick (swick) Sebastian Wick (swick)

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 0.35.0
------ ------

View file

@ -1,7 +1,12 @@
#!/bin/sh #!/bin/sh
export CXX=g++ if [ "${ANALYZE}" ]; then
export CC=gcc 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 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 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 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 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 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 sudo mkdir /usr/src/gtest/build
cd /usr/src/gtest/build cd /usr/src/gtest/build
sudo cmake .. -DBUILD_SHARED_LIBS=1 sudo cmake .. -DBUILD_SHARED_LIBS=1

View file

@ -2,4 +2,6 @@
mkdir build mkdir build
cd 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_MAJOR 0)
set(OPENMW_VERSION_MINOR 35) set(OPENMW_VERSION_MINOR 35)
set(OPENMW_VERSION_RELEASE 0) set(OPENMW_VERSION_RELEASE 1)
set(OPENMW_VERSION_COMMITHASH "") set(OPENMW_VERSION_COMMITHASH "")
set(OPENMW_VERSION_TAGHASH "") set(OPENMW_VERSION_TAGHASH "")
@ -98,43 +98,6 @@ endif()
# We probably support older versions than this. # We probably support older versions than this.
cmake_minimum_required(VERSION 2.6) 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 # Sound setup
set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE SWRESAMPLE AVRESAMPLE) set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE SWRESAMPLE AVRESAMPLE)
unset(FFMPEG_LIBRARIES CACHE) unset(FFMPEG_LIBRARIES CACHE)
@ -270,7 +233,8 @@ endif ()
endif(WIN32) endif(WIN32)
endif(OGRE_STATIC) 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} ${OGRE_INCLUDE_DIR}/Ogre ${OGRE_INCLUDE_DIR}/OGRE ${OGRE_INCLUDE_DIRS} ${OGRE_PLUGIN_INCLUDE_DIRS}
${OGRE_INCLUDE_DIR}/Overlay ${OGRE_Overlay_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Overlay ${OGRE_Overlay_INCLUDE_DIR}
${SDL2_INCLUDE_DIR} ${SDL2_INCLUDE_DIR}
@ -279,7 +243,7 @@ include_directories("."
${MYGUI_INCLUDE_DIRS} ${MYGUI_INCLUDE_DIRS}
${MYGUI_PLATFORM_INCLUDE_DIRS} ${MYGUI_PLATFORM_INCLUDE_DIRS}
${OPENAL_INCLUDE_DIR} ${OPENAL_INCLUDE_DIR}
${LIBS_DIR} ${BULLET_INCLUDE_DIRS}
) )
link_directories(${SDL2_LIBRARY_DIRS} ${Boost_LIBRARY_DIRS} ${OGRE_LIB_DIR} ${MYGUI_LIB_DIR}) link_directories(${SDL2_LIBRARY_DIRS} ${Boost_LIBRARY_DIRS} ${OGRE_LIB_DIR} ${MYGUI_LIB_DIR})
@ -379,6 +343,9 @@ configure_file(${OpenMW_SOURCE_DIR}/files/opencs.ini
configure_file(${OpenMW_SOURCE_DIR}/files/opencs/defaultfilters configure_file(${OpenMW_SOURCE_DIR}/files/opencs/defaultfilters
"${OpenMW_BINARY_DIR}/resources/defaultfilters" COPYONLY) "${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) if (NOT WIN32 AND NOT APPLE)
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.desktop configure_file(${OpenMW_SOURCE_DIR}/files/openmw.desktop
"${OpenMW_BINARY_DIR}/openmw.desktop") "${OpenMW_BINARY_DIR}/openmw.desktop")
@ -386,22 +353,22 @@ if (NOT WIN32 AND NOT APPLE)
"${OpenMW_BINARY_DIR}/openmw-cs.desktop") "${OpenMW_BINARY_DIR}/openmw-cs.desktop")
endif() endif()
# Compiler settings # CXX Compiler settings
if (CMAKE_COMPILER_IS_GNUCC) if (CMAKE_CXX_COMPILER_ID STREQUAL GNU OR CMAKE_CXX_COMPILER_ID STREQUAL Clang)
SET(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unused-parameter -Wno-reorder -std=c++98 -pedantic -Wno-long-long ${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unused-parameter -Wno-reorder -std=c++98 -pedantic -Wno-long-long")
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
OUTPUT_VARIABLE GCC_VERSION) OUTPUT_VARIABLE GCC_VERSION)
if ("${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 "-Wno-unused-but-set-parameter ${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-but-set-parameter")
endif("${GCC_VERSION}" VERSION_GREATER 4.6 OR "${GCC_VERSION}" VERSION_EQUAL 4.6) endif(CMAKE_CXX_COMPILER_ID STREQUAL GNU AND "${GCC_VERSION}" VERSION_GREATER 4.6 OR "${GCC_VERSION}" VERSION_EQUAL 4.6)
elseif (MSVC) elseif (MSVC)
# Enable link-time code generation globally for all linking # Enable link-time code generation globally for all linking
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG") 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_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG")
set(CMAKE_STATIC_LINKER_FLAGS_RELEASE "${CMAKE_STATIC_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) IF(NOT WIN32 AND NOT APPLE)
# Linux building # Linux building
@ -468,6 +435,8 @@ IF(NOT WIN32 AND NOT APPLE)
INSTALL(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw") 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}/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}/openmw.cfg.install" DESTINATION "${SYSCONFDIR}" RENAME "openmw.cfg" COMPONENT "openmw")
INSTALL(FILES "${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")
IF(BUILD_OPENCS) IF(BUILD_OPENCS)
INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION "${SYSCONFDIR}" COMPONENT "opencs") INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION "${SYSCONFDIR}" COMPONENT "opencs")
ENDIF(BUILD_OPENCS) ENDIF(BUILD_OPENCS)
@ -488,6 +457,7 @@ if(WIN32)
"${OpenMW_SOURCE_DIR}/Docs/license/DejaVu Font License.txt" "${OpenMW_SOURCE_DIR}/Docs/license/DejaVu Font License.txt"
"${OpenMW_BINARY_DIR}/settings-default.cfg" "${OpenMW_BINARY_DIR}/settings-default.cfg"
"${OpenMW_BINARY_DIR}/transparency-overrides.cfg" "${OpenMW_BINARY_DIR}/transparency-overrides.cfg"
"${OpenMW_BINARY_DIR}/gamecontrollerdb.txt"
"${OpenMW_BINARY_DIR}/Release/openmw.exe" "${OpenMW_BINARY_DIR}/Release/openmw.exe"
DESTINATION ".") DESTINATION ".")
@ -572,6 +542,10 @@ if(WIN32)
include(CPack) include(CPack)
endif(WIN32) endif(WIN32)
# Libs
include_directories(libs)
add_subdirectory(libs/openengine)
# Extern # Extern
#add_subdirectory (extern/shiny) #add_subdirectory (extern/shiny)
#add_subdirectory (extern/ogre-ffmpeg-videoplayer) #add_subdirectory (extern/ogre-ffmpeg-videoplayer)
@ -682,6 +656,7 @@ if (WIN32)
4193 # #pragma warning(pop) : no matching '#pragma warning(push)' 4193 # #pragma warning(pop) : no matching '#pragma warning(push)'
4251 # class 'XXXX' needs to have dll-interface to be used by clients of class 'YYYY' 4251 # class 'XXXX' needs to have dll-interface to be used by clients of class 'YYYY'
4275 # non dll-interface struct 'XXXX' used as base for dll-interface class 'YYYY' 4275 # non dll-interface struct 'XXXX' used as base for dll-interface class 'YYYY'
4315 # undocumented, 'this' pointer for member might not be aligned (OgreMemoryStlAllocator.h)
# caused by boost # caused by boost
4191 # 'type cast' : unsafe conversion (1.56, thread_primitives.hpp, normally off) 4191 # 'type cast' : unsafe conversion (1.56, thread_primitives.hpp, normally off)
@ -689,6 +664,7 @@ if (WIN32)
# OpenMW specific warnings # OpenMW specific warnings
4099 # Type mismatch, declared class or struct is defined with other type 4099 # Type mismatch, declared class or struct is defined with other type
4100 # Unreferenced formal parameter (-Wunused-parameter) 4100 # Unreferenced formal parameter (-Wunused-parameter)
4101 # Unreferenced local variable (-Wunused-variable)
4127 # Conditional expression is constant 4127 # Conditional expression is constant
4242 # Storing value in a variable of a smaller type, possible loss of data 4242 # Storing value in a variable of a smaller type, possible loss of data
4244 # Storing value of one type in variable of another (size_t in int, for example) 4244 # Storing value of one type in variable of another (size_t in int, for example)
@ -707,56 +683,23 @@ if (WIN32)
set(WARNINGS "${WARNINGS} /wd${d}") set(WARNINGS "${WARNINGS} /wd${d}")
endforeach(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 # boost::wave has a few issues with signed / unsigned conversions, so we suppress those here
set(SHINY_WARNINGS "${WARNINGS} /wd4245") set(SHINY_WARNINGS "${WARNINGS} /wd4245")
set_target_properties(shiny PROPERTIES COMPILE_FLAGS "${SHINY_WARNINGS} ${MT_BUILD}") set_target_properties(shiny PROPERTIES COMPILE_FLAGS "${SHINY_WARNINGS} ${MT_BUILD}")
# there's an unreferenced local variable in the ogre platform, suppress it
set(SHINY_OGRE_WARNINGS "${WARNINGS} /wd4101")
set_target_properties(shiny.OgrePlatform PROPERTIES COMPILE_FLAGS "${SHINY_OGRE_WARNINGS} ${MT_BUILD}")
set_target_properties(sdl4ogre PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
# oics uses tinyxml, which has an initialized but unused variable # oics uses tinyxml, which has an initialized but unused variable
set(OICS_WARNINGS "${WARNINGS} /wd4189") set(OICS_WARNINGS "${WARNINGS} /wd4189")
set_target_properties(oics PROPERTIES COMPILE_FLAGS "${OICS_WARNINGS} ${MT_BUILD}") set_target_properties(oics PROPERTIES COMPILE_FLAGS "${OICS_WARNINGS} ${MT_BUILD}")
set_target_properties(components PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
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) if (BUILD_OPENCS)
# QT triggers an informational warning that the object layout may differ when compiled with /vd2 # QT triggers an informational warning that the object layout may differ when compiled with /vd2
set(OPENCS_WARNINGS "${WARNINGS} ${MT_BUILD} /wd4435") set(OPENCS_WARNINGS "${WARNINGS} ${MT_BUILD} /wd4435")
set_target_properties(openmw-cs PROPERTIES COMPILE_FLAGS ${OPENCS_WARNINGS}) set_target_properties(openmw-cs PROPERTIES COMPILE_FLAGS ${OPENCS_WARNINGS})
endif (BUILD_OPENCS) endif (BUILD_OPENCS)
if (BUILD_MWINIIMPORTER)
set_target_properties(openmw-iniimporter PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
endif (BUILD_MWINIIMPORTER)
endif(MSVC) 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 # 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_RELEASE "/SUBSYSTEM:WINDOWS")
#set_target_properties(openmw PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS") #set_target_properties(openmw PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS")
@ -770,6 +713,7 @@ if (APPLE)
install(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) 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}/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}/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}/transparency-overrides.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
install(FILES "${OpenMW_BINARY_DIR}/opencs.ini" 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 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. 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) * License: GPL (see docs/license/GPL3.txt for more information)
* Website: http://www.openmw.org * Website: http://www.openmw.org
* IRC: #openmw on irc.freenode.net * IRC: #openmw on irc.freenode.net
@ -23,7 +23,7 @@ Getting Started
* [Testing the game](https://wiki.openmw.org/index.php?title=Testing) * [Testing the game](https://wiki.openmw.org/index.php?title=Testing)
* [How to contribute](https://wiki.openmw.org/index.php?title=Contribution_Wanted) * [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! * [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 The data path
------------- -------------
@ -68,9 +68,9 @@ Command line options
of the blacklist is enabled) of the blacklist is enabled)
--script-blacklist-use [=arg(=1)] (=1) --script-blacklist-use [=arg(=1)] (=1)
enable script blacklisting enable script blacklisting
--load-savegame arg load a save game file on game startup --load-savegame arg load a save game file on game startup
(specify an absolute filename or a (specify an absolute filename or a
filename relative to the current filename relative to the current
working directory) working directory)
--skip-menu [=arg(=1)] (=0) skip main menu on game startup --skip-menu [=arg(=1)] (=0) skip main menu on game startup
--new-game [=arg(=1)] (=0) run new game sequence (ignored if --new-game [=arg(=1)] (=0) run new game sequence (ignored if

View file

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

View file

@ -6,6 +6,9 @@
#include <boost/format.hpp> #include <boost/format.hpp>
namespace
{
void printAIPackage(ESM::AIPackage p) void printAIPackage(ESM::AIPackage p)
{ {
std::cout << " AI Type: " << aiTypeLabel(p.mType) 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 << " Duration: " << p.mWander.mDuration << std::endl;
std::cout << " Time of Day: " << (int)p.mWander.mTimeOfDay << std::endl; std::cout << " Time of Day: " << (int)p.mWander.mTimeOfDay << std::endl;
if (p.mWander.mShouldRepeat != 1) 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: "; std::cout << " Idle: ";
for (int i = 0; i != 8; i++) 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 { namespace EsmTool {
RecordBase * RecordBase *
@ -631,6 +654,8 @@ void Record<ESM::Creature>::print()
for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); ++sit) for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); ++sit)
std::cout << " Spell: " << *sit << std::endl; std::cout << " Spell: " << *sit << std::endl;
printTransport(mData.getTransport());
std::cout << " Artifical Intelligence: " << mData.mHasAI << std::endl; std::cout << " Artifical Intelligence: " << mData.mHasAI << std::endl;
std::cout << " AI Hello:" << (int)mData.mAiData.mHello << std::endl; std::cout << " AI Hello:" << (int)mData.mAiData.mHello << std::endl;
std::cout << " AI Fight:" << (int)mData.mAiData.mFight << 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) for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); ++sit)
std::cout << " Spell: " << *sit << std::endl; std::cout << " Spell: " << *sit << std::endl;
std::vector<ESM::NPC::Dest>::iterator dit; printTransport(mData.getTransport());
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;
}
std::cout << " Artifical Intelligence: " << mData.mHasAI << std::endl; std::cout << " Artifical Intelligence: " << mData.mHasAI << std::endl;
std::cout << " AI Hello:" << (int)mData.mAiData.mHello << std::endl; std::cout << " AI Hello:" << (int)mData.mAiData.mHello << std::endl;
@ -1253,7 +1265,7 @@ void Record<ESM::Spell>::print()
template<> template<>
void Record<ESM::StartScript>::print() 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; std::cout << "Start Data: " << mData.mData << std::endl;
} }

View file

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

View file

@ -553,7 +553,7 @@ public:
ESM::WeatherState weather; ESM::WeatherState weather;
weather.mCurrentWeather = toString(mGame.mGMDT.mCurrentWeather); weather.mCurrentWeather = toString(mGame.mGMDT.mCurrentWeather);
weather.mNextWeather = toString(mGame.mGMDT.mNextWeather); 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.mHour = mContext->mHour;
weather.mWindSpeed = 0.f; weather.mWindSpeed = 0.f;
weather.mTimePassed = 0.0; weather.mTimePassed = 0.0;

View file

@ -43,13 +43,17 @@ namespace ESSImport
float mMagicEffects[27]; // Effect attributes: https://wiki.openmw.org/index.php?title=Research:Magic#Effect_attributes float mMagicEffects[27]; // Effect attributes: https://wiki.openmw.org/index.php?title=Research:Magic#Effect_attributes
unsigned char mUnknown4[4]; unsigned char mUnknown4[4];
unsigned int mGoldPool; unsigned int mGoldPool;
unsigned char mUnknown5[4]; unsigned char mCountDown; // seen the same value as in ACSC.mCorpseClearCountdown, maybe
// this one is for respawning?
unsigned char mUnknown5[3];
}; };
struct ACSC struct ACSC
{ {
unsigned char mUnknown1[17]; unsigned char mUnknown1[17];
unsigned char mFlags; // ACSCFlags unsigned char mFlags; // ACSCFlags
unsigned char mUnknown2[94]; unsigned char mUnknown2[22];
unsigned char mCorpseClearCountdown; // hours?
unsigned char mUnknown3[71];
}; };
#pragma pack(pop) #pragma pack(pop)

View file

@ -43,7 +43,7 @@ namespace ESSImport
{ {
unsigned int deleted; unsigned int deleted;
esm.getHT(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")) if (esm.isNextSub("MVRF"))

View file

@ -14,10 +14,10 @@ namespace ESSImport
float scale; float scale;
esm.getHNOT(scale, "XSCL"); esm.getHNOT(scale, "XSCL");
// FIXME: use AiPackageList, need to fix getSubName()
while (esm.isNextSub("AI_W") || esm.isNextSub("AI_E") || esm.isNextSub("AI_T") || esm.isNextSub("AI_F") while (esm.isNextSub("AI_W") || esm.isNextSub("AI_E") || esm.isNextSub("AI_T") || esm.isNextSub("AI_F")
|| esm.isNextSub("AI_A")) || esm.isNextSub("AI_A"))
esm.skipHSub(); mAiPackages.add(esm);
mInventory.load(esm); mInventory.load(esm);
} }

View file

@ -2,6 +2,7 @@
#define OPENMW_ESSIMPORT_CREC_H #define OPENMW_ESSIMPORT_CREC_H
#include "importinventory.hpp" #include "importinventory.hpp"
#include <components/esm/aipackage.hpp>
namespace ESM namespace ESM
{ {
@ -17,6 +18,7 @@ namespace ESSImport
int mIndex; int mIndex;
Inventory mInventory; Inventory mInventory;
ESM::AIPackageList mAiPackages;
void load(ESM::ESMReader& esm); void load(ESM::ESMReader& esm);
}; };

View file

@ -9,10 +9,9 @@ namespace ESSImport
{ {
esm.getHNT(mNPDT, "NPDT"); esm.getHNT(mNPDT, "NPDT");
// FIXME: use AiPackageList, need to fix getSubName()
while (esm.isNextSub("AI_W") || esm.isNextSub("AI_E") || esm.isNextSub("AI_T") || esm.isNextSub("AI_F") while (esm.isNextSub("AI_W") || esm.isNextSub("AI_E") || esm.isNextSub("AI_T") || esm.isNextSub("AI_F")
|| esm.isNextSub("AI_A")) || esm.isNextSub("AI_A"))
esm.skipHSub(); mAiPackages.add(esm);
mInventory.load(esm); mInventory.load(esm);
} }

View file

@ -27,6 +27,7 @@ namespace ESSImport
} mNPDT; } mNPDT;
Inventory mInventory; Inventory mInventory;
ESM::AIPackageList mAiPackages;
void load(ESM::ESMReader &esm); void load(ESM::ESMReader &esm);
}; };

View file

@ -61,6 +61,7 @@ Launcher::MainDialog::MainDialog(QWidget *parent)
QString revision(OPENMW_VERSION_COMMITHASH); QString revision(OPENMW_VERSION_COMMITHASH);
QString tag(OPENMW_VERSION_TAGHASH); QString tag(OPENMW_VERSION_TAGHASH);
versionLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
if (!revision.isEmpty() && !tag.isEmpty()) if (!revision.isEmpty() && !tag.isEmpty())
{ {
if (revision == tag) { if (revision == tag) {
@ -238,24 +239,8 @@ void Launcher::MainDialog::changePage(QListWidgetItem *current, QListWidgetItem
current = previous; current = previous;
int currentIndex = iconWidget->row(current); int currentIndex = iconWidget->row(current);
// int previousIndex = iconWidget->row(previous);
pagesWidget->setCurrentIndex(currentIndex); pagesWidget->setCurrentIndex(currentIndex);
mSettingsPage->resetProgressBar();
// DataFilesPage *previousPage = dynamic_cast<DataFilesPage *>(pagesWidget->widget(previousIndex));
// DataFilesPage *currentPage = dynamic_cast<DataFilesPage *>(pagesWidget->widget(currentIndex));
// //special call to update/save data files page list view when it's displayed/hidden.
// if (previousPage)
// {
// if (previousPage->objectName() == "DataFilesPage")
// previousPage->saveSettings();
// }
// else if (currentPage)
// {
// if (currentPage->objectName() == "DataFilesPage")
// currentPage->loadSettings();
// }
} }
bool Launcher::MainDialog::setupLauncherSettings() bool Launcher::MainDialog::setupLauncherSettings()

View file

@ -39,6 +39,7 @@ Launcher::SettingsPage::SettingsPage(Files::ConfigurationManager &cfg,
mWizardInvoker = new ProcessInvoker(); mWizardInvoker = new ProcessInvoker();
mImporterInvoker = new ProcessInvoker(); mImporterInvoker = new ProcessInvoker();
resetProgressBar();
connect(mWizardInvoker->getProcess(), SIGNAL(started()), connect(mWizardInvoker->getProcess(), SIGNAL(started()),
this, SLOT(wizardStarted())); this, SLOT(wizardStarted()));
@ -94,7 +95,7 @@ Launcher::SettingsPage::~SettingsPage()
void Launcher::SettingsPage::on_wizardButton_clicked() void Launcher::SettingsPage::on_wizardButton_clicked()
{ {
saveSettings(); mMain->writeSettings();
if (!mWizardInvoker->startProcess(QLatin1String("openmw-wizard"), false)) if (!mWizardInvoker->startProcess(QLatin1String("openmw-wizard"), false))
return; return;
@ -102,7 +103,7 @@ void Launcher::SettingsPage::on_wizardButton_clicked()
void Launcher::SettingsPage::on_importerButton_clicked() void Launcher::SettingsPage::on_importerButton_clicked()
{ {
saveSettings(); mMain->writeSettings();
// Create the file if it doesn't already exist, else the importer will fail // Create the file if it doesn't already exist, else the importer will fail
QString path(QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str())); QString path(QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str()));
@ -141,8 +142,13 @@ void Launcher::SettingsPage::on_importerButton_clicked()
qDebug() << "arguments " << arguments; qDebug() << "arguments " << arguments;
// start the progress bar as a "bouncing ball"
progressBar->setMaximum(0);
progressBar->setValue(0);
if (!mImporterInvoker->startProcess(QLatin1String("openmw-iniimporter"), arguments, false)) if (!mImporterInvoker->startProcess(QLatin1String("openmw-iniimporter"), arguments, false))
return; {
resetProgressBar();
}
} }
void Launcher::SettingsPage::on_browseButton_clicked() void Launcher::SettingsPage::on_browseButton_clicked()
@ -197,38 +203,35 @@ void Launcher::SettingsPage::importerStarted()
void Launcher::SettingsPage::importerFinished(int exitCode, QProcess::ExitStatus exitStatus) void Launcher::SettingsPage::importerFinished(int exitCode, QProcess::ExitStatus exitStatus)
{ {
if (exitCode != 0 || exitStatus == QProcess::CrashExit) if (exitCode != 0 || exitStatus == QProcess::CrashExit)
return;
// Importer may have changed settings, so refresh
mMain->reloadSettings();
// Import selected data files from openmw.cfg
if (addonsCheckBox->isChecked())
{ {
// Because we've reloaded settings, the current content list matches content in OpenMW.cfg resetProgressBar();
QString oldContentListName = mLauncherSettings.getCurrentContentListName();
if (mProfileDialog->exec() == QDialog::Accepted)
{
// remove the current content list to prevent duplication
//... except, not allowed to delete the Default content list
if (oldContentListName.compare(DataFilesPage::mDefaultContentListName) != 0)
{
mLauncherSettings.removeContentList(oldContentListName);
}
const QString newContentListName(mProfileDialog->lineEdit()->text()); QMessageBox msgBox;
const QStringList files(mGameSettings.getContentList()); msgBox.setWindowTitle(tr("Importer finished"));
mLauncherSettings.setCurrentContentListName(newContentListName); msgBox.setStandardButtons(QMessageBox::Ok);
mLauncherSettings.setContentList(newContentListName, files); msgBox.setIcon(QMessageBox::Warning);
msgBox.setText(tr("Failed to import settings from INI file."));
msgBox.exec();
}
else
{
// indicate progress finished
progressBar->setMaximum(1);
progressBar->setValue(1);
// Make DataFiles Page load the new content list. // Importer may have changed settings, so refresh
mMain->reloadSettings(); mMain->reloadSettings();
}
} }
importerButton->setEnabled(true); importerButton->setEnabled(true);
} }
void Launcher::SettingsPage::resetProgressBar()
{
// set progress bar to 0 %
progressBar->reset();
}
void Launcher::SettingsPage::updateOkButton(const QString &text) void Launcher::SettingsPage::updateOkButton(const QString &text)
{ {
// We do this here because we need to access the profiles // We do this here because we need to access the profiles

View file

@ -29,6 +29,9 @@ namespace Launcher
void saveSettings(); void saveSettings();
bool loadSettings(); bool loadSettings();
/// set progress bar on page to 0%
void resetProgressBar();
private slots: private slots:
@ -57,7 +60,6 @@ namespace Launcher
MainDialog *mMain; MainDialog *mMain;
TextInputDialog *mProfileDialog; TextInputDialog *mProfileDialog;
}; };
} }

View file

@ -8,7 +8,8 @@
#include <sstream> #include <sstream>
#include <components/misc/stringops.hpp> #include <components/misc/stringops.hpp>
#include <boost/filesystem/path.hpp> #include <boost/version.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp> #include <boost/filesystem/fstream.hpp>
namespace bfs = boost::filesystem; namespace bfs = boost::filesystem;
@ -660,7 +661,7 @@ std::string MwIniImporter::numberToString(int n) {
return str.str(); return str.str();
} }
MwIniImporter::multistrmap MwIniImporter::loadIniFile(const std::string& filename) const { MwIniImporter::multistrmap MwIniImporter::loadIniFile(const boost::filesystem::path& filename) const {
std::cout << "load ini file: " << filename << std::endl; std::cout << "load ini file: " << filename << std::endl;
std::string section(""); std::string section("");
@ -719,7 +720,7 @@ MwIniImporter::multistrmap MwIniImporter::loadIniFile(const std::string& filenam
return map; return map;
} }
MwIniImporter::multistrmap MwIniImporter::loadCfgFile(const std::string& filename) { MwIniImporter::multistrmap MwIniImporter::loadCfgFile(const boost::filesystem::path& filename) {
std::cout << "load cfg file: " << filename << std::endl; std::cout << "load cfg file: " << filename << std::endl;
MwIniImporter::multistrmap map; MwIniImporter::multistrmap map;
@ -825,10 +826,14 @@ void MwIniImporter::importArchives(multistrmap &cfg, const multistrmap &ini) con
} }
} }
void MwIniImporter::importGameFiles(multistrmap &cfg, const multistrmap &ini) const { void MwIniImporter::importGameFiles(multistrmap &cfg, const multistrmap &ini, const boost::filesystem::path& iniFilename) const {
std::vector<std::string> contentFiles; std::vector<std::pair<std::time_t, std::string> > contentFiles;
std::string baseGameFile("Game Files:GameFile"); std::string baseGameFile("Game Files:GameFile");
std::string gameFile(""); std::string gameFile("");
std::time_t defaultTime = 0;
// assume the Game Files are all in a "Data Files" directory under the directory holding Morrowind.ini
const boost::filesystem::path gameFilesDir(iniFilename.parent_path() /= "Data Files");
multistrmap::const_iterator it = ini.begin(); multistrmap::const_iterator it = ini.begin();
for(int i=0; it != ini.end(); i++) { for(int i=0; it != ini.end(); i++) {
@ -845,18 +850,20 @@ void MwIniImporter::importGameFiles(multistrmap &cfg, const multistrmap &ini) co
Misc::StringUtils::toLower(filetype); Misc::StringUtils::toLower(filetype);
if(filetype.compare("esm") == 0 || filetype.compare("esp") == 0) { if(filetype.compare("esm") == 0 || filetype.compare("esp") == 0) {
contentFiles.push_back(*entry); boost::filesystem::path filepath(gameFilesDir);
filepath /= *entry;
contentFiles.push_back(std::make_pair(lastWriteTime(filepath, defaultTime), *entry));
} }
} }
gameFile = "";
} }
cfg.erase("content"); cfg.erase("content");
cfg.insert( std::make_pair("content", std::vector<std::string>() ) ); cfg.insert( std::make_pair("content", std::vector<std::string>() ) );
for(std::vector<std::string>::const_iterator it=contentFiles.begin(); it!=contentFiles.end(); ++it) { // this will sort files by time order first, then alphabetical (maybe), I suspect non ASCII filenames will be stuffed.
cfg["content"].push_back(*it); sort(contentFiles.begin(), contentFiles.end());
for(std::vector<std::pair<std::time_t, std::string> >::const_iterator it=contentFiles.begin(); it!=contentFiles.end(); ++it) {
cfg["content"].push_back(it->second);
} }
} }
@ -873,3 +880,27 @@ void MwIniImporter::setInputEncoding(const ToUTF8::FromType &encoding)
{ {
mEncoding = encoding; mEncoding = encoding;
} }
std::time_t MwIniImporter::lastWriteTime(const boost::filesystem::path& filename, std::time_t defaultTime)
{
std::time_t writeTime(defaultTime);
if (boost::filesystem::exists(filename))
{
// FixMe: remove #if when Boost dependency for Linux builds updated
// This allows Linux to build until then
#if (BOOST_VERSION >= 104800)
// need to resolve any symlinks so that we get time of file, not symlink
boost::filesystem::path resolved = boost::filesystem::canonical(filename);
#else
boost::filesystem::path resolved = filename;
#endif
writeTime = boost::filesystem::last_write_time(resolved);
std::cout << "content file: " << resolved << " timestamp = (" << writeTime <<
") " << asctime(localtime(&writeTime)) << std::endl;
}
else
{
std::cout << "content file: " << filename << " not found" << std::endl;
}
return writeTime;
}

View file

@ -6,6 +6,7 @@
#include <vector> #include <vector>
#include <exception> #include <exception>
#include <iosfwd> #include <iosfwd>
#include <boost/filesystem/path.hpp>
#include <components/to_utf8/to_utf8.hpp> #include <components/to_utf8/to_utf8.hpp>
@ -17,17 +18,22 @@ class MwIniImporter {
MwIniImporter(); MwIniImporter();
void setInputEncoding(const ToUTF8::FromType& encoding); void setInputEncoding(const ToUTF8::FromType& encoding);
void setVerbose(bool verbose); void setVerbose(bool verbose);
multistrmap loadIniFile(const std::string& filename) const; multistrmap loadIniFile(const boost::filesystem::path& filename) const;
static multistrmap loadCfgFile(const std::string& filename); static multistrmap loadCfgFile(const boost::filesystem::path& filename);
void merge(multistrmap &cfg, const multistrmap &ini) const; void merge(multistrmap &cfg, const multistrmap &ini) const;
void mergeFallback(multistrmap &cfg, const multistrmap &ini) const; void mergeFallback(multistrmap &cfg, const multistrmap &ini) const;
void importGameFiles(multistrmap &cfg, const multistrmap &ini) const; void importGameFiles(multistrmap &cfg, const multistrmap &ini,
const boost::filesystem::path& iniFilename) const;
void importArchives(multistrmap &cfg, const multistrmap &ini) const; void importArchives(multistrmap &cfg, const multistrmap &ini) const;
static void writeToFile(std::ostream &out, const multistrmap &cfg); static void writeToFile(std::ostream &out, const multistrmap &cfg);
private: private:
static void insertMultistrmap(multistrmap &cfg, const std::string& key, const std::string& value); static void insertMultistrmap(multistrmap &cfg, const std::string& key, const std::string& value);
static std::string numberToString(int n); static std::string numberToString(int n);
/// \return file's "last modified time", used in original MW to determine plug-in load order
static std::time_t lastWriteTime(const boost::filesystem::path& filename, std::time_t defaultTime);
bool mVerbose; bool mVerbose;
strmap mMergeMap; strmap mMergeMap;
std::vector<std::string> mMergeFallback; std::vector<std::string> mMergeFallback;

View file

@ -93,8 +93,8 @@ int wmain(int argc, wchar_t *wargv[]) {
bpo::notify(vm); bpo::notify(vm);
std::string iniFile = vm["ini"].as<std::string>(); boost::filesystem::path iniFile(vm["ini"].as<std::string>());
std::string cfgFile = vm["cfg"].as<std::string>(); boost::filesystem::path cfgFile(vm["cfg"].as<std::string>());
// if no output is given, write back to cfg file // if no output is given, write back to cfg file
std::string outputFile(vm["output"].as<std::string>()); std::string outputFile(vm["output"].as<std::string>());
@ -110,7 +110,7 @@ int wmain(int argc, wchar_t *wargv[]) {
std::cerr << "cfg file does not exist" << std::endl; std::cerr << "cfg file does not exist" << std::endl;
MwIniImporter importer; MwIniImporter importer;
importer.setVerbose(vm.count("verbose")); importer.setVerbose(vm.count("verbose") != 0);
// Font encoding settings // Font encoding settings
std::string encoding(vm["encoding"].as<std::string>()); std::string encoding(vm["encoding"].as<std::string>());
@ -123,7 +123,7 @@ int wmain(int argc, wchar_t *wargv[]) {
importer.mergeFallback(cfg, ini); importer.mergeFallback(cfg, ini);
if(vm.count("game-files")) { if(vm.count("game-files")) {
importer.importGameFiles(cfg, ini); importer.importGameFiles(cfg, ini, iniFile);
} }
if(!vm.count("no-archives")) { if(!vm.count("no-archives")) {

View file

@ -5,7 +5,7 @@ set (OPENCS_SRC main.cpp
opencs_units (. editor) opencs_units (. editor)
opencs_units (model/doc opencs_units (model/doc
document operation saving documentmanager loader runner document operation saving documentmanager loader runner operationholder
) )
opencs_units_noqt (model/doc opencs_units_noqt (model/doc
@ -40,6 +40,7 @@ opencs_units (model/tools
opencs_units_noqt (model/tools opencs_units_noqt (model/tools
mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck
birthsigncheck spellcheck referencecheck referenceablecheck scriptcheck bodypartcheck birthsigncheck spellcheck referencecheck referenceablecheck scriptcheck bodypartcheck
startscriptcheck
) )
@ -164,7 +165,8 @@ qt4_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI})
qt4_wrap_cpp(OPENCS_MOC_SRC ${OPENCS_HDR_QT}) qt4_wrap_cpp(OPENCS_MOC_SRC ${OPENCS_HDR_QT})
qt4_add_resources(OPENCS_RES_SRC ${OPENCS_RES}) 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) if(APPLE)
set (OPENCS_MAC_ICON ${CMAKE_SOURCE_DIR}/files/mac/openmw-cs.icns) set (OPENCS_MAC_ICON ${CMAKE_SOURCE_DIR}/files/mac/openmw-cs.icns)
@ -174,7 +176,6 @@ endif(APPLE)
add_executable(openmw-cs add_executable(openmw-cs
MACOSX_BUNDLE MACOSX_BUNDLE
${OENGINE_BULLET}
${OPENCS_SRC} ${OPENCS_SRC}
${OPENCS_UI_HDR} ${OPENCS_UI_HDR}
${OPENCS_MOC_SRC} ${OPENCS_MOC_SRC}
@ -198,6 +199,7 @@ if(APPLE)
endif(APPLE) endif(APPLE)
target_link_libraries(openmw-cs target_link_libraries(openmw-cs
${OENGINE_LIBRARY}
${OGRE_LIBRARIES} ${OGRE_LIBRARIES}
${OGRE_Overlay_LIBRARIES} ${OGRE_Overlay_LIBRARIES}
${OGRE_STATIC_PLUGINS} ${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::transform (ids.begin(), ids.end(), list.begin()+size, Misc::StringUtils::lowerCase);
std::sort (list.begin(), list.end()); std::sort (list.begin(), list.end());
} }

View file

@ -2252,7 +2252,8 @@ CSMDoc::Document::Document (const VFS::Manager* vfs, const Files::ConfigurationM
mTools (*this), mResDir(resDir), mTools (*this), mResDir(resDir),
mProjectPath ((configuration.getUserDataPath() / "projects") / mProjectPath ((configuration.getUserDataPath() / "projects") /
(savePath.filename().string() + ".project")), (savePath.filename().string() + ".project")),
mSaving (*this, mProjectPath, encoding), mSavingOperation (*this, mProjectPath, encoding),
mSaving (&mSavingOperation),
mRunner (mProjectPath) mRunner (mProjectPath)
{ {
if (mContentFiles.empty()) if (mContentFiles.empty())

View file

@ -20,6 +20,7 @@
#include "saving.hpp" #include "saving.hpp"
#include "blacklist.hpp" #include "blacklist.hpp"
#include "runner.hpp" #include "runner.hpp"
#include "operationholder.hpp"
class QAbstractItemModel; class QAbstractItemModel;
@ -38,7 +39,7 @@ namespace ESM
namespace Files namespace Files
{ {
class ConfigurationManager; struct ConfigurationManager;
} }
namespace CSMWorld namespace CSMWorld
@ -61,7 +62,8 @@ namespace CSMDoc
CSMWorld::Data mData; CSMWorld::Data mData;
CSMTools::Tools mTools; CSMTools::Tools mTools;
boost::filesystem::path mProjectPath; boost::filesystem::path mProjectPath;
Saving mSaving; Saving mSavingOperation;
OperationHolder mSaving;
boost::filesystem::path mResDir; boost::filesystem::path mResDir;
Blacklist mBlacklist; Blacklist mBlacklist;
Runner mRunner; Runner mRunner;

View file

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

View file

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

View file

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

View file

@ -3,7 +3,8 @@
#include <vector> #include <vector>
#include <QThread> #include <QObject>
#include <QTimer>
namespace CSMWorld namespace CSMWorld
{ {
@ -14,7 +15,7 @@ namespace CSMDoc
{ {
class Stage; class Stage;
class Operation : public QThread class Operation : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -27,6 +28,8 @@ namespace CSMDoc
int mOrdered; int mOrdered;
bool mFinalAlways; bool mFinalAlways;
bool mError; bool mError;
bool mConnected;
QTimer *mTimer;
void prepareStages(); void prepareStages();
@ -38,8 +41,6 @@ namespace CSMDoc
virtual ~Operation(); virtual ~Operation();
virtual void run();
void appendStage (Stage *stage); void appendStage (Stage *stage);
///< The ownership of \a stage is transferred to *this. ///< The ownership of \a stage is transferred to *this.
/// ///
@ -60,6 +61,8 @@ namespace CSMDoc
void abort(); void abort();
void run();
private slots: private slots:
void executeStage(); 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 <QTemporaryFile>
#include <QTextStream> #include <QTextStream>
#include "operation.hpp" #include "operationholder.hpp"
CSMDoc::Runner::Runner (const boost::filesystem::path& projectPath) CSMDoc::Runner::Runner (const boost::filesystem::path& projectPath)
: mRunning (false), mStartup (0), mProjectPath (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) : QObject (runner), mRunner (runner)
{ {
connect (operation, SIGNAL (done (int, bool)), this, SLOT (saveDone (int, bool))); connect (operation, SIGNAL (done (int, bool)), this, SLOT (saveDone (int, bool)));

View file

@ -16,6 +16,8 @@ class QTemporaryFile;
namespace CSMDoc namespace CSMDoc
{ {
class OperationHolder;
class Runner : public QObject class Runner : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -74,7 +76,7 @@ namespace CSMDoc
public: public:
/// *this attaches itself to runner /// *this attaches itself to runner
SaveWatcher (Runner *runner, Operation *operation); SaveWatcher (Runner *runner, OperationHolder *operation);
private slots: 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> > appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::MagicEffect> >
(mDocument.getData().getMagicEffects(), mState)); (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, false));
appendStage (new WriteDialogueCollectionStage (mDocument, mState, true)); 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 WritePathgridCollectionStage (mDocument, mState));
appendStage (new WriteLandCollectionStage (mDocument, mState));
appendStage (new WriteLandTextureCollectionStage (mDocument, mState));
// close file and clean up // close file and clean up
appendStage (new CloseSaveStage (mState)); appendStage (new CloseSaveStage (mState));
appendStage (new FinalSavingStage (mDocument, 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, CSMDoc::WriteDialogueCollectionStage::WriteDialogueCollectionStage (Document& document,
SavingState& state, bool journal) SavingState& state, bool journal)
: mDocument (document), mState (state), : mState (state),
mTopics (journal ? document.getData().getJournals() : document.getData().getTopics()), mTopics (journal ? document.getData().getJournals() : document.getData().getTopics()),
mInfos (journal ? document.getData().getJournalInfos() : document.getData().getTopicInfos()) 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) CSMDoc::CloseSaveStage::CloseSaveStage (SavingState& state)
: mState (state) : mState (state)
{} {}

View file

@ -7,6 +7,8 @@
#include "../world/idcollection.hpp" #include "../world/idcollection.hpp"
#include "../world/scope.hpp" #include "../world/scope.hpp"
#include <components/esm/defs.hpp>
#include "savingstate.hpp" #include "savingstate.hpp"
namespace ESM namespace ESM
@ -103,8 +105,15 @@ namespace CSMDoc
if (state==CSMWorld::RecordBase::State_Modified || if (state==CSMWorld::RecordBase::State_Modified ||
state==CSMWorld::RecordBase::State_ModifiedOnly) state==CSMWorld::RecordBase::State_ModifiedOnly)
{ {
mState.getWriter().startRecord (mCollection.getRecord (stage).mModified.sRecordId); // FIXME: A quick Workaround to support records which should not write
mState.getWriter().writeHNCString ("NAME", mCollection.getId (stage)); // 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()); mCollection.getRecord (stage).mModified.save (mState.getWriter());
mState.getWriter().endRecord (mCollection.getRecord (stage).mModified.sRecordId); mState.getWriter().endRecord (mCollection.getRecord (stage).mModified.sRecordId);
} }
@ -117,7 +126,6 @@ namespace CSMDoc
class WriteDialogueCollectionStage : public Stage class WriteDialogueCollectionStage : public Stage
{ {
Document& mDocument;
SavingState& mState; SavingState& mState;
const CSMWorld::IdCollection<ESM::Dialogue>& mTopics; const CSMWorld::IdCollection<ESM::Dialogue>& mTopics;
CSMWorld::InfoCollection& mInfos; CSMWorld::InfoCollection& mInfos;
@ -200,6 +208,40 @@ namespace CSMDoc
///< Messages resulting from this stage will be appended to \a messages. ///< 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 class CloseSaveStage : public Stage
{ {
SavingState& mState; SavingState& mState;

View file

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

View file

@ -12,4 +12,4 @@ bool CSMFilter::BooleanNode::test (const CSMWorld::IdTableBase& table, int row,
std::string CSMFilter::BooleanNode::toString (bool numericColumns) const std::string CSMFilter::BooleanNode::toString (bool numericColumns) const
{ {
return mTrue ? "true" : "false"; 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() {} 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 const std::map<int, int>& columns) const
{ {
return !getChild().test (table, row, columns); return !getChild().test (table, row, columns);
} }

View file

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

View file

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

View file

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

View file

@ -41,4 +41,4 @@ void CSMTools::BirthsignCheckStage::perform (int stage, CSMDoc::Messages& messag
/// \todo test if the texture exists /// \todo test if the texture exists
/// \todo check data members that can't be edited in the table view /// \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, messages.push_back (std::make_pair (id,
ESM::Skill::indexToId (iter->first) + " is listed more than once")); 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 || if (mIdCollection.searchId (mIds.at (stage))==-1 ||
mIdCollection.getRecord (mIds.at (stage)).isDeleted()) mIdCollection.getRecord (mIds.at (stage)).isDeleted())
messages.add (mCollectionId, "Missing mandatory record: " + mIds.at (stage)); 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); performFinal (messages);
else else
performPerRecord (stage, messages); 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 object have owner, check if that owner reference is valid
if (!cellRef.mOwner.empty() && mReferencables.searchId(cellRef.mOwner) == -1) if (!cellRef.mOwner.empty() && mReferencables.searchId(cellRef.mOwner) == -1)
messages.push_back(std::make_pair(id, " has non existing owner " + cellRef.mOwner)); 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 // Check item's faction rank
if (hasFaction && cellRef.mFactionRank < -1) 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) 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 door have destination cell, check if that reference is valid
if (!cellRef.mDestCell.empty()) 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 test that the ID in mSleeplist exists
/// \todo check data members that can't be edited in the table view /// \todo check data members that can't be edited in the table view
} }

View file

@ -78,4 +78,4 @@ const CSMWorld::UniversalId& CSMTools::ReportModel::getUniversalId (int row) con
std::string CSMTools::ReportModel::getHint (int row) const std::string CSMTools::ReportModel::getHint (int row) const
{ {
return mRows.at (row).second.second; return mRows.at (row).second.second;
} }

View file

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

View file

@ -39,4 +39,4 @@ void CSMTools::SkillCheckStage::perform (int stage, CSMDoc::Messages& messages)
if (skill.mDescription.empty()) if (skill.mDescription.empty())
messages.push_back (std::make_pair (id, skill.mId + " has an empty description")); 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")); messages.push_back (std::make_pair (id, "Maximum range larger than minimum range"));
/// \todo check, if the sound file exists /// \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")); 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 /// \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,32 @@
#include "scriptcheck.hpp" #include "scriptcheck.hpp"
#include "bodypartcheck.hpp" #include "bodypartcheck.hpp"
#include "referencecheck.hpp" #include "referencecheck.hpp"
#include "startscriptcheck.hpp"
CSMDoc::Operation *CSMTools::Tools::get (int type) CSMDoc::OperationHolder *CSMTools::Tools::get (int type)
{ {
switch (type) switch (type)
{ {
case CSMDoc::State_Verifying: return mVerifier; case CSMDoc::State_Verifying: return &mVerifier;
} }
return 0; 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); 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 (progress (int, int, int)), this, SIGNAL (progress (int, int, int)));
connect (mVerifier, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool))); connect (&mVerifier, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool)));
connect (mVerifier, connect (&mVerifier,
SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)), 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))); this, SLOT (verifierMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)));
@ -58,48 +59,49 @@ CSMDoc::Operation *CSMTools::Tools::getVerifier()
mandatoryIds.push_back ("GameHour"); mandatoryIds.push_back ("GameHour");
mandatoryIds.push_back ("Month"); mandatoryIds.push_back ("Month");
mandatoryIds.push_back ("PCRace"); mandatoryIds.push_back ("PCRace");
mandatoryIds.push_back ("PCVampire");
mandatoryIds.push_back ("PCWerewolf");
mandatoryIds.push_back ("PCYear");
mVerifier->appendStage (new MandatoryIdStage (mData.getGlobals(), mVerifierOperation->appendStage (new MandatoryIdStage (mData.getGlobals(),
CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Globals), mandatoryIds)); 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( new BodyPartCheckStage(
mData.getBodyParts(), mData.getBodyParts(),
mData.getResources( mData.getResources(
CSMWorld::UniversalId( CSMWorld::UniversalId::Type_Meshes )), CSMWorld::UniversalId( CSMWorld::UniversalId::Type_Meshes )),
mData.getRaces() )); mData.getRaces() ));
mVerifier.setOperation (mVerifierOperation);
} }
return mVerifier; return &mVerifier;
} }
CSMTools::Tools::Tools (CSMDoc::Document& document) CSMTools::Tools::Tools (CSMDoc::Document& document)
: mDocument (document), mData (document.getData()), mVerifier (0), mNextReportNumber (0) : mDocument (document), mData (document.getData()), mVerifierOperation (0), mNextReportNumber (0)
{ {
// index 0: load error log // index 0: load error log
mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel)); mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel));
@ -108,7 +110,11 @@ CSMTools::Tools::Tools (CSMDoc::Document& document)
CSMTools::Tools::~Tools() CSMTools::Tools::~Tools()
{ {
delete mVerifier; if (mVerifierOperation)
{
mVerifier.abortAndWait();
delete mVerifierOperation;
}
for (std::map<int, ReportModel *>::iterator iter (mReports.begin()); iter!=mReports.end(); ++iter) for (std::map<int, ReportModel *>::iterator iter (mReports.begin()); iter!=mReports.end(); ++iter)
delete iter->second; delete iter->second;
@ -126,7 +132,7 @@ CSMWorld::UniversalId CSMTools::Tools::runVerifier()
void CSMTools::Tools::abortOperation (int type) void CSMTools::Tools::abortOperation (int type)
{ {
if (CSMDoc::Operation *operation = get (type)) if (CSMDoc::OperationHolder *operation = get (type))
operation->abort(); operation->abort();
} }
@ -141,7 +147,7 @@ int CSMTools::Tools::getRunningOperations() const
int result = 0; int result = 0;
for (int i=0; sOperations[i]!=-1; ++i) 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()) if (operation->isRunning())
result |= sOperations[i]; result |= sOperations[i];

View file

@ -5,6 +5,8 @@
#include <map> #include <map>
#include "../doc/operationholder.hpp"
namespace CSMWorld namespace CSMWorld
{ {
class Data; class Data;
@ -27,7 +29,8 @@ namespace CSMTools
CSMDoc::Document& mDocument; CSMDoc::Document& mDocument;
CSMWorld::Data& mData; CSMWorld::Data& mData;
CSMDoc::Operation *mVerifier; CSMDoc::Operation *mVerifierOperation;
CSMDoc::OperationHolder mVerifier;
std::map<int, ReportModel *> mReports; std::map<int, ReportModel *> mReports;
int mNextReportNumber; int mNextReportNumber;
std::map<int, int> mActiveReports; // type, report number std::map<int, int> mActiveReports; // type, report number
@ -36,12 +39,12 @@ namespace CSMTools
Tools (const Tools&); Tools (const Tools&);
Tools& operator= (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. ///< 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. ///< Returns a 0-pointer, if operation hasn't been used yet.
public: public:

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"); throw std::logic_error ("invalid column index");
return index; return index;
} }

View file

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

View file

@ -22,4 +22,4 @@ std::string CSMWorld::ColumnBase::getTitle() const
int CSMWorld::ColumnBase::getId() const int CSMWorld::ColumnBase::getId() const
{ {
return mColumnId; return mColumnId;
} }

View file

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

View file

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

View file

@ -20,7 +20,7 @@ namespace CSMWorld
{ {
class IdTable; class IdTable;
class IdTable; class IdTable;
class RecordBase; struct RecordBase;
class ModifyCommand : public QUndoCommand 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 RecordStateColumn<Pathgrid>);
mPathgrids.addColumn (new FixedRecordTypeColumn<Pathgrid> (UniversalId::Type_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 StringIdColumn<CellRef> (true));
mRefs.addColumn (new RecordStateColumn<CellRef>); mRefs.addColumn (new RecordStateColumn<CellRef>);
mRefs.addColumn (new FixedRecordTypeColumn<CellRef> (UniversalId::Type_Reference)); 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 (&mSoundGens), UniversalId::Type_SoundGen);
addModel (new IdTable (&mMagicEffects), UniversalId::Type_MagicEffect); addModel (new IdTable (&mMagicEffects), UniversalId::Type_MagicEffect);
addModel (new IdTable (&mPathgrids), UniversalId::Type_Pathgrid); addModel (new IdTable (&mPathgrids), UniversalId::Type_Pathgrid);
addModel (new IdTable (&mStartScripts), UniversalId::Type_StartScript);
addModel (new IdTable (&mReferenceables, IdTable::Feature_Preview), addModel (new IdTable (&mReferenceables, IdTable::Feature_Preview),
UniversalId::Type_Referenceable); UniversalId::Type_Referenceable);
addModel (new IdTable (&mRefs, IdTable::Feature_ViewCell | IdTable::Feature_Preview), UniversalId::Type_Reference); addModel (new IdTable (&mRefs, IdTable::Feature_ViewCell | IdTable::Feature_Preview), UniversalId::Type_Reference);
@ -620,6 +625,16 @@ CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& CSMWorld::Data::getPathgrids()
return mPathgrids; 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 const CSMWorld::Resources& CSMWorld::Data::getResources (const UniversalId& id) const
{ {
return mResourcesManager.get (id.getType()); return mResourcesManager.get (id.getType());
@ -724,6 +739,7 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages)
case ESM::REC_SNDG: mSoundGens.load (*mReader, mBase); break; case ESM::REC_SNDG: mSoundGens.load (*mReader, mBase); break;
case ESM::REC_MGEF: mMagicEffects.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_PGRD: mPathgrids.load (*mReader, mBase); break;
case ESM::REC_SSCR: mStartScripts.load (*mReader, mBase); break;
case ESM::REC_LTEX: mLandTextures.load (*mReader, mBase); break; case ESM::REC_LTEX: mLandTextures.load (*mReader, mBase); break;
@ -734,7 +750,7 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages)
if (index!=-1 && !mBase) if (index!=-1 && !mBase)
mLand.getRecord (index).mModified.mLand->loadData ( mLand.getRecord (index).mModified.mLand->loadData (
ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | ESM::Land::DATA_VCLR | ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | ESM::Land::DATA_VCLR |
ESM::Land::DATA_VTEX); ESM::Land::DATA_VTEX | ESM::Land::DATA_WNAM);
break; break;
} }

View file

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

View file

@ -10,7 +10,7 @@
namespace CSMWorld namespace CSMWorld
{ {
class CollectionBase; class CollectionBase;
class RecordBase; struct RecordBase;
class IdTable : public IdTableBase class IdTable : public IdTableBase
{ {

View file

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

View file

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

View file

@ -6,7 +6,7 @@
namespace ESM namespace ESM
{ {
class Dialogue; struct Dialogue;
} }
namespace CSMWorld namespace CSMWorld
@ -22,7 +22,7 @@ namespace CSMWorld
void load (const Info& record, bool base); 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) ///< Return index for record \a id or -1 (if not present; deleted records are considered)
/// ///
/// \param id info ID without topic prefix /// \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 bool CSMWorld::RecordBase::isModified() const
{ {
return mState==State_Modified || mState==State_ModifiedOnly; return mState==State_Modified || mState==State_ModifiedOnly;
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -470,8 +470,7 @@ void CSMWorld::RefIdCollection::cloneRecord(const std::string& origin,
const std::string& destination, const std::string& destination,
const CSMWorld::UniversalId::Type type) const CSMWorld::UniversalId::Type type)
{ {
std::auto_ptr<RecordBase> newRecord(mData.getRecord(mData.searchId(origin)).clone()); std::auto_ptr<RecordBase> newRecord(mData.getRecord(mData.searchId(origin)).modifiedCopy());
newRecord->mState = RecordBase::State_ModifiedOnly;
mAdapters.find(type)->second->setId(*newRecord, destination); mAdapters.find(type)->second->setId(*newRecord, destination);
mData.insertRecord(*newRecord, type, 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. // columns we are interested in. If not we can exit the function here and avoid all updating.
addCells (topLeft.row(), bottomRight.row()); addCells (topLeft.row(), bottomRight.row());
} }

View file

@ -143,4 +143,4 @@ std::pair<CSMWorld::UniversalId, std::string> CSMWorld::ResourceTable::view (int
bool CSMWorld::ResourceTable::isDeleted (const std::string& id) const bool CSMWorld::ResourceTable::isDeleted (const std::string& id) const
{ {
return false; return false;
} }

View file

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

View file

@ -120,4 +120,4 @@ void CSMWorld::ScriptContext::clear()
mIds.clear(); mIds.clear();
mIdsUpdated = false; mIdsUpdated = false;
mLocals.clear(); 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_SoundGens, "Sound Generators", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MagicEffects, "Magic Effects", 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_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 { 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_SoundGen, "Sound Generator", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MagicEffect, "Magic Effect", 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_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 { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
}; };

View file

@ -128,6 +128,8 @@ namespace CSMWorld
Type_MagicEffect, Type_MagicEffect,
Type_Pathgrids, Type_Pathgrids,
Type_Pathgrid, Type_Pathgrid,
Type_StartScripts,
Type_StartScript,
Type_RunLog Type_RunLog
}; };

View file

@ -5,6 +5,7 @@
#include <string> #include <string>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/algorithm/string/case_conv.hpp>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QLabel> #include <QLabel>
@ -72,8 +73,11 @@ void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon)
{ {
boost::filesystem::path path (name.toUtf8().data()); boost::filesystem::path path (name.toUtf8().data());
bool isLegacyPath = (path.extension() == ".esm" || std::string extension = path.extension().string();
path.extension() == ".esp"); boost::algorithm::to_lower(extension);
bool isLegacyPath = (extension == ".esm" ||
extension == ".esp");
bool isFilePathChanged = (path.parent_path().string() != mLocalData.string()); bool isFilePathChanged = (path.parent_path().string() != mLocalData.string());

View file

@ -147,17 +147,19 @@ void CSVDoc::FileDialog::slotUpdateAcceptButton(int)
void CSVDoc::FileDialog::slotUpdateAcceptButton(const QString &name, bool) void CSVDoc::FileDialog::slotUpdateAcceptButton(const QString &name, bool)
{ {
bool success = (mSelector->selectedFiles().size() > 0); bool success = !mSelector->selectedFiles().empty();
bool isNew = (mAction == ContentAction_New); bool isNew = (mAction == ContentAction_New);
if (isNew) if (isNew)
success = success && !(name.isEmpty()); success = success && !(name.isEmpty());
else else if (success)
{ {
ContentSelectorModel::EsmFile *file = mSelector->selectedFiles().back(); ContentSelectorModel::EsmFile *file = mSelector->selectedFiles().back();
mAdjusterWidget->setName (file->filePath(), !file->isGameFile()); mAdjusterWidget->setName (file->filePath(), !file->isGameFile());
} }
else
mAdjusterWidget->setName ("", true);
ui.projectButtonBox->button (QDialogButtonBox::Ok)->setEnabled (success); ui.projectButtonBox->button (QDialogButtonBox::Ok)->setEnabled (success);
} }

View file

@ -90,4 +90,4 @@ void CSVDoc::GlobalDebugProfileMenu::profileChanged (const QModelIndex& topLeft,
void CSVDoc::GlobalDebugProfileMenu::actionTriggered (QAction *action) void CSVDoc::GlobalDebugProfileMenu::actionTriggered (QAction *action)
{ {
emit triggered (std::string (action->text().toUtf8().constData())); emit triggered (std::string (action->text().toUtf8().constData()));
} }

View file

@ -20,7 +20,7 @@ void CSVDoc::LoadingDocument::closeEvent (QCloseEvent *event)
CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document)
: mDocument (document), mAborted (false), mMessages (0), mTotalRecords (0) : mDocument (document), mAborted (false), mMessages (0), mTotalRecords (0)
{ {
setWindowTitle (("Opening " + document->getSavePath().filename().string()).c_str()); setWindowTitle (QString::fromUtf8((std::string("Opening ") + document->getSavePath().filename().string()).c_str()));
setMinimumWidth (400); setMinimumWidth (400);

View file

@ -17,4 +17,4 @@ CSVDoc::RunLogSubView::RunLogSubView (const CSMWorld::UniversalId& id,
void CSVDoc::RunLogSubView::setEditLock (bool locked) void CSVDoc::RunLogSubView::setEditLock (bool locked)
{ {
// ignored since this SubView does not have editing // ignored since this SubView does not have editing
} }

View file

@ -96,7 +96,7 @@ QWidget *CSVDoc::StartupDialogue::createTools()
CSVDoc::StartupDialogue::StartupDialogue() : mWidth (0), mColumn (2) CSVDoc::StartupDialogue::StartupDialogue() : mWidth (0), mColumn (2)
{ {
setWindowTitle ("Open CS"); setWindowTitle ("OpenMW-CS");
QVBoxLayout *layout = new QVBoxLayout (this); QVBoxLayout *layout = new QVBoxLayout (this);

View file

@ -26,7 +26,7 @@ void CSVDoc::SubView::updateUserSetting (const QString &, const QStringList &)
void CSVDoc::SubView::setUniversalId (const CSMWorld::UniversalId& id) void CSVDoc::SubView::setUniversalId (const CSMWorld::UniversalId& id)
{ {
mUniversalId = id; mUniversalId = id;
setWindowTitle (mUniversalId.toString().c_str()); setWindowTitle (QString::fromUtf8(mUniversalId.toString().c_str()));
} }
void CSVDoc::SubView::closeEvent (QCloseEvent *event) void CSVDoc::SubView::closeEvent (QCloseEvent *event)

View file

@ -35,4 +35,4 @@ CSVDoc::SubView *CSVDoc::SubViewFactoryManager::makeSubView (const CSMWorld::Uni
throw std::runtime_error ("Failed to create a sub view for: " + id.toString()); throw std::runtime_error ("Failed to create a sub view for: " + id.toString());
return iter->second->makeSubView (id, document); return iter->second->makeSubView (id, document);
} }

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