Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
506b9130a8 | ||
|
|
5d1b70a7f2 | ||
|
|
eff3df57d9 | ||
|
|
2931f3380f |
+15
-75
@@ -1,29 +1,14 @@
|
|||||||
cmake_minimum_required (VERSION 2.8.11)
|
cmake_minimum_required (VERSION 2.6.4)
|
||||||
|
|
||||||
if(COMMAND cmake_policy)
|
|
||||||
if(POLICY CMP0054)
|
|
||||||
cmake_policy(SET CMP0054 NEW)
|
|
||||||
endif()
|
|
||||||
if(POLICY CMP0042)
|
|
||||||
cmake_policy(SET CMP0042 NEW)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
include (CheckFunctionExists)
|
include (CheckFunctionExists)
|
||||||
include (CheckIncludeFile)
|
include (CheckIncludeFile)
|
||||||
include (CheckLibraryExists)
|
|
||||||
include (CheckCXXSourceCompiles)
|
include (CheckCXXSourceCompiles)
|
||||||
include (CheckCXXCompilerFlag)
|
include (CheckCXXCompilerFlag)
|
||||||
include (GenerateExportHeader)
|
|
||||||
|
project(SimGear)
|
||||||
|
|
||||||
# using 10.7 because boost requires libc++ and 10.6 doesn't include it
|
# using 10.7 because boost requires libc++ and 10.6 doesn't include it
|
||||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7)
|
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7)
|
||||||
|
|
||||||
# only relevant for building shared libs but let's set it regardless
|
|
||||||
set(CMAKE_OSX_RPATH 1)
|
|
||||||
|
|
||||||
project(SimGear)
|
|
||||||
|
|
||||||
# read 'version' file into a variable (stripping any newlines or spaces)
|
# read 'version' file into a variable (stripping any newlines or spaces)
|
||||||
file(READ version versionFile)
|
file(READ version versionFile)
|
||||||
string(STRIP ${versionFile} SIMGEAR_VERSION)
|
string(STRIP ${versionFile} SIMGEAR_VERSION)
|
||||||
@@ -80,7 +65,12 @@ endif(NOT CMAKE_BUILD_TYPE)
|
|||||||
# Determine name of library installation directory, i.e. "lib" vs "lib64", which
|
# Determine name of library installation directory, i.e. "lib" vs "lib64", which
|
||||||
# differs between all Debian-based vs all other Linux distros.
|
# differs between all Debian-based vs all other Linux distros.
|
||||||
# See cmake bug #11964, http://cmake.org/gitweb?p=cmake.git;a=commit;h=126c993d
|
# See cmake bug #11964, http://cmake.org/gitweb?p=cmake.git;a=commit;h=126c993d
|
||||||
include(GNUInstallDirs)
|
# GNUInstallDirs requires CMake >= 2.8.5, use own file for older cmake
|
||||||
|
if(${CMAKE_VERSION} VERSION_GREATER 2.8.4)
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
else(${CMAKE_VERSION} VERSION_GREATER 2.8.4)
|
||||||
|
include(OldGNUInstallDirs)
|
||||||
|
endif(${CMAKE_VERSION} VERSION_GREATER 2.8.4)
|
||||||
message(STATUS "Library installation directory: ${CMAKE_INSTALL_LIBDIR}")
|
message(STATUS "Library installation directory: ${CMAKE_INSTALL_LIBDIR}")
|
||||||
|
|
||||||
#####################################################################################
|
#####################################################################################
|
||||||
@@ -117,7 +107,6 @@ option(ENABLE_RTI "Set to ON to build SimGear with RTI support" OFF)
|
|||||||
option(ENABLE_TESTS "Set to OFF to disable building SimGear's test applications" ON)
|
option(ENABLE_TESTS "Set to OFF to disable building SimGear's test applications" ON)
|
||||||
option(ENABLE_SOUND "Set to OFF to disable building SimGear's sound support" ON)
|
option(ENABLE_SOUND "Set to OFF to disable building SimGear's sound support" ON)
|
||||||
option(ENABLE_PKGUTIL "Set to ON to build the sg_pkgutil application (default)" ON)
|
option(ENABLE_PKGUTIL "Set to ON to build the sg_pkgutil application (default)" ON)
|
||||||
option(ENABLE_CURL "Set to ON to use libCurl as the HTTP client backend" OFF)
|
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
GET_FILENAME_COMPONENT(PARENT_DIR ${PROJECT_BINARY_DIR} PATH)
|
GET_FILENAME_COMPONENT(PARENT_DIR ${PROJECT_BINARY_DIR} PATH)
|
||||||
@@ -175,23 +164,13 @@ endif (MSVC AND MSVC_3RDPARTY_ROOT)
|
|||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
find_library(COCOA_LIBRARY Cocoa)
|
find_library(COCOA_LIBRARY Cocoa)
|
||||||
|
|
||||||
# this should be handled by setting CMAKE_OSX_DEPLOYMENT_TARGET
|
|
||||||
# but it's not working reliably, so forcing it for now
|
|
||||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.7")
|
|
||||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmacosx-version-min=10.7")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux" OR
|
|
||||||
${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
|
|
||||||
find_package(Threads REQUIRED)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Somehow this only works if included before searching for Boost...
|
# Somehow this only works if included before searching for Boost...
|
||||||
include(BoostTestTargets)
|
include(BoostTestTargets)
|
||||||
|
|
||||||
find_package(Boost REQUIRED)
|
find_package(Boost REQUIRED)
|
||||||
set (BOOST_CXX_FLAGS "-DBOOST_BIMAP_DISABLE_SERIALIZATION")
|
set (BOOST_CXX_FLAGS "-DBOOST_MULTI_INDEX_DISABLE_SERIALIZATION -DBOOST_BIMAP_DISABLE_SERIALIZATION")
|
||||||
|
|
||||||
if(SIMGEAR_HEADLESS)
|
if(SIMGEAR_HEADLESS)
|
||||||
message(STATUS "SimGear mode: HEADLESS")
|
message(STATUS "SimGear mode: HEADLESS")
|
||||||
@@ -209,11 +188,7 @@ else()
|
|||||||
endif(SIMGEAR_HEADLESS)
|
endif(SIMGEAR_HEADLESS)
|
||||||
|
|
||||||
find_package(ZLIB REQUIRED)
|
find_package(ZLIB REQUIRED)
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
if (ENABLE_CURL)
|
|
||||||
find_package(CURL REQUIRED)
|
|
||||||
message(STATUS "Curl HTTP client: ENABLED")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (SYSTEM_EXPAT)
|
if (SYSTEM_EXPAT)
|
||||||
message(STATUS "Requested to use system Expat library, forcing SIMGEAR_SHARED to true")
|
message(STATUS "Requested to use system Expat library, forcing SIMGEAR_SHARED to true")
|
||||||
@@ -325,8 +300,7 @@ if(CMAKE_COMPILER_IS_GNUCXX)
|
|||||||
endif(CMAKE_COMPILER_IS_GNUCXX)
|
endif(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
# Boost redeclares class members
|
set(WARNING_FLAGS_CXX "-Wall -Wno-overloaded-virtual")
|
||||||
set(WARNING_FLAGS_CXX "-Wall -Wno-overloaded-virtual -Wno-redeclared-class-member")
|
|
||||||
set(WARNING_FLAGS_C "-Wall")
|
set(WARNING_FLAGS_C "-Wall")
|
||||||
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++")
|
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++")
|
||||||
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++11")
|
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++11")
|
||||||
@@ -380,7 +354,6 @@ include_directories(${OPENSCENEGRAPH_INCLUDE_DIRS}
|
|||||||
${Boost_INCLUDE_DIRS}
|
${Boost_INCLUDE_DIRS}
|
||||||
${ZLIB_INCLUDE_DIR}
|
${ZLIB_INCLUDE_DIR}
|
||||||
${OPENAL_INCLUDE_DIR}
|
${OPENAL_INCLUDE_DIR}
|
||||||
${CURL_INCLUDE_DIRS}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
add_definitions(-DHAVE_CONFIG_H)
|
add_definitions(-DHAVE_CONFIG_H)
|
||||||
@@ -409,8 +382,7 @@ set(TEST_LIBS_INTERNAL_CORE
|
|||||||
${WINSOCK_LIBRARY}
|
${WINSOCK_LIBRARY}
|
||||||
${RT_LIBRARY}
|
${RT_LIBRARY}
|
||||||
${DL_LIBRARY}
|
${DL_LIBRARY}
|
||||||
${COCOA_LIBRARY}
|
${COCOA_LIBRARY})
|
||||||
${CURL_LIBRARIES})
|
|
||||||
set(TEST_LIBS SimGearCore ${TEST_LIBS_INTERNAL_CORE})
|
set(TEST_LIBS SimGearCore ${TEST_LIBS_INTERNAL_CORE})
|
||||||
|
|
||||||
if(NOT SIMGEAR_HEADLESS)
|
if(NOT SIMGEAR_HEADLESS)
|
||||||
@@ -424,40 +396,6 @@ include_directories(3rdparty/utf8/source)
|
|||||||
add_subdirectory(3rdparty)
|
add_subdirectory(3rdparty)
|
||||||
add_subdirectory(simgear)
|
add_subdirectory(simgear)
|
||||||
|
|
||||||
#-----------------------------------------------------------------------------
|
|
||||||
### Export stuff, see https://cmake.org/cmake/help/v3.2/manual/cmake-packages.7.html#creating-packages
|
|
||||||
#-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
generate_export_header(SimGearCore)
|
|
||||||
if(NOT SIMGEAR_HEADLESS)
|
|
||||||
generate_export_header(SimGearScene)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
include(CMakePackageConfigHelpers)
|
|
||||||
|
|
||||||
write_basic_package_version_file(
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/SimGear/SimGearConfigVersion.cmake"
|
|
||||||
VERSION ${SIMGEAR_VERSION}
|
|
||||||
COMPATIBILITY AnyNewerVersion
|
|
||||||
)
|
|
||||||
|
|
||||||
configure_file(SimGearConfig.cmake.in
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/SimGear/SimGearConfig.cmake"
|
|
||||||
@ONLY
|
|
||||||
)
|
|
||||||
|
|
||||||
set(ConfigPackageLocation lib/cmake/SimGear)
|
|
||||||
install(EXPORT SimGearTargets
|
|
||||||
DESTINATION ${ConfigPackageLocation}
|
|
||||||
)
|
|
||||||
install(
|
|
||||||
FILES
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/SimGear/SimGearConfig.cmake"
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/SimGear/SimGearConfigVersion.cmake"
|
|
||||||
DESTINATION ${ConfigPackageLocation}
|
|
||||||
COMPONENT Devel
|
|
||||||
)
|
|
||||||
|
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
### uninstall target
|
### uninstall target
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
@@ -467,3 +405,5 @@ CONFIGURE_FILE(
|
|||||||
IMMEDIATE @ONLY)
|
IMMEDIATE @ONLY)
|
||||||
ADD_CUSTOM_TARGET(uninstall
|
ADD_CUSTOM_TARGET(uninstall
|
||||||
"${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
|
"${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,182 @@
|
|||||||
|
# - Define GNU standard installation directories
|
||||||
|
# Provides install directory variables as defined for GNU software:
|
||||||
|
# http://www.gnu.org/prep/standards/html_node/Directory-Variables.html
|
||||||
|
# Inclusion of this module defines the following variables:
|
||||||
|
# CMAKE_INSTALL_<dir> - destination for files of a given type
|
||||||
|
# CMAKE_INSTALL_FULL_<dir> - corresponding absolute path
|
||||||
|
# where <dir> is one of:
|
||||||
|
# BINDIR - user executables (bin)
|
||||||
|
# SBINDIR - system admin executables (sbin)
|
||||||
|
# LIBEXECDIR - program executables (libexec)
|
||||||
|
# SYSCONFDIR - read-only single-machine data (etc)
|
||||||
|
# SHAREDSTATEDIR - modifiable architecture-independent data (com)
|
||||||
|
# LOCALSTATEDIR - modifiable single-machine data (var)
|
||||||
|
# LIBDIR - object code libraries (lib or lib64)
|
||||||
|
# INCLUDEDIR - C header files (include)
|
||||||
|
# OLDINCLUDEDIR - C header files for non-gcc (/usr/include)
|
||||||
|
# DATAROOTDIR - read-only architecture-independent data root (share)
|
||||||
|
# DATADIR - read-only architecture-independent data (DATAROOTDIR)
|
||||||
|
# INFODIR - info documentation (DATAROOTDIR/info)
|
||||||
|
# LOCALEDIR - locale-dependent data (DATAROOTDIR/locale)
|
||||||
|
# MANDIR - man documentation (DATAROOTDIR/man)
|
||||||
|
# DOCDIR - documentation root (DATAROOTDIR/doc/PROJECT_NAME)
|
||||||
|
# Each CMAKE_INSTALL_<dir> value may be passed to the DESTINATION options of
|
||||||
|
# install() commands for the corresponding file type. If the includer does
|
||||||
|
# not define a value the above-shown default will be used and the value will
|
||||||
|
# appear in the cache for editing by the user.
|
||||||
|
# Each CMAKE_INSTALL_FULL_<dir> value contains an absolute path constructed
|
||||||
|
# from the corresponding destination by prepending (if necessary) the value
|
||||||
|
# of CMAKE_INSTALL_PREFIX.
|
||||||
|
|
||||||
|
#=============================================================================
|
||||||
|
# Copyright 2011 Nikita Krupen'ko <krnekit@gmail.com>
|
||||||
|
# Copyright 2011 Kitware, Inc.
|
||||||
|
#
|
||||||
|
# Distributed under the OSI-approved BSD License (the "License");
|
||||||
|
# see accompanying file Copyright.txt for details.
|
||||||
|
#
|
||||||
|
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||||
|
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
# See the License for more information.
|
||||||
|
#=============================================================================
|
||||||
|
# (To distribute this file outside of CMake, substitute the full
|
||||||
|
# License text for the above reference.)
|
||||||
|
|
||||||
|
# Installation directories
|
||||||
|
#
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_BINDIR)
|
||||||
|
set(CMAKE_INSTALL_BINDIR "bin" CACHE PATH "user executables (bin)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_SBINDIR)
|
||||||
|
set(CMAKE_INSTALL_SBINDIR "sbin" CACHE PATH "system admin executables (sbin)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_LIBEXECDIR)
|
||||||
|
set(CMAKE_INSTALL_LIBEXECDIR "libexec" CACHE PATH "program executables (libexec)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_SYSCONFDIR)
|
||||||
|
set(CMAKE_INSTALL_SYSCONFDIR "etc" CACHE PATH "read-only single-machine data (etc)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_SHAREDSTATEDIR)
|
||||||
|
set(CMAKE_INSTALL_SHAREDSTATEDIR "com" CACHE PATH "modifiable architecture-independent data (com)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_LOCALSTATEDIR)
|
||||||
|
set(CMAKE_INSTALL_LOCALSTATEDIR "var" CACHE PATH "modifiable single-machine data (var)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_LIBDIR)
|
||||||
|
set(_LIBDIR_DEFAULT "lib")
|
||||||
|
# Override this default 'lib' with 'lib64' iff:
|
||||||
|
# - we are on Linux system but NOT cross-compiling
|
||||||
|
# - we are NOT on debian
|
||||||
|
# - we are on a 64 bits system
|
||||||
|
# reason is: amd64 ABI: http://www.x86-64.org/documentation/abi.pdf
|
||||||
|
# Note that the future of multi-arch handling may be even
|
||||||
|
# more complicated than that: http://wiki.debian.org/Multiarch
|
||||||
|
if(CMAKE_SYSTEM_NAME MATCHES "Linux"
|
||||||
|
AND NOT CMAKE_CROSSCOMPILING
|
||||||
|
AND NOT EXISTS "/etc/debian_version")
|
||||||
|
if(NOT DEFINED CMAKE_SIZEOF_VOID_P)
|
||||||
|
message(AUTHOR_WARNING
|
||||||
|
"Unable to determine default CMAKE_INSTALL_LIBDIR directory because no target architecture is known. "
|
||||||
|
"Please enable at least one language before including GNUInstallDirs.")
|
||||||
|
else()
|
||||||
|
if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
|
||||||
|
set(_LIBDIR_DEFAULT "lib64")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
set(CMAKE_INSTALL_LIBDIR "${_LIBDIR_DEFAULT}" CACHE PATH "object code libraries (${_LIBDIR_DEFAULT})")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_INCLUDEDIR)
|
||||||
|
set(CMAKE_INSTALL_INCLUDEDIR "include" CACHE PATH "C header files (include)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_OLDINCLUDEDIR)
|
||||||
|
set(CMAKE_INSTALL_OLDINCLUDEDIR "/usr/include" CACHE PATH "C header files for non-gcc (/usr/include)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_DATAROOTDIR)
|
||||||
|
set(CMAKE_INSTALL_DATAROOTDIR "share" CACHE PATH "read-only architecture-independent data root (share)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Values whose defaults are relative to DATAROOTDIR. Store empty values in
|
||||||
|
# the cache and store the defaults in local variables if the cache values are
|
||||||
|
# not set explicitly. This auto-updates the defaults as DATAROOTDIR changes.
|
||||||
|
|
||||||
|
if(NOT CMAKE_INSTALL_DATADIR)
|
||||||
|
set(CMAKE_INSTALL_DATADIR "" CACHE PATH "read-only architecture-independent data (DATAROOTDIR)")
|
||||||
|
set(CMAKE_INSTALL_DATADIR "${CMAKE_INSTALL_DATAROOTDIR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT CMAKE_INSTALL_INFODIR)
|
||||||
|
set(CMAKE_INSTALL_INFODIR "" CACHE PATH "info documentation (DATAROOTDIR/info)")
|
||||||
|
set(CMAKE_INSTALL_INFODIR "${CMAKE_INSTALL_DATAROOTDIR}/info")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT CMAKE_INSTALL_LOCALEDIR)
|
||||||
|
set(CMAKE_INSTALL_LOCALEDIR "" CACHE PATH "locale-dependent data (DATAROOTDIR/locale)")
|
||||||
|
set(CMAKE_INSTALL_LOCALEDIR "${CMAKE_INSTALL_DATAROOTDIR}/locale")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT CMAKE_INSTALL_MANDIR)
|
||||||
|
set(CMAKE_INSTALL_MANDIR "" CACHE PATH "man documentation (DATAROOTDIR/man)")
|
||||||
|
set(CMAKE_INSTALL_MANDIR "${CMAKE_INSTALL_DATAROOTDIR}/man")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT CMAKE_INSTALL_DOCDIR)
|
||||||
|
set(CMAKE_INSTALL_DOCDIR "" CACHE PATH "documentation root (DATAROOTDIR/doc/PROJECT_NAME)")
|
||||||
|
set(CMAKE_INSTALL_DOCDIR "${CMAKE_INSTALL_DATAROOTDIR}/doc/${PROJECT_NAME}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
mark_as_advanced(
|
||||||
|
CMAKE_INSTALL_BINDIR
|
||||||
|
CMAKE_INSTALL_SBINDIR
|
||||||
|
CMAKE_INSTALL_LIBEXECDIR
|
||||||
|
CMAKE_INSTALL_SYSCONFDIR
|
||||||
|
CMAKE_INSTALL_SHAREDSTATEDIR
|
||||||
|
CMAKE_INSTALL_LOCALSTATEDIR
|
||||||
|
CMAKE_INSTALL_LIBDIR
|
||||||
|
CMAKE_INSTALL_INCLUDEDIR
|
||||||
|
CMAKE_INSTALL_OLDINCLUDEDIR
|
||||||
|
CMAKE_INSTALL_DATAROOTDIR
|
||||||
|
CMAKE_INSTALL_DATADIR
|
||||||
|
CMAKE_INSTALL_INFODIR
|
||||||
|
CMAKE_INSTALL_LOCALEDIR
|
||||||
|
CMAKE_INSTALL_MANDIR
|
||||||
|
CMAKE_INSTALL_DOCDIR
|
||||||
|
)
|
||||||
|
|
||||||
|
# Result directories
|
||||||
|
#
|
||||||
|
foreach(dir
|
||||||
|
BINDIR
|
||||||
|
SBINDIR
|
||||||
|
LIBEXECDIR
|
||||||
|
SYSCONFDIR
|
||||||
|
SHAREDSTATEDIR
|
||||||
|
LOCALSTATEDIR
|
||||||
|
LIBDIR
|
||||||
|
INCLUDEDIR
|
||||||
|
OLDINCLUDEDIR
|
||||||
|
DATAROOTDIR
|
||||||
|
DATADIR
|
||||||
|
INFODIR
|
||||||
|
LOCALEDIR
|
||||||
|
MANDIR
|
||||||
|
DOCDIR
|
||||||
|
)
|
||||||
|
if(NOT IS_ABSOLUTE ${CMAKE_INSTALL_${dir}})
|
||||||
|
set(CMAKE_INSTALL_FULL_${dir} "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_${dir}}")
|
||||||
|
else()
|
||||||
|
set(CMAKE_INSTALL_FULL_${dir} "${CMAKE_INSTALL_${dir}}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
include(CMakeFindDependencyMacro)
|
|
||||||
|
|
||||||
find_dependency(ZLIB)
|
|
||||||
find_dependency(Threads)
|
|
||||||
|
|
||||||
# OSG
|
|
||||||
|
|
||||||
set(SIMGEAR_HEADLESS @SIMGEAR_HEADLESS@)
|
|
||||||
set(SIMGEAR_SOUND @ENABLE_SOUND@)
|
|
||||||
|
|
||||||
# OpenAL isn't a public dependency, so maybe not needed
|
|
||||||
#if (SIMGEAR_SOUND)
|
|
||||||
# find_dependency(OpenAL)
|
|
||||||
#endif()
|
|
||||||
|
|
||||||
include("${CMAKE_CURRENT_LIST_DIR}/SimGearTargets.cmake")
|
|
||||||
+7
-16
@@ -54,10 +54,8 @@ if(SIMGEAR_SHARED)
|
|||||||
set_property(TARGET SimGearCore PROPERTY LINKER_LANGUAGE CXX)
|
set_property(TARGET SimGearCore PROPERTY LINKER_LANGUAGE CXX)
|
||||||
set_property(TARGET SimGearCore PROPERTY VERSION ${SIMGEAR_VERSION})
|
set_property(TARGET SimGearCore PROPERTY VERSION ${SIMGEAR_VERSION})
|
||||||
set_property(TARGET SimGearCore PROPERTY SOVERSION ${SIMGEAR_SOVERSION})
|
set_property(TARGET SimGearCore PROPERTY SOVERSION ${SIMGEAR_SOVERSION})
|
||||||
install(TARGETS SimGearCore
|
install(TARGETS SimGearCore EXPORT SimGearCoreConfig LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||||
EXPORT SimGearTargets
|
install(EXPORT SimGearCoreConfig DESTINATION share/SimGearCore)
|
||||||
LIBRARY DESTINATION
|
|
||||||
${CMAKE_INSTALL_LIBDIR})
|
|
||||||
|
|
||||||
if(NOT SIMGEAR_HEADLESS)
|
if(NOT SIMGEAR_HEADLESS)
|
||||||
add_library(SimGearScene SHARED ${sceneSources})
|
add_library(SimGearScene SHARED ${sceneSources})
|
||||||
@@ -66,10 +64,8 @@ if(SIMGEAR_SHARED)
|
|||||||
set_property(TARGET SimGearScene PROPERTY SOVERSION ${SIMGEAR_SOVERSION})
|
set_property(TARGET SimGearScene PROPERTY SOVERSION ${SIMGEAR_SOVERSION})
|
||||||
|
|
||||||
# EXPORT SimGearSceneConfig
|
# EXPORT SimGearSceneConfig
|
||||||
install(TARGETS SimGearScene
|
install(TARGETS SimGearScene LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} )
|
||||||
EXPORT SimGearTargets
|
# install(EXPORT SimGearSceneConfig DESTINATION share/SimGearScene)
|
||||||
LIBRARY
|
|
||||||
DESTINATION ${CMAKE_INSTALL_LIBDIR} )
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
else()
|
else()
|
||||||
@@ -94,9 +90,7 @@ else()
|
|||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
add_library(SimGearCore STATIC ${coreSources} ${localExpatSources})
|
add_library(SimGearCore STATIC ${coreSources} ${localExpatSources})
|
||||||
install(TARGETS SimGearCore
|
install(TARGETS SimGearCore ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||||
EXPORT SimGearTargets
|
|
||||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
|
||||||
|
|
||||||
if(NOT SIMGEAR_HEADLESS)
|
if(NOT SIMGEAR_HEADLESS)
|
||||||
get_property(FG_GROUPS_SCENE_SOURCES_C GLOBAL PROPERTY FG_GROUPS_SCENE_SOURCES_C)
|
get_property(FG_GROUPS_SCENE_SOURCES_C GLOBAL PROPERTY FG_GROUPS_SCENE_SOURCES_C)
|
||||||
@@ -118,9 +112,7 @@ else()
|
|||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
add_library(SimGearScene STATIC ${sceneSources})
|
add_library(SimGearScene STATIC ${sceneSources})
|
||||||
install(TARGETS SimGearScene
|
install(TARGETS SimGearScene ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||||
EXPORT SimGearTargets
|
|
||||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
|
||||||
endif(NOT SIMGEAR_HEADLESS)
|
endif(NOT SIMGEAR_HEADLESS)
|
||||||
endif(SIMGEAR_SHARED)
|
endif(SIMGEAR_SHARED)
|
||||||
|
|
||||||
@@ -130,8 +122,7 @@ target_link_libraries(SimGearCore
|
|||||||
${DL_LIBRARY}
|
${DL_LIBRARY}
|
||||||
${EXPAT_LIBRARIES}
|
${EXPAT_LIBRARIES}
|
||||||
${CMAKE_THREAD_LIBS_INIT}
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
${COCOA_LIBRARY}
|
${COCOA_LIBRARY})
|
||||||
${CURL_LIBRARIES})
|
|
||||||
|
|
||||||
if(NOT SIMGEAR_HEADLESS)
|
if(NOT SIMGEAR_HEADLESS)
|
||||||
target_link_libraries(SimGearScene
|
target_link_libraries(SimGearScene
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public:
|
|||||||
void removeChild(BVHNode* child);
|
void removeChild(BVHNode* child);
|
||||||
|
|
||||||
unsigned getNumChildren() const
|
unsigned getNumChildren() const
|
||||||
{ return static_cast<unsigned>(_children.size()); }
|
{ return _children.size(); }
|
||||||
const BVHNode* getChild(unsigned i) const
|
const BVHNode* getChild(unsigned i) const
|
||||||
{ if (_children.size() <= i) return 0; return _children[i]; }
|
{ if (_children.size() <= i) return 0; return _children[i]; }
|
||||||
BVHNode* getChild(unsigned i)
|
BVHNode* getChild(unsigned i)
|
||||||
|
|||||||
@@ -31,13 +31,13 @@ public:
|
|||||||
virtual ~BVHStaticData() {}
|
virtual ~BVHStaticData() {}
|
||||||
|
|
||||||
unsigned addVertex(const SGVec3f& vertex)
|
unsigned addVertex(const SGVec3f& vertex)
|
||||||
{ _vertices.push_back(vertex); return static_cast<unsigned>(_vertices.size() - 1); }
|
{ _vertices.push_back(vertex); return _vertices.size() - 1; }
|
||||||
const SGVec3f& getVertex(unsigned i) const
|
const SGVec3f& getVertex(unsigned i) const
|
||||||
{ return _vertices[i]; }
|
{ return _vertices[i]; }
|
||||||
|
|
||||||
|
|
||||||
unsigned addMaterial(const BVHMaterial* material)
|
unsigned addMaterial(const BVHMaterial* material)
|
||||||
{ _materials.push_back(material); return static_cast<unsigned>(_materials.size() - 1); }
|
{ _materials.push_back(material); return _materials.size() - 1; }
|
||||||
const BVHMaterial* getMaterial(unsigned i) const
|
const BVHMaterial* getMaterial(unsigned i) const
|
||||||
{ if (_materials.size() <= i) return 0; return _materials[i]; }
|
{ if (_materials.size() <= i) return 0; return _materials[i]; }
|
||||||
|
|
||||||
|
|||||||
@@ -207,6 +207,19 @@ namespace canvas
|
|||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
Element::~Element()
|
Element::~Element()
|
||||||
{
|
{
|
||||||
|
if( !_transform.valid() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
for(unsigned int i = 0; i < _transform->getNumChildren(); ++i)
|
||||||
|
{
|
||||||
|
OSGUserData* ud =
|
||||||
|
static_cast<OSGUserData*>(_transform->getChild(i)->getUserData());
|
||||||
|
|
||||||
|
if( ud )
|
||||||
|
// Ensure parent is cleared to prevent accessing released memory if an
|
||||||
|
// element somehow survives longer than his parent.
|
||||||
|
ud->element->_parent = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@@ -233,7 +246,7 @@ namespace canvas
|
|||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
ElementPtr Element::getParent() const
|
ElementPtr Element::getParent() const
|
||||||
{
|
{
|
||||||
return _parent.lock();
|
return _parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@@ -311,9 +324,8 @@ namespace canvas
|
|||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool Element::ascend(EventVisitor& visitor)
|
bool Element::ascend(EventVisitor& visitor)
|
||||||
{
|
{
|
||||||
ElementPtr parent = getParent();
|
if( _parent )
|
||||||
if( parent )
|
return _parent->accept(visitor);
|
||||||
return parent->accept(visitor);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,9 +374,9 @@ namespace canvas
|
|||||||
EventPropagationPath path;
|
EventPropagationPath path;
|
||||||
path.push_back( EventTarget(this) );
|
path.push_back( EventTarget(this) );
|
||||||
|
|
||||||
for( ElementPtr parent = getParent();
|
for( Element* parent = _parent;
|
||||||
parent.valid();
|
parent != NULL;
|
||||||
parent = parent->getParent() )
|
parent = parent->_parent )
|
||||||
path.push_front( EventTarget(parent) );
|
path.push_front( EventTarget(parent) );
|
||||||
|
|
||||||
CanvasPtr canvas = _canvas.lock();
|
CanvasPtr canvas = _canvas.lock();
|
||||||
@@ -760,7 +772,7 @@ namespace canvas
|
|||||||
Element::Element( const CanvasWeakPtr& canvas,
|
Element::Element( const CanvasWeakPtr& canvas,
|
||||||
const SGPropertyNode_ptr& node,
|
const SGPropertyNode_ptr& node,
|
||||||
const Style& parent_style,
|
const Style& parent_style,
|
||||||
ElementWeakPtr parent ):
|
Element* parent ):
|
||||||
PropertyBasedElement(node),
|
PropertyBasedElement(node),
|
||||||
_canvas( canvas ),
|
_canvas( canvas ),
|
||||||
_parent( parent ),
|
_parent( parent ),
|
||||||
@@ -859,12 +871,11 @@ namespace canvas
|
|||||||
Element::getParentStyle(const SGPropertyNode* child) const
|
Element::getParentStyle(const SGPropertyNode* child) const
|
||||||
{
|
{
|
||||||
// Try to get value from parent...
|
// Try to get value from parent...
|
||||||
ElementPtr parent = getParent();
|
if( _parent )
|
||||||
if( parent )
|
|
||||||
{
|
{
|
||||||
Style::const_iterator style =
|
Style::const_iterator style =
|
||||||
parent->_style.find(child->getNameString());
|
_parent->_style.find(child->getNameString());
|
||||||
if( style != parent->_style.end() )
|
if( style != _parent->_style.end() )
|
||||||
return style->second;
|
return style->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ namespace canvas
|
|||||||
class RelativeScissor;
|
class RelativeScissor;
|
||||||
|
|
||||||
CanvasWeakPtr _canvas;
|
CanvasWeakPtr _canvas;
|
||||||
ElementWeakPtr _parent;
|
Element *_parent;
|
||||||
|
|
||||||
mutable uint32_t _attributes_dirty;
|
mutable uint32_t _attributes_dirty;
|
||||||
|
|
||||||
@@ -256,7 +256,7 @@ namespace canvas
|
|||||||
Element( const CanvasWeakPtr& canvas,
|
Element( const CanvasWeakPtr& canvas,
|
||||||
const SGPropertyNode_ptr& node,
|
const SGPropertyNode_ptr& node,
|
||||||
const Style& parent_style,
|
const Style& parent_style,
|
||||||
ElementWeakPtr parent );
|
Element* parent );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns false on first call and true on any successive call. Use to
|
* Returns false on first call and true on any successive call. Use to
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ namespace canvas
|
|||||||
Group::Group( const CanvasWeakPtr& canvas,
|
Group::Group( const CanvasWeakPtr& canvas,
|
||||||
const SGPropertyNode_ptr& node,
|
const SGPropertyNode_ptr& node,
|
||||||
const Style& parent_style,
|
const Style& parent_style,
|
||||||
ElementWeakPtr parent ):
|
Element* parent ):
|
||||||
Element(canvas, node, parent_style, parent)
|
Element(canvas, node, parent_style, parent)
|
||||||
{
|
{
|
||||||
staticInit();
|
staticInit();
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ namespace canvas
|
|||||||
Group( const CanvasWeakPtr& canvas,
|
Group( const CanvasWeakPtr& canvas,
|
||||||
const SGPropertyNode_ptr& node,
|
const SGPropertyNode_ptr& node,
|
||||||
const Style& parent_style = Style(),
|
const Style& parent_style = Style(),
|
||||||
ElementWeakPtr parent = 0 );
|
Element* parent = 0 );
|
||||||
virtual ~Group();
|
virtual ~Group();
|
||||||
|
|
||||||
ElementPtr createChild( const std::string& type,
|
ElementPtr createChild( const std::string& type,
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ namespace canvas
|
|||||||
Image::Image( const CanvasWeakPtr& canvas,
|
Image::Image( const CanvasWeakPtr& canvas,
|
||||||
const SGPropertyNode_ptr& node,
|
const SGPropertyNode_ptr& node,
|
||||||
const Style& parent_style,
|
const Style& parent_style,
|
||||||
ElementWeakPtr parent ):
|
Element* parent ):
|
||||||
Element(canvas, node, parent_style, parent),
|
Element(canvas, node, parent_style, parent),
|
||||||
_texture(new osg::Texture2D),
|
_texture(new osg::Texture2D),
|
||||||
_node_src_rect( node->getNode("source", 0, true) ),
|
_node_src_rect( node->getNode("source", 0, true) ),
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ namespace canvas
|
|||||||
Image( const CanvasWeakPtr& canvas,
|
Image( const CanvasWeakPtr& canvas,
|
||||||
const SGPropertyNode_ptr& node,
|
const SGPropertyNode_ptr& node,
|
||||||
const Style& parent_style = Style(),
|
const Style& parent_style = Style(),
|
||||||
ElementWeakPtr parent = 0 );
|
Element* parent = 0 );
|
||||||
virtual ~Image();
|
virtual ~Image();
|
||||||
|
|
||||||
virtual void update(double dt);
|
virtual void update(double dt);
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ namespace canvas
|
|||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
const std::string GEO = "-geo";
|
const std::string GEO = "-geo";
|
||||||
const std::string HDG = "hdg";
|
|
||||||
const std::string Map::TYPE_NAME = "map";
|
const std::string Map::TYPE_NAME = "map";
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@@ -62,7 +61,7 @@ namespace canvas
|
|||||||
Map::Map( const CanvasWeakPtr& canvas,
|
Map::Map( const CanvasWeakPtr& canvas,
|
||||||
const SGPropertyNode_ptr& node,
|
const SGPropertyNode_ptr& node,
|
||||||
const Style& parent_style,
|
const Style& parent_style,
|
||||||
ElementWeakPtr parent ):
|
Element* parent ):
|
||||||
Group(canvas, node, parent_style, parent),
|
Group(canvas, node, parent_style, parent),
|
||||||
// TODO make projection configurable
|
// TODO make projection configurable
|
||||||
_projection(new SansonFlamsteedProjection),
|
_projection(new SansonFlamsteedProjection),
|
||||||
@@ -113,89 +112,39 @@ namespace canvas
|
|||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void Map::childAdded(SGPropertyNode* parent, SGPropertyNode* child)
|
void Map::childAdded(SGPropertyNode* parent, SGPropertyNode* child)
|
||||||
{
|
{
|
||||||
if( boost::ends_with(child->getNameString(), GEO) )
|
if( !boost::ends_with(child->getNameString(), GEO) )
|
||||||
_geo_nodes[child].reset(new GeoNodePair());
|
|
||||||
else if( parent != _node && child->getNameString() == HDG )
|
|
||||||
_hdg_nodes.insert(child);
|
|
||||||
else
|
|
||||||
return Element::childAdded(parent, child);
|
return Element::childAdded(parent, child);
|
||||||
|
|
||||||
|
_geo_nodes[child].reset(new GeoNodePair());
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void Map::childRemoved(SGPropertyNode* parent, SGPropertyNode* child)
|
void Map::childRemoved(SGPropertyNode* parent, SGPropertyNode* child)
|
||||||
{
|
{
|
||||||
if( boost::ends_with(child->getNameString(), GEO) )
|
if( !boost::ends_with(child->getNameString(), GEO) )
|
||||||
|
return Element::childRemoved(parent, child);
|
||||||
|
|
||||||
// TODO remove from other node
|
// TODO remove from other node
|
||||||
_geo_nodes.erase(child);
|
_geo_nodes.erase(child);
|
||||||
else if( parent != _node && child->getName() == HDG )
|
|
||||||
{
|
|
||||||
_hdg_nodes.erase(child);
|
|
||||||
|
|
||||||
// Remove rotation matrix (tf[0]) and return to element always being
|
|
||||||
// oriented upwards (or any orientation inside other matrices).
|
|
||||||
child->getParent()->removeChild("tf", 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return Element::childRemoved(parent, child);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void Map::valueChanged(SGPropertyNode* child)
|
void Map::valueChanged(SGPropertyNode * child)
|
||||||
{
|
|
||||||
if( child->getParent() != _node )
|
|
||||||
{
|
{
|
||||||
const std::string& name = child->getNameString();
|
const std::string& name = child->getNameString();
|
||||||
|
|
||||||
if( boost::ends_with(name, GEO) )
|
if( !boost::ends_with(name, GEO) )
|
||||||
return geoNodeChanged(child);
|
|
||||||
else if( name == HDG )
|
|
||||||
return hdgNodeChanged(child);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Group::valueChanged(child);
|
return Group::valueChanged(child);
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
void Map::childChanged(SGPropertyNode* child)
|
|
||||||
{
|
|
||||||
if( child->getParent() != _node )
|
|
||||||
return Group::childChanged(child);
|
|
||||||
|
|
||||||
if( child->getNameString() == "ref-lat"
|
|
||||||
|| child->getNameString() == "ref-lon" )
|
|
||||||
_projection->setWorldPosition( _node->getDoubleValue("ref-lat"),
|
|
||||||
_node->getDoubleValue("ref-lon") );
|
|
||||||
else if( child->getNameString() == HDG )
|
|
||||||
{
|
|
||||||
_projection->setOrientation(child->getFloatValue());
|
|
||||||
for( NodeSet::iterator it = _hdg_nodes.begin();
|
|
||||||
it != _hdg_nodes.end();
|
|
||||||
++it )
|
|
||||||
hdgNodeChanged(*it);
|
|
||||||
}
|
|
||||||
else if( child->getNameString() == "range" )
|
|
||||||
_projection->setRange(child->getDoubleValue());
|
|
||||||
else if( child->getNameString() == "screen-range" )
|
|
||||||
_projection->setScreenRange(child->getDoubleValue());
|
|
||||||
else
|
|
||||||
return Group::childChanged(child);
|
|
||||||
|
|
||||||
_projection_dirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
void Map::geoNodeChanged(SGPropertyNode* child)
|
|
||||||
{
|
|
||||||
GeoNodes::iterator it_geo_node = _geo_nodes.find(child);
|
GeoNodes::iterator it_geo_node = _geo_nodes.find(child);
|
||||||
if( it_geo_node == _geo_nodes.end() )
|
if( it_geo_node == _geo_nodes.end() )
|
||||||
LOG_GEO_RET("GeoNode not found!")
|
LOG_GEO_RET("geo node not found!")
|
||||||
GeoNodePair* geo_node = it_geo_node->second.get();
|
GeoNodePair* geo_node = it_geo_node->second.get();
|
||||||
|
|
||||||
geo_node->setDirty();
|
geo_node->setDirty();
|
||||||
|
|
||||||
if( !(geo_node->getStatus() & GeoNodePair::INCOMPLETE) )
|
if( geo_node->getStatus() & GeoNodePair::INCOMPLETE )
|
||||||
return;
|
{
|
||||||
|
|
||||||
// Detect lat, lon tuples...
|
// Detect lat, lon tuples...
|
||||||
GeoCoord coord = parseGeoCoord(child->getStringValue());
|
GeoCoord coord = parseGeoCoord(child->getStringValue());
|
||||||
int index_other = -1;
|
int index_other = -1;
|
||||||
@@ -214,7 +163,6 @@ namespace canvas
|
|||||||
LOG_GEO_RET("Invalid geo coord")
|
LOG_GEO_RET("Invalid geo coord")
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& name = child->getNameString();
|
|
||||||
SGPropertyNode *other = child->getParent()->getChild(name, index_other);
|
SGPropertyNode *other = child->getParent()->getChild(name, index_other);
|
||||||
if( !other )
|
if( !other )
|
||||||
return;
|
return;
|
||||||
@@ -241,14 +189,28 @@ namespace canvas
|
|||||||
// Set name for resulting screen coordinate nodes
|
// Set name for resulting screen coordinate nodes
|
||||||
geo_node->setTargetName( name.substr(0, name.length() - GEO.length()) );
|
geo_node->setTargetName( name.substr(0, name.length() - GEO.length()) );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void Map::hdgNodeChanged(SGPropertyNode* child)
|
void Map::childChanged(SGPropertyNode * child)
|
||||||
{
|
{
|
||||||
child->getParent()->setFloatValue(
|
if( child->getParent() != _node )
|
||||||
"tf[0]/rot",
|
return Group::childChanged(child);
|
||||||
SGMiscf::deg2rad(child->getFloatValue() - _projection->orientation())
|
|
||||||
);
|
if( child->getNameString() == "ref-lat"
|
||||||
|
|| child->getNameString() == "ref-lon" )
|
||||||
|
_projection->setWorldPosition( _node->getDoubleValue("ref-lat"),
|
||||||
|
_node->getDoubleValue("ref-lon") );
|
||||||
|
else if( child->getNameString() == "hdg" )
|
||||||
|
_projection->setOrientation(child->getFloatValue());
|
||||||
|
else if( child->getNameString() == "range" )
|
||||||
|
_projection->setRange(child->getDoubleValue());
|
||||||
|
else if( child->getNameString() == "screen-range" )
|
||||||
|
_projection->setScreenRange(child->getDoubleValue());
|
||||||
|
else
|
||||||
|
return Group::childChanged(child);
|
||||||
|
|
||||||
|
_projection_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <boost/unordered_map.hpp>
|
#include <boost/unordered_map.hpp>
|
||||||
#include <boost/unordered_set.hpp>
|
|
||||||
|
|
||||||
namespace simgear
|
namespace simgear
|
||||||
{
|
{
|
||||||
@@ -42,7 +41,7 @@ namespace canvas
|
|||||||
Map( const CanvasWeakPtr& canvas,
|
Map( const CanvasWeakPtr& canvas,
|
||||||
const SGPropertyNode_ptr& node,
|
const SGPropertyNode_ptr& node,
|
||||||
const Style& parent_style,
|
const Style& parent_style,
|
||||||
ElementWeakPtr parent = 0 );
|
Element* parent = 0 );
|
||||||
virtual ~Map();
|
virtual ~Map();
|
||||||
|
|
||||||
virtual void update(double dt);
|
virtual void update(double dt);
|
||||||
@@ -60,18 +59,14 @@ namespace canvas
|
|||||||
typedef boost::unordered_map< SGPropertyNode*,
|
typedef boost::unordered_map< SGPropertyNode*,
|
||||||
boost::shared_ptr<GeoNodePair>
|
boost::shared_ptr<GeoNodePair>
|
||||||
> GeoNodes;
|
> GeoNodes;
|
||||||
typedef boost::unordered_set<SGPropertyNode*> NodeSet;
|
|
||||||
|
|
||||||
GeoNodes _geo_nodes;
|
GeoNodes _geo_nodes;
|
||||||
NodeSet _hdg_nodes;
|
|
||||||
boost::shared_ptr<HorizontalProjection> _projection;
|
boost::shared_ptr<HorizontalProjection> _projection;
|
||||||
bool _projection_dirty;
|
bool _projection_dirty;
|
||||||
|
|
||||||
struct GeoCoord
|
struct GeoCoord
|
||||||
{
|
{
|
||||||
GeoCoord():
|
GeoCoord():
|
||||||
type(INVALID),
|
type(INVALID)
|
||||||
value(0)
|
|
||||||
{}
|
{}
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
@@ -82,9 +77,6 @@ namespace canvas
|
|||||||
double value;
|
double value;
|
||||||
};
|
};
|
||||||
|
|
||||||
void geoNodeChanged(SGPropertyNode * child);
|
|
||||||
void hdgNodeChanged(SGPropertyNode * child);
|
|
||||||
|
|
||||||
GeoCoord parseGeoCoord(const std::string& val) const;
|
GeoCoord parseGeoCoord(const std::string& val) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -531,7 +531,7 @@ namespace canvas
|
|||||||
Path::Path( const CanvasWeakPtr& canvas,
|
Path::Path( const CanvasWeakPtr& canvas,
|
||||||
const SGPropertyNode_ptr& node,
|
const SGPropertyNode_ptr& node,
|
||||||
const Style& parent_style,
|
const Style& parent_style,
|
||||||
ElementWeakPtr parent ):
|
Element* parent ):
|
||||||
Element(canvas, node, parent_style, parent),
|
Element(canvas, node, parent_style, parent),
|
||||||
_path( new PathDrawable(this) )
|
_path( new PathDrawable(this) )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ namespace canvas
|
|||||||
Path( const CanvasWeakPtr& canvas,
|
Path( const CanvasWeakPtr& canvas,
|
||||||
const SGPropertyNode_ptr& node,
|
const SGPropertyNode_ptr& node,
|
||||||
const Style& parent_style,
|
const Style& parent_style,
|
||||||
ElementWeakPtr parent = 0 );
|
Element* parent = 0 );
|
||||||
virtual ~Path();
|
virtual ~Path();
|
||||||
|
|
||||||
virtual void update(double dt);
|
virtual void update(double dt);
|
||||||
|
|||||||
@@ -159,12 +159,8 @@ namespace canvas
|
|||||||
|
|
||||||
if( empty() )
|
if( empty() )
|
||||||
return pos;
|
return pos;
|
||||||
#if OSG_VERSION_LESS_THAN(3,3,5)
|
|
||||||
GlyphQuads::Coords2 const& coords = _quads->_coords;
|
GlyphQuads::Coords2 const& coords = _quads->_coords;
|
||||||
#else
|
|
||||||
GlyphQuads::Coords2 refCoords = _quads->_coords;
|
|
||||||
GlyphQuads::Coords2::element_type &coords = *refCoords.get();
|
|
||||||
#endif
|
|
||||||
size_t global_i = _begin + i;
|
size_t global_i = _begin + i;
|
||||||
|
|
||||||
if( global_i == _begin )
|
if( global_i == _begin )
|
||||||
@@ -198,12 +194,7 @@ namespace canvas
|
|||||||
return cursorPos(0);
|
return cursorPos(0);
|
||||||
|
|
||||||
GlyphQuads::Glyphs const& glyphs = _quads->_glyphs;
|
GlyphQuads::Glyphs const& glyphs = _quads->_glyphs;
|
||||||
#if OSG_VERSION_LESS_THAN(3,3,5)
|
|
||||||
GlyphQuads::Coords2 const& coords = _quads->_coords;
|
GlyphQuads::Coords2 const& coords = _quads->_coords;
|
||||||
#else
|
|
||||||
GlyphQuads::Coords2 refCoords = _quads->_coords;
|
|
||||||
GlyphQuads::Coords2::element_type &coords = *refCoords.get();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
float const HIT_FRACTION = 0.6;
|
float const HIT_FRACTION = 0.6;
|
||||||
float const character_width = _text->getCharacterHeight()
|
float const character_width = _text->getCharacterHeight()
|
||||||
@@ -636,13 +627,7 @@ namespace canvas
|
|||||||
|
|
||||||
const GlyphQuads& quads = _textureGlyphQuadMap.begin()->second;
|
const GlyphQuads& quads = _textureGlyphQuadMap.begin()->second;
|
||||||
const GlyphQuads::Glyphs& glyphs = quads._glyphs;
|
const GlyphQuads::Glyphs& glyphs = quads._glyphs;
|
||||||
#if OSG_VERSION_LESS_THAN(3,3,5)
|
const GlyphQuads::Coords2& coords = quads._coords;
|
||||||
GlyphQuads::Coords2 const& coords = quads._coords;
|
|
||||||
#else
|
|
||||||
GlyphQuads::Coords2 refCoords = quads._coords;
|
|
||||||
GlyphQuads::Coords2::element_type &coords = *refCoords.get();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const GlyphQuads::LineNumbers& line_numbers = quads._lineNumbers;
|
const GlyphQuads::LineNumbers& line_numbers = quads._lineNumbers;
|
||||||
|
|
||||||
float wr = _characterHeight / getCharacterAspectRatio();
|
float wr = _characterHeight / getCharacterAspectRatio();
|
||||||
@@ -740,7 +725,7 @@ namespace canvas
|
|||||||
Text::Text( const CanvasWeakPtr& canvas,
|
Text::Text( const CanvasWeakPtr& canvas,
|
||||||
const SGPropertyNode_ptr& node,
|
const SGPropertyNode_ptr& node,
|
||||||
const Style& parent_style,
|
const Style& parent_style,
|
||||||
ElementWeakPtr parent ):
|
Element* parent ):
|
||||||
Element(canvas, node, parent_style, parent),
|
Element(canvas, node, parent_style, parent),
|
||||||
_text( new Text::TextOSG(this) )
|
_text( new Text::TextOSG(this) )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ namespace canvas
|
|||||||
Text( const CanvasWeakPtr& canvas,
|
Text( const CanvasWeakPtr& canvas,
|
||||||
const SGPropertyNode_ptr& node,
|
const SGPropertyNode_ptr& node,
|
||||||
const Style& parent_style,
|
const Style& parent_style,
|
||||||
ElementWeakPtr parent = 0 );
|
Element* parent = 0 );
|
||||||
~Text();
|
~Text();
|
||||||
|
|
||||||
void setText(const char* text);
|
void setText(const char* text);
|
||||||
|
|||||||
@@ -34,10 +34,7 @@ namespace canvas
|
|||||||
public:
|
public:
|
||||||
struct ScreenPosition
|
struct ScreenPosition
|
||||||
{
|
{
|
||||||
ScreenPosition():
|
ScreenPosition() {}
|
||||||
x(0),
|
|
||||||
y(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
ScreenPosition(double x, double y):
|
ScreenPosition(double x, double y):
|
||||||
x(x),
|
x(x),
|
||||||
@@ -70,11 +67,8 @@ namespace canvas
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
HorizontalProjection():
|
HorizontalProjection():
|
||||||
_ref_lat(0),
|
_cos_rot(1),
|
||||||
_ref_lon(0),
|
_sin_rot(0),
|
||||||
_angle(0),
|
|
||||||
_cos_angle(1),
|
|
||||||
_sin_angle(0),
|
|
||||||
_range(5)
|
_range(5)
|
||||||
{
|
{
|
||||||
setScreenRange(200);
|
setScreenRange(200);
|
||||||
@@ -94,19 +88,9 @@ namespace canvas
|
|||||||
*/
|
*/
|
||||||
void setOrientation(float hdg)
|
void setOrientation(float hdg)
|
||||||
{
|
{
|
||||||
_angle = hdg;
|
|
||||||
|
|
||||||
hdg = SGMiscf::deg2rad(hdg);
|
hdg = SGMiscf::deg2rad(hdg);
|
||||||
_sin_angle = sin(hdg);
|
_sin_rot = sin(hdg);
|
||||||
_cos_angle = cos(hdg);
|
_cos_rot = cos(hdg);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get orientation/heading of the projection (in degree)
|
|
||||||
*/
|
|
||||||
float orientation() const
|
|
||||||
{
|
|
||||||
return _angle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRange(double range)
|
void setRange(double range)
|
||||||
@@ -130,8 +114,8 @@ namespace canvas
|
|||||||
pos.y *= scale;
|
pos.y *= scale;
|
||||||
return ScreenPosition
|
return ScreenPosition
|
||||||
(
|
(
|
||||||
_cos_angle * pos.x - _sin_angle * pos.y,
|
_cos_rot * pos.x - _sin_rot * pos.y,
|
||||||
-_sin_angle * pos.x - _cos_angle * pos.y
|
-_sin_rot * pos.x - _cos_rot * pos.y
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,11 +129,10 @@ namespace canvas
|
|||||||
*/
|
*/
|
||||||
virtual ScreenPosition project(double lat, double lon) const = 0;
|
virtual ScreenPosition project(double lat, double lon) const = 0;
|
||||||
|
|
||||||
double _ref_lat, ///<! Reference latitude (radian)
|
double _ref_lat,
|
||||||
_ref_lon, ///<! Reference latitude (radian)
|
_ref_lon,
|
||||||
_angle, ///<! Map rotation angle (degree)
|
_cos_rot,
|
||||||
_cos_angle,
|
_sin_rot,
|
||||||
_sin_angle,
|
|
||||||
_range;
|
_range;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -190,12 +190,6 @@ inline int (isnan)(double r) { return !(r <= 0 || r >= 0); }
|
|||||||
# define DEPRECATED
|
# define DEPRECATED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__clang__)
|
|
||||||
# define SG_NO_RETURN [[noreturn]]
|
|
||||||
#else
|
|
||||||
# define SG_NO_RETURN
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// No user modifiable definitions beyond here.
|
// No user modifiable definitions beyond here.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -32,8 +32,7 @@ typedef enum {
|
|||||||
SG_SOUND = 0x00200000,
|
SG_SOUND = 0x00200000,
|
||||||
SG_NAVAID = 0x00400000,
|
SG_NAVAID = 0x00400000,
|
||||||
SG_GUI = 0x00800000,
|
SG_GUI = 0x00800000,
|
||||||
SG_TERRASYNC = 0x01000000,
|
SG_UNDEFD = 0x01000000, // For range checking
|
||||||
SG_UNDEFD = 0x02000000, // For range checking
|
|
||||||
|
|
||||||
SG_ALL = 0xFFFFFFFF
|
SG_ALL = 0xFFFFFFFF
|
||||||
} sgDebugClass;
|
} sgDebugClass;
|
||||||
|
|||||||
@@ -71,7 +71,6 @@ const char* debugClassToString(sgDebugClass c)
|
|||||||
case SG_SOUND: return "sound";
|
case SG_SOUND: return "sound";
|
||||||
case SG_NAVAID: return "navaid";
|
case SG_NAVAID: return "navaid";
|
||||||
case SG_GUI: return "gui";
|
case SG_GUI: return "gui";
|
||||||
case SG_TERRASYNC: return "terrasync";
|
|
||||||
default: return "unknown";
|
default: return "unknown";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
* $Id$
|
* $Id$
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include <cmath>
|
#include <math.h>
|
||||||
|
|
||||||
#include "jupiter.hxx"
|
#include "jupiter.hxx"
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
* $Id$
|
* $Id$
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include <cmath>
|
#include <math.h>
|
||||||
|
|
||||||
#include "mars.hxx"
|
#include "mars.hxx"
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
* $Id$
|
* $Id$
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include <cmath>
|
#include <math.h>
|
||||||
|
|
||||||
#include "mercury.hxx"
|
#include "mercury.hxx"
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
#ifdef __BORLANDC__
|
#ifdef __BORLANDC__
|
||||||
# define exception c_exception
|
# define exception c_exception
|
||||||
#endif
|
#endif
|
||||||
#include <cmath>
|
#include <math.h>
|
||||||
|
|
||||||
#include "neptune.hxx"
|
#include "neptune.hxx"
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
* $Id$
|
* $Id$
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include <cmath>
|
#include <math.h>
|
||||||
|
|
||||||
#include "saturn.hxx"
|
#include "saturn.hxx"
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
* $Id$
|
* $Id$
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include <cmath>
|
#include <math.h>
|
||||||
|
|
||||||
#include <simgear/debug/logstream.hxx>
|
#include <simgear/debug/logstream.hxx>
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ public:
|
|||||||
bool load( const SGPath& path );
|
bool load( const SGPath& path );
|
||||||
|
|
||||||
// stars
|
// stars
|
||||||
inline int getNumStars() const { return static_cast<int>(_stars.size()); }
|
inline int getNumStars() const { return _stars.size(); }
|
||||||
inline SGVec3d *getStars() { return &(_stars[0]); }
|
inline SGVec3d *getStars() { return &(_stars[0]); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
* $Id$
|
* $Id$
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include <cmath>
|
#include <math.h>
|
||||||
|
|
||||||
#include "uranus.hxx"
|
#include "uranus.hxx"
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
* $Id$
|
* $Id$
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include <cmath>
|
#include <math.h>
|
||||||
|
|
||||||
#include "venus.hxx"
|
#include "venus.hxx"
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ set(HEADERS
|
|||||||
HTTPFileRequest.hxx
|
HTTPFileRequest.hxx
|
||||||
HTTPMemoryRequest.hxx
|
HTTPMemoryRequest.hxx
|
||||||
HTTPRequest.hxx
|
HTTPRequest.hxx
|
||||||
|
HTTPContentDecode.hxx
|
||||||
DAVMultiStatus.hxx
|
DAVMultiStatus.hxx
|
||||||
SVNRepository.hxx
|
SVNRepository.hxx
|
||||||
SVNDirectory.hxx
|
SVNDirectory.hxx
|
||||||
@@ -40,17 +41,13 @@ set(SOURCES
|
|||||||
HTTPFileRequest.cxx
|
HTTPFileRequest.cxx
|
||||||
HTTPMemoryRequest.cxx
|
HTTPMemoryRequest.cxx
|
||||||
HTTPRequest.cxx
|
HTTPRequest.cxx
|
||||||
|
HTTPContentDecode.cxx
|
||||||
DAVMultiStatus.cxx
|
DAVMultiStatus.cxx
|
||||||
SVNRepository.cxx
|
SVNRepository.cxx
|
||||||
SVNDirectory.cxx
|
SVNDirectory.cxx
|
||||||
SVNReportParser.cxx
|
SVNReportParser.cxx
|
||||||
)
|
)
|
||||||
|
|
||||||
if (NOT ENABLE_CURL)
|
|
||||||
list(APPEND SOURCES HTTPContentDecode.cxx)
|
|
||||||
list(APPEND HEADERS HTTPContentDecode.hxx)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
simgear_component(io io "${SOURCES}" "${HEADERS}")
|
simgear_component(io io "${SOURCES}" "${HEADERS}")
|
||||||
|
|
||||||
if(ENABLE_TESTS)
|
if(ENABLE_TESTS)
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ public:
|
|||||||
{
|
{
|
||||||
if (tagStack.empty()) {
|
if (tagStack.empty()) {
|
||||||
if (strcmp(name, DAV_MULTISTATUS_TAG)) {
|
if (strcmp(name, DAV_MULTISTATUS_TAG)) {
|
||||||
SG_LOG(SG_TERRASYNC, SG_WARN, "root element is not " <<
|
SG_LOG(SG_IO, SG_WARN, "root element is not " <<
|
||||||
DAV_MULTISTATUS_TAG << ", got:" << name);
|
DAV_MULTISTATUS_TAG << ", got:" << name);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@@ -202,7 +202,7 @@ public:
|
|||||||
// not at the root element
|
// not at the root element
|
||||||
if (tagStack.back() == DAV_MULTISTATUS_TAG) {
|
if (tagStack.back() == DAV_MULTISTATUS_TAG) {
|
||||||
if (strcmp(name, DAV_RESPONSE_TAG)) {
|
if (strcmp(name, DAV_RESPONSE_TAG)) {
|
||||||
SG_LOG(SG_TERRASYNC, SG_WARN, "multistatus child is not response: saw:"
|
SG_LOG(SG_IO, SG_WARN, "multistatus child is not response: saw:"
|
||||||
<< name);
|
<< name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -362,7 +362,7 @@ void DAVMultiStatus::parseXML(const char* data, int size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!XML_Parse(_d->xmlParser, data, size, false)) {
|
if (!XML_Parse(_d->xmlParser, data, size, false)) {
|
||||||
SG_LOG(SG_TERRASYNC, SG_WARN, "DAV parse error:" << XML_ErrorString(XML_GetErrorCode(_d->xmlParser))
|
SG_LOG(SG_IO, SG_WARN, "DAV parse error:" << XML_ErrorString(XML_GetErrorCode(_d->xmlParser))
|
||||||
<< " at line:" << XML_GetCurrentLineNumber(_d->xmlParser)
|
<< " at line:" << XML_GetCurrentLineNumber(_d->xmlParser)
|
||||||
<< " column " << XML_GetCurrentColumnNumber(_d->xmlParser));
|
<< " column " << XML_GetCurrentColumnNumber(_d->xmlParser));
|
||||||
|
|
||||||
@@ -376,7 +376,7 @@ void DAVMultiStatus::finishParse()
|
|||||||
{
|
{
|
||||||
if (_d->parserInited) {
|
if (_d->parserInited) {
|
||||||
if (!XML_Parse(_d->xmlParser, NULL, 0, true)) {
|
if (!XML_Parse(_d->xmlParser, NULL, 0, true)) {
|
||||||
SG_LOG(SG_TERRASYNC, SG_WARN, "DAV parse error:" << XML_ErrorString(XML_GetErrorCode(_d->xmlParser))
|
SG_LOG(SG_IO, SG_WARN, "DAV parse error:" << XML_ErrorString(XML_GetErrorCode(_d->xmlParser))
|
||||||
<< " at line:" << XML_GetCurrentLineNumber(_d->xmlParser)
|
<< " at line:" << XML_GetCurrentLineNumber(_d->xmlParser)
|
||||||
<< " column " << XML_GetCurrentColumnNumber(_d->xmlParser));
|
<< " column " << XML_GetCurrentColumnNumber(_d->xmlParser));
|
||||||
_d->valid = false;
|
_d->valid = false;
|
||||||
|
|||||||
+29
-275
@@ -21,7 +21,6 @@
|
|||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
#include "HTTPClient.hxx"
|
#include "HTTPClient.hxx"
|
||||||
#include "HTTPFileRequest.hxx"
|
#include "HTTPFileRequest.hxx"
|
||||||
|
|
||||||
@@ -36,16 +35,8 @@
|
|||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
#include <boost/algorithm/string/case_conv.hpp>
|
#include <boost/algorithm/string/case_conv.hpp>
|
||||||
|
|
||||||
#include <simgear/simgear_config.h>
|
|
||||||
|
|
||||||
#if defined(ENABLE_CURL)
|
|
||||||
#include <curl/multi.h>
|
|
||||||
#else
|
|
||||||
#include <simgear/io/HTTPContentDecode.hxx>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <simgear/io/sg_netChat.hxx>
|
#include <simgear/io/sg_netChat.hxx>
|
||||||
|
#include <simgear/io/HTTPContentDecode.hxx>
|
||||||
#include <simgear/misc/strutils.hxx>
|
#include <simgear/misc/strutils.hxx>
|
||||||
#include <simgear/compiler.h>
|
#include <simgear/compiler.h>
|
||||||
#include <simgear/debug/logstream.hxx>
|
#include <simgear/debug/logstream.hxx>
|
||||||
@@ -77,24 +68,17 @@ typedef std::list<Request_ptr> RequestList;
|
|||||||
class Client::ClientPrivate
|
class Client::ClientPrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
#if defined(ENABLE_CURL)
|
|
||||||
CURLM* curlMulti;
|
|
||||||
bool haveActiveRequests;
|
|
||||||
#else
|
|
||||||
NetChannelPoller poller;
|
|
||||||
// connections by host (potentially more than one)
|
|
||||||
ConnectionDict connections;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::string userAgent;
|
std::string userAgent;
|
||||||
std::string proxy;
|
std::string proxy;
|
||||||
int proxyPort;
|
int proxyPort;
|
||||||
std::string proxyAuth;
|
std::string proxyAuth;
|
||||||
|
NetChannelPoller poller;
|
||||||
unsigned int maxConnections;
|
unsigned int maxConnections;
|
||||||
|
|
||||||
RequestList pendingRequests;
|
RequestList pendingRequests;
|
||||||
|
|
||||||
|
// connections by host (potentially more than one)
|
||||||
|
ConnectionDict connections;
|
||||||
|
|
||||||
SGTimeStamp timeTransferSample;
|
SGTimeStamp timeTransferSample;
|
||||||
unsigned int bytesTransferred;
|
unsigned int bytesTransferred;
|
||||||
@@ -102,15 +86,13 @@ public:
|
|||||||
uint64_t totalBytesDownloaded;
|
uint64_t totalBytesDownloaded;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if !defined(ENABLE_CURL)
|
|
||||||
class Connection : public NetChat
|
class Connection : public NetChat
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Connection(Client* pr, const std::string& conId) :
|
Connection(Client* pr) :
|
||||||
client(pr),
|
client(pr),
|
||||||
state(STATE_CLOSED),
|
state(STATE_CLOSED),
|
||||||
port(DEFAULT_HTTP_PORT),
|
port(DEFAULT_HTTP_PORT)
|
||||||
connectionId(conId)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,11 +123,6 @@ public:
|
|||||||
virtual void handleError(int error)
|
virtual void handleError(int error)
|
||||||
{
|
{
|
||||||
const char* errStr = strerror(error);
|
const char* errStr = strerror(error);
|
||||||
SG_LOG(SG_IO, SG_WARN, "HTTP Connection handleError:" << error << " ("
|
|
||||||
<< errStr << ")");
|
|
||||||
|
|
||||||
debugDumpRequests();
|
|
||||||
|
|
||||||
if (!activeRequest)
|
if (!activeRequest)
|
||||||
{
|
{
|
||||||
// connection level failure, eg name lookup or routing
|
// connection level failure, eg name lookup or routing
|
||||||
@@ -174,11 +151,6 @@ public:
|
|||||||
state = STATE_SOCKET_ERROR;
|
state = STATE_SOCKET_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleTimeout()
|
|
||||||
{
|
|
||||||
handleError(ETIMEDOUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void handleClose()
|
virtual void handleClose()
|
||||||
{
|
{
|
||||||
NetChat::handleClose();
|
NetChat::handleClose();
|
||||||
@@ -191,13 +163,6 @@ public:
|
|||||||
state = STATE_CLOSED;
|
state = STATE_CLOSED;
|
||||||
responseComplete();
|
responseComplete();
|
||||||
} else {
|
} else {
|
||||||
if (state == STATE_WAITING_FOR_RESPONSE) {
|
|
||||||
assert(!sentRequests.empty());
|
|
||||||
sentRequests.front()->setFailure(500, "server closed connection unexpectedly");
|
|
||||||
// no active request, but don't restore the front sent one
|
|
||||||
sentRequests.erase(sentRequests.begin());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (activeRequest) {
|
if (activeRequest) {
|
||||||
activeRequest->setFailure(500, "server closed connection");
|
activeRequest->setFailure(500, "server closed connection");
|
||||||
// remove the failed request from sentRequests, so it does
|
// remove the failed request from sentRequests, so it does
|
||||||
@@ -225,6 +190,19 @@ public:
|
|||||||
sentRequests.clear();
|
sentRequests.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handleTimeout()
|
||||||
|
{
|
||||||
|
NetChat::handleError(ETIMEDOUT);
|
||||||
|
if (activeRequest) {
|
||||||
|
SG_LOG(SG_IO, SG_DEBUG, "HTTP socket timeout");
|
||||||
|
activeRequest->setFailure(ETIMEDOUT, "socket timeout");
|
||||||
|
activeRequest = NULL;
|
||||||
|
_contentDecoder.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
state = STATE_SOCKET_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
void queueRequest(const Request_ptr& r)
|
void queueRequest(const Request_ptr& r)
|
||||||
{
|
{
|
||||||
queuedRequests.push_back(r);
|
queuedRequests.push_back(r);
|
||||||
@@ -241,7 +219,6 @@ public:
|
|||||||
activeRequest->responseStart(buffer);
|
activeRequest->responseStart(buffer);
|
||||||
} catch (sg_exception& e) {
|
} catch (sg_exception& e) {
|
||||||
handleError(EIO);
|
handleError(EIO);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state = STATE_GETTING_HEADERS;
|
state = STATE_GETTING_HEADERS;
|
||||||
@@ -361,7 +338,9 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SG_LOG(SG_IO, SG_DEBUG, "con:" << connectionId << " did start request:" << r->url());
|
// SG_LOG(SG_IO, SG_INFO, "did start request:" << r->url() <<
|
||||||
|
// "\n\t @ " << reinterpret_cast<void*>(r.ptr()) <<
|
||||||
|
// "\n\t on connection " << this);
|
||||||
// successfully sent, remove from queue, and maybe send the next
|
// successfully sent, remove from queue, and maybe send the next
|
||||||
queuedRequests.pop_front();
|
queuedRequests.pop_front();
|
||||||
sentRequests.push_back(r);
|
sentRequests.push_back(r);
|
||||||
@@ -426,23 +405,21 @@ public:
|
|||||||
|
|
||||||
bool hasIdleTimeout() const
|
bool hasIdleTimeout() const
|
||||||
{
|
{
|
||||||
if ((state != STATE_IDLE) && (state != STATE_CLOSED)) {
|
if (state != STATE_IDLE) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(sentRequests.empty());
|
assert(sentRequests.empty());
|
||||||
bool isTimedOut = (idleTime.elapsedMSec() > (1000 * 10)); // 10 seconds
|
return idleTime.elapsedMSec() > 1000 * 10; // ten seconds
|
||||||
return isTimedOut;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasErrorTimeout() const
|
bool hasErrorTimeout() const
|
||||||
{
|
{
|
||||||
if ((state == STATE_IDLE) || (state == STATE_CLOSED)) {
|
if (state == STATE_IDLE) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isTimedOut = (idleTime.elapsedMSec() > (1000 * 30)); // 30 seconds
|
return idleTime.elapsedMSec() > (1000 * 30); // 30 seconds
|
||||||
return isTimedOut;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasError() const
|
bool hasError() const
|
||||||
@@ -459,37 +436,17 @@ public:
|
|||||||
{
|
{
|
||||||
return !queuedRequests.empty() || !sentRequests.empty();
|
return !queuedRequests.empty() || !sentRequests.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void debugDumpRequests() const
|
|
||||||
{
|
|
||||||
SG_LOG(SG_IO, SG_DEBUG, "requests for:" << host << ":" << port << " (conId=" << connectionId
|
|
||||||
<< "; state=" << state << ")");
|
|
||||||
if (activeRequest) {
|
|
||||||
SG_LOG(SG_IO, SG_DEBUG, "\tactive:" << activeRequest->url());
|
|
||||||
} else {
|
|
||||||
SG_LOG(SG_IO, SG_DEBUG, "\tNo active request");
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_FOREACH(Request_ptr req, sentRequests) {
|
|
||||||
SG_LOG(SG_IO, SG_DEBUG, "\tsent:" << req->url());
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_FOREACH(Request_ptr req, queuedRequests) {
|
|
||||||
SG_LOG(SG_IO, SG_DEBUG, "\tqueued:" << req->url());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
bool connectToHost()
|
bool connectToHost()
|
||||||
{
|
{
|
||||||
SG_LOG(SG_IO, SG_DEBUG, "HTTP connecting to " << host << ":" << port);
|
SG_LOG(SG_IO, SG_DEBUG, "HTTP connecting to " << host << ":" << port);
|
||||||
|
|
||||||
if (!open()) {
|
if (!open()) {
|
||||||
SG_LOG(SG_IO, SG_WARN, "HTTP::Connection: connectToHost: open() failed");
|
SG_LOG(SG_ALL, SG_WARN, "HTTP::Connection: connectToHost: open() failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connect(host.c_str(), port) != 0) {
|
if (connect(host.c_str(), port) != 0) {
|
||||||
SG_LOG(SG_IO, SG_WARN, "HTTP::Connection: connectToHost: connect() failed");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -630,6 +587,7 @@ private:
|
|||||||
|
|
||||||
// notify request after we change state, so this connection is idle
|
// notify request after we change state, so this connection is idle
|
||||||
// if completion triggers other requests (which is likely)
|
// if completion triggers other requests (which is likely)
|
||||||
|
// SG_LOG(SG_IO, SG_INFO, "*** responseComplete:" << activeRequest->url());
|
||||||
completedRequest->responseComplete();
|
completedRequest->responseComplete();
|
||||||
client->requestFinished(this);
|
client->requestFinished(this);
|
||||||
|
|
||||||
@@ -663,9 +621,7 @@ private:
|
|||||||
RequestList sentRequests;
|
RequestList sentRequests;
|
||||||
|
|
||||||
ContentDecoder _contentDecoder;
|
ContentDecoder _contentDecoder;
|
||||||
std::string connectionId;
|
|
||||||
};
|
};
|
||||||
#endif // of !ENABLE_CURL
|
|
||||||
|
|
||||||
Client::Client() :
|
Client::Client() :
|
||||||
d(new ClientPrivate)
|
d(new ClientPrivate)
|
||||||
@@ -678,22 +634,10 @@ Client::Client() :
|
|||||||
d->totalBytesDownloaded = 0;
|
d->totalBytesDownloaded = 0;
|
||||||
|
|
||||||
setUserAgent("SimGear-" SG_STRINGIZE(SIMGEAR_VERSION));
|
setUserAgent("SimGear-" SG_STRINGIZE(SIMGEAR_VERSION));
|
||||||
#if defined(ENABLE_CURL)
|
|
||||||
static bool didInitCurlGlobal = false;
|
|
||||||
if (!didInitCurlGlobal) {
|
|
||||||
curl_global_init(CURL_GLOBAL_ALL);
|
|
||||||
didInitCurlGlobal = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
d->curlMulti = curl_multi_init();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Client::~Client()
|
Client::~Client()
|
||||||
{
|
{
|
||||||
#if defined(ENABLE_CURL)
|
|
||||||
curl_multi_cleanup(d->curlMulti);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::setMaxConnections(unsigned int maxCon)
|
void Client::setMaxConnections(unsigned int maxCon)
|
||||||
@@ -703,47 +647,10 @@ void Client::setMaxConnections(unsigned int maxCon)
|
|||||||
}
|
}
|
||||||
|
|
||||||
d->maxConnections = maxCon;
|
d->maxConnections = maxCon;
|
||||||
#if defined(ENABLE_CURL)
|
|
||||||
curl_multi_setopt(d->curlMulti, CURLMOPT_MAXCONNECTS, (long) maxCon);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::update(int waitTimeout)
|
void Client::update(int waitTimeout)
|
||||||
{
|
{
|
||||||
#if defined(ENABLE_CURL)
|
|
||||||
int remainingActive, messagesInQueue;
|
|
||||||
curl_multi_perform(d->curlMulti, &remainingActive);
|
|
||||||
d->haveActiveRequests = (remainingActive > 0);
|
|
||||||
|
|
||||||
CURLMsg* msg;
|
|
||||||
while ((msg = curl_multi_info_read(d->curlMulti, &messagesInQueue))) {
|
|
||||||
if (msg->msg == CURLMSG_DONE) {
|
|
||||||
Request* req;
|
|
||||||
CURL *e = msg->easy_handle;
|
|
||||||
curl_easy_getinfo(e, CURLINFO_PRIVATE, &req);
|
|
||||||
|
|
||||||
long responseCode;
|
|
||||||
curl_easy_getinfo(e, CURLINFO_RESPONSE_CODE, &responseCode);
|
|
||||||
|
|
||||||
if (msg->data.result == 0) {
|
|
||||||
req->responseComplete();
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Result: %d - %s\n",
|
|
||||||
msg->data.result, curl_easy_strerror(msg->data.result));
|
|
||||||
req->setFailure(msg->data.result, curl_easy_strerror(msg->data.result));
|
|
||||||
}
|
|
||||||
|
|
||||||
curl_multi_remove_handle(d->curlMulti, e);
|
|
||||||
|
|
||||||
// balance the reference we take in makeRequest
|
|
||||||
SGReferenced::put(req);
|
|
||||||
curl_easy_cleanup(e);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
SG_LOG(SG_IO, SG_ALERT, "CurlMSG:" << msg->msg);
|
|
||||||
}
|
|
||||||
} // of curl message processing loop
|
|
||||||
#else
|
|
||||||
if (!d->poller.hasChannels() && (waitTimeout > 0)) {
|
if (!d->poller.hasChannels() && (waitTimeout > 0)) {
|
||||||
SGTimeStamp::sleepForMSec(waitTimeout);
|
SGTimeStamp::sleepForMSec(waitTimeout);
|
||||||
} else {
|
} else {
|
||||||
@@ -789,7 +696,6 @@ void Client::update(int waitTimeout)
|
|||||||
makeRequest(req);
|
makeRequest(req);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::makeRequest(const Request_ptr& r)
|
void Client::makeRequest(const Request_ptr& r)
|
||||||
@@ -802,82 +708,6 @@ void Client::makeRequest(const Request_ptr& r)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(ENABLE_CURL)
|
|
||||||
CURL* curlRequest = curl_easy_init();
|
|
||||||
curl_easy_setopt(curlRequest, CURLOPT_URL, r->url().c_str());
|
|
||||||
|
|
||||||
// manually increase the ref count of the request
|
|
||||||
SGReferenced::get(r.get());
|
|
||||||
curl_easy_setopt(curlRequest, CURLOPT_PRIVATE, r.get());
|
|
||||||
// disable built-in libCurl progress feedback
|
|
||||||
curl_easy_setopt(curlRequest, CURLOPT_NOPROGRESS, 1);
|
|
||||||
|
|
||||||
curl_easy_setopt(curlRequest, CURLOPT_WRITEFUNCTION, requestWriteCallback);
|
|
||||||
curl_easy_setopt(curlRequest, CURLOPT_WRITEDATA, r.get());
|
|
||||||
curl_easy_setopt(curlRequest, CURLOPT_HEADERFUNCTION, requestHeaderCallback);
|
|
||||||
curl_easy_setopt(curlRequest, CURLOPT_HEADERDATA, r.get());
|
|
||||||
|
|
||||||
curl_easy_setopt(curlRequest, CURLOPT_USERAGENT, d->userAgent.c_str());
|
|
||||||
|
|
||||||
if (!d->proxy.empty()) {
|
|
||||||
curl_easy_setopt(curlRequest, CURLOPT_PROXY, d->proxy.c_str());
|
|
||||||
curl_easy_setopt(curlRequest, CURLOPT_PROXYPORT, d->proxyPort);
|
|
||||||
|
|
||||||
if (!d->proxyAuth.empty()) {
|
|
||||||
curl_easy_setopt(curlRequest, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
|
|
||||||
curl_easy_setopt(curlRequest, CURLOPT_PROXYUSERPWD, d->proxyAuth.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string method = boost::to_lower_copy(r->method());
|
|
||||||
if (method == "get") {
|
|
||||||
curl_easy_setopt(curlRequest, CURLOPT_HTTPGET, 1);
|
|
||||||
} else if (method == "put") {
|
|
||||||
curl_easy_setopt(curlRequest, CURLOPT_PUT, 1);
|
|
||||||
curl_easy_setopt(curlRequest, CURLOPT_UPLOAD, 1);
|
|
||||||
} else if (method == "post") {
|
|
||||||
// see http://curl.haxx.se/libcurl/c/CURLOPT_POST.html
|
|
||||||
curl_easy_setopt(curlRequest, CURLOPT_HTTPPOST, 1);
|
|
||||||
|
|
||||||
std::string q = r->query().substr(1);
|
|
||||||
curl_easy_setopt(curlRequest, CURLOPT_COPYPOSTFIELDS, q.c_str());
|
|
||||||
|
|
||||||
// reset URL to exclude query pieces
|
|
||||||
std::string urlWithoutQuery = r->url();
|
|
||||||
std::string::size_type queryPos = urlWithoutQuery.find('?');
|
|
||||||
urlWithoutQuery.resize(queryPos);
|
|
||||||
curl_easy_setopt(curlRequest, CURLOPT_URL, urlWithoutQuery.c_str());
|
|
||||||
} else {
|
|
||||||
curl_easy_setopt(curlRequest, CURLOPT_CUSTOMREQUEST, r->method().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
struct curl_slist* headerList = NULL;
|
|
||||||
if (r->hasBodyData() && (method != "post")) {
|
|
||||||
curl_easy_setopt(curlRequest, CURLOPT_UPLOAD, 1);
|
|
||||||
curl_easy_setopt(curlRequest, CURLOPT_INFILESIZE, r->bodyLength());
|
|
||||||
curl_easy_setopt(curlRequest, CURLOPT_READFUNCTION, requestReadCallback);
|
|
||||||
curl_easy_setopt(curlRequest, CURLOPT_READDATA, r.get());
|
|
||||||
std::string h = "Content-Type:" + r->bodyType();
|
|
||||||
headerList = curl_slist_append(headerList, h.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
StringMap::const_iterator it;
|
|
||||||
for (it = r->requestHeaders().begin(); it != r->requestHeaders().end(); ++it) {
|
|
||||||
std::string h = it->first + ": " + it->second;
|
|
||||||
headerList = curl_slist_append(headerList, h.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headerList != NULL) {
|
|
||||||
curl_easy_setopt(curlRequest, CURLOPT_HTTPHEADER, headerList);
|
|
||||||
}
|
|
||||||
|
|
||||||
curl_multi_add_handle(d->curlMulti, curlRequest);
|
|
||||||
d->haveActiveRequests = true;
|
|
||||||
|
|
||||||
// FIXME - premature?
|
|
||||||
r->requestStart();
|
|
||||||
|
|
||||||
#else
|
|
||||||
if( r->url().find("http://") != 0 ) {
|
if( r->url().find("http://") != 0 ) {
|
||||||
r->setFailure(EINVAL, "only HTTP protocol is supported");
|
r->setFailure(EINVAL, "only HTTP protocol is supported");
|
||||||
return;
|
return;
|
||||||
@@ -935,7 +765,7 @@ void Client::makeRequest(const Request_ptr& r)
|
|||||||
|
|
||||||
// allocate a new connection object
|
// allocate a new connection object
|
||||||
if (!con) {
|
if (!con) {
|
||||||
con = new Connection(this, connectionId);
|
con = new Connection(this);
|
||||||
con->setServer(host, port);
|
con->setServer(host, port);
|
||||||
d->poller.addChannel(con);
|
d->poller.addChannel(con);
|
||||||
d->connections.insert(d->connections.end(),
|
d->connections.insert(d->connections.end(),
|
||||||
@@ -943,7 +773,6 @@ void Client::makeRequest(const Request_ptr& r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
con->queueRequest(r);
|
con->queueRequest(r);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -999,16 +828,12 @@ void Client::setProxy( const std::string& proxy,
|
|||||||
|
|
||||||
bool Client::hasActiveRequests() const
|
bool Client::hasActiveRequests() const
|
||||||
{
|
{
|
||||||
#if defined(ENABLE_CURL)
|
|
||||||
return d->haveActiveRequests;
|
|
||||||
#else
|
|
||||||
ConnectionDict::const_iterator it = d->connections.begin();
|
ConnectionDict::const_iterator it = d->connections.begin();
|
||||||
for (; it != d->connections.end(); ++it) {
|
for (; it != d->connections.end(); ++it) {
|
||||||
if (it->second->isActive()) return true;
|
if (it->second->isActive()) return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::receivedBytes(unsigned int count)
|
void Client::receivedBytes(unsigned int count)
|
||||||
@@ -1048,77 +873,6 @@ uint64_t Client::totalBytesDownloaded() const
|
|||||||
return d->totalBytesDownloaded;
|
return d->totalBytesDownloaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Client::requestWriteCallback(char *ptr, size_t size, size_t nmemb, void *userdata)
|
|
||||||
{
|
|
||||||
size_t byteSize = size * nmemb;
|
|
||||||
|
|
||||||
Request* req = static_cast<Request*>(userdata);
|
|
||||||
req->processBodyBytes(ptr, byteSize);
|
|
||||||
return byteSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t Client::requestReadCallback(char *ptr, size_t size, size_t nmemb, void *userdata)
|
|
||||||
{
|
|
||||||
size_t maxBytes = size * nmemb;
|
|
||||||
Request* req = static_cast<Request*>(userdata);
|
|
||||||
size_t actualBytes = req->getBodyData(ptr, 0, maxBytes);
|
|
||||||
return actualBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t Client::requestHeaderCallback(char *rawBuffer, size_t size, size_t nitems, void *userdata)
|
|
||||||
{
|
|
||||||
size_t byteSize = size * nitems;
|
|
||||||
Request* req = static_cast<Request*>(userdata);
|
|
||||||
std::string h = strutils::simplify(std::string(rawBuffer, byteSize));
|
|
||||||
|
|
||||||
if (req->readyState() == HTTP::Request::OPENED) {
|
|
||||||
req->responseStart(h);
|
|
||||||
return byteSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (h.empty()) {
|
|
||||||
// got a 100-continue reponse; restart
|
|
||||||
if (req->responseCode() == 100) {
|
|
||||||
req->setReadyState(HTTP::Request::OPENED);
|
|
||||||
return byteSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
req->responseHeadersComplete();
|
|
||||||
return byteSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (req->responseCode() == 100) {
|
|
||||||
return byteSize; // skip headers associated with 100-continue status
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t colonPos = h.find(':');
|
|
||||||
if (colonPos == std::string::npos) {
|
|
||||||
SG_LOG(SG_IO, SG_WARN, "malformed HTTP response header:" << h);
|
|
||||||
return byteSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string key = strutils::simplify(h.substr(0, colonPos));
|
|
||||||
std::string lkey = boost::to_lower_copy(key);
|
|
||||||
std::string value = strutils::strip(h.substr(colonPos + 1));
|
|
||||||
|
|
||||||
req->responseHeader(lkey, value);
|
|
||||||
return byteSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::debugDumpRequests()
|
|
||||||
{
|
|
||||||
#if defined(ENABLE_CURL)
|
|
||||||
|
|
||||||
#else
|
|
||||||
SG_LOG(SG_IO, SG_INFO, "== HTTP connection dump");
|
|
||||||
ConnectionDict::iterator it = d->connections.begin();
|
|
||||||
for (; it != d->connections.end(); ++it) {
|
|
||||||
it->second->debugDumpRequests();
|
|
||||||
}
|
|
||||||
SG_LOG(SG_IO, SG_INFO, "==");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
} // of namespace HTTP
|
} // of namespace HTTP
|
||||||
|
|
||||||
} // of namespace simgear
|
} // of namespace simgear
|
||||||
|
|||||||
@@ -98,14 +98,7 @@ public:
|
|||||||
* monitoring
|
* monitoring
|
||||||
*/
|
*/
|
||||||
uint64_t totalBytesDownloaded() const;
|
uint64_t totalBytesDownloaded() const;
|
||||||
|
|
||||||
void debugDumpRequests();
|
|
||||||
private:
|
private:
|
||||||
// libCurl callbacks
|
|
||||||
static size_t requestWriteCallback(char *ptr, size_t size, size_t nmemb, void *userdata);
|
|
||||||
static size_t requestReadCallback(char *ptr, size_t size, size_t nmemb, void *userdata);
|
|
||||||
static size_t requestHeaderCallback(char *buffer, size_t size, size_t nitems, void *userdata);
|
|
||||||
|
|
||||||
void requestFinished(Connection* con);
|
void requestFinished(Connection* con);
|
||||||
|
|
||||||
void receivedBytes(unsigned int count);
|
void receivedBytes(unsigned int count);
|
||||||
|
|||||||
@@ -133,25 +133,19 @@ void Request::responseStart(const std::string& r)
|
|||||||
const int maxSplit = 2; // HTTP/1.1 nnn reason-string
|
const int maxSplit = 2; // HTTP/1.1 nnn reason-string
|
||||||
string_list parts = strutils::split(r, NULL, maxSplit);
|
string_list parts = strutils::split(r, NULL, maxSplit);
|
||||||
if (parts.size() != 3) {
|
if (parts.size() != 3) {
|
||||||
throw sg_io_exception("bad HTTP response:" + r);
|
throw sg_io_exception("bad HTTP response");
|
||||||
}
|
}
|
||||||
|
|
||||||
_responseVersion = decodeHTTPVersion(parts[0]);
|
_responseVersion = decodeHTTPVersion(parts[0]);
|
||||||
_responseStatus = strutils::to_int(parts[1]);
|
_responseStatus = strutils::to_int(parts[1]);
|
||||||
_responseReason = parts[2];
|
_responseReason = parts[2];
|
||||||
|
|
||||||
setReadyState(STATUS_RECEIVED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void Request::responseHeader(const std::string& key, const std::string& value)
|
void Request::responseHeader(const std::string& key, const std::string& value)
|
||||||
{
|
{
|
||||||
if( key == "connection" ) {
|
if( key == "connection" )
|
||||||
_willClose = (value.find("close") != std::string::npos);
|
_willClose = (value.find("close") != std::string::npos);
|
||||||
} else if (key == "content-length") {
|
|
||||||
int sz = strutils::to_int(value);
|
|
||||||
setResponseLength(sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
_responseHeaders[key] = value;
|
_responseHeaders[key] = value;
|
||||||
}
|
}
|
||||||
@@ -325,7 +319,6 @@ unsigned int Request::responseLength() const
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void Request::setFailure(int code, const std::string& reason)
|
void Request::setFailure(int code, const std::string& reason)
|
||||||
{
|
{
|
||||||
SG_LOG(SG_IO, SG_WARN, "HTTP request: set failure:" << code << " reason " << reason);
|
|
||||||
_responseStatus = code;
|
_responseStatus = code;
|
||||||
_responseReason = reason;
|
_responseReason = reason;
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ public:
|
|||||||
{
|
{
|
||||||
UNSENT = 0,
|
UNSENT = 0,
|
||||||
OPENED,
|
OPENED,
|
||||||
STATUS_RECEIVED,
|
|
||||||
HEADERS_RECEIVED,
|
HEADERS_RECEIVED,
|
||||||
LOADING,
|
LOADING,
|
||||||
DONE,
|
DONE,
|
||||||
|
|||||||
@@ -96,14 +96,14 @@ void SVNDirectory::parseCache()
|
|||||||
LineState lineState = LINESTATE_HREF;
|
LineState lineState = LINESTATE_HREF;
|
||||||
std::ifstream file(p.c_str());
|
std::ifstream file(p.c_str());
|
||||||
if (!file.is_open()) {
|
if (!file.is_open()) {
|
||||||
SG_LOG(SG_TERRASYNC, SG_WARN, "unable to open cache file for reading:" << p);
|
SG_LOG(SG_IO, SG_WARN, "unable to open cache file for reading:" << p);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bool doneSelf = false;
|
bool doneSelf = false;
|
||||||
|
|
||||||
file.getline(href, 1024);
|
file.getline(href, 1024);
|
||||||
if (strcmp(CACHE_VERSION_4_TOKEN, href)) {
|
if (strcmp(CACHE_VERSION_4_TOKEN, href)) {
|
||||||
SG_LOG(SG_TERRASYNC, SG_WARN, "invalid cache file [missing header token]:" << p << " '" << href << "'");
|
SG_LOG(SG_IO, SG_WARN, "invalid cache file [missing header token]:" << p << " '" << href << "'");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,7 +183,7 @@ void SVNDirectory::writeCache()
|
|||||||
void SVNDirectory::setBaseUrl(const string& url)
|
void SVNDirectory::setBaseUrl(const string& url)
|
||||||
{
|
{
|
||||||
if (_parent) {
|
if (_parent) {
|
||||||
SG_LOG(SG_TERRASYNC, SG_ALERT, "setting base URL on non-root directory " << url);
|
SG_LOG(SG_IO, SG_ALERT, "setting base URL on non-root directory " << url);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,6 +239,7 @@ void SVNDirectory::deleteChildByName(const std::string& nm)
|
|||||||
{
|
{
|
||||||
DAVResource* child = dav->childWithName(nm);
|
DAVResource* child = dav->childWithName(nm);
|
||||||
if (!child) {
|
if (!child) {
|
||||||
|
// std::cerr << "ZZZ: deleteChildByName: unknown:" << nm << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,24 +247,17 @@ void SVNDirectory::deleteChildByName(const std::string& nm)
|
|||||||
|
|
||||||
if (child->isCollection()) {
|
if (child->isCollection()) {
|
||||||
Dir d(path);
|
Dir d(path);
|
||||||
bool ok = d.remove(true);
|
d.remove(true);
|
||||||
if (!ok) {
|
|
||||||
SG_LOG(SG_TERRASYNC, SG_ALERT, "SVNDirectory::deleteChildByName: failed to remove dir:"
|
|
||||||
<< nm << " at path:\n\t" << path);
|
|
||||||
}
|
|
||||||
|
|
||||||
DirectoryList::iterator it = findChildDir(nm);
|
DirectoryList::iterator it = findChildDir(nm);
|
||||||
if (it != _children.end()) {
|
if (it != _children.end()) {
|
||||||
SVNDirectory* c = *it;
|
SVNDirectory* c = *it;
|
||||||
|
// std::cout << "YYY: deleting SVNDirectory for:" << nm << std::endl;
|
||||||
delete c;
|
delete c;
|
||||||
_children.erase(it);
|
_children.erase(it);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bool ok = path.remove();
|
path.remove();
|
||||||
if (!ok) {
|
|
||||||
SG_LOG(SG_TERRASYNC, SG_ALERT, "SVNDirectory::deleteChildByName: failed to remove path:" << nm
|
|
||||||
<< " at path:\n\t" << path);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dav->removeChild(child);
|
dav->removeChild(child);
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ public:
|
|||||||
|
|
||||||
void updateFailed(HTTP::Request* req, SVNRepository::ResultCode err)
|
void updateFailed(HTTP::Request* req, SVNRepository::ResultCode err)
|
||||||
{
|
{
|
||||||
SG_LOG(SG_TERRASYNC, SG_WARN, "SVN: failed to update from:" << req->url()
|
SG_LOG(SG_IO, SG_WARN, "SVN: failed to update from:" << req->url()
|
||||||
<< "\n(repository:" << p->baseUrl() << ")");
|
<< "\n(repository:" << p->baseUrl() << ")");
|
||||||
isUpdating = false;
|
isUpdating = false;
|
||||||
status = err;
|
status = err;
|
||||||
@@ -120,7 +120,6 @@ namespace { // anonmouse
|
|||||||
Request(repo->baseUrl, "PROPFIND"),
|
Request(repo->baseUrl, "PROPFIND"),
|
||||||
_repo(repo)
|
_repo(repo)
|
||||||
{
|
{
|
||||||
assert(repo);
|
|
||||||
requestHeader("Depth") = "0";
|
requestHeader("Depth") = "0";
|
||||||
setBodyData( PROPFIND_REQUEST_BODY,
|
setBodyData( PROPFIND_REQUEST_BODY,
|
||||||
"application/xml; charset=\"utf-8\"" );
|
"application/xml; charset=\"utf-8\"" );
|
||||||
@@ -134,13 +133,11 @@ namespace { // anonmouse
|
|||||||
} else if (responseCode() == 404) {
|
} else if (responseCode() == 404) {
|
||||||
_repo->propFindFailed(this, SVNRepository::SVN_ERROR_NOT_FOUND);
|
_repo->propFindFailed(this, SVNRepository::SVN_ERROR_NOT_FOUND);
|
||||||
} else {
|
} else {
|
||||||
SG_LOG(SG_TERRASYNC, SG_WARN, "request for:" << url() <<
|
SG_LOG(SG_IO, SG_WARN, "request for:" << url() <<
|
||||||
" return code " << responseCode());
|
" return code " << responseCode());
|
||||||
_repo->propFindFailed(this, SVNRepository::SVN_ERROR_SOCKET);
|
_repo->propFindFailed(this, SVNRepository::SVN_ERROR_SOCKET);
|
||||||
_repo = NULL;
|
_repo = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Request::responseHeadersComplete();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void onDone()
|
virtual void onDone()
|
||||||
@@ -231,7 +228,7 @@ protected:
|
|||||||
_repo->updateFailed(this, SVNRepository::SVN_ERROR_NOT_FOUND);
|
_repo->updateFailed(this, SVNRepository::SVN_ERROR_NOT_FOUND);
|
||||||
_failed = true;
|
_failed = true;
|
||||||
} else {
|
} else {
|
||||||
SG_LOG(SG_TERRASYNC, SG_WARN, "SVN: request for:" << url() <<
|
SG_LOG(SG_IO, SG_WARN, "SVN: request for:" << url() <<
|
||||||
" got HTTP status " << responseCode());
|
" got HTTP status " << responseCode());
|
||||||
_repo->updateFailed(this, SVNRepository::SVN_ERROR_HTTP);
|
_repo->updateFailed(this, SVNRepository::SVN_ERROR_HTTP);
|
||||||
_failed = true;
|
_failed = true;
|
||||||
@@ -331,7 +328,7 @@ void SVNRepository::update()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_d->targetRevision == rootDir()->cachedRevision()) {
|
if (_d->targetRevision == rootDir()->cachedRevision()) {
|
||||||
SG_LOG(SG_TERRASYNC, SG_DEBUG, baseUrl() << " in sync at version " << _d->targetRevision);
|
SG_LOG(SG_IO, SG_DEBUG, baseUrl() << " in sync at version " << _d->targetRevision);
|
||||||
_d->isUpdating = false;
|
_d->isUpdating = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -375,7 +372,7 @@ void SVNRepoPrivate::propFindComplete(HTTP::Request* req, DAVCollection* c)
|
|||||||
void SVNRepoPrivate::propFindFailed(HTTP::Request *req, SVNRepository::ResultCode err)
|
void SVNRepoPrivate::propFindFailed(HTTP::Request *req, SVNRepository::ResultCode err)
|
||||||
{
|
{
|
||||||
if (err != SVNRepository::SVN_ERROR_NOT_FOUND) {
|
if (err != SVNRepository::SVN_ERROR_NOT_FOUND) {
|
||||||
SG_LOG(SG_TERRASYNC, SG_WARN, "PropFind failed for:" << req->url());
|
SG_LOG(SG_IO, SG_WARN, "PropFind failed for:" << req->url());
|
||||||
}
|
}
|
||||||
|
|
||||||
isUpdating = false;
|
isUpdating = false;
|
||||||
|
|||||||
@@ -227,13 +227,6 @@ void NetChannel::handleAccept (void) {
|
|||||||
|
|
||||||
void NetChannel::handleError (int error)
|
void NetChannel::handleError (int error)
|
||||||
{
|
{
|
||||||
if (error == EINPROGRESS) {
|
|
||||||
// this shoudl never happen, because we should use isNonBlocking to check
|
|
||||||
// such error codes.
|
|
||||||
SG_LOG(SG_IO, SG_WARN, "Got EINPROGRESS at NetChannel::handleError: suggests broken logic somewhere else");
|
|
||||||
return; // not an actual error, don't warn
|
|
||||||
}
|
|
||||||
|
|
||||||
// warn about address lookup failures seperately, don't warn again.
|
// warn about address lookup failures seperately, don't warn again.
|
||||||
// (and we (ab-)use ENOENT to mean 'name not found'.
|
// (and we (ab-)use ENOENT to mean 'name not found'.
|
||||||
if (error != ENOENT) {
|
if (error != ENOENT) {
|
||||||
@@ -258,11 +251,6 @@ NetChannelPoller::removeChannel(NetChannel* channel)
|
|||||||
assert(channel->poller == this);
|
assert(channel->poller == this);
|
||||||
channel->poller = NULL;
|
channel->poller = NULL;
|
||||||
|
|
||||||
// portability: MSVC throws assertion failure when empty
|
|
||||||
if (channels.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ChannelList::iterator it = channels.begin();
|
ChannelList::iterator it = channels.begin();
|
||||||
for (; it != channels.end(); ++it) {
|
for (; it != channels.end(); ++it) {
|
||||||
if (*it == channel) {
|
if (*it == channel) {
|
||||||
|
|||||||
@@ -27,7 +27,6 @@
|
|||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace simgear {
|
namespace simgear {
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,6 @@
|
|||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdlib> // for atoi
|
#include <cstdlib> // for atoi
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
|
|||||||
+21
-146
@@ -3,23 +3,15 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include <boost/algorithm/string/case_conv.hpp>
|
#include <boost/algorithm/string/case_conv.hpp>
|
||||||
|
|
||||||
#include <simgear/simgear_config.h>
|
|
||||||
|
|
||||||
#include "HTTPClient.hxx"
|
#include "HTTPClient.hxx"
|
||||||
#include "HTTPRequest.hxx"
|
#include "HTTPRequest.hxx"
|
||||||
|
|
||||||
#include <simgear/io/sg_netChat.hxx>
|
#include <simgear/io/sg_netChat.hxx>
|
||||||
#include <simgear/misc/strutils.hxx>
|
#include <simgear/misc/strutils.hxx>
|
||||||
#include <simgear/timing/timestamp.hxx>
|
#include <simgear/timing/timestamp.hxx>
|
||||||
#include <simgear/debug/logstream.hxx>
|
|
||||||
|
|
||||||
#if defined(ENABLE_CURL)
|
|
||||||
#include <curl/multi.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using std::cout;
|
using std::cout;
|
||||||
using std::cerr;
|
using std::cerr;
|
||||||
@@ -64,8 +56,7 @@ public:
|
|||||||
|
|
||||||
TestRequest(const std::string& url, const std::string method = "GET") :
|
TestRequest(const std::string& url, const std::string method = "GET") :
|
||||||
HTTP::Request(url, method),
|
HTTP::Request(url, method),
|
||||||
complete(false),
|
complete(false)
|
||||||
failed(false)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -91,7 +82,6 @@ protected:
|
|||||||
|
|
||||||
virtual void responseHeader(const string& header, const string& value)
|
virtual void responseHeader(const string& header, const string& value)
|
||||||
{
|
{
|
||||||
Request::responseHeader(header, value);
|
|
||||||
headers[header] = value;
|
headers[header] = value;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -151,7 +141,7 @@ public:
|
|||||||
|
|
||||||
string::size_type colonPos = buffer.find(':');
|
string::size_type colonPos = buffer.find(':');
|
||||||
if (colonPos == string::npos) {
|
if (colonPos == string::npos) {
|
||||||
cerr << "test malformed HTTP response header:" << buffer << endl;
|
cerr << "malformed HTTP response header:" << buffer << endl;
|
||||||
buffer.clear();
|
buffer.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -187,6 +177,7 @@ public:
|
|||||||
void receivedRequestHeaders()
|
void receivedRequestHeaders()
|
||||||
{
|
{
|
||||||
state = STATE_IDLE;
|
state = STATE_IDLE;
|
||||||
|
|
||||||
if (path == "/test1") {
|
if (path == "/test1") {
|
||||||
string contentStr(BODY1);
|
string contentStr(BODY1);
|
||||||
stringstream d;
|
stringstream d;
|
||||||
@@ -246,7 +237,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (requestHeaders["Proxy-Authorization"] != string()) {
|
if (requestHeaders["Proxy-Authorization"] != string()) {
|
||||||
sendErrorResponse(401, false, "bad auth, not empty"); // shouldn't supply auth
|
sendErrorResponse(401, false, "bad auth"); // shouldn't supply auth
|
||||||
}
|
}
|
||||||
|
|
||||||
sendBody2();
|
sendBody2();
|
||||||
@@ -256,28 +247,8 @@ public:
|
|||||||
sendErrorResponse(400, true, "bad destination");
|
sendErrorResponse(400, true, "bad destination");
|
||||||
}
|
}
|
||||||
|
|
||||||
string credentials = requestHeaders["Proxy-Authorization"];
|
if (requestHeaders["Proxy-Authorization"] != "ABCDEF") {
|
||||||
if (credentials.substr(0, 5) != "Basic") {
|
sendErrorResponse(401, false, "bad auth"); // forbidden
|
||||||
// request basic auth
|
|
||||||
stringstream d;
|
|
||||||
d << "HTTP/1.1 " << 407 << " " << reasonForCode(407) << "\r\n";
|
|
||||||
d << "WWW-Authenticate: Basic real=\"simgear\"\r\n";
|
|
||||||
d << "\r\n"; // final CRLF to terminate the headers
|
|
||||||
push(d.str().c_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<unsigned char> userAndPass;
|
|
||||||
strutils::decodeBase64(credentials.substr(6), userAndPass);
|
|
||||||
std::string decodedUserPass((char*) userAndPass.data(), userAndPass.size());
|
|
||||||
|
|
||||||
if (decodedUserPass != "johndoe:swordfish") {
|
|
||||||
std::map<string, string>::const_iterator it;
|
|
||||||
for (it = requestHeaders.begin(); it != requestHeaders.end(); ++it) {
|
|
||||||
cerr << "header:" << it->first << " = " << it->second << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
sendErrorResponse(401, false, "bad auth, not as set"); // forbidden
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sendBody2();
|
sendBody2();
|
||||||
@@ -301,12 +272,6 @@ public:
|
|||||||
d << contentStr;
|
d << contentStr;
|
||||||
push(d.str().c_str());
|
push(d.str().c_str());
|
||||||
closeAfterSending();
|
closeAfterSending();
|
||||||
} else if (path == "/test_abrupt_close") {
|
|
||||||
// simulate server doing socket close before sending any
|
|
||||||
// response - this used to cause a TerraSync failure since we
|
|
||||||
// would get stuck restarting the request
|
|
||||||
closeAfterSending();
|
|
||||||
|
|
||||||
} else if (path == "/test_args") {
|
} else if (path == "/test_args") {
|
||||||
if ((args["foo"] != "abc") || (args["bar"] != "1234") || (args["username"] != "johndoe")) {
|
if ((args["foo"] != "abc") || (args["bar"] != "1234") || (args["username"] != "johndoe")) {
|
||||||
sendErrorResponse(400, true, "bad arguments");
|
sendErrorResponse(400, true, "bad arguments");
|
||||||
@@ -327,16 +292,6 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
requestContentLength = strutils::to_int(requestHeaders["Content-Length"]);
|
|
||||||
setByteCount(requestContentLength);
|
|
||||||
state = STATE_REQUEST_BODY;
|
|
||||||
} else if ((path == "/test_put") || (path == "/test_create")) {
|
|
||||||
if (requestHeaders["Content-Type"] != "x-application/foobar") {
|
|
||||||
cerr << "bad content type: '" << requestHeaders["Content-Type"] << "'" << endl;
|
|
||||||
sendErrorResponse(400, true, "bad content type");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
requestContentLength = strutils::to_int(requestHeaders["Content-Length"]);
|
requestContentLength = strutils::to_int(requestHeaders["Content-Length"]);
|
||||||
setByteCount(requestContentLength);
|
setByteCount(requestContentLength);
|
||||||
state = STATE_REQUEST_BODY;
|
state = STATE_REQUEST_BODY;
|
||||||
@@ -368,34 +323,9 @@ public:
|
|||||||
d << "HTTP/1.1 " << 204 << " " << reasonForCode(204) << "\r\n";
|
d << "HTTP/1.1 " << 204 << " " << reasonForCode(204) << "\r\n";
|
||||||
d << "\r\n"; // final CRLF to terminate the headers
|
d << "\r\n"; // final CRLF to terminate the headers
|
||||||
push(d.str().c_str());
|
push(d.str().c_str());
|
||||||
} else if (path == "/test_put") {
|
|
||||||
std::cerr << "sending PUT response" << std::endl;
|
|
||||||
|
|
||||||
COMPARE(buffer, BODY3);
|
cerr << "sent 204 response ok" << endl;
|
||||||
stringstream d;
|
|
||||||
d << "HTTP/1.1 " << 204 << " " << reasonForCode(204) << "\r\n";
|
|
||||||
d << "\r\n"; // final CRLF to terminate the headers
|
|
||||||
push(d.str().c_str());
|
|
||||||
} else if (path == "/test_create") {
|
|
||||||
std::cerr << "sending create response" << std::endl;
|
|
||||||
|
|
||||||
std::string entityStr = "http://localhost:2000/something.txt";
|
|
||||||
|
|
||||||
COMPARE(buffer, BODY3);
|
|
||||||
stringstream d;
|
|
||||||
d << "HTTP/1.1 " << 201 << " " << reasonForCode(201) << "\r\n";
|
|
||||||
d << "Location:" << entityStr << "\r\n";
|
|
||||||
d << "Content-Length:" << entityStr.size() << "\r\n";
|
|
||||||
d << "\r\n"; // final CRLF to terminate the headers
|
|
||||||
d << entityStr;
|
|
||||||
|
|
||||||
push(d.str().c_str());
|
|
||||||
} else {
|
|
||||||
std::cerr << "weird URL " << path << std::endl;
|
|
||||||
sendErrorResponse(400, true, "bad URL:" + path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendBody2()
|
void sendBody2()
|
||||||
@@ -411,8 +341,6 @@ public:
|
|||||||
void sendErrorResponse(int code, bool close, string content)
|
void sendErrorResponse(int code, bool close, string content)
|
||||||
{
|
{
|
||||||
cerr << "sending error " << code << " for " << path << endl;
|
cerr << "sending error " << code << " for " << path << endl;
|
||||||
cerr << "\tcontent:" << content << endl;
|
|
||||||
|
|
||||||
stringstream headerData;
|
stringstream headerData;
|
||||||
headerData << "HTTP/1.1 " << code << " " << reasonForCode(code) << "\r\n";
|
headerData << "HTTP/1.1 " << code << " " << reasonForCode(code) << "\r\n";
|
||||||
headerData << "Content-Length:" << content.size() << "\r\n";
|
headerData << "Content-Length:" << content.size() << "\r\n";
|
||||||
@@ -429,10 +357,8 @@ public:
|
|||||||
{
|
{
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case 200: return "OK";
|
case 200: return "OK";
|
||||||
case 201: return "Created";
|
|
||||||
case 204: return "no content";
|
case 204: return "no content";
|
||||||
case 404: return "not found";
|
case 404: return "not found";
|
||||||
case 407: return "proxy authentication required";
|
|
||||||
default: return "unknown code";
|
default: return "unknown code";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -453,8 +379,6 @@ class TestServer : public NetChannel
|
|||||||
public:
|
public:
|
||||||
TestServer()
|
TestServer()
|
||||||
{
|
{
|
||||||
Socket::initSockets();
|
|
||||||
|
|
||||||
open();
|
open();
|
||||||
bind(NULL, 2000); // localhost, any port
|
bind(NULL, 2000); // localhost, any port
|
||||||
listen(5);
|
listen(5);
|
||||||
@@ -490,14 +414,14 @@ TestServer testServer;
|
|||||||
void waitForComplete(HTTP::Client* cl, TestRequest* tr)
|
void waitForComplete(HTTP::Client* cl, TestRequest* tr)
|
||||||
{
|
{
|
||||||
SGTimeStamp start(SGTimeStamp::now());
|
SGTimeStamp start(SGTimeStamp::now());
|
||||||
while (start.elapsedMSec() < 10000) {
|
while (start.elapsedMSec() < 1000) {
|
||||||
cl->update();
|
cl->update();
|
||||||
testServer.poll();
|
testServer.poll();
|
||||||
|
|
||||||
if (tr->complete) {
|
if (tr->complete) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SGTimeStamp::sleepForMSec(15);
|
SGTimeStamp::sleepForMSec(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
cerr << "timed out" << endl;
|
cerr << "timed out" << endl;
|
||||||
@@ -506,14 +430,14 @@ void waitForComplete(HTTP::Client* cl, TestRequest* tr)
|
|||||||
void waitForFailed(HTTP::Client* cl, TestRequest* tr)
|
void waitForFailed(HTTP::Client* cl, TestRequest* tr)
|
||||||
{
|
{
|
||||||
SGTimeStamp start(SGTimeStamp::now());
|
SGTimeStamp start(SGTimeStamp::now());
|
||||||
while (start.elapsedMSec() < 10000) {
|
while (start.elapsedMSec() < 1000) {
|
||||||
cl->update();
|
cl->update();
|
||||||
testServer.poll();
|
testServer.poll();
|
||||||
|
|
||||||
if (tr->failed) {
|
if (tr->failed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SGTimeStamp::sleepForMSec(15);
|
SGTimeStamp::sleepForMSec(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
cerr << "timed out waiting for failure" << endl;
|
cerr << "timed out waiting for failure" << endl;
|
||||||
@@ -521,7 +445,6 @@ void waitForFailed(HTTP::Client* cl, TestRequest* tr)
|
|||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
sglog().setLogLevels( SG_ALL, SG_INFO );
|
|
||||||
|
|
||||||
HTTP::Client cl;
|
HTTP::Client cl;
|
||||||
// force all requests to use the same connection for this test
|
// force all requests to use the same connection for this test
|
||||||
@@ -577,6 +500,8 @@ int main(int argc, char* argv[])
|
|||||||
COMPARE(tr->responseCode(), 200);
|
COMPARE(tr->responseCode(), 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cerr << "done args" << endl;
|
||||||
|
|
||||||
{
|
{
|
||||||
TestRequest* tr = new TestRequest("http://localhost:2000/test_headers");
|
TestRequest* tr = new TestRequest("http://localhost:2000/test_headers");
|
||||||
HTTP::Request_ptr own(tr);
|
HTTP::Request_ptr own(tr);
|
||||||
@@ -607,7 +532,7 @@ int main(int argc, char* argv[])
|
|||||||
COMPARE(tr->bodyData, string(body2, body2Size));
|
COMPARE(tr->bodyData, string(body2, body2Size));
|
||||||
}
|
}
|
||||||
|
|
||||||
cerr << "testing chunked transfer encoding" << endl;
|
cerr << "testing chunked" << endl;
|
||||||
{
|
{
|
||||||
TestRequest* tr = new TestRequest("http://localhost:2000/testchunked");
|
TestRequest* tr = new TestRequest("http://localhost:2000/testchunked");
|
||||||
HTTP::Request_ptr own(tr);
|
HTTP::Request_ptr own(tr);
|
||||||
@@ -668,40 +593,15 @@ int main(int argc, char* argv[])
|
|||||||
}
|
}
|
||||||
cout << "done3" << endl;
|
cout << "done3" << endl;
|
||||||
// test connectToHost failure
|
// test connectToHost failure
|
||||||
|
/*
|
||||||
{
|
{
|
||||||
TestRequest* tr = new TestRequest("http://not.found/something");
|
TestRequest* tr = new TestRequest("http://not.found/something");
|
||||||
HTTP::Request_ptr own(tr);
|
HTTP::Request_ptr own(tr);
|
||||||
cl.makeRequest(tr);
|
cl.makeRequest(tr);
|
||||||
waitForFailed(&cl, tr);
|
waitForFailed(tr);
|
||||||
|
COMPARE(tr->responseCode(), -1);
|
||||||
|
|
||||||
|
|
||||||
#if defined(ENABLE_CURL)
|
|
||||||
const int HOST_NOT_FOUND_CODE = CURLE_COULDNT_RESOLVE_HOST;
|
|
||||||
#else
|
|
||||||
const int HOST_NOT_FOUND_CODE = ENOENT;
|
|
||||||
#endif
|
|
||||||
COMPARE(tr->responseCode(), HOST_NOT_FOUND_CODE);
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
cout << "testing abrupt close" << endl;
|
|
||||||
// test server-side abrupt close
|
|
||||||
{
|
|
||||||
TestRequest* tr = new TestRequest("http://localhost:2000/test_abrupt_close");
|
|
||||||
HTTP::Request_ptr own(tr);
|
|
||||||
cl.makeRequest(tr);
|
|
||||||
waitForFailed(&cl, tr);
|
|
||||||
|
|
||||||
#if defined(ENABLE_CURL)
|
|
||||||
const int SERVER_NO_DATA_CODE = CURLE_GOT_NOTHING;
|
|
||||||
#else
|
|
||||||
const int SERVER_NO_DATA_CODE = 500;
|
|
||||||
#endif
|
|
||||||
COMPARE(tr->responseCode(), SERVER_NO_DATA_CODE);
|
|
||||||
}
|
|
||||||
|
|
||||||
cout << "testing proxy close" << endl;
|
|
||||||
// test proxy
|
// test proxy
|
||||||
{
|
{
|
||||||
cl.setProxy("localhost", 2000);
|
cl.setProxy("localhost", 2000);
|
||||||
@@ -714,9 +614,8 @@ cout << "testing proxy close" << endl;
|
|||||||
COMPARE(tr->bodyData, string(body2, body2Size));
|
COMPARE(tr->bodyData, string(body2, body2Size));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(ENABLE_CURL)
|
|
||||||
{
|
{
|
||||||
cl.setProxy("localhost", 2000, "johndoe:swordfish");
|
cl.setProxy("localhost", 2000, "ABCDEF");
|
||||||
TestRequest* tr = new TestRequest("http://www.google.com/test3");
|
TestRequest* tr = new TestRequest("http://www.google.com/test3");
|
||||||
HTTP::Request_ptr own(tr);
|
HTTP::Request_ptr own(tr);
|
||||||
cl.makeRequest(tr);
|
cl.makeRequest(tr);
|
||||||
@@ -725,10 +624,9 @@ cout << "testing proxy close" << endl;
|
|||||||
COMPARE(tr->responseBytesReceived(), body2Size);
|
COMPARE(tr->responseBytesReceived(), body2Size);
|
||||||
COMPARE(tr->bodyData, string(body2, body2Size));
|
COMPARE(tr->bodyData, string(body2, body2Size));
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// pipelining
|
// pipelining
|
||||||
cout << "testing HTTP 1.1 pipelining" << endl;
|
cout << "testing HTTP 1.1 pipelineing" << endl;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -791,7 +689,7 @@ cout << "testing proxy close" << endl;
|
|||||||
|
|
||||||
// POST
|
// POST
|
||||||
{
|
{
|
||||||
cout << "testing POST" << endl;
|
cout << "POST" << endl;
|
||||||
TestRequest* tr = new TestRequest("http://localhost:2000/test_post?foo=abc&bar=1234&username=johndoe", "POST");
|
TestRequest* tr = new TestRequest("http://localhost:2000/test_post?foo=abc&bar=1234&username=johndoe", "POST");
|
||||||
tr->setBodyData("", "application/x-www-form-urlencoded");
|
tr->setBodyData("", "application/x-www-form-urlencoded");
|
||||||
|
|
||||||
@@ -801,29 +699,6 @@ cout << "testing proxy close" << endl;
|
|||||||
COMPARE(tr->responseCode(), 204);
|
COMPARE(tr->responseCode(), 204);
|
||||||
}
|
}
|
||||||
|
|
||||||
// PUT
|
|
||||||
{
|
|
||||||
cout << "testing PUT" << endl;
|
|
||||||
TestRequest* tr = new TestRequest("http://localhost:2000/test_put", "PUT");
|
|
||||||
tr->setBodyData(BODY3, "x-application/foobar");
|
|
||||||
|
|
||||||
HTTP::Request_ptr own(tr);
|
|
||||||
cl.makeRequest(tr);
|
|
||||||
waitForComplete(&cl, tr);
|
|
||||||
COMPARE(tr->responseCode(), 204);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
cout << "testing PUT create" << endl;
|
|
||||||
TestRequest* tr = new TestRequest("http://localhost:2000/test_create", "PUT");
|
|
||||||
tr->setBodyData(BODY3, "x-application/foobar");
|
|
||||||
|
|
||||||
HTTP::Request_ptr own(tr);
|
|
||||||
cl.makeRequest(tr);
|
|
||||||
waitForComplete(&cl, tr);
|
|
||||||
COMPARE(tr->responseCode(), 201);
|
|
||||||
}
|
|
||||||
|
|
||||||
// test_zero_length_content
|
// test_zero_length_content
|
||||||
{
|
{
|
||||||
cout << "zero-length-content-response" << endl;
|
cout << "zero-length-content-response" << endl;
|
||||||
|
|||||||
+65
-79
@@ -24,7 +24,7 @@
|
|||||||
// Put in some bullet-proofing to handle magnetic and geographic poles.
|
// Put in some bullet-proofing to handle magnetic and geographic poles.
|
||||||
// 3/28/2000 EAW
|
// 3/28/2000 EAW
|
||||||
//
|
//
|
||||||
// Updated coefficient arrays to use the current wmm2005 model,
|
// Updated coefficient arrays to use the current WMM2005 model,
|
||||||
// (valid between 2005.0 and 2010.0)
|
// (valid between 2005.0 and 2010.0)
|
||||||
// Also removed unused variables and corrected earth radii constants
|
// Also removed unused variables and corrected earth radii constants
|
||||||
// to the values for WGS84 and WMM2005.
|
// to the values for WGS84 and WMM2005.
|
||||||
@@ -36,20 +36,6 @@
|
|||||||
//
|
//
|
||||||
// 25/10/2006 Wim Van Hoydonck -- wim.van.hoydonck@gmail.com
|
// 25/10/2006 Wim Van Hoydonck -- wim.van.hoydonck@gmail.com
|
||||||
//
|
//
|
||||||
//
|
|
||||||
// Updated coefficient arrays to use the current WMM2015 model,
|
|
||||||
// (valid between 2015.0 and 2020.0)
|
|
||||||
// Also removed unused variables and corrected earth radii constants
|
|
||||||
// to the values for WGS84 and WMM2015.
|
|
||||||
// Reference:
|
|
||||||
// A. Chulliat , S. Macmillan, P. Alken, C. Beggan, M.
|
|
||||||
// Nair, B. Hamilton, A. Woods, V. Ridley,
|
|
||||||
// S Maus, and A Thomson, December 2014, The
|
|
||||||
// US/UK World Magnetic Model for 2015-2020,
|
|
||||||
// NOAA Technical Report WMM2015_Report.pdf
|
|
||||||
//
|
|
||||||
// 18/06/2015 Jean-Paul Anceaux -- j.p.r.anceaux@gmail.com
|
|
||||||
|
|
||||||
|
|
||||||
// The routine uses a spherical harmonic expansion of the magnetic
|
// The routine uses a spherical harmonic expansion of the magnetic
|
||||||
// potential up to twelfth order, together with its time variation, as
|
// potential up to twelfth order, together with its time variation, as
|
||||||
@@ -93,7 +79,7 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <cmath>
|
#include <math.h>
|
||||||
|
|
||||||
#include <simgear/constants.h>
|
#include <simgear/constants.h>
|
||||||
#include <simgear/sg_inlines.h>
|
#include <simgear/sg_inlines.h>
|
||||||
@@ -104,72 +90,72 @@ static const double a = 6378.137; /* semi-major axis (equatorial radius) o
|
|||||||
static const double b = 6356.7523142; /* semi-minor axis referenced to the WGS84 ellipsoid */
|
static const double b = 6356.7523142; /* semi-minor axis referenced to the WGS84 ellipsoid */
|
||||||
static const double r_0 = 6371.2; /* standard Earth magnetic reference radius */
|
static const double r_0 = 6371.2; /* standard Earth magnetic reference radius */
|
||||||
|
|
||||||
static double gnm_wmm2015[13][13] =
|
static double gnm_wmm2005[13][13] =
|
||||||
{
|
{
|
||||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{-29438.5, -1501.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{-29556.8, -1671.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{-2445.3, 3012.5, 1676.6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{-2340.6, 3046.9, 1657.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{1351.1, -2352.3, 1225.6, 581.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{1335.4, -2305.1, 1246.7, 674.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{907.2, 813.7, 120.3, -335.0, 70.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{919.8, 798.1, 211.3, -379.4, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{-232.6, 360.1, 192.4, -141.0, -157.4, 4.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{-227.4, 354.6, 208.7, -136.5, -168.3, -14.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{69.5, 67.4, 72.8, -129.8, -29.0, 13.2, -70.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{73.2, 69.7, 76.7, -151.2, -14.9, 14.6, -86.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{81.6, -76.1, -6.8, 51.9, 15.0, 9.3, -2.8, 6.7, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{80.1, -74.5, -1.4, 38.5, 12.4, 9.5, 5.7, 1.8, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{24.0, 8.6, -16.9, -3.2, -20.6, 13.3, 11.7, -16.0, -2.0, 0.0, 0.0, 0.0, 0.0},
|
{24.9, 7.7, -11.6, -6.9, -18.2, 10.0, 9.2, -11.6, -5.2, 0.0, 0.0, 0.0, 0.0},
|
||||||
{5.4, 8.8, 3.1, -3.1, 0.6, -13.3, -0.1, 8.7, -9.1, -10.5, 0.0, 0.0, 0.0},
|
{5.6, 9.9, 3.5, -7.0, 5.1, -10.8, -1.3, 8.8, -6.7, -9.1, 0.0, 0.0, 0.0},
|
||||||
{-1.9, -6.5, 0.2, 0.6, -0.6, 1.7, -0.7, 2.1, 2.3, -1.8, -3.6, 0.0, 0.0},
|
{-2.3, -6.3, 1.6, -2.6, 0.0, 3.1, 0.4, 2.1, 3.9, -0.1, -2.3, 0.0, 0.0},
|
||||||
{3.1, -1.5, -2.3, 2.1, -0.9, 0.6, -0.7, 0.2, 1.7, -0.2, 0.4, 3.5, 0.0},
|
{2.8, -1.6, -1.7, 1.7, -0.1, 0.1, -0.7, 0.7, 1.8, 0.0, 1.1, 4.1, 0.0},
|
||||||
{-2.0, -0.3, 0.4, 1.3, -0.9, 0.9, 0.1, 0.5, -0.4, -0.4, 0.2, -0.9, 0.0},
|
{-2.4, -0.4, 0.2, 0.8, -0.3, 1.1, -0.5, 0.4, -0.3, -0.3, -0.1, -0.3, -0.1},
|
||||||
};
|
};
|
||||||
|
|
||||||
static double hnm_wmm2015[13][13]=
|
static double hnm_wmm2005[13][13]=
|
||||||
{
|
{
|
||||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 4796.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, 5079.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, -2845.6, -642.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, -2594.7, -516.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, -115.3, 245.0, -538.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, -199.9, 269.3, -524.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 283.4, -188.6, 180.9, -329.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, 281.5, -226.0, 145.8, -304.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 47.4, 196.9, -119.4, 16.1, 100.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, 42.4, 179.8, -123.0, -19.5, 103.6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, -20.7, 33.2, 58.8, -66.5, 7.3, 62.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, -20.3, 54.7, 63.6, -63.4, -0.1, 50.4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, -54.1, -19.4, 5.6, 24.4, 3.3, -27.5, -2.3, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, -61.5, -22.4, 7.2, 25.4, 11.0, -26.4, -5.1, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 10.2, -18.1, 13.2, -14.6, 16.2, 5.7, -9.1, 2.2, 0.0, 0.0, 0.0, 0.0},
|
{0.0, 11.2, -21.0, 9.6, -19.8, 16.1, 7.7, -12.9, -0.2, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, -21.6, 10.8, 11.7, -6.8, -6.9, 7.8, 1.0, -3.9, 8.5, 0.0, 0.0, 0.0},
|
{0.0, -20.1, 12.9, 12.6, -6.7, -8.1, 8.0, 2.9, -7.9, 6.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 3.3, -0.3, 4.6, 4.4, -7.9, -0.6, -4.1, -2.8, -1.1, -8.7, 0.0, 0.0},
|
{0.0, 2.4, 0.2, 4.4, 4.8, -6.5, -1.1, -3.4, -0.8, -2.3, -7.9, 0.0, 0.0},
|
||||||
{0.0, -0.1, 2.1, -0.7, -1.1, 0.7, -0.2, -2.1, -1.5, -2.5, -2.0, -2.3, 0.0},
|
{0.0, 0.3, 1.2, -0.8, -2.5, 0.9, -0.6, -2.7, -0.9, -1.3, -2.0, -1.2, 0.0},
|
||||||
{0.0, -1.0, 0.5, 1.8, -2.2, 0.3, 0.7, -0.1, 0.3, 0.2, -0.9, -0.2, 0.7},
|
{0.0, -0.4, 0.3, 2.4, -2.6, 0.6, 0.3, 0.0, 0.0, 0.3, -0.9, -0.4, 0.8},
|
||||||
};
|
};
|
||||||
|
|
||||||
static double gtnm_wmm2015[13][13]=
|
static double gtnm_wmm2005[13][13]=
|
||||||
{
|
{
|
||||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{10.7, 17.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{8.0, 10.6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{-8.6, -3.3, 2.4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{-15.1, -7.8, -0.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{3.1, -6.2, -0.4, -10.4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.4, -2.6, -1.2, -6.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{-0.4, 0.8, -9.2, 4.0, -4.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{-2.5, 2.8, -7.0, 6.2, -3.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{-0.2, 0.1, -1.4, 0.0, 1.3, 3.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{-2.8, 0.7, -3.2, -1.1, 0.1, -0.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{-0.5, -0.2, -0.6, 2.4, -1.1, 0.3, 1.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{-0.7, 0.4, -0.3, 2.3, -2.1, -0.6, 1.4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.2, -0.2, -0.4, 1.3, 0.2, -0.4, -0.9, 0.3, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.2, -0.1, -0.3, 1.1, 0.6, 0.5, -0.4, 0.6, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 0.1, -0.5, 0.5, -0.2, 0.4, 0.2, -0.4, 0.3, 0.0, 0.0, 0.0, 0.0},
|
{0.1, 0.3, -0.4, 0.3, -0.3, 0.2, 0.4, -0.7, 0.4, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, -0.1, -0.1, 0.4, -0.5, -0.2, 0.1, 0.0, -0.2, -0.1, 0.0, 0.0, 0.0},
|
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 0.0, -0.1, 0.3, -0.1, -0.1, -0.1, 0.0, -0.2, -0.1, -0.2, 0.0, 0.0},
|
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 0.0, -0.1, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.1, -0.1, 0.0},
|
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.1, 0.0, 0.0, 0.1, -0.1, 0.0, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
};
|
};
|
||||||
|
|
||||||
static double htnm_wmm2015[13][13]=
|
static double htnm_wmm2005[13][13]=
|
||||||
{
|
{
|
||||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, -26.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, -20.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, -27.1, -13.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, -23.2, -14.6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 8.4, -0.4, 2.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, 5.0, -7.0, -0.6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, -0.6, 5.3, 3.0, -5.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, 2.2, 1.6, 5.8, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 0.4, 1.6, -1.1, 3.3, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, 0.0, 1.7, 2.1, 4.8, -1.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 0.0, -2.2, -0.7, 0.1, 1.0, 1.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, -0.6, -1.9, -0.4, -0.5, -0.3, 0.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 0.7, 0.5, -0.2, -0.1, -0.7, 0.1, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, 0.6, 0.4, 0.2, 0.3, -0.8, -0.2, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, -0.3, 0.3, 0.3, 0.6, -0.1, -0.2, 0.3, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, -0.2, 0.1, 0.3, 0.4, 0.1, -0.2, 0.4, 0.4, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, -0.2, -0.1, -0.2, 0.1, 0.1, 0.0, -0.2, 0.4, 0.3, 0.0, 0.0, 0.0},
|
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 0.1, -0.1, 0.0, 0.0, -0.2, 0.1, -0.1, -0.2, 0.1, -0.1, 0.0, 0.0},
|
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 0.0, 0.1, 0.0, 0.1, 0.0, 0.0, 0.1, 0.0, -0.1, 0.0, -0.1, 0.0},
|
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 0.0, 0.0, -0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int nmax = 12;
|
static const int nmax = 12;
|
||||||
@@ -209,8 +195,8 @@ double calc_magvar( double lat, double lon, double h, long dat, double* field )
|
|||||||
{
|
{
|
||||||
/* output field B_r,B_th,B_phi,B_x,B_y,B_z */
|
/* output field B_r,B_th,B_phi,B_x,B_y,B_z */
|
||||||
int n,m;
|
int n,m;
|
||||||
/* reference date for current model is 1 januari 2015 */
|
/* reference date for current model is 1 januari 2005 */
|
||||||
long date0_wmm2015 = yymmdd_to_julian_days(15,1,1);
|
long date0_wmm2005 = yymmdd_to_julian_days(5,1,1);
|
||||||
|
|
||||||
double yearfrac,sr,r,theta,c,s,psi,fn,fn_0,B_r,B_theta,B_phi,X,Y,Z;
|
double yearfrac,sr,r,theta,c,s,psi,fn,fn_0,B_r,B_theta,B_phi,X,Y,Z;
|
||||||
double sinpsi, cospsi, inv_s;
|
double sinpsi, cospsi, inv_s;
|
||||||
@@ -297,12 +283,12 @@ double calc_magvar( double lat, double lon, double h, long dat, double* field )
|
|||||||
|
|
||||||
/* compute Gauss coefficients gnm and hnm of degree n and order m for the desired time
|
/* compute Gauss coefficients gnm and hnm of degree n and order m for the desired time
|
||||||
achieved by adjusting the coefficients at time t0 for linear secular variation */
|
achieved by adjusting the coefficients at time t0 for linear secular variation */
|
||||||
/* WMM2015 */
|
/* WMM2005 */
|
||||||
yearfrac = (dat - date0_wmm2015) / 365.25;
|
yearfrac = (dat - date0_wmm2005) / 365.25;
|
||||||
for ( n = 1; n <= nmax; n++ ) {
|
for ( n = 1; n <= nmax; n++ ) {
|
||||||
for ( m = 0; m <= nmax; m++ ) {
|
for ( m = 0; m <= nmax; m++ ) {
|
||||||
gnm[n][m] = gnm_wmm2015[n][m] + yearfrac * gtnm_wmm2015[n][m];
|
gnm[n][m] = gnm_wmm2005[n][m] + yearfrac * gtnm_wmm2005[n][m];
|
||||||
hnm[n][m] = hnm_wmm2015[n][m] + yearfrac * htnm_wmm2015[n][m];
|
hnm[n][m] = hnm_wmm2005[n][m] + yearfrac * htnm_wmm2005[n][m];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,7 +350,7 @@ double SGMagVarOrig( double lat, double lon, double h, long dat, double* field )
|
|||||||
/* output field B_r,B_th,B_phi,B_x,B_y,B_z */
|
/* output field B_r,B_th,B_phi,B_x,B_y,B_z */
|
||||||
int n,m;
|
int n,m;
|
||||||
/* reference dates */
|
/* reference dates */
|
||||||
long date0_wmm2015 = yymmdd_to_julian_days(5,1,1);
|
long date0_wmm2005 = yymmdd_to_julian_days(5,1,1);
|
||||||
|
|
||||||
double yearfrac,sr,r,theta,c,s,psi,fn,B_r,B_theta,B_phi,X,Y,Z;
|
double yearfrac,sr,r,theta,c,s,psi,fn,B_r,B_theta,B_phi,X,Y,Z;
|
||||||
|
|
||||||
@@ -421,12 +407,12 @@ double SGMagVarOrig( double lat, double lon, double h, long dat, double* field )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* compute gnm, hnm at dat */
|
/* compute gnm, hnm at dat */
|
||||||
/* WMM2015 */
|
/* WMM2005 */
|
||||||
yearfrac = (dat - date0_wmm2015) / 365.25;
|
yearfrac = (dat - date0_wmm2005) / 365.25;
|
||||||
for ( n = 1; n <= nmax; n++ ) {
|
for ( n = 1; n <= nmax; n++ ) {
|
||||||
for ( m = 0; m <= nmax; m++ ) {
|
for ( m = 0; m <= nmax; m++ ) {
|
||||||
gnm[n][m] = gnm_wmm2015[n][m] + yearfrac * gtnm_wmm2015[n][m];
|
gnm[n][m] = gnm_wmm2005[n][m] + yearfrac * gtnm_wmm2005[n][m];
|
||||||
hnm[n][m] = hnm_wmm2015[n][m] + yearfrac * htnm_wmm2015[n][m];
|
hnm[n][m] = hnm_wmm2005[n][m] + yearfrac * htnm_wmm2005[n][m];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include <cmath>
|
#include <math.h>
|
||||||
|
|
||||||
#include <simgear/magvar/magvar.hxx>
|
#include <simgear/magvar/magvar.hxx>
|
||||||
#include <simgear/math/SGMath.hxx>
|
#include <simgear/math/SGMath.hxx>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <cmath>
|
#include <math.h>
|
||||||
|
|
||||||
#include <simgear/constants.h>
|
#include <simgear/constants.h>
|
||||||
|
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ public:
|
|||||||
static bool isNaN(const T& v)
|
static bool isNaN(const T& v)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_ISNAN
|
#ifdef HAVE_ISNAN
|
||||||
return (isnan(v) != 0);
|
return isnan(v);
|
||||||
#elif defined HAVE_STD_ISNAN
|
#elif defined HAVE_STD_ISNAN
|
||||||
return std::isnan(v);
|
return std::isnan(v);
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ namespace simgear
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setMaxSubdiv( size_t aMaxSubdiv ) { mMaxSubdiv = aMaxSubdiv; }
|
void setMaxSubdiv( size_t aMaxSubdiv ) { mMaxSubdiv = aMaxSubdiv; }
|
||||||
size_t getMaxSubdiv() const { return mMaxSubdiv; }
|
void getMaxSubdiv() const { return mMaxSubdiv; }
|
||||||
PointList &pointList() { return mPointList; }
|
PointList &pointList() { return mPointList; }
|
||||||
const PointList &pointList() const { return mPointList; }
|
const PointList &pointList() const { return mPointList; }
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ SGInterpTable::SGInterpTable( const std::string& file )
|
|||||||
while ( in ) {
|
while ( in ) {
|
||||||
double ind, dep;
|
double ind, dep;
|
||||||
in >> ind >> dep;
|
in >> ind >> dep;
|
||||||
in >> std::skipws;
|
in >> skipws;
|
||||||
_table[ind] = dep;
|
_table[ind] = dep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,10 +37,6 @@ set(SOURCES
|
|||||||
gzcontainerfile.cxx
|
gzcontainerfile.cxx
|
||||||
)
|
)
|
||||||
|
|
||||||
if (WINDOWS)
|
|
||||||
list(APPEND HEADERS sgversionhelpers.hxx)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
list(APPEND SOURCES CocoaHelpers.mm)
|
list(APPEND SOURCES CocoaHelpers.mm)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -141,11 +141,7 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
// add
|
// add
|
||||||
pc.add("/opt/local");
|
pc.add("/opt/local");
|
||||||
#ifdef _WIN32
|
|
||||||
COMPARE(pc.str(), std::string("/usr/local/include/;/opt/local"));
|
|
||||||
#else
|
|
||||||
COMPARE(pc.str(), std::string("/usr/local/include/:/opt/local"));
|
COMPARE(pc.str(), std::string("/usr/local/include/:/opt/local"));
|
||||||
#endif
|
|
||||||
|
|
||||||
// concat
|
// concat
|
||||||
SGPath pd = pb;
|
SGPath pd = pb;
|
||||||
|
|||||||
@@ -382,7 +382,6 @@ bool Dir::remove(bool recursive)
|
|||||||
|
|
||||||
if (recursive) {
|
if (recursive) {
|
||||||
if (!removeChildren()) {
|
if (!removeChildren()) {
|
||||||
SG_LOG(SG_IO, SG_WARN, "Dir at:" << _path << " failed to remove children");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} // of recursive deletion
|
} // of recursive deletion
|
||||||
|
|||||||
+25
-88
@@ -57,9 +57,6 @@ static const char sgSearchPathSep = ':';
|
|||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <ShlObj.h> // for CSIDL
|
#include <ShlObj.h> // for CSIDL
|
||||||
// TODO: replace this include file with the official <versionhelpers.h> header
|
|
||||||
// included in the Windows 8.1 SDK
|
|
||||||
#include "sgversionhelpers.hxx"
|
|
||||||
|
|
||||||
static SGPath pathForCSIDL(int csidl, const SGPath& def)
|
static SGPath pathForCSIDL(int csidl, const SGPath& def)
|
||||||
{
|
{
|
||||||
@@ -83,42 +80,6 @@ static SGPath pathForCSIDL(int csidl, const SGPath& def)
|
|||||||
|
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SGPath pathForKnownFolder(REFKNOWNFOLDERID folderId, const SGPath& def)
|
|
||||||
{
|
|
||||||
typedef HRESULT (WINAPI*PSHGKFP)(REFKNOWNFOLDERID, DWORD, HANDLE, PWSTR*);
|
|
||||||
|
|
||||||
HINSTANCE shellDll = LoadLibrary(TEXT("shell32"));
|
|
||||||
if (shellDll != NULL) {
|
|
||||||
PSHGKFP pSHGetKnownFolderPath = (PSHGKFP) GetProcAddress(shellDll, "SHGetKnownFolderPath");
|
|
||||||
if (pSHGetKnownFolderPath != NULL) {
|
|
||||||
// system call will allocate dynamic memory... which we must release when done
|
|
||||||
wchar_t* localFolder = 0;
|
|
||||||
|
|
||||||
if (pSHGetKnownFolderPath(folderId, KF_FLAG_DEFAULT_PATH, NULL, &localFolder) == S_OK) {
|
|
||||||
// copy into local memory
|
|
||||||
char path[MAX_PATH];
|
|
||||||
size_t len;
|
|
||||||
if (wcstombs_s(&len, path, localFolder, MAX_PATH) != S_OK) {
|
|
||||||
path[0] = '\0';
|
|
||||||
SG_LOG(SG_GENERAL, SG_WARN, "WCS to MBS failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
SGPath folder_path = SGPath(path, def.getPermissionChecker());
|
|
||||||
|
|
||||||
// release dynamic memory
|
|
||||||
CoTaskMemFree(static_cast<void*>(localFolder));
|
|
||||||
|
|
||||||
return folder_path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FreeLibrary(shellDll);
|
|
||||||
}
|
|
||||||
|
|
||||||
return def;
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif __APPLE__
|
#elif __APPLE__
|
||||||
|
|
||||||
// defined in CocoaHelpers.mm
|
// defined in CocoaHelpers.mm
|
||||||
@@ -743,35 +704,20 @@ SGPath SGPath::standardLocation(StandardLocation type, const SGPath& def)
|
|||||||
{
|
{
|
||||||
case HOME:
|
case HOME:
|
||||||
return home(def);
|
return home(def);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
case DESKTOP:
|
case DESKTOP:
|
||||||
if (IsWindowsVistaOrGreater())
|
|
||||||
return pathForKnownFolder(FOLDERID_Desktop, def);
|
|
||||||
|
|
||||||
return pathForCSIDL(CSIDL_DESKTOPDIRECTORY, def);
|
return pathForCSIDL(CSIDL_DESKTOPDIRECTORY, def);
|
||||||
|
|
||||||
case DOWNLOADS:
|
case DOWNLOADS:
|
||||||
if (IsWindowsVistaOrGreater())
|
// TODO use KnownFolders
|
||||||
return pathForKnownFolder(FOLDERID_Downloads, def);
|
// http://msdn.microsoft.com/en-us/library/bb776911%28v=vs.85%29.aspx
|
||||||
|
if( !def.isNull() )
|
||||||
if (!def.isNull())
|
|
||||||
return def;
|
return def;
|
||||||
|
|
||||||
return pathForCSIDL(CSIDL_DESKTOPDIRECTORY, def);
|
return pathForCSIDL(CSIDL_DESKTOPDIRECTORY, def);
|
||||||
|
|
||||||
case DOCUMENTS:
|
case DOCUMENTS:
|
||||||
if (IsWindowsVistaOrGreater())
|
|
||||||
return pathForKnownFolder(FOLDERID_Documents, def);
|
|
||||||
|
|
||||||
return pathForCSIDL(CSIDL_MYDOCUMENTS, def);
|
return pathForCSIDL(CSIDL_MYDOCUMENTS, def);
|
||||||
|
|
||||||
case PICTURES:
|
case PICTURES:
|
||||||
if (IsWindowsVistaOrGreater())
|
|
||||||
return pathForKnownFolder(FOLDERID_Pictures, def);
|
|
||||||
|
|
||||||
return pathForCSIDL(CSIDL_MYPICTURES, def);
|
return pathForCSIDL(CSIDL_MYPICTURES, def);
|
||||||
|
|
||||||
#elif __APPLE__
|
#elif __APPLE__
|
||||||
// since this is C++, we can't include NSPathUtilities.h to access the enum
|
// since this is C++, we can't include NSPathUtilities.h to access the enum
|
||||||
// values, so hard-coding them here (they are stable, don't worry)
|
// values, so hard-coding them here (they are stable, don't worry)
|
||||||
@@ -810,15 +756,20 @@ SGPath SGPath::fromEnv(const char* name, const SGPath& def)
|
|||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
SGPath SGPath::home(const SGPath& def)
|
SGPath SGPath::home(const SGPath& def)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
// TODO
|
||||||
return fromEnv("USERPROFILE", def);
|
return def;
|
||||||
#else
|
|
||||||
return fromEnv("HOME", def);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
SGPath SGPath::home(const SGPath& def)
|
||||||
|
{
|
||||||
|
return fromEnv("HOME", def);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
SGPath SGPath::desktop(const SGPath& def)
|
SGPath SGPath::desktop(const SGPath& def)
|
||||||
@@ -835,39 +786,25 @@ SGPath SGPath::documents(const SGPath& def)
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
std::string SGPath::realpath() const
|
std::string SGPath::realpath() const
|
||||||
{
|
{
|
||||||
#if defined(_MSC_VER) /*for MS compilers */ || defined(_WIN32) /*needed for non MS windows compilers like MingW*/
|
#if (defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED <= 1050)
|
||||||
|
// Workaround for Mac OS 10.5. Somehow fgfs crashes on Mac at ::realpath.
|
||||||
|
// This means relative paths cannot be used on Mac OS <= 10.5
|
||||||
|
return path;
|
||||||
|
#else
|
||||||
|
#if defined(_MSC_VER) /*for MS compilers */ || defined(_WIN32) /*needed for non MS windows compilers like MingW*/
|
||||||
// with absPath NULL, will allocate, and ignore length
|
// with absPath NULL, will allocate, and ignore length
|
||||||
char *buf = _fullpath( NULL, path.c_str(), _MAX_PATH );
|
char *buf = _fullpath( NULL, path.c_str(), _MAX_PATH );
|
||||||
#else
|
#else
|
||||||
// POSIX
|
// POSIX
|
||||||
char* buf = ::realpath(path.c_str(), NULL);
|
char* buf = ::realpath(path.c_str(), NULL);
|
||||||
#endif
|
#endif
|
||||||
if (!buf) // File does not exist: return the realpath it would have if created now
|
if (!buf)
|
||||||
// (needed for fgValidatePath security)
|
|
||||||
{
|
{
|
||||||
if (path.empty()) {
|
SG_LOG(SG_IO, SG_ALERT, "ERROR: The path '" << path << "' does not exist in the file system.");
|
||||||
return SGPath(".").realpath(); // current directory
|
return path;
|
||||||
}
|
|
||||||
std::string this_dir = dir();
|
|
||||||
if (isAbsolute() && this_dir.empty()) { // top level
|
|
||||||
this_dir = "/";
|
|
||||||
}
|
|
||||||
if (file() == "..") {
|
|
||||||
this_dir = SGPath(SGPath(this_dir).realpath()).dir();
|
|
||||||
if (this_dir.empty()) { // invalid path: .. above root
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return SGPath(this_dir).realpath(); // use native path separator,
|
|
||||||
// and handle 'existing/nonexisting/../symlink' paths
|
|
||||||
}
|
|
||||||
return SGPath(this_dir).realpath() +
|
|
||||||
#if defined(_MSC_VER) || defined(_WIN32)
|
|
||||||
"\\" + file();
|
|
||||||
#else
|
|
||||||
"/" + file();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
std::string p(buf);
|
std::string p(buf);
|
||||||
free(buf);
|
free(buf);
|
||||||
return p;
|
return p;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,122 +0,0 @@
|
|||||||
// Clean drop-in replacement for the versionhelpers.h header
|
|
||||||
//
|
|
||||||
// Copyright (C) 2015 Alessandro Menti <alessandro.menti@hotmail.it>
|
|
||||||
//
|
|
||||||
// This library is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU Library General Public
|
|
||||||
// License as published by the Free Software Foundation; either
|
|
||||||
// version 2 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
|
|
||||||
// Library General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Library General Public
|
|
||||||
// License along with this library; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
||||||
|
|
||||||
#ifndef SG_VERSIONHELPERS_HXX_
|
|
||||||
#define SG_VERSIONHELPERS_HXX_
|
|
||||||
|
|
||||||
#include <sdkddkver.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
#define VERSIONHELPERAPI inline bool
|
|
||||||
#else
|
|
||||||
#define VERSIONHELPERAPI FORCEINLINE BOOL
|
|
||||||
#endif // __cplusplus
|
|
||||||
|
|
||||||
/* Windows 8/8.1 version numbers, not defined in the Windows 7 SDK. */
|
|
||||||
#ifndef _WIN32_WINNT_WIN8
|
|
||||||
#define _WIN32_WINNT_WIN8 0x0602
|
|
||||||
#endif
|
|
||||||
#ifndef _WIN32_WINNT_WINBLUE
|
|
||||||
#define _WIN32_WINNT_WINBLUE 0x0603
|
|
||||||
#endif
|
|
||||||
|
|
||||||
VERSIONHELPERAPI IsWindowsVersionOrGreater(WORD wMajorVersion,
|
|
||||||
WORD wMinorVersion, WORD wServicePackMajor) {
|
|
||||||
OSVERSIONINFOEXW osVersionInfo;
|
|
||||||
DWORDLONG dwlConditionMask = 0;
|
|
||||||
ZeroMemory(&osVersionInfo, sizeof(osVersionInfo));
|
|
||||||
osVersionInfo.dwOSVersionInfoSize = sizeof(osVersionInfo);
|
|
||||||
osVersionInfo.dwMajorVersion = wMajorVersion;
|
|
||||||
osVersionInfo.dwMinorVersion = wMinorVersion;
|
|
||||||
osVersionInfo.wServicePackMajor = wServicePackMajor;
|
|
||||||
VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION,
|
|
||||||
VER_GREATER_EQUAL);
|
|
||||||
VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION,
|
|
||||||
VER_GREATER_EQUAL);
|
|
||||||
VER_SET_CONDITION(dwlConditionMask, VER_SERVICEPACKMAJOR,
|
|
||||||
VER_GREATER_EQUAL);
|
|
||||||
return VerifyVersionInfoW(&osVersionInfo, VER_MAJORVERSION
|
|
||||||
| VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask);
|
|
||||||
}
|
|
||||||
|
|
||||||
VERSIONHELPERAPI IsWindowsXPOrGreater() {
|
|
||||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP),
|
|
||||||
LOBYTE(_WIN32_WINNT_WINXP), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
VERSIONHELPERAPI IsWindowsXPSP1OrGreater() {
|
|
||||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP),
|
|
||||||
LOBYTE(_WIN32_WINNT_WINXP), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
VERSIONHELPERAPI IsWindowsXPSP2OrGreater() {
|
|
||||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP),
|
|
||||||
LOBYTE(_WIN32_WINNT_WINXP), 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
VERSIONHELPERAPI IsWindowsXPSP3OrGreater() {
|
|
||||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP),
|
|
||||||
LOBYTE(_WIN32_WINNT_WINXP), 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
VERSIONHELPERAPI IsWindowsVistaOrGreater() {
|
|
||||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA),
|
|
||||||
LOBYTE(_WIN32_WINNT_VISTA), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
VERSIONHELPERAPI IsWindowsVistaSP1OrGreater() {
|
|
||||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA),
|
|
||||||
LOBYTE(_WIN32_WINNT_VISTA), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
VERSIONHELPERAPI IsWindowsVistaSP2OrGreater() {
|
|
||||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA),
|
|
||||||
LOBYTE(_WIN32_WINNT_VISTA), 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
VERSIONHELPERAPI IsWindows7OrGreater() {
|
|
||||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7),
|
|
||||||
LOBYTE(_WIN32_WINNT_WIN7), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
VERSIONHELPERAPI IsWindows7SP1OrGreater() {
|
|
||||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7),
|
|
||||||
LOBYTE(_WIN32_WINNT_WIN7), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
VERSIONHELPERAPI IsWindows8OrGreater() {
|
|
||||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8),
|
|
||||||
LOBYTE(_WIN32_WINNT_WIN8), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
VERSIONHELPERAPI IsWindows8Point1OrGreater() {
|
|
||||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINBLUE),
|
|
||||||
LOBYTE(_WIN32_WINNT_WINBLUE), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
VERSIONHELPERAPI IsWindowsServer() {
|
|
||||||
OSVERSIONINFOEXW osVersionInfo;
|
|
||||||
DWORDLONG dwlConditionMask = 0;
|
|
||||||
ZeroMemory(&osVersionInfo, sizeof(osVersionInfo));
|
|
||||||
osVersionInfo.dwOSVersionInfoSize = sizeof(osVersionInfo);
|
|
||||||
osVersionInfo.wProductType = VER_NT_WORKSTATION;
|
|
||||||
VER_SET_CONDITION(dwlConditionMask, VER_PRODUCT_TYPE, VER_EQUAL);
|
|
||||||
return !VerifyVersionInfoW(&osVersionInfo, VER_PRODUCT_TYPE,
|
|
||||||
dwlConditionMask);
|
|
||||||
}
|
|
||||||
#endif // SG_VERSIONHELPERS_HXX_
|
|
||||||
@@ -23,7 +23,6 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include "strutils.hxx"
|
#include "strutils.hxx"
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ include (SimGearComponent)
|
|||||||
set(HEADERS
|
set(HEADERS
|
||||||
naref.h
|
naref.h
|
||||||
nasal.h
|
nasal.h
|
||||||
iolib.h
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
@@ -27,6 +26,7 @@ set(SOURCES
|
|||||||
vector.c
|
vector.c
|
||||||
code.h
|
code.h
|
||||||
data.h
|
data.h
|
||||||
|
iolib.h
|
||||||
parse.h
|
parse.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -66,6 +66,14 @@ namespace nasal
|
|||||||
void GhostMetadata::addDerived(const GhostMetadata* derived)
|
void GhostMetadata::addDerived(const GhostMetadata* derived)
|
||||||
{
|
{
|
||||||
assert(derived);
|
assert(derived);
|
||||||
|
|
||||||
|
SG_LOG
|
||||||
|
(
|
||||||
|
SG_NASAL,
|
||||||
|
SG_INFO,
|
||||||
|
"Ghost::addDerived: " << _name_strong << " -> "
|
||||||
|
<< derived->_name_strong
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -39,12 +39,6 @@ static void runNumTests( double (TestContext::*test_double)(const std::string&),
|
|||||||
BOOST_CHECK_EQUAL((c.*test_int)("0x755"), 0x755);
|
BOOST_CHECK_EQUAL((c.*test_int)("0x755"), 0x755);
|
||||||
BOOST_CHECK_EQUAL((c.*test_int)("0x055"), 0x55);
|
BOOST_CHECK_EQUAL((c.*test_int)("0x055"), 0x55);
|
||||||
BOOST_CHECK_EQUAL((c.*test_int)("-0x155"), -0x155);
|
BOOST_CHECK_EQUAL((c.*test_int)("-0x155"), -0x155);
|
||||||
|
|
||||||
BOOST_CHECK_CLOSE((c.*test_double)("2.000000953656983160"),
|
|
||||||
2.000000953656983160, 1e-5);
|
|
||||||
/* this value has bit pattern 0x400000007fff6789L,
|
|
||||||
* so will look like a pointer if the endianness is set wrong
|
|
||||||
* (see naref.h, data.h)*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE( parse_num )
|
BOOST_AUTO_TEST_CASE( parse_num )
|
||||||
|
|||||||
@@ -142,9 +142,6 @@ naRef naIOGhost(naContext c, FILE* f)
|
|||||||
return naNewGhost(c, &naIOGhostType, ghost);
|
return naNewGhost(c, &naIOGhostType, ghost);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SG_NASAL_UNRESTRICTED_OPEN
|
|
||||||
// Allows unrestricted file access, which would be a security hole
|
|
||||||
// Replaced by the one in flightgear src/Scripting/NasalSys.cxx
|
|
||||||
static naRef f_open(naContext c, naRef me, int argc, naRef* args)
|
static naRef f_open(naContext c, naRef me, int argc, naRef* args)
|
||||||
{
|
{
|
||||||
FILE* f;
|
FILE* f;
|
||||||
@@ -155,7 +152,6 @@ static naRef f_open(naContext c, naRef me, int argc, naRef* args)
|
|||||||
if(!f) naRuntimeError(c, strerror(errno));
|
if(!f) naRuntimeError(c, strerror(errno));
|
||||||
return naIOGhost(c, f);
|
return naIOGhost(c, f);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// frees buffer before tossing an error
|
// frees buffer before tossing an error
|
||||||
static int getcguard(naContext ctx, FILE* f, void* buf)
|
static int getcguard(naContext ctx, FILE* f, void* buf)
|
||||||
@@ -248,9 +244,7 @@ static naCFuncItem funcs[] = {
|
|||||||
{ "seek", f_seek },
|
{ "seek", f_seek },
|
||||||
{ "tell", f_tell },
|
{ "tell", f_tell },
|
||||||
{ "flush", f_flush },
|
{ "flush", f_flush },
|
||||||
#if SG_NASAL_UNRESTRICTED_OPEN
|
|
||||||
{ "open", f_open },
|
{ "open", f_open },
|
||||||
#endif
|
|
||||||
{ "readln", f_readln },
|
{ "readln", f_readln },
|
||||||
{ "stat", f_stat },
|
{ "stat", f_stat },
|
||||||
{ 0 }
|
{ 0 }
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
#ifndef _IOLIB_H
|
#ifndef _IOLIB_H
|
||||||
#define _IOLIB_H
|
#define _IOLIB_H
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "nasal.h"
|
#include "nasal.h"
|
||||||
|
|
||||||
@@ -36,7 +33,5 @@ extern struct naIOType naStdIOType;
|
|||||||
|
|
||||||
// Defined in iolib.c, there is no "library" header to put this in
|
// Defined in iolib.c, there is no "library" header to put this in
|
||||||
naRef naIOGhost(naContext c, FILE* f);
|
naRef naIOGhost(naContext c, FILE* f);
|
||||||
#ifdef __cplusplus
|
|
||||||
} // extern "C"
|
|
||||||
#endif
|
|
||||||
#endif // _IOLIB_H
|
#endif // _IOLIB_H
|
||||||
|
|||||||
+15
-18
@@ -1,31 +1,28 @@
|
|||||||
#ifndef _NAREF_H
|
#ifndef _NAREF_H
|
||||||
#define _NAREF_H
|
#define _NAREF_H
|
||||||
|
|
||||||
|
/* Rather than play elaborate and complicated games with
|
||||||
|
* platform-dependent endianness headers, just detect the platforms we
|
||||||
|
* support. This list is simpler and smaller, yet still quite
|
||||||
|
* complete. */
|
||||||
#if (defined(__x86_64) && defined(__linux__)) || defined(__sparcv9) || \
|
#if (defined(__x86_64) && defined(__linux__)) || defined(__sparcv9) || \
|
||||||
defined(__powerpc64__)
|
defined(__powerpc64__)
|
||||||
/* NASAL_NAN64 mode requires 64 bit pointers that only use the
|
/* Win64 and Irix should work with this too, but have not been
|
||||||
* lower 48 bits; Win64 and Irix should work with this too, but
|
* tested */
|
||||||
* have not been tested */
|
|
||||||
# define NASAL_NAN64
|
# define NASAL_NAN64
|
||||||
#elif defined(__BYTE_ORDER__)
|
#elif defined(_M_IX86) || defined(i386) || defined(__x86_64) || \
|
||||||
/* GCC and Clang define these (as a builtin, while
|
|
||||||
* __LITTLE_ENDIAN__ requires a header), MSVC doesn't */
|
|
||||||
# if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
|
|
||||||
# define NASAL_LE
|
|
||||||
# elif __BYTE_ORDER__==__ORDER_BIG_ENDIAN__
|
|
||||||
# define NASAL_BE
|
|
||||||
# else
|
|
||||||
# error Unrecognized endianness
|
|
||||||
# endif
|
|
||||||
#elif defined(_M_IX86) || defined(__i386) || defined(__x86_64) || \
|
|
||||||
defined(__ia64__) || defined(_M_IA64) || defined(__ARMEL__) || \
|
defined(__ia64__) || defined(_M_IA64) || defined(__ARMEL__) || \
|
||||||
defined(_M_X64) || defined(_M_ARM)
|
defined(_M_X64) || defined(__alpha__) || \
|
||||||
|
(defined(__sh__) && defined(__LITTLE_ENDIAN__))
|
||||||
# define NASAL_LE
|
# define NASAL_LE
|
||||||
#elif defined(__sparc) || defined(__ARMEB__) || \
|
#elif defined(__sparc) || defined(__ppc__) || defined(__PPC) || \
|
||||||
defined(__hppa__) || defined(__s390__) || defined(__s390x__)
|
defined (__powerpc__) || defined (__powerpc64__) || defined (__alpha__) || \
|
||||||
|
defined(__mips) || defined(__ARMEB__) || \
|
||||||
|
defined(__hppa__) || defined(__s390__) || defined(__s390x__) || \
|
||||||
|
(defined(__sh__) && !defined(__LITTLE_ENDIAN__))
|
||||||
# define NASAL_BE
|
# define NASAL_BE
|
||||||
#else
|
#else
|
||||||
# error Unknown endianness
|
# error Unrecognized CPU architecture
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
|
|||||||
@@ -26,15 +26,3 @@ if(ENABLE_PKGUTIL)
|
|||||||
add_executable(sg_pkgutil pkgutil.cxx)
|
add_executable(sg_pkgutil pkgutil.cxx)
|
||||||
target_link_libraries(sg_pkgutil ${TEST_LIBS})
|
target_link_libraries(sg_pkgutil ${TEST_LIBS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(ENABLE_TESTS)
|
|
||||||
|
|
||||||
add_executable(catalog_test CatalogTest.cxx)
|
|
||||||
target_link_libraries(catalog_test ${TEST_LIBS})
|
|
||||||
|
|
||||||
set_target_properties(catalog_test PROPERTIES
|
|
||||||
COMPILE_DEFINITIONS "SRC_DIR=\"${CMAKE_CURRENT_SOURCE_DIR}\"" )
|
|
||||||
|
|
||||||
add_test(catalog_test ${EXECUTABLE_OUTPUT_PATH}/catalog_test)
|
|
||||||
|
|
||||||
endif(ENABLE_TESTS)
|
|
||||||
+60
-189
@@ -31,56 +31,12 @@
|
|||||||
#include <simgear/package/Package.hxx>
|
#include <simgear/package/Package.hxx>
|
||||||
#include <simgear/package/Root.hxx>
|
#include <simgear/package/Root.hxx>
|
||||||
#include <simgear/package/Install.hxx>
|
#include <simgear/package/Install.hxx>
|
||||||
#include <simgear/misc/strutils.hxx>
|
|
||||||
|
|
||||||
namespace simgear {
|
namespace simgear {
|
||||||
|
|
||||||
namespace pkg {
|
namespace pkg {
|
||||||
|
|
||||||
bool checkVersion(const std::string& aVersion, SGPropertyNode_ptr props)
|
CatalogList static_catalogs;
|
||||||
{
|
|
||||||
BOOST_FOREACH(SGPropertyNode* v, props->getChildren("version")) {
|
|
||||||
std::string s(v->getStringValue());
|
|
||||||
if (s == aVersion) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// examine each dot-seperated component in turn, supporting a wildcard
|
|
||||||
// in the versions from the catalog.
|
|
||||||
string_list appVersionParts = simgear::strutils::split(aVersion, ".");
|
|
||||||
string_list catVersionParts = simgear::strutils::split(s, ".");
|
|
||||||
|
|
||||||
size_t partCount = appVersionParts.size();
|
|
||||||
if (partCount != catVersionParts.size()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ok = true;
|
|
||||||
for (unsigned int p=0; p < partCount; ++p) {
|
|
||||||
if (catVersionParts[p] == "*") {
|
|
||||||
// always passes
|
|
||||||
} else if (appVersionParts[p] != catVersionParts[p]) {
|
|
||||||
ok = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ok) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string redirectUrlForVersion(const std::string& aVersion, SGPropertyNode_ptr props)
|
|
||||||
{
|
|
||||||
BOOST_FOREACH(SGPropertyNode* v, props->getChildren("alternate-version")) {
|
|
||||||
if (v->getStringValue("version") == aVersion) {
|
|
||||||
return v->getStringValue("url");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::string();
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -91,8 +47,6 @@ public:
|
|||||||
HTTP::Request(aUrl),
|
HTTP::Request(aUrl),
|
||||||
m_owner(aOwner)
|
m_owner(aOwner)
|
||||||
{
|
{
|
||||||
// refreshing
|
|
||||||
m_owner->changeStatus(Delegate::STATUS_IN_PROGRESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -104,13 +58,8 @@ protected:
|
|||||||
virtual void onDone()
|
virtual void onDone()
|
||||||
{
|
{
|
||||||
if (responseCode() != 200) {
|
if (responseCode() != 200) {
|
||||||
Delegate::StatusCode code = Delegate::FAIL_DOWNLOAD;
|
SG_LOG(SG_GENERAL, SG_ALERT, "catalog download failure:" << m_owner->url());
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "catalog download failure:" << m_owner->url()
|
m_owner->refreshComplete(Delegate::FAIL_DOWNLOAD);
|
||||||
<< "\n\t" << responseCode());
|
|
||||||
if (responseCode() == 404) {
|
|
||||||
code = Delegate::FAIL_NOT_FOUND;
|
|
||||||
}
|
|
||||||
m_owner->refreshComplete(code);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,35 +74,13 @@ protected:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_owner->root()->catalogVersion() != props->getIntValue("catalog-version")) {
|
std::string ver(m_owner->root()->catalogVersion());
|
||||||
SG_LOG(SG_GENERAL, SG_WARN, "catalog:" << m_owner->url() << " is not version "
|
|
||||||
<< m_owner->root()->catalogVersion());
|
|
||||||
m_owner->refreshComplete(Delegate::FAIL_VERSION);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::string ver(m_owner->root()->applicationVersion());
|
|
||||||
if (!checkVersion(ver, props)) {
|
if (!checkVersion(ver, props)) {
|
||||||
SG_LOG(SG_GENERAL, SG_WARN, "downloaded catalog " << m_owner->url() << ", version mismatch:\n\t"
|
SG_LOG(SG_GENERAL, SG_WARN, "downloaded catalog " << m_owner->url() << ", version mismatch:\n\t"
|
||||||
<< props->getStringValue("version") << " vs required " << ver);
|
<< props->getStringValue("version") << " vs required " << ver);
|
||||||
|
|
||||||
// check for a version redirect entry
|
|
||||||
std::string url = redirectUrlForVersion(ver, props);
|
|
||||||
if (!url.empty()) {
|
|
||||||
SG_LOG(SG_GENERAL, SG_WARN, "redirecting from " << m_owner->url() <<
|
|
||||||
" to \n\t" << url);
|
|
||||||
|
|
||||||
// update the URL and kick off a new request
|
|
||||||
m_owner->m_url = url;
|
|
||||||
Downloader* dl = new Downloader(m_owner, url);
|
|
||||||
m_owner->root()->makeHTTPRequest(dl);
|
|
||||||
} else {
|
|
||||||
m_owner->refreshComplete(Delegate::FAIL_VERSION);
|
m_owner->refreshComplete(Delegate::FAIL_VERSION);
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} // of version check failed
|
}
|
||||||
|
|
||||||
// cache the catalog data, now we have a valid install root
|
// cache the catalog data, now we have a valid install root
|
||||||
Dir d(m_owner->installRoot());
|
Dir d(m_owner->installRoot());
|
||||||
@@ -165,10 +92,19 @@ protected:
|
|||||||
|
|
||||||
time(&m_owner->m_retrievedTime);
|
time(&m_owner->m_retrievedTime);
|
||||||
m_owner->writeTimestamp();
|
m_owner->writeTimestamp();
|
||||||
m_owner->refreshComplete(Delegate::STATUS_REFRESHED);
|
m_owner->refreshComplete(Delegate::FAIL_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool checkVersion(const std::string& aVersion, SGPropertyNode* aProps)
|
||||||
|
{
|
||||||
|
BOOST_FOREACH(SGPropertyNode* v, aProps->getChildren("version")) {
|
||||||
|
if (v->getStringValue() == aVersion) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
CatalogRef m_owner;
|
CatalogRef m_owner;
|
||||||
std::string m_buffer;
|
std::string m_buffer;
|
||||||
@@ -176,22 +112,31 @@ private:
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
CatalogList Catalog::allCatalogs()
|
||||||
|
{
|
||||||
|
return static_catalogs;
|
||||||
|
}
|
||||||
|
|
||||||
Catalog::Catalog(Root *aRoot) :
|
Catalog::Catalog(Root *aRoot) :
|
||||||
m_root(aRoot),
|
m_root(aRoot),
|
||||||
m_status(Delegate::FAIL_UNKNOWN),
|
|
||||||
m_retrievedTime(0)
|
m_retrievedTime(0)
|
||||||
{
|
{
|
||||||
|
static_catalogs.push_back(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Catalog::~Catalog()
|
Catalog::~Catalog()
|
||||||
{
|
{
|
||||||
|
CatalogList::iterator it = std::find(static_catalogs.begin(), static_catalogs.end(), this);
|
||||||
|
static_catalogs.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
CatalogRef Catalog::createFromUrl(Root* aRoot, const std::string& aUrl)
|
CatalogRef Catalog::createFromUrl(Root* aRoot, const std::string& aUrl)
|
||||||
{
|
{
|
||||||
CatalogRef c = new Catalog(aRoot);
|
CatalogRef c = new Catalog(aRoot);
|
||||||
c->m_url = aUrl;
|
c->m_url = aUrl;
|
||||||
c->refresh();
|
Downloader* dl = new Downloader(c, aUrl);
|
||||||
|
aRoot->makeHTTPRequest(dl);
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,13 +156,10 @@ CatalogRef Catalog::createFromPath(Root* aRoot, const SGPath& aPath)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool versionCheckOk = checkVersion(aRoot->applicationVersion(), props);
|
if (props->getStringValue("version") != aRoot->catalogVersion()) {
|
||||||
|
SG_LOG(SG_GENERAL, SG_WARN, "skipping catalog at " << aPath << ", version mismatch:\n\t"
|
||||||
if (!versionCheckOk) {
|
<< props->getStringValue("version") << " vs required " << aRoot->catalogVersion());
|
||||||
SG_LOG(SG_GENERAL, SG_INFO, "catalog at:" << aPath << " failed version check: need" << aRoot->applicationVersion());
|
return NULL;
|
||||||
// keep the catalog but mark it as needing an update
|
|
||||||
} else {
|
|
||||||
SG_LOG(SG_GENERAL, SG_DEBUG, "creating catalog from:" << aPath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CatalogRef c = new Catalog(aRoot);
|
CatalogRef c = new Catalog(aRoot);
|
||||||
@@ -225,43 +167,9 @@ CatalogRef Catalog::createFromPath(Root* aRoot, const SGPath& aPath)
|
|||||||
c->parseProps(props);
|
c->parseProps(props);
|
||||||
c->parseTimestamp();
|
c->parseTimestamp();
|
||||||
|
|
||||||
if (versionCheckOk) {
|
|
||||||
// parsed XML ok, mark status as valid
|
|
||||||
c->changeStatus(Delegate::STATUS_SUCCESS);
|
|
||||||
} else {
|
|
||||||
c->changeStatus(Delegate::FAIL_VERSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Catalog::uninstall()
|
|
||||||
{
|
|
||||||
bool ok;
|
|
||||||
bool atLeastOneFailure = false;
|
|
||||||
|
|
||||||
BOOST_FOREACH(PackageRef p, installedPackages()) {
|
|
||||||
ok = p->existingInstall()->uninstall();
|
|
||||||
if (!ok) {
|
|
||||||
SG_LOG(SG_GENERAL, SG_WARN, "uninstall of package " <<
|
|
||||||
p->id() << " failed");
|
|
||||||
// continue trying other packages, bailing out here
|
|
||||||
// gains us nothing
|
|
||||||
atLeastOneFailure = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Dir d(m_installRoot);
|
|
||||||
ok = d.remove(true /* recursive */);
|
|
||||||
if (!ok) {
|
|
||||||
atLeastOneFailure = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
changeStatus(atLeastOneFailure ? Delegate::FAIL_FILESYSTEM
|
|
||||||
: Delegate::STATUS_SUCCESS);
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
PackageList const&
|
PackageList const&
|
||||||
Catalog::packages() const
|
Catalog::packages() const
|
||||||
{
|
{
|
||||||
@@ -308,30 +216,29 @@ Catalog::installedPackages() const
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Catalog::refresh()
|
InstallRef Catalog::installForPackage(PackageRef pkg) const
|
||||||
{
|
{
|
||||||
if (m_refreshRequest.valid()) {
|
PackageInstallDict::const_iterator it = m_installed.find(pkg);
|
||||||
// refresh in progress
|
if (it == m_installed.end()) {
|
||||||
return;
|
// check if it exists on disk, create
|
||||||
|
|
||||||
|
SGPath p(pkg->pathOnDisk());
|
||||||
|
if (p.exists()) {
|
||||||
|
return Install::createFromPath(p, CatalogRef(const_cast<Catalog*>(this)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Downloader* dl = new Downloader(this, url());
|
return NULL;
|
||||||
m_refreshRequest = dl;
|
}
|
||||||
// will update status to IN_PROGRESS
|
|
||||||
m_root->makeHTTPRequest(dl);
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FindById
|
void Catalog::refresh()
|
||||||
{
|
{
|
||||||
FindById(const std::string &id) : m_id(id) {}
|
Downloader* dl = new Downloader(this, url());
|
||||||
|
m_root->makeHTTPRequest(dl);
|
||||||
bool operator()(const PackageRef& ref) const
|
m_root->catalogRefreshBegin(this);
|
||||||
{
|
}
|
||||||
return ref->id() == m_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string m_id;
|
|
||||||
};
|
|
||||||
|
|
||||||
void Catalog::parseProps(const SGPropertyNode* aProps)
|
void Catalog::parseProps(const SGPropertyNode* aProps)
|
||||||
{
|
{
|
||||||
@@ -346,14 +253,8 @@ void Catalog::parseProps(const SGPropertyNode* aProps)
|
|||||||
for (int i = 0; i < nChildren; i++) {
|
for (int i = 0; i < nChildren; i++) {
|
||||||
const SGPropertyNode* pkgProps = aProps->getChild(i);
|
const SGPropertyNode* pkgProps = aProps->getChild(i);
|
||||||
if (strcmp(pkgProps->getName(), "package") == 0) {
|
if (strcmp(pkgProps->getName(), "package") == 0) {
|
||||||
// can't use getPackageById here becuase the variant dict isn't
|
PackageRef p = getPackageById(pkgProps->getStringValue("id"));
|
||||||
// built yet. Instead we need to look at m_packages directly.
|
if (p) {
|
||||||
|
|
||||||
PackageList::iterator pit = std::find_if(m_packages.begin(), m_packages.end(),
|
|
||||||
FindById(pkgProps->getStringValue("id")));
|
|
||||||
PackageRef p;
|
|
||||||
if (pit != m_packages.end()) {
|
|
||||||
p = *pit;
|
|
||||||
// existing package
|
// existing package
|
||||||
p->updateFromProps(pkgProps);
|
p->updateFromProps(pkgProps);
|
||||||
orphans.erase(p); // not an orphan
|
orphans.erase(p); // not an orphan
|
||||||
@@ -411,23 +312,11 @@ PackageRef Catalog::getPackageById(const std::string& aId) const
|
|||||||
// works as expected.
|
// works as expected.
|
||||||
PackageWeakMap::const_iterator it = m_variantDict.find(aId);
|
PackageWeakMap::const_iterator it = m_variantDict.find(aId);
|
||||||
if (it == m_variantDict.end())
|
if (it == m_variantDict.end())
|
||||||
return PackageRef();
|
return NULL;
|
||||||
|
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
PackageRef Catalog::getPackageByPath(const std::string& aPath) const
|
|
||||||
{
|
|
||||||
PackageList::const_iterator it;
|
|
||||||
for (it = m_packages.begin(); it != m_packages.end(); ++it) {
|
|
||||||
if ((*it)->dirName() == aPath) {
|
|
||||||
return *it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return PackageRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Catalog::id() const
|
std::string Catalog::id() const
|
||||||
{
|
{
|
||||||
return m_props->getStringValue("id");
|
return m_props->getStringValue("id");
|
||||||
@@ -438,11 +327,6 @@ std::string Catalog::url() const
|
|||||||
return m_url;
|
return m_url;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Catalog::name() const
|
|
||||||
{
|
|
||||||
return getLocalisedString(m_props, "name");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Catalog::description() const
|
std::string Catalog::description() const
|
||||||
{
|
{
|
||||||
return getLocalisedString(m_props, "description");
|
return getLocalisedString(m_props, "description");
|
||||||
@@ -479,21 +363,12 @@ unsigned int Catalog::ageInSeconds() const
|
|||||||
|
|
||||||
bool Catalog::needsRefresh() const
|
bool Catalog::needsRefresh() const
|
||||||
{
|
{
|
||||||
// always refresh in these cases
|
|
||||||
if ((m_status == Delegate::FAIL_VERSION) || (m_status == Delegate::FAIL_DOWNLOAD)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int maxAge = m_props->getIntValue("max-age-sec", m_root->maxAgeSeconds());
|
unsigned int maxAge = m_props->getIntValue("max-age-sec", m_root->maxAgeSeconds());
|
||||||
return (ageInSeconds() > maxAge);
|
return (ageInSeconds() > maxAge);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Catalog::getLocalisedString(const SGPropertyNode* aRoot, const char* aName) const
|
std::string Catalog::getLocalisedString(const SGPropertyNode* aRoot, const char* aName) const
|
||||||
{
|
{
|
||||||
if (!aRoot) {
|
|
||||||
return std::string();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aRoot->hasChild(m_root->getLocale())) {
|
if (aRoot->hasChild(m_root->getLocale())) {
|
||||||
const SGPropertyNode* localeRoot = aRoot->getChild(m_root->getLocale().c_str());
|
const SGPropertyNode* localeRoot = aRoot->getChild(m_root->getLocale().c_str());
|
||||||
if (localeRoot->hasChild(aName)) {
|
if (localeRoot->hasChild(aName)) {
|
||||||
@@ -504,31 +379,27 @@ std::string Catalog::getLocalisedString(const SGPropertyNode* aRoot, const char*
|
|||||||
return aRoot->getStringValue(aName);
|
return aRoot->getStringValue(aName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Catalog::refreshComplete(Delegate::StatusCode aReason)
|
void Catalog::refreshComplete(Delegate::FailureCode aReason)
|
||||||
{
|
{
|
||||||
changeStatus(aReason);
|
m_root->catalogRefreshComplete(this, aReason);
|
||||||
m_refreshRequest.reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Catalog::changeStatus(Delegate::StatusCode newStatus)
|
void Catalog::registerInstall(Install* ins)
|
||||||
{
|
{
|
||||||
if (m_status == newStatus) {
|
if (!ins || ins->package()->catalog() != this) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_status = newStatus;
|
m_installed[ins->package()] = ins;
|
||||||
m_root->catalogRefreshStatus(this, newStatus);
|
|
||||||
m_statusCallbacks(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Catalog::addStatusCallback(const Callback& cb)
|
void Catalog::unregisterInstall(Install* ins)
|
||||||
{
|
{
|
||||||
m_statusCallbacks.push_back(cb);
|
if (!ins || ins->package()->catalog() != this) {
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Delegate::StatusCode Catalog::status() const
|
m_installed.erase(ins->package());
|
||||||
{
|
|
||||||
return m_status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // of namespace pkg
|
} // of namespace pkg
|
||||||
|
|||||||
+12
-30
@@ -22,15 +22,11 @@
|
|||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include <boost/bind.hpp>
|
|
||||||
|
|
||||||
#include <simgear/misc/sg_path.hxx>
|
#include <simgear/misc/sg_path.hxx>
|
||||||
#include <simgear/props/props.hxx>
|
#include <simgear/props/props.hxx>
|
||||||
|
|
||||||
#include <simgear/structure/SGReferenced.hxx>
|
#include <simgear/structure/SGReferenced.hxx>
|
||||||
#include <simgear/structure/SGSharedPtr.hxx>
|
#include <simgear/structure/SGSharedPtr.hxx>
|
||||||
#include <simgear/structure/function_list.hxx>
|
|
||||||
#include <simgear/io/HTTPRequest.hxx>
|
|
||||||
|
|
||||||
#include <simgear/package/Delegate.hxx>
|
#include <simgear/package/Delegate.hxx>
|
||||||
|
|
||||||
@@ -64,14 +60,11 @@ public:
|
|||||||
|
|
||||||
static CatalogRef createFromPath(Root* aRoot, const SGPath& aPath);
|
static CatalogRef createFromPath(Root* aRoot, const SGPath& aPath);
|
||||||
|
|
||||||
|
static CatalogList allCatalogs();
|
||||||
|
|
||||||
Root* root() const
|
Root* root() const
|
||||||
{ return m_root;};
|
{ return m_root;};
|
||||||
|
|
||||||
/**
|
|
||||||
* uninstall this catalog entirely, including all installed packages
|
|
||||||
*/
|
|
||||||
bool uninstall();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* perform a refresh of the catalog contents
|
* perform a refresh of the catalog contents
|
||||||
*/
|
*/
|
||||||
@@ -106,13 +99,11 @@ public:
|
|||||||
|
|
||||||
std::string url() const;
|
std::string url() const;
|
||||||
|
|
||||||
std::string name() const;
|
|
||||||
|
|
||||||
std::string description() const;
|
std::string description() const;
|
||||||
|
|
||||||
PackageRef getPackageById(const std::string& aId) const;
|
PackageRef getPackageById(const std::string& aId) const;
|
||||||
|
|
||||||
PackageRef getPackageByPath(const std::string& aPath) const;
|
InstallRef installForPackage(PackageRef pkg) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test if the catalog data was retrieved longer ago than the
|
* test if the catalog data was retrieved longer ago than the
|
||||||
@@ -126,41 +117,29 @@ public:
|
|||||||
* access the raw property data in the catalog
|
* access the raw property data in the catalog
|
||||||
*/
|
*/
|
||||||
SGPropertyNode* properties() const;
|
SGPropertyNode* properties() const;
|
||||||
|
|
||||||
Delegate::StatusCode status() const;
|
|
||||||
|
|
||||||
typedef boost::function<void(Catalog*)> Callback;
|
|
||||||
|
|
||||||
void addStatusCallback(const Callback& cb);
|
|
||||||
|
|
||||||
template<class C>
|
|
||||||
void addStatusCallback(C* instance, void (C::*mem_func)(Catalog*))
|
|
||||||
{
|
|
||||||
return addStatusCallback(boost::bind(mem_func, instance, _1));
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
Catalog(Root* aRoot);
|
Catalog(Root* aRoot);
|
||||||
|
|
||||||
class Downloader;
|
class Downloader;
|
||||||
friend class Downloader;
|
friend class Downloader;
|
||||||
|
|
||||||
|
friend class Install;
|
||||||
|
void registerInstall(Install* ins);
|
||||||
|
void unregisterInstall(Install* ins);
|
||||||
|
|
||||||
void parseProps(const SGPropertyNode* aProps);
|
void parseProps(const SGPropertyNode* aProps);
|
||||||
|
|
||||||
void refreshComplete(Delegate::StatusCode aReason);
|
void refreshComplete(Delegate::FailureCode aReason);
|
||||||
|
|
||||||
void parseTimestamp();
|
void parseTimestamp();
|
||||||
void writeTimestamp();
|
void writeTimestamp();
|
||||||
|
|
||||||
std::string getLocalisedString(const SGPropertyNode* aRoot, const char* aName) const;
|
std::string getLocalisedString(const SGPropertyNode* aRoot, const char* aName) const;
|
||||||
|
|
||||||
void changeStatus(Delegate::StatusCode newStatus);
|
|
||||||
|
|
||||||
Root* m_root;
|
Root* m_root;
|
||||||
SGPropertyNode_ptr m_props;
|
SGPropertyNode_ptr m_props;
|
||||||
SGPath m_installRoot;
|
SGPath m_installRoot;
|
||||||
std::string m_url;
|
std::string m_url;
|
||||||
Delegate::StatusCode m_status;
|
|
||||||
HTTP::Request_ptr m_refreshRequest;
|
|
||||||
|
|
||||||
PackageList m_packages;
|
PackageList m_packages;
|
||||||
time_t m_retrievedTime;
|
time_t m_retrievedTime;
|
||||||
@@ -168,7 +147,10 @@ private:
|
|||||||
typedef std::map<std::string, Package*> PackageWeakMap;
|
typedef std::map<std::string, Package*> PackageWeakMap;
|
||||||
PackageWeakMap m_variantDict;
|
PackageWeakMap m_variantDict;
|
||||||
|
|
||||||
function_list<Callback> m_statusCallbacks;
|
// important that this is a weak-ref to Installs,
|
||||||
|
// since it is only cleaned up in the Install destructor
|
||||||
|
typedef std::map<PackageRef, Install*> PackageInstallDict;
|
||||||
|
PackageInstallDict m_installed;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // of namespace pkg
|
} // of namespace pkg
|
||||||
|
|||||||
@@ -1,107 +0,0 @@
|
|||||||
// Copyright (C) 2015 James Turner - zakalawe@mac.com
|
|
||||||
//
|
|
||||||
// This library is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU Library General Public
|
|
||||||
// License as published by the Free Software Foundation; either
|
|
||||||
// version 2 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
|
|
||||||
// Library General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include <simgear_config.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <simgear/misc/test_macros.hxx>
|
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <simgear/package/Catalog.hxx>
|
|
||||||
#include <simgear/package/Root.hxx>
|
|
||||||
#include <simgear/package/Package.hxx>
|
|
||||||
|
|
||||||
#include <simgear/misc/sg_dir.hxx>
|
|
||||||
|
|
||||||
using namespace simgear;
|
|
||||||
|
|
||||||
int parseTest()
|
|
||||||
{
|
|
||||||
SGPath rootPath = simgear::Dir::current().path();
|
|
||||||
rootPath.append("testRoot");
|
|
||||||
pkg::Root* root = new pkg::Root(rootPath, "8.1.12");
|
|
||||||
pkg::CatalogRef cat = pkg::Catalog::createFromPath(root, SGPath(SRC_DIR "/catalogTest1"));
|
|
||||||
|
|
||||||
VERIFY(cat.valid());
|
|
||||||
|
|
||||||
COMPARE(cat->id(), "org.flightgear.test.catalog1");
|
|
||||||
COMPARE(cat->url(), "http://download.flightgear.org/catalog1/catalog.xml");
|
|
||||||
COMPARE(cat->description(), "First test catalog");
|
|
||||||
|
|
||||||
// check the packages too
|
|
||||||
COMPARE(cat->packages().size(), 3);
|
|
||||||
|
|
||||||
pkg::PackageRef p1 = cat->packages().front();
|
|
||||||
COMPARE(p1->catalog(), cat.ptr());
|
|
||||||
|
|
||||||
COMPARE(p1->id(), "alpha");
|
|
||||||
COMPARE(p1->qualifiedId(), "org.flightgear.test.catalog1.alpha");
|
|
||||||
COMPARE(p1->name(), "Alpha package");
|
|
||||||
COMPARE(p1->revision(), 8);
|
|
||||||
COMPARE(p1->fileSizeBytes(), 1234567);
|
|
||||||
|
|
||||||
|
|
||||||
pkg::PackageRef p2 = cat->getPackageById("c172p");
|
|
||||||
VERIFY(p2.valid());
|
|
||||||
COMPARE(p2->qualifiedId(), "org.flightgear.test.catalog1.c172p");
|
|
||||||
COMPARE(p2->description(), "A plane made by Cessna");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// test filtering / searching too
|
|
||||||
string_set tags(p2->tags());
|
|
||||||
COMPARE(tags.size(), 4);
|
|
||||||
VERIFY(tags.find("ifr") != tags.end());
|
|
||||||
VERIFY(tags.find("cessna") != tags.end());
|
|
||||||
VERIFY(tags.find("jet") == tags.end());
|
|
||||||
|
|
||||||
|
|
||||||
SGPropertyNode_ptr queryA(new SGPropertyNode);
|
|
||||||
queryA->setStringValue("tag", "ifr");
|
|
||||||
VERIFY(p2->matches(queryA.ptr()));
|
|
||||||
|
|
||||||
SGPropertyNode_ptr queryB(new SGPropertyNode);
|
|
||||||
queryB->setStringValue("name", "ces");
|
|
||||||
VERIFY(p2->matches(queryB.ptr()));
|
|
||||||
|
|
||||||
SGPropertyNode_ptr queryC(new SGPropertyNode);
|
|
||||||
queryC->setStringValue("name", "foo");
|
|
||||||
VERIFY(!p2->matches(queryC.ptr()));
|
|
||||||
|
|
||||||
SGPropertyNode_ptr queryD(new SGPropertyNode);
|
|
||||||
queryD->setIntValue("rating-FDM", 3);
|
|
||||||
VERIFY(p2->matches(queryD.ptr()));
|
|
||||||
|
|
||||||
SGPropertyNode_ptr queryE(new SGPropertyNode);
|
|
||||||
queryE->setIntValue("rating-model", 5);
|
|
||||||
queryE->setStringValue("description", "cessna");
|
|
||||||
VERIFY(p2->matches(queryE.ptr()));
|
|
||||||
|
|
||||||
|
|
||||||
delete root;
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
|
||||||
{
|
|
||||||
parseTest();
|
|
||||||
std::cout << "Successfully passed all tests!" << std::endl;
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
@@ -18,9 +18,6 @@
|
|||||||
#ifndef SG_PACKAGE_DELEGATE_HXX
|
#ifndef SG_PACKAGE_DELEGATE_HXX
|
||||||
#define SG_PACKAGE_DELEGATE_HXX
|
#define SG_PACKAGE_DELEGATE_HXX
|
||||||
|
|
||||||
#include <simgear/misc/stdint.hxx>
|
|
||||||
#include <simgear/structure/SGSharedPtr.hxx>
|
|
||||||
|
|
||||||
namespace simgear
|
namespace simgear
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -30,9 +27,6 @@ namespace pkg
|
|||||||
class Install;
|
class Install;
|
||||||
class Catalog;
|
class Catalog;
|
||||||
|
|
||||||
typedef SGSharedPtr<Catalog> CatalogRef;
|
|
||||||
typedef SGSharedPtr<Install> InstallRef;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* package delegate is the mechanism to discover progress / completion /
|
* package delegate is the mechanism to discover progress / completion /
|
||||||
* errors in packaging steps asynchronously.
|
* errors in packaging steps asynchronously.
|
||||||
@@ -41,40 +35,38 @@ class Delegate
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef enum {
|
typedef enum {
|
||||||
STATUS_SUCCESS = 0,
|
FAIL_SUCCESS = 0, ///< not a failure :)
|
||||||
FAIL_UNKNOWN = 1,
|
FAIL_UNKNOWN = 1,
|
||||||
STATUS_IN_PROGRESS, ///< downloading/installation in progress
|
FAIL_IN_PROGRESS, ///< downloading/installation in progress (not a failure :P)
|
||||||
FAIL_CHECKSUM, ///< package MD5 verificstion failed
|
FAIL_CHECKSUM, ///< package MD5 verificstion failed
|
||||||
FAIL_DOWNLOAD, ///< network issue
|
FAIL_DOWNLOAD, ///< network issue
|
||||||
FAIL_EXTRACT, ///< package archive failed to extract cleanly
|
FAIL_EXTRACT, ///< package archive failed to extract cleanly
|
||||||
FAIL_FILESYSTEM, ///< unknown filesystem error occurred
|
FAIL_FILESYSTEM, ///< unknown filesystem error occurred
|
||||||
FAIL_VERSION, ///< version check mismatch
|
FAIL_VERSION ///< version check mismatch
|
||||||
FAIL_NOT_FOUND, ///< package URL returned a 404
|
} FailureCode;
|
||||||
STATUS_REFRESHED,
|
|
||||||
USER_CANCELLED
|
|
||||||
} StatusCode;
|
|
||||||
|
|
||||||
|
|
||||||
virtual ~Delegate() { }
|
virtual ~Delegate() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* invoked when all catalogs have finished refreshing - either successfully
|
||||||
|
* or with a failure.
|
||||||
|
*/
|
||||||
|
virtual void refreshComplete() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* emitted when a catalog refesh completes, either success or failure
|
* emitted when a catalog fails to refresh, due to a network issue or
|
||||||
* If catalog is null, this means /all/ catalogs have been refreshed
|
* some other failure.
|
||||||
*/
|
*/
|
||||||
virtual void catalogRefreshed(CatalogRef, StatusCode aReason) = 0;
|
virtual void failedRefresh(Catalog*, FailureCode aReason) = 0;
|
||||||
|
|
||||||
virtual void startInstall(InstallRef aInstall) = 0;
|
virtual void startInstall(Install* aInstall) = 0;
|
||||||
virtual void installProgress(InstallRef aInstall, unsigned int aBytes, unsigned int aTotal) = 0;
|
virtual void installProgress(Install* aInstall, unsigned int aBytes, unsigned int aTotal) = 0;
|
||||||
virtual void finishInstall(InstallRef aInstall, StatusCode aReason) = 0;
|
virtual void finishInstall(Install* aInstall) = 0;
|
||||||
|
|
||||||
/**
|
|
||||||
* Notification when catalogs/packages are added or removed
|
|
||||||
*/
|
|
||||||
virtual void availablePackagesChanged() {}
|
|
||||||
|
|
||||||
virtual void dataForThumbnail(const std::string& aThumbnailUrl,
|
virtual void failedInstall(Install* aInstall, FailureCode aReason) = 0;
|
||||||
size_t lenth, const uint8_t* bytes) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // of namespace pkg
|
} // of namespace pkg
|
||||||
|
|||||||
+34
-168
@@ -24,7 +24,6 @@
|
|||||||
#include <simgear/package/md5.h>
|
#include <simgear/package/md5.h>
|
||||||
|
|
||||||
#include <simgear/structure/exception.hxx>
|
#include <simgear/structure/exception.hxx>
|
||||||
#include <simgear/props/props_io.hxx>
|
|
||||||
#include <simgear/package/Catalog.hxx>
|
#include <simgear/package/Catalog.hxx>
|
||||||
#include <simgear/package/Package.hxx>
|
#include <simgear/package/Package.hxx>
|
||||||
#include <simgear/package/Root.hxx>
|
#include <simgear/package/Root.hxx>
|
||||||
@@ -46,8 +45,7 @@ class Install::PackageArchiveDownloader : public HTTP::Request
|
|||||||
public:
|
public:
|
||||||
PackageArchiveDownloader(InstallRef aOwner) :
|
PackageArchiveDownloader(InstallRef aOwner) :
|
||||||
HTTP::Request("" /* dummy URL */),
|
HTTP::Request("" /* dummy URL */),
|
||||||
m_owner(aOwner),
|
m_owner(aOwner)
|
||||||
m_downloaded(0)
|
|
||||||
{
|
{
|
||||||
m_urls = m_owner->package()->downloadUrls();
|
m_urls = m_owner->package()->downloadUrls();
|
||||||
if (m_urls.empty()) {
|
if (m_urls.empty()) {
|
||||||
@@ -57,39 +55,10 @@ public:
|
|||||||
// TODO randomise order of m_urls
|
// TODO randomise order of m_urls
|
||||||
|
|
||||||
m_extractPath = aOwner->path().dir();
|
m_extractPath = aOwner->path().dir();
|
||||||
m_extractPath.append("_extract_" + aOwner->package()->md5());
|
m_extractPath.append("_DOWNLOAD"); // add some temporary value
|
||||||
|
|
||||||
// clean up any existing files
|
|
||||||
Dir d(m_extractPath);
|
|
||||||
if (d.exists()) {
|
|
||||||
d.remove(true /* recursive */);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~PackageArchiveDownloader()
|
|
||||||
{
|
|
||||||
// always clean up our extraction dir: if we successfully downloaded
|
|
||||||
// and installed it will be an empty dir, if we failed it might contain
|
|
||||||
// (some) of the package files.
|
|
||||||
Dir d(m_extractPath);
|
|
||||||
if (d.exists()) {
|
|
||||||
d.remove(true /* recursive */);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t downloadedBytes() const
|
|
||||||
{
|
|
||||||
return m_downloaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
int percentDownloaded() const
|
|
||||||
{
|
|
||||||
if (responseLength() <= 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (m_downloaded * 100) / responseLength();
|
|
||||||
}
|
|
||||||
protected:
|
protected:
|
||||||
virtual std::string url() const
|
virtual std::string url() const
|
||||||
{
|
{
|
||||||
@@ -98,8 +67,6 @@ protected:
|
|||||||
|
|
||||||
virtual void responseHeadersComplete()
|
virtual void responseHeadersComplete()
|
||||||
{
|
{
|
||||||
Request::responseHeadersComplete();
|
|
||||||
|
|
||||||
Dir d(m_extractPath);
|
Dir d(m_extractPath);
|
||||||
d.create(0755);
|
d.create(0755);
|
||||||
|
|
||||||
@@ -112,21 +79,14 @@ protected:
|
|||||||
m_buffer += std::string(s, n);
|
m_buffer += std::string(s, n);
|
||||||
SG_MD5Update(&m_md5, (unsigned char*) s, n);
|
SG_MD5Update(&m_md5, (unsigned char*) s, n);
|
||||||
|
|
||||||
m_downloaded = m_buffer.size();
|
|
||||||
m_owner->installProgress(m_buffer.size(), responseLength());
|
m_owner->installProgress(m_buffer.size(), responseLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void onDone()
|
virtual void onDone()
|
||||||
{
|
{
|
||||||
if (responseCode() != 200) {
|
if (responseCode() != 200) {
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "download failure:" << responseCode() <<
|
SG_LOG(SG_GENERAL, SG_ALERT, "download failure");
|
||||||
"\n\t" << url());
|
doFailure(Delegate::FAIL_DOWNLOAD);
|
||||||
Delegate::StatusCode code = Delegate::FAIL_DOWNLOAD;
|
|
||||||
if (responseCode() == 404) {
|
|
||||||
code = Delegate::FAIL_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
doFailure(code);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,16 +111,13 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_owner->path().exists()) {
|
if (m_owner->path().exists()) {
|
||||||
|
//std::cout << "removing existing path" << std::endl;
|
||||||
Dir destDir(m_owner->path());
|
Dir destDir(m_owner->path());
|
||||||
destDir.remove(true /* recursive */);
|
destDir.remove(true /* recursive */);
|
||||||
}
|
}
|
||||||
|
|
||||||
// build a path like /path/to/packages/org.some.catalog/Aircraft/extract_xxxx/MyAircraftDir
|
m_extractPath.append(m_owner->package()->id());
|
||||||
SGPath extractedPath = m_extractPath;
|
bool ok = m_extractPath.rename(m_owner->path());
|
||||||
extractedPath.append(m_owner->package()->dirName());
|
|
||||||
|
|
||||||
// rename it to path/to/packages/org.some.catalog/Aircraft/MyAircraftDir
|
|
||||||
bool ok = extractedPath.rename(m_owner->path());
|
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
doFailure(Delegate::FAIL_FILESYSTEM);
|
doFailure(Delegate::FAIL_FILESYSTEM);
|
||||||
return;
|
return;
|
||||||
@@ -168,18 +125,7 @@ protected:
|
|||||||
|
|
||||||
m_owner->m_revision = m_owner->package()->revision();
|
m_owner->m_revision = m_owner->package()->revision();
|
||||||
m_owner->writeRevisionFile();
|
m_owner->writeRevisionFile();
|
||||||
m_owner->m_download.reset(); // so isDownloading reports false
|
m_owner->installResult(Delegate::FAIL_SUCCESS);
|
||||||
|
|
||||||
m_owner->installResult(Delegate::STATUS_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void onFail()
|
|
||||||
{
|
|
||||||
if (responseCode() == -1) {
|
|
||||||
doFailure(Delegate::USER_CANCELLED);
|
|
||||||
} else {
|
|
||||||
doFailure(Delegate::FAIL_DOWNLOAD);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -282,16 +228,19 @@ private:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void doFailure(Delegate::StatusCode aReason)
|
void doFailure(Delegate::FailureCode aReason)
|
||||||
{
|
{
|
||||||
Dir dir(m_extractPath);
|
Dir dir(m_extractPath);
|
||||||
if (dir.exists()) {
|
|
||||||
dir.remove(true /* recursive */);
|
dir.remove(true /* recursive */);
|
||||||
|
|
||||||
|
if (m_urls.size() == 1) {
|
||||||
|
std::cout << "failure:" << aReason << std::endl;
|
||||||
|
m_owner->installResult(aReason);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO - try other mirrors
|
std::cout << "retrying download" << std::endl;
|
||||||
m_owner->m_download.reset(); // ensure we get cleaned up
|
m_urls.erase(m_urls.begin()); // pop first URL
|
||||||
m_owner->installResult(aReason);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InstallRef m_owner;
|
InstallRef m_owner;
|
||||||
@@ -299,29 +248,30 @@ private:
|
|||||||
SG_MD5_CTX m_md5;
|
SG_MD5_CTX m_md5;
|
||||||
std::string m_buffer;
|
std::string m_buffer;
|
||||||
SGPath m_extractPath;
|
SGPath m_extractPath;
|
||||||
size_t m_downloaded;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
Install::Install(PackageRef aPkg, const SGPath& aPath) :
|
Install::Install(PackageRef aPkg, const SGPath& aPath) :
|
||||||
m_package(aPkg),
|
m_package(aPkg),
|
||||||
m_path(aPath),
|
m_path(aPath),
|
||||||
m_status(Delegate::STATUS_IN_PROGRESS)
|
m_download(NULL),
|
||||||
|
_status(Delegate::FAIL_IN_PROGRESS)
|
||||||
{
|
{
|
||||||
parseRevision();
|
parseRevision();
|
||||||
m_package->catalog()->root()->registerInstall(this);
|
m_package->catalog()->registerInstall(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Install::~Install()
|
Install::~Install()
|
||||||
{
|
{
|
||||||
|
m_package->catalog()->unregisterInstall(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
InstallRef Install::createFromPath(const SGPath& aPath, CatalogRef aCat)
|
InstallRef Install::createFromPath(const SGPath& aPath, CatalogRef aCat)
|
||||||
{
|
{
|
||||||
std::string path = aPath.file();
|
std::string id = aPath.file();
|
||||||
PackageRef pkg = aCat->getPackageByPath(path);
|
PackageRef pkg = aCat->getPackageById(id);
|
||||||
if (!pkg)
|
if (!pkg)
|
||||||
throw sg_exception("no package with path:" + path);
|
throw sg_exception("no package with id:" + id);
|
||||||
|
|
||||||
return new Install(pkg, aPath);
|
return new Install(pkg, aPath);
|
||||||
}
|
}
|
||||||
@@ -363,102 +313,17 @@ void Install::startUpdate()
|
|||||||
m_package->catalog()->root()->startInstall(this);
|
m_package->catalog()->root()->startInstall(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Install::uninstall()
|
void Install::uninstall()
|
||||||
{
|
{
|
||||||
Dir d(m_path);
|
Dir d(m_path);
|
||||||
if (!d.remove(true)) {
|
d.remove(true);
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "package uninstall failed: couldn't remove path " << m_path);
|
m_package->catalog()->unregisterInstall(this);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_package->catalog()->root()->unregisterInstall(this);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Install::isDownloading() const
|
|
||||||
{
|
|
||||||
return (m_download.valid());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Install::isQueued() const
|
|
||||||
{
|
|
||||||
return m_package->catalog()->root()->isInstallQueued(const_cast<Install*>(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
int Install::downloadedPercent() const
|
|
||||||
{
|
|
||||||
if (!m_download.valid()) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
PackageArchiveDownloader* dl = static_cast<PackageArchiveDownloader*>(m_download.get());
|
|
||||||
return dl->percentDownloaded();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t Install::downloadedBytes() const
|
|
||||||
{
|
|
||||||
if (!m_download.valid()) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
PackageArchiveDownloader* dl = static_cast<PackageArchiveDownloader*>(m_download.get());
|
|
||||||
return dl->downloadedBytes();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Install::cancelDownload()
|
|
||||||
{
|
|
||||||
if (m_download.valid()) {
|
|
||||||
m_download->abort("User cancelled download");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_revision == 0) {
|
|
||||||
SG_LOG(SG_GENERAL, SG_INFO, "cancel install of package, will unregister");
|
|
||||||
m_package->catalog()->root()->unregisterInstall(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_package->catalog()->root()->cancelDownload(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct PathAppender
|
|
||||||
{
|
|
||||||
PathAppender(const SGPath& p) : m_path(p) {}
|
|
||||||
|
|
||||||
SGPath operator()(const std::string& s) const
|
|
||||||
{
|
|
||||||
SGPath p(m_path);
|
|
||||||
p.append(s);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
SGPath m_path;
|
|
||||||
};
|
|
||||||
|
|
||||||
PathList Install::thumbnailPaths() const
|
|
||||||
{
|
|
||||||
const string_list& thumbs(m_package->thumbnails());
|
|
||||||
PathList result;
|
|
||||||
if (thumbs.empty())
|
|
||||||
return result;
|
|
||||||
|
|
||||||
std::transform(thumbs.begin(), thumbs.end(),
|
|
||||||
std::back_inserter(result),
|
|
||||||
PathAppender(m_path));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
SGPath Install::primarySetPath() const
|
|
||||||
{
|
|
||||||
SGPath setPath(m_path);
|
|
||||||
std::string ps(m_package->id());
|
|
||||||
setPath.append(ps + "-set.xml");
|
|
||||||
return setPath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
Install* Install::done(const Callback& cb)
|
Install* Install::done(const Callback& cb)
|
||||||
{
|
{
|
||||||
if( m_status == Delegate::STATUS_SUCCESS )
|
if( _status == Delegate::FAIL_SUCCESS )
|
||||||
cb(this);
|
cb(this);
|
||||||
else
|
else
|
||||||
_cb_done.push_back(cb);
|
_cb_done.push_back(cb);
|
||||||
@@ -469,8 +334,8 @@ Install* Install::done(const Callback& cb)
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
Install* Install::fail(const Callback& cb)
|
Install* Install::fail(const Callback& cb)
|
||||||
{
|
{
|
||||||
if( m_status != Delegate::STATUS_SUCCESS
|
if( _status != Delegate::FAIL_SUCCESS
|
||||||
&& m_status != Delegate::STATUS_IN_PROGRESS )
|
&& _status != Delegate::FAIL_IN_PROGRESS )
|
||||||
cb(this);
|
cb(this);
|
||||||
else
|
else
|
||||||
_cb_fail.push_back(cb);
|
_cb_fail.push_back(cb);
|
||||||
@@ -481,7 +346,7 @@ Install* Install::fail(const Callback& cb)
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
Install* Install::always(const Callback& cb)
|
Install* Install::always(const Callback& cb)
|
||||||
{
|
{
|
||||||
if( m_status != Delegate::STATUS_IN_PROGRESS )
|
if( _status != Delegate::FAIL_IN_PROGRESS )
|
||||||
cb(this);
|
cb(this);
|
||||||
else
|
else
|
||||||
_cb_always.push_back(cb);
|
_cb_always.push_back(cb);
|
||||||
@@ -497,12 +362,13 @@ Install* Install::progress(const ProgressCallback& cb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void Install::installResult(Delegate::StatusCode aReason)
|
void Install::installResult(Delegate::FailureCode aReason)
|
||||||
{
|
{
|
||||||
m_package->catalog()->root()->finishInstall(this, aReason);
|
if (aReason == Delegate::FAIL_SUCCESS) {
|
||||||
if (aReason == Delegate::STATUS_SUCCESS) {
|
m_package->catalog()->root()->finishInstall(this);
|
||||||
_cb_done(this);
|
_cb_done(this);
|
||||||
} else {
|
} else {
|
||||||
|
m_package->catalog()->root()->failedInstall(this, aReason);
|
||||||
_cb_fail(this);
|
_cb_fail(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,13 +21,11 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <simgear/misc/sg_path.hxx>
|
#include <simgear/misc/sg_path.hxx>
|
||||||
#include <simgear/misc/sg_dir.hxx>
|
|
||||||
#include <simgear/package/Delegate.hxx>
|
#include <simgear/package/Delegate.hxx>
|
||||||
|
|
||||||
#include <simgear/structure/function_list.hxx>
|
#include <simgear/structure/function_list.hxx>
|
||||||
#include <simgear/structure/SGReferenced.hxx>
|
#include <simgear/structure/SGReferenced.hxx>
|
||||||
#include <simgear/structure/SGSharedPtr.hxx>
|
#include <simgear/structure/SGSharedPtr.hxx>
|
||||||
#include <simgear/io/HTTPRequest.hxx>
|
|
||||||
|
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
|
|
||||||
@@ -76,34 +74,7 @@ public:
|
|||||||
|
|
||||||
void startUpdate();
|
void startUpdate();
|
||||||
|
|
||||||
bool uninstall();
|
void uninstall();
|
||||||
|
|
||||||
bool isDownloading() const;
|
|
||||||
|
|
||||||
bool isQueued() const;
|
|
||||||
|
|
||||||
int downloadedPercent() const;
|
|
||||||
|
|
||||||
size_t downloadedBytes() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* full path to the primary -set.xml file for this install
|
|
||||||
*/
|
|
||||||
SGPath primarySetPath() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* if a download is in progress, cancel it. If this is the first install
|
|
||||||
* of the package (as opposed to an update), the install will be cleaned
|
|
||||||
* up once the last reference is gone.
|
|
||||||
*/
|
|
||||||
void cancelDownload();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return the thumbnails associated with this install, but as locations
|
|
||||||
* on the file system, not URLs. It is assumed the order of thumbnails
|
|
||||||
* is consistent with the URLs returned from Package::thumbnailUrls()
|
|
||||||
*/
|
|
||||||
PathList thumbnailPaths() const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the handler to be called when the installation successfully
|
* Set the handler to be called when the installation successfully
|
||||||
@@ -174,16 +145,16 @@ private:
|
|||||||
void parseRevision();
|
void parseRevision();
|
||||||
void writeRevisionFile();
|
void writeRevisionFile();
|
||||||
|
|
||||||
void installResult(Delegate::StatusCode aReason);
|
void installResult(Delegate::FailureCode aReason);
|
||||||
void installProgress(unsigned int aBytes, unsigned int aTotal);
|
void installProgress(unsigned int aBytes, unsigned int aTotal);
|
||||||
|
|
||||||
PackageRef m_package;
|
PackageRef m_package;
|
||||||
unsigned int m_revision; ///< revision on disk
|
unsigned int m_revision; ///< revision on disk
|
||||||
SGPath m_path; ///< installation point on disk
|
SGPath m_path; ///< installation point on disk
|
||||||
|
|
||||||
HTTP::Request_ptr m_download;
|
PackageArchiveDownloader* m_download;
|
||||||
|
|
||||||
Delegate::StatusCode m_status;
|
Delegate::FailureCode _status;
|
||||||
|
|
||||||
function_list<Callback> _cb_done,
|
function_list<Callback> _cb_done,
|
||||||
_cb_fail,
|
_cb_fail,
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ SGPath Package::pathOnDisk() const
|
|||||||
{
|
{
|
||||||
SGPath p(m_catalog->installRoot());
|
SGPath p(m_catalog->installRoot());
|
||||||
p.append("Aircraft");
|
p.append("Aircraft");
|
||||||
p.append(dirName());
|
p.append(id());
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,12 +139,7 @@ InstallRef Package::install()
|
|||||||
|
|
||||||
InstallRef Package::existingInstall(const InstallCallback& cb) const
|
InstallRef Package::existingInstall(const InstallCallback& cb) const
|
||||||
{
|
{
|
||||||
InstallRef install;
|
InstallRef install = m_catalog->installForPackage(const_cast<Package*>(this));
|
||||||
try {
|
|
||||||
install = m_catalog->root()->existingInstallForPackage(const_cast<Package*>(this));
|
|
||||||
} catch (std::exception& e) {
|
|
||||||
return InstallRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
if( cb )
|
if( cb )
|
||||||
{
|
{
|
||||||
@@ -167,30 +162,13 @@ std::string Package::qualifiedId() const
|
|||||||
return m_catalog->id() + "." + id();
|
return m_catalog->id() + "." + id();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Package::qualifiedVariantId(const unsigned int variantIndex) const
|
|
||||||
{
|
|
||||||
return m_catalog->id() + "." + variants()[variantIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Package::md5() const
|
std::string Package::md5() const
|
||||||
{
|
{
|
||||||
return m_props->getStringValue("md5");
|
return m_props->getStringValue("md5");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Package::dirName() const
|
|
||||||
{
|
|
||||||
std::string r(m_props->getStringValue("dir"));
|
|
||||||
if (r.empty())
|
|
||||||
throw sg_exception("missing dir property on catalog package entry for " + m_id);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int Package::revision() const
|
unsigned int Package::revision() const
|
||||||
{
|
{
|
||||||
if (!m_props) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_props->getIntValue("revision");
|
return m_props->getIntValue("revision");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,11 +187,6 @@ std::string Package::description() const
|
|||||||
return getLocalisedProp("description");
|
return getLocalisedProp("description");
|
||||||
}
|
}
|
||||||
|
|
||||||
string_set Package::tags() const
|
|
||||||
{
|
|
||||||
return m_tags;
|
|
||||||
}
|
|
||||||
|
|
||||||
SGPropertyNode* Package::properties() const
|
SGPropertyNode* Package::properties() const
|
||||||
{
|
{
|
||||||
return m_props.ptr();
|
return m_props.ptr();
|
||||||
@@ -222,36 +195,15 @@ SGPropertyNode* Package::properties() const
|
|||||||
string_list Package::thumbnailUrls() const
|
string_list Package::thumbnailUrls() const
|
||||||
{
|
{
|
||||||
string_list r;
|
string_list r;
|
||||||
if (!m_props) {
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_FOREACH(SGPropertyNode* dl, m_props->getChildren("thumbnail")) {
|
BOOST_FOREACH(SGPropertyNode* dl, m_props->getChildren("thumbnail")) {
|
||||||
r.push_back(dl->getStringValue());
|
r.push_back(dl->getStringValue());
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
string_list Package::thumbnails() const
|
|
||||||
{
|
|
||||||
string_list r;
|
|
||||||
if (!m_props) {
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_FOREACH(SGPropertyNode* dl, m_props->getChildren("thumbnail-path")) {
|
|
||||||
r.push_back(dl->getStringValue());
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
string_list Package::downloadUrls() const
|
string_list Package::downloadUrls() const
|
||||||
{
|
{
|
||||||
string_list r;
|
string_list r;
|
||||||
if (!m_props) {
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_FOREACH(SGPropertyNode* dl, m_props->getChildren("url")) {
|
BOOST_FOREACH(SGPropertyNode* dl, m_props->getChildren("url")) {
|
||||||
r.push_back(dl->getStringValue());
|
r.push_back(dl->getStringValue());
|
||||||
}
|
}
|
||||||
@@ -286,7 +238,7 @@ PackageList Package::dependencies() const
|
|||||||
|
|
||||||
// prefer local hangar package if possible, in case someone does something
|
// prefer local hangar package if possible, in case someone does something
|
||||||
// silly with naming. Of course flightgear's aircraft search doesn't know
|
// silly with naming. Of course flightgear's aircraft search doesn't know
|
||||||
// about hangars, so names still need to be unique.
|
// about hanagrs, so names still need to be unique.
|
||||||
PackageRef depPkg = m_catalog->getPackageById(depName);
|
PackageRef depPkg = m_catalog->getPackageById(depName);
|
||||||
if (!depPkg) {
|
if (!depPkg) {
|
||||||
Root* rt = m_catalog->root();
|
Root* rt = m_catalog->root();
|
||||||
@@ -338,20 +290,6 @@ std::string Package::nameForVariant(const std::string& vid) const
|
|||||||
throw sg_exception("Unknow variant +" + vid + " in package " + id());
|
throw sg_exception("Unknow variant +" + vid + " in package " + id());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Package::nameForVariant(const unsigned int vIndex) const
|
|
||||||
{
|
|
||||||
if (vIndex == 0)
|
|
||||||
return name();
|
|
||||||
|
|
||||||
// offset by minus one to allow for index 0 being the primary
|
|
||||||
SGPropertyNode_ptr var = m_props->getChild("variant", vIndex - 1);
|
|
||||||
if (var)
|
|
||||||
return var->getStringValue("name");
|
|
||||||
|
|
||||||
throw sg_exception("Unknow variant in package " + id());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // of namespace pkg
|
} // of namespace pkg
|
||||||
|
|
||||||
} // of namespace simgear
|
} // of namespace simgear
|
||||||
|
|||||||
@@ -76,11 +76,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
std::string qualifiedId() const;
|
std::string qualifiedId() const;
|
||||||
|
|
||||||
/**
|
|
||||||
* Fully-qualified ID, including our catalog'd ID
|
|
||||||
*/
|
|
||||||
std::string qualifiedVariantId(const unsigned int variantIndex) const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* human-readable name - note this is probably not localised,
|
* human-readable name - note this is probably not localised,
|
||||||
* although this is not ruled out for the future.
|
* although this is not ruled out for the future.
|
||||||
@@ -92,8 +87,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
std::string nameForVariant(const std::string& vid) const;
|
std::string nameForVariant(const std::string& vid) const;
|
||||||
|
|
||||||
std::string nameForVariant(const unsigned int vIndex) const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* syntactic sugar to get the localised description
|
* syntactic sugar to get the localised description
|
||||||
*/
|
*/
|
||||||
@@ -120,8 +113,6 @@ public:
|
|||||||
|
|
||||||
bool matches(const SGPropertyNode* aFilter) const;
|
bool matches(const SGPropertyNode* aFilter) const;
|
||||||
|
|
||||||
string_set tags() const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* download URLs for the package
|
* download URLs for the package
|
||||||
*/
|
*/
|
||||||
@@ -129,28 +120,16 @@ public:
|
|||||||
|
|
||||||
string_list thumbnailUrls() const;
|
string_list thumbnailUrls() const;
|
||||||
|
|
||||||
/**
|
|
||||||
* thumbnail file paths within the package on disk
|
|
||||||
*/
|
|
||||||
string_list thumbnails() const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Packages we depend upon.
|
* Packages we depend upon.
|
||||||
* If the dependency list cannot be satisifed for some reason,
|
* If the dependency list cannot be satisifed for some reason,
|
||||||
* this will raise an sg_exception.
|
* this will raise an sg_exception.
|
||||||
*/
|
*/
|
||||||
PackageList dependencies() const;
|
PackageList dependencies() const;
|
||||||
|
|
||||||
/**
|
|
||||||
* Name of the package directory on disk. This may or may not be the
|
|
||||||
* same as the primary ID, depending on the aircraft author
|
|
||||||
*/
|
|
||||||
std::string dirName() const;
|
|
||||||
private:
|
private:
|
||||||
SGPath pathOnDisk() const;
|
SGPath pathOnDisk() const;
|
||||||
|
|
||||||
friend class Catalog;
|
friend class Catalog;
|
||||||
friend class Root;
|
|
||||||
|
|
||||||
Package(const SGPropertyNode* aProps, CatalogRef aCatalog);
|
Package(const SGPropertyNode* aProps, CatalogRef aCatalog);
|
||||||
|
|
||||||
|
|||||||
+47
-348
@@ -38,159 +38,31 @@ namespace simgear {
|
|||||||
namespace pkg {
|
namespace pkg {
|
||||||
|
|
||||||
typedef std::map<std::string, CatalogRef> CatalogDict;
|
typedef std::map<std::string, CatalogRef> CatalogDict;
|
||||||
typedef std::vector<Delegate*> DelegateVec;
|
|
||||||
typedef std::map<std::string, std::string> MemThumbnailCache;
|
|
||||||
typedef std::deque<std::string> StringDeque;
|
|
||||||
|
|
||||||
class Root::ThumbnailDownloader : public HTTP::Request
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ThumbnailDownloader(Root::RootPrivate* aOwner, const std::string& aUrl) :
|
|
||||||
HTTP::Request(aUrl),
|
|
||||||
m_owner(aOwner)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void gotBodyData(const char* s, int n)
|
|
||||||
{
|
|
||||||
m_buffer += std::string(s, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void onDone();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Root::RootPrivate* m_owner;
|
|
||||||
std::string m_buffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Root::RootPrivate
|
class Root::RootPrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RootPrivate() :
|
RootPrivate() :
|
||||||
http(NULL),
|
http(NULL),
|
||||||
maxAgeSeconds(60 * 60 * 24)
|
maxAgeSeconds(60 * 60 * 24),
|
||||||
|
delegate(NULL)
|
||||||
{
|
{
|
||||||
}
|
|
||||||
|
|
||||||
void fireStartInstall(InstallRef install)
|
|
||||||
{
|
|
||||||
DelegateVec::const_iterator it;
|
|
||||||
for (it = delegates.begin(); it != delegates.end(); ++it) {
|
|
||||||
(*it)->startInstall(install);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void fireInstallProgress(InstallRef install,
|
|
||||||
unsigned int aBytes, unsigned int aTotal)
|
|
||||||
{
|
|
||||||
DelegateVec::const_iterator it;
|
|
||||||
for (it = delegates.begin(); it != delegates.end(); ++it) {
|
|
||||||
(*it)->installProgress(install, aBytes, aTotal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void fireFinishInstall(InstallRef install, Delegate::StatusCode status)
|
|
||||||
{
|
|
||||||
DelegateVec::const_iterator it;
|
|
||||||
for (it = delegates.begin(); it != delegates.end(); ++it) {
|
|
||||||
(*it)->finishInstall(install, status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void fireRefreshStatus(CatalogRef catalog, Delegate::StatusCode status)
|
|
||||||
{
|
|
||||||
DelegateVec::const_iterator it;
|
|
||||||
for (it = delegates.begin(); it != delegates.end(); ++it) {
|
|
||||||
(*it)->catalogRefreshed(catalog, status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void firePackagesChanged()
|
|
||||||
{
|
|
||||||
DelegateVec::const_iterator it;
|
|
||||||
for (it = delegates.begin(); it != delegates.end(); ++it) {
|
|
||||||
(*it)->availablePackagesChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void thumbnailDownloadComplete(HTTP::Request_ptr request,
|
|
||||||
Delegate::StatusCode status, const std::string& bytes)
|
|
||||||
{
|
|
||||||
std::string u(request->url());
|
|
||||||
if (status == Delegate::STATUS_SUCCESS) {
|
|
||||||
thumbnailCache[u] = bytes;
|
|
||||||
fireDataForThumbnail(u, bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
downloadNextPendingThumbnail();
|
|
||||||
}
|
|
||||||
|
|
||||||
void fireDataForThumbnail(const std::string& aUrl, const std::string& bytes)
|
|
||||||
{
|
|
||||||
DelegateVec::const_iterator it;
|
|
||||||
const uint8_t* data = reinterpret_cast<const uint8_t*>(bytes.data());
|
|
||||||
for (it = delegates.begin(); it != delegates.end(); ++it) {
|
|
||||||
(*it)->dataForThumbnail(aUrl, bytes.size(), data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void downloadNextPendingThumbnail()
|
|
||||||
{
|
|
||||||
thumbnailDownloadRequest.clear();
|
|
||||||
if (pendingThumbnails.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string u = pendingThumbnails.front();
|
|
||||||
pendingThumbnails.pop_front();
|
|
||||||
thumbnailDownloadRequest = new Root::ThumbnailDownloader(this, u);
|
|
||||||
|
|
||||||
if (http) {
|
|
||||||
http->makeRequest(thumbnailDownloadRequest);
|
|
||||||
} else {
|
|
||||||
httpPendingRequests.push_back(thumbnailDownloadRequest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateVec delegates;
|
|
||||||
|
|
||||||
SGPath path;
|
SGPath path;
|
||||||
std::string locale;
|
std::string locale;
|
||||||
HTTP::Client* http;
|
HTTP::Client* http;
|
||||||
CatalogDict catalogs;
|
CatalogDict catalogs;
|
||||||
CatalogList disabledCatalogs;
|
|
||||||
unsigned int maxAgeSeconds;
|
unsigned int maxAgeSeconds;
|
||||||
|
Delegate* delegate;
|
||||||
std::string version;
|
std::string version;
|
||||||
|
|
||||||
std::set<CatalogRef> refreshing;
|
std::set<CatalogRef> refreshing;
|
||||||
typedef std::deque<InstallRef> UpdateDeque;
|
std::deque<InstallRef> updateDeque;
|
||||||
UpdateDeque updateDeque;
|
|
||||||
std::deque<HTTP::Request_ptr> httpPendingRequests;
|
std::deque<HTTP::Request_ptr> httpPendingRequests;
|
||||||
|
|
||||||
HTTP::Request_ptr thumbnailDownloadRequest;
|
|
||||||
StringDeque pendingThumbnails;
|
|
||||||
MemThumbnailCache thumbnailCache;
|
|
||||||
|
|
||||||
typedef std::map<PackageRef, InstallRef> InstallCache;
|
|
||||||
InstallCache m_installs;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void Root::ThumbnailDownloader::onDone()
|
|
||||||
{
|
|
||||||
if (responseCode() != 200) {
|
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "thumbnail download failure:" << url());
|
|
||||||
m_owner->thumbnailDownloadComplete(this, Delegate::FAIL_DOWNLOAD, std::string());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_owner->thumbnailDownloadComplete(this, Delegate::STATUS_SUCCESS, m_buffer);
|
|
||||||
//time(&m_owner->m_retrievedTime);
|
|
||||||
//m_owner->writeTimestamp();
|
|
||||||
//m_owner->refreshComplete(Delegate::STATUS_REFRESHED);
|
|
||||||
}
|
|
||||||
|
|
||||||
SGPath Root::path() const
|
SGPath Root::path() const
|
||||||
{
|
{
|
||||||
return d->path;
|
return d->path;
|
||||||
@@ -241,16 +113,10 @@ Root::Root(const SGPath& aPath, const std::string& aVersion) :
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_FOREACH(SGPath c, dir.children(Dir::TYPE_DIR | Dir::NO_DOT_OR_DOTDOT)) {
|
BOOST_FOREACH(SGPath c, dir.children(Dir::TYPE_DIR)) {
|
||||||
CatalogRef cat = Catalog::createFromPath(this, c);
|
CatalogRef cat = Catalog::createFromPath(this, c);
|
||||||
if (cat) {
|
if (cat) {
|
||||||
if (cat->status() == Delegate::STATUS_SUCCESS) {
|
|
||||||
d->catalogs[cat->id()] = cat;
|
d->catalogs[cat->id()] = cat;
|
||||||
} else {
|
|
||||||
// catalog has problems, such as needing an update
|
|
||||||
// keep it out of the main collection for now
|
|
||||||
d->disabledCatalogs.push_back(cat);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} // of child directories iteration
|
} // of child directories iteration
|
||||||
}
|
}
|
||||||
@@ -260,12 +126,7 @@ Root::~Root()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Root::catalogVersion() const
|
std::string Root::catalogVersion() const
|
||||||
{
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Root::applicationVersion() const
|
|
||||||
{
|
{
|
||||||
return d->version;
|
return d->version;
|
||||||
}
|
}
|
||||||
@@ -319,20 +180,6 @@ CatalogList Root::catalogs() const
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
PackageList
|
|
||||||
Root::allPackages() const
|
|
||||||
{
|
|
||||||
PackageList r;
|
|
||||||
|
|
||||||
CatalogDict::const_iterator it = d->catalogs.begin();
|
|
||||||
for (; it != d->catalogs.end(); ++it) {
|
|
||||||
const PackageList& r2(it->second->packages());
|
|
||||||
r.insert(r.end(), r2.begin(), r2.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
PackageList
|
PackageList
|
||||||
Root::packagesMatching(const SGPropertyNode* aFilter) const
|
Root::packagesMatching(const SGPropertyNode* aFilter) const
|
||||||
{
|
{
|
||||||
@@ -363,45 +210,17 @@ Root::packagesNeedingUpdate() const
|
|||||||
|
|
||||||
void Root::refresh(bool aForce)
|
void Root::refresh(bool aForce)
|
||||||
{
|
{
|
||||||
bool didStartAny = false;
|
|
||||||
|
|
||||||
// copy all candidate ctalogs to a seperate list, since refreshing
|
|
||||||
// can modify both the main collection and/or the disabled list
|
|
||||||
CatalogList toRefresh;
|
|
||||||
CatalogDict::iterator it = d->catalogs.begin();
|
CatalogDict::iterator it = d->catalogs.begin();
|
||||||
for (; it != d->catalogs.end(); ++it) {
|
for (; it != d->catalogs.end(); ++it) {
|
||||||
toRefresh.push_back(it->second);
|
if (aForce || it->second->needsRefresh()) {
|
||||||
|
it->second->refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
toRefresh.insert(toRefresh.end(), d->disabledCatalogs.begin(),
|
|
||||||
d->disabledCatalogs.end());
|
|
||||||
|
|
||||||
|
|
||||||
CatalogList::iterator j = toRefresh.begin();
|
|
||||||
for (; j != toRefresh.end(); ++j) {
|
|
||||||
(*j)->refresh();
|
|
||||||
didStartAny = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!didStartAny) {
|
|
||||||
// signal refresh complete to the delegate already
|
|
||||||
d->fireRefreshStatus(CatalogRef(), Delegate::STATUS_REFRESHED);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Root::addDelegate(simgear::pkg::Delegate *aDelegate)
|
void Root::setDelegate(simgear::pkg::Delegate *aDelegate)
|
||||||
{
|
{
|
||||||
d->delegates.push_back(aDelegate);
|
d->delegate = aDelegate;
|
||||||
}
|
|
||||||
|
|
||||||
void Root::removeDelegate(simgear::pkg::Delegate *aDelegate)
|
|
||||||
{
|
|
||||||
DelegateVec::iterator it = std::find(d->delegates.begin(),
|
|
||||||
d->delegates.end(), aDelegate);
|
|
||||||
if (it == d->delegates.end()) {
|
|
||||||
throw sg_exception("unknown delegate in removeDelegate");
|
|
||||||
}
|
|
||||||
d->delegates.erase(it);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Root::setLocale(const std::string& aLocale)
|
void Root::setLocale(const std::string& aLocale)
|
||||||
@@ -435,21 +254,18 @@ void Root::scheduleToUpdate(InstallRef aInstall)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Root::isInstallQueued(InstallRef aInstall) const
|
|
||||||
{
|
|
||||||
RootPrivate::UpdateDeque::const_iterator it =
|
|
||||||
std::find(d->updateDeque.begin(), d->updateDeque.end(), aInstall);
|
|
||||||
return (it != d->updateDeque.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Root::startInstall(InstallRef aInstall)
|
void Root::startInstall(InstallRef aInstall)
|
||||||
{
|
{
|
||||||
d->fireStartInstall(aInstall);
|
if (d->delegate) {
|
||||||
|
d->delegate->startInstall(aInstall.ptr());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Root::installProgress(InstallRef aInstall, unsigned int aBytes, unsigned int aTotal)
|
void Root::installProgress(InstallRef aInstall, unsigned int aBytes, unsigned int aTotal)
|
||||||
{
|
{
|
||||||
d->fireInstallProgress(aInstall, aBytes, aTotal);
|
if (d->delegate) {
|
||||||
|
d->delegate->installProgress(aInstall.ptr(), aBytes, aTotal);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Root::startNext(InstallRef aCurrent)
|
void Root::startNext(InstallRef aCurrent)
|
||||||
@@ -465,176 +281,59 @@ void Root::startNext(InstallRef aCurrent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Root::finishInstall(InstallRef aInstall, Delegate::StatusCode aReason)
|
void Root::finishInstall(InstallRef aInstall)
|
||||||
|
{
|
||||||
|
if (d->delegate) {
|
||||||
|
d->delegate->finishInstall(aInstall.ptr());
|
||||||
|
}
|
||||||
|
|
||||||
|
startNext(aInstall);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Root::failedInstall(InstallRef aInstall, Delegate::FailureCode aReason)
|
||||||
{
|
{
|
||||||
if (aReason != Delegate::STATUS_SUCCESS) {
|
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "failed to install package:"
|
SG_LOG(SG_GENERAL, SG_ALERT, "failed to install package:"
|
||||||
<< aInstall->package()->id() << ":" << aReason);
|
<< aInstall->package()->id() << ":" << aReason);
|
||||||
|
if (d->delegate) {
|
||||||
|
d->delegate->failedInstall(aInstall.ptr(), aReason);
|
||||||
}
|
}
|
||||||
|
|
||||||
// order matters here, so a call to 'isQueued' from a finish-install
|
|
||||||
// callback returns false, not true
|
|
||||||
startNext(aInstall);
|
startNext(aInstall);
|
||||||
d->fireFinishInstall(aInstall, aReason);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Root::cancelDownload(InstallRef aInstall)
|
void Root::catalogRefreshBegin(CatalogRef aCat)
|
||||||
{
|
{
|
||||||
RootPrivate::UpdateDeque::iterator it =
|
d->refreshing.insert(aCat);
|
||||||
std::find(d->updateDeque.begin(), d->updateDeque.end(), aInstall);
|
|
||||||
if (it != d->updateDeque.end()) {
|
|
||||||
bool startNext = (aInstall == d->updateDeque.front());
|
|
||||||
d->updateDeque.erase(it);
|
|
||||||
if (startNext) {
|
|
||||||
if (!d->updateDeque.empty()) {
|
|
||||||
d->updateDeque.front()->startUpdate();
|
|
||||||
}
|
|
||||||
} // of install was front item
|
|
||||||
} // of found install in queue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Root::catalogRefreshStatus(CatalogRef aCat, Delegate::StatusCode aReason)
|
void Root::catalogRefreshComplete(CatalogRef aCat, Delegate::FailureCode aReason)
|
||||||
{
|
{
|
||||||
CatalogDict::iterator catIt = d->catalogs.find(aCat->id());
|
CatalogDict::iterator catIt = d->catalogs.find(aCat->id());
|
||||||
d->fireRefreshStatus(aCat, aReason);
|
if (aReason != Delegate::FAIL_SUCCESS) {
|
||||||
|
if (d->delegate) {
|
||||||
if (aReason == Delegate::STATUS_IN_PROGRESS) {
|
d->delegate->failedRefresh(aCat, aReason);
|
||||||
d->refreshing.insert(aCat);
|
|
||||||
} else {
|
|
||||||
d->refreshing.erase(aCat);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((aReason == Delegate::STATUS_REFRESHED) && (catIt == d->catalogs.end())) {
|
// if the failure is permanent, delete the catalog from our
|
||||||
assert(!aCat->id().empty());
|
// list (don't touch it on disk)
|
||||||
d->catalogs.insert(catIt, CatalogDict::value_type(aCat->id(), aCat));
|
bool isPermanentFailure = (aReason == Delegate::FAIL_VERSION);
|
||||||
|
if (isPermanentFailure) {
|
||||||
// catalog might have been previously disabled, let's remove in that case
|
SG_LOG(SG_GENERAL, SG_WARN, "permanent failure for catalog:" << aCat->id());
|
||||||
CatalogList::iterator j = std::find(d->disabledCatalogs.begin(),
|
|
||||||
d->disabledCatalogs.end(),
|
|
||||||
aCat);
|
|
||||||
if (j != d->disabledCatalogs.end()) {
|
|
||||||
SG_LOG(SG_GENERAL, SG_INFO, "re-enabling disabled catalog:" << aCat->id());
|
|
||||||
d->disabledCatalogs.erase(j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((aReason != Delegate::STATUS_REFRESHED) &&
|
|
||||||
(aReason != Delegate::STATUS_IN_PROGRESS) &&
|
|
||||||
(aReason != Delegate::STATUS_SUCCESS))
|
|
||||||
{
|
|
||||||
// catalog has errors, disable it
|
|
||||||
CatalogList::iterator j = std::find(d->disabledCatalogs.begin(),
|
|
||||||
d->disabledCatalogs.end(),
|
|
||||||
aCat);
|
|
||||||
if (j == d->disabledCatalogs.end()) {
|
|
||||||
SG_LOG(SG_GENERAL, SG_INFO, "disabling catalog:" << aCat->id());
|
|
||||||
d->disabledCatalogs.push_back(aCat);
|
|
||||||
}
|
|
||||||
|
|
||||||
// and remove it from the active collection
|
|
||||||
if (catIt != d->catalogs.end()) {
|
if (catIt != d->catalogs.end()) {
|
||||||
d->catalogs.erase(catIt);
|
d->catalogs.erase(catIt);
|
||||||
}
|
}
|
||||||
} // of catalog has errors case
|
}
|
||||||
|
} else if (catIt == d->catalogs.end()) {
|
||||||
|
// first fresh, add to our storage now
|
||||||
|
d->catalogs.insert(catIt, CatalogDict::value_type(aCat->id(), aCat));
|
||||||
|
}
|
||||||
|
|
||||||
|
d->refreshing.erase(aCat);
|
||||||
if (d->refreshing.empty()) {
|
if (d->refreshing.empty()) {
|
||||||
d->fireRefreshStatus(CatalogRef(), Delegate::STATUS_REFRESHED);
|
if (d->delegate) {
|
||||||
d->firePackagesChanged();
|
d->delegate->refreshComplete();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Root::removeCatalogById(const std::string& aId)
|
|
||||||
{
|
|
||||||
CatalogRef cat;
|
|
||||||
|
|
||||||
CatalogDict::iterator catIt = d->catalogs.find(aId);
|
|
||||||
if (catIt == d->catalogs.end()) {
|
|
||||||
// check the disabled list
|
|
||||||
CatalogList::iterator j = d->disabledCatalogs.begin();
|
|
||||||
for (; j != d->disabledCatalogs.end(); ++j) {
|
|
||||||
if ((*j)->id() == aId) {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (j == d->disabledCatalogs.end()) {
|
|
||||||
SG_LOG(SG_GENERAL, SG_WARN, "removeCatalogById: no catalog with id:" << aId);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
cat = *j;
|
|
||||||
d->disabledCatalogs.erase(j);
|
|
||||||
} else {
|
|
||||||
cat = catIt->second;
|
|
||||||
// drop the reference
|
|
||||||
d->catalogs.erase(catIt);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ok = cat->uninstall();
|
|
||||||
if (!ok) {
|
|
||||||
SG_LOG(SG_GENERAL, SG_WARN, "removeCatalogById: catalog :" << aId
|
|
||||||
<< "failed to uninstall");
|
|
||||||
}
|
|
||||||
|
|
||||||
// notify that a catalog is being removed
|
|
||||||
d->firePackagesChanged();
|
|
||||||
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Root::requestThumbnailData(const std::string& aUrl)
|
|
||||||
{
|
|
||||||
MemThumbnailCache::iterator it = d->thumbnailCache.find(aUrl);
|
|
||||||
if (it == d->thumbnailCache.end()) {
|
|
||||||
// insert into cache to mark as pending
|
|
||||||
d->pendingThumbnails.push_front(aUrl);
|
|
||||||
d->thumbnailCache[aUrl] = std::string();
|
|
||||||
d->downloadNextPendingThumbnail();
|
|
||||||
} else if (!it->second.empty()) {
|
|
||||||
// already loaded, fire data synchronously
|
|
||||||
d->fireDataForThumbnail(aUrl, it->second);
|
|
||||||
} else {
|
|
||||||
// in cache but empty data, still fetching
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
InstallRef Root::existingInstallForPackage(PackageRef p) const
|
|
||||||
{
|
|
||||||
RootPrivate::InstallCache::const_iterator it =
|
|
||||||
d->m_installs.find(p);
|
|
||||||
if (it == d->m_installs.end()) {
|
|
||||||
// check if it exists on disk, create
|
|
||||||
SGPath path(p->pathOnDisk());
|
|
||||||
if (path.exists()) {
|
|
||||||
// this will add to our cache, and hence, modify m_installs
|
|
||||||
return Install::createFromPath(path, p->catalog());
|
|
||||||
}
|
|
||||||
|
|
||||||
// insert a null reference into the dictionary, so we don't call
|
|
||||||
// the pathOnDisk -> exists codepath repeatedley
|
|
||||||
d->m_installs[p] = InstallRef();
|
|
||||||
return InstallRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Root::registerInstall(InstallRef ins)
|
|
||||||
{
|
|
||||||
if (!ins.valid()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
d->m_installs[ins->package()] = ins;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Root::unregisterInstall(InstallRef ins)
|
|
||||||
{
|
|
||||||
if (!ins .valid()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
d->m_installs.erase(ins->package());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // of namespace pkg
|
} // of namespace pkg
|
||||||
|
|||||||
@@ -62,9 +62,7 @@ public:
|
|||||||
|
|
||||||
void setLocale(const std::string& aLocale);
|
void setLocale(const std::string& aLocale);
|
||||||
|
|
||||||
void addDelegate(Delegate* aDelegate);
|
void setDelegate(Delegate* aDelegate);
|
||||||
|
|
||||||
void removeDelegate(Delegate* aDelegate);
|
|
||||||
|
|
||||||
std::string getLocale() const;
|
std::string getLocale() const;
|
||||||
|
|
||||||
@@ -83,16 +81,10 @@ public:
|
|||||||
void makeHTTPRequest(HTTP::Request* req);
|
void makeHTTPRequest(HTTP::Request* req);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The catalog XML/property version in use. This is used to make incomaptible
|
* the version string of the root. Catalogs must match this version,
|
||||||
* changes to the package/catalog syntax
|
|
||||||
*/
|
|
||||||
int catalogVersion() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* the version string of the application. Catalogs must match this version,
|
|
||||||
* or they will be ignored / rejected.
|
* or they will be ignored / rejected.
|
||||||
*/
|
*/
|
||||||
std::string applicationVersion() const;
|
std::string catalogVersion() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* refresh catalogs which are more than the maximum age (24 hours by default)
|
* refresh catalogs which are more than the maximum age (24 hours by default)
|
||||||
@@ -100,11 +92,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
void refresh(bool aForce = false);
|
void refresh(bool aForce = false);
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
PackageList allPackages() const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* retrieve packages matching a filter.
|
* retrieve packages matching a filter.
|
||||||
* filter consists of required / minimum values, AND-ed together.
|
* filter consists of required / minimum values, AND-ed together.
|
||||||
@@ -122,39 +109,21 @@ public:
|
|||||||
CatalogRef getCatalogById(const std::string& aId) const;
|
CatalogRef getCatalogById(const std::string& aId) const;
|
||||||
|
|
||||||
void scheduleToUpdate(InstallRef aInstall);
|
void scheduleToUpdate(InstallRef aInstall);
|
||||||
|
|
||||||
/**
|
|
||||||
* remove a catalog. Will uninstall all packages originating
|
|
||||||
* from the catalog too.
|
|
||||||
*/
|
|
||||||
bool removeCatalogById(const std::string& aId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* request thumbnail data from the cache / network
|
|
||||||
*/
|
|
||||||
void requestThumbnailData(const std::string& aUrl);
|
|
||||||
|
|
||||||
bool isInstallQueued(InstallRef aInstall) const;
|
|
||||||
private:
|
private:
|
||||||
friend class Install;
|
friend class Install;
|
||||||
friend class Catalog;
|
friend class Catalog;
|
||||||
friend class Package;
|
|
||||||
|
|
||||||
InstallRef existingInstallForPackage(PackageRef p) const;
|
|
||||||
|
|
||||||
void catalogRefreshStatus(CatalogRef aCat, Delegate::StatusCode aReason);
|
void catalogRefreshBegin(CatalogRef aCat);
|
||||||
|
void catalogRefreshComplete(CatalogRef aCat, Delegate::FailureCode aReason);
|
||||||
|
|
||||||
void startNext(InstallRef aCurrent);
|
void startNext(InstallRef aCurrent);
|
||||||
|
|
||||||
void startInstall(InstallRef aInstall);
|
void startInstall(InstallRef aInstall);
|
||||||
void installProgress(InstallRef aInstall, unsigned int aBytes, unsigned int aTotal);
|
void installProgress(InstallRef aInstall, unsigned int aBytes, unsigned int aTotal);
|
||||||
void finishInstall(InstallRef aInstall, Delegate::StatusCode aReason);
|
void finishInstall(InstallRef aInstall);
|
||||||
void cancelDownload(InstallRef aInstall);
|
void failedInstall(InstallRef aInstall, Delegate::FailureCode aReason);
|
||||||
|
|
||||||
void registerInstall(InstallRef ins);
|
|
||||||
void unregisterInstall(InstallRef ins);
|
|
||||||
|
|
||||||
class ThumbnailDownloader;
|
|
||||||
class RootPrivate;
|
class RootPrivate;
|
||||||
std::auto_ptr<RootPrivate> d;
|
std::auto_ptr<RootPrivate> d;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
<?xml version="1.0"?>
|
|
||||||
|
|
||||||
<PropertyList>
|
|
||||||
<id>org.flightgear.test.catalog1</id>
|
|
||||||
<description>First test catalog</description>
|
|
||||||
<url>http://download.flightgear.org/catalog1/catalog.xml</url>
|
|
||||||
<version>8.1.*</version>
|
|
||||||
<version>8.0.0</version>
|
|
||||||
<version>8.2.0</version>
|
|
||||||
|
|
||||||
<package>
|
|
||||||
<id>alpha</id>
|
|
||||||
<name>Alpha package</name>
|
|
||||||
<revision type="int">8</revision>
|
|
||||||
<file-size-bytes type="int">1234567</file-size-bytes>
|
|
||||||
</package>
|
|
||||||
|
|
||||||
<package>
|
|
||||||
<id>c172p</id>
|
|
||||||
<name>Cessna 172-P</name>
|
|
||||||
<description>A plane made by Cessna</description>
|
|
||||||
<revision type="int">42</revision>
|
|
||||||
<file-size-bytes type="int">34567</file-size-bytes>
|
|
||||||
|
|
||||||
<tag>cessna</tag>
|
|
||||||
<tag>ga</tag>
|
|
||||||
<tag>piston</tag>
|
|
||||||
<tag>ifr</tag>
|
|
||||||
|
|
||||||
<rating>
|
|
||||||
<FDM type="int">3</FDM>
|
|
||||||
<systems type="int">4</systems>
|
|
||||||
<model type="int">5</model>
|
|
||||||
<cockpit type="int">4</cockpit>
|
|
||||||
</rating>
|
|
||||||
|
|
||||||
<!-- local dependency -->
|
|
||||||
<depends>
|
|
||||||
<id>org.flightgear.test.catalog1.common-sounds</id>
|
|
||||||
<revision>10</revision>
|
|
||||||
</depends>
|
|
||||||
|
|
||||||
<variant>
|
|
||||||
<id>c172p-2d-panel</id>
|
|
||||||
<name>C172 with 2d panel only</name>
|
|
||||||
</variant>
|
|
||||||
|
|
||||||
<variant>
|
|
||||||
<id>c172p-floats</id>
|
|
||||||
<name>C172 with floats</name>
|
|
||||||
</variant>
|
|
||||||
|
|
||||||
<variant>
|
|
||||||
<id>c172p-skis</id>
|
|
||||||
<name>C172 with skis</name>
|
|
||||||
</variant>
|
|
||||||
</package>
|
|
||||||
|
|
||||||
<package>
|
|
||||||
<id>common-sounds</id>
|
|
||||||
<name>Common sound files for test catalog aircraft</name>
|
|
||||||
<revision>10</revision>
|
|
||||||
</package>
|
|
||||||
</PropertyList>
|
|
||||||
@@ -158,8 +158,7 @@ SG_MD5Transform(u_int32_t state[4], const u_int8_t block[MD5_BLOCK_LENGTH])
|
|||||||
{
|
{
|
||||||
u_int32_t a, b, c, d, in[MD5_BLOCK_LENGTH / 4];
|
u_int32_t a, b, c, d, in[MD5_BLOCK_LENGTH / 4];
|
||||||
|
|
||||||
#if ((defined(__BYTE_ORDER__) && __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__) || \
|
#ifndef WORDS_BIGENDIAN
|
||||||
defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM) )
|
|
||||||
memcpy(in, block, sizeof(in));
|
memcpy(in, block, sizeof(in));
|
||||||
#else
|
#else
|
||||||
for (a = 0; a < MD5_BLOCK_LENGTH / 4; a++) {
|
for (a = 0; a < MD5_BLOCK_LENGTH / 4; a++) {
|
||||||
|
|||||||
+15
-21
@@ -34,28 +34,22 @@ bool keepRunning = true;
|
|||||||
class MyDelegate : public pkg::Delegate
|
class MyDelegate : public pkg::Delegate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void catalogRefreshed(pkg::CatalogRef aCatalog, StatusCode aReason)
|
virtual void refreshComplete()
|
||||||
{
|
{
|
||||||
if (aReason == STATUS_REFRESHED) {
|
|
||||||
if (aCatalog.ptr() == NULL) {
|
|
||||||
cout << "refreshed all catalogs" << endl;
|
|
||||||
} else {
|
|
||||||
cout << "refreshed catalog " << aCatalog->url() << endl;
|
|
||||||
}
|
|
||||||
} else if (aReason == STATUS_IN_PROGRESS) {
|
|
||||||
cout << "started refresh of " << aCatalog->url() << endl;
|
|
||||||
} else {
|
|
||||||
cerr << "failed refresh of " << aCatalog->url() << ":" << aReason << endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void startInstall(pkg::InstallRef aInstall)
|
virtual void failedRefresh(pkg::Catalog* aCatalog, FailureCode aReason)
|
||||||
|
{
|
||||||
|
cerr << "failed refresh of " << aCatalog->description() << ":" << aReason << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void startInstall(pkg::Install* aInstall)
|
||||||
{
|
{
|
||||||
_lastPercent = 999;
|
_lastPercent = 999;
|
||||||
cout << "starting install of " << aInstall->package()->name() << endl;
|
cout << "starting install of " << aInstall->package()->name() << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void installProgress(pkg::InstallRef aInstall, unsigned int bytes, unsigned int total)
|
virtual void installProgress(pkg::Install* aInstall, unsigned int bytes, unsigned int total)
|
||||||
{
|
{
|
||||||
unsigned int percent = (bytes * 100) / total;
|
unsigned int percent = (bytes * 100) / total;
|
||||||
if (percent == _lastPercent) {
|
if (percent == _lastPercent) {
|
||||||
@@ -66,15 +60,15 @@ public:
|
|||||||
cout << percent << "%" << endl;
|
cout << percent << "%" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void finishInstall(pkg::InstallRef aInstall, StatusCode aReason)
|
virtual void finishInstall(pkg::Install* aInstall)
|
||||||
{
|
{
|
||||||
if (aReason == STATUS_SUCCESS) {
|
|
||||||
cout << "done install of " << aInstall->package()->name() << endl;
|
cout << "done install of " << aInstall->package()->name() << endl;
|
||||||
} else {
|
|
||||||
cerr << "failed install of " << aInstall->package()->name() << endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void failedInstall(pkg::Install* aInstall, FailureCode aReason)
|
||||||
|
{
|
||||||
|
cerr << "failed install of " << aInstall->package()->name() << endl;
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
unsigned int _lastPercent;
|
unsigned int _lastPercent;
|
||||||
|
|
||||||
@@ -125,10 +119,10 @@ int main(int argc, char** argv)
|
|||||||
pkg::Root* root = new pkg::Root(Dir::current().path(), "");
|
pkg::Root* root = new pkg::Root(Dir::current().path(), "");
|
||||||
|
|
||||||
MyDelegate dlg;
|
MyDelegate dlg;
|
||||||
root->addDelegate(&dlg);
|
root->setDelegate(&dlg);
|
||||||
|
|
||||||
cout << "Package root is:" << Dir::current().path() << endl;
|
cout << "Package root is:" << Dir::current().path() << endl;
|
||||||
cout << "have " << root->catalogs().size() << " catalog(s)" << endl;
|
cout << "have " << pkg::Catalog::allCatalogs().size() << " catalog(s)" << endl;
|
||||||
|
|
||||||
root->setHTTPClient(http);
|
root->setHTTPClient(http);
|
||||||
|
|
||||||
|
|||||||
@@ -144,9 +144,9 @@ public:
|
|||||||
|
|
||||||
#undef SG_DEF_ASSIGN_OP
|
#undef SG_DEF_ASSIGN_OP
|
||||||
|
|
||||||
SGPropertyNode* node(bool aCreate = false) const
|
SGPropertyNode* node() const
|
||||||
{
|
{
|
||||||
return PropertyObjectBase::node(aCreate);
|
return PropertyObjectBase::node(false);
|
||||||
}
|
}
|
||||||
}; // of template PropertyObject
|
}; // of template PropertyObject
|
||||||
|
|
||||||
@@ -237,9 +237,9 @@ public:
|
|||||||
return (s == value);
|
return (s == value);
|
||||||
}
|
}
|
||||||
|
|
||||||
SGPropertyNode* node(bool aCreate = false) const
|
SGPropertyNode* node() const
|
||||||
{
|
{
|
||||||
return PropertyObjectBase::node(aCreate);
|
return PropertyObjectBase::node(false);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|||||||
+32
-253
@@ -11,6 +11,8 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "props.hxx"
|
#include "props.hxx"
|
||||||
|
#include "PropertyInterpolationMgr.hxx"
|
||||||
|
#include "vectorPropTemplates.hxx"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
@@ -22,30 +24,31 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <boost/algorithm/string/find_iterator.hpp>
|
||||||
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
|
#include <boost/algorithm/string/classification.hpp>
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
#include <boost/functional/hash.hpp>
|
||||||
|
#include <boost/range.hpp>
|
||||||
|
|
||||||
#if PROPS_STANDALONE
|
#if PROPS_STANDALONE
|
||||||
# include <iostream>
|
#include <iostream>
|
||||||
using std::cerr;
|
|
||||||
#else
|
#else
|
||||||
# include <boost/algorithm/string/find_iterator.hpp>
|
|
||||||
# include <boost/algorithm/string/predicate.hpp>
|
|
||||||
# include <boost/algorithm/string/classification.hpp>
|
|
||||||
# include <boost/bind.hpp>
|
|
||||||
# include <boost/functional/hash.hpp>
|
|
||||||
# include <boost/range.hpp>
|
|
||||||
# include <simgear/compiler.h>
|
|
||||||
# include <simgear/debug/logstream.hxx>
|
|
||||||
|
|
||||||
# include "PropertyInterpolationMgr.hxx"
|
#include <simgear/compiler.h>
|
||||||
# include "vectorPropTemplates.hxx"
|
#include <simgear/debug/logstream.hxx>
|
||||||
|
|
||||||
# if ( _MSC_VER == 1200 )
|
#if ( _MSC_VER == 1200 )
|
||||||
// MSVC 6 is buggy, and needs something strange here
|
// MSVC 6 is buggy, and needs something strange here
|
||||||
using std::vector<SGPropertyNode_ptr>;
|
using std::vector<SGPropertyNode_ptr>;
|
||||||
using std::vector<SGPropertyChangeListener *>;
|
using std::vector<SGPropertyChangeListener *>;
|
||||||
using std::vector<SGPropertyNode *>;
|
using std::vector<SGPropertyNode *>;
|
||||||
# endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if PROPS_STANDALONE
|
||||||
|
using std::cerr;
|
||||||
|
#endif
|
||||||
using std::endl;
|
using std::endl;
|
||||||
using std::find;
|
using std::find;
|
||||||
using std::sort;
|
using std::sort;
|
||||||
@@ -81,14 +84,6 @@ public:
|
|||||||
// Local path normalization code.
|
// Local path normalization code.
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#if PROPS_STANDALONE
|
|
||||||
struct PathComponent
|
|
||||||
{
|
|
||||||
string name;
|
|
||||||
int index;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the name for a path component.
|
* Parse the name for a path component.
|
||||||
*
|
*
|
||||||
@@ -151,149 +146,10 @@ inline bool validateName(const std::string& name)
|
|||||||
return false;
|
return false;
|
||||||
if (!isalpha(name[0]) && name[0] != '_')
|
if (!isalpha(name[0]) && name[0] != '_')
|
||||||
return false;
|
return false;
|
||||||
#if PROPS_STANDALONE
|
|
||||||
std::string is_any_of("_-.");
|
|
||||||
bool rv = true;
|
|
||||||
for(unsigned i=1; i<name.length(); ++i) {
|
|
||||||
if (!isalnum(name[i]) && is_any_of.find(name[i]) == std::string::npos) {
|
|
||||||
rv = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rv;
|
|
||||||
#else
|
|
||||||
return all(make_iterator_range(name.begin(), name.end()),
|
return all(make_iterator_range(name.begin(), name.end()),
|
||||||
is_alnum() || is_any_of("_-."));
|
is_alnum() || is_any_of("_-."));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PROPS_STANDALONE
|
|
||||||
/**
|
|
||||||
* Parse the name for a path component.
|
|
||||||
*
|
|
||||||
* Name: [_a-zA-Z][-._a-zA-Z0-9]*
|
|
||||||
*/
|
|
||||||
static inline const string
|
|
||||||
parse_name (const string &path, int &i)
|
|
||||||
{
|
|
||||||
string name = "";
|
|
||||||
int max = (int)path.size();
|
|
||||||
|
|
||||||
if (path[i] == '.') {
|
|
||||||
i++;
|
|
||||||
if (i < max && path[i] == '.') {
|
|
||||||
i++;
|
|
||||||
name = "..";
|
|
||||||
} else {
|
|
||||||
name = ".";
|
|
||||||
}
|
|
||||||
if (i < max && path[i] != '/')
|
|
||||||
throw string("Illegal character after " + name);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (isalpha(path[i]) || path[i] == '_') {
|
|
||||||
name += path[i];
|
|
||||||
i++;
|
|
||||||
|
|
||||||
// The rules inside a name are a little
|
|
||||||
// less restrictive.
|
|
||||||
while (i < max) {
|
|
||||||
if (isalpha(path[i]) || isdigit(path[i]) || path[i] == '_' ||
|
|
||||||
path[i] == '-' || path[i] == '.') {
|
|
||||||
name += path[i];
|
|
||||||
} else if (path[i] == '[' || path[i] == '/') {
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
throw string("name may contain only ._- and alphanumeric characters");
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
if (name.size() == 0)
|
|
||||||
throw string("name must begin with alpha or '_'");
|
|
||||||
}
|
|
||||||
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse the optional integer index for a path component.
|
|
||||||
*
|
|
||||||
* Index: "[" [0-9]+ "]"
|
|
||||||
*/
|
|
||||||
static inline int
|
|
||||||
parse_index (const string &path, int &i)
|
|
||||||
{
|
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
if (path[i] != '[')
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
i++;
|
|
||||||
|
|
||||||
for (int max = (int)path.size(); i < max; i++) {
|
|
||||||
if (isdigit(path[i])) {
|
|
||||||
index = (index * 10) + (path[i] - '0');
|
|
||||||
} else if (path[i] == ']') {
|
|
||||||
i++;
|
|
||||||
return index;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw string("unterminated index (looking for ']')");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse a single path component.
|
|
||||||
*
|
|
||||||
* Component: Name Index?
|
|
||||||
*/
|
|
||||||
static inline PathComponent
|
|
||||||
parse_component (const string &path, int &i)
|
|
||||||
{
|
|
||||||
PathComponent component;
|
|
||||||
component.name = parse_name(path, i);
|
|
||||||
if (component.name[0] != '.')
|
|
||||||
component.index = parse_index(path, i);
|
|
||||||
else
|
|
||||||
component.index = -1;
|
|
||||||
return component;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse a path into its components.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
parse_path (const string &path, vector<PathComponent> &components)
|
|
||||||
{
|
|
||||||
int pos = 0;
|
|
||||||
int max = (int)path.size();
|
|
||||||
|
|
||||||
// Check for initial '/'
|
|
||||||
if (path[pos] == '/') {
|
|
||||||
PathComponent root;
|
|
||||||
root.name = "";
|
|
||||||
root.index = -1;
|
|
||||||
components.push_back(root);
|
|
||||||
pos++;
|
|
||||||
while (pos < max && path[pos] == '/')
|
|
||||||
pos++;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (pos < max) {
|
|
||||||
components.push_back(parse_component(path, pos));
|
|
||||||
while (pos < max && path[pos] == '/')
|
|
||||||
pos++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// Other static utility functions.
|
// Other static utility functions.
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
@@ -326,13 +182,6 @@ static int
|
|||||||
find_child (Itr begin, Itr end, int index, const PropertyList& nodes)
|
find_child (Itr begin, Itr end, int index, const PropertyList& nodes)
|
||||||
{
|
{
|
||||||
size_t nNodes = nodes.size();
|
size_t nNodes = nodes.size();
|
||||||
#if PROPS_STANDALONE
|
|
||||||
for (int i = 0; i < nNodes; i++) {
|
|
||||||
SGPropertyNode * node = nodes[i];
|
|
||||||
if (node->getIndex() == index && compare_strings(node->getName(), begin))
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
boost::iterator_range<Itr> name(begin, end);
|
boost::iterator_range<Itr> name(begin, end);
|
||||||
for (size_t i = 0; i < nNodes; i++) {
|
for (size_t i = 0; i < nNodes; i++) {
|
||||||
SGPropertyNode * node = nodes[i];
|
SGPropertyNode * node = nodes[i];
|
||||||
@@ -342,7 +191,6 @@ find_child (Itr begin, Itr end, int index, const PropertyList& nodes)
|
|||||||
if (node->getIndex() == index && boost::equals(node->getName(), name))
|
if (node->getIndex() == index && boost::equals(node->getName(), name))
|
||||||
return static_cast<int>(i);
|
return static_cast<int>(i);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -485,52 +333,6 @@ find_node_aux(SGPropertyNode * current, SplitItr& itr, bool create,
|
|||||||
|
|
||||||
// Internal function for parsing property paths. last_index provides
|
// Internal function for parsing property paths. last_index provides
|
||||||
// and index value for the last node name token, if supplied.
|
// and index value for the last node name token, if supplied.
|
||||||
#if PROPS_STANDALONE
|
|
||||||
static SGPropertyNode *
|
|
||||||
find_node (SGPropertyNode * current,
|
|
||||||
const vector<PathComponent> &components,
|
|
||||||
int position,
|
|
||||||
bool create)
|
|
||||||
{
|
|
||||||
// Run off the end of the list
|
|
||||||
if (current == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Success! This is the one we want.
|
|
||||||
else if (position >= (int)components.size()) {
|
|
||||||
return (current->getAttribute(SGPropertyNode::REMOVED) ? 0 : current);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Empty component means root.
|
|
||||||
else if (components[position].name == "") {
|
|
||||||
return find_node(current->getRootNode(), components, position + 1, create);
|
|
||||||
}
|
|
||||||
|
|
||||||
// . means current directory
|
|
||||||
else if (components[position].name == ".") {
|
|
||||||
return find_node(current, components, position + 1, create);
|
|
||||||
}
|
|
||||||
|
|
||||||
// .. means parent directory
|
|
||||||
else if (components[position].name == "..") {
|
|
||||||
SGPropertyNode * parent = current->getParent();
|
|
||||||
if (parent == 0)
|
|
||||||
throw string("Attempt to move past root with '..'");
|
|
||||||
else
|
|
||||||
return find_node(parent, components, position + 1, create);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, a child name
|
|
||||||
else {
|
|
||||||
SGPropertyNode * child =
|
|
||||||
current->getChild(components[position].name.c_str(),
|
|
||||||
components[position].index,
|
|
||||||
create);
|
|
||||||
return find_node(child, components, position + 1, create);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
template<typename Range>
|
template<typename Range>
|
||||||
SGPropertyNode*
|
SGPropertyNode*
|
||||||
find_node (SGPropertyNode * current,
|
find_node (SGPropertyNode * current,
|
||||||
@@ -549,7 +351,6 @@ find_node (SGPropertyNode * current,
|
|||||||
else
|
else
|
||||||
return find_node_aux(current, itr, create, last_index);
|
return find_node_aux(current, itr, create, last_index);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// Private methods from SGPropertyNode (may be inlined for speed).
|
// Private methods from SGPropertyNode (may be inlined for speed).
|
||||||
@@ -810,8 +611,13 @@ SGPropertyNode::make_string () const
|
|||||||
void
|
void
|
||||||
SGPropertyNode::trace_write () const
|
SGPropertyNode::trace_write () const
|
||||||
{
|
{
|
||||||
|
#if PROPS_STANDALONE
|
||||||
|
cerr << "TRACE: Write node " << getPath () << ", value \""
|
||||||
|
<< make_string() << '"' << endl;
|
||||||
|
#else
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "TRACE: Write node " << getPath()
|
SG_LOG(SG_GENERAL, SG_ALERT, "TRACE: Write node " << getPath()
|
||||||
<< ", value \"" << make_string() << '"');
|
<< ", value \"" << make_string() << '"');
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -820,8 +626,13 @@ SGPropertyNode::trace_write () const
|
|||||||
void
|
void
|
||||||
SGPropertyNode::trace_read () const
|
SGPropertyNode::trace_read () const
|
||||||
{
|
{
|
||||||
|
#if PROPS_STANDALONE
|
||||||
|
cerr << "TRACE: Write node " << getPath () << ", value \""
|
||||||
|
<< make_string() << '"' << endl;
|
||||||
|
#else
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "TRACE: Read node " << getPath()
|
SG_LOG(SG_GENERAL, SG_ALERT, "TRACE: Read node " << getPath()
|
||||||
<< ", value \"" << make_string() << '"');
|
<< ", value \"" << make_string() << '"');
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
@@ -975,6 +786,8 @@ SGPropertyNode::alias (SGPropertyNode * target)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if PROPS_STANDALONE
|
||||||
|
#else
|
||||||
if (!target)
|
if (!target)
|
||||||
{
|
{
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT,
|
SG_LOG(SG_GENERAL, SG_ALERT,
|
||||||
@@ -996,6 +809,7 @@ SGPropertyNode::alias (SGPropertyNode * target)
|
|||||||
SG_LOG(SG_GENERAL, SG_ALERT, "Failed to create alias at " << target->getPath() << ". "
|
SG_LOG(SG_GENERAL, SG_ALERT, "Failed to create alias at " << target->getPath() << ". "
|
||||||
"Source " << getPath() << " is a tied property.");
|
"Source " << getPath() << " is a tied property.");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1143,18 +957,11 @@ SGPropertyNode::getChild (const char * name, int index, bool create)
|
|||||||
SGPropertyNode *
|
SGPropertyNode *
|
||||||
SGPropertyNode::getChild (const std::string& name, int index, bool create)
|
SGPropertyNode::getChild (const std::string& name, int index, bool create)
|
||||||
{
|
{
|
||||||
#if PROPS_STANDALONE
|
|
||||||
const char *n = name.c_str();
|
|
||||||
int pos = find_child(n, n + strlen(n), index, _children);
|
|
||||||
if (pos >= 0) {
|
|
||||||
return _children[pos];
|
|
||||||
#else
|
|
||||||
SGPropertyNode* node = getExistingChild(name.begin(), name.end(), index);
|
SGPropertyNode* node = getExistingChild(name.begin(), name.end(), index);
|
||||||
if (node) {
|
if (node) {
|
||||||
return node;
|
return node;
|
||||||
#endif
|
|
||||||
} else if (create) {
|
} else if (create) {
|
||||||
SGPropertyNode* node = new SGPropertyNode(name, index, this);
|
node = new SGPropertyNode(name, index, this);
|
||||||
_children.push_back(node);
|
_children.push_back(node);
|
||||||
fireChildAdded(node);
|
fireChildAdded(node);
|
||||||
return node;
|
return node;
|
||||||
@@ -1828,14 +1635,12 @@ SGPropertyNode::setUnspecifiedValue (const char * value)
|
|||||||
case props::UNSPECIFIED:
|
case props::UNSPECIFIED:
|
||||||
result = set_string(value);
|
result = set_string(value);
|
||||||
break;
|
break;
|
||||||
#if !PROPS_STANDALONE
|
|
||||||
case props::VEC3D:
|
case props::VEC3D:
|
||||||
result = static_cast<SGRawValue<SGVec3d>*>(_value.val)->setValue(parseString<SGVec3d>(value));
|
result = static_cast<SGRawValue<SGVec3d>*>(_value.val)->setValue(parseString<SGVec3d>(value));
|
||||||
break;
|
break;
|
||||||
case props::VEC4D:
|
case props::VEC4D:
|
||||||
result = static_cast<SGRawValue<SGVec4d>*>(_value.val)->setValue(parseString<SGVec4d>(value));
|
result = static_cast<SGRawValue<SGVec4d>*>(_value.val)->setValue(parseString<SGVec4d>(value));
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
case props::NONE:
|
case props::NONE:
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -1847,7 +1652,6 @@ SGPropertyNode::setUnspecifiedValue (const char * value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
#if !PROPS_STANDALONE
|
|
||||||
bool SGPropertyNode::interpolate( const std::string& type,
|
bool SGPropertyNode::interpolate( const std::string& type,
|
||||||
const SGPropertyNode& target,
|
const SGPropertyNode& target,
|
||||||
double duration,
|
double duration,
|
||||||
@@ -1897,7 +1701,6 @@ simgear::PropertyInterpolationMgr* SGPropertyNode::getInterpolationMgr()
|
|||||||
}
|
}
|
||||||
|
|
||||||
simgear::PropertyInterpolationMgr* SGPropertyNode::_interpolation_mgr = 0;
|
simgear::PropertyInterpolationMgr* SGPropertyNode::_interpolation_mgr = 0;
|
||||||
#endif
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
std::ostream& SGPropertyNode::printOn(std::ostream& stream) const
|
std::ostream& SGPropertyNode::printOn(std::ostream& stream) const
|
||||||
@@ -2051,37 +1854,20 @@ SGPropertyNode::getRootNode () const
|
|||||||
SGPropertyNode *
|
SGPropertyNode *
|
||||||
SGPropertyNode::getNode (const char * relative_path, bool create)
|
SGPropertyNode::getNode (const char * relative_path, bool create)
|
||||||
{
|
{
|
||||||
#if PROPS_STANDALONE
|
|
||||||
vector<PathComponent> components;
|
|
||||||
parse_path(relative_path, components);
|
|
||||||
return find_node(this, components, 0, create);
|
|
||||||
|
|
||||||
#else
|
|
||||||
using namespace boost;
|
using namespace boost;
|
||||||
|
|
||||||
return find_node(this, make_iterator_range(relative_path, relative_path
|
return find_node(this, make_iterator_range(relative_path, relative_path
|
||||||
+ strlen(relative_path)),
|
+ strlen(relative_path)),
|
||||||
create);
|
create);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SGPropertyNode *
|
SGPropertyNode *
|
||||||
SGPropertyNode::getNode (const char * relative_path, int index, bool create)
|
SGPropertyNode::getNode (const char * relative_path, int index, bool create)
|
||||||
{
|
{
|
||||||
#if PROPS_STANDALONE
|
|
||||||
vector<PathComponent> components;
|
|
||||||
parse_path(relative_path, components);
|
|
||||||
if (components.size() > 0)
|
|
||||||
components.back().index = index;
|
|
||||||
return find_node(this, components, 0, create);
|
|
||||||
|
|
||||||
#else
|
|
||||||
using namespace boost;
|
using namespace boost;
|
||||||
|
|
||||||
return find_node(this, make_iterator_range(relative_path, relative_path
|
return find_node(this, make_iterator_range(relative_path, relative_path
|
||||||
+ strlen(relative_path)),
|
+ strlen(relative_path)),
|
||||||
create, index);
|
create, index);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const SGPropertyNode *
|
const SGPropertyNode *
|
||||||
@@ -2529,7 +2315,6 @@ SGPropertyChangeListener::unregister_property (SGPropertyNode * node)
|
|||||||
_properties.erase(it);
|
_properties.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !PROPS_STANDALONE
|
|
||||||
template<>
|
template<>
|
||||||
std::ostream& SGRawBase<SGVec3d>::printOn(std::ostream& stream) const
|
std::ostream& SGRawBase<SGVec3d>::printOn(std::ostream& stream) const
|
||||||
{
|
{
|
||||||
@@ -2566,11 +2351,9 @@ std::ostream& SGRawBase<SGVec4d>::printOn(std::ostream& stream) const
|
|||||||
}
|
}
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace simgear
|
namespace simgear
|
||||||
{
|
{
|
||||||
#if !PROPS_STANDALONE
|
|
||||||
template<>
|
template<>
|
||||||
std::istream& readFrom<SGVec4d>(std::istream& stream, SGVec4d& result)
|
std::istream& readFrom<SGVec4d>(std::istream& stream, SGVec4d& result)
|
||||||
{
|
{
|
||||||
@@ -2579,7 +2362,6 @@ std::istream& readFrom<SGVec4d>(std::istream& stream, SGVec4d& result)
|
|||||||
}
|
}
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@@ -2607,12 +2389,10 @@ bool compareNodeValue(const SGPropertyNode& lhs, const SGPropertyNode& rhs)
|
|||||||
case props::STRING:
|
case props::STRING:
|
||||||
case props::UNSPECIFIED:
|
case props::UNSPECIFIED:
|
||||||
return !strcmp(lhs.getStringValue(), rhs.getStringValue());
|
return !strcmp(lhs.getStringValue(), rhs.getStringValue());
|
||||||
#if !PROPS_STANDALONE
|
|
||||||
case props::VEC3D:
|
case props::VEC3D:
|
||||||
return lhs.getValue<SGVec3d>() == rhs.getValue<SGVec3d>();
|
return lhs.getValue<SGVec3d>() == rhs.getValue<SGVec3d>();
|
||||||
case props::VEC4D:
|
case props::VEC4D:
|
||||||
return lhs.getValue<SGVec4d>() == rhs.getValue<SGVec4d>();
|
return lhs.getValue<SGVec4d>() == rhs.getValue<SGVec4d>();
|
||||||
#endif
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -2669,10 +2449,10 @@ struct PropertyPlaceLess {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#if !PROPS_STANDALONE
|
|
||||||
size_t hash_value(const SGPropertyNode& node)
|
size_t hash_value(const SGPropertyNode& node)
|
||||||
{
|
{
|
||||||
using namespace boost;
|
using namespace boost;
|
||||||
|
|
||||||
if (node.nChildren() == 0) {
|
if (node.nChildren() == 0) {
|
||||||
switch (node.getType()) {
|
switch (node.getType()) {
|
||||||
case props::NONE:
|
case props::NONE:
|
||||||
@@ -2723,6 +2503,5 @@ size_t hash_value(const SGPropertyNode& node)
|
|||||||
return seed;
|
return seed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// end of props.cxx
|
// end of props.cxx
|
||||||
|
|||||||
+9
-49
@@ -22,54 +22,24 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
|
|
||||||
#include <simgear/compiler.h>
|
#include <boost/utility.hpp>
|
||||||
|
#include <boost/type_traits/is_enum.hpp>
|
||||||
|
|
||||||
#if PROPS_STANDALONE
|
#if PROPS_STANDALONE
|
||||||
// taken from: boost/utility/enable_if.hpp
|
|
||||||
#ifndef SG_LOG
|
|
||||||
# define SG_GENERAL 0
|
|
||||||
# define SG_ALERT 0
|
|
||||||
# define SG_WARN 1
|
|
||||||
# define SG_LOG(type, level, message) (type) ? (std::cerr <<message << endl) : (std::cout <<message << endl)
|
|
||||||
#endif
|
|
||||||
namespace boost {
|
|
||||||
template <bool B, class T = void>
|
|
||||||
struct enable_if_c {
|
|
||||||
typedef T type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
struct enable_if_c<false, T> {};
|
|
||||||
|
|
||||||
template <class Cond, class T = void>
|
|
||||||
struct enable_if : public enable_if_c<Cond::value, T> {};
|
|
||||||
|
|
||||||
template <bool B, class T = void>
|
|
||||||
struct disable_if_c {
|
|
||||||
typedef T type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
struct disable_if_c<true, T> {};
|
|
||||||
|
|
||||||
template <class Cond, class T = void>
|
|
||||||
struct disable_if : public disable_if_c<Cond::value, T> {};
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
# include <boost/utility.hpp>
|
#include <simgear/compiler.h>
|
||||||
# include <boost/type_traits/is_enum.hpp>
|
#include <simgear/debug/logstream.hxx>
|
||||||
|
|
||||||
# include <simgear/debug/logstream.hxx>
|
|
||||||
# include <simgear/math/SGMathFwd.hxx>
|
|
||||||
# include <simgear/math/sg_types.hxx>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include <simgear/math/SGMathFwd.hxx>
|
||||||
|
#include <simgear/math/sg_types.hxx>
|
||||||
#include <simgear/structure/SGReferenced.hxx>
|
#include <simgear/structure/SGReferenced.hxx>
|
||||||
#include <simgear/structure/SGSharedPtr.hxx>
|
#include <simgear/structure/SGSharedPtr.hxx>
|
||||||
|
|
||||||
// XXX This whole file should be in the simgear namespace, but I don't
|
// XXX This whole file should be in the simgear namespace, but I don't
|
||||||
// have the guts yet...
|
// have the guts yet...
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace simgear
|
namespace simgear
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -1305,7 +1275,6 @@ public:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !PROPS_STANDALONE
|
|
||||||
/**
|
/**
|
||||||
* Interpolate current value to target value within given time.
|
* Interpolate current value to target value within given time.
|
||||||
*
|
*
|
||||||
@@ -1341,7 +1310,6 @@ public:
|
|||||||
* Get the interpolation manager
|
* Get the interpolation manager
|
||||||
*/
|
*/
|
||||||
static simgear::PropertyInterpolationMgr* getInterpolationMgr();
|
static simgear::PropertyInterpolationMgr* getInterpolationMgr();
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print the value of the property to a stream.
|
* Print the value of the property to a stream.
|
||||||
@@ -1839,11 +1807,7 @@ private:
|
|||||||
|
|
||||||
// Convenience functions for use in templates
|
// Convenience functions for use in templates
|
||||||
template<typename T>
|
template<typename T>
|
||||||
#if PROPS_STANDALONE
|
|
||||||
T
|
|
||||||
#else
|
|
||||||
typename boost::disable_if<boost::is_enum<T>, T>::type
|
typename boost::disable_if<boost::is_enum<T>, T>::type
|
||||||
#endif
|
|
||||||
getValue(const SGPropertyNode*);
|
getValue(const SGPropertyNode*);
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
@@ -1907,11 +1871,7 @@ namespace simgear
|
|||||||
|
|
||||||
/** Extract enum from SGPropertyNode */
|
/** Extract enum from SGPropertyNode */
|
||||||
template<typename T>
|
template<typename T>
|
||||||
#if PROPS_STANDALONE
|
|
||||||
inline T
|
|
||||||
#else
|
|
||||||
inline typename boost::enable_if<boost::is_enum<T>, T>::type
|
inline typename boost::enable_if<boost::is_enum<T>, T>::type
|
||||||
#endif
|
|
||||||
getValue(const SGPropertyNode* node)
|
getValue(const SGPropertyNode* node)
|
||||||
{
|
{
|
||||||
typedef simgear::enum_traits<T> Traits;
|
typedef simgear::enum_traits<T> Traits;
|
||||||
|
|||||||
@@ -326,15 +326,9 @@ public:
|
|||||||
= GL2Extensions::Get(static_cast<unsigned>(contextId), true);
|
= GL2Extensions::Get(static_cast<unsigned>(contextId), true);
|
||||||
if (!extensions)
|
if (!extensions)
|
||||||
return;
|
return;
|
||||||
#if OSG_VERSION_LESS_THAN(3,3,4)
|
|
||||||
if (!extensions->isGlslSupported())
|
if (!extensions->isGlslSupported())
|
||||||
return;
|
return;
|
||||||
value = extensions->getLanguageVersion();
|
value = extensions->getLanguageVersion();
|
||||||
#else
|
|
||||||
if (!extensions->isGlslSupported)
|
|
||||||
return;
|
|
||||||
value = extensions->glslLanguageVersion;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -363,11 +357,7 @@ public:
|
|||||||
= GL2Extensions::Get(static_cast<unsigned>(contextId), true);
|
= GL2Extensions::Get(static_cast<unsigned>(contextId), true);
|
||||||
if (!extensions)
|
if (!extensions)
|
||||||
return;
|
return;
|
||||||
#if OSG_VERSION_LESS_THAN(3,3,4)
|
|
||||||
value = extensions->isGlslSupported();
|
value = extensions->isGlslSupported();
|
||||||
#else
|
|
||||||
value = extensions->isGlslSupported;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -323,7 +323,6 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options,
|
|||||||
|
|
||||||
// Random vegetation properties
|
// Random vegetation properties
|
||||||
wood_coverage = props->getDoubleValue("wood-coverage", 0.0);
|
wood_coverage = props->getDoubleValue("wood-coverage", 0.0);
|
||||||
tree_effect = props->getStringValue("tree-effect", "Effects/tree");
|
|
||||||
tree_height = props->getDoubleValue("tree-height-m", 0.0);
|
tree_height = props->getDoubleValue("tree-height-m", 0.0);
|
||||||
tree_width = props->getDoubleValue("tree-width-m", 0.0);
|
tree_width = props->getDoubleValue("tree-width-m", 0.0);
|
||||||
tree_range = props->getDoubleValue("tree-range-m", 0.0);
|
tree_range = props->getDoubleValue("tree-range-m", 0.0);
|
||||||
|
|||||||
@@ -274,14 +274,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
inline std::string get_tree_texture () const { return tree_texture; }
|
inline std::string get_tree_texture () const { return tree_texture; }
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the effect file name to use for trees
|
|
||||||
*
|
|
||||||
* @return the effect to use for this set of trees.
|
|
||||||
*/
|
|
||||||
inline std::string get_tree_effect () const { return tree_effect; }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the cosine of the maximum tree density slope angle. We
|
* Get the cosine of the maximum tree density slope angle. We
|
||||||
* use the cosine as it can be compared directly to the z component
|
* use the cosine as it can be compared directly to the z component
|
||||||
@@ -485,9 +477,6 @@ private:
|
|||||||
// Tree texture, typically a strip of applicable tree textures
|
// Tree texture, typically a strip of applicable tree textures
|
||||||
std::string tree_texture;
|
std::string tree_texture;
|
||||||
|
|
||||||
// Tree effect to be used for a particular material
|
|
||||||
std::string tree_effect;
|
|
||||||
|
|
||||||
// Object mask, a simple RGB texture used as a mask when placing
|
// Object mask, a simple RGB texture used as a mask when placing
|
||||||
// random vegetation, objects and buildings
|
// random vegetation, objects and buildings
|
||||||
std::vector<Texture2DRef> _masks;
|
std::vector<Texture2DRef> _masks;
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ SGMaterialCache *SGMaterialLib::generateMatCache(SGGeod center)
|
|||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
SGMaterialLib::~SGMaterialLib ( void ) {
|
SGMaterialLib::~SGMaterialLib ( void ) {
|
||||||
SG_LOG( SG_TERRAIN, SG_DEBUG, "SGMaterialLib::~SGMaterialLib() size=" << matlib.size());
|
SG_LOG( SG_GENERAL, SG_INFO, "SGMaterialLib::~SGMaterialLib() size=" << matlib.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
const SGMaterial *SGMaterialLib::findMaterial(const osg::Geode* geode)
|
const SGMaterial *SGMaterialLib::findMaterial(const osg::Geode* geode)
|
||||||
@@ -244,5 +244,5 @@ SGMaterial *SGMaterialCache::find(const string& material) const
|
|||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
SGMaterialCache::~SGMaterialCache ( void ) {
|
SGMaterialCache::~SGMaterialCache ( void ) {
|
||||||
SG_LOG( SG_TERRAIN, SG_DEBUG, "SGMaterialCache::~SGMaterialCache() size=" << cache.size());
|
SG_LOG( SG_GENERAL, SG_INFO, "SGMaterialCache::~SGMaterialCache() size=" << cache.size());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -364,8 +364,6 @@ public:
|
|||||||
if (_textureProp) {
|
if (_textureProp) {
|
||||||
std::string textureName = _textureProp->getStringValue();
|
std::string textureName = _textureProp->getStringValue();
|
||||||
if (_textureName != textureName) {
|
if (_textureName != textureName) {
|
||||||
_textureName = textureName;
|
|
||||||
|
|
||||||
while (stateSet->getTextureAttribute(0,
|
while (stateSet->getTextureAttribute(0,
|
||||||
osg::StateAttribute::TEXTURE)) {
|
osg::StateAttribute::TEXTURE)) {
|
||||||
stateSet->removeTextureAttribute(0, osg::StateAttribute::TEXTURE);
|
stateSet->removeTextureAttribute(0, osg::StateAttribute::TEXTURE);
|
||||||
@@ -379,11 +377,7 @@ public:
|
|||||||
osg::StateAttribute::OVERRIDE);
|
osg::StateAttribute::OVERRIDE);
|
||||||
stateSet->setTextureMode(0, GL_TEXTURE_2D,
|
stateSet->setTextureMode(0, GL_TEXTURE_2D,
|
||||||
osg::StateAttribute::ON);
|
osg::StateAttribute::ON);
|
||||||
}
|
_textureName = textureName;
|
||||||
} else {
|
|
||||||
SG_LOG(SG_IO, SG_WARN, "texture animation: requested texture : " << textureName << " not found. Searched paths:" );
|
|
||||||
for( osgDB::FilePathList::iterator it = _texturePathList.begin(); it != _texturePathList.end(); ++it ) {
|
|
||||||
SG_LOG(SG_IO, SG_WARN, " - " << *it );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ SGModelLib::panel_func SGModelLib::static_panelFunc = NULL;
|
|||||||
void SGModelLib::init(const string &root_dir, SGPropertyNode* root)
|
void SGModelLib::init(const string &root_dir, SGPropertyNode* root)
|
||||||
{
|
{
|
||||||
osgDB::Registry::instance()->getDataFilePathList().push_front(root_dir);
|
osgDB::Registry::instance()->getDataFilePathList().push_front(root_dir);
|
||||||
osgDB::Registry::instance()->getOptions()->getDatabasePathList().push_front(root_dir);
|
|
||||||
static_propRoot = root;
|
static_propRoot = root;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +114,6 @@ SGModelLib::loadModel(const string &path,
|
|||||||
{
|
{
|
||||||
osg::ref_ptr<SGReaderWriterOptions> opt;
|
osg::ref_ptr<SGReaderWriterOptions> opt;
|
||||||
opt = SGReaderWriterOptions::copyOrCreate(osgDB::Registry::instance()->getOptions());
|
opt = SGReaderWriterOptions::copyOrCreate(osgDB::Registry::instance()->getOptions());
|
||||||
opt->getDatabasePathList().push_front( osgDB::getFilePath(path) );
|
|
||||||
opt->setPropertyNode(prop_root ? prop_root: static_propRoot.get());
|
opt->setPropertyNode(prop_root ? prop_root: static_propRoot.get());
|
||||||
opt->setModelData(data);
|
opt->setModelData(data);
|
||||||
|
|
||||||
@@ -138,10 +136,8 @@ SGModelLib::loadDeferredModel(const string &path, SGPropertyNode *prop_root,
|
|||||||
proxyNode->setLoadingExternalReferenceMode(osg::ProxyNode::DEFER_LOADING_TO_DATABASE_PAGER);
|
proxyNode->setLoadingExternalReferenceMode(osg::ProxyNode::DEFER_LOADING_TO_DATABASE_PAGER);
|
||||||
proxyNode->setFileName(0, path);
|
proxyNode->setFileName(0, path);
|
||||||
|
|
||||||
|
|
||||||
osg::ref_ptr<SGReaderWriterOptions> opt;
|
osg::ref_ptr<SGReaderWriterOptions> opt;
|
||||||
opt = SGReaderWriterOptions::copyOrCreate(osgDB::Registry::instance()->getOptions());
|
opt = SGReaderWriterOptions::copyOrCreate(osgDB::Registry::instance()->getOptions());
|
||||||
opt->getDatabasePathList().push_front( osgDB::getFilePath(path) );
|
|
||||||
opt->setPropertyNode(prop_root ? prop_root: static_propRoot.get());
|
opt->setPropertyNode(prop_root ? prop_root: static_propRoot.get());
|
||||||
opt->setModelData(data);
|
opt->setModelData(data);
|
||||||
opt->setLoadPanel(static_panelFunc);
|
opt->setLoadPanel(static_panelFunc);
|
||||||
|
|||||||
@@ -128,11 +128,7 @@ void CloudShaderGeometry::drawImplementation(RenderInfo& renderInfo) const
|
|||||||
sortData.frameSorted = frameNumber;
|
sortData.frameSorted = frameNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if OSG_VERSION_LESS_THAN(3,3,4)
|
|
||||||
const Extensions* extensions = getExtensions(state.getContextID(),true);
|
const Extensions* extensions = getExtensions(state.getContextID(),true);
|
||||||
#else
|
|
||||||
const GLExtensions* extensions = GLExtensions::Get(state.getContextID(), true);
|
|
||||||
#endif
|
|
||||||
GLfloat ua1[3] = { (GLfloat) alpha_factor,
|
GLfloat ua1[3] = { (GLfloat) alpha_factor,
|
||||||
(GLfloat) shade_factor,
|
(GLfloat) shade_factor,
|
||||||
(GLfloat) cloud_height };
|
(GLfloat) cloud_height };
|
||||||
|
|||||||
@@ -216,46 +216,6 @@ SGSun::build( SGPath path, double sun_size, SGPropertyNode *property_tree_Node )
|
|||||||
|
|
||||||
sun_transform->addChild( geode );
|
sun_transform->addChild( geode );
|
||||||
|
|
||||||
|
|
||||||
// set up the brilliance state
|
|
||||||
|
|
||||||
geode = new osg::Geode;
|
|
||||||
stateSet = geode->getOrCreateStateSet();
|
|
||||||
stateSet->setRenderBinDetails(-9, "RenderBin");
|
|
||||||
|
|
||||||
|
|
||||||
texture = SGLoadTexture2D("brilliance.png", options.get());
|
|
||||||
stateSet->setTextureAttributeAndModes(0, texture);
|
|
||||||
|
|
||||||
|
|
||||||
// Build ssg structure
|
|
||||||
brilliance_cl = new osg::Vec4Array;
|
|
||||||
brilliance_cl->push_back(osg::Vec4(1, 1, 1, 1));
|
|
||||||
|
|
||||||
double brilliance_size = sun_size * 12.0;
|
|
||||||
osg::Vec3Array* brilliance_vl = new osg::Vec3Array;
|
|
||||||
brilliance_vl->push_back(osg::Vec3(-brilliance_size, 0, -brilliance_size));
|
|
||||||
brilliance_vl->push_back(osg::Vec3(brilliance_size, 0, -brilliance_size));
|
|
||||||
brilliance_vl->push_back(osg::Vec3(-brilliance_size, 0, brilliance_size));
|
|
||||||
brilliance_vl->push_back(osg::Vec3(brilliance_size, 0, brilliance_size));
|
|
||||||
|
|
||||||
osg::Vec2Array* brilliance_tl = new osg::Vec2Array;
|
|
||||||
brilliance_tl->push_back(osg::Vec2(0, 0));
|
|
||||||
brilliance_tl->push_back(osg::Vec2(1, 0));
|
|
||||||
brilliance_tl->push_back(osg::Vec2(0, 1));
|
|
||||||
brilliance_tl->push_back(osg::Vec2(1, 1));
|
|
||||||
|
|
||||||
geometry = new osg::Geometry;
|
|
||||||
geometry->setUseDisplayList(false);
|
|
||||||
geometry->setVertexArray(brilliance_vl);
|
|
||||||
geometry->setColorArray(brilliance_cl.get(), osg::Array::BIND_OVERALL);
|
|
||||||
geometry->setNormalBinding(osg::Geometry::BIND_OFF);
|
|
||||||
geometry->setTexCoordArray(0, brilliance_tl, osg::Array::BIND_PER_VERTEX);
|
|
||||||
geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
|
||||||
geode->addDrawable(geometry);
|
|
||||||
|
|
||||||
sun_transform->addChild( geode );
|
|
||||||
|
|
||||||
// force a repaint of the sun colors with arbitrary defaults
|
// force a repaint of the sun colors with arbitrary defaults
|
||||||
repaint( 0.0, 1.0 );
|
repaint( 0.0, 1.0 );
|
||||||
|
|
||||||
@@ -302,7 +262,7 @@ bool SGSun::repaint( double sun_angle, double new_visibility ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ok, now let's go and generate the sun and scene color
|
// ok, now let's go and generate the sun and scene color
|
||||||
osg::Vec4 i_halo_color, o_halo_color, scene_color, sun_color, brilliance_color;
|
osg::Vec4 i_halo_color, o_halo_color, scene_color, sun_color;
|
||||||
|
|
||||||
// Some comments:
|
// Some comments:
|
||||||
// * When the sunangle changes, light has to travel a longer
|
// * When the sunangle changes, light has to travel a longer
|
||||||
@@ -376,29 +336,16 @@ bool SGSun::repaint( double sun_angle, double new_visibility ) {
|
|||||||
if (o_halo_color[3] > 1) o_halo_color[3] = 1;
|
if (o_halo_color[3] > 1) o_halo_color[3] = 1;
|
||||||
if (o_halo_color[3] < 0) o_halo_color[3] = 0;
|
if (o_halo_color[3] < 0) o_halo_color[3] = 0;
|
||||||
|
|
||||||
brilliance_color[0] = i_halo_color[0];
|
|
||||||
brilliance_color[1] = i_halo_color[1];
|
|
||||||
brilliance_color[2] = i_halo_color[2];
|
|
||||||
|
|
||||||
double norm = (i_halo_color[0] * i_halo_color[0] + i_halo_color[1] * i_halo_color[1] + i_halo_color[2] * i_halo_color[2])/1.732;
|
|
||||||
|
|
||||||
brilliance_color[3] = pow(norm, 6.0);
|
|
||||||
if (brilliance_color[3] < 0.0) {brilliance_color[3] = 0.0;}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
gamma_correct_rgb( i_halo_color._v );
|
gamma_correct_rgb( i_halo_color._v );
|
||||||
gamma_correct_rgb( o_halo_color._v );
|
gamma_correct_rgb( o_halo_color._v );
|
||||||
gamma_correct_rgb( scene_color._v );
|
gamma_correct_rgb( scene_color._v );
|
||||||
gamma_correct_rgb( sun_color._v );
|
gamma_correct_rgb( sun_color._v );
|
||||||
gamma_correct_rgb( brilliance_color._v );
|
|
||||||
|
|
||||||
if (sun_angle >91.0 * 3.1415/180.0 + horizon_angle)
|
if (sun_angle >91.0 * 3.1415/180.0 + horizon_angle)
|
||||||
{
|
{
|
||||||
sun_color[3] = 0;
|
sun_color[3] = 0;
|
||||||
o_halo_color[3]=0;
|
o_halo_color[3]=0;
|
||||||
i_halo_color[3]=0;
|
i_halo_color[3]=0;
|
||||||
brilliance_color[3]=0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(*sun_cl)[0] = sun_color;
|
(*sun_cl)[0] = sun_color;
|
||||||
@@ -409,8 +356,6 @@ bool SGSun::repaint( double sun_angle, double new_visibility ) {
|
|||||||
ihalo_cl->dirty();
|
ihalo_cl->dirty();
|
||||||
(*ohalo_cl)[0] = o_halo_color;
|
(*ohalo_cl)[0] = o_halo_color;
|
||||||
ohalo_cl->dirty();
|
ohalo_cl->dirty();
|
||||||
(*brilliance_cl)[0] = brilliance_color;
|
|
||||||
brilliance_cl->dirty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -427,14 +372,19 @@ bool SGSun::reposition( double rightAscension, double declination,
|
|||||||
{
|
{
|
||||||
// GST - GMT sidereal time
|
// GST - GMT sidereal time
|
||||||
osg::Matrix T2, RA, DEC;
|
osg::Matrix T2, RA, DEC;
|
||||||
|
|
||||||
// xglRotatef( ((SGD_RADIANS_TO_DEGREES * rightAscension)- 90.0),
|
// xglRotatef( ((SGD_RADIANS_TO_DEGREES * rightAscension)- 90.0),
|
||||||
// 0.0, 0.0, 1.0);
|
// 0.0, 0.0, 1.0);
|
||||||
RA.makeRotate(rightAscension - 90*SGD_DEGREES_TO_RADIANS, osg::Vec3(0, 0, 1));
|
RA.makeRotate(rightAscension - 90*SGD_DEGREES_TO_RADIANS, osg::Vec3(0, 0, 1));
|
||||||
|
|
||||||
// xglRotatef((SGD_RADIANS_TO_DEGREES * declination), 1.0, 0.0, 0.0);
|
// xglRotatef((SGD_RADIANS_TO_DEGREES * declination), 1.0, 0.0, 0.0);
|
||||||
DEC.makeRotate(declination, osg::Vec3(1, 0, 0));
|
DEC.makeRotate(declination, osg::Vec3(1, 0, 0));
|
||||||
|
|
||||||
// xglTranslatef(0,sun_dist);
|
// xglTranslatef(0,sun_dist);
|
||||||
T2.makeTranslate(osg::Vec3(0, sun_dist, 0));
|
T2.makeTranslate(osg::Vec3(0, sun_dist, 0));
|
||||||
|
|
||||||
sun_transform->setMatrix(T2*DEC*RA);
|
sun_transform->setMatrix(T2*DEC*RA);
|
||||||
|
|
||||||
// Suncolor related things:
|
// Suncolor related things:
|
||||||
if ( prev_sun_angle != sun_angle ) {
|
if ( prev_sun_angle != sun_angle ) {
|
||||||
if ( sun_angle == 0 ) sun_angle = 0.1;
|
if ( sun_angle == 0 ) sun_angle = 0.1;
|
||||||
@@ -462,7 +412,7 @@ bool SGSun::reposition( double rightAscension, double declination,
|
|||||||
if ( alt_half < 0.0 ) alt_half = 0.0;
|
if ( alt_half < 0.0 ) alt_half = 0.0;
|
||||||
|
|
||||||
//angle at which the sun is visible below the horizon
|
//angle at which the sun is visible below the horizon
|
||||||
horizon_angle = acos(min(r_earth/position_radius, 1.0));
|
horizon_angle = acos(r_earth/position_radius);
|
||||||
|
|
||||||
// Push the data to the property tree, so it can be used in the enviromental code
|
// Push the data to the property tree, so it can be used in the enviromental code
|
||||||
if ( env_node ){
|
if ( env_node ){
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ class SGSun : public SGReferenced {
|
|||||||
osg::ref_ptr<osg::Vec4Array> scene_cl;
|
osg::ref_ptr<osg::Vec4Array> scene_cl;
|
||||||
osg::ref_ptr<osg::Vec4Array> ihalo_cl;
|
osg::ref_ptr<osg::Vec4Array> ihalo_cl;
|
||||||
osg::ref_ptr<osg::Vec4Array> ohalo_cl;
|
osg::ref_ptr<osg::Vec4Array> ohalo_cl;
|
||||||
osg::ref_ptr<osg::Vec4Array> brilliance_cl;
|
|
||||||
|
|
||||||
double visibility;
|
double visibility;
|
||||||
double prev_sun_angle;
|
double prev_sun_angle;
|
||||||
|
|||||||
@@ -44,7 +44,6 @@
|
|||||||
#include <simgear/misc/sgstream.hxx>
|
#include <simgear/misc/sgstream.hxx>
|
||||||
#include <simgear/scene/util/OptionsReadFileCallback.hxx>
|
#include <simgear/scene/util/OptionsReadFileCallback.hxx>
|
||||||
#include <simgear/scene/util/OsgMath.hxx>
|
#include <simgear/scene/util/OsgMath.hxx>
|
||||||
#include <simgear/scene/util/QuadTreeBuilder.hxx>
|
|
||||||
#include <simgear/scene/util/RenderConstants.hxx>
|
#include <simgear/scene/util/RenderConstants.hxx>
|
||||||
#include <simgear/scene/util/SGReaderWriterOptions.hxx>
|
#include <simgear/scene/util/SGReaderWriterOptions.hxx>
|
||||||
#include <simgear/scene/tgdb/apt_signs.hxx>
|
#include <simgear/scene/tgdb/apt_signs.hxx>
|
||||||
@@ -114,79 +113,48 @@ struct ReaderWriterSTG::_ModelBin {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class DelayLoadReadFileCallback : public OptionsReadFileCallback {
|
class DelayLoadReadFileCallback : public OptionsReadFileCallback {
|
||||||
|
|
||||||
private:
|
|
||||||
// QuadTreeBuilder for structuring static objects
|
|
||||||
struct MakeQuadLeaf {
|
|
||||||
osg::LOD* operator() () const { return new osg::LOD; }
|
|
||||||
};
|
|
||||||
struct AddModelLOD {
|
|
||||||
void operator() (osg::LOD* leaf, _ObjectStatic o) const
|
|
||||||
{
|
|
||||||
osg::ref_ptr<osg::Node> node;
|
|
||||||
if (o._proxy) {
|
|
||||||
osg::ref_ptr<osg::ProxyNode> proxy = new osg::ProxyNode;
|
|
||||||
proxy->setName("proxyNode");
|
|
||||||
proxy->setLoadingExternalReferenceMode(osg::ProxyNode::DEFER_LOADING_TO_DATABASE_PAGER);
|
|
||||||
proxy->setFileName(0, o._name);
|
|
||||||
proxy->setDatabaseOptions(o._options.get());
|
|
||||||
|
|
||||||
// Give the node some values so the Quadtree builder has
|
|
||||||
// a BoundingBox to work with prior to the model being loaded.
|
|
||||||
proxy->setCenter(osg::Vec3f(0.0f,0.0f,0.0f));
|
|
||||||
proxy->setRadius(10);
|
|
||||||
proxy->setCenterMode(osg::ProxyNode::UNION_OF_BOUNDING_SPHERE_AND_USER_DEFINED);
|
|
||||||
node = proxy;
|
|
||||||
} else {
|
|
||||||
node = osgDB::readRefNodeFile(o._name, o._options.get());
|
|
||||||
if (!node.valid()) {
|
|
||||||
SG_LOG(SG_TERRAIN, SG_ALERT, o._errorLocation << ": Failed to load "
|
|
||||||
<< o._token << " '" << o._name << "'");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (SGPath(o._name).lower_extension() == "ac")
|
|
||||||
node->setNodeMask(~simgear::MODELLIGHT_BIT);
|
|
||||||
|
|
||||||
osg::Matrix matrix;
|
|
||||||
matrix = makeZUpFrame(SGGeod::fromDegM(o._lon, o._lat, o._elev));
|
|
||||||
matrix.preMultRotate(osg::Quat(SGMiscd::deg2rad(o._hdg), osg::Vec3(0, 0, 1)));
|
|
||||||
matrix.preMultRotate(osg::Quat(SGMiscd::deg2rad(o._pitch), osg::Vec3(0, 1, 0)));
|
|
||||||
matrix.preMultRotate(osg::Quat(SGMiscd::deg2rad(o._roll), osg::Vec3(1, 0, 0)));
|
|
||||||
|
|
||||||
osg::MatrixTransform* matrixTransform;
|
|
||||||
matrixTransform = new osg::MatrixTransform(matrix);
|
|
||||||
matrixTransform->setName("rotateStaticObject");
|
|
||||||
matrixTransform->setDataVariance(osg::Object::STATIC);
|
|
||||||
matrixTransform->addChild(node.get());
|
|
||||||
leaf->addChild(matrixTransform, 0, 20000); //TODO: Make configurable?
|
|
||||||
}
|
|
||||||
};
|
|
||||||
struct GetModelLODCoord {
|
|
||||||
GetModelLODCoord() {}
|
|
||||||
GetModelLODCoord(const GetModelLODCoord& rhs)
|
|
||||||
{}
|
|
||||||
osg::Vec3 operator() (const _ObjectStatic& o) const
|
|
||||||
{
|
|
||||||
SGVec3d coord;
|
|
||||||
SGGeodesy::SGGeodToCart(SGGeod::fromDegM(o._lon, o._lat, o._elev), coord);
|
|
||||||
return toOsg(coord);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
typedef QuadTreeBuilder<osg::LOD*, _ObjectStatic, MakeQuadLeaf, AddModelLOD,
|
|
||||||
GetModelLODCoord> STGObjectsQuadtree;
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual osgDB::ReaderWriter::ReadResult
|
virtual osgDB::ReaderWriter::ReadResult
|
||||||
readNode(const std::string&, const osgDB::Options*)
|
readNode(const std::string&, const osgDB::Options*)
|
||||||
{
|
{
|
||||||
STGObjectsQuadtree quadtree((GetModelLODCoord()), (AddModelLOD()));
|
osg::ref_ptr<osg::Group> group = new osg::Group;
|
||||||
quadtree.buildQuadTree(_objectStaticList.begin(), _objectStaticList.end());
|
|
||||||
osg::ref_ptr<osg::Group> group = quadtree.getRoot();
|
|
||||||
group->setName("STG-group-A");
|
group->setName("STG-group-A");
|
||||||
group->setDataVariance(osg::Object::STATIC);
|
group->setDataVariance(osg::Object::STATIC);
|
||||||
|
|
||||||
|
for (std::list<_ObjectStatic>::iterator i = _objectStaticList.begin(); i != _objectStaticList.end(); ++i) {
|
||||||
|
osg::ref_ptr<osg::Node> node;
|
||||||
|
if (i->_proxy) {
|
||||||
|
osg::ref_ptr<osg::ProxyNode> proxy = new osg::ProxyNode;
|
||||||
|
proxy->setName("proxyNode");
|
||||||
|
proxy->setLoadingExternalReferenceMode(osg::ProxyNode::DEFER_LOADING_TO_DATABASE_PAGER);
|
||||||
|
proxy->setFileName(0, i->_name);
|
||||||
|
proxy->setDatabaseOptions(i->_options.get());
|
||||||
|
node = proxy;
|
||||||
|
} else {
|
||||||
|
node = osgDB::readRefNodeFile(i->_name, i->_options.get());
|
||||||
|
if (!node.valid()) {
|
||||||
|
SG_LOG(SG_TERRAIN, SG_ALERT, i->_errorLocation << ": Failed to load "
|
||||||
|
<< i->_token << " '" << i->_name << "'");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (SGPath(i->_name).lower_extension() == "ac")
|
||||||
|
node->setNodeMask(~simgear::MODELLIGHT_BIT);
|
||||||
|
|
||||||
|
osg::Matrix matrix;
|
||||||
|
matrix = makeZUpFrame(SGGeod::fromDegM(i->_lon, i->_lat, i->_elev));
|
||||||
|
matrix.preMultRotate(osg::Quat(SGMiscd::deg2rad(i->_hdg), osg::Vec3(0, 0, 1)));
|
||||||
|
matrix.preMultRotate(osg::Quat(SGMiscd::deg2rad(i->_pitch), osg::Vec3(0, 1, 0)));
|
||||||
|
matrix.preMultRotate(osg::Quat(SGMiscd::deg2rad(i->_roll), osg::Vec3(1, 0, 0)));
|
||||||
|
|
||||||
|
osg::MatrixTransform* matrixTransform;
|
||||||
|
matrixTransform = new osg::MatrixTransform(matrix);
|
||||||
|
matrixTransform->setName("positionStaticObject");
|
||||||
|
matrixTransform->setDataVariance(osg::Object::STATIC);
|
||||||
|
matrixTransform->addChild(node.get());
|
||||||
|
group->addChild(matrixTransform);
|
||||||
|
}
|
||||||
|
|
||||||
simgear::AirportSignBuilder signBuilder(_options->getMaterialLib(), _bucket.get_center());
|
simgear::AirportSignBuilder signBuilder(_options->getMaterialLib(), _bucket.get_center());
|
||||||
for (std::list<_Sign>::iterator i = _signList.begin(); i != _signList.end(); ++i)
|
for (std::list<_Sign>::iterator i = _signList.begin(); i != _signList.end(); ++i)
|
||||||
signBuilder.addSign(SGGeod::fromDegM(i->_lon, i->_lat, i->_elev), i->_hdg, i->_name, i->_size);
|
signBuilder.addSign(SGGeod::fromDegM(i->_lon, i->_lat, i->_elev), i->_hdg, i->_name, i->_size);
|
||||||
|
|||||||
@@ -386,10 +386,10 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
|||||||
int row = ((int) (mt_rand(&seed) * 1000)) % 5;
|
int row = ((int) (mt_rand(&seed) * 1000)) % 5;
|
||||||
float base_y = (float) row * 16.0 * 3.0 / 1024.0;
|
float base_y = (float) row * 16.0 * 3.0 / 1024.0;
|
||||||
float top_y = base_y + 16.0 * (float) building.floors / 1024.0;
|
float top_y = base_y + 16.0 * (float) building.floors / 1024.0;
|
||||||
float left_x = 32.0 / 1024.0 * SGMisc<double>::round((float)building.width / 6.0f);
|
float left_x = 32.0 / 1024.0 * round((float) building.width / 6.0f);
|
||||||
float right_x = 0.0f;
|
float right_x = 0.0f;
|
||||||
float front_x = 384.0/1024.0;
|
float front_x = 384.0/1024.0;
|
||||||
float back_x = 384.0 / 1024.0 + 32.0 / 1024.0 * SGMisc<double>::round((float)building.depth / 6.0f);
|
float back_x = 384.0/1024.0 + 32.0 / 1024.0 * round((float) building.depth/ 6.0f);
|
||||||
|
|
||||||
// BASEMENT - uses the baseline texture
|
// BASEMENT - uses the baseline texture
|
||||||
for (unsigned int i = 0; i < 16; i++) {
|
for (unsigned int i = 0; i < 16; i++) {
|
||||||
@@ -424,7 +424,7 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
|||||||
if (building.pitched) {
|
if (building.pitched) {
|
||||||
// Use the entire height of the roof texture
|
// Use the entire height of the roof texture
|
||||||
top_y = base_y + 16.0 * 3.0 / 1024.0;
|
top_y = base_y + 16.0 * 3.0 / 1024.0;
|
||||||
left_x = 512 / 1024.0 + 32.0 / 1024.0 * SGMisc<double>::round(building.width / 6.0f);
|
left_x = 512/1024.0 + 32.0 / 1024.0 * round(building.width / 6.0f);
|
||||||
right_x = 512/1024.0;
|
right_x = 512/1024.0;
|
||||||
front_x = 480.0/1024.0;
|
front_x = 480.0/1024.0;
|
||||||
back_x = 512.0/1024.0;
|
back_x = 512.0/1024.0;
|
||||||
@@ -475,7 +475,7 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
|||||||
int column = ((int) (mt_rand(&seed) * 1000)) % 5;
|
int column = ((int) (mt_rand(&seed) * 1000)) % 5;
|
||||||
float base_y = 288 / 1024.0;
|
float base_y = 288 / 1024.0;
|
||||||
float top_y = base_y + 16.0 * (float) building.floors / 1024.0;
|
float top_y = base_y + 16.0 * (float) building.floors / 1024.0;
|
||||||
float left_x = column * 192.0 / 1024.0 + 32.0 / 1024.0 * SGMisc<double>::round((float)building.width / 10.0f);
|
float left_x = column * 192.0 /1024.0 + 32.0 / 1024.0 * round((float) building.width / 10.0f);
|
||||||
float right_x = column * 192.0 /1024.0;
|
float right_x = column * 192.0 /1024.0;
|
||||||
|
|
||||||
// BASEMENT - uses the baseline texture
|
// BASEMENT - uses the baseline texture
|
||||||
@@ -560,7 +560,7 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
|||||||
int column = ((int) (mt_rand(&seed) * 1000)) % 8;
|
int column = ((int) (mt_rand(&seed) * 1000)) % 8;
|
||||||
float base_y = 576 / 1024.0;
|
float base_y = 576 / 1024.0;
|
||||||
float top_y = base_y + 16.0 * (float) building.floors / 1024.0;
|
float top_y = base_y + 16.0 * (float) building.floors / 1024.0;
|
||||||
float left_x = column * 128.0 / 1024.0 + 32.0 / 1024.0 * SGMisc<double>::round((float)building.width / 20.0f);
|
float left_x = column * 128.0 /1024.0 + 32.0 / 1024.0 * round((float) building.width / 20.0f);
|
||||||
float right_x = column * 128.0 /1024.0;
|
float right_x = column * 128.0 /1024.0;
|
||||||
|
|
||||||
// BASEMENT - uses the baseline texture
|
// BASEMENT - uses the baseline texture
|
||||||
|
|||||||
@@ -291,8 +291,7 @@ public:
|
|||||||
float vegetation_density,
|
float vegetation_density,
|
||||||
float cos_max_density_angle,
|
float cos_max_density_angle,
|
||||||
float cos_zero_density_angle,
|
float cos_zero_density_angle,
|
||||||
std::vector<SGVec3f>& points,
|
std::vector<SGVec3f>& points)
|
||||||
std::vector<SGVec3f>& normals)
|
|
||||||
{
|
{
|
||||||
if ( !geometries.empty() ) {
|
if ( !geometries.empty() ) {
|
||||||
const osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometries[0]->getVertexArray());
|
const osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometries[0]->getVertexArray());
|
||||||
@@ -367,11 +366,9 @@ public:
|
|||||||
if (mt_rand(&seed) < img->getColor(x, y).g()) {
|
if (mt_rand(&seed) < img->getColor(x, y).g()) {
|
||||||
// The red channel contains the rotation for this object
|
// The red channel contains the rotation for this object
|
||||||
points.push_back(randomPoint);
|
points.push_back(randomPoint);
|
||||||
normals.push_back(normalize(normal));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
points.push_back(randomPoint);
|
points.push_back(randomPoint);
|
||||||
normals.push_back(normalize(normal));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,6 @@
|
|||||||
#include <osg/Geometry>
|
#include <osg/Geometry>
|
||||||
#include <osg/PrimitiveSet>
|
#include <osg/PrimitiveSet>
|
||||||
#include <osg/Texture2D>
|
#include <osg/Texture2D>
|
||||||
#include <osg/ref_ptr>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <simgear/math/sg_random.h>
|
#include <simgear/math/sg_random.h>
|
||||||
@@ -123,16 +122,16 @@ public:
|
|||||||
osg::DrawElements* getDrawElements()
|
osg::DrawElements* getDrawElements()
|
||||||
{
|
{
|
||||||
if (count > 65535) {
|
if (count > 65535) {
|
||||||
_ushortElements = 0;
|
free (_ushortElements);
|
||||||
return _uintElements;
|
return _uintElements;
|
||||||
} else {
|
} else {
|
||||||
_uintElements = 0;
|
free (_uintElements);
|
||||||
return _ushortElements;
|
return _ushortElements;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
osg::ref_ptr<osg::DrawElementsUShort> _ushortElements;
|
osg::DrawElementsUShort* _ushortElements;
|
||||||
osg::ref_ptr<osg::DrawElementsUInt> _uintElements;
|
osg::DrawElementsUInt* _uintElements;
|
||||||
unsigned count;
|
unsigned count;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -216,8 +215,7 @@ public:
|
|||||||
float vegetation_density,
|
float vegetation_density,
|
||||||
float cos_max_density_angle,
|
float cos_max_density_angle,
|
||||||
float cos_zero_density_angle,
|
float cos_zero_density_angle,
|
||||||
std::vector<SGVec3f>& points,
|
std::vector<SGVec3f>& points)
|
||||||
std::vector<SGVec3f>& normals)
|
|
||||||
{
|
{
|
||||||
unsigned num = getNumTriangles();
|
unsigned num = getNumTriangles();
|
||||||
for (unsigned i = 0; i < num; ++i) {
|
for (unsigned i = 0; i < num; ++i) {
|
||||||
@@ -283,11 +281,9 @@ public:
|
|||||||
if (mt_rand(&seed) < img->getColor(x, y).g()) {
|
if (mt_rand(&seed) < img->getColor(x, y).g()) {
|
||||||
// The red channel contains the rotation for this object
|
// The red channel contains the rotation for this object
|
||||||
points.push_back(randomPoint);
|
points.push_back(randomPoint);
|
||||||
normals.push_back(normalize(normal));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
points.push_back(randomPoint);
|
points.push_back(randomPoint);
|
||||||
normals.push_back(normalize(normal));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ public:
|
|||||||
virtual ~SGTileDetailsCallback()
|
virtual ~SGTileDetailsCallback()
|
||||||
{
|
{
|
||||||
num_tdcb--;
|
num_tdcb--;
|
||||||
SG_LOG( SG_TERRAIN, SG_DEBUG, "SGTileDetailsCallback::~SGTileDetailsCallback() num cbs left " << num_tdcb );
|
SG_LOG( SG_GENERAL, SG_INFO, "SGTileDetailsCallback::~SGTileDetailsCallback() num cbs left " << num_tdcb );
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual osgDB::ReaderWriter::ReadResult readNode(
|
virtual osgDB::ReaderWriter::ReadResult readNode(
|
||||||
@@ -723,7 +723,6 @@ public:
|
|||||||
BOOST_FOREACH(bin, randomForest)
|
BOOST_FOREACH(bin, randomForest)
|
||||||
{
|
{
|
||||||
if ((bin->texture == mat->get_tree_texture() ) &&
|
if ((bin->texture == mat->get_tree_texture() ) &&
|
||||||
(bin->teffect == mat->get_tree_effect() ) &&
|
|
||||||
(bin->texture_varieties == mat->get_tree_varieties()) &&
|
(bin->texture_varieties == mat->get_tree_varieties()) &&
|
||||||
(bin->range == mat->get_tree_range() ) &&
|
(bin->range == mat->get_tree_range() ) &&
|
||||||
(bin->width == mat->get_tree_width() ) &&
|
(bin->width == mat->get_tree_width() ) &&
|
||||||
@@ -736,9 +735,7 @@ public:
|
|||||||
if (!found) {
|
if (!found) {
|
||||||
bin = new TreeBin();
|
bin = new TreeBin();
|
||||||
bin->texture = mat->get_tree_texture();
|
bin->texture = mat->get_tree_texture();
|
||||||
SG_LOG(SG_TERRAIN, SG_DEBUG, "Tree texture " << bin->texture);
|
SG_LOG(SG_INPUT, SG_DEBUG, "Tree texture " << bin->texture);
|
||||||
bin->teffect = mat->get_tree_effect();
|
|
||||||
SG_LOG(SG_TERRAIN, SG_DEBUG, "Tree effect " << bin->teffect);
|
|
||||||
bin->range = mat->get_tree_range();
|
bin->range = mat->get_tree_range();
|
||||||
bin->width = mat->get_tree_width();
|
bin->width = mat->get_tree_width();
|
||||||
bin->height = mat->get_tree_height();
|
bin->height = mat->get_tree_height();
|
||||||
@@ -747,19 +744,16 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<SGVec3f> randomPoints;
|
std::vector<SGVec3f> randomPoints;
|
||||||
std::vector<SGVec3f> randomPointNormals;
|
|
||||||
matTris[i].addRandomTreePoints(wood_coverage,
|
matTris[i].addRandomTreePoints(wood_coverage,
|
||||||
mat->get_one_object_mask(matTris[i].getTextureIndex()),
|
mat->get_one_object_mask(matTris[i].getTextureIndex()),
|
||||||
vegetation_density,
|
vegetation_density,
|
||||||
mat->get_cos_tree_max_density_slope_angle(),
|
mat->get_cos_tree_max_density_slope_angle(),
|
||||||
mat->get_cos_tree_zero_density_slope_angle(),
|
mat->get_cos_tree_zero_density_slope_angle(),
|
||||||
randomPoints,
|
randomPoints);
|
||||||
randomPointNormals);
|
|
||||||
|
|
||||||
std::vector<SGVec3f>::iterator k;
|
std::vector<SGVec3f>::iterator k;
|
||||||
std::vector<SGVec3f>::iterator j;
|
for (k = randomPoints.begin(); k != randomPoints.end(); ++k) {
|
||||||
for (k = randomPoints.begin(), j = randomPointNormals.begin(); k != randomPoints.end(); ++k, ++j) {
|
bin->insert(*k);
|
||||||
bin->insert(*k, *j);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -789,6 +783,11 @@ public:
|
|||||||
float coverage = mat->get_light_coverage();
|
float coverage = mat->get_light_coverage();
|
||||||
if (coverage <= 0)
|
if (coverage <= 0)
|
||||||
continue;
|
continue;
|
||||||
|
if (coverage < 10000.0) {
|
||||||
|
SG_LOG(SG_INPUT, SG_ALERT, "Light coverage is "
|
||||||
|
<< coverage << ", pushing up to 10000");
|
||||||
|
coverage = 10000;
|
||||||
|
}
|
||||||
|
|
||||||
int texIndex = matTris[i].getTextureIndex();
|
int texIndex = matTris[i].getTextureIndex();
|
||||||
|
|
||||||
@@ -872,7 +871,7 @@ public:
|
|||||||
lightGroup->addChild(groundLights2);
|
lightGroup->addChild(groundLights2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! vasiLights.empty()) {
|
if (vasiLights.empty()) {
|
||||||
EffectGeode* vasiGeode = new EffectGeode;
|
EffectGeode* vasiGeode = new EffectGeode;
|
||||||
Effect* vasiEffect = getLightEffect(24, osg::Vec3(1, 0.0001, 0.000001), 1, 24, true, _options);
|
Effect* vasiEffect = getLightEffect(24, osg::Vec3(1, 0.0001, 0.000001), 1, 24, true, _options);
|
||||||
vasiGeode->setEffect(vasiEffect);
|
vasiGeode->setEffect(vasiEffect);
|
||||||
|
|||||||
@@ -47,11 +47,7 @@ void ShaderGeometry::addObject(const Vec3& position, float scale,
|
|||||||
void ShaderGeometry::drawImplementation(osg::RenderInfo& renderInfo) const
|
void ShaderGeometry::drawImplementation(osg::RenderInfo& renderInfo) const
|
||||||
{
|
{
|
||||||
State& state = *renderInfo.getState();
|
State& state = *renderInfo.getState();
|
||||||
#if OSG_VERSION_LESS_THAN(3,3,4)
|
|
||||||
const Extensions* extensions = getExtensions(state.getContextID(), true);
|
const Extensions* extensions = getExtensions(state.getContextID(), true);
|
||||||
#else
|
|
||||||
const GLExtensions* extensions = GLExtensions::Get(state.getContextID(), true);
|
|
||||||
#endif
|
|
||||||
Vec4Array::const_iterator citer = _posScaleArray->begin();
|
Vec4Array::const_iterator citer = _posScaleArray->begin();
|
||||||
Vec4Array::const_iterator cend = _posScaleArray->end();
|
Vec4Array::const_iterator cend = _posScaleArray->end();
|
||||||
FloatArray::const_iterator viter = _vertexAttribArray->begin();
|
FloatArray::const_iterator viter = _vertexAttribArray->begin();
|
||||||
|
|||||||
@@ -49,7 +49,6 @@
|
|||||||
#include <simgear/scene/util/QuadTreeBuilder.hxx>
|
#include <simgear/scene/util/QuadTreeBuilder.hxx>
|
||||||
#include <simgear/scene/util/RenderConstants.hxx>
|
#include <simgear/scene/util/RenderConstants.hxx>
|
||||||
#include <simgear/scene/util/StateAttributeFactory.hxx>
|
#include <simgear/scene/util/StateAttributeFactory.hxx>
|
||||||
#include <simgear/scene/util/SGReaderWriterOptions.hxx>
|
|
||||||
#include <simgear/structure/OSGUtils.hxx>
|
#include <simgear/structure/OSGUtils.hxx>
|
||||||
|
|
||||||
#include "ShaderGeometry.hxx"
|
#include "ShaderGeometry.hxx"
|
||||||
@@ -63,9 +62,6 @@ using namespace osg;
|
|||||||
namespace simgear
|
namespace simgear
|
||||||
{
|
{
|
||||||
|
|
||||||
bool use_tree_shadows;
|
|
||||||
bool use_tree_normals;
|
|
||||||
|
|
||||||
// Tree instance scheme:
|
// Tree instance scheme:
|
||||||
// vertex - local position of quad vertex.
|
// vertex - local position of quad vertex.
|
||||||
// normal - x y scaling, z number of varieties
|
// normal - x y scaling, z number of varieties
|
||||||
@@ -168,24 +164,15 @@ Geometry* createTreeGeometry(float width, float height, int varieties)
|
|||||||
// Positions
|
// Positions
|
||||||
quadGeom->setColorArray(new Vec3Array);
|
quadGeom->setColorArray(new Vec3Array);
|
||||||
quadGeom->setColorBinding(Geometry::BIND_PER_VERTEX);
|
quadGeom->setColorBinding(Geometry::BIND_PER_VERTEX);
|
||||||
// Normals
|
FloatArray* rotation = new FloatArray(2);
|
||||||
if (use_tree_shadows || use_tree_normals)
|
|
||||||
{
|
|
||||||
quadGeom->setSecondaryColorArray(new Vec3Array);
|
|
||||||
quadGeom->setSecondaryColorBinding(Geometry::BIND_PER_VERTEX);
|
|
||||||
}
|
|
||||||
FloatArray* rotation = new FloatArray(3);
|
|
||||||
(*rotation)[0] = 0.0;
|
(*rotation)[0] = 0.0;
|
||||||
(*rotation)[1] = PI_2;
|
(*rotation)[1] = PI_2;
|
||||||
if (use_tree_shadows) {(*rotation)[2] = -1.0;}
|
|
||||||
quadGeom->setFogCoordArray(rotation);
|
quadGeom->setFogCoordArray(rotation);
|
||||||
quadGeom->setFogCoordBinding(Geometry::BIND_PER_PRIMITIVE_SET);
|
quadGeom->setFogCoordBinding(Geometry::BIND_PER_PRIMITIVE_SET);
|
||||||
// The primitive sets render the same geometry, but the second
|
// The primitive sets render the same geometry, but the second
|
||||||
// will rotated 90 degrees by the vertex shader, which uses the
|
// will rotated 90 degrees by the vertex shader, which uses the
|
||||||
// fog coordinate as a rotation.
|
// fog coordinate as a rotation.
|
||||||
int imax = 2;
|
for (int i = 0; i < 2; ++i)
|
||||||
if (use_tree_shadows) {imax = 3;}
|
|
||||||
for (int i = 0; i < imax; ++i)
|
|
||||||
quadGeom->addPrimitiveSet(new DrawArrays(PrimitiveSet::QUADS));
|
quadGeom->addPrimitiveSet(new DrawArrays(PrimitiveSet::QUADS));
|
||||||
return quadGeom;
|
return quadGeom;
|
||||||
}
|
}
|
||||||
@@ -197,17 +184,13 @@ EffectGeode* createTreeGeode(float width, float height, int varieties)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addTreeToLeafGeode(Geode* geode, const SGVec3f& p, const SGVec3f& t)
|
void addTreeToLeafGeode(Geode* geode, const SGVec3f& p)
|
||||||
{
|
{
|
||||||
Vec3 pos = toOsg(p);
|
Vec3 pos = toOsg(p);
|
||||||
Vec3 ter = toOsg(t);
|
|
||||||
unsigned int numDrawables = geode->getNumDrawables();
|
unsigned int numDrawables = geode->getNumDrawables();
|
||||||
Geometry* geom
|
Geometry* geom
|
||||||
= static_cast<Geometry*>(geode->getDrawable(numDrawables - 1));
|
= static_cast<Geometry*>(geode->getDrawable(numDrawables - 1));
|
||||||
Vec3Array* posArray = static_cast<Vec3Array*>(geom->getColorArray());
|
Vec3Array* posArray = static_cast<Vec3Array*>(geom->getColorArray());
|
||||||
Vec3Array* tnormalArray;
|
|
||||||
if (use_tree_shadows || use_tree_normals)
|
|
||||||
{tnormalArray = static_cast<Vec3Array*>(geom->getSecondaryColorArray());}
|
|
||||||
if (posArray->size()
|
if (posArray->size()
|
||||||
>= static_cast<Vec3Array*>(geom->getVertexArray())->size()) {
|
>= static_cast<Vec3Array*>(geom->getVertexArray())->size()) {
|
||||||
Vec3Array* paramsArray
|
Vec3Array* paramsArray
|
||||||
@@ -215,17 +198,11 @@ void addTreeToLeafGeode(Geode* geode, const SGVec3f& p, const SGVec3f& t)
|
|||||||
Vec3 params = (*paramsArray)[0];
|
Vec3 params = (*paramsArray)[0];
|
||||||
geom = createTreeGeometry(params.x(), params.y(), params.z());
|
geom = createTreeGeometry(params.x(), params.y(), params.z());
|
||||||
posArray = static_cast<Vec3Array*>(geom->getColorArray());
|
posArray = static_cast<Vec3Array*>(geom->getColorArray());
|
||||||
if (use_tree_shadows || use_tree_normals)
|
|
||||||
{tnormalArray = static_cast<Vec3Array*>(geom->getSecondaryColorArray());}
|
|
||||||
geode->addDrawable(geom);
|
geode->addDrawable(geom);
|
||||||
}
|
}
|
||||||
posArray->insert(posArray->end(), 4, pos);
|
posArray->insert(posArray->end(), 4, pos);
|
||||||
if (use_tree_shadows || use_tree_normals)
|
|
||||||
{tnormalArray->insert(tnormalArray->end(),4,ter);}
|
|
||||||
size_t numVerts = posArray->size();
|
size_t numVerts = posArray->size();
|
||||||
int imax = 2;
|
for (int i = 0; i < 2; ++i) {
|
||||||
if (use_tree_shadows) {imax = 3;}
|
|
||||||
for (int i = 0; i < imax; ++i) {
|
|
||||||
DrawArrays* primSet
|
DrawArrays* primSet
|
||||||
= static_cast<DrawArrays*>(geom->getPrimitiveSet(i));
|
= static_cast<DrawArrays*>(geom->getPrimitiveSet(i));
|
||||||
primSet->setCount(numVerts);
|
primSet->setCount(numVerts);
|
||||||
@@ -278,7 +255,7 @@ struct AddTreesLeafObject
|
|||||||
void operator() (LOD* lod, const TreeBin::Tree& tree) const
|
void operator() (LOD* lod, const TreeBin::Tree& tree) const
|
||||||
{
|
{
|
||||||
Geode* geode = static_cast<Geode*>(lod->getChild(int(tree.position.x() * 10.0f) % lod->getNumChildren()));
|
Geode* geode = static_cast<Geode*>(lod->getChild(int(tree.position.x() * 10.0f) % lod->getNumChildren()));
|
||||||
addTreeToLeafGeode(geode, tree.position, tree.tnormal);
|
addTreeToLeafGeode(geode, tree.position);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -300,8 +277,7 @@ struct TreeTransformer
|
|||||||
TreeBin::Tree operator()(const TreeBin::Tree& tree) const
|
TreeBin::Tree operator()(const TreeBin::Tree& tree) const
|
||||||
{
|
{
|
||||||
Vec3 pos = toOsg(tree.position);
|
Vec3 pos = toOsg(tree.position);
|
||||||
Vec3 norm = toOsg(tree.tnormal);
|
return TreeBin::Tree(toSG(pos * mat));
|
||||||
return TreeBin::Tree(toSG(pos * mat),toSG(norm * mat));
|
|
||||||
}
|
}
|
||||||
Matrix mat;
|
Matrix mat;
|
||||||
};
|
};
|
||||||
@@ -357,20 +333,6 @@ osg::Group* createForest(SGTreeBinList& forestList, const osg::Matrix& transform
|
|||||||
|
|
||||||
SGTreeBinList::iterator i;
|
SGTreeBinList::iterator i;
|
||||||
|
|
||||||
use_tree_shadows = false;
|
|
||||||
use_tree_normals = false;
|
|
||||||
if (options) {
|
|
||||||
SGPropertyNode* propertyNode = options->getPropertyNode().get();
|
|
||||||
if (propertyNode) {
|
|
||||||
use_tree_shadows
|
|
||||||
= propertyNode->getBoolValue("/sim/rendering/random-vegetation-shadows",
|
|
||||||
use_tree_shadows);
|
|
||||||
use_tree_normals
|
|
||||||
= propertyNode->getBoolValue("/sim/rendering/random-vegetation-normals",
|
|
||||||
use_tree_normals);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = forestList.begin(); i != forestList.end(); ++i) {
|
for (i = forestList.begin(); i != forestList.end(); ++i) {
|
||||||
TreeBin* forest = *i;
|
TreeBin* forest = *i;
|
||||||
|
|
||||||
@@ -381,7 +343,7 @@ osg::Group* createForest(SGTreeBinList& forestList, const osg::Matrix& transform
|
|||||||
(!iter->second.lock(effect)))
|
(!iter->second.lock(effect)))
|
||||||
{
|
{
|
||||||
SGPropertyNode_ptr effectProp = new SGPropertyNode;
|
SGPropertyNode_ptr effectProp = new SGPropertyNode;
|
||||||
makeChild(effectProp, "inherits-from")->setStringValue(forest->teffect);
|
makeChild(effectProp, "inherits-from")->setStringValue("Effects/tree");
|
||||||
SGPropertyNode* params = makeChild(effectProp, "parameters");
|
SGPropertyNode* params = makeChild(effectProp, "parameters");
|
||||||
// emphasize n = 0
|
// emphasize n = 0
|
||||||
params->getChild("texture", 0, true)->getChild("image", 0, true)
|
params->getChild("texture", 0, true)->getChild("image", 0, true)
|
||||||
|
|||||||
@@ -36,10 +36,10 @@ namespace simgear
|
|||||||
class TreeBin {
|
class TreeBin {
|
||||||
public:
|
public:
|
||||||
struct Tree {
|
struct Tree {
|
||||||
SGVec3f position;
|
Tree(const SGVec3f& p) :
|
||||||
SGVec3f tnormal;
|
position(p)
|
||||||
Tree(const SGVec3f& p, const SGVec3f& t) : position(p),tnormal(t)
|
|
||||||
{ }
|
{ }
|
||||||
|
SGVec3f position;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<Tree> TreeList;
|
typedef std::vector<Tree> TreeList;
|
||||||
@@ -49,13 +49,11 @@ public:
|
|||||||
float height;
|
float height;
|
||||||
float width;
|
float width;
|
||||||
std::string texture;
|
std::string texture;
|
||||||
std::string teffect;
|
|
||||||
|
|
||||||
void insert(const Tree& t)
|
void insert(const Tree& t)
|
||||||
{ _trees.push_back(t); }
|
{ _trees.push_back(t); }
|
||||||
|
void insert(const SGVec3f& p, int t, float s)
|
||||||
void insert(const SGVec3f& p, const SGVec3f& tnorm)
|
{ insert(Tree(p)); }
|
||||||
{insert(Tree(p,tnorm));}
|
|
||||||
|
|
||||||
unsigned getNumTrees() const
|
unsigned getNumTrees() const
|
||||||
{ return _trees.size(); }
|
{ return _trees.size(); }
|
||||||
|
|||||||
@@ -51,7 +51,6 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include <simgear/compiler.h>
|
#include <simgear/compiler.h>
|
||||||
#include <simgear/version.h>
|
|
||||||
|
|
||||||
#include "terrasync.hxx"
|
#include "terrasync.hxx"
|
||||||
|
|
||||||
@@ -200,43 +199,6 @@ static unsigned int syncSlotForType(SyncItem::Type ty)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Base server query
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
class ServerSelectQuery : public HTTP::Request
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ServerSelectQuery() :
|
|
||||||
HTTP::Request("http://scenery.flightgear.org/svn-server", "GET")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string svnUrl() const
|
|
||||||
{
|
|
||||||
std::string s = simgear::strutils::strip(m_url);
|
|
||||||
if (s.at(s.length() - 1) == '/') {
|
|
||||||
s = s.substr(0, s.length() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
virtual void gotBodyData(const char* s, int n)
|
|
||||||
{
|
|
||||||
m_url.append(std::string(s, n));
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void onFail()
|
|
||||||
{
|
|
||||||
SG_LOG(SG_TERRASYNC, SG_ALERT, "Failed to query TerraSync SVN server");
|
|
||||||
HTTP::Request::onFail();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string m_url;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// SGTerraSync::SvnThread /////////////////////////////////////////////////////
|
// SGTerraSync::SvnThread /////////////////////////////////////////////////////
|
||||||
@@ -344,7 +306,7 @@ SGTerraSync::SvnThread::SvnThread() :
|
|||||||
_stop(false),
|
_stop(false),
|
||||||
_use_svn(true)
|
_use_svn(true)
|
||||||
{
|
{
|
||||||
_http.setUserAgent("terrascenery-" SG_STRINGIZE(SIMGEAR_VERSION));
|
_http.setUserAgent("terrascenery-" SG_STRINGIZE(SG_VERSION));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SGTerraSync::SvnThread::stop()
|
void SGTerraSync::SvnThread::stop()
|
||||||
@@ -370,7 +332,7 @@ bool SGTerraSync::SvnThread::start()
|
|||||||
|
|
||||||
if (_local_dir=="")
|
if (_local_dir=="")
|
||||||
{
|
{
|
||||||
SG_LOG(SG_TERRASYNC,SG_ALERT,
|
SG_LOG(SG_TERRAIN,SG_ALERT,
|
||||||
"Cannot start scenery download. Local cache directory is undefined.");
|
"Cannot start scenery download. Local cache directory is undefined.");
|
||||||
_fail_count++;
|
_fail_count++;
|
||||||
_stalled = true;
|
_stalled = true;
|
||||||
@@ -380,7 +342,7 @@ bool SGTerraSync::SvnThread::start()
|
|||||||
SGPath path(_local_dir);
|
SGPath path(_local_dir);
|
||||||
if (!path.exists())
|
if (!path.exists())
|
||||||
{
|
{
|
||||||
SG_LOG(SG_TERRASYNC,SG_ALERT,
|
SG_LOG(SG_TERRAIN,SG_ALERT,
|
||||||
"Cannot start scenery download. Directory '" << _local_dir <<
|
"Cannot start scenery download. Directory '" << _local_dir <<
|
||||||
"' does not exist. Set correct directory path or create directory folder.");
|
"' does not exist. Set correct directory path or create directory folder.");
|
||||||
_fail_count++;
|
_fail_count++;
|
||||||
@@ -391,7 +353,7 @@ bool SGTerraSync::SvnThread::start()
|
|||||||
path.append("version");
|
path.append("version");
|
||||||
if (path.exists())
|
if (path.exists())
|
||||||
{
|
{
|
||||||
SG_LOG(SG_TERRASYNC,SG_ALERT,
|
SG_LOG(SG_TERRAIN,SG_ALERT,
|
||||||
"Cannot start scenery download. Directory '" << _local_dir <<
|
"Cannot start scenery download. Directory '" << _local_dir <<
|
||||||
"' contains the base package. Use a separate directory.");
|
"' contains the base package. Use a separate directory.");
|
||||||
_fail_count++;
|
_fail_count++;
|
||||||
@@ -401,10 +363,17 @@ bool SGTerraSync::SvnThread::start()
|
|||||||
|
|
||||||
_use_svn |= _use_built_in;
|
_use_svn |= _use_built_in;
|
||||||
|
|
||||||
|
if ((_use_svn)&&(_svn_server==""))
|
||||||
|
{
|
||||||
|
SG_LOG(SG_TERRAIN,SG_ALERT,
|
||||||
|
"Cannot start scenery download. Subversion scenery server is undefined.");
|
||||||
|
_fail_count++;
|
||||||
|
_stalled = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if ((!_use_svn)&&(_rsync_server==""))
|
if ((!_use_svn)&&(_rsync_server==""))
|
||||||
{
|
{
|
||||||
SG_LOG(SG_TERRASYNC,SG_ALERT,
|
SG_LOG(SG_TERRAIN,SG_ALERT,
|
||||||
"Cannot start scenery download. Rsync scenery server is undefined.");
|
"Cannot start scenery download. Rsync scenery server is undefined.");
|
||||||
_fail_count++;
|
_fail_count++;
|
||||||
_stalled = true;
|
_stalled = true;
|
||||||
@@ -436,7 +405,7 @@ bool SGTerraSync::SvnThread::start()
|
|||||||
|
|
||||||
// not really an alert - but we want to (always) see this message, so user is
|
// not really an alert - but we want to (always) see this message, so user is
|
||||||
// aware we're downloading scenery (and using bandwidth).
|
// aware we're downloading scenery (and using bandwidth).
|
||||||
SG_LOG(SG_TERRASYNC,SG_ALERT,
|
SG_LOG(SG_TERRAIN,SG_ALERT,
|
||||||
"Starting automatic scenery download/synchronization. "
|
"Starting automatic scenery download/synchronization. "
|
||||||
<< status
|
<< status
|
||||||
<< "Directory: '" << _local_dir << "'.");
|
<< "Directory: '" << _local_dir << "'.");
|
||||||
@@ -476,7 +445,7 @@ bool SGTerraSync::SvnThread::runExternalSyncCommand(const char* dir)
|
|||||||
#else
|
#else
|
||||||
command = buf.str();
|
command = buf.str();
|
||||||
#endif
|
#endif
|
||||||
SG_LOG(SG_TERRASYNC,SG_DEBUG, "sync command '" << command << "'");
|
SG_LOG(SG_TERRAIN,SG_DEBUG, "sync command '" << command << "'");
|
||||||
|
|
||||||
#ifdef SG_WINDOWS
|
#ifdef SG_WINDOWS
|
||||||
// tbd: does Windows support "popen"?
|
// tbd: does Windows support "popen"?
|
||||||
@@ -491,7 +460,7 @@ bool SGTerraSync::SvnThread::runExternalSyncCommand(const char* dir)
|
|||||||
|
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
SG_LOG(SG_TERRASYNC,SG_ALERT,
|
SG_LOG(SG_TERRAIN,SG_ALERT,
|
||||||
"Failed to synchronize directory '" << dir << "', " <<
|
"Failed to synchronize directory '" << dir << "', " <<
|
||||||
"error code= " << rc);
|
"error code= " << rc);
|
||||||
return false;
|
return false;
|
||||||
@@ -504,32 +473,6 @@ void SGTerraSync::SvnThread::run()
|
|||||||
_active = true;
|
_active = true;
|
||||||
initCompletedTilesPersistentCache();
|
initCompletedTilesPersistentCache();
|
||||||
|
|
||||||
{
|
|
||||||
if (_svn_server.empty()) {
|
|
||||||
SG_LOG(SG_TERRASYNC,SG_INFO, "Querying closest TerraSync server");
|
|
||||||
ServerSelectQuery* ssq = new ServerSelectQuery;
|
|
||||||
HTTP::Request_ptr req = ssq;
|
|
||||||
_http.makeRequest(req);
|
|
||||||
while (!req->isComplete()) {
|
|
||||||
_http.update(20);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (req->readyState() == HTTP::Request::DONE) {
|
|
||||||
_svn_server = ssq->svnUrl();
|
|
||||||
SG_LOG(SG_TERRASYNC,SG_INFO, "Closest TerraSync server:" << _svn_server);
|
|
||||||
} else {
|
|
||||||
SG_LOG(SG_TERRASYNC,SG_WARN, "Failed to query closest TerraSync server");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
SG_LOG(SG_TERRASYNC,SG_INFO, "Explicit: TerraSync server:" << _svn_server);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_svn_server.empty()) {
|
|
||||||
// default value
|
|
||||||
_svn_server = "http://foxtrot.mgras.net:8080/terrascenery/trunk/data/Scenery";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_use_built_in) {
|
if (_use_built_in) {
|
||||||
runInternal();
|
runInternal();
|
||||||
} else {
|
} else {
|
||||||
@@ -552,7 +495,7 @@ void SGTerraSync::SvnThread::runExternal()
|
|||||||
SyncItem::Status cacheStatus = isPathCached(next);
|
SyncItem::Status cacheStatus = isPathCached(next);
|
||||||
if (cacheStatus != SyncItem::Invalid) {
|
if (cacheStatus != SyncItem::Invalid) {
|
||||||
_cache_hits++;
|
_cache_hits++;
|
||||||
SG_LOG(SG_TERRASYNC, SG_DEBUG,
|
SG_LOG(SG_TERRAIN, SG_DEBUG,
|
||||||
"Cache hit for: '" << next._dir << "'");
|
"Cache hit for: '" << next._dir << "'");
|
||||||
next._status = cacheStatus;
|
next._status = cacheStatus;
|
||||||
_freshTiles.push_back(next);
|
_freshTiles.push_back(next);
|
||||||
@@ -582,7 +525,7 @@ void SGTerraSync::SvnThread::syncPathExternal(const SyncItem& next)
|
|||||||
if (isNewDirectory) {
|
if (isNewDirectory) {
|
||||||
int rc = path.create_dir( 0755 );
|
int rc = path.create_dir( 0755 );
|
||||||
if (rc) {
|
if (rc) {
|
||||||
SG_LOG(SG_TERRASYNC,SG_ALERT,
|
SG_LOG(SG_TERRAIN,SG_ALERT,
|
||||||
"Cannot create directory '" << path << "', return code = " << rc );
|
"Cannot create directory '" << path << "', return code = " << rc );
|
||||||
throw sg_exception("Cannot create directory for terrasync", path.str());
|
throw sg_exception("Cannot create directory for terrasync", path.str());
|
||||||
}
|
}
|
||||||
@@ -605,10 +548,10 @@ void SGTerraSync::SvnThread::updateSyncSlot(SyncSlot &slot)
|
|||||||
{
|
{
|
||||||
if (slot.repository.get()) {
|
if (slot.repository.get()) {
|
||||||
if (slot.repository->isDoingSync()) {
|
if (slot.repository->isDoingSync()) {
|
||||||
#if 1
|
#if 0
|
||||||
if (slot.stamp.elapsedMSec() > (int)slot.nextWarnTimeout) {
|
if (slot.stamp.elapsedMSec() > slot.nextWarnTimeout) {
|
||||||
SG_LOG(SG_TERRASYNC, SG_INFO, "sync taking a long time:" << slot.currentItem._dir << " taken " << slot.stamp.elapsedMSec());
|
SG_LOG(SG_TERRAIN, SG_INFO, "sync taking a long time:" << slot.currentItem._dir << " taken " << slot.stamp.elapsedMSec());
|
||||||
SG_LOG(SG_TERRASYNC, SG_INFO, "HTTP request count:" << _http.hasActiveRequests());
|
SG_LOG(SG_TERRAIN, SG_INFO, "HTTP status:" << _http.hasActiveRequests());
|
||||||
slot.nextWarnTimeout += 10000;
|
slot.nextWarnTimeout += 10000;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -623,7 +566,7 @@ void SGTerraSync::SvnThread::updateSyncSlot(SyncSlot &slot)
|
|||||||
fail(slot.currentItem);
|
fail(slot.currentItem);
|
||||||
} else {
|
} else {
|
||||||
updated(slot.currentItem, slot.isNewDirectory);
|
updated(slot.currentItem, slot.isNewDirectory);
|
||||||
SG_LOG(SG_TERRASYNC, SG_DEBUG, "sync of " << slot.repository->baseUrl() << " finished ("
|
SG_LOG(SG_TERRAIN, SG_DEBUG, "sync of " << slot.repository->baseUrl() << " finished ("
|
||||||
<< slot.stamp.elapsedMSec() << " msec");
|
<< slot.stamp.elapsedMSec() << " msec");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -643,7 +586,7 @@ void SGTerraSync::SvnThread::updateSyncSlot(SyncSlot &slot)
|
|||||||
if (slot.isNewDirectory) {
|
if (slot.isNewDirectory) {
|
||||||
int rc = path.create_dir( 0755 );
|
int rc = path.create_dir( 0755 );
|
||||||
if (rc) {
|
if (rc) {
|
||||||
SG_LOG(SG_TERRASYNC,SG_ALERT,
|
SG_LOG(SG_TERRAIN,SG_ALERT,
|
||||||
"Cannot create directory '" << path << "', return code = " << rc );
|
"Cannot create directory '" << path << "', return code = " << rc );
|
||||||
fail(slot.currentItem);
|
fail(slot.currentItem);
|
||||||
return;
|
return;
|
||||||
@@ -662,7 +605,7 @@ void SGTerraSync::SvnThread::updateSyncSlot(SyncSlot &slot)
|
|||||||
slot.nextWarnTimeout = 20000;
|
slot.nextWarnTimeout = 20000;
|
||||||
slot.stamp.stamp();
|
slot.stamp.stamp();
|
||||||
slot.busy = true;
|
slot.busy = true;
|
||||||
SG_LOG(SG_TERRASYNC, SG_INFO, "sync of " << slot.repository->baseUrl() << " started, queue size is " << slot.queue.size());
|
SG_LOG(SG_TERRAIN, SG_DEBUG, "sync of " << slot.repository->baseUrl() << " started, queue size is " << slot.queue.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -683,7 +626,7 @@ void SGTerraSync::SvnThread::runInternal()
|
|||||||
SyncItem::Status cacheStatus = isPathCached(next);
|
SyncItem::Status cacheStatus = isPathCached(next);
|
||||||
if (cacheStatus != SyncItem::Invalid) {
|
if (cacheStatus != SyncItem::Invalid) {
|
||||||
_cache_hits++;
|
_cache_hits++;
|
||||||
SG_LOG(SG_TERRASYNC, SG_DEBUG, "\nTerraSync Cache hit for: '" << next._dir << "'");
|
SG_LOG(SG_TERRAIN, SG_DEBUG, "\nTerraSync Cache hit for: '" << next._dir << "'");
|
||||||
next._status = cacheStatus;
|
next._status = cacheStatus;
|
||||||
_freshTiles.push_back(next);
|
_freshTiles.push_back(next);
|
||||||
_is_dirty = true;
|
_is_dirty = true;
|
||||||
@@ -740,8 +683,6 @@ void SGTerraSync::SvnThread::fail(SyncItem failedItem)
|
|||||||
_fail_count++;
|
_fail_count++;
|
||||||
failedItem._status = SyncItem::Failed;
|
failedItem._status = SyncItem::Failed;
|
||||||
_freshTiles.push_back(failedItem);
|
_freshTiles.push_back(failedItem);
|
||||||
SG_LOG(SG_TERRASYNC,SG_INFO,
|
|
||||||
"Failed to sync'" << failedItem._dir << "'");
|
|
||||||
_completedTiles[ failedItem._dir ] = now + UpdateInterval::FailedAttempt;
|
_completedTiles[ failedItem._dir ] = now + UpdateInterval::FailedAttempt;
|
||||||
_is_dirty = true;
|
_is_dirty = true;
|
||||||
}
|
}
|
||||||
@@ -766,7 +707,7 @@ void SGTerraSync::SvnThread::updated(SyncItem item, bool isNewDirectory)
|
|||||||
time_t now = time(0);
|
time_t now = time(0);
|
||||||
_consecutive_errors = 0;
|
_consecutive_errors = 0;
|
||||||
_success_count++;
|
_success_count++;
|
||||||
SG_LOG(SG_TERRASYNC,SG_INFO,
|
SG_LOG(SG_TERRAIN,SG_INFO,
|
||||||
"Successfully synchronized directory '" << item._dir << "'");
|
"Successfully synchronized directory '" << item._dir << "'");
|
||||||
|
|
||||||
item._status = SyncItem::Updated;
|
item._status = SyncItem::Updated;
|
||||||
@@ -792,7 +733,7 @@ void SGTerraSync::SvnThread::initCompletedTilesPersistentCache()
|
|||||||
try {
|
try {
|
||||||
readProperties(_persistentCachePath.str(), cacheRoot);
|
readProperties(_persistentCachePath.str(), cacheRoot);
|
||||||
} catch (sg_exception& e) {
|
} catch (sg_exception& e) {
|
||||||
SG_LOG(SG_TERRASYNC, SG_INFO, "corrupted persistent cache, discarding");
|
SG_LOG(SG_TERRAIN, SG_INFO, "corrupted persistent cache, discarding");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -853,7 +794,7 @@ SGTerraSync::SGTerraSync() :
|
|||||||
_inited(false)
|
_inited(false)
|
||||||
{
|
{
|
||||||
_svnThread = new SvnThread();
|
_svnThread = new SvnThread();
|
||||||
_log = new BufferedLogCallback(SG_TERRASYNC, SG_INFO);
|
_log = new BufferedLogCallback(SG_TERRAIN, SG_INFO);
|
||||||
_log->truncateAt(255);
|
_log->truncateAt(255);
|
||||||
|
|
||||||
sglog().addCallback(_log);
|
sglog().addCallback(_log);
|
||||||
@@ -978,13 +919,13 @@ void SGTerraSync::update(double)
|
|||||||
{
|
{
|
||||||
if (_svnThread->_stalled)
|
if (_svnThread->_stalled)
|
||||||
{
|
{
|
||||||
SG_LOG(SG_TERRASYNC,SG_ALERT,
|
SG_LOG(SG_TERRAIN,SG_ALERT,
|
||||||
"Automatic scenery download/synchronization stalled. Too many errors.");
|
"Automatic scenery download/synchronization stalled. Too many errors.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// not really an alert - just always show this message
|
// not really an alert - just always show this message
|
||||||
SG_LOG(SG_TERRASYNC,SG_ALERT,
|
SG_LOG(SG_TERRAIN,SG_ALERT,
|
||||||
"Automatic scenery download/synchronization has stopped.");
|
"Automatic scenery download/synchronization has stopped.");
|
||||||
}
|
}
|
||||||
_stalledNode->setBoolValue(_svnThread->_stalled);
|
_stalledNode->setBoolValue(_svnThread->_stalled);
|
||||||
|
|||||||
@@ -25,13 +25,11 @@
|
|||||||
|
|
||||||
#include "SGSceneFeatures.hxx"
|
#include "SGSceneFeatures.hxx"
|
||||||
|
|
||||||
#include <osg/Version>
|
|
||||||
#include <osg/FragmentProgram>
|
#include <osg/FragmentProgram>
|
||||||
#include <osg/VertexProgram>
|
#include <osg/VertexProgram>
|
||||||
#include <osg/Point>
|
#include <osg/Point>
|
||||||
#include <osg/PointSprite>
|
#include <osg/PointSprite>
|
||||||
#include <osg/Texture>
|
#include <osg/Texture>
|
||||||
#include <osg/GLExtensions>
|
|
||||||
|
|
||||||
#include <OpenThreads/Mutex>
|
#include <OpenThreads/Mutex>
|
||||||
#include <OpenThreads/ScopedLock>
|
#include <OpenThreads/ScopedLock>
|
||||||
@@ -86,18 +84,12 @@ SGSceneFeatures::setTextureCompression(osg::Texture* texture) const
|
|||||||
bool
|
bool
|
||||||
SGSceneFeatures::getHavePointSprites(unsigned contextId) const
|
SGSceneFeatures::getHavePointSprites(unsigned contextId) const
|
||||||
{
|
{
|
||||||
#if OSG_VERSION_LESS_THAN(3,3,4)
|
|
||||||
return osg::PointSprite::isPointSpriteSupported(contextId);
|
return osg::PointSprite::isPointSpriteSupported(contextId);
|
||||||
#else
|
|
||||||
const osg::GLExtensions* ex = osg::GLExtensions::Get(contextId, true);
|
|
||||||
return ex && ex->isPointSpriteSupported;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SGSceneFeatures::getHaveFragmentPrograms(unsigned contextId) const
|
SGSceneFeatures::getHaveFragmentPrograms(unsigned contextId) const
|
||||||
{
|
{
|
||||||
#if OSG_VERSION_LESS_THAN(3,3,4)
|
|
||||||
const osg::FragmentProgram::Extensions* fpe;
|
const osg::FragmentProgram::Extensions* fpe;
|
||||||
fpe = osg::FragmentProgram::getExtensions(contextId, true);
|
fpe = osg::FragmentProgram::getExtensions(contextId, true);
|
||||||
if (!fpe)
|
if (!fpe)
|
||||||
@@ -106,16 +98,11 @@ SGSceneFeatures::getHaveFragmentPrograms(unsigned contextId) const
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
#else
|
|
||||||
const osg::GLExtensions* ex = osg::GLExtensions::Get(contextId, true);
|
|
||||||
return ex && ex->isFragmentProgramSupported;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SGSceneFeatures::getHaveVertexPrograms(unsigned contextId) const
|
SGSceneFeatures::getHaveVertexPrograms(unsigned contextId) const
|
||||||
{
|
{
|
||||||
#if OSG_VERSION_LESS_THAN(3,3,4)
|
|
||||||
const osg::VertexProgram::Extensions* vpe;
|
const osg::VertexProgram::Extensions* vpe;
|
||||||
vpe = osg::VertexProgram::getExtensions(contextId, true);
|
vpe = osg::VertexProgram::getExtensions(contextId, true);
|
||||||
if (!vpe)
|
if (!vpe)
|
||||||
@@ -124,10 +111,6 @@ SGSceneFeatures::getHaveVertexPrograms(unsigned contextId) const
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
#else
|
|
||||||
const osg::GLExtensions* ex = osg::GLExtensions::Get(contextId, true);
|
|
||||||
return ex && ex->isVertexProgramSupported;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@@ -141,7 +124,6 @@ SGSceneFeatures::getHaveShaderPrograms(unsigned contextId) const
|
|||||||
bool
|
bool
|
||||||
SGSceneFeatures::getHavePointParameters(unsigned contextId) const
|
SGSceneFeatures::getHavePointParameters(unsigned contextId) const
|
||||||
{
|
{
|
||||||
#if OSG_VERSION_LESS_THAN(3,3,4)
|
|
||||||
const osg::Point::Extensions* pe;
|
const osg::Point::Extensions* pe;
|
||||||
pe = osg::Point::getExtensions(contextId, true);
|
pe = osg::Point::getExtensions(contextId, true);
|
||||||
if (!pe)
|
if (!pe)
|
||||||
@@ -149,9 +131,5 @@ SGSceneFeatures::getHavePointParameters(unsigned contextId) const
|
|||||||
if (!pe->isPointParametersSupported())
|
if (!pe->isPointParametersSupported())
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
#else
|
|
||||||
const osg::GLExtensions* ex = osg::GLExtensions::Get(contextId, true);
|
|
||||||
return ex && ex->isPointParametersSupported;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,4 +18,3 @@
|
|||||||
|
|
||||||
#cmakedefine SYSTEM_EXPAT
|
#cmakedefine SYSTEM_EXPAT
|
||||||
#cmakedefine ENABLE_SOUND
|
#cmakedefine ENABLE_SOUND
|
||||||
#cmakedefine ENABLE_CURL
|
|
||||||
|
|||||||
@@ -402,8 +402,7 @@ void SGSampleGroup::set_volume( float vol )
|
|||||||
// set the source position and orientation of all managed sounds
|
// set the source position and orientation of all managed sounds
|
||||||
void SGSampleGroup::update_pos_and_orientation() {
|
void SGSampleGroup::update_pos_and_orientation() {
|
||||||
|
|
||||||
SGVec3d base_position = SGVec3d::fromGeod(_base_pos);
|
SGVec3d position = SGVec3d::fromGeod(_base_pos) - _smgr->get_position();
|
||||||
SGVec3d smgr_position = _smgr->get_position();
|
|
||||||
SGQuatd hlOr = SGQuatd::fromLonLat(_base_pos);
|
SGQuatd hlOr = SGQuatd::fromLonLat(_base_pos);
|
||||||
SGQuatd ec2body = hlOr*_orientation;
|
SGQuatd ec2body = hlOr*_orientation;
|
||||||
|
|
||||||
@@ -419,14 +418,12 @@ void SGSampleGroup::update_pos_and_orientation() {
|
|||||||
sample->set_master_volume( _volume );
|
sample->set_master_volume( _volume );
|
||||||
sample->set_orientation( _orientation );
|
sample->set_orientation( _orientation );
|
||||||
sample->set_rotation( ec2body );
|
sample->set_rotation( ec2body );
|
||||||
sample->set_position(base_position);
|
sample->set_position( position );
|
||||||
sample->set_velocity( velocity );
|
sample->set_velocity( velocity );
|
||||||
|
|
||||||
// Test if a sample is farther away than max distance, if so
|
// Test if a sample is farther away than max distance, if so
|
||||||
// stop the sound playback and free it's source.
|
// stop the sound playback and free it's source.
|
||||||
if (!_tied_to_listener) {
|
if (!_tied_to_listener) {
|
||||||
sample->update_pos_and_orientation();
|
|
||||||
SGVec3d position = sample->get_position() - smgr_position;
|
|
||||||
float max2 = sample->get_max_dist() * sample->get_max_dist();
|
float max2 = sample->get_max_dist() * sample->get_max_dist();
|
||||||
float dist2 = position[0]*position[0]
|
float dist2 = position[0]*position[0]
|
||||||
+ position[1]*position[1] + position[2]*position[2];
|
+ position[1]*position[1] + position[2]*position[2];
|
||||||
@@ -452,7 +449,7 @@ void SGSampleGroup::update_sample_config( SGSoundSample *sample )
|
|||||||
} else {
|
} else {
|
||||||
sample->update_pos_and_orientation();
|
sample->update_pos_and_orientation();
|
||||||
orientation = sample->get_orientation();
|
orientation = sample->get_orientation();
|
||||||
position = sample->get_position() - _smgr->get_position();
|
position = sample->get_position();
|
||||||
velocity = sample->get_velocity();
|
velocity = sample->get_velocity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,6 @@
|
|||||||
|
|
||||||
#include <stdlib.h> // rand(), free()
|
#include <stdlib.h> // rand(), free()
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <simgear/debug/logstream.hxx>
|
#include <simgear/debug/logstream.hxx>
|
||||||
#include <simgear/structure/exception.hxx>
|
#include <simgear/structure/exception.hxx>
|
||||||
@@ -79,12 +78,8 @@ SGSoundSample::SGSoundSample() :
|
|||||||
_playing(false),
|
_playing(false),
|
||||||
_static_changed(true),
|
_static_changed(true),
|
||||||
_out_of_range(false),
|
_out_of_range(false),
|
||||||
_is_file(false),
|
_is_file(false)
|
||||||
_use_pos_props(false)
|
|
||||||
{
|
{
|
||||||
_pos_prop[0] = 0;
|
|
||||||
_pos_prop[1] = 0;
|
|
||||||
_pos_prop[2] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
@@ -119,14 +114,10 @@ SGSoundSample::SGSoundSample(const char *file, const SGPath& currentDir) :
|
|||||||
_playing(false),
|
_playing(false),
|
||||||
_static_changed(true),
|
_static_changed(true),
|
||||||
_out_of_range(false),
|
_out_of_range(false),
|
||||||
_is_file(true),
|
_is_file(true)
|
||||||
_use_pos_props(false)
|
|
||||||
{
|
{
|
||||||
SGPath p = simgear::ResourceManager::instance()->findPath(file, currentDir);
|
SGPath p = simgear::ResourceManager::instance()->findPath(file, currentDir);
|
||||||
_refname = p.str();
|
_refname = p.str();
|
||||||
_pos_prop[0] = 0;
|
|
||||||
_pos_prop[1] = 0;
|
|
||||||
_pos_prop[2] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
@@ -161,14 +152,10 @@ SGSoundSample::SGSoundSample( const unsigned char** data,
|
|||||||
_playing(false),
|
_playing(false),
|
||||||
_static_changed(true),
|
_static_changed(true),
|
||||||
_out_of_range(false),
|
_out_of_range(false),
|
||||||
_is_file(false),
|
_is_file(false)
|
||||||
_use_pos_props(false)
|
|
||||||
{
|
{
|
||||||
SG_LOG( SG_SOUND, SG_DEBUG, "In memory sounds sample" );
|
SG_LOG( SG_SOUND, SG_DEBUG, "In memory sounds sample" );
|
||||||
_data = (unsigned char*)*data; *data = NULL;
|
_data = (unsigned char*)*data; *data = NULL;
|
||||||
_pos_prop[0] = 0;
|
|
||||||
_pos_prop[1] = 0;
|
|
||||||
_pos_prop[2] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
@@ -202,14 +189,10 @@ SGSoundSample::SGSoundSample( void** data, int len, int freq, int format ) :
|
|||||||
_playing(false),
|
_playing(false),
|
||||||
_static_changed(true),
|
_static_changed(true),
|
||||||
_out_of_range(false),
|
_out_of_range(false),
|
||||||
_is_file(false),
|
_is_file(false)
|
||||||
_use_pos_props(false)
|
|
||||||
{
|
{
|
||||||
SG_LOG( SG_SOUND, SG_DEBUG, "In memory sounds sample" );
|
SG_LOG( SG_SOUND, SG_DEBUG, "In memory sounds sample" );
|
||||||
_data = (unsigned char*)*data; *data = NULL;
|
_data = (unsigned char*)*data; *data = NULL;
|
||||||
_pos_prop[0] = 0;
|
|
||||||
_pos_prop[1] = 0;
|
|
||||||
_pos_prop[2] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -220,17 +203,10 @@ SGSoundSample::~SGSoundSample() {
|
|||||||
|
|
||||||
void SGSoundSample::update_pos_and_orientation() {
|
void SGSoundSample::update_pos_and_orientation() {
|
||||||
|
|
||||||
if (_use_pos_props) {
|
|
||||||
if (_pos_prop[0]) _absolute_pos[0] = _pos_prop[0]->getDoubleValue();
|
|
||||||
if (_pos_prop[1]) _absolute_pos[1] = _pos_prop[1]->getDoubleValue();
|
|
||||||
if (_pos_prop[2]) _absolute_pos[2] = _pos_prop[2]->getDoubleValue();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
_absolute_pos = _base_pos;
|
_absolute_pos = _base_pos;
|
||||||
if (_relative_pos[0] || _relative_pos[1] || _relative_pos[2] ) {
|
if (_relative_pos[0] || _relative_pos[1] || _relative_pos[2] ) {
|
||||||
_absolute_pos += _rotation.rotate( _relative_pos );
|
_absolute_pos += _rotation.rotate( _relative_pos );
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
_orivec = SGVec3f::zeros();
|
_orivec = SGVec3f::zeros();
|
||||||
if ( _direction[0] || _direction[1] || _direction[2] ) {
|
if ( _direction[0] || _direction[1] || _direction[2] ) {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user