diff --git a/CHANGELOG.md b/CHANGELOG.md index 6eee39a95..297b8e9d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,27 @@ # ChangeLog -## [Unreleased] +## [0.4.1] - 2017-02-07 -## [0.4.0] - 2017-xx-xx +### Engine +* Corrected wrong postion handling for events. +* Added AnimationManager, issue #675 +* Enhanced XML formats, issue #963 +* Added events for mouse wheel left and right, issue #967 +* Fixed Location::getLayerCoordinates() on hex grids, issue #970 +* Removed special treatment of function keys, issue #976 +* Fixed tinyxml issue, was not being able to overwrite existing file, issue #978 +* Map more SDL keys to CEGUI keys, issue #980 + +### Extensions +* Load default settings if settings file has no FIFE module, issue #959 +* Update exception handler in ApplicationBase, issue #969 +* Remove Icon from manager on source load failure, issue #972 + +### Misc +* Ensure that FIFE exception message is printed in Python, issue #974 +* Several build fixes and improvements + +## [0.4.0] - 2017-01-16 * removed Psyco JIT support (by removing "UsePsyco" and the related code) * removed "scons" build system @@ -20,12 +39,12 @@ local-tinyxml is defined for SCons or the system version of tinyxml is not found. [t:619] * Add animation & color overlays [t:201], fixes [t:762], [t:764] and [t:763] -** Merge GSOC work done by vdaras. -** Replaces Guichan dependency by Fifechan -** Add support for librocket -** Add support for cegui [t:726] -*** Fixed keyboard input of control characters for CEGUI by Niektory [t: 796] -** Make use of Fifechan optional +* Merge GSOC work done by vdaras. +* Replaces Guichan dependency by Fifechan +* Add support for librocket +* Add support for cegui [t:726] +* Fixed keyboard input of control characters for CEGUI by Niektory [t: 796] +* Make use of Fifechan optional * Add overlay test ### Extensions diff --git a/CMakeLists.txt b/CMakeLists.txt index ba23ac5c5..adeaefce1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,7 @@ project (fifengine) set (FIFE_MAJOR_VERSION 0) set (FIFE_MINOR_VERSION 4) -set (FIFE_PATCH_VERSION 0) +set (FIFE_PATCH_VERSION 1) set(FIFE_VERSION ${FIFE_MAJOR_VERSION}.${FIFE_MINOR_VERSION}.${FIFE_PATCH_VERSION}) @@ -67,6 +67,17 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) Before that, cleanup:\nrm -rf CMakeCache.txt CMakeFiles") endif() +# Do not allow the build directory to be in the source directory for older +# versions of cmake. +if (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_BINARY_DIR} MATCHES "^${CMAKE_SOURCE_DIR}") + message(FATAL_ERROR "# Please chose a different build directory.\n + In cmake versions < 3 SWIG does not work well when the build directory is + placed inside the source directory. + Use something like this:\n + mkdir ../_build; cd ../_build; cmake ../fifengine\n + You can remove your current build folder.") +endif() + # Disable in-source builds and modifications to the source tree. set(CMAKE_DISABLE_SOURCE_CHANGES ON) set(CMAKE_DISABLE_IN_SOURCE_BUILD ON) @@ -181,6 +192,7 @@ set (FIFE_CORE_SRC ${PROJECT_SOURCE_DIR}/engine/core/loaders/native/map/objectloader.cpp ${PROJECT_SOURCE_DIR}/engine/core/loaders/native/map/percentdonelistener.cpp ${PROJECT_SOURCE_DIR}/engine/core/loaders/native/video/imageloader.cpp + ${PROJECT_SOURCE_DIR}/engine/core/loaders/native/video/resourceanimationloader.cpp ${PROJECT_SOURCE_DIR}/engine/core/model/model.cpp ${PROJECT_SOURCE_DIR}/engine/core/model/metamodel/action.cpp ${PROJECT_SOURCE_DIR}/engine/core/model/metamodel/object.cpp @@ -229,6 +241,7 @@ set (FIFE_CORE_SRC ${PROJECT_SOURCE_DIR}/engine/core/vfs/raw/rawdatamemsource.cpp ${PROJECT_SOURCE_DIR}/engine/core/vfs/raw/rawdatasource.cpp ${PROJECT_SOURCE_DIR}/engine/core/video/animation.cpp + ${PROJECT_SOURCE_DIR}/engine/core/video/animationmanager.cpp ${PROJECT_SOURCE_DIR}/engine/core/video/atlasbook.cpp ${PROJECT_SOURCE_DIR}/engine/core/video/color.cpp ${PROJECT_SOURCE_DIR}/engine/core/video/cursor.cpp @@ -373,6 +386,7 @@ set (FIFE_CORE_HDR ${PROJECT_SOURCE_DIR}/engine/core/loaders/native/map/objectloader.h ${PROJECT_SOURCE_DIR}/engine/core/loaders/native/map/percentdonelistener.h ${PROJECT_SOURCE_DIR}/engine/core/loaders/native/video/imageloader.h + ${PROJECT_SOURCE_DIR}/engine/core/loaders/native/video/resourceanimationloader.h ${PROJECT_SOURCE_DIR}/engine/core/model/model.h ${PROJECT_SOURCE_DIR}/engine/core/model/metamodel/action.h ${PROJECT_SOURCE_DIR}/engine/core/model/metamodel/ipather.h @@ -448,6 +462,7 @@ set (FIFE_CORE_HDR ${PROJECT_SOURCE_DIR}/engine/core/vfs/zip/zipsource.h ${PROJECT_SOURCE_DIR}/engine/core/vfs/zip/ziptree.h ${PROJECT_SOURCE_DIR}/engine/core/video/animation.h + ${PROJECT_SOURCE_DIR}/engine/core/video/animationmanager.h ${PROJECT_SOURCE_DIR}/engine/core/video/atlasbook.h ${PROJECT_SOURCE_DIR}/engine/core/video/color.h ${PROJECT_SOURCE_DIR}/engine/core/video/cursor.h @@ -679,13 +694,14 @@ endif(cegui) if(build-python) # Setting up SWIG files - + set(SWIG_MODULE_fife_EXTRA_DEPS) set(CMAKE_SWIG_IMPORTS "") set(CMAKE_SWIG_INCLUSIONS "") set(CMAKE_SWIG_IMPORTS_FCHAN "") set(CMAKE_SWIG_INCLUSIONS_FCHAN "") foreach(filename ${FIFE_CORE_SWIG}) + list(APPEND SWIG_MODULE_fife_EXTRA_DEPS "${PROJECT_SOURCE_DIR}/engine/core/${filename}") set(CMAKE_SWIG_INCLUSIONS "${CMAKE_SWIG_INCLUSIONS}%include ${filename}\n") endforeach(filename ${FIFE_CORE_SWIG}) endif(build-python) @@ -695,10 +711,15 @@ if(fifechan) find_package(FifeChan COMPONENTS sdl REQUIRED) if(build-python) + set(SWIG_MODULE_fifechan_EXTRA_DEPS) foreach(filename ${FIFE_FCHAN_SWIG_LIB}) + list(APPEND SWIG_MODULE_fife_EXTRA_DEPS "${PROJECT_SOURCE_DIR}/engine/core/${filename}") + list(APPEND SWIG_MODULE_fifechan_EXTRA_DEPS "${PROJECT_SOURCE_DIR}/engine/core/${filename}") set(CMAKE_SWIG_INCLUSIONS_FCHAN "${CMAKE_SWIG_INCLUSIONS_FCHAN}%include ${filename}\n") endforeach(filename ${FIFE_FCHAN_SWIG_LIB}) foreach(filename ${FIFE_FCHAN_SWIG}) + list(APPEND SWIG_MODULE_fife_EXTRA_DEPS "${PROJECT_SOURCE_DIR}/engine/core/${filename}") + list(APPEND SWIG_MODULE_fifechan_EXTRA_DEPS "${PROJECT_SOURCE_DIR}/engine/core/${filename}") set(CMAKE_SWIG_INCLUSIONS "${CMAKE_SWIG_INCLUSIONS}%include ${filename}\n") endforeach(filename ${FIFE_FCHAN_SWIG}) set(CMAKE_SWIG_IMPORTS "${CMAKE_SWIG_IMPORTS}%import ${PROJECT_BINARY_DIR}/fifechan.i") @@ -743,6 +764,7 @@ endif(fifechan) if(cegui) if(build-python) foreach(filename ${FIFE_CEGUI_SWIG}) + list(APPEND SWIG_MODULE_fife_EXTRA_DEPS "${PROJECT_SOURCE_DIR}/engine/core/${filename}") set(CMAKE_SWIG_INCLUSIONS "${CMAKE_SWIG_INCLUSIONS}%include ${filename}\n") endforeach(filename ${FIFE_CEGUI_SWIG}) endif(build-python) diff --git a/appveyor.yml b/appveyor.yml index 52d55c210..421027454 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,11 +1,6 @@ # Build worker image (VM template) image: Visual Studio 2015 -branches: - only: - - master - - python3 - clone_depth: 5 version: '{build}' @@ -64,8 +59,8 @@ init: install: # set path to boost according to compiler toolchain - - if "%generator%" == "Visual Studio 14" (SET boost_root=C:\Libraries\boost_1_59_0) - - if "%generator%" == "Visual Studio 14" (SET boost_librarydir=C:\Libraries\boost_1_59_0\lib32-msvc-14.0) + - if "%generator%" == "Visual Studio 14" (SET boost_root=C:\Libraries\boost_1_63_0) + - if "%generator%" == "Visual Studio 14" (SET boost_librarydir=C:\Libraries\boost_1_63_0\lib32-msvc-14.0) # get dependencies - cmake dependencies -G "%generator%" -B../fifengine-dependencies/build - cmake --build ../fifengine-dependencies/build --target ALL_BUILD --config %configuration% @@ -121,13 +116,13 @@ after_build: # package dependencies artifact - call %APPVEYOR_BUILD_FOLDER%\build\appveyor\copy-boost-to-includes.bat - cd C:\projects\fifengine-dependencies\includes - - 7z a -tzip -mx9 "%APPVEYOR_BUILD_FOLDER%\libfife-dependencies-%APPVEYOR_BUILD_VERSION%-%COMPILER%.zip" - - appveyor PushArtifact "%APPVEYOR_BUILD_FOLDER%\libfife-dependencies-%APPVEYOR_BUILD_VERSION%-%COMPILER%.zip" + - 7z a -tzip -mx9 "%APPVEYOR_BUILD_FOLDER%\libfife-dependencies-%APPVEYOR_BUILD_VERSION%-%COMPILER%-%platform%.zip" + - appveyor PushArtifact "%APPVEYOR_BUILD_FOLDER%\libfife-dependencies-%APPVEYOR_BUILD_VERSION%-%COMPILER%-%platform%.zip" # package libfife artifact - cd c:\fife\install - - 7z a -tzip -mx9 "%APPVEYOR_BUILD_FOLDER%\libfife-%APPVEYOR_BUILD_VERSION%-%COMPILER%.zip" - - appveyor PushArtifact "%APPVEYOR_BUILD_FOLDER%\libfife-%APPVEYOR_BUILD_VERSION%-%COMPILER%.zip" + - 7z a -tzip -mx9 "%APPVEYOR_BUILD_FOLDER%\libfife-%APPVEYOR_BUILD_VERSION%-%COMPILER%-%platform%.zip" + - appveyor PushArtifact "%APPVEYOR_BUILD_FOLDER%\libfife-%APPVEYOR_BUILD_VERSION%-%COMPILER%-%platform%.zip" # package Python Installer artifact - xcopy /Y /S "C:\projects\build\*.py" "%APPVEYOR_BUILD_FOLDER%\engine\python\fife\" @@ -135,9 +130,11 @@ after_build: - xcopy /Y /S "C:\projects\fifengine-dependencies\includes\bin\*.dll" "%APPVEYOR_BUILD_FOLDER%\engine\python\fife\" - xcopy /Y /S "C:\projects\fifengine-dependencies\includes\lib\x86\*.dll" "%APPVEYOR_BUILD_FOLDER%\engine\python\fife\" - cd %APPVEYOR_BUILD_FOLDER% - - python setup.py set_metadata --version=0.4.0 bdist_msi --target-version="%PYTHON_VERSION%" + - python setup.py set_metadata --version=0.4.1 bdist_msi --target-version="%PYTHON_VERSION%" + - python setup.py set_metadata --version=0.4.1 bdist_dumb --format=zip - dir %APPVEYOR_BUILD_FOLDER%\dist - - appveyor PushArtifact "%APPVEYOR_BUILD_FOLDER%\dist\libfife-0.4.0.win32-py%PYTHON_VERSION%.msi" + - appveyor PushArtifact "%APPVEYOR_BUILD_FOLDER%\dist\libfife-0.4.1.win32-py%PYTHON_VERSION%.msi" + - appveyor PushArtifact "%APPVEYOR_BUILD_FOLDER%\dist\libfife-0.4.1.win32.zip" - dir C:\projects\build /s - dir "%APPVEYOR_BUILD_FOLDER%\engine\python\fife\" /s @@ -149,6 +146,8 @@ artifacts: name: LibFife - path: 'dist\libfife-*py2.7.msi' name: Python27Installer + - path: 'dist\libfife-0.4.1.win32.zip' + name: Python27-zip # deploy to Github Releases on tag push deploy: @@ -156,9 +155,10 @@ deploy: release: 'Fifengine $(APPVEYOR_REPO_TAG_NAME)' tag: $(APPVEYOR_REPO_TAG_NAME) description: '[**Changelog**](https://github.com/fifengine/fifengine/blob/master/CHANGELOG.md)' - artifact: Dependencies, LibFife, Python27Installer + artifact: Dependencies, LibFife, Python27Installer, Python27-zip draft: false prerelease: false + force_update: true # overwrite files of existing release on GitHub on: branch: master # release from master branch only appveyor_repo_tag: true # deploy on tag push only diff --git a/build/appveyor/copy-boost-to-includes.bat b/build/appveyor/copy-boost-to-includes.bat index c1b384803..952da7a73 100644 --- a/build/appveyor/copy-boost-to-includes.bat +++ b/build/appveyor/copy-boost-to-includes.bat @@ -7,17 +7,17 @@ mkdir C:\projects\fifengine-dependencies\includes\lib\boost mkdir C:\projects\fifengine-dependencies\includes\include\boost :: copy boost includes -xcopy /Y /S "C:\Libraries\boost_1_59_0\boost" "C:\projects\fifengine-dependencies\includes\include\boost" >nul 2>&1 +xcopy /Y /S "C:\Libraries\boost_1_63_0\boost" "C:\projects\fifengine-dependencies\includes\include\boost" >nul 2>&1 :: copy binaries (dlls) and libs -copy "C:\Libraries\boost_1_59_0\lib32-msvc-14.0\boost_filesystem-vc140-mt-1_59.dll" "C:\projects\fifengine-dependencies\includes\bin\boost_filesystem-vc140-mt-1_59.dll" -copy "C:\Libraries\boost_1_59_0\lib32-msvc-14.0\boost_system-vc140-mt-1_59.dll" "C:\projects\fifengine-dependencies\includes\bin\boost_system-vc140-mt-1_59.dll" -copy "C:\Libraries\boost_1_59_0\lib32-msvc-14.0\boost_regex-vc140-mt-1_59.dll" "C:\projects\fifengine-dependencies\includes\bin\boost_regex-vc140-mt-1_59.dll" -copy "C:\Libraries\boost_1_59_0\lib32-msvc-14.0\libboost_filesystem-vc140-mt-1_59.lib" "C:\projects\fifengine-dependencies\includes\lib\boost\libboost_filesystem-vc140-mt-1_59.lib" -copy "C:\Libraries\boost_1_59_0\lib32-msvc-14.0\libboost_system-vc140-mt-1_59.lib" "C:\projects\fifengine-dependencies\includes\lib\boost\libboost_system-vc140-mt-1_59.lib" -copy "C:\Libraries\boost_1_59_0\lib32-msvc-14.0\libboost_regex-vc140-mt-1_59.lib" "C:\projects\fifengine-dependencies\includes\lib\boost\libboost_regex-vc140-mt-1_59.lib" +copy "C:\Libraries\boost_1_63_0\lib32-msvc-14.0\boost_filesystem-vc140-mt-1_63.dll" "C:\projects\fifengine-dependencies\includes\bin\boost_filesystem-vc140-mt-1_63.dll" +copy "C:\Libraries\boost_1_63_0\lib32-msvc-14.0\boost_system-vc140-mt-1_63.dll" "C:\projects\fifengine-dependencies\includes\bin\boost_system-vc140-mt-1_63.dll" +copy "C:\Libraries\boost_1_63_0\lib32-msvc-14.0\boost_regex-vc140-mt-1_63.dll" "C:\projects\fifengine-dependencies\includes\bin\boost_regex-vc140-mt-1_63.dll" +copy "C:\Libraries\boost_1_63_0\lib32-msvc-14.0\libboost_filesystem-vc140-mt-1_63.lib" "C:\projects\fifengine-dependencies\includes\lib\boost\libboost_filesystem-vc140-mt-1_63.lib" +copy "C:\Libraries\boost_1_63_0\lib32-msvc-14.0\libboost_system-vc140-mt-1_63.lib" "C:\projects\fifengine-dependencies\includes\lib\boost\libboost_system-vc140-mt-1_63.lib" +copy "C:\Libraries\boost_1_63_0\lib32-msvc-14.0\libboost_regex-vc140-mt-1_63.lib" "C:\projects\fifengine-dependencies\includes\lib\boost\libboost_regex-vc140-mt-1_63.lib" :: remove the "share" folder rmdir /S /Q C:\projects\fifengine-dependencies\includes\share -echo "Done." \ No newline at end of file +echo "Done." diff --git a/cmake/get-fifechan.cmake b/cmake/get-fifechan.cmake index 9e26c009c..0f6483062 100644 --- a/cmake/get-fifechan.cmake +++ b/cmake/get-fifechan.cmake @@ -5,28 +5,28 @@ include(ExternalProject) -set(FIFECHAN_VERSION "0.2.0") +set(FIFECHAN_VERSION "0.1.4") # For Windows it's faster to download the pre-compiled development binaries. if (WIN32) - if(MINGW) # download pre-compiled dev package for MinGW 32/64-bit + #if(MINGW) # download pre-compiled dev package for MinGW 32/64-bit - ExternalProject_Add( - fifechan - PREFIX ${DEPENDENCY_EXTRACT_DIR} - DOWNLOAD_DIR ${DEPENDENCY_DOWNLOAD_DIR} + #ExternalProject_Add( + #fifechan + #PREFIX ${DEPENDENCY_EXTRACT_DIR} + #DOWNLOAD_DIR ${DEPENDENCY_DOWNLOAD_DIR} #URL https://github.com/fifengine/fifechan/releases/tag/${FIFECHAN_VERSION}/fifechan-v${FIFECHAN_VERSION}-MinGW.tar.gz - URL https://ci.appveyor.com/api/projects/jakoch/fifechan/artifacts/fifechan-shared-MinGW.tar.gz - URL_MD5 1 - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND - COMMAND ${CMAKE_COMMAND} -E copy_directory ${DEPENDENCY_EXTRACT_DIR}/src/fifechan/lib ${DEPENDENCY_INSTALL_DIR}/lib - COMMAND ${CMAKE_COMMAND} -E copy_directory ${DEPENDENCY_EXTRACT_DIR}/src/fifechan/include ${DEPENDENCY_INSTALL_DIR}/include/fifechan - ) + #URL https://ci.appveyor.com/api/projects/jakoch/fifechan/artifacts/fifechan-shared-MinGW.tar.gz + #URL_MD5 1 + #CONFIGURE_COMMAND "" + #BUILD_COMMAND "" + #INSTALL_COMMAND + #COMMAND ${CMAKE_COMMAND} -E copy_directory ${DEPENDENCY_EXTRACT_DIR}/src/fifechan/lib ${DEPENDENCY_INSTALL_DIR}/lib + #COMMAND ${CMAKE_COMMAND} -E copy_directory ${DEPENDENCY_EXTRACT_DIR}/src/fifechan/include ${DEPENDENCY_INSTALL_DIR}/include/fifechan + #) - endif(MINGW) + #endif(MINGW) if(MSVC) # download pre-compiled dev package for Visual C++ 32/64-bit @@ -35,8 +35,8 @@ if (WIN32) PREFIX ${DEPENDENCY_EXTRACT_DIR} DOWNLOAD_DIR ${DEPENDENCY_DOWNLOAD_DIR} #URL https://github.com/fifengine/fifechan/releases/tag/${FIFECHAN_VERSION}/fifechan-v${FIFECHAN_VERSION}-VC14.zip - URL https://ci.appveyor.com/api/buildjobs/lel0aaieaa4cgnmv/artifacts/fifechan-shared-VC14.zip - URL_MD5 3bc2c39b9c0842b4bcc6eaddf84d4525 + URL https://ci.appveyor.com/api/buildjobs/k6gfl3mdxnkhy9mn/artifacts/fifechan-shared-0.1.4-VC14-x86.zip + URL_MD5 4925a3d07994b1e360e034ed0475dc37 CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND diff --git a/cmake/get-libpng.cmake b/cmake/get-libpng.cmake index e7d954c2d..f15eb4daf 100644 --- a/cmake/get-libpng.cmake +++ b/cmake/get-libpng.cmake @@ -1,13 +1,13 @@ #------------------------------------------------------------------------------ # External Project: libpng # Website: http://www.libpng.org/pub/png/libpng.html -# Downloads: ftp://ftp.simplesystems.org/pub/libpng/png/src/libpng16/lpng1624.zip +# Downloads: https://github.com/glennrp/libpng/archive/v1.6.28.zip # Github: https://github.com/glennrp/libpng #------------------------------------------------------------------------------ include(ExternalProject) -set(LIBPNG_VERSION "1.6.24") +set(LIBPNG_VERSION "1.6.28") set(LIBPNG_CMAKE_ARGS ${COMMON_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= @@ -31,7 +31,7 @@ ExternalProject_Add( DOWNLOAD_DIR ${DEPENDENCY_DOWNLOAD_DIR} DOWNLOAD_NAME libpng-v${LIBPNG_VERSION}.zip URL https://github.com/glennrp/libpng/archive/v${LIBPNG_VERSION}.zip - URL_MD5 8e8d519124c7c6a2b7ec72a23c453fbd + URL_MD5 eeb04099fb0910df8d4691ecf8135cb8 INSTALL_DIR ${DEPENDENCY_INSTALL_DIR} CONFIGURE_COMMAND ${CMAKE_COMMAND} ${DEPENDENCY_EXTRACT_DIR}/src/libpng -G ${CMAKE_GENERATOR} @@ -42,4 +42,4 @@ ExternalProject_Add( #BUILD_COMMAND msbuild libpng.sln /target:INSTALL /p:Platform=Win32 /p:Configuration=Release #INSTALL_COMMAND msbuild libpng.sln /build Release /project INSTALL #CMAKE_ARGS ${LIBPNG_CMAKE_ARGS} -) \ No newline at end of file +) diff --git a/cmake/get-openal.cmake b/cmake/get-openal.cmake index f66de3b9d..abb23e30a 100644 --- a/cmake/get-openal.cmake +++ b/cmake/get-openal.cmake @@ -1,8 +1,8 @@ #------------------------------------------------------------------------------ -# External Project: OpenAL +# External Project: OpenAL-Soft # -# Website: https://www.openal.org/ -# Downloads: https://www.openal.org/downloads/ +# Website: http://kcat.strangesoft.net/openal.html +# Downloads: http://kcat.strangesoft.net/openal.html#download # # Alternative Downloads: http://kcat.strangesoft.net/openal-binaries/ # http://kcat.strangesoft.net/openal-releases/ @@ -58,4 +58,4 @@ else() # build from source CMAKE_ARGS ${OPENAL_CMAKE_ARGS} ) -endif() \ No newline at end of file +endif() diff --git a/cmake/get-sdl2.cmake b/cmake/get-sdl2.cmake index 84f9e7a4b..e804ff4df 100644 --- a/cmake/get-sdl2.cmake +++ b/cmake/get-sdl2.cmake @@ -5,7 +5,7 @@ include(ExternalProject) -set(SDL2_VERSION "2.0.4") +set(SDL2_VERSION "2.0.5") # For Windows it's faster to download the pre-compiled development binaries. if (WIN32) @@ -17,7 +17,7 @@ if (WIN32) PREFIX ${DEPENDENCY_EXTRACT_DIR} DOWNLOAD_DIR ${DEPENDENCY_DOWNLOAD_DIR} URL http://libsdl.org/release/SDL2-devel-${SDL2_VERSION}-mingw.tar.gz - URL_MD5 1 + URL_MD5 ecf8fb614d57e7d284086a36dae6878f CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND @@ -34,7 +34,7 @@ if (WIN32) PREFIX ${DEPENDENCY_EXTRACT_DIR} DOWNLOAD_DIR ${DEPENDENCY_DOWNLOAD_DIR} URL http://libsdl.org/release/SDL2-devel-${SDL2_VERSION}-VC.zip - URL_MD5 3025645afc813bf00b789a34dcc92d42 + URL_MD5 b771f36bb640c173e53fa8259cdd3835 CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND @@ -65,4 +65,4 @@ else() # build from source CMAKE_ARGS ${SDL2_CMAKE_ARGS} ) -endif() \ No newline at end of file +endif() diff --git a/cmake/get-swig.cmake b/cmake/get-swig.cmake index ce3261e3a..401102b2f 100644 --- a/cmake/get-swig.cmake +++ b/cmake/get-swig.cmake @@ -7,7 +7,7 @@ INCLUDE(ExternalProject) -set(SWIG_VERSION "3.0.10") +set(SWIG_VERSION "3.0.12") # For Windows it's faster to download the pre-compiled development binaries. if(WIN32) @@ -17,7 +17,7 @@ if(WIN32) PREFIX ${DEPENDENCY_EXTRACT_DIR} DOWNLOAD_DIR ${DEPENDENCY_DOWNLOAD_DIR} URL http://downloads.sourceforge.net/project/swig/swigwin/swigwin-${SWIG_VERSION}/swigwin-${SWIG_VERSION}.zip - URL_MD5 f229724fe856aa78df6128ecfefe6e0a + URL_MD5 a49524dad2c91ae1920974e7062bfc93 #INSTALL_DIR ${DEPENDENCY_INSTALL_DIR}/../build-tools/swig CONFIGURE_COMMAND "" BUILD_COMMAND "" @@ -37,4 +37,4 @@ else() INSTALL_DIR ${DEPENDENCY_INSTALL_DIR}/../build-tools/swig ) -endif() \ No newline at end of file +endif() diff --git a/cmake/get-zlib.cmake b/cmake/get-zlib.cmake index 1a749f65c..fcc74bf41 100644 --- a/cmake/get-zlib.cmake +++ b/cmake/get-zlib.cmake @@ -6,7 +6,7 @@ include(ExternalProject) -set(ZLIB_VERSION "1.2.8") +set(ZLIB_VERSION "1.2.11") set(ZLIB_CMAKE_ARGS ${COMMON_CMAKE_ARGS} @@ -23,6 +23,6 @@ ExternalProject_Add( DOWNLOAD_DIR ${DEPENDENCY_DOWNLOAD_DIR} DOWNLOAD_NAME zlib-v${ZLIB_VERSION}.zip URL https://github.com/madler/zlib/archive/v${ZLIB_VERSION}.zip - URL_MD5 9b568ed0e7f95311dda39595995570ff + URL_MD5 9d6a627693163bbbf3f26403a3a0b0b1 CMAKE_ARGS ${ZLIB_CMAKE_ARGS} ) diff --git a/engine/core/controller/engine.cpp b/engine/core/controller/engine.cpp index b88d9bd3d..13b422d7b 100644 --- a/engine/core/controller/engine.cpp +++ b/engine/core/controller/engine.cpp @@ -44,6 +44,7 @@ #endif #include "eventchannel/eventmanager.h" #include "video/imagemanager.h" +#include "video/animationmanager.h" #include "audio/soundclipmanager.h" #include "video/renderbackend.h" #include "video/cursor.h" @@ -96,6 +97,7 @@ namespace FIFE { m_soundmanager(0), m_timemanager(0), m_imagemanager(0), + m_animationmanager(0), m_soundclipmanager(0), m_vfs(0), m_model(0), @@ -192,6 +194,7 @@ namespace FIFE { FL_LOG(_log, "Creating resource managers"); m_imagemanager = new ImageManager(); + m_animationmanager = new AnimationManager(); m_soundclipmanager = new SoundClipManager(); FL_LOG(_log, "Creating render backend"); @@ -321,6 +324,7 @@ namespace FIFE { delete m_soundmanager; delete m_guimanager; + delete m_animationmanager; delete m_imagemanager; delete m_soundclipmanager; delete m_eventmanager; diff --git a/engine/core/controller/engine.h b/engine/core/controller/engine.h index ea65be20a..8b9aadd0b 100644 --- a/engine/core/controller/engine.h +++ b/engine/core/controller/engine.h @@ -57,6 +57,7 @@ namespace FIFE { class RendererBase; class Image; class ImageManager; + class AnimationManager; class SoundClipManager; class OffRenderer; class TargetRenderer; @@ -152,6 +153,10 @@ namespace FIFE { */ ImageManager* getImageManager() const { return m_imagemanager; } + /** Provides access point to the ImageManager + */ + AnimationManager* getAnimationManager() const { return m_animationmanager; } + /** Provides access point to the SoundClipManager */ SoundClipManager* getSoundClipManager() const { return m_soundclipmanager; } @@ -201,6 +206,7 @@ namespace FIFE { SoundManager* m_soundmanager; TimeManager* m_timemanager; ImageManager* m_imagemanager; + AnimationManager* m_animationmanager; SoundClipManager* m_soundclipmanager; VFS* m_vfs; diff --git a/engine/core/controller/engine.i b/engine/core/controller/engine.i index e065a8830..e160532ff 100644 --- a/engine/core/controller/engine.i +++ b/engine/core/controller/engine.i @@ -42,6 +42,7 @@ namespace FIFE { class ScreenMode; class Image; class ImageManager; + class AnimationManager; class SoundClipManager; class OffRenderer; class TargetRenderer; @@ -150,6 +151,7 @@ namespace FIFE { void setGuiManager(IGUIManager* guimanager); IGUIManager* getGuiManager(); ImageManager* getImageManager(); + AnimationManager* getAnimationManager(); SoundClipManager* getSoundClipManager(); RenderBackend* getRenderBackend(); Model* getModel(); diff --git a/engine/core/eventchannel/eventchannel.i b/engine/core/eventchannel/eventchannel.i index f172180bc..59e5740ef 100644 --- a/engine/core/eventchannel/eventchannel.i +++ b/engine/core/eventchannel/eventchannel.i @@ -165,6 +165,8 @@ namespace FIFE { RELEASED, WHEEL_MOVED_DOWN, WHEEL_MOVED_UP, + WHEEL_MOVED_RIGHT, + WHEEL_MOVED_LEFT, CLICKED, ENTERED, EXITED, @@ -199,6 +201,8 @@ namespace FIFE { virtual void mouseClicked(MouseEvent& evt) = 0; virtual void mouseWheelMovedUp(MouseEvent& evt) = 0; virtual void mouseWheelMovedDown(MouseEvent& evt) = 0; + virtual void mouseWheelMovedRight(MouseEvent& evt) = 0; + virtual void mouseWheelMovedLeft(MouseEvent& evt) = 0; virtual void mouseMoved(MouseEvent& evt) = 0; virtual void mouseDragged(MouseEvent& evt) = 0; virtual ~IMouseListener(); diff --git a/engine/core/eventchannel/eventmanager.cpp b/engine/core/eventchannel/eventmanager.cpp index 14940c303..939c2307e 100644 --- a/engine/core/eventchannel/eventmanager.cpp +++ b/engine/core/eventchannel/eventmanager.cpp @@ -350,6 +350,12 @@ namespace FIFE { case MouseEvent::WHEEL_MOVED_UP: (*i)->mouseWheelMovedUp(evt); break; + case MouseEvent::WHEEL_MOVED_RIGHT: + (*i)->mouseWheelMovedRight(evt); + break; + case MouseEvent::WHEEL_MOVED_LEFT: + (*i)->mouseWheelMovedLeft(evt); + break; case MouseEvent::CLICKED: (*i)->mouseClicked(evt); break; @@ -578,14 +584,9 @@ namespace FIFE { keyevt.setSource(this); fillKeyEvent(event, keyevt); m_keystatemap[keyevt.getKey().getValue()] = (keyevt.getType() == KeyEvent::PRESSED); - - bool dispatchAsSdl = !keyevt.getKey().isFunctionKey(); - if( dispatchAsSdl && m_keyfilter ) { - dispatchAsSdl = !m_keyfilter->isFiltered(keyevt); - } - - if( dispatchAsSdl ) { - if( dispatchSdlEvent(event) ) + // if event is not filtered it gets dispatched, even it is a function key + if (!m_keyfilter || !m_keyfilter->isFiltered(keyevt)) { + if (dispatchSdlEvent(event)) return; } @@ -741,13 +742,22 @@ namespace FIFE { } } if (sdlevt.type == SDL_MOUSEWHEEL) { - if (sdlevt.wheel.y > 0 || sdlevt.wheel.x > 0) { + //if (sdlevt.wheel.y > 0 || (sdlevt.wheel.direction == SDL_MOUSEWHEEL_FLIPPED && sdlevt.wheel.y < 0)) { + if (sdlevt.wheel.y > 0) { mouseevt.setType(MouseEvent::WHEEL_MOVED_UP); - } else if (sdlevt.wheel.y < 0 || sdlevt.wheel.x < 0) { + //} else if (sdlevt.wheel.y < 0 || (sdlevt.wheel.direction == SDL_MOUSEWHEEL_FLIPPED && sdlevt.wheel.y > 0)) { + } else if (sdlevt.wheel.y < 0) { mouseevt.setType(MouseEvent::WHEEL_MOVED_DOWN); } + //if (sdlevt.wheel.x > 0 || (sdlevt.wheel.direction == SDL_MOUSEWHEEL_FLIPPED && sdlevt.wheel.x < 0)) { + if (sdlevt.wheel.x > 0) { + mouseevt.setType(MouseEvent::WHEEL_MOVED_RIGHT); + //} else if (sdlevt.wheel.x < 0 || (sdlevt.wheel.direction == SDL_MOUSEWHEEL_FLIPPED && sdlevt.wheel.x > 0)) { + } else if (sdlevt.wheel.x < 0) { + mouseevt.setType(MouseEvent::WHEEL_MOVED_LEFT); + } } - //if ((mouseevt.getType() == MouseEvent::MOVED) && m_mousestate) { + if ((mouseevt.getType() == MouseEvent::MOVED) && ((m_mousestate & m_mostrecentbtn) != 0)) { mouseevt.setType(MouseEvent::DRAGGED); mouseevt.setButton(m_mostrecentbtn); diff --git a/engine/core/eventchannel/mouse/ec_imouselistener.h b/engine/core/eventchannel/mouse/ec_imouselistener.h index b16e49764..79d424a9e 100644 --- a/engine/core/eventchannel/mouse/ec_imouselistener.h +++ b/engine/core/eventchannel/mouse/ec_imouselistener.h @@ -88,6 +88,18 @@ namespace FIFE { */ virtual void mouseWheelMovedDown(MouseEvent& evt) = 0; + /** + * Called when the mouse wheel has moved right on the event source area. + * @param evt describes the event. + */ + virtual void mouseWheelMovedRight(MouseEvent& evt) = 0; + + /** + * Called when the mouse wheel has moved left on the event source area. + * @param evt MouseEvent that describes the event. + */ + virtual void mouseWheelMovedLeft(MouseEvent& evt) = 0; + /** * Called when the mouse has moved in the event source area and no mouse button * has been pressed diff --git a/engine/core/eventchannel/mouse/ec_mouseevent.h b/engine/core/eventchannel/mouse/ec_mouseevent.h index fadc2aa1b..65fb3b561 100644 --- a/engine/core/eventchannel/mouse/ec_mouseevent.h +++ b/engine/core/eventchannel/mouse/ec_mouseevent.h @@ -52,6 +52,8 @@ namespace FIFE { RELEASED, WHEEL_MOVED_DOWN, WHEEL_MOVED_UP, + WHEEL_MOVED_RIGHT, + WHEEL_MOVED_LEFT, CLICKED, ENTERED, EXITED, @@ -169,6 +171,12 @@ namespace FIFE { case MouseEvent::WHEEL_MOVED_UP: s = "wheel_moved_up"; break; + case MouseEvent::WHEEL_MOVED_RIGHT: + s = "wheel_moved_right"; + break; + case MouseEvent::WHEEL_MOVED_LEFT: + s = "wheel_moved_left"; + break; case MouseEvent::CLICKED: s = "clicked"; break; @@ -204,6 +212,15 @@ namespace FIFE { case MouseEvent::MIDDLE: s = "middle"; break; + case MouseEvent::X1: + s = "x1"; + break; + case MouseEvent::X2: + s = "x2"; + break; + case MouseEvent::UNKNOWN_BUTTON: + s = "unknown button"; + break; default: break; } diff --git a/engine/core/gui/cegui/base/ceguiinputprocessor.cpp b/engine/core/gui/cegui/base/ceguiinputprocessor.cpp index ad8cd86dc..4b36423f3 100644 --- a/engine/core/gui/cegui/base/ceguiinputprocessor.cpp +++ b/engine/core/gui/cegui/base/ceguiinputprocessor.cpp @@ -103,6 +103,7 @@ namespace FIFE { switch(event.type) { case SDL_MOUSEBUTTONDOWN: + { switch(event.button.button) { case SDL_BUTTON_LEFT: consumed = CEGUI::System::getSingleton().getDefaultGUIContext().injectMouseButtonDown(CEGUI::LeftButton); @@ -120,8 +121,10 @@ namespace FIFE { ; } break; + } case SDL_MOUSEBUTTONUP: + { switch(event.button.button) { case SDL_BUTTON_LEFT: consumed = CEGUI::System::getSingleton().getDefaultGUIContext().injectMouseButtonUp(CEGUI::LeftButton); @@ -139,16 +142,20 @@ namespace FIFE { ; } break; + } case SDL_MOUSEWHEEL: - // wheel up - if (event.wheel.y > 0) { - consumed = CEGUI::System::getSingleton().getDefaultGUIContext().injectMouseWheelChange(1); - // wheel down - } else if (event.wheel.y < 0) { - consumed = CEGUI::System::getSingleton().getDefaultGUIContext().injectMouseWheelChange(-1); + { + // mousewheel up or down + int32_t wheelChange = event.wheel.y; + if (wheelChange != 0) { + /*if (event.wheel.direction == SDL_MOUSEWHEEL_FLIPPED) { + wheelChange *= -1; + }*/ + consumed = CEGUI::System::getSingleton().getDefaultGUIContext().injectMouseWheelChange(wheelChange); } break; + } default: ; @@ -207,10 +214,13 @@ namespace FIFE { m_keymap[SDLK_MINUS] = CEGUI::Key::Minus; m_keymap[SDLK_EQUALS] = CEGUI::Key::Equals; m_keymap[SDLK_SEMICOLON] = CEGUI::Key::Semicolon; + m_keymap[SDLK_COLON] = CEGUI::Key::Colon; m_keymap[SDLK_LEFTBRACKET] = CEGUI::Key::LeftBracket; m_keymap[SDLK_RIGHTBRACKET] = CEGUI::Key::RightBracket; m_keymap[SDLK_QUOTE] = CEGUI::Key::Apostrophe; m_keymap[SDLK_BACKQUOTE] = CEGUI::Key::Grave; + m_keymap[SDLK_AT] = CEGUI::Key::At; + m_keymap[SDLK_UNDERSCORE] = CEGUI::Key::Underline; m_keymap[SDLK_RETURN] = CEGUI::Key::Return; m_keymap[SDLK_SPACE] = CEGUI::Key::Space; @@ -221,9 +231,33 @@ namespace FIFE { m_keymap[SDLK_PAUSE] = CEGUI::Key::Pause; m_keymap[SDLK_SYSREQ] = CEGUI::Key::SysRq; m_keymap[SDLK_POWER] = CEGUI::Key::Power; + m_keymap[SDLK_SLEEP] = CEGUI::Key::Sleep; + + m_keymap[SDLK_CALCULATOR] = CEGUI::Key::Calculator; + m_keymap[SDLK_MAIL] = CEGUI::Key::Mail; + m_keymap[SDLK_COMPUTER] = CEGUI::Key::MyComputer; + m_keymap[SDLK_MEDIASELECT] = CEGUI::Key::MediaSelect; + m_keymap[SDLK_AC_STOP] = CEGUI::Key::Stop; + + m_keymap[SDLK_AUDIOPLAY] = CEGUI::Key::PlayPause; + m_keymap[SDLK_AUDIOSTOP] = CEGUI::Key::MediaStop; + m_keymap[SDLK_AUDIOPREV] = CEGUI::Key::PrevTrack; + m_keymap[SDLK_AUDIONEXT] = CEGUI::Key::NextTrack; + m_keymap[SDLK_AUDIOMUTE] = CEGUI::Key::Mute; + m_keymap[SDLK_VOLUMEUP] = CEGUI::Key::VolumeUp; + m_keymap[SDLK_VOLUMEDOWN] = CEGUI::Key::VolumeDown; + + m_keymap[SDLK_AC_BACK] = CEGUI::Key::WebBack; + m_keymap[SDLK_AC_FORWARD] = CEGUI::Key::WebForward; + m_keymap[SDLK_AC_HOME] = CEGUI::Key::WebHome; + m_keymap[SDLK_AC_BOOKMARKS] = CEGUI::Key::WebFavorites; + m_keymap[SDLK_AC_SEARCH] = CEGUI::Key::WebSearch; + m_keymap[SDLK_AC_REFRESH] = CEGUI::Key::WebRefresh; + m_keymap[SDLK_AC_STOP] = CEGUI::Key::WebStop; m_keymap[SDLK_NUMLOCKCLEAR] = CEGUI::Key::NumLock; m_keymap[SDLK_SCROLLLOCK] = CEGUI::Key::ScrollLock; + m_keymap[SDLK_CAPSLOCK] = CEGUI::Key::Capital; m_keymap[SDLK_F1] = CEGUI::Key::F1; m_keymap[SDLK_F2] = CEGUI::Key::F2; @@ -267,6 +301,8 @@ namespace FIFE { m_keymap[SDLK_KP_MULTIPLY] = CEGUI::Key::Multiply; m_keymap[SDLK_KP_DIVIDE] = CEGUI::Key::Divide; m_keymap[SDLK_KP_ENTER] = CEGUI::Key::NumpadEnter; + m_keymap[SDLK_KP_COMMA] = CEGUI::Key::NumpadComma; + m_keymap[SDLK_KP_EQUALS] = CEGUI::Key::NumpadEquals; m_keymap[SDLK_UP] = CEGUI::Key::ArrowUp; m_keymap[SDLK_LEFT] = CEGUI::Key::ArrowLeft; diff --git a/engine/core/gui/fifechan/fifechanmanager.cpp b/engine/core/gui/fifechan/fifechanmanager.cpp index 6448cc977..4e1bf914b 100644 --- a/engine/core/gui/fifechan/fifechanmanager.cpp +++ b/engine/core/gui/fifechan/fifechanmanager.cpp @@ -75,6 +75,8 @@ namespace FIFE { m_fcn_topcontainer->setFocusable(false); m_had_mouse = false; m_had_widget = false; + m_lastMotionX = 0; + m_lastMotionY = 0; } FifechanManager::~FifechanManager() { @@ -97,7 +99,7 @@ namespace FIFE { return false; } - bool overWidget = m_fcn_topcontainer->getWidgetAt(evt.button.x,evt.button.y) != 0; + bool overWidget = m_fcn_topcontainer->getWidgetAt(m_lastMotionX, m_lastMotionY) != 0; switch(evt.type) { case SDL_MOUSEWHEEL: @@ -125,7 +127,9 @@ namespace FIFE { return false; case SDL_MOUSEMOTION: - if( m_fcn_topcontainer->getWidgetAt(evt.button.x,evt.button.y) ) { + m_lastMotionX = evt.motion.x; + m_lastMotionY = evt.motion.y; + if (m_fcn_topcontainer->getWidgetAt(evt.motion.x,evt.motion.y)) { m_had_mouse = true; m_input->pushInput(evt); return true; diff --git a/engine/core/gui/fifechan/fifechanmanager.h b/engine/core/gui/fifechan/fifechanmanager.h index 30c0ece15..df8a9c243 100644 --- a/engine/core/gui/fifechan/fifechanmanager.h +++ b/engine/core/gui/fifechan/fifechanmanager.h @@ -176,6 +176,9 @@ namespace FIFE { // Used to accept mouse motion events that leave widget space bool m_had_mouse; bool m_had_widget; + // Track last motion event position + int32_t m_lastMotionX; + int32_t m_lastMotionY; // default font settings std::string m_fontpath; diff --git a/engine/core/gui/fifechan/lib/fifechanlistener.i b/engine/core/gui/fifechan/lib/fifechanlistener.i index dba9e0429..0cc6accc3 100644 --- a/engine/core/gui/fifechan/lib/fifechanlistener.i +++ b/engine/core/gui/fifechan/lib/fifechanlistener.i @@ -41,6 +41,8 @@ namespace fcn { virtual void mouseClicked(fcn::MouseEvent& mouseEvent); virtual void mouseWheelMovedUp(fcn::MouseEvent& mouseEvent); virtual void mouseWheelMovedDown(fcn::MouseEvent& mouseEvent); + virtual void mouseWheelMovedRight(fcn::MouseEvent& mouseEvent); + virtual void mouseWheelMovedLeft(fcn::MouseEvent& mouseEvent); virtual void mouseMoved(fcn::MouseEvent& mouseEvent); virtual void mouseDragged(fcn::MouseEvent& mouseEvent); protected: @@ -69,18 +71,18 @@ namespace fcn { %feature("director") WidgetListener; class WidgetListener { public: - virtual ~WidgetListener() { } - - virtual void widgetResized(const fcn::Event& event); - virtual void widgetMoved(const fcn::Event& event); - virtual void widgetHidden(const fcn::Event& event); - virtual void widgetShown(const fcn::Event& event); - virtual void ancestorMoved(const fcn::Event& event); - virtual void ancestorHidden(const fcn::Event& event); - virtual void ancestorShown(const fcn::Event& event); - + virtual ~WidgetListener() { } + + virtual void widgetResized(const fcn::Event& event); + virtual void widgetMoved(const fcn::Event& event); + virtual void widgetHidden(const fcn::Event& event); + virtual void widgetShown(const fcn::Event& event); + virtual void ancestorMoved(const fcn::Event& event); + virtual void ancestorHidden(const fcn::Event& event); + virtual void ancestorShown(const fcn::Event& event); + protected: - WidgetListener() { } + WidgetListener() { } }; } diff --git a/engine/core/gui/librocket/base/librocketinputprocessor.cpp b/engine/core/gui/librocket/base/librocketinputprocessor.cpp index 993afaea3..33ddbf286 100644 --- a/engine/core/gui/librocket/base/librocketinputprocessor.cpp +++ b/engine/core/gui/librocket/base/librocketinputprocessor.cpp @@ -153,6 +153,7 @@ namespace FIFE { bool LibRocketInputProcessor::processMouseWheelMotion(SDL_Event& event) { // mousewheel up + //if (event.wheel.y > 0 || (event.wheel.direction == SDL_MOUSEWHEEL_FLIPPED && event.wheel.y < 0)) { if (event.wheel.y > 0) { if(m_wheelCounter <= 0) { m_wheelCounter--; @@ -163,6 +164,7 @@ namespace FIFE { } } // mousewheel down + //else if (event.wheel.y < 0 || (event.wheel.direction == SDL_MOUSEWHEEL_FLIPPED && event.wheel.y > 0)) { else if (event.wheel.y < 0) { if(m_wheelCounter >= 0) { m_wheelCounter++; diff --git a/engine/core/loaders/native/map/animationloader.cpp b/engine/core/loaders/native/map/animationloader.cpp index 0fd7944c0..92aee93ba 100644 --- a/engine/core/loaders/native/map/animationloader.cpp +++ b/engine/core/loaders/native/map/animationloader.cpp @@ -32,6 +32,7 @@ #include "vfs/vfs.h" #include "vfs/raw/rawdata.h" #include "video/imagemanager.h" +#include "video/animationmanager.h" #include "video/image.h" #include "video/animation.h" #include "util/base/exception.h" @@ -45,157 +46,256 @@ namespace FIFE { /** Logger to use for this source file. * @relates Logger */ - static Logger _log(LM_NATIVE_LOADERS); + static Logger _log(LM_NATIVE_LOADERS); - AnimationLoader::AnimationLoader(VFS* vfs, ImageManager* imageManager) - : m_vfs(vfs), m_imageManager(imageManager) { + AnimationLoader::AnimationLoader(VFS* vfs, ImageManager* imageManager, AnimationManager* animationManager) + : m_vfs(vfs), m_imageManager(imageManager), m_animationManager(animationManager) { - } + } - bool AnimationLoader::isLoadable(const std::string& filename) { - bfs::path animPath(filename); + bool AnimationLoader::isLoadable(const std::string& filename) { + bfs::path animPath(filename); - std::string animationFilename = animPath.string(); + std::string animationFilename = animPath.string(); + TiXmlDocument animFile; - try { - RawData* data = m_vfs->open(animationFilename); + try { + RawData* data = m_vfs->open(animationFilename); - if (data) { - if (data->getDataLength() != 0) { - // TODO - this could be expanded to do more checks - TiXmlDocument doc; - doc.Parse(data->readString(data->getDataLength()).c_str()); + if (data) { + if (data->getDataLength() != 0) { + // TODO - this could be expanded to do more checks + animFile.Parse(data->readString(data->getDataLength()).c_str()); - if (doc.Error()) { - return false; - } - } + if (animFile.Error()) { + return false; + } + } - // done with data delete resource - delete data; - data = 0; - } - } - catch (NotFound&) { - return false; - } + // done with data delete resource + delete data; + data = 0; + } + } + catch (NotFound&) { + return false; + } + + // if we get here then loading the file went well + TiXmlElement* root = animFile.RootElement(); - return true; - } + if (root && root->ValueStr() == "assets") { + if (root->FirstChildElement("animation")) { + return true; + } + } - AnimationPtr AnimationLoader::load(const std::string& filename) { - bfs::path animPath(filename); + return false; + } - std::string animationFilename = animPath.string(); + AnimationPtr AnimationLoader::load(const std::string& filename) { + bfs::path animPath(filename); - TiXmlDocument doc; - - AnimationPtr animation; - - try { - RawData* data = m_vfs->open(animationFilename); - - if (data) { - if (data->getDataLength() != 0) { - doc.Parse(data->readString(data->getDataLength()).c_str()); - - if (doc.Error()) { - return animation; - } - - // done with data delete resource - delete data; - data = 0; - } - } - } - catch (NotFound& e) { - FL_ERR(_log, e.what()); - - // TODO - should we abort here - // or rethrow the exception - // or just keep going - - return animation; - } - - // if we get here then everything loaded properly - // so we can just parse out the contents - TiXmlElement* root = doc.RootElement(); - - if (root) { - animation.reset(new Animation()); - - int animDelay = 0; - root->QueryValueAttribute("delay", &animDelay); - - int animXoffset = 0; - int animYoffset = 0; - int action = -1; - root->QueryValueAttribute("x_offset", &animXoffset); - root->QueryValueAttribute("y_offset", &animYoffset); - root->QueryValueAttribute("action", &action); - - for (TiXmlElement* frameElement = root->FirstChildElement("frame"); frameElement; frameElement = frameElement->NextSiblingElement("frame")) { - if (animation) { - animation->setActionFrame(action); - - const std::string* sourceId = frameElement->Attribute(std::string("source")); - - if (sourceId) { - bfs::path framePath(filename); - - if (HasParentPath(framePath)) { - framePath = GetParentPath(framePath) / *sourceId; - } else { - framePath = bfs::path(*sourceId); - } - - ImagePtr imagePtr; - if(!m_imageManager->exists(framePath.string())) { - imagePtr = m_imageManager->create(framePath.string()); - } - else { - imagePtr = m_imageManager->getPtr(framePath.string()); - } - - if (imagePtr) { - int frameXoffset = 0; - int frameYoffset = 0; - - int success = root->QueryValueAttribute("x_offset", &frameXoffset); - - if (success == TIXML_SUCCESS) { - imagePtr->setXShift(frameXoffset); - } - else { - imagePtr->setXShift(animXoffset); - } - - success = root->QueryValueAttribute("y_offset", &frameYoffset); - - if (success == TIXML_SUCCESS) { - imagePtr->setYShift(frameYoffset); - } - else { - imagePtr->setYShift(animYoffset); - } - - int frameDelay = 0; - success = root->QueryValueAttribute("delay", &frameDelay); - - if (success == TIXML_SUCCESS) { - animation->addFrame(imagePtr, frameDelay); - } - else { - animation->addFrame(imagePtr, animDelay); - } - } - } - } - } - } - - return animation; - } + std::string animationFilename = animPath.string(); + + TiXmlDocument doc; + + AnimationPtr animation; + + try { + RawData* data = m_vfs->open(animationFilename); + + if (data) { + if (data->getDataLength() != 0) { + doc.Parse(data->readString(data->getDataLength()).c_str()); + + if (doc.Error()) { + return animation; + } + + // done with data delete resource + delete data; + data = 0; + } + } + } + catch (NotFound& e) { + FL_ERR(_log, e.what()); + + // TODO - should we abort here + // or rethrow the exception + // or just keep going + + return animation; + } + + // if we get here then everything loaded properly + // so we can just parse out the contents + TiXmlElement* root = doc.RootElement(); + + if (root && root->ValueStr() == "assets") { + animation = loadAnimation(filename, root->FirstChildElement("animation")); + } + + return animation; + } + + std::vector AnimationLoader::loadMultiple(const std::string& filename) { + bfs::path animPath(filename); + + std::string animationFilename = animPath.string(); + + TiXmlDocument doc; + + std::vector animationVector; + + try { + RawData* data = m_vfs->open(animationFilename); + + if (data) { + if (data->getDataLength() != 0) { + doc.Parse(data->readString(data->getDataLength()).c_str()); + + if (doc.Error()) { + return animationVector; + } + + // done with data delete resource + delete data; + data = 0; + } + } + } + catch (NotFound& e) { + FL_ERR(_log, e.what()); + + // TODO - should we abort here + // or rethrow the exception + // or just keep going + + return animationVector; + } + + // if we get here then everything loaded properly + // so we can just parse out the contents + TiXmlElement* root = doc.RootElement(); + + if (root && root->ValueStr() == "assets") { + for (TiXmlElement* animationElem = root->FirstChildElement("animation"); animationElem; animationElem = animationElem->NextSiblingElement("animation")) { + AnimationPtr animation = loadAnimation(filename, animationElem); + if (animation) { + animationVector.push_back(animation); + } + } + } + + return animationVector; + } + + AnimationPtr AnimationLoader::loadAnimation(const std::string& filename, TiXmlElement* animationElem) { + AnimationPtr animation; + if (!animationElem) { + return animation; + } + + bfs::path animPath(filename); + std::string animationFilename = animPath.string(); + + bool alreadyLoaded = false; + // first try to use the id, if no id exists it use the filename as fallback + const std::string* animationId = animationElem->Attribute(std::string("id")); + if (animationId) { + if (!m_animationManager->exists(*animationId)) { + animation = m_animationManager->create(*animationId); + } else { + animation = m_animationManager->getPtr(*animationId); + alreadyLoaded = animation->getFrameCount() != 0; + } + } else { + if (HasParentPath(animPath)) { + animPath= GetParentPath(animPath) / animationFilename; + } else { + animPath = bfs::path(animationFilename); + } + if (!m_animationManager->exists(animPath.string())) { + animation = m_animationManager->create(animPath.string()); + } else { + animation = m_animationManager->getPtr(animPath.string()); + alreadyLoaded = animation->getFrameCount() != 0; + } + } + + if (alreadyLoaded) { + return animation; + } + + int direction = 0; + int actionFrame = -1; + int animDelay = 0; + int animXoffset = 0; + int animYoffset = 0; + + int success = animationElem->QueryValueAttribute("direction", &direction); + if (success == TIXML_SUCCESS) { + animation->setDirection(direction); + } + success = animationElem->QueryValueAttribute("action_frame", &actionFrame); + if (success == TIXML_SUCCESS) { + animation->setActionFrame(actionFrame); + } + animationElem->QueryValueAttribute("delay", &animDelay); + animationElem->QueryValueAttribute("x_offset", &animXoffset); + animationElem->QueryValueAttribute("y_offset", &animYoffset); + + for (TiXmlElement* frameElement = animationElem->FirstChildElement("frame"); frameElement; frameElement = frameElement->NextSiblingElement("frame")) { + const std::string* sourceId = frameElement->Attribute(std::string("source")); + if (sourceId) { + bfs::path framePath(filename); + + if (HasParentPath(framePath)) { + framePath = GetParentPath(framePath) / *sourceId; + if (!bfs::exists(framePath)) { + framePath = bfs::path(*sourceId); + } + } else { + framePath = bfs::path(*sourceId); + } + + ImagePtr imagePtr; + if (!m_imageManager->exists(framePath.string())) { + imagePtr = m_imageManager->create(framePath.string()); + } else { + imagePtr = m_imageManager->getPtr(framePath.string()); + } + + if (imagePtr) { + int frameXoffset = 0; + success = frameElement->QueryValueAttribute("x_offset", &frameXoffset); + if (success == TIXML_SUCCESS) { + imagePtr->setXShift(frameXoffset); + } else { + imagePtr->setXShift(animXoffset); + } + + int frameYoffset = 0; + success = frameElement->QueryValueAttribute("y_offset", &frameYoffset); + if (success == TIXML_SUCCESS) { + imagePtr->setYShift(frameYoffset); + } else { + imagePtr->setYShift(animYoffset); + } + + int frameDelay = 0; + success = frameElement->QueryValueAttribute("delay", &frameDelay); + if (success == TIXML_SUCCESS) { + animation->addFrame(imagePtr, frameDelay); + } else { + animation->addFrame(imagePtr, animDelay); + } + } + } + } + + return animation; + } } diff --git a/engine/core/loaders/native/map/animationloader.h b/engine/core/loaders/native/map/animationloader.h index dcf4b4468..a77bd099d 100644 --- a/engine/core/loaders/native/map/animationloader.h +++ b/engine/core/loaders/native/map/animationloader.h @@ -23,6 +23,7 @@ #define FIFE_ANIMATION_LOADER_H // Standard C++ library includes +#include // 3rd party library includes @@ -36,27 +37,36 @@ namespace FIFE { - class VFS; - class ImageManager; + class VFS; + class ImageManager; + class AnimationManager; - class AnimationLoader : public IAnimationLoader { - public: - AnimationLoader(VFS* vfs, ImageManager* imageManager); + class AnimationLoader : public IAnimationLoader { + public: + AnimationLoader(VFS* vfs, ImageManager* imageManager, AnimationManager* animationManager); - /** - * @see IAnimationLoader::isLoadable - */ - virtual bool isLoadable(const std::string& filename); + /** + * @see IAnimationLoader::isLoadable + */ + virtual bool isLoadable(const std::string& filename); - /** - * @see IAnimationLoader::load - */ - virtual AnimationPtr load(const std::string& filename); + /** + * @see IAnimationLoader::load + */ + virtual AnimationPtr load(const std::string& filename); - private: - VFS* m_vfs; - ImageManager* m_imageManager; - }; + /** + * @see IAnimationLoader::loadMultiple + */ + virtual std::vector loadMultiple(const std::string& filename); + + private: + AnimationPtr loadAnimation(const std::string& filename, TiXmlElement* animationElem); + + VFS* m_vfs; + ImageManager* m_imageManager; + AnimationManager* m_animationManager; + }; } #endif diff --git a/engine/core/loaders/native/map/atlasloader.cpp b/engine/core/loaders/native/map/atlasloader.cpp index 15c9b6050..2e5766023 100644 --- a/engine/core/loaders/native/map/atlasloader.cpp +++ b/engine/core/loaders/native/map/atlasloader.cpp @@ -37,6 +37,7 @@ #include "util/log/logger.h" #include "util/resource/resource.h" #include "util/resource/resourcemanager.h" +#include "video/animationmanager.h" #include "view/visual.h" #include "atlasloader.h" @@ -84,8 +85,8 @@ namespace FIFE { return m_name; } - AtlasLoader::AtlasLoader(Model* model, VFS* vfs, ImageManager* imageManager) - : m_model(model), m_vfs(vfs), m_imageManager(imageManager) { + AtlasLoader::AtlasLoader(Model* model, VFS* vfs, ImageManager* imageManager, AnimationManager* animationManager) + : m_model(model), m_vfs(vfs), m_imageManager(imageManager), m_animationManager(animationManager) { } AtlasLoader::~AtlasLoader() { @@ -118,21 +119,22 @@ namespace FIFE { return false; } - // if we get here then loading the file went well - TiXmlElement* root = atlasFile.RootElement(); + // if we get here then loading the file went well + TiXmlElement* root = atlasFile.RootElement(); - if (root && root->ValueStr() == "atlas") { - return true; - } - else { - return false; - } + if (root && root->ValueStr() == "assets") { + if (root->FirstChildElement("atlas")) { + return true; + } + } + + return false; } AtlasPtr AtlasLoader::load(const std::string& filename) { bfs::path atlasPath(filename); bfs::path atlasPathDirectory; - m_atlasFilename = atlasPath.string(); + std::string atlasFilename = atlasPath.string(); if (HasParentPath(atlasPath)) { // save the directory where the atlas file is located @@ -143,7 +145,7 @@ namespace FIFE { AtlasPtr atlas; try { - RawData* data = m_vfs->open(m_atlasFilename); + RawData* data = m_vfs->open(atlasFilename); if (data) { if (data->getDataLength() != 0) { @@ -173,289 +175,185 @@ namespace FIFE { // so we can just parse out the contents TiXmlElement* root = doc.RootElement(); - if (root && root->ValueStr() == "atlas") { - const std::string* atlasName = root->Attribute(std::string("name")); - if(atlasName) { - const std::string* namespaceId = root->Attribute(std::string("namespace")); - if(!namespaceId) { - namespaceId = atlasName; - } - - // Atlas itself doesn't have appended namespace - bfs::path atlasImagePath = atlasPathDirectory / *atlasName; - atlas.reset(new Atlas(atlasImagePath.string())); - - // End-user could create the same atlas for the second time. - // Since we don't hold any data for Atlases like ImageManager we need to recreate - // atlas parameters (to return proper AtlasPtr) but don't reload pixel data (they are held by ImageManager). - - bool atlasExists = m_imageManager->exists(atlas->getName()); - - if(!atlasExists) { - atlas->setPackedImage(m_imageManager->create(atlas->getName())); - } - else { - atlas->setPackedImage(m_imageManager->getPtr(atlas->getName())); - } - - // We don't really need this now, though we could use it to assert if the loaded atlas is the same sized as these - //int atlasWidth, atlasHeight; - //root->QueryValueAttribute("width", &atlasWidth); - //root->QueryValueAttribute("height", &atlasHeight); - bool subsExists = true; - for (TiXmlElement* imageElem = root->FirstChildElement("image"); - imageElem != 0; imageElem = imageElem->NextSiblingElement("image")) { - - Rect region; - imageElem->QueryValueAttribute("xpos", ®ion.x); - imageElem->QueryValueAttribute("ypos", ®ion.y); - imageElem->QueryValueAttribute("width", ®ion.w); - imageElem->QueryValueAttribute("height", ®ion.h); - - const std::string* subimageName = imageElem->Attribute(std::string("source")); - - if (subimageName) { - std::string finalname = *namespaceId + ":" +*subimageName; - ImagePtr subImage; - - bool subExists = m_imageManager->exists(finalname); - if (!subExists) { - subsExists = false; - subImage = m_imageManager->create(finalname); - } - else { - subImage = m_imageManager->getPtr(finalname); - } - subImage->useSharedImage(atlas->getPackedImage(), region); - - AtlasData atlas_data = {region, subImage}; - atlas->addImage(finalname, atlas_data); - } - } - subsExists = subsExists && atlasExists; - - // Now parse object definition - for(TiXmlElement* objElem = root->NextSiblingElement("object"); - objElem != 0; objElem = objElem->NextSiblingElement("object")) - { - // sanity check - if(objElem->ValueStr() == "object") { - parseObject(atlas.get(), objElem, subsExists); - } - } - } + if (root && root->ValueStr() == "assets") { + atlas = loadAtlas(filename, root->FirstChildElement("atlas")); } return atlas; } - void AtlasLoader::parseObject(Atlas* atlas, TiXmlElement* root, bool exists) { - const std::string* objectId = root->Attribute(std::string("id")); - const std::string* namespaceId = root->Attribute(std::string("namespace")); - - Object* obj = NULL; - if (objectId && namespaceId) { - const std::string* parentId = root->Attribute(std::string("parent")); - - if (parentId) { - Object* parent = m_model->getObject(*parentId, *namespaceId); - if (parent) { - try { - obj = m_model->createObject(*objectId, *namespaceId, parent); - } - catch (NameClash&) { - // TODO - handle exception - assert(false); - } - } - } - else { - // this will make sure the object has not already been loaded - if (m_model->getObject(*objectId, *namespaceId) == NULL) { - try { - obj = m_model->createObject(*objectId, *namespaceId); - } - catch (NameClash&) { - // TODO - handle exception - assert(false); - } - // if atlas or subimage was recreated then we have to update the ObjectVisual - } else if (!exists) { - obj = m_model->getObject(*objectId, *namespaceId); - ObjectVisual* objVisual = obj->getVisual(); - // make sure obj have visual - if (!objVisual) { - objVisual = ObjectVisual::create(obj); - } + std::vector AtlasLoader::loadMultiple(const std::string& filename) { + bfs::path atlasPath(filename); + bfs::path atlasPathDirectory; + std::string atlasFilename = atlasPath.string(); - for (TiXmlElement* imageElement = root->FirstChildElement("image"); imageElement; imageElement = imageElement->NextSiblingElement("image")) { - const std::string* sourceId = imageElement->Attribute(std::string("source")); + if (HasParentPath(atlasPath)) { + // save the directory where the atlas file is located + atlasPathDirectory = GetParentPath(atlasPath); + } - if (sourceId) { - std::string source = *namespaceId + ":" + *sourceId; - if(!m_imageManager->exists(source)) { - throw NotFound(source + " couldn't be found."); - } - ImagePtr imagePtr = m_imageManager->getPtr(source); + TiXmlDocument doc; + std::vector atlasVector; - int xOffset = 0; - int success = imageElement->QueryIntAttribute("x_offset", &xOffset); - if (success == TIXML_SUCCESS) { - imagePtr->setXShift(xOffset); - } + try { + RawData* data = m_vfs->open(atlasFilename); - int yOffset = 0; - success = imageElement->QueryIntAttribute("y_offset", &yOffset); - if (success == TIXML_SUCCESS) { - imagePtr->setYShift(yOffset); - } + if (data) { + if (data->getDataLength() != 0) { + doc.Parse(data->readString(data->getDataLength()).c_str()); - int direction = 0; - success = imageElement->QueryIntAttribute("direction", &direction); - if (success == TIXML_SUCCESS) { - if (objVisual) { - objVisual->addStaticImage(direction, static_cast(imagePtr->getHandle())); - } - } - } + if (doc.Error()) { + return atlasVector; } - return; + + // done with data delete resource + delete data; + data = 0; } } } + catch (NotFound& e) { + FL_ERR(_log, e.what()); - if (obj) { - //obj->setFilename(atlas->getName()); - obj->setFilename(m_atlasFilename); - ObjectVisual::create(obj); - - int isBlocking = 0; - root->QueryIntAttribute("blocking", &isBlocking); - obj->setBlocking(isBlocking!=0); - - int isStatic = 0; - root->QueryIntAttribute("static", &isStatic); - obj->setStatic(isStatic!=0); + // TODO - should we abort here + // or rethrow the exception + // or just keep going - const std::string* pather = root->Attribute(std::string("pather")); + return atlasVector; + } - if (pather) { - obj->setPather(m_model->getPather(*pather)); - } - else { - obj->setPather(m_model->getPather("RoutePather")); - } + // if we get here then everything loaded properly + // so we can just parse out the contents + TiXmlElement* root = doc.RootElement(); - const std::string* costId = root->Attribute(std::string("cost_id")); - if (costId) { - obj->setCostId(*costId); - double cost = 1.0; - int success = root->QueryDoubleAttribute("cost", &cost); - if (success == TIXML_SUCCESS) { - obj->setCost(cost); + if (root && root->ValueStr() == "assets") { + for (TiXmlElement* atlasElem = root->FirstChildElement("atlas"); atlasElem; atlasElem = atlasElem->NextSiblingElement("atlas")) { + AtlasPtr atlas = loadAtlas(filename, atlasElem); + if (atlas) { + atlasVector.push_back(atlas); } } - - const std::string* areaId = root->Attribute(std::string("area_id")); - if (areaId) { - obj->setArea(*areaId); - } + } - // loop over all walkable areas - for (TiXmlElement* walkableElement = root->FirstChildElement("walkable_area"); walkableElement; walkableElement = walkableElement->NextSiblingElement("walkable_area")) { - const std::string* walkableId = walkableElement->Attribute(std::string("id")); - if (walkableId) { - obj->addWalkableArea(*walkableId); - } - } + return atlasVector; + } - int cellStack = 0; - root->QueryIntAttribute("cellstack", &cellStack); - obj->setCellStackPosition(cellStack); - - double ax = 0; - double ay = 0; - double az = 0; - - int xRetVal = root->QueryValueAttribute("anchor_x", &ax); - int yRetVal = root->QueryValueAttribute("anchor_y", &ay); - if (xRetVal == TIXML_SUCCESS && yRetVal == TIXML_SUCCESS) { - obj->setRotationAnchor(ExactModelCoordinate(ax, ay, az)); - } + AtlasPtr AtlasLoader::loadAtlas(const std::string& filename, TiXmlElement* atlasElem) { + AtlasPtr atlas; + if (!atlasElem) { + return atlas; + } - int isRestrictedRotation = 0; - root->QueryIntAttribute("restricted_rotation", &isRestrictedRotation); - obj->setRestrictedRotation(isRestrictedRotation!=0); + const std::string* atlasSource = atlasElem->Attribute(std::string("source")); + if (atlasSource) { + const std::string* atlasId = atlasElem->Attribute(std::string("id")); - int zStep = 0; - int zRetVal = root->QueryIntAttribute("z_step_limit", &zStep); - if (zRetVal == TIXML_SUCCESS) { - obj->setZStepRange(zStep); + bfs::path atlasPath(filename); + bfs::path atlasPathDirectory; + if (HasParentPath(atlasPath)) { + // save the directory where the atlas file is located + atlasPathDirectory = GetParentPath(atlasPath); } - // loop over all multi parts - for (TiXmlElement* multiElement = root->FirstChildElement("multipart"); multiElement; multiElement = multiElement->NextSiblingElement("multipart")) { - const std::string* partId = multiElement->Attribute(std::string("id")); - if (partId) { - obj->addMultiPartId(*partId); - } - for (TiXmlElement* multiRotation = multiElement->FirstChildElement("rotation"); multiRotation; multiRotation = multiRotation->NextSiblingElement("rotation")) { - int rotation = 0; - multiRotation->QueryIntAttribute("rot", &rotation); - // relative coordinates which are used to position the object - for (TiXmlElement* multiCoordinate = multiRotation->FirstChildElement("occupied_coord"); multiCoordinate; multiCoordinate = multiCoordinate->NextSiblingElement("occupied_coord")) { - int x = 0; - int y = 0; - xRetVal = multiCoordinate->QueryValueAttribute("x", &x); - yRetVal = multiCoordinate->QueryValueAttribute("y", &y); - if (xRetVal == TIXML_SUCCESS && yRetVal == TIXML_SUCCESS) { - int z = 0; - multiCoordinate->QueryIntAttribute("z", &z); - obj->addMultiPartCoordinate(rotation, ModelCoordinate(x, y, z)); - } - } - } + // Atlas itself doesn't have appended id + bfs::path atlasImagePath = atlasPathDirectory / *atlasSource; + atlas.reset(new Atlas(atlasImagePath.string())); + + // End-user could create the same atlas for the second time. + // Since we don't hold any data for Atlases like ImageManager we need to recreate + // atlas parameters (to return proper AtlasPtr) but don't reload pixel data (they are held by ImageManager). + if (!m_imageManager->exists(atlas->getName())) { + atlas->setPackedImage(m_imageManager->create(atlas->getName())); + } else { + atlas->setPackedImage(m_imageManager->getPtr(atlas->getName())); } - // loop over all image tags - for (TiXmlElement* imageElement = root->FirstChildElement("image"); imageElement; imageElement = imageElement->NextSiblingElement("image")) { - const std::string* sourceId = imageElement->Attribute(std::string("source")); - - if (sourceId) { - std::string source = *namespaceId + ":" + *sourceId; - if(!m_imageManager->exists(source)) { - throw NotFound(source + " couldn't be found."); - } - ImagePtr imagePtr = m_imageManager->getPtr(source); - int xOffset = 0; - int success = imageElement->QueryIntAttribute("x_offset", &xOffset); - - if (success == TIXML_SUCCESS) { - imagePtr->setXShift(xOffset); - } + // Create subimages with given id and individual position and size + if (atlasElem->FirstChildElement("subimage")) { + for (TiXmlElement* imageElem = atlasElem->FirstChildElement("subimage"); + imageElem != 0; imageElem = imageElem->NextSiblingElement("subimage")) { + + const std::string* subimageId = imageElem->Attribute(std::string("id")); + if (subimageId) { + Rect region; + imageElem->QueryValueAttribute("xpos", ®ion.x); + imageElem->QueryValueAttribute("ypos", ®ion.y); + imageElem->QueryValueAttribute("width", ®ion.w); + imageElem->QueryValueAttribute("height", ®ion.h); + + std::string finalname; + // atlas id is optional here + if (atlasId) { + finalname = *atlasId + ":" + *subimageId; + } else { + finalname = *subimageId; + } + ImagePtr subImage; - int yOffset = 0; - success = imageElement->QueryIntAttribute("y_offset", &yOffset); + if (!m_imageManager->exists(finalname)) { + subImage = m_imageManager->create(finalname); + } else { + subImage = m_imageManager->getPtr(finalname); + } + subImage->useSharedImage(atlas->getPackedImage(), region); - if (success == TIXML_SUCCESS) { - imagePtr->setYShift(yOffset); + AtlasData atlasData = {region, subImage}; + atlas->addImage(finalname, atlasData); } + } + } else { + // Create subimages with automatic id and same size + int frame = 0; + int atlasWidth = 0; + int atlasHeight = 0; + int subimageWidth = 0; + int subimageHeight = 0; + atlasElem->QueryValueAttribute("atlas_width", &atlasWidth); + atlasElem->QueryValueAttribute("atlas_height", &atlasHeight); + atlasElem->QueryValueAttribute("subimage_width", &subimageWidth); + atlasElem->QueryValueAttribute("subimage_height", &subimageHeight); + // file extension of the atlas is also used as subimage extension + std::string extension = bfs::extension(*atlasSource); + // we need an atlas id + if (!atlasId) { + atlasId = atlasSource; + } + + if (atlasWidth != 0 && atlasHeight != 0 && subimageWidth != 0 && subimageHeight != 0) { + int x_rows = atlasWidth / subimageWidth; + int y_rows = atlasHeight / subimageHeight; + Rect region(0, 0, subimageWidth, subimageHeight); + for (int y = 0; y < y_rows; ++y) { + region.y = y * subimageHeight; + for (int x = 0; x < x_rows; ++x) { + region.x = x * subimageWidth; + + static char tmp[64]; + snprintf(tmp, 64, "%04d", frame); + std::ostringstream finalname; + finalname << *atlasId << ":" << std::string(tmp) << extension; + + ImagePtr subImage; + if (!m_imageManager->exists(finalname.str())) { + subImage = m_imageManager->create(finalname.str()); + } else { + subImage = m_imageManager->getPtr(finalname.str()); + } + subImage->useSharedImage(atlas->getPackedImage(), region); - int direction = 0; - success = imageElement->QueryIntAttribute("direction", &direction); - - if (success == TIXML_SUCCESS) { - ObjectVisual* objVisual = obj->getVisual(); + AtlasData atlasData = {region, subImage}; + atlas->addImage(finalname.str(), atlasData); - if (objVisual) { - objVisual->addStaticImage(direction, static_cast(imagePtr->getHandle())); + ++frame; } } } } } + + return atlas; } - AtlasLoader* createDefaultAtlasLoader(Model* model, VFS* vfs, ImageManager* imageManager) { - return new AtlasLoader(model, vfs, imageManager); + AtlasLoader* createDefaultAtlasLoader(Model* model, VFS* vfs, ImageManager* imageManager, AnimationManager* animationManager) { + return new AtlasLoader(model, vfs, imageManager, animationManager); } } diff --git a/engine/core/loaders/native/map/atlasloader.h b/engine/core/loaders/native/map/atlasloader.h index 1d16fc40d..f3a521ac4 100644 --- a/engine/core/loaders/native/map/atlasloader.h +++ b/engine/core/loaders/native/map/atlasloader.h @@ -41,6 +41,7 @@ class TiXmlElement; namespace FIFE { class VFS; class ImageManager; + class AnimationManager; struct AtlasData { Rect rect; @@ -93,7 +94,7 @@ namespace FIFE { class AtlasLoader : public IAtlasLoader { public: - AtlasLoader(Model* model, VFS* vfs, ImageManager* imageManager); + AtlasLoader(Model* model, VFS* vfs, ImageManager* imageManager, AnimationManager* animationManager); virtual ~AtlasLoader(); @@ -107,20 +108,25 @@ namespace FIFE { */ virtual AtlasPtr load(const std::string& filename); + /** + * @see IAtlasLoader::loadMultiple + */ + virtual std::vector loadMultiple(const std::string& filename); + private: + AtlasPtr loadAtlas(const std::string& filename, TiXmlElement* atlasElem); + Model* m_model; VFS* m_vfs; ImageManager* m_imageManager; - std::string m_atlasFilename; - - void parseObject(Atlas* atlas, TiXmlElement* root, bool exists); + AnimationManager* m_animationManager; }; /** convenience function for creating the default fife atlas loader * deleting the object returned from this function is the * responsibility of the caller */ - AtlasLoader* createDefaultAtlasLoader(Model* model, VFS* vfs, ImageManager* imageManager); + AtlasLoader* createDefaultAtlasLoader(Model* model, VFS* vfs, ImageManager* imageManager, AnimationManager* animationManager); } #endif diff --git a/engine/core/loaders/native/map/ianimationloader.h b/engine/core/loaders/native/map/ianimationloader.h index db83512be..060f680ea 100644 --- a/engine/core/loaders/native/map/ianimationloader.h +++ b/engine/core/loaders/native/map/ianimationloader.h @@ -47,6 +47,11 @@ namespace FIFE { * returns a shared pointer to an animation resource */ virtual AnimationPtr load(const std::string& filename) = 0; + + /** responsible for loading all animations + * returns a vector of shared pointer to an animation resource + */ + virtual std::vector loadMultiple(const std::string& filename) = 0; }; typedef SharedPtr AnimationLoaderPtr; diff --git a/engine/core/loaders/native/map/iatlasloader.h b/engine/core/loaders/native/map/iatlasloader.h index 2c5bc691b..48cc82d19 100644 --- a/engine/core/loaders/native/map/iatlasloader.h +++ b/engine/core/loaders/native/map/iatlasloader.h @@ -23,6 +23,7 @@ #define FIFE_IATLAS_LOADER_H // Standard C++ library includes +#include // 3rd party library includes @@ -49,6 +50,11 @@ namespace FIFE { * returns a shared pointer to an image resource */ virtual AtlasPtr load(const std::string& filename) = 0; + + /** responsible for loading the all atlases + * returns a vector of shared pointer to an image resource + */ + virtual std::vector loadMultiple(const std::string& filename) = 0; }; typedef SharedPtr AtlasLoaderPtr; diff --git a/engine/core/loaders/native/map/iobjectloader.h b/engine/core/loaders/native/map/iobjectloader.h index 5cf924995..d198067c5 100644 --- a/engine/core/loaders/native/map/iobjectloader.h +++ b/engine/core/loaders/native/map/iobjectloader.h @@ -34,33 +34,42 @@ #include "util/base/sharedptr.h" #include "ianimationloader.h" +#include "iatlasloader.h" namespace FIFE { - /** Interface class that all object loaders should derive from - */ - class IObjectLoader { - public: - virtual ~IObjectLoader() { }; + /** Interface class that all object loaders should derive from + */ + class IObjectLoader { + public: + virtual ~IObjectLoader() { }; - /** allows setting which animation loader will be - * used to load animation files - */ - virtual void setAnimationLoader(const AnimationLoaderPtr& animationLoader) = 0; + /** allows setting which animation loader will be + * used to load animation files + */ + virtual void setAnimationLoader(const AnimationLoaderPtr& animationLoader) = 0; - /** determines whether the resource is in - * the correct format for this loader - */ - virtual bool isLoadable(const std::string& filename) const = 0; + virtual AnimationLoaderPtr getAnimationLoader() = 0; - /** responsible for loading the object resource - * and populating the engine - */ - virtual void load(const std::string& filename) = 0; + /** allows setting which atlas loader will be + * used to load atlas files + */ + virtual void setAtlasLoader(const AtlasLoaderPtr& atlasLoader) = 0; - }; + virtual AtlasLoaderPtr getAtlasLoader() = 0; - typedef SharedPtr ObjectLoaderPtr; + /** determines whether the resource is in + * the correct format for this loader + */ + virtual bool isLoadable(const std::string& filename) const = 0; + + /** responsible for loading the object resource + * and populating the engine + */ + virtual void load(const std::string& filename) = 0; + }; + + typedef SharedPtr ObjectLoaderPtr; } #endif \ No newline at end of file diff --git a/engine/core/loaders/native/map/maploader.cpp b/engine/core/loaders/native/map/maploader.cpp index aa815f701..7a29864f3 100644 --- a/engine/core/loaders/native/map/maploader.cpp +++ b/engine/core/loaders/native/map/maploader.cpp @@ -49,6 +49,7 @@ #include "util/resource/resource.h" #include "util/structures/rect.h" #include "video/imagemanager.h" +#include "video/animationmanager.h" #include "video/image.h" #include "video/renderbackend.h" #include "view/visual.h" @@ -65,21 +66,21 @@ namespace FIFE { /** Logger to use for this source file. * @relates Logger */ - static Logger _log(LM_NATIVE_LOADERS); + static Logger _log(LM_NATIVE_LOADERS); MapLoader::MapLoader(Model* model, VFS* vfs, ImageManager* imageManager, RenderBackend* renderBackend) - : m_model(model), m_vfs(vfs), m_imageManager(imageManager), m_renderBackend(renderBackend), + : m_model(model), m_vfs(vfs), m_imageManager(imageManager), m_animationManager(AnimationManager::instance()), m_renderBackend(renderBackend), m_loaderName("fife"), m_mapDirectory("") { - AnimationLoaderPtr animationLoader(new AnimationLoader(m_vfs, m_imageManager)); - m_objectLoader.reset(new ObjectLoader(m_model, m_vfs, m_imageManager, animationLoader)); - m_atlasLoader.reset(new AtlasLoader(m_model, m_vfs, m_imageManager)); + AnimationLoaderPtr animationLoader(new AnimationLoader(m_vfs, m_imageManager, m_animationManager)); + AtlasLoaderPtr atlasLoader(new AtlasLoader(m_model, m_vfs, m_imageManager, m_animationManager)); + m_objectLoader.reset(new ObjectLoader(m_model, m_vfs, m_imageManager, m_animationManager, animationLoader, atlasLoader)); } - MapLoader::~MapLoader() { + MapLoader::~MapLoader() { - } + } - Map* MapLoader::load(const std::string& filename) { + Map* MapLoader::load(const std::string& filename) { Map* map = NULL; // reset percent done listener just in case @@ -89,54 +90,54 @@ namespace FIFE { bfs::path mapPath(filename); if (HasParentPath(mapPath)) { - if (GetParentPath(mapPath).string() != m_mapDirectory) { - // save the directory where the map file is located - m_mapDirectory = GetParentPath(mapPath).string(); - } + if (GetParentPath(mapPath).string() != m_mapDirectory) { + // save the directory where the map file is located + m_mapDirectory = GetParentPath(mapPath).string(); + } } TiXmlDocument mapFile; - std::string mapFilename = mapPath.string(); - - try { - RawData* data = m_vfs->open(mapFilename); - - if (data) { - if (data->getDataLength() != 0) { - mapFile.Parse(data->readString(data->getDataLength()).c_str()); - - if (mapFile.Error()) { - std::ostringstream oss; - oss << " Failed to load" - << mapFilename - << " : " << __FILE__ - << " [" << __LINE__ << "]" - << std::endl; - FL_ERR(_log, oss.str()); - - return map; - } - } - - // done with data delete resource - delete data; - data = 0; - } - } - catch (NotFound& e) - { - FL_ERR(_log, e.what()); - - // TODO - should we abort here - // or rethrow the exception - // or just keep going - - return map; - } - - // if we get here then everything loaded properly - // so we can just parse out the contents + std::string mapFilename = mapPath.string(); + + try { + RawData* data = m_vfs->open(mapFilename); + + if (data) { + if (data->getDataLength() != 0) { + mapFile.Parse(data->readString(data->getDataLength()).c_str()); + + if (mapFile.Error()) { + std::ostringstream oss; + oss << " Failed to load" + << mapFilename + << " : " << __FILE__ + << " [" << __LINE__ << "]" + << std::endl; + FL_ERR(_log, oss.str()); + + return map; + } + } + + // done with data delete resource + delete data; + data = 0; + } + } + catch (NotFound& e) + { + FL_ERR(_log, e.what()); + + // TODO - should we abort here + // or rethrow the exception + // or just keep going + + return map; + } + + // if we get here then everything loaded properly + // so we can just parse out the contents const TiXmlElement* root = mapFile.RootElement(); if (root) { @@ -159,46 +160,46 @@ namespace FIFE { catch (NameClash& e) { FL_ERR(_log, e.what()); - // just rethrow to client - throw; + // just rethrow to client + throw; } if (map) { - map->setFilename(mapFilename); + map->setFilename(mapFilename); std::string ns = ""; for (const TiXmlElement *importElement = root->FirstChildElement("import"); importElement; importElement = importElement->NextSiblingElement("import")) { const std::string* importDir = importElement->Attribute(std::string("dir")); const std::string* importFile = importElement->Attribute(std::string("file")); - std::string directory = ""; - if (importDir) { - directory = *importDir; - } - - std::string file = ""; - if (importFile) { - file = *importFile; - } - - if (importDir && !importFile) { - bfs::path fullPath(m_mapDirectory); - fullPath /= directory; - loadImportDirectory(fullPath.string()); - } - else if (importFile) { - bfs::path fullFilePath(file); - bfs::path fullDirPath(directory); - if (importDir) { - fullDirPath = bfs::path(m_mapDirectory); - fullDirPath /= directory; - } - else { - fullFilePath = bfs::path(m_mapDirectory); - fullFilePath /= file; - } - loadImportFile(fullFilePath.string(), fullDirPath.string()); - } + std::string directory = ""; + if (importDir) { + directory = *importDir; + } + + std::string file = ""; + if (importFile) { + file = *importFile; + } + + if (importDir && !importFile) { + bfs::path fullPath(m_mapDirectory); + fullPath /= directory; + loadImportDirectory(fullPath.string()); + } + else if (importFile) { + bfs::path fullFilePath(file); + bfs::path fullDirPath(directory); + if (importDir) { + fullDirPath = bfs::path(m_mapDirectory); + fullDirPath /= directory; + } + else { + fullFilePath = bfs::path(m_mapDirectory); + fullFilePath /= file; + } + loadImportFile(fullFilePath.string(), fullDirPath.string()); + } } // converts multiobject part id to object pointer std::list namespaces = m_model->getNamespaces(); @@ -432,16 +433,16 @@ namespace FIFE { inst->actRepeat("default", target); } } - else - { - std::ostringstream oss; - oss << " Failed to create instance of object " - << *objectId - << " : " << __FILE__ - << " [" << __LINE__ << "]" - << std::endl; - FL_ERR(_log, oss.str()); - } + else + { + std::ostringstream oss; + oss << " Failed to create instance of object " + << *objectId + << " : " << __FILE__ + << " [" << __LINE__ << "]" + << std::endl; + FL_ERR(_log, oss.str()); + } } } @@ -744,12 +745,12 @@ namespace FIFE { cam->setZToY(zToY); } - // active instance renderer for camera - InstanceRenderer* instanceRenderer = InstanceRenderer::getInstance(cam); - if (instanceRenderer) - { - instanceRenderer->activateAllLayers(map); - } + // active instance renderer for camera + InstanceRenderer* instanceRenderer = InstanceRenderer::getInstance(cam); + if (instanceRenderer) + { + instanceRenderer->activateAllLayers(map); + } } } @@ -763,118 +764,138 @@ namespace FIFE { return map; } - void MapLoader::setObjectLoader(const FIFE::ObjectLoaderPtr& objectLoader) { - assert(objectLoader); + void MapLoader::setObjectLoader(const FIFE::ObjectLoaderPtr& objectLoader) { + assert(objectLoader); - m_objectLoader = objectLoader; - } + m_objectLoader = objectLoader; + } + FIFE::ObjectLoaderPtr MapLoader::getObjectLoader() { + return m_objectLoader; + } - void MapLoader::setAnimationLoader(const FIFE::AnimationLoaderPtr& animationLoader) { - assert(animationLoader); + void MapLoader::setAnimationLoader(const FIFE::AnimationLoaderPtr& animationLoader) { + assert(animationLoader); - m_objectLoader->setAnimationLoader(animationLoader); - } + m_objectLoader->setAnimationLoader(animationLoader); + } - void MapLoader::setAtlasLoader(const FIFE::AtlasLoaderPtr& atlasLoader) { - assert(atlasLoader); + FIFE::AnimationLoaderPtr MapLoader::getAnimationLoader() { + if (m_objectLoader) { + return m_objectLoader->getAnimationLoader(); + } + return FIFE::AnimationLoaderPtr(); + } + + void MapLoader::setAtlasLoader(const FIFE::AtlasLoaderPtr& atlasLoader) { + assert(atlasLoader); + + m_objectLoader->setAtlasLoader(atlasLoader); + } - m_atlasLoader = atlasLoader; - } + FIFE::AtlasLoaderPtr MapLoader::getAtlasLoader() { + if (m_objectLoader) { + return m_objectLoader->getAtlasLoader(); + } + return FIFE::AtlasLoaderPtr(); + } - bool MapLoader::isLoadable(const std::string& filename) const { + bool MapLoader::isLoadable(const std::string& filename) const { bfs::path mapPath(filename); TiXmlDocument mapFile; - std::string mapFilename = mapPath.string(); + std::string mapFilename = mapPath.string(); - try { - RawData* data = m_vfs->open(mapFilename); + try { + RawData* data = m_vfs->open(mapFilename); - if (data) { - if (data->getDataLength() != 0) { - mapFile.Parse(data->readString(data->getDataLength()).c_str()); + if (data) { + if (data->getDataLength() != 0) { + mapFile.Parse(data->readString(data->getDataLength()).c_str()); - if (mapFile.Error()) { - return false; - } + if (mapFile.Error()) { + return false; + } - const TiXmlElement* root = mapFile.RootElement(); + const TiXmlElement* root = mapFile.RootElement(); - if (root) { - const std::string* loaderName = root->Attribute(std::string("loader")); + if (root) { + const std::string* loaderName = root->Attribute(std::string("loader")); - // if the file does not specify a loader but was opened and parsed - // correctly then we know we have a compatible extension so we will - // attempt to load it, if it does specify a loader then the loader - // name will be checked - if (!loaderName || (loaderName && *loaderName == getLoaderName())) { - return true; - } - } - } + // if the file does not specify a loader but was opened and parsed + // correctly then we know we have a compatible extension so we will + // attempt to load it, if it does specify a loader then the loader + // name will be checked + if (!loaderName || (loaderName && *loaderName == getLoaderName())) { + return true; + } + } + } - // done with file delete the resource - delete data; - data = 0; - } - } - catch (NotFound& e) { - FL_ERR(_log, e.what()); + // done with file delete the resource + delete data; + data = 0; + } + } + catch (NotFound& e) { + FL_ERR(_log, e.what()); - return false; - } + return false; + } - return false; + return false; } - void MapLoader::loadImportFile(const std::string& file, const std::string& directory) { - if (!file.empty()) { - bfs::path importFilePath(directory); - importFilePath /= file; - - std::string importFileString = importFilePath.string(); - if (m_objectLoader && m_objectLoader->isLoadable(importFileString)) { - m_objectLoader->load(importFileString); - } - else if (m_atlasLoader && m_atlasLoader->isLoadable(importFileString)) { - m_atlasLoader->load(importFileString); - } - } - } - - void MapLoader::loadImportDirectory(const std::string& directory) { - if (!directory.empty()) { - bfs::path importDirectory(directory); - std::string importDirectoryString = importDirectory.string(); - - std::set files = m_vfs->listFiles(importDirectoryString); - - // load all xml files in the directory - std::set::iterator iter; - for (iter = files.begin(); iter != files.end(); ++iter) { - // TODO - vtchill - may need a way to allow clients to load things other - // than .xml and .zip files - std::string ext = bfs::extension(*iter); - if (ext == ".xml" || ext == ".zip") { - loadImportFile(*iter, importDirectoryString); - } - } - - std::set nestedDirectories = m_vfs->listDirectories(importDirectoryString); - for (iter = nestedDirectories.begin(); iter != nestedDirectories.end(); ++iter) { - // do not attempt to load anything from a .svn directory - if ((*iter).find(".svn") == std::string::npos) { - loadImportDirectory(importDirectoryString + "/" + *iter); - } - } - } - } - - void MapLoader::addPercentDoneListener(PercentDoneListener* listener) { - m_percentDoneListener.addListener(listener); - } + void MapLoader::loadImportFile(const std::string& file, const std::string& directory) { + if (!file.empty()) { + bfs::path importFilePath(directory); + importFilePath /= file; + + std::string importFileString = importFilePath.string(); + if (m_objectLoader && m_objectLoader->getAtlasLoader() && m_objectLoader->getAtlasLoader()->isLoadable(importFileString)) { + m_objectLoader->getAtlasLoader()->loadMultiple(importFileString); + } + if (m_objectLoader && m_objectLoader->getAnimationLoader() && m_objectLoader->getAnimationLoader()->isLoadable(importFileString)) { + m_objectLoader->getAnimationLoader()->loadMultiple(importFileString); + } + if (m_objectLoader && m_objectLoader->isLoadable(importFileString)) { + m_objectLoader->load(importFileString); + } + } + } + + void MapLoader::loadImportDirectory(const std::string& directory) { + if (!directory.empty()) { + bfs::path importDirectory(directory); + std::string importDirectoryString = importDirectory.string(); + + std::set files = m_vfs->listFiles(importDirectoryString); + + // load all xml files in the directory + std::set::iterator iter; + for (iter = files.begin(); iter != files.end(); ++iter) { + // TODO - vtchill - may need a way to allow clients to load things other + // than .xml and .zip files + std::string ext = bfs::extension(*iter); + if (ext == ".xml" || ext == ".zip") { + loadImportFile(*iter, importDirectoryString); + } + } + + std::set nestedDirectories = m_vfs->listDirectories(importDirectoryString); + for (iter = nestedDirectories.begin(); iter != nestedDirectories.end(); ++iter) { + // do not attempt to load anything from a .svn directory + if ((*iter).find(".svn") == std::string::npos) { + loadImportDirectory(importDirectoryString + "/" + *iter); + } + } + } + } + + void MapLoader::addPercentDoneListener(PercentDoneListener* listener) { + m_percentDoneListener.addListener(listener); + } const std::string& MapLoader::getLoaderName() const { return m_loaderName; diff --git a/engine/core/loaders/native/map/maploader.h b/engine/core/loaders/native/map/maploader.h index e597eccfe..dfc8ead75 100644 --- a/engine/core/loaders/native/map/maploader.h +++ b/engine/core/loaders/native/map/maploader.h @@ -43,71 +43,87 @@ namespace FIFE { class VFS; class Layer; class ImageManager; + class AnimationManager; class RenderBackend; class PercentDoneListener; class MapLoader : public IMapLoader { public: MapLoader(Model* model, VFS* vfs, ImageManager* imageManager, RenderBackend* renderBackend); - - ~MapLoader(); - - /** - * @see IMapLoader::setObjectLoader - */ - void setObjectLoader(const FIFE::ObjectLoaderPtr& objectLoader); - - /** - * @see IMapLoader::setAnimationLoader - */ - void setAnimationLoader(const FIFE::AnimationLoaderPtr& animationLoader); - - /** - * @see IMapLoader::setAtlasLoader - */ - void setAtlasLoader(const FIFE::AtlasLoaderPtr& atlasLoader); - - /** - * @see IMapLoader::isLoadable - */ - bool isLoadable(const std::string& filename) const; - - /** - * @see IMapLoader::load - */ - Map* load(const std::string& filename); - - /** used to load an object file - * if directory is provided then file is assumed relative to directory - * if relativeToMap is true then the file/directory is assumed to be relative to - * location of map file - */ - void loadImportFile(const std::string& file, const std::string& directory=""); - - /** used to load a directory of object files recursively - * if relativeToMap is true then the directory is assumed to be relative to - * location of map file - */ - void loadImportDirectory(const std::string& directory); - - /** - * allows adding a listener to the map loader - * for percent completed events - */ + + ~MapLoader(); + + /** + * @see IMapLoader::setObjectLoader + */ + void setObjectLoader(const FIFE::ObjectLoaderPtr& objectLoader); + + /** + * @see IMapLoader::getObjectLoader + */ + FIFE::ObjectLoaderPtr getObjectLoader(); + + /** + * @see IMapLoader::setAnimationLoader + */ + void setAnimationLoader(const FIFE::AnimationLoaderPtr& animationLoader); + + /** + * @see IMapLoader::getAnimationLoader + */ + FIFE::AnimationLoaderPtr getAnimationLoader(); + + /** + * @see IMapLoader::setAtlasLoader + */ + void setAtlasLoader(const FIFE::AtlasLoaderPtr& atlasLoader); + + /** + * @see IMapLoader::getAtlasLoader + */ + FIFE::AtlasLoaderPtr getAtlasLoader(); + + /** + * @see IMapLoader::isLoadable + */ + bool isLoadable(const std::string& filename) const; + + /** + * @see IMapLoader::load + */ + Map* load(const std::string& filename); + + /** used to load an object file + * if directory is provided then file is assumed relative to directory + * if relativeToMap is true then the file/directory is assumed to be relative to + * location of map file + */ + void loadImportFile(const std::string& file, const std::string& directory=""); + + /** used to load a directory of object files recursively + * if relativeToMap is true then the directory is assumed to be relative to + * location of map file + */ + void loadImportDirectory(const std::string& directory); + + /** + * allows adding a listener to the map loader + * for percent completed events + */ void addPercentDoneListener(PercentDoneListener* listener); - /** returns the loader name associated with this - * map file loader, this will only be populated - * after the load function is called - */ - const std::string& getLoaderName() const; + /** returns the loader name associated with this + * map file loader, this will only be populated + * after the load function is called + */ + const std::string& getLoaderName() const; private: Model* m_model; VFS* m_vfs; ImageManager* m_imageManager; - ObjectLoaderPtr m_objectLoader; - AtlasLoaderPtr m_atlasLoader; + AnimationManager* m_animationManager; + ObjectLoaderPtr m_objectLoader; RenderBackend* m_renderBackend; PercentDoneCallback m_percentDoneListener; @@ -117,10 +133,10 @@ namespace FIFE { }; - /** convenience function for creating the default fife map loader - * deleting the object returned from this function is the - * responsibility of the caller - */ + /** convenience function for creating the default fife map loader + * deleting the object returned from this function is the + * responsibility of the caller + */ MapLoader* createDefaultMapLoader(Model* model, VFS* vfs, ImageManager* imageManager, RenderBackend* renderBackend); } diff --git a/engine/core/loaders/native/map/objectloader.cpp b/engine/core/loaders/native/map/objectloader.cpp index 085746bf5..77ac59072 100644 --- a/engine/core/loaders/native/map/objectloader.cpp +++ b/engine/core/loaders/native/map/objectloader.cpp @@ -37,7 +37,9 @@ #include "vfs/raw/rawdata.h" #include "view/visual.h" #include "video/imagemanager.h" +#include "video/animationmanager.h" +#include "atlasloader.h" #include "objectloader.h" #include "animationloader.h" @@ -45,479 +47,604 @@ namespace FIFE { /** Logger to use for this source file. * @relates Logger */ - static Logger _log(LM_NATIVE_LOADERS); - - ObjectLoader::ObjectLoader(Model* model, VFS* vfs, ImageManager* imageManager, const AnimationLoaderPtr& animationLoader) - : m_model(model), m_vfs(vfs), m_imageManager(imageManager) { - assert(m_model && m_vfs && m_imageManager); - - if (animationLoader) { - m_animationLoader = animationLoader; - } - else { - m_animationLoader.reset(new AnimationLoader(m_vfs, m_imageManager)); - } - } - - ObjectLoader::~ObjectLoader() { - - } - - void ObjectLoader::setAnimationLoader(const AnimationLoaderPtr& animationLoader) { - assert(animationLoader); - - m_animationLoader = animationLoader; - } - - bool ObjectLoader::isLoadable(const std::string& filename) const { - bfs::path objectPath(filename); - - TiXmlDocument objectFile; - - try { - RawData* data = m_vfs->open(objectPath.string()); - - if (data) { - if (data->getDataLength() != 0) { - objectFile.Parse(data->readString(data->getDataLength()).c_str()); - - if (objectFile.Error()) { - std::ostringstream oss; - oss << " Failed to load" - << objectPath.string() - << " : " << __FILE__ - << " [" << __LINE__ << "]" - << std::endl; - FL_ERR(_log, oss.str()); - - return false; - } - } - else { - std::ostringstream oss; - oss << " Failed to load" - << objectPath.string() - << " : " << __FILE__ - << " [" << __LINE__ << "]" - << std::endl; - FL_ERR(_log, oss.str()); - - return false; - } - - // done with data delete resource - delete data; - data = 0; - } - else { - std::ostringstream oss; - oss << " Failed to load" - << objectPath.string() - << " : " << __FILE__ - << " [" << __LINE__ << "]" - << std::endl; - FL_ERR(_log, oss.str()); - - return false; - } - } - catch (NotFound&) { - std::ostringstream oss; - oss << " Failed to load" - << objectPath.string() - << " : " << __FILE__ - << " [" << __LINE__ << "]" - << std::endl; - FL_ERR(_log, oss.str()); - - // TODO - should we abort here - // or rethrow the exception - // or just keep going - - return false; - } - - // if we get here then loading the file went well - TiXmlElement* root = objectFile.RootElement(); - - if (root && root->ValueStr() == "object") { - return true; - } - else { - return false; - } - } - - void ObjectLoader::load(const std::string& filename) { - bfs::path objectPath(filename); - - TiXmlDocument objectFile; - - try { - RawData* data = m_vfs->open(objectPath.string()); - - if (data) { - if (data->getDataLength() != 0) { - objectFile.Parse(data->readString(data->getDataLength()).c_str()); - - if (objectFile.Error()) { - return; - } - } - - // done with data delete resource - delete data; - data = 0; - } - } - catch (NotFound&) { - std::ostringstream oss; - oss << " Failed to load" - << objectPath.string() - << " : " << __FILE__ - << " [" << __LINE__ << "]" - << std::endl; - FL_ERR(_log, oss.str()); - - // TODO - should we abort here - // or rethrow the exception - // or just keep going - - return; - } - - // if we get here then loading the file went well - TiXmlElement* root = objectFile.RootElement(); - - if (root && root->ValueStr() == "object") { - const std::string* objectId = root->Attribute(std::string("id")); - const std::string* namespaceId = root->Attribute(std::string("namespace")); - - Object* obj = NULL; - if (objectId && namespaceId) { - const std::string* parentId = root->Attribute(std::string("parent")); - - if (parentId) { - Object* parent = m_model->getObject(*parentId, *namespaceId); - if (parent) { - try { - obj = m_model->createObject(*objectId, *namespaceId, parent); - } - catch (NameClash&) { - // TODO - handle exception - assert(false); - } - } - } - else { - // this will make sure the object has not already been loaded - if (m_model->getObject(*objectId, *namespaceId) == NULL) { - try { - obj = m_model->createObject(*objectId, *namespaceId); - } - catch (NameClash &e) { - FL_ERR(_log, e.what()); - - // TODO - handle exception - assert(false); - } - } - } - } - - if (obj) { - obj->setFilename(objectPath.string()); - ObjectVisual::create(obj); - - int isBlocking = 0; - root->QueryIntAttribute("blocking", &isBlocking); - obj->setBlocking(isBlocking!=0); - - int isStatic = 0; - root->QueryIntAttribute("static", &isStatic); - obj->setStatic(isStatic!=0); - - const std::string* pather = root->Attribute(std::string("pather")); - - if (pather) { - obj->setPather(m_model->getPather(*pather)); - } - else { - obj->setPather(m_model->getPather("RoutePather")); - } - - const std::string* costId = root->Attribute(std::string("cost_id")); - if (costId) { - obj->setCostId(*costId); - double cost = 1.0; - int success = root->QueryDoubleAttribute("cost", &cost); - if (success == TIXML_SUCCESS) { - obj->setCost(cost); + static Logger _log(LM_NATIVE_LOADERS); + + ObjectLoader::ObjectLoader(Model* model, VFS* vfs, ImageManager* imageManager, AnimationManager* animationManager, const AnimationLoaderPtr& animationLoader, const AtlasLoaderPtr& atlasLoader) + : m_model(model), m_vfs(vfs), m_imageManager(imageManager), m_animationManager(animationManager) { + assert(m_model && m_vfs && m_imageManager && m_animationManager); + + if (animationLoader) { + m_animationLoader = animationLoader; + } + else { + m_animationLoader.reset(new AnimationLoader(m_vfs, m_imageManager, m_animationManager)); + } + + if (atlasLoader) { + m_atlasLoader = atlasLoader; + } + else { + m_atlasLoader.reset(new AtlasLoader(m_model, m_vfs, m_imageManager, m_animationManager)); + } + } + + ObjectLoader::~ObjectLoader() { + + } + + void ObjectLoader::setAnimationLoader(const AnimationLoaderPtr& animationLoader) { + assert(animationLoader); + + m_animationLoader = animationLoader; + } + + AnimationLoaderPtr ObjectLoader::getAnimationLoader() { + return m_animationLoader; + } + + void ObjectLoader::setAtlasLoader(const AtlasLoaderPtr& atlasLoader) { + assert(atlasLoader); + + m_atlasLoader = atlasLoader; + } + + AtlasLoaderPtr ObjectLoader::getAtlasLoader() { + return m_atlasLoader; + } + + bool ObjectLoader::isLoadable(const std::string& filename) const { + bfs::path objectPath(filename); + + TiXmlDocument objectFile; + + try { + RawData* data = m_vfs->open(objectPath.string()); + + if (data) { + if (data->getDataLength() != 0) { + objectFile.Parse(data->readString(data->getDataLength()).c_str()); + + if (objectFile.Error()) { + std::ostringstream oss; + oss << " Failed to load" + << objectPath.string() + << " : " << __FILE__ + << " [" << __LINE__ << "]" + << std::endl; + FL_ERR(_log, oss.str()); + + return false; } } - - double speed = 1.0; - int success = root->QueryDoubleAttribute("speed", &speed); - if (success == TIXML_SUCCESS) { - obj->setSpeed(speed); - } - - const std::string* areaId = root->Attribute(std::string("area_id")); - if (areaId) { - obj->setArea(*areaId); + else { + std::ostringstream oss; + oss << " Failed to load" + << objectPath.string() + << " : " << __FILE__ + << " [" << __LINE__ << "]" + << std::endl; + FL_ERR(_log, oss.str()); + + return false; } - // loop over all walkable areas - for (TiXmlElement* walkableElement = root->FirstChildElement("walkable_area"); walkableElement; walkableElement = walkableElement->NextSiblingElement("walkable_area")) { - const std::string* walkableId = walkableElement->Attribute(std::string("id")); - if (walkableId) { - obj->addWalkableArea(*walkableId); + // done with data delete resource + delete data; + data = 0; + } + else { + std::ostringstream oss; + oss << " Failed to load" + << objectPath.string() + << " : " << __FILE__ + << " [" << __LINE__ << "]" + << std::endl; + FL_ERR(_log, oss.str()); + + return false; + } + } + catch (NotFound&) { + std::ostringstream oss; + oss << " Failed to load" + << objectPath.string() + << " : " << __FILE__ + << " [" << __LINE__ << "]" + << std::endl; + FL_ERR(_log, oss.str()); + + // TODO - should we abort here + // or rethrow the exception + // or just keep going + + return false; + } + + // if we get here then loading the file went well + TiXmlElement* root = objectFile.RootElement(); + + if (root && root->ValueStr() == "assets") { + if (root->FirstChildElement("object")) { + return true; + } + } + + return false; + } + + void ObjectLoader::load(const std::string& filename) { + bfs::path objectPath(filename); + + TiXmlDocument objectFile; + + try { + RawData* data = m_vfs->open(objectPath.string()); + + if (data) { + if (data->getDataLength() != 0) { + objectFile.Parse(data->readString(data->getDataLength()).c_str()); + + if (objectFile.Error()) { + return; } } - int cellStack = 0; - root->QueryIntAttribute("cellstack", &cellStack); - obj->setCellStackPosition(cellStack); - - double ax = 0; - double ay = 0; - double az = 0; - - int xRetVal = root->QueryValueAttribute("anchor_x", &ax); - int yRetVal = root->QueryValueAttribute("anchor_y", &ay); - if (xRetVal == TIXML_SUCCESS && yRetVal == TIXML_SUCCESS) { - obj->setRotationAnchor(ExactModelCoordinate(ax, ay, az)); + // done with data delete resource + delete data; + data = 0; + } + } + catch (NotFound&) { + std::ostringstream oss; + oss << " Failed to load" + << objectPath.string() + << " : " << __FILE__ + << " [" << __LINE__ << "]" + << std::endl; + FL_ERR(_log, oss.str()); + + // TODO - should we abort here + // or rethrow the exception + // or just keep going + + return; + } + std::string objectDirectory = ""; + if (HasParentPath(objectPath)) { + objectDirectory = GetParentPath(objectPath).string(); + } + + // if we get here then loading the file went well + TiXmlElement* root = objectFile.RootElement(); + if (root) { + for (const TiXmlElement *importElement = root->FirstChildElement("import"); importElement; importElement = importElement->NextSiblingElement("import")) { + const std::string* importDir = importElement->Attribute(std::string("dir")); + const std::string* importFile = importElement->Attribute(std::string("file")); + + std::string directory = ""; + if (importDir) { + directory = *importDir; } - int isRestrictedRotation = 0; - root->QueryIntAttribute("restricted_rotation", &isRestrictedRotation); - obj->setRestrictedRotation(isRestrictedRotation!=0); - - int zStep = 0; - int zRetVal = root->QueryIntAttribute("z_step_limit", &zStep); - if (zRetVal == TIXML_SUCCESS) { - obj->setZStepRange(zStep); + std::string file = ""; + if (importFile) { + file = *importFile; } - // loop over all multi parts - for (TiXmlElement* multiElement = root->FirstChildElement("multipart"); multiElement; multiElement = multiElement->NextSiblingElement("multipart")) { - const std::string* partId = multiElement->Attribute(std::string("id")); - if (partId) { - obj->addMultiPartId(*partId); + if (importDir && !importFile) { + bfs::path fullPath(objectDirectory); + fullPath /= directory; + loadImportDirectory(fullPath.string()); + } else if (importFile) { + bfs::path fullFilePath(file); + bfs::path fullDirPath(directory); + if (importDir) { + fullDirPath = bfs::path(objectDirectory); + fullDirPath /= directory; + } else { + fullFilePath = bfs::path(objectDirectory); + fullFilePath /= file; } - for (TiXmlElement* multiRotation = multiElement->FirstChildElement("rotation"); multiRotation; multiRotation = multiRotation->NextSiblingElement("rotation")) { - int rotation = 0; - multiRotation->QueryIntAttribute("rot", &rotation); - // relative coordinates which are used to position the object - for (TiXmlElement* multiCoordinate = multiRotation->FirstChildElement("occupied_coord"); multiCoordinate; multiCoordinate = multiCoordinate->NextSiblingElement("occupied_coord")) { - int x = 0; - int y = 0; - xRetVal = multiCoordinate->QueryValueAttribute("x", &x); - yRetVal = multiCoordinate->QueryValueAttribute("y", &y); - if (xRetVal == TIXML_SUCCESS && yRetVal == TIXML_SUCCESS) { - int z = 0; - multiCoordinate->QueryIntAttribute("z", &z); - obj->addMultiPartCoordinate(rotation, ModelCoordinate(x, y, z)); + loadImportFile(fullFilePath.string(), fullDirPath.string()); + } + } + } + + if (root && root->ValueStr() == "assets") { + for (TiXmlElement* objectElem = root->FirstChildElement("object"); objectElem; objectElem = objectElem->NextSiblingElement("object")) { + const std::string* objectId = objectElem->Attribute(std::string("id")); + const std::string* namespaceId = objectElem->Attribute(std::string("namespace")); + + Object* obj = NULL; + if (objectId && namespaceId) { + const std::string* parentId = objectElem->Attribute(std::string("parent")); + + if (parentId) { + Object* parent = m_model->getObject(*parentId, *namespaceId); + if (parent) { + try { + obj = m_model->createObject(*objectId, *namespaceId, parent); + } + catch (NameClash&) { + // TODO - handle exception + assert(false); + } + } + } else { + // this will make sure the object has not already been loaded + if (m_model->getObject(*objectId, *namespaceId) == NULL) { + try { + obj = m_model->createObject(*objectId, *namespaceId); + } + catch (NameClash &e) { + FL_ERR(_log, e.what()); + + // TODO - handle exception + assert(false); } } } } - // loop over all image tags - for (TiXmlElement* imageElement = root->FirstChildElement("image"); imageElement; imageElement = imageElement->NextSiblingElement("image")) { - const std::string* sourceId = imageElement->Attribute(std::string("source")); + if (obj) { + obj->setFilename(objectPath.string()); + ObjectVisual::create(obj); + + int isBlocking = 0; + objectElem->QueryIntAttribute("blocking", &isBlocking); + obj->setBlocking(isBlocking!=0); + + int isStatic = 0; + objectElem->QueryIntAttribute("static", &isStatic); + obj->setStatic(isStatic!=0); + + const std::string* pather = objectElem->Attribute(std::string("pather")); + + if (pather) { + obj->setPather(m_model->getPather(*pather)); + } + else { + obj->setPather(m_model->getPather("RoutePather")); + } + + const std::string* costId = objectElem->Attribute(std::string("cost_id")); + if (costId) { + obj->setCostId(*costId); + double cost = 1.0; + int success = objectElem->QueryDoubleAttribute("cost", &cost); + if (success == TIXML_SUCCESS) { + obj->setCost(cost); + } + } + + const std::string* areaId = objectElem->Attribute(std::string("area_id")); + if (areaId) { + obj->setArea(*areaId); + } + + double speed = 1.0; + int success = root->QueryDoubleAttribute("speed", &speed); + if (success == TIXML_SUCCESS) { + obj->setSpeed(speed); + } + + // loop over all walkable areas + for (TiXmlElement* walkableElement = objectElem->FirstChildElement("walkable_area"); walkableElement; walkableElement = walkableElement->NextSiblingElement("walkable_area")) { + const std::string* walkableId = walkableElement->Attribute(std::string("id")); + if (walkableId) { + obj->addWalkableArea(*walkableId); + } + } + + int cellStack = 0; + objectElem->QueryIntAttribute("cellstack", &cellStack); + obj->setCellStackPosition(cellStack); + + double ax = 0; + double ay = 0; + double az = 0; + + int xRetVal = objectElem->QueryValueAttribute("anchor_x", &ax); + int yRetVal = objectElem->QueryValueAttribute("anchor_y", &ay); + if (xRetVal == TIXML_SUCCESS && yRetVal == TIXML_SUCCESS) { + obj->setRotationAnchor(ExactModelCoordinate(ax, ay, az)); + } - if (sourceId) { - bfs::path imagePath(filename); + int isRestrictedRotation = 0; + objectElem->QueryIntAttribute("restricted_rotation", &isRestrictedRotation); + obj->setRestrictedRotation(isRestrictedRotation!=0); - if (HasParentPath(imagePath)) { - imagePath = GetParentPath(imagePath) / *sourceId; - } else { - imagePath = bfs::path(*sourceId); - } + int zStep = 0; + int zRetVal = objectElem->QueryIntAttribute("z_step_limit", &zStep); + if (zRetVal == TIXML_SUCCESS) { + obj->setZStepRange(zStep); + } - ImagePtr imagePtr; - if(!m_imageManager->exists(imagePath.string())) { - imagePtr = m_imageManager->create(imagePath.string()); + // loop over all multi parts + for (TiXmlElement* multiElement = objectElem->FirstChildElement("multipart"); multiElement; multiElement = multiElement->NextSiblingElement("multipart")) { + const std::string* partId = multiElement->Attribute(std::string("id")); + if (partId) { + obj->addMultiPartId(*partId); } - else { - imagePtr = m_imageManager->getPtr(imagePath.string()); + for (TiXmlElement* multiRotation = multiElement->FirstChildElement("rotation"); multiRotation; multiRotation = multiRotation->NextSiblingElement("rotation")) { + int rotation = 0; + multiRotation->QueryIntAttribute("rot", &rotation); + // relative coordinates which are used to position the object + for (TiXmlElement* multiCoordinate = multiRotation->FirstChildElement("occupied_coord"); multiCoordinate; multiCoordinate = multiCoordinate->NextSiblingElement("occupied_coord")) { + int x = 0; + int y = 0; + xRetVal = multiCoordinate->QueryValueAttribute("x", &x); + yRetVal = multiCoordinate->QueryValueAttribute("y", &y); + if (xRetVal == TIXML_SUCCESS && yRetVal == TIXML_SUCCESS) { + int z = 0; + multiCoordinate->QueryIntAttribute("z", &z); + obj->addMultiPartCoordinate(rotation, ModelCoordinate(x, y, z)); + } + } } + } + + // loop over all image tags + for (TiXmlElement* imageElement = objectElem->FirstChildElement("image"); imageElement; imageElement = imageElement->NextSiblingElement("image")) { + const std::string* sourceId = imageElement->Attribute(std::string("source")); + + if (sourceId) { + bfs::path imagePath(filename); + + if (HasParentPath(imagePath)) { + imagePath = GetParentPath(imagePath) / *sourceId; + } else { + imagePath = bfs::path(*sourceId); + } + + if (!bfs::exists(imagePath)) { + imagePath= bfs::path(*sourceId); + } - if (imagePtr) { - int xOffset = 0; - int success = imageElement->QueryIntAttribute("x_offset", &xOffset); - - if (success == TIXML_SUCCESS) { - imagePtr->setXShift(xOffset); - } - - int yOffset = 0; - success = imageElement->QueryIntAttribute("y_offset", &yOffset); - - if (success == TIXML_SUCCESS) { - imagePtr->setYShift(yOffset); - } - - int direction = 0; - success = imageElement->QueryIntAttribute("direction", &direction); - - if (success == TIXML_SUCCESS) { - ObjectVisual* objVisual = obj->getVisual(); - - if (objVisual) { - objVisual->addStaticImage(direction, static_cast(imagePtr->getHandle())); - } - } - } - } - } - - for (TiXmlElement* actionElement = root->FirstChildElement("action"); actionElement; actionElement = actionElement->NextSiblingElement("action")) { - const std::string* actionId = actionElement->Attribute(std::string("id")); - - if (actionId) { - Action* action = obj->createAction(*actionId); - ActionVisual::create(action); - - for (TiXmlElement* animElement = actionElement->FirstChildElement("animation"); animElement; animElement = animElement->NextSiblingElement("animation")) { - const std::string* sourceId = animElement->Attribute(std::string("atlas")); - if(sourceId) { - bfs::path atlasPath(filename); - - if (HasParentPath(atlasPath)) { - atlasPath = GetParentPath(atlasPath) / *sourceId; - } else { - atlasPath = bfs::path(*sourceId); - } - - ImagePtr atlasImgPtr; - // we need to load this since its shared image - if(!m_imageManager->exists(atlasPath.string())) { - atlasImgPtr = m_imageManager->create(atlasPath.string()); + ImagePtr imagePtr; + if(!m_imageManager->exists(imagePath.string())) { + imagePtr = m_imageManager->create(imagePath.string()); + } + else { + imagePtr = m_imageManager->getPtr(imagePath.string()); + } + + if (imagePtr) { + int xOffset = 0; + int success = imageElement->QueryIntAttribute("x_offset", &xOffset); + + if (success == TIXML_SUCCESS) { + imagePtr->setXShift(xOffset); + } + + int yOffset = 0; + success = imageElement->QueryIntAttribute("y_offset", &yOffset); + + if (success == TIXML_SUCCESS) { + imagePtr->setYShift(yOffset); } - else { - atlasImgPtr = m_imageManager->getPtr(atlasPath.string()); + + int direction = 0; + success = imageElement->QueryIntAttribute("direction", &direction); + + if (success == TIXML_SUCCESS) { + ObjectVisual* objVisual = obj->getVisual(); + + if (objVisual) { + objVisual->addStaticImage(direction, static_cast(imagePtr->getHandle())); + } } + } + } + } - int animFrames = 0; - int animDelay = 0; - int animXoffset = 0; - int animYoffset = 0; - int frameWidth = 0; - int frameHeight = 0; - - animElement->QueryValueAttribute("width", &frameWidth); - animElement->QueryValueAttribute("height", &frameHeight); - animElement->QueryValueAttribute("frames", &animFrames); - animElement->QueryValueAttribute("delay", &animDelay); - animElement->QueryValueAttribute("x_offset", &animXoffset); - animElement->QueryValueAttribute("y_offset", &animYoffset); - int nDir = 0; - - for (TiXmlElement* dirElement = animElement->FirstChildElement("direction"); - dirElement; dirElement = dirElement->NextSiblingElement("direction")) { - AnimationPtr animation(new Animation); - - int dir; - dirElement->QueryIntAttribute("dir", &dir); - - int frames; - int success; - - success = dirElement->QueryValueAttribute("frames", &frames); - if(success != TIXML_SUCCESS) { - frames = animFrames; - } - - int delay; - success = dirElement->QueryValueAttribute("delay", &delay); - if(success != TIXML_SUCCESS) { - delay = animDelay; - } - - int xoffset; - success = dirElement->QueryValueAttribute("x_offset", &xoffset); - if(success != TIXML_SUCCESS) { - xoffset = animXoffset; - } - - int yoffset; - success = dirElement->QueryValueAttribute("y_offset", &yoffset); - if(success != TIXML_SUCCESS) { - yoffset = animYoffset; - } - - int action_frame; - success = dirElement->QueryValueAttribute("action", &action_frame); - if(success == TIXML_SUCCESS) { - animation->setActionFrame(action_frame); + for (TiXmlElement* actionElement = objectElem->FirstChildElement("action"); actionElement; actionElement = actionElement->NextSiblingElement("action")) { + const std::string* actionId = actionElement->Attribute(std::string("id")); + + if (actionId) { + int isDefault = 0; + actionElement->QueryIntAttribute("default", &isDefault); + Action* action = obj->createAction(*actionId, (isDefault != 0)); + ActionVisual::create(action); + + for (TiXmlElement* animElement = actionElement->FirstChildElement("animation"); animElement; animElement = animElement->NextSiblingElement("animation")) { + // Fetch already created animation + const std::string* animationId = animElement->Attribute(std::string("animation_id")); + if (animationId) { + AnimationPtr animation = m_animationManager->getPtr(*animationId); + if (animation) { + ActionVisual* actionVisual = action->getVisual(); + if (actionVisual) { + actionVisual->addAnimation(animation->getDirection(), animation); + action->setDuration(animation->getDuration()); + continue; } + } + } + + // Create animated spritesheet + const std::string* sourceId = animElement->Attribute(std::string("atlas")); + if (sourceId) { + bfs::path atlasPath(filename); + + if (HasParentPath(atlasPath)) { + atlasPath = GetParentPath(atlasPath) / *sourceId; + } else { + atlasPath = bfs::path(*sourceId); + } + + ImagePtr atlasImgPtr; + // we need to load this since its shared image + if (!m_imageManager->exists(atlasPath.string())) { + atlasImgPtr = m_imageManager->create(atlasPath.string()); + } else { + atlasImgPtr = m_imageManager->getPtr(atlasPath.string()); + } + + int animFrames = 0; + int animDelay = 0; + int animXoffset = 0; + int animYoffset = 0; + int frameWidth = 0; + int frameHeight = 0; + + animElement->QueryValueAttribute("width", &frameWidth); + animElement->QueryValueAttribute("height", &frameHeight); + animElement->QueryValueAttribute("frames", &animFrames); + animElement->QueryValueAttribute("delay", &animDelay); + animElement->QueryValueAttribute("x_offset", &animXoffset); + animElement->QueryValueAttribute("y_offset", &animYoffset); + int nDir = 0; + + for (TiXmlElement* dirElement = animElement->FirstChildElement("direction"); + dirElement; dirElement = dirElement->NextSiblingElement("direction")) { + int dir; + dirElement->QueryIntAttribute("dir", &dir); + + static char tmp[64]; + snprintf(tmp, 64, "%03d", dir); + std::string aniId = *objectId + ":" + *actionId + ":" + std::string(tmp); + AnimationPtr animation = m_animationManager->get(aniId); + + int frames; + int success = dirElement->QueryValueAttribute("frames", &frames); + if(success != TIXML_SUCCESS) { + frames = animFrames; + } + + int delay; + success = dirElement->QueryValueAttribute("delay", &delay); + if(success != TIXML_SUCCESS) { + delay = animDelay; + } + + int xoffset; + success = dirElement->QueryValueAttribute("x_offset", &xoffset); + if(success != TIXML_SUCCESS) { + xoffset = animXoffset; + } + + int yoffset; + success = dirElement->QueryValueAttribute("y_offset", &yoffset); + if(success != TIXML_SUCCESS) { + yoffset = animYoffset; + } + + int action_frame; + success = dirElement->QueryValueAttribute("action_frame", &action_frame); + if(success == TIXML_SUCCESS) { + animation->setActionFrame(action_frame); + } - for (int iframe = 0; iframe < frames; ++iframe) { - static char tmpBuf[64]; - sprintf(tmpBuf, "%03d:%04d", dir, iframe); - - std::string frameId = *objectId + ":" + *actionId + ":" + std::string(tmpBuf); - - ImagePtr framePtr; - if (!m_imageManager->exists(frameId)) { - framePtr = m_imageManager->create(frameId); - Rect region( - frameWidth * iframe, frameHeight * nDir, frameWidth, frameHeight - ); - framePtr->useSharedImage(atlasImgPtr, region); - framePtr->setXShift(xoffset); - framePtr->setYShift(yoffset); + for (int iframe = 0; iframe < frames; ++iframe) { + static char tmpBuf[64]; + snprintf(tmpBuf, 64, "%03d:%04d", dir, iframe); + + std::string frameId = *objectId + ":" + *actionId + ":" + std::string(tmpBuf); + Rect region(frameWidth * iframe, frameHeight * nDir, frameWidth, frameHeight); + ImagePtr framePtr; + if (!m_imageManager->exists(frameId)) { + framePtr = m_imageManager->create(frameId); + framePtr->useSharedImage(atlasImgPtr, region); + framePtr->setXShift(xoffset); + framePtr->setYShift(yoffset); + } else { + framePtr = m_imageManager->getPtr(frameId); + } + animation->addFrame(framePtr, delay); } - else { - framePtr = m_imageManager->getPtr(frameId); + + ActionVisual* actionVisual = action->getVisual(); + if(actionVisual) { + actionVisual->addAnimation(dir, animation); + action->setDuration(animation->getDuration()); } - animation->addFrame(framePtr, delay); - } - - ActionVisual* actionVisual = action->getVisual(); - if(actionVisual) { - actionVisual->addAnimation(dir, animation); - action->setDuration(animation->getDuration()); - } - ++nDir; - } - - } else { - sourceId = animElement->Attribute(std::string("source")); - if (sourceId) { - bfs::path animPath(filename); - - if (HasParentPath(animPath)) { - animPath = GetParentPath(animPath) / *sourceId; - } else { - animPath = bfs::path(*sourceId); - } - - AnimationPtr animation; - if (m_animationLoader && m_animationLoader->isLoadable(animPath.string())) { - animation = m_animationLoader->load(animPath.string()); - } - - int direction = 0; - animElement->QueryIntAttribute("direction", &direction); - - if (action && animation) { - ActionVisual* actionVisual = action->getVisual(); - - if (actionVisual) { - actionVisual->addAnimation(direction, animation); - action->setDuration(animation->getDuration()); - } - } - } - } - } - } - } - } - } - } + ++nDir; + } + continue; + } + + // Load animation.xml with frames + sourceId = animElement->Attribute(std::string("source")); + if (sourceId) { + int direction = 0; + int success = animElement->QueryValueAttribute("direction", &direction); + + bfs::path animPath(filename); + + if (HasParentPath(animPath)) { + animPath = GetParentPath(animPath) / *sourceId; + } else { + animPath = bfs::path(*sourceId); + } + + AnimationPtr animation; + if (m_animationLoader && m_animationLoader->isLoadable(animPath.string())) { + animation = m_animationLoader->load(animPath.string()); + } + + if (action && animation) { + if (success != TIXML_SUCCESS) { + direction = animation->getDirection(); + } + ActionVisual* actionVisual = action->getVisual(); + if (actionVisual) { + actionVisual->addAnimation(direction, animation); + action->setDuration(animation->getDuration()); + } + } + } + } + } + } + } + } + } + } + + void ObjectLoader::loadImportFile(const std::string& file, const std::string& directory) { + if (!file.empty()) { + bfs::path importFilePath(directory); + importFilePath /= file; + + std::string importFileString = importFilePath.string(); + if (m_atlasLoader && m_atlasLoader->isLoadable(importFileString)) { + m_atlasLoader->loadMultiple(importFileString); + } + if (m_animationLoader && m_animationLoader->isLoadable(importFileString)) { + m_animationLoader->loadMultiple(importFileString); + } + if (isLoadable(importFileString)) { + load(importFileString); + } + } + } + + void ObjectLoader::loadImportDirectory(const std::string& directory) { + if (!directory.empty()) { + bfs::path importDirectory(directory); + std::string importDirectoryString = importDirectory.string(); + + std::set files = m_vfs->listFiles(importDirectoryString); + + // load all xml files in the directory + std::set::iterator iter; + for (iter = files.begin(); iter != files.end(); ++iter) { + // TODO - vtchill - may need a way to allow clients to load things other + // than .xml and .zip files + std::string ext = bfs::extension(*iter); + if (ext == ".xml" || ext == ".zip") { + loadImportFile(*iter, importDirectoryString); + } + } + std::set nestedDirectories = m_vfs->listDirectories(importDirectoryString); + for (iter = nestedDirectories.begin(); iter != nestedDirectories.end(); ++iter) { + // do not attempt to load anything from a .svn directory + if ((*iter).find(".svn") == std::string::npos) { + loadImportDirectory(importDirectoryString + "/" + *iter); + } + } + } + } } diff --git a/engine/core/loaders/native/map/objectloader.h b/engine/core/loaders/native/map/objectloader.h index bd1a681f2..80c2caed0 100644 --- a/engine/core/loaders/native/map/objectloader.h +++ b/engine/core/loaders/native/map/objectloader.h @@ -35,40 +35,68 @@ #include "iobjectloader.h" #include "ianimationloader.h" +#include "iatlasloader.h" namespace FIFE { - class Model; - class VFS; - class ImageManager; - - class ObjectLoader : public IObjectLoader { - public: - ObjectLoader(Model* model, VFS* vfs, ImageManager* imageManager, const AnimationLoaderPtr& animationLoader=AnimationLoaderPtr()); - - ~ObjectLoader(); - - /** - * @see IObjectLoader::setAnimationLoader - */ - virtual void setAnimationLoader(const AnimationLoaderPtr& animationLoader); - - /** - * @see IObjectLoader::isLoadable - */ - virtual bool isLoadable(const std::string& filename) const; - - /** - * @see IObjectLoader::load - */ - virtual void load(const std::string& filename); - - private: - Model* m_model; - VFS* m_vfs; - ImageManager* m_imageManager; - AnimationLoaderPtr m_animationLoader; - }; + class Model; + class VFS; + class ImageManager; + class AnimationManager; + + class ObjectLoader : public IObjectLoader { + public: + ObjectLoader(Model* model, VFS* vfs, ImageManager* imageManager, AnimationManager* animationManager, const AnimationLoaderPtr& animationLoader=AnimationLoaderPtr(), const AtlasLoaderPtr& atlasLoader=AtlasLoaderPtr()); + + ~ObjectLoader(); + + /** + * @see IObjectLoader::setAnimationLoader + */ + virtual void setAnimationLoader(const AnimationLoaderPtr& animationLoader); + + /** + * @see IObjectLoader::getAnimationLoader + */ + virtual AnimationLoaderPtr getAnimationLoader(); + + /** + * @see IObjectLoader::setAtlasLoader + */ + virtual void setAtlasLoader(const AtlasLoaderPtr& atlasLoader); + + /** + * @see IObjectLoader::getAtlasLoader + */ + virtual AtlasLoaderPtr getAtlasLoader(); + + /** + * @see IObjectLoader::isLoadable + */ + virtual bool isLoadable(const std::string& filename) const; + + /** + * @see IObjectLoader::load + */ + virtual void load(const std::string& filename); + + /** used to load an object, atlas or animation file + * if directory is provided then file is assumed relative to directory + */ + void loadImportFile(const std::string& file, const std::string& directory=""); + + /** used to load a directory of object, atlas or animation files recursively + */ + void loadImportDirectory(const std::string& directory); + + private: + Model* m_model; + VFS* m_vfs; + ImageManager* m_imageManager; + AnimationManager* m_animationManager; + AnimationLoaderPtr m_animationLoader; + AtlasLoaderPtr m_atlasLoader; + }; } #endif \ No newline at end of file diff --git a/engine/core/loaders/native/video/resourceanimationloader.cpp b/engine/core/loaders/native/video/resourceanimationloader.cpp new file mode 100644 index 000000000..30b1c6ca2 --- /dev/null +++ b/engine/core/loaders/native/video/resourceanimationloader.cpp @@ -0,0 +1,48 @@ +/*************************************************************************** + * Copyright (C) 2005-2013 by the FIFE team * + * http://www.fifengine.net * + * This file is part of FIFE. * + * * + * FIFE is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +// Standard C++ library includes + +// 3rd party library includes + +// FIFE includes +// These includes are split up in two parts, separated by one empty line +// First block: files included from the FIFE root src directory +// Second block: files included from the same folder +#include "util/base/exception.h" +#include "video/animation.h" + +#include "resourceanimationloader.h" + +namespace FIFE { + + void ResourceAnimationLoader::load(IResource* res) { + Animation* anim = dynamic_cast(res); + if (anim) { + std::vector frames = anim->getFrames(); + for (std::vector::iterator it = frames.begin(); it != frames.end(); ++it) { + if ((*it)->getState() != IResource::RES_LOADED) { + (*it)->load(); + } + } + } + } +} //FIFE diff --git a/engine/core/loaders/native/video/resourceanimationloader.h b/engine/core/loaders/native/video/resourceanimationloader.h new file mode 100644 index 000000000..1818bcaa4 --- /dev/null +++ b/engine/core/loaders/native/video/resourceanimationloader.h @@ -0,0 +1,44 @@ +/*************************************************************************** + * Copyright (C) 2005-2013 by the FIFE team * + * http://www.fifengine.net * + * This file is part of FIFE. * + * * + * FIFE is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef FIFE_VIDEO_LOADERS_ANIMATION_PROVIDER_H +#define FIFE_VIDEO_LOADERS_ANIMATION_PROVIDER_H + +// Standard C++ library includes + +// 3rd party library includes + +// FIFE includes +// These includes are split up in two parts, separated by one empty line +// First block: files included from the FIFE root src directory +// Second block: files included from the same folder +#include "util/resource/resource.h" + +namespace FIFE { + /** ResourceAnimationLoader. + */ + class ResourceAnimationLoader : public IResourceLoader { + public: + ResourceAnimationLoader() {} + virtual void load(IResource* res); + }; +} +#endif diff --git a/engine/core/model/metamodel/grids/cellgrid.h b/engine/core/model/metamodel/grids/cellgrid.h index 393ebc185..6342be5dd 100644 --- a/engine/core/model/metamodel/grids/cellgrid.h +++ b/engine/core/model/metamodel/grids/cellgrid.h @@ -110,6 +110,11 @@ namespace FIFE { */ virtual ExactModelCoordinate toExactLayerCoordinates(const ExactModelCoordinate& map_coord) = 0; + /** Transforms given point from exact layer coordinates to cell precision layer coordinates + * @return point in layer coordinates + */ + virtual ModelCoordinate toLayerCoordinatesFromExactLayerCoordinates(const ExactModelCoordinate& exact_layer_coords) = 0; + /** Fills given point vector with vertices from selected cell * @param vtx vertices for given cell * @param cell cell to get vertices from diff --git a/engine/core/model/metamodel/grids/cellgrids.i b/engine/core/model/metamodel/grids/cellgrids.i index 9b9a2dcf1..e880f3f7d 100644 --- a/engine/core/model/metamodel/grids/cellgrids.i +++ b/engine/core/model/metamodel/grids/cellgrids.i @@ -50,6 +50,7 @@ namespace FIFE { virtual ExactModelCoordinate toMapCoordinates(const ExactModelCoordinate& layer_coords) = 0; virtual ModelCoordinate toLayerCoordinates(const ExactModelCoordinate& map_coord) = 0; virtual ExactModelCoordinate toExactLayerCoordinates(const ExactModelCoordinate& map_coord) = 0; + virtual ModelCoordinate toLayerCoordinatesFromExactLayerCoordinates(const ExactModelCoordinate& exact_layer_coords) = 0; virtual void getVertices(std::vector& vtx, const ModelCoordinate& cell) = 0; virtual std::vector getCoordinatesInLine(const ModelCoordinate& start, const ModelCoordinate& end) = 0; void setXShift(const double& xshift); @@ -81,6 +82,7 @@ namespace FIFE { ExactModelCoordinate toMapCoordinates(const ExactModelCoordinate& layer_coords); ModelCoordinate toLayerCoordinates(const ExactModelCoordinate& map_coord); ExactModelCoordinate toExactLayerCoordinates(const ExactModelCoordinate& map_coord); + ModelCoordinate toLayerCoordinatesFromExactLayerCoordinates(const ExactModelCoordinate& exact_layer_coords); void getVertices(std::vector& vtx, const ModelCoordinate& cell); std::vector getCoordinatesInLine(const ModelCoordinate& start, const ModelCoordinate& end); }; @@ -98,6 +100,7 @@ namespace FIFE { ExactModelCoordinate toMapCoordinates(const ExactModelCoordinate& layer_coords); ModelCoordinate toLayerCoordinates(const ExactModelCoordinate& map_coord); ExactModelCoordinate toExactLayerCoordinates(const ExactModelCoordinate& map_coord); + ModelCoordinate toLayerCoordinatesFromExactLayerCoordinates(const ExactModelCoordinate& exact_layer_coords); void getVertices(std::vector& vtx, const ModelCoordinate& cell); std::vector getCoordinatesInLine(const ModelCoordinate& start, const ModelCoordinate& end); }; diff --git a/engine/core/model/metamodel/grids/hexgrid.cpp b/engine/core/model/metamodel/grids/hexgrid.cpp index 02fa21994..be57ad8b4 100644 --- a/engine/core/model/metamodel/grids/hexgrid.cpp +++ b/engine/core/model/metamodel/grids/hexgrid.cpp @@ -138,6 +138,19 @@ namespace FIFE { FL_DBG(_log, LMsg("==============\nConverting map coords ") << map_coord << " to int32_t layer coords..."); ExactModelCoordinate elc = m_inverse_matrix * map_coord; elc.y *= VERTICAL_MULTIP_INV; + return toLayerCoordinatesHelper(elc); + } + + ModelCoordinate HexGrid::toLayerCoordinatesFromExactLayerCoordinates(const ExactModelCoordinate& exact_layer_coords) { + ExactModelCoordinate elc = exact_layer_coords; + elc.x += getXZigzagOffset(elc.y); + return toLayerCoordinatesHelper(elc); + } + + ModelCoordinate HexGrid::toLayerCoordinatesHelper(const ExactModelCoordinate& coords) { + // this helper method takes exact layer coordinates with zigzag removed + // and converts them to layer coordinates + ExactModelCoordinate elc = coords; // approximate conversion using squares instead of hexes if( static_cast(round(elc.y)) & 1 ) diff --git a/engine/core/model/metamodel/grids/hexgrid.h b/engine/core/model/metamodel/grids/hexgrid.h index 3da408fa0..7536a328e 100644 --- a/engine/core/model/metamodel/grids/hexgrid.h +++ b/engine/core/model/metamodel/grids/hexgrid.h @@ -49,6 +49,7 @@ namespace FIFE { ExactModelCoordinate toMapCoordinates(const ExactModelCoordinate& layer_coords); ModelCoordinate toLayerCoordinates(const ExactModelCoordinate& map_coord); ExactModelCoordinate toExactLayerCoordinates(const ExactModelCoordinate& map_coord); + ModelCoordinate toLayerCoordinatesFromExactLayerCoordinates(const ExactModelCoordinate& exact_layer_coords); void getVertices(std::vector& vtx, const ModelCoordinate& cell); std::vector toMultiCoordinates(const ModelCoordinate& position, const std::vector& orig, bool reverse); std::vector getCoordinatesInLine(const ModelCoordinate& start, const ModelCoordinate& end); @@ -56,6 +57,7 @@ namespace FIFE { private: double getXZigzagOffset(double y); + ModelCoordinate toLayerCoordinatesHelper(const ExactModelCoordinate& coords); }; } diff --git a/engine/core/model/metamodel/grids/squaregrid.cpp b/engine/core/model/metamodel/grids/squaregrid.cpp index 5461b0458..681eeb12b 100644 --- a/engine/core/model/metamodel/grids/squaregrid.cpp +++ b/engine/core/model/metamodel/grids/squaregrid.cpp @@ -104,8 +104,11 @@ namespace FIFE { ModelCoordinate SquareGrid::toLayerCoordinates(const ExactModelCoordinate& map_coord) { ExactModelCoordinate dblpt = toExactLayerCoordinates(map_coord); - ModelCoordinate result(round(dblpt.x), round(dblpt.y), round(dblpt.z)); + return toLayerCoordinatesFromExactLayerCoordinates(dblpt); + } + ModelCoordinate SquareGrid::toLayerCoordinatesFromExactLayerCoordinates(const ExactModelCoordinate& exact_layer_coords) { + ModelCoordinate result(round(exact_layer_coords.x), round(exact_layer_coords.y), round(exact_layer_coords.z)); return result; } diff --git a/engine/core/model/metamodel/grids/squaregrid.h b/engine/core/model/metamodel/grids/squaregrid.h index 82d3f876c..41cfece99 100644 --- a/engine/core/model/metamodel/grids/squaregrid.h +++ b/engine/core/model/metamodel/grids/squaregrid.h @@ -49,6 +49,7 @@ namespace FIFE { ExactModelCoordinate toMapCoordinates(const ExactModelCoordinate& layer_coords); ModelCoordinate toLayerCoordinates(const ExactModelCoordinate& map_coord); ExactModelCoordinate toExactLayerCoordinates(const ExactModelCoordinate& map_coord); + ModelCoordinate toLayerCoordinatesFromExactLayerCoordinates(const ExactModelCoordinate& exact_layer_coords); void getVertices(std::vector& vtx, const ModelCoordinate& cell); std::vector toMultiCoordinates(const ModelCoordinate& position, const std::vector& orig, bool reverse); std::vector getCoordinatesInLine(const ModelCoordinate& start, const ModelCoordinate& end); diff --git a/engine/core/model/structures/location.cpp b/engine/core/model/structures/location.cpp index 71b252ad5..31c2fb84d 100644 --- a/engine/core/model/structures/location.cpp +++ b/engine/core/model/structures/location.cpp @@ -111,7 +111,7 @@ namespace FIFE { } ModelCoordinate Location::getLayerCoordinates() const { - return ModelCoordinate(doublePt2intPt(m_exact_layer_coords)); + return m_layer->getCellGrid()->toLayerCoordinatesFromExactLayerCoordinates(m_exact_layer_coords); } ExactModelCoordinate Location::getMapCoordinates() const { diff --git a/engine/core/savers/native/map/mapsaver.cpp b/engine/core/savers/native/map/mapsaver.cpp index a4a54e477..f5356e68e 100644 --- a/engine/core/savers/native/map/mapsaver.cpp +++ b/engine/core/savers/native/map/mapsaver.cpp @@ -493,7 +493,14 @@ namespace FIFE { } } + FILE* fp = 0; + #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) + fp = _fsopen( filename.c_str(), "w", _SH_DENYNO ); + #else + fp = fopen( filename.c_str(), "w" ); + #endif // save the map xml file - doc.SaveFile(filename); + doc.SaveFile(fp); + fclose(fp); } -} \ No newline at end of file +} diff --git a/engine/core/video/animation.cpp b/engine/core/video/animation.cpp index 7417a2db6..b949a3b4e 100644 --- a/engine/core/video/animation.cpp +++ b/engine/core/video/animation.cpp @@ -23,7 +23,6 @@ #include // 3rd party library includes -#include // FIFE includes // These includes are split up in two parts, separated by one empty line @@ -31,24 +30,77 @@ // Second block: files included from the same folder #include "util/base/exception.h" #include "util/time/timemanager.h" +#include "loaders/native/video/resourceanimationloader.h" #include "animation.h" #include "image.h" -#include "util/structures/rect.h" namespace FIFE { - Animation::Animation(): + Animation::Animation(IResourceLoader* loader): + IResource(createUniqueAnimationName(), loader), m_action_frame(-1), m_animation_endtime(-1), m_direction(0) { - } + } + + Animation::Animation(const std::string& name, IResourceLoader* loader): + IResource(name, loader), + m_action_frame(-1), + m_animation_endtime(-1), + m_direction(0) { + } Animation::~Animation() { // note: we don't need to free the images, as they are handled via // smart references. } + size_t Animation::getSize() { + return 0; + } + + void Animation::load() { + if (m_loader){ + m_loader->load(this); + } else { + ResourceAnimationLoader loader; + loader.load(this); + } + m_state = IResource::RES_LOADED; + } + + void Animation::free() { + std::vector::iterator it = m_frames.begin(); + for (; it != m_frames.end(); ++it) { + (*it).image->free(); + } + m_state = IResource::RES_NOT_LOADED; + } + + void Animation::invalidate() { + free(); + m_framemap.clear(); + m_frames.clear(); + m_action_frame = -1; + m_animation_endtime = -1; + m_direction = 0; + } + + std::string Animation::createUniqueAnimationName() { + // automated counting for name generation, in case the user doesn't provide a name + static uint32_t uniqueNumber = 0; + static std::string baseName = "animation"; + + std::ostringstream oss; + oss << uniqueNumber << "_" << baseName; + + const std::string name = oss.str(); + ++uniqueNumber; + + return name; + } + void Animation::addFrame(ImagePtr image, uint32_t duration) { FrameInfo info; info.index = m_frames.size(); @@ -85,15 +137,14 @@ namespace FIFE { } ImagePtr Animation::getFrame(int32_t index) { + ImagePtr image; if (isValidIndex(index)) { - ImagePtr image = m_frames[index].image; - if(image->getState() == IResource::RES_NOT_LOADED) { + image = m_frames[index].image; + if (image->getState() == IResource::RES_NOT_LOADED) { image->load(); } - return image; - } else { - return ImagePtr(); //return an invalid image . } + return image; } ImagePtr Animation::getFrameByTimestamp(uint32_t timestamp) { @@ -109,12 +160,19 @@ namespace FIFE { return val; } + std::vector Animation::getFrames() { + std::vector frames; + for (std::vector::iterator it = m_frames.begin(); it != m_frames.end(); ++it) { + frames.push_back((*it).image); + } + return frames; + } + int32_t Animation::getFrameDuration(int32_t index) const{ if (isValidIndex(index)) { return m_frames[index].duration; - } else { - return -1; } + return -1; } uint32_t Animation::getFrameCount() const { @@ -122,7 +180,7 @@ namespace FIFE { } void Animation::setDirection(uint32_t direction) { - m_direction %= 360; + m_direction = direction % 360; } } /* vim: set noexpandtab: set shiftwidth=2: set tabstop=2: */ diff --git a/engine/core/video/animation.h b/engine/core/video/animation.h index e7b4a7682..f8bab3f90 100644 --- a/engine/core/video/animation.h +++ b/engine/core/video/animation.h @@ -29,8 +29,7 @@ // Platform specific includes #include "util/base/fife_stdint.h" -#include "util/base/fifeclass.h" -#include "util/base/sharedptr.h" +#include "util/resource/resource.h" #include "image.h" @@ -43,8 +42,6 @@ namespace FIFE { - class Image; - /** Animation. * * A container of Images describing an animation. Animation itself does @@ -53,16 +50,24 @@ namespace FIFE { * animation user to query frames based on current timestamp and show * returned images on screen. */ - class Animation : public FifeClass { + class Animation : public IResource { public: /** Constructor. - */ - explicit Animation(); + */ + Animation(IResourceLoader* loader = 0); + Animation(const std::string& name, IResourceLoader* loader = 0); /** Destructor. Decreases the reference count of all referred images. */ ~Animation(); + virtual size_t getSize(); + + virtual void load(); + virtual void free(); + + void invalidate(); + /** Adds new frame into animation * Frames must be added starting from first frame. Increases the reference * count of the given image. @@ -87,6 +92,10 @@ namespace FIFE { */ ImagePtr getFrameByTimestamp(uint32_t timestamp); + /** Gets all frame images. + */ + std::vector getFrames(); + /** Gets the frame duration for given (indexed) frame. Returns negative value in case * of incorrect index */ @@ -136,6 +145,8 @@ namespace FIFE { uint32_t duration; ImagePtr image; }; + + std::string createUniqueAnimationName(); /** Checks for animation frame index overflows */ diff --git a/engine/core/video/animationmanager.cpp b/engine/core/video/animationmanager.cpp new file mode 100644 index 000000000..ad1a01f48 --- /dev/null +++ b/engine/core/video/animationmanager.cpp @@ -0,0 +1,470 @@ +/*************************************************************************** + * Copyright (C) 2005-2013 by the FIFE team * + * http://www.fifengine.net * + * This file is part of FIFE. * + * * + * FIFE is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +// Standard C++ library includes +#include + +// 3rd party library includes +#include + +// FIFE includes +// These includes are split up in two parts, separated by one empty line +// First block: files included from the FIFE root src directory +// Second block: files included from the same folder +#include "util/log/logger.h" +#include "util/resource/resourcemanager.h" +#include "util/resource/resource.h" +#include "video/renderbackend.h" + +#include "animationmanager.h" + +namespace FIFE { + /** Logger to use for this source file. + * @relates Logger + */ + static Logger _log(LM_RESMGR); + + AnimationManager::~AnimationManager() { + + } + + size_t AnimationManager::getMemoryUsed() const { + size_t totalSize = 0; + + AnimationHandleMapConstIterator it = m_animHandleMap.begin(), + itend = m_animHandleMap.end(); + + for ( ; it != itend; ++it) { + totalSize += it->second->getSize(); + } + + return totalSize; + } + + size_t AnimationManager::getTotalResourcesCreated() const { + AnimationHandleMapConstIterator it = m_animHandleMap.begin(), + itend = m_animHandleMap.end(); + size_t count = 0; + + for ( ; it != itend; ++it) { + if ( it->second->getState() == IResource::RES_NOT_LOADED ) { + count++; + } + } + + return count; + } + + size_t AnimationManager::getTotalResourcesLoaded() const { + AnimationHandleMapConstIterator it = m_animHandleMap.begin(), + itend = m_animHandleMap.end(); + size_t count = 0; + + for ( ; it != itend; ++it) { + if ( it->second->getState() == IResource::RES_LOADED ) { + count++; + } + } + + return count; + } + + size_t AnimationManager::getTotalResources() const { + return m_animHandleMap.size(); + } + + AnimationPtr AnimationManager::create(IResourceLoader* loader){ + Animation* ptr = new Animation(loader); + return add(ptr); + } + + AnimationPtr AnimationManager::create(const std::string& name, IResourceLoader* loader){ + if (exists(name)) { + FL_WARN(_log, LMsg("AnimationManager::create(std::string, IResourceLoader* loader) - ") << "Resource name " << name << " was previously created. Returning original Animation..."); + return getPtr(name); + } + + Animation* ptr = new Animation(name, loader); + return add(ptr); + } + + AnimationPtr AnimationManager::load(const std::string& name, IResourceLoader* loader) { + AnimationNameMapIterator nit = m_animNameMap.find(name); + + if (nit != m_animNameMap.end()) { + if ( nit->second->getState() == IResource::RES_NOT_LOADED ) { + nit->second->load(); + } + + return nit->second; + } + + //was not found so create and load resource + AnimationPtr ptr = create(name, loader); + ptr->load(); + + if (ptr->getState() == IResource::RES_NOT_LOADED){ + FL_WARN(_log, LMsg("AnimationManager::load(std::string) - ") << "Resource name " << name << " was not found and could not be loaded."); + remove(name); + } + + return ptr; + } + + AnimationPtr AnimationManager::add(Animation* res) { + assert(res); + assert(!(exists(res->getHandle()) || exists(res->getName()))); + + AnimationPtr resptr(res); + + std::pair returnValue; + returnValue = m_animHandleMap.insert ( AnimationHandleMapPair(res->getHandle(), resptr)); + + if (returnValue.second) { + m_animNameMap.insert ( AnimationNameMapPair(returnValue.first->second->getName(), returnValue.first->second) ); + } + else { + FL_WARN(_log, LMsg("AnimationManager::add(IResource*) - ") << "Resource " << res->getName() << " already exists.... ignoring."); + } + + return returnValue.first->second; + } + + bool AnimationManager::exists(const std::string& name) { + AnimationNameMapIterator it = m_animNameMap.find(name); + if (it != m_animNameMap.end()) { + return true; + } + + return false; + } + + bool AnimationManager::exists(ResourceHandle handle) { + AnimationHandleMapConstIterator it = m_animHandleMap.find(handle); + if (it != m_animHandleMap.end()) { + return true; + } + + return false; + } + + void AnimationManager::reload(const std::string& name) { + AnimationNameMapIterator nit = m_animNameMap.find(name); + + if (nit != m_animNameMap.end()) { + if ( nit->second->getState() == IResource::RES_LOADED) { + nit->second->free(); + } + nit->second->load(); + return; + } + + FL_WARN(_log, LMsg("AnimationManager::reload(std::string) - ") << "Resource name " << name << " not found."); + } + + void AnimationManager::reload(ResourceHandle handle) { + AnimationHandleMapIterator it = m_animHandleMap.find(handle); + + if ( it != m_animHandleMap.end()) { + if ( it->second->getState() == IResource::RES_LOADED) { + it->second->free(); + } + it->second->load(); + return; + } + + FL_WARN(_log, LMsg("AnimationManager::reload(ResourceHandle) - ") << "Resource handle " << handle << " not found."); + + } + + void AnimationManager::reloadAll() { + AnimationHandleMapIterator it = m_animHandleMap.begin(), + itend = m_animHandleMap.end(); + + for ( ; it != itend; ++it) { + if ( it->second->getState() == IResource::RES_LOADED) { + it->second->free(); + } + it->second->load(); + } + } + + void AnimationManager::loadUnreferenced() { + AnimationHandleMapIterator it = m_animHandleMap.begin(), + itend = m_animHandleMap.end(); + + int32_t count = 0; + for ( ; it != itend; ++it) { + if (it->second.useCount() == 2 && it->second->getState() != IResource::RES_LOADED){ + it->second->load(); + count++; + } + } + FL_DBG(_log, LMsg("AnimationManager::loadUnreferenced() - ") << "Loaded " << count << " unreferenced resources."); + } + + void AnimationManager::free(const std::string& name) { + AnimationNameMapIterator nit = m_animNameMap.find(name); + + if (nit != m_animNameMap.end()) { + if ( nit->second->getState() == IResource::RES_LOADED) { + nit->second->free(); + } + return; + } + + FL_WARN(_log, LMsg("AnimationManager::free(std::string) - ") << "Resource name " << name << " not found."); + } + + void AnimationManager::free(ResourceHandle handle) { + AnimationHandleMapConstIterator it = m_animHandleMap.find(handle); + if (it != m_animHandleMap.end()) { + if ( it->second->getState() == IResource::RES_LOADED) { + it->second->free(); + } + return; + } + + FL_WARN(_log, LMsg("AnimationManager::free(ResourceHandle) - ") << "Resource handle " << handle << " not found."); + } + + void AnimationManager::freeAll() { + AnimationHandleMapIterator it = m_animHandleMap.begin(), + itend = m_animHandleMap.end(); + + int32_t count = 0; + + for ( ; it != itend; ++it) { + if ( it->second->getState() == IResource::RES_LOADED) { + it->second->free(); + count++; + } + } + + FL_DBG(_log, LMsg("AnimationManager::freeAll() - ") << "Freed all " << count << " resources."); + } + + void AnimationManager::freeUnreferenced() { + AnimationHandleMapIterator it = m_animHandleMap.begin(), + itend = m_animHandleMap.end(); + + int32_t count = 0; + for ( ; it != itend; ++it) { + if (it->second.useCount() == 2 && it->second->getState() == IResource::RES_LOADED ){ + it->second->free(); + count++; + } + } + + FL_DBG(_log, LMsg("AnimationManager::freeUnreferenced() - ") << "Freed " << count << " unreferenced resources."); + } + + void AnimationManager::remove(AnimationPtr& resource) { + AnimationHandleMapIterator it = m_animHandleMap.find(resource->getHandle()); + AnimationNameMapIterator nit = m_animNameMap.find(resource->getName()); + + if (it != m_animHandleMap.end()) { + m_animHandleMap.erase(it); + + if (nit != m_animNameMap.end()) { + m_animNameMap.erase(nit); + return; + } + assert(false); //should never get here + } + + FL_WARN(_log, LMsg("AnimationManager::remove(ResourcePtr&) - ") << "Resource " << resource->getName() << " was not found."); + } + + void AnimationManager::remove(const std::string& name) { + std::size_t handle; + + AnimationNameMapIterator nit = m_animNameMap.find(name); + if (nit != m_animNameMap.end()) { + handle = nit->second->getHandle(); + m_animNameMap.erase(nit); + } + else { + FL_WARN(_log, LMsg("AnimationManager::remove(std::string) - ") << "Resource " << name << " was not found."); + return; + } + + AnimationHandleMapIterator it = m_animHandleMap.find(handle); + if ( it != m_animHandleMap.end()) { + m_animHandleMap.erase(it); + return; + } + + assert(false); //should never get here + } + + void AnimationManager::remove(ResourceHandle handle) { + std::string name; + + AnimationHandleMapIterator it = m_animHandleMap.find(handle); + + if (it != m_animHandleMap.end()) { + name = it->second->getName(); + m_animHandleMap.erase(it); + } + else { + FL_WARN(_log, LMsg("AnimationManager::remove(ResourceHandle) - ") << "Resource handle " << handle << " was not found."); + return; + } + + AnimationNameMapIterator nit = m_animNameMap.find(name); + if ( nit != m_animNameMap.end() ) { + m_animNameMap.erase(nit); + return; + } + + assert(false); //should never get here + } + + void AnimationManager::removeAll() { + //should always be equal + assert (m_animHandleMap.size() == m_animNameMap.size()); + + size_t count = m_animHandleMap.size(); + + m_animHandleMap.clear(); + m_animNameMap.clear(); + + FL_DBG(_log, LMsg("AnimationManager::removeAll() - ") << "Removed all " << count << " resources."); + } + + void AnimationManager::removeUnreferenced() { + AnimationHandleMapIterator it = m_animHandleMap.begin(), + itend = m_animHandleMap.end(); + + std::vector imgHandles; + + int32_t count = 0; + for ( ; it != itend; ++it) { + if ( it->second.useCount() == 2) { + imgHandles.push_back(it->second->getHandle()); + count++; + } + } + + for (std::vector::iterator it = imgHandles.begin(); it != imgHandles.end(); ++it) { + remove(*it); + } + + FL_DBG(_log, LMsg("AnimationManager::removeUnreferenced() - ") << "Removed " << count << " unreferenced resources."); + } + + AnimationPtr AnimationManager::get(const std::string& name) { + AnimationNameMapIterator nit = m_animNameMap.find(name); + + if (nit != m_animNameMap.end()) { + if (nit->second->getState() != IResource::RES_LOADED){ + //resource is not loaded so load it + nit->second->load(); + } + return nit->second; + } + + //not found so attempt to create and load the resource + AnimationPtr ptr = load(name); + return ptr; + } + + AnimationPtr AnimationManager::get(ResourceHandle handle) { + AnimationHandleMapConstIterator it = m_animHandleMap.find(handle); + if (it != m_animHandleMap.end()) { + if (it->second->getState() != IResource::RES_LOADED){ + //resource is not loaded so load it + it->second->load(); + } + return it->second; + } + + FL_WARN(_log, LMsg("AnimationManager::get(ResourceHandle) - ") << "Resource handle " << handle << " is undefined."); + + return AnimationPtr(); + } + + AnimationPtr AnimationManager::getPtr(const std::string& name) { + AnimationNameMapIterator nit = m_animNameMap.find(name); + + if (nit != m_animNameMap.end()) { + return nit->second; + } + + FL_WARN(_log, LMsg("AnimationManager::getPtr(std::string) - ") << "Resource " << name << " is undefined."); + + return AnimationPtr(); + } + + AnimationPtr AnimationManager::getPtr(ResourceHandle handle) { + AnimationHandleMapConstIterator it = m_animHandleMap.find(handle); + if (it != m_animHandleMap.end()) { + return it->second; + } + + FL_WARN(_log, LMsg("AnimationManager::getPtr(ResourceHandle) - ") << "Resource handle " << handle << " is undefined."); + + return AnimationPtr(); + } + + ResourceHandle AnimationManager::getResourceHandle(const std::string& name) { + AnimationNameMapIterator nit = m_animNameMap.find(name); + if (nit != m_animNameMap.end()) { + return nit->second->getHandle(); + } + + FL_WARN(_log, LMsg("AnimationManager::getResourceHandle(std::string) - ") << "Resource " << name << " is undefined."); + + return 0; + } + + void AnimationManager::invalidate(const std::string& name) { + AnimationNameMapIterator it = m_animNameMap.find(name); + if (it != m_animNameMap.end()) { + if (it->second->getState() == IResource::RES_LOADED){ + it->second.get()->invalidate(); + } + } + } + + void AnimationManager::invalidate(ResourceHandle handle) { + AnimationHandleMapIterator it = m_animHandleMap.find(handle); + if (it != m_animHandleMap.end()) { + if (it->second->getState() == IResource::RES_LOADED) { + it->second.get()->invalidate(); + } + } + } + + void AnimationManager::invalidateAll() { + AnimationHandleMapIterator it = m_animHandleMap.begin(), + itend = m_animHandleMap.end(); + + for ( ; it != itend; ++it) { + if (it->second->getState() == IResource::RES_LOADED) { + it->second.get()->invalidate(); + } + } + + } + +} //FIFE diff --git a/engine/core/video/animationmanager.h b/engine/core/video/animationmanager.h new file mode 100644 index 000000000..967029d94 --- /dev/null +++ b/engine/core/video/animationmanager.h @@ -0,0 +1,380 @@ +/*************************************************************************** + * Copyright (C) 2005-2013 by the FIFE team * + * http://www.fifengine.net * + * This file is part of FIFE. * + * * + * FIFE is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef FIFE_ANIMATION_MANAGER_H +#define FIFE_ANIMATION_MANAGER_H + +// Standard C++ library includes +#include +#include +#include + +// 3rd party library includes + +// FIFE includes +// These includes are split up in two parts, separated by one empty line +// First block: files included from the FIFE root src directory +// Second block: files included from the same folder +#include "util/base/singleton.h" +#include "util/resource/resource.h" +#include "util/resource/resourcemanager.h" + +#include "animation.h" + +namespace FIFE { + + /** AnimationManager + * + * An interface for managing animations. + * + * @see IResource + * @see IResourceLoader + * @see IResourceManager + * + */ + + class AnimationManager : public IResourceManager, public DynamicSingleton { + public: + + /** Default constructor. + */ + AnimationManager() : IResourceManager() { } + + /** Destructor. + */ + virtual ~AnimationManager(); + + virtual size_t getMemoryUsed() const; + virtual size_t getTotalResourcesCreated() const; + virtual size_t getTotalResourcesLoaded() const; + virtual size_t getTotalResources() const; + + /** Creates a blank Animation but does not load it immediately + * + * @param loader A pointer to the custom resource loader. The + * default is NULL. If this parameter is present the resource + * will use the loader to load instead of the default built in + * functions. + * @return An AnimationPtr to the newly created Animation + * + * @see Animation + * @see AnimationLoader + * @see IResourceLoader + * + */ + virtual AnimationPtr create(IResourceLoader* loader = 0); + + /** Creates a blank Animation but does not load it immediately + * + * @param name The resource name. Typically a filename. + * @param loader A pointer to the custom resource loader. The + * default is NULL. If this parameter is present the resource + * will use the loader to load instead of the default built in + * functions. + * @return An AnimationPtr to the newly created Animation + * + * @see Animation + * @see AnimationLoader + * @see IResourceLoader + * + */ + virtual AnimationPtr create(const std::string& name, IResourceLoader* loader = 0); + + /** Creates a blank resource and loads it from disk + * + * This function will create the Animation if necessary and load + * the Animation from disk. If the Animation is not defined it + * will call AnimationManager::create() before loading. + * + * @param name The resource name. Typically a filename. + * @param loader A pointer to the custom resource loader. The + * default is NULL. If this parameter is present the resource + * will use the loader to load instead of the default built in + * functions. + * @return A AnimationPtr to the loaded Animation + * + * @see Animation + * @see AnimationLoader + * @see IResourceLoader + * + */ + virtual AnimationPtr load(const std::string& name, IResourceLoader* loader = 0); + + /** Add an Animation to the manager + * + * This function will create a AnimationPtr and add the Animation + * to the manager. The manager assumes ownership of the Animation + * so DO NOT delete it. + * + * @param res A pointer to the Animation + * @return A AnimationPtr to the added resource + * + * @see Animation + * + */ + virtual AnimationPtr add(Animation* res); + + /** Checks to see if an Animation exists + * + * This function will search the manager for Animations + * that match the parameter + * + * @param name The name of the Animation + * @return True if the Animation exists. False otherwise. + * + */ + virtual bool exists(const std::string& name); + + /** Checks to see if an Animation exists + * + * This function will search the manager for Animations + * that match the parameter + * + * @param handle The handle of the Animation + * @return True if the Animation exists. False otherwise. + * + */ + virtual bool exists(ResourceHandle handle); + + /** Reloads an Animation + * + * This function will reload an Animation if it is managed + * by the manager. If not it creates an entry in the log + * specifying that the Animation could not be found. It will + * load the Animation if it is not already loaded. + * + * @param name The name of the resource + * + */ + virtual void reload(const std::string& name); + + /** Reloads a resource + * + * This function will reload an Animation if it is managed + * by the manager. If not it creates an entry in the log + * specifying that the Animation could not be found. It will + * load the Animation if it is not already loaded. + * + * @param handle The handle of the resource + * + */ + virtual void reload(ResourceHandle handle); + + /** Reloads all Animations + * + * This function will reload all Animations managed by the + * manager. It will load an Animation if it is not already loaded. + * + * @todo It might be beneficial to supply a parameter to + * only reload resources that are already loaded + * + */ + virtual void reloadAll(); + + /** Loads all unreferenced Animations + * + * All Animations that have no external references will be + * loaded into memory. + * + */ + virtual void loadUnreferenced(); + + /** Frees an Animation from memory + * + * The Animation is not deleted but it's data is freed. + * This calls the Animation::free() function and it is + * up to the resource to properly free it's memory. The + * manager keeps a reference to the Animation in case + * its required in the future. + * + * @param name The name of the Animation + * + * @see Animation + * + */ + virtual void free(const std::string& name); + + /** Frees an Animation from memory + * + * The Animation is not deleted but it's data is freed. + * This calls the Animation::free() function and it is + * up to the resource to properly free it's memory. The + * manager keeps a reference to the Animation in case + * its required in the future. + * + * @param handle The handle of the Animation + * + * @see Animation + * + */ + virtual void free(ResourceHandle handle); + + /** Frees all Animations + * + * This calls the Animation::free() function for every + * Animation the manager is managing. It does not remove + * them from the manager. + * + * @see Animation + * + */ + virtual void freeAll(); + + /** Frees all unreferenced Animation + * + * This calls the IResource::free() function for Animations + * that have no external references to them. It does not + * remove them from the manager. + * + * @see IResource + * + */ + virtual void freeUnreferenced(); + + /** Removes an Animation from the manager + * + * This removes all references to the Animation from the + * manager. It does not however guarantee that the resources + * destructor is called. If the client has any left over + * references to the resource it will not be freed. + * + * @param resource A AnimationPtr to the Animation to be removed + * from the manager + * + * @note This is useful if you want to remove ownership of a resource + * from the manager + * + * @see Animation + * + */ + virtual void remove(AnimationPtr& resource); + + /** Removes an Animation from the manager + * + * This removes all references to the Animation from the + * manager. It does not however guarantee that the resources + * destructor is called. If the client has any left over + * references to the resource it will not be freed. + * + * @param name The name of the Animation + * + * @see Animation + * + */ + virtual void remove(const std::string& name); + + /** Removes an Animation from the manager + * + * This removes all references to the Animation from the + * manager. It does not however guarantee that the resources + * destructor is called. If the client has any left over + * references to the resource it will not be freed. + * + * @param handle The handle of the Animation + * + * @see Animation + * + */ + virtual void remove(ResourceHandle handle); + + /** Removes all Animations from the manager + * + * This effectively removes all references to all Animations from + * the manager. If there are left over shared pointers to + * any resources they will not be deleted. + * + * @see Animation + * + */ + virtual void removeAll(); + + /** Removes all unreferenced Animations + * + * This effectively removes all Animations that dont have an + * external reference. The resources will be deleted. + * + * @see Animation + * + */ + virtual void removeUnreferenced(); + + /** Gets a shared pointer to the Animation + * + * If the Animation is not defined it will attempt to create + * and load the Animation based on the name (it assumes the name + * is a filename) + * + * @param name The name of the Animation + * @return An AnimationPtr to the Animation + * + */ + virtual AnimationPtr get(const std::string& name); + + /** Gets a shared pointer to the Animation + * + * If the resource is not defined it returns an empty + * (or invalid) AnimationPtr and makes an entry in the log. + * + * @param handle The handle of the resource + * @return A AnimationPtr to the resource + * + * @todo This should throw an exception instead of an + * empty AnimationPtr + * + */ + virtual AnimationPtr get(ResourceHandle handle); + + virtual AnimationPtr getPtr(const std::string& name); + virtual AnimationPtr getPtr(ResourceHandle handle); + + /** Gets an Animation handle by name + * + * Returns the Animation handle associated with the name + * + * @param name The name of the Animation + * @return 0 if the resource name is invalid + * + */ + virtual ResourceHandle getResourceHandle(const std::string& name); + + virtual void invalidate(const std::string& name); + virtual void invalidate(ResourceHandle handle); + virtual void invalidateAll(); + + private: + typedef std::map< ResourceHandle, AnimationPtr > AnimationHandleMap; + typedef std::map< ResourceHandle, AnimationPtr >::iterator AnimationHandleMapIterator; + typedef std::map< ResourceHandle, AnimationPtr >::const_iterator AnimationHandleMapConstIterator; + typedef std::pair< ResourceHandle, AnimationPtr > AnimationHandleMapPair; + + typedef std::map< std::string, AnimationPtr > AnimationNameMap; + typedef std::map< std::string, AnimationPtr >::iterator AnimationNameMapIterator; + typedef std::map< std::string, AnimationPtr >::const_iterator AnimationNameMapConstIterator; + typedef std::pair< std::string, AnimationPtr > AnimationNameMapPair; + + AnimationHandleMap m_animHandleMap; + + AnimationNameMap m_animNameMap; + }; + +} //FIFE + +#endif //FIFE_ANIMATION_MANAGER_H diff --git a/engine/core/video/video.i b/engine/core/video/video.i index c516fce65..83b768cea 100644 --- a/engine/core/video/video.i +++ b/engine/core/video/video.i @@ -25,6 +25,7 @@ #include "video/cursor.h" #include "video/animation.h" #include "video/imagemanager.h" +#include "video/animationmanager.h" #include "video/renderbackend.h" #include "video/devicecaps.h" #include "video/atlasbook.h" @@ -130,9 +131,8 @@ namespace FIFE { virtual void invalidateAll(); }; - class Animation: public FifeClass { + class Animation: public IResource { public: - explicit Animation(); ~Animation(); void addFrame(ImagePtr image, uint32_t duration); int32_t getFrameIndex(uint32_t timestamp); @@ -150,12 +150,49 @@ namespace FIFE { typedef SharedPtr AnimationPtr; %template(SharedAnimationPointer) SharedPtr; - %extend Animation { - static SharedPtr createAnimation() { - FIFE::SharedPtr ani(new FIFE::Animation()); - return ani; - } - } + class AnimationManager : public IResourceManager { + public: + virtual ~AnimationManager(); + + virtual size_t getMemoryUsed() const; + virtual size_t getTotalResourcesCreated() const; + virtual size_t getTotalResourcesLoaded() const; + virtual size_t getTotalResources() const; + + virtual AnimationPtr create(const std::string& name, IResourceLoader* loader = 0); + virtual AnimationPtr add(Animation* res); + + virtual bool exists(const std::string& name); + virtual bool exists(ResourceHandle handle); + + virtual void reload(const std::string& name); + virtual void reload(ResourceHandle handle); + virtual void reloadAll(); + virtual void loadUnreferenced(); + + virtual void free(const std::string& name); + virtual void free(ResourceHandle handle); + virtual void freeAll(); + virtual void freeUnreferenced(); + + virtual void remove(ImagePtr& resource); + virtual void remove(const std::string& name); + virtual void remove(ResourceHandle handle); + virtual void removeAll(); + virtual void removeUnreferenced(); + + virtual AnimationPtr get(const std::string& name); + virtual AnimationPtr get(ResourceHandle handle); + + virtual AnimationPtr getPtr(const std::string& name); + virtual AnimationPtr getPtr(ResourceHandle handle); + + virtual ResourceHandle getResourceHandle(const std::string& name); + + virtual void invalidate(const std::string& name); + virtual void invalidate(ResourceHandle handle); + virtual void invalidateAll(); + }; enum TextureFiltering { TEXTURE_FILTER_NONE = 0, diff --git a/engine/python/fife/extensions/basicapplication.py b/engine/python/fife/extensions/basicapplication.py index 5ff4d45fb..7cd30596a 100644 --- a/engine/python/fife/extensions/basicapplication.py +++ b/engine/python/fife/extensions/basicapplication.py @@ -223,11 +223,9 @@ def mainLoop(self): while not self.quitRequested: try: self.engine.pump() - except RuntimeError, e: + except fife.Exception as e: print str(e) self.quitRequested = True - except: - self.quitRequested = True self._pump() diff --git a/engine/python/fife/extensions/fife_settings.py b/engine/python/fife/extensions/fife_settings.py index c0719e7a2..abf467a23 100644 --- a/engine/python/fife/extensions/fife_settings.py +++ b/engine/python/fife/extensions/fife_settings.py @@ -157,6 +157,11 @@ def __init__(self, app_name="", settings_file="", default_settings_file= "settin self.initSerializer() + # if there's no FIFE module assume the settings file is broken + # and replace with default settings file + if "FIFE" not in self._serializer.getModuleNameList(): + self.setDefaults() + # Get all modules and initialize reading of them from xml file as false self._allModules = self._serializer.getModuleNameList() # print("All Module Names:",self._allModules) diff --git a/engine/python/fife/extensions/pychan/events.py b/engine/python/fife/extensions/pychan/events.py index 6b05635f5..e7484f842 100644 --- a/engine/python/fife/extensions/pychan/events.py +++ b/engine/python/fife/extensions/pychan/events.py @@ -79,6 +79,8 @@ def dumpEventInfo(event=0,widget=0): "mouseMoved", "mouseWheelMovedUp", "mouseWheelMovedDown", + "mouseWheelMovedRight", + "mouseWheelMovedLeft", "mouseDragged", "action", "keyPressed", @@ -221,6 +223,8 @@ def mouseClicked(self,e): self._redirectEvent("mouseClicked",e) def mouseMoved(self,e): self._redirectEvent("mouseMoved",e) def mouseWheelMovedUp(self,e): self._redirectEvent("mouseWheelMovedUp",e) def mouseWheelMovedDown(self,e): self._redirectEvent("mouseWheelMovedDown",e) + def mouseWheelMovedRight(self,e): self._redirectEvent("mouseWheelMovedRight",e) + def mouseWheelMovedLeft(self,e): self._redirectEvent("mouseWheelMovedLeft",e) def mouseDragged(self,e): self._redirectEvent("mouseDragged",e) class _KeyEventListener(EventListenerBase,fifechan.KeyListener): diff --git a/engine/python/fife/extensions/pychan/widgets/icon.py b/engine/python/fife/extensions/pychan/widgets/icon.py index 9d5daf3bd..b94a6a582 100644 --- a/engine/python/fife/extensions/pychan/widgets/icon.py +++ b/engine/python/fife/extensions/pychan/widgets/icon.py @@ -26,6 +26,7 @@ from fife.extensions.pychan.attrs import Attr, BoolAttr from fife.extensions.pychan.properties import ImageProperty +from common import get_manager from widget import Widget @@ -88,7 +89,11 @@ def __init__(self, if scale is not None: self.scale = scale - self.image = image + try: + self.image = image + except Exception: + get_manager().removeWidget(self) + raise #if the size parameter is specified set it (again) to override #the icons size. diff --git a/engine/python/fife/extensions/serializers/xmlanimation.py b/engine/python/fife/extensions/serializers/xmlanimation.py index c20adf486..c29b0bc4c 100644 --- a/engine/python/fife/extensions/serializers/xmlanimation.py +++ b/engine/python/fife/extensions/serializers/xmlanimation.py @@ -29,19 +29,26 @@ def loadXMLAnimation(engine, filename): f.thisown = 1 imgMgr = engine.getImageManager() + aniMgr = engine.getAnimationManager() tree = ET.parse(f) node = tree.getroot() - animation = fife.Animation.createAnimation() + ani_id = node.get('id') + if not ani_id: + ani_id = filename + if aniMgr.exists(ani_id): + animation = aniMgr.getPtr(str(ani_id)) + else: + animation = aniMgr.create(str(ani_id)) + common_width = int(node.get('width', 0)) common_height = int(node.get('height', 0)) - common_y_offset = int(node.get('y_offset', 0)) common_frame_delay = int(node.get('delay', 0)) common_x_offset = int(node.get('x_offset', 0)) common_y_offset = int(node.get('y_offset', 0)) - animation.setActionFrame(int(node.get('action', 0))) + animation.setActionFrame(int(node.get('action_frame', 0))) frames = node.findall('frame') if not frames: diff --git a/engine/swigwrappers/python/fife.i.templ b/engine/swigwrappers/python/fife.i.templ index 727f5f207..55aaff00c 100644 --- a/engine/swigwrappers/python/fife.i.templ +++ b/engine/swigwrappers/python/fife.i.templ @@ -170,6 +170,12 @@ print s\n\ %exceptionclass FIFE::InconsistencyDetected; %exceptionclass FIFE::OutOfMemory; +%extend FIFE::Exception { + const char *__str__() { + return self->what(); + } +}; + %feature("director:except") { if ($$error != NULL) { handleDirectorException(); diff --git a/engine/swigwrappers/python/fife.i.templ.cm b/engine/swigwrappers/python/fife.i.templ.cm index 02d6e554a..639fcbd7e 100644 --- a/engine/swigwrappers/python/fife.i.templ.cm +++ b/engine/swigwrappers/python/fife.i.templ.cm @@ -170,6 +170,12 @@ print s\n\ %exceptionclass FIFE::InconsistencyDetected; %exceptionclass FIFE::OutOfMemory; +%extend FIFE::Exception { + const char *__str__() { + return self->what(); + } +}; + %feature("director:except") { if ($error != NULL) { handleDirectorException(); diff --git a/tests/fife_test/data/objects/actors/player/frigate/back_object.xml b/tests/fife_test/data/objects/actors/player/frigate/back_object.xml index 5553904a9..597f149bc 100644 --- a/tests/fife_test/data/objects/actors/player/frigate/back_object.xml +++ b/tests/fife_test/data/objects/actors/player/frigate/back_object.xml @@ -1,51 +1,53 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/frigate/dummy/animation.xml b/tests/fife_test/data/objects/actors/player/frigate/dummy/animation.xml index c210eb10b..870d8192e 100644 --- a/tests/fife_test/data/objects/actors/player/frigate/dummy/animation.xml +++ b/tests/fife_test/data/objects/actors/player/frigate/dummy/animation.xml @@ -1,4 +1,6 @@ - - - + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/frigate/front_object.xml b/tests/fife_test/data/objects/actors/player/frigate/front_object.xml index 602454add..39ed4263d 100644 --- a/tests/fife_test/data/objects/actors/player/frigate/front_object.xml +++ b/tests/fife_test/data/objects/actors/player/frigate/front_object.xml @@ -1,51 +1,53 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/frigate/move/0/animation.xml b/tests/fife_test/data/objects/actors/player/frigate/move/0/animation.xml index d0292a866..f65c4d16d 100644 --- a/tests/fife_test/data/objects/actors/player/frigate/move/0/animation.xml +++ b/tests/fife_test/data/objects/actors/player/frigate/move/0/animation.xml @@ -1,4 +1,6 @@ - - - + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/frigate/move/135/animation.xml b/tests/fife_test/data/objects/actors/player/frigate/move/135/animation.xml index d0292a866..f65c4d16d 100644 --- a/tests/fife_test/data/objects/actors/player/frigate/move/135/animation.xml +++ b/tests/fife_test/data/objects/actors/player/frigate/move/135/animation.xml @@ -1,4 +1,6 @@ - - - + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/frigate/move/180/animation.xml b/tests/fife_test/data/objects/actors/player/frigate/move/180/animation.xml index d0292a866..f65c4d16d 100644 --- a/tests/fife_test/data/objects/actors/player/frigate/move/180/animation.xml +++ b/tests/fife_test/data/objects/actors/player/frigate/move/180/animation.xml @@ -1,4 +1,6 @@ - - - + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/frigate/move/225/animation.xml b/tests/fife_test/data/objects/actors/player/frigate/move/225/animation.xml index d0292a866..f65c4d16d 100644 --- a/tests/fife_test/data/objects/actors/player/frigate/move/225/animation.xml +++ b/tests/fife_test/data/objects/actors/player/frigate/move/225/animation.xml @@ -1,4 +1,6 @@ - - - + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/frigate/move/270/animation.xml b/tests/fife_test/data/objects/actors/player/frigate/move/270/animation.xml index d0292a866..f65c4d16d 100644 --- a/tests/fife_test/data/objects/actors/player/frigate/move/270/animation.xml +++ b/tests/fife_test/data/objects/actors/player/frigate/move/270/animation.xml @@ -1,4 +1,6 @@ - - - + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/frigate/move/315/animation.xml b/tests/fife_test/data/objects/actors/player/frigate/move/315/animation.xml index d0292a866..f65c4d16d 100644 --- a/tests/fife_test/data/objects/actors/player/frigate/move/315/animation.xml +++ b/tests/fife_test/data/objects/actors/player/frigate/move/315/animation.xml @@ -1,4 +1,6 @@ - - - + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/frigate/move/45/animation.xml b/tests/fife_test/data/objects/actors/player/frigate/move/45/animation.xml index d0292a866..f65c4d16d 100644 --- a/tests/fife_test/data/objects/actors/player/frigate/move/45/animation.xml +++ b/tests/fife_test/data/objects/actors/player/frigate/move/45/animation.xml @@ -1,4 +1,6 @@ - - - + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/frigate/move/90/animation.xml b/tests/fife_test/data/objects/actors/player/frigate/move/90/animation.xml index d0292a866..f65c4d16d 100644 --- a/tests/fife_test/data/objects/actors/player/frigate/move/90/animation.xml +++ b/tests/fife_test/data/objects/actors/player/frigate/move/90/animation.xml @@ -1,4 +1,6 @@ - - - + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/frigate/object.xml b/tests/fife_test/data/objects/actors/player/frigate/object.xml index 3405adbd6..52d5e4b5e 100644 --- a/tests/fife_test/data/objects/actors/player/frigate/object.xml +++ b/tests/fife_test/data/objects/actors/player/frigate/object.xml @@ -1,25 +1,27 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/hero/buckler_atlas.xml b/tests/fife_test/data/objects/actors/player/hero/buckler_atlas.xml index 298757574..f20786733 100644 --- a/tests/fife_test/data/objects/actors/player/hero/buckler_atlas.xml +++ b/tests/fife_test/data/objects/actors/player/hero/buckler_atlas.xml @@ -1,115 +1,117 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/hero/clothes_atlas.xml b/tests/fife_test/data/objects/actors/player/hero/clothes_atlas.xml index efd218a2c..d39ffb9f5 100644 --- a/tests/fife_test/data/objects/actors/player/hero/clothes_atlas.xml +++ b/tests/fife_test/data/objects/actors/player/hero/clothes_atlas.xml @@ -1,115 +1,117 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/hero/dagger_atlas.xml b/tests/fife_test/data/objects/actors/player/hero/dagger_atlas.xml index c027cf2ee..16f59824f 100644 --- a/tests/fife_test/data/objects/actors/player/hero/dagger_atlas.xml +++ b/tests/fife_test/data/objects/actors/player/hero/dagger_atlas.xml @@ -1,115 +1,117 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/hero/greatbow_atlas.xml b/tests/fife_test/data/objects/actors/player/hero/greatbow_atlas.xml index d612be29e..560c79f01 100644 --- a/tests/fife_test/data/objects/actors/player/hero/greatbow_atlas.xml +++ b/tests/fife_test/data/objects/actors/player/hero/greatbow_atlas.xml @@ -1,115 +1,117 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/hero/greatstaff_atlas.xml b/tests/fife_test/data/objects/actors/player/hero/greatstaff_atlas.xml index d0a9b7303..c09fca648 100644 --- a/tests/fife_test/data/objects/actors/player/hero/greatstaff_atlas.xml +++ b/tests/fife_test/data/objects/actors/player/hero/greatstaff_atlas.xml @@ -1,115 +1,117 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/hero/greatsword_atlas.xml b/tests/fife_test/data/objects/actors/player/hero/greatsword_atlas.xml index 59c79a6a3..b6ea9e463 100644 --- a/tests/fife_test/data/objects/actors/player/hero/greatsword_atlas.xml +++ b/tests/fife_test/data/objects/actors/player/hero/greatsword_atlas.xml @@ -1,115 +1,117 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/hero/leather_armor_atlas.xml b/tests/fife_test/data/objects/actors/player/hero/leather_armor_atlas.xml index 8154497fa..07710a473 100644 --- a/tests/fife_test/data/objects/actors/player/hero/leather_armor_atlas.xml +++ b/tests/fife_test/data/objects/actors/player/hero/leather_armor_atlas.xml @@ -1,115 +1,117 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/hero/longbow_atlas.xml b/tests/fife_test/data/objects/actors/player/hero/longbow_atlas.xml index 43258dace..8f4f8970d 100644 --- a/tests/fife_test/data/objects/actors/player/hero/longbow_atlas.xml +++ b/tests/fife_test/data/objects/actors/player/hero/longbow_atlas.xml @@ -1,115 +1,117 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/hero/longsword_atlas.xml b/tests/fife_test/data/objects/actors/player/hero/longsword_atlas.xml index b52b49e97..e5d6b4150 100644 --- a/tests/fife_test/data/objects/actors/player/hero/longsword_atlas.xml +++ b/tests/fife_test/data/objects/actors/player/hero/longsword_atlas.xml @@ -1,115 +1,117 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/hero/male_head1_atlas.xml b/tests/fife_test/data/objects/actors/player/hero/male_head1_atlas.xml index dde4fc6f6..d9b521ad7 100644 --- a/tests/fife_test/data/objects/actors/player/hero/male_head1_atlas.xml +++ b/tests/fife_test/data/objects/actors/player/hero/male_head1_atlas.xml @@ -1,115 +1,117 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/hero/male_head2_atlas.xml b/tests/fife_test/data/objects/actors/player/hero/male_head2_atlas.xml index e81ea6914..2f21ca183 100644 --- a/tests/fife_test/data/objects/actors/player/hero/male_head2_atlas.xml +++ b/tests/fife_test/data/objects/actors/player/hero/male_head2_atlas.xml @@ -1,115 +1,117 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/hero/male_head3_atlas.xml b/tests/fife_test/data/objects/actors/player/hero/male_head3_atlas.xml index 0fb5cc697..26b0c7fea 100644 --- a/tests/fife_test/data/objects/actors/player/hero/male_head3_atlas.xml +++ b/tests/fife_test/data/objects/actors/player/hero/male_head3_atlas.xml @@ -1,115 +1,117 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/hero/object.xml b/tests/fife_test/data/objects/actors/player/hero/object.xml index 0abddba8c..f0c232fb3 100644 --- a/tests/fife_test/data/objects/actors/player/hero/object.xml +++ b/tests/fife_test/data/objects/actors/player/hero/object.xml @@ -1,7 +1,9 @@ - - - - - - + + + + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/hero/rod_atlas.xml b/tests/fife_test/data/objects/actors/player/hero/rod_atlas.xml index ea4dc54ad..159fa30d9 100644 --- a/tests/fife_test/data/objects/actors/player/hero/rod_atlas.xml +++ b/tests/fife_test/data/objects/actors/player/hero/rod_atlas.xml @@ -1,115 +1,117 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/hero/shield_atlas.xml b/tests/fife_test/data/objects/actors/player/hero/shield_atlas.xml index 3840eaae3..ff3bb6b09 100644 --- a/tests/fife_test/data/objects/actors/player/hero/shield_atlas.xml +++ b/tests/fife_test/data/objects/actors/player/hero/shield_atlas.xml @@ -1,115 +1,117 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/hero/shortbow_atlas.xml b/tests/fife_test/data/objects/actors/player/hero/shortbow_atlas.xml index 043b68c88..f423b4e3c 100644 --- a/tests/fife_test/data/objects/actors/player/hero/shortbow_atlas.xml +++ b/tests/fife_test/data/objects/actors/player/hero/shortbow_atlas.xml @@ -1,115 +1,117 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/hero/shortsword_atlas.xml b/tests/fife_test/data/objects/actors/player/hero/shortsword_atlas.xml index 6f74529ff..6bfdc86f2 100644 --- a/tests/fife_test/data/objects/actors/player/hero/shortsword_atlas.xml +++ b/tests/fife_test/data/objects/actors/player/hero/shortsword_atlas.xml @@ -1,115 +1,117 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/hero/slingshot_atlas.xml b/tests/fife_test/data/objects/actors/player/hero/slingshot_atlas.xml index d117f3671..27e9da43e 100644 --- a/tests/fife_test/data/objects/actors/player/hero/slingshot_atlas.xml +++ b/tests/fife_test/data/objects/actors/player/hero/slingshot_atlas.xml @@ -1,115 +1,117 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/hero/staff_atlas.xml b/tests/fife_test/data/objects/actors/player/hero/staff_atlas.xml index 34b92151e..4ae9664c2 100644 --- a/tests/fife_test/data/objects/actors/player/hero/staff_atlas.xml +++ b/tests/fife_test/data/objects/actors/player/hero/staff_atlas.xml @@ -1,115 +1,117 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/hero/steel_armor_atlas.xml b/tests/fife_test/data/objects/actors/player/hero/steel_armor_atlas.xml index b78d46bfc..50046c170 100644 --- a/tests/fife_test/data/objects/actors/player/hero/steel_armor_atlas.xml +++ b/tests/fife_test/data/objects/actors/player/hero/steel_armor_atlas.xml @@ -1,115 +1,117 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/hero/wand_atlas.xml b/tests/fife_test/data/objects/actors/player/hero/wand_atlas.xml index e31e4fb36..8b716a748 100644 --- a/tests/fife_test/data/objects/actors/player/hero/wand_atlas.xml +++ b/tests/fife_test/data/objects/actors/player/hero/wand_atlas.xml @@ -1,115 +1,117 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/objects/actors/player/skel/object.xml b/tests/fife_test/data/objects/actors/player/skel/object.xml index 64773dd20..30b0f7518 100644 --- a/tests/fife_test/data/objects/actors/player/skel/object.xml +++ b/tests/fife_test/data/objects/actors/player/skel/object.xml @@ -1,27 +1,29 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/tilesets/grassland_tiles.xml b/tests/fife_test/data/tilesets/grassland_tiles.xml index 799929083..a56cd1b06 100644 --- a/tests/fife_test/data/tilesets/grassland_tiles.xml +++ b/tests/fife_test/data/tilesets/grassland_tiles.xml @@ -1,846 +1,848 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/tilesets/rpg_tiles.xml b/tests/fife_test/data/tilesets/rpg_tiles.xml index 3c7a588f7..c2517f724 100644 --- a/tests/fife_test/data/tilesets/rpg_tiles.xml +++ b/tests/fife_test/data/tilesets/rpg_tiles.xml @@ -1,192 +1,194 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/tilesets/skel_overlay_tiles.xml b/tests/fife_test/data/tilesets/skel_overlay_tiles.xml index 3828f2887..e586a4b13 100644 --- a/tests/fife_test/data/tilesets/skel_overlay_tiles.xml +++ b/tests/fife_test/data/tilesets/skel_overlay_tiles.xml @@ -1,42 +1,44 @@ - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/tilesets/terrain1.xml b/tests/fife_test/data/tilesets/terrain1.xml index e1e202250..cf4bf0283 100644 --- a/tests/fife_test/data/tilesets/terrain1.xml +++ b/tests/fife_test/data/tilesets/terrain1.xml @@ -1,246 +1,248 @@ - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/fife_test/data/tilesets/toilett.xml b/tests/fife_test/data/tilesets/toilett.xml index c3aa1f2c6..b32649e40 100644 --- a/tests/fife_test/data/tilesets/toilett.xml +++ b/tests/fife_test/data/tilesets/toilett.xml @@ -1,11 +1,13 @@ - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + \ No newline at end of file